X-Git-Url: https://git.piment-noir.org/?p=deb_ffmpeg.git;a=blobdiff_plain;f=ffmpeg%2Flibavfilter%2Fvf_perspective.c;fp=ffmpeg%2Flibavfilter%2Fvf_perspective.c;h=bf06d02f463d7b7246e008ca1b18d981d7e02e1f;hp=a796bd489bac1ac49dbdb1728c8773e357df95c8;hb=f6fa7814ccfe3e76514b36cf04f5cd3cb657c8cf;hpb=2ba45a602cbfa7b771effba9b11bb4245c21bc00 diff --git a/ffmpeg/libavfilter/vf_perspective.c b/ffmpeg/libavfilter/vf_perspective.c index a796bd4..bf06d02 100644 --- a/ffmpeg/libavfilter/vf_perspective.c +++ b/ffmpeg/libavfilter/vf_perspective.c @@ -46,6 +46,7 @@ typedef struct PerspectiveContext { int height[4]; int hsub, vsub; int nb_planes; + int sense; int (*perspective)(AVFilterContext *ctx, void *arg, int job, int nb_jobs); @@ -54,6 +55,11 @@ typedef struct PerspectiveContext { #define OFFSET(x) offsetof(PerspectiveContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +enum PERSPECTIVESense { + PERSPECTIVE_SENSE_SOURCE = 0, ///< coordinates give locations in source of corners of destination. + PERSPECTIVE_SENSE_DESTINATION = 1, ///< coordinates give locations in destination of corners of source. +}; + static const AVOption perspective_options[] = { { "x0", "set top left x coordinate", OFFSET(expr_str[0][0]), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS }, { "y0", "set top left y coordinate", OFFSET(expr_str[0][1]), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS }, @@ -66,6 +72,12 @@ static const AVOption perspective_options[] = { { "interpolation", "set interpolation", OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=LINEAR}, 0, 1, FLAGS, "interpolation" }, { "linear", "", 0, AV_OPT_TYPE_CONST, {.i64=LINEAR}, 0, 0, FLAGS, "interpolation" }, { "cubic", "", 0, AV_OPT_TYPE_CONST, {.i64=CUBIC}, 0, 0, FLAGS, "interpolation" }, + { "sense", "specify the sense of the coordinates", OFFSET(sense), AV_OPT_TYPE_INT, {.i64=PERSPECTIVE_SENSE_SOURCE}, 0, 1, FLAGS, "sense"}, + { "source", "specify locations in source to send to corners in destination", + 0, AV_OPT_TYPE_CONST, {.i64=PERSPECTIVE_SENSE_SOURCE}, 0, 0, FLAGS, "sense"}, + { "destination", "specify locations in destination to send corners of source", + 0, AV_OPT_TYPE_CONST, {.i64=PERSPECTIVE_SENSE_DESTINATION}, 0, 0, FLAGS, "sense"}, + { NULL } }; @@ -105,7 +117,8 @@ enum { VAR_W, VAR_H, VAR_VARS_NB }; static int config_input(AVFilterLink *inlink) { - double x0, x1, x2, x3, x4, x5, x6, x7, q; + double x0, x1, x2, x3, x4, x5, x6, x7, x8, q; + double t0, t1, t2, t3; AVFilterContext *ctx = inlink->dst; PerspectiveContext *s = ctx->priv; double (*ref)[2] = s->ref; @@ -141,32 +154,64 @@ static int config_input(AVFilterLink *inlink) if (!s->pv) return AVERROR(ENOMEM); - x6 = ((ref[0][0] - ref[1][0] - ref[2][0] + ref[3][0]) * - (ref[2][1] - ref[3][1]) - - ( ref[0][1] - ref[1][1] - ref[2][1] + ref[3][1]) * - (ref[2][0] - ref[3][0])) * h; - x7 = ((ref[0][1] - ref[1][1] - ref[2][1] + ref[3][1]) * - (ref[1][0] - ref[3][0]) - - ( ref[0][0] - ref[1][0] - ref[2][0] + ref[3][0]) * - (ref[1][1] - ref[3][1])) * w; - q = ( ref[1][0] - ref[3][0]) * (ref[2][1] - ref[3][1]) - - ( ref[2][0] - ref[3][0]) * (ref[1][1] - ref[3][1]); - - x0 = q * (ref[1][0] - ref[0][0]) * h + x6 * ref[1][0]; - x1 = q * (ref[2][0] - ref[0][0]) * w + x7 * ref[2][0]; - x2 = q * ref[0][0] * w * h; - x3 = q * (ref[1][1] - ref[0][1]) * h + x6 * ref[1][1]; - x4 = q * (ref[2][1] - ref[0][1]) * w + x7 * ref[2][1]; - x5 = q * ref[0][1] * w * h; + switch (s->sense) { + case PERSPECTIVE_SENSE_SOURCE: + x6 = ((ref[0][0] - ref[1][0] - ref[2][0] + ref[3][0]) * + (ref[2][1] - ref[3][1]) - + ( ref[0][1] - ref[1][1] - ref[2][1] + ref[3][1]) * + (ref[2][0] - ref[3][0])) * h; + x7 = ((ref[0][1] - ref[1][1] - ref[2][1] + ref[3][1]) * + (ref[1][0] - ref[3][0]) - + ( ref[0][0] - ref[1][0] - ref[2][0] + ref[3][0]) * + (ref[1][1] - ref[3][1])) * w; + q = ( ref[1][0] - ref[3][0]) * (ref[2][1] - ref[3][1]) - + ( ref[2][0] - ref[3][0]) * (ref[1][1] - ref[3][1]); + + x0 = q * (ref[1][0] - ref[0][0]) * h + x6 * ref[1][0]; + x1 = q * (ref[2][0] - ref[0][0]) * w + x7 * ref[2][0]; + x2 = q * ref[0][0] * w * h; + x3 = q * (ref[1][1] - ref[0][1]) * h + x6 * ref[1][1]; + x4 = q * (ref[2][1] - ref[0][1]) * w + x7 * ref[2][1]; + x5 = q * ref[0][1] * w * h; + x8 = q * w * h; + break; + case PERSPECTIVE_SENSE_DESTINATION: + t0 = ref[0][0] * (ref[3][1] - ref[1][1]) + + ref[1][0] * (ref[0][1] - ref[3][1]) + + ref[3][0] * (ref[1][1] - ref[0][1]); + t1 = ref[1][0] * (ref[2][1] - ref[3][1]) + + ref[2][0] * (ref[3][1] - ref[1][1]) + + ref[3][0] * (ref[1][1] - ref[2][1]); + t2 = ref[0][0] * (ref[3][1] - ref[2][1]) + + ref[2][0] * (ref[0][1] - ref[3][1]) + + ref[3][0] * (ref[2][1] - ref[0][1]); + t3 = ref[0][0] * (ref[1][1] - ref[2][1]) + + ref[1][0] * (ref[2][1] - ref[0][1]) + + ref[2][0] * (ref[0][1] - ref[1][1]); + + x0 = t0 * t1 * w * (ref[2][1] - ref[0][1]); + x1 = t0 * t1 * w * (ref[0][0] - ref[2][0]); + x2 = t0 * t1 * w * (ref[0][1] * ref[2][0] - ref[0][0] * ref[2][1]); + x3 = t1 * t2 * h * (ref[1][1] - ref[0][1]); + x4 = t1 * t2 * h * (ref[0][0] - ref[1][0]); + x5 = t1 * t2 * h * (ref[0][1] * ref[1][0] - ref[0][0] * ref[1][1]); + x6 = t1 * t2 * (ref[1][1] - ref[0][1]) + + t0 * t3 * (ref[2][1] - ref[3][1]); + x7 = t1 * t2 * (ref[0][0] - ref[1][0]) + + t0 * t3 * (ref[3][0] - ref[2][0]); + x8 = t1 * t2 * (ref[0][1] * ref[1][0] - ref[0][0] * ref[1][1]) + + t0 * t3 * (ref[2][0] * ref[3][1] - ref[2][1] * ref[3][0]); + break; + } for (y = 0; y < h; y++){ for (x = 0; x < w; x++){ int u, v; u = (int)floor(SUB_PIXELS * (x0 * x + x1 * y + x2) / - (x6 * x + x7 * y + q * w * h) + 0.5); + (x6 * x + x7 * y + x8) + 0.5); v = (int)floor(SUB_PIXELS * (x3 * x + x4 * y + x5) / - (x6 * x + x7 * y + q * w * h) + 0.5); + (x6 * x + x7 * y + x8) + 0.5); s->pv[x + y * w][0] = u; s->pv[x + y * w][1] = v;