Commit 22cfa1f7 authored by Nicholas Robbins's avatar Nicholas Robbins Committed by Michael Niedermayer

libavfi: added option to vf_perspective to specify transformation by giving...

libavfi: added option to vf_perspective to specify transformation by giving destinations of corners of source.
Signed-off-by: 's avatarNicholas Robbins <nickrobbins@yahoo.com>
Signed-off-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parent 9d51bad6
...@@ -6718,6 +6718,9 @@ A description of the accepted parameters follows. ...@@ -6718,6 +6718,9 @@ A description of the accepted parameters follows.
@item y3 @item y3
Set coordinates expression for top left, top right, bottom left and bottom right corners. Set coordinates expression for top left, top right, bottom left and bottom right corners.
Default values are @code{0:0:W:0:0:H:W:H} with which perspective will remain unchanged. Default values are @code{0:0:W:0:0:H:W:H} with which perspective will remain unchanged.
If the @code{sense} option is set to @code{source}, then the specified points will be sent
to the corners of the destination. If the @code{sense} option is set to @code{destination},
then the corners of the source will be sent to the specified coordinates.
The expressions can use the following variables: The expressions can use the following variables:
...@@ -6737,6 +6740,24 @@ It accepts the following values: ...@@ -6737,6 +6740,24 @@ It accepts the following values:
@end table @end table
Default value is @samp{linear}. Default value is @samp{linear}.
@item sense
Set interpretation of coordinate options.
It accepts the following values:
@table @samp
@item 0, source
Send point in the source specified by the given coordinates to
the corners of the destination.
@item 1, destination
Send the corners of the source to the point in the destination specified
by the given coordinates.
Default value is @samp{source}.
@end table
@end table @end table
@section phase @section phase
......
...@@ -46,6 +46,7 @@ typedef struct PerspectiveContext { ...@@ -46,6 +46,7 @@ typedef struct PerspectiveContext {
int height[4]; int height[4];
int hsub, vsub; int hsub, vsub;
int nb_planes; int nb_planes;
int sense;
int (*perspective)(AVFilterContext *ctx, int (*perspective)(AVFilterContext *ctx,
void *arg, int job, int nb_jobs); void *arg, int job, int nb_jobs);
...@@ -54,6 +55,11 @@ typedef struct PerspectiveContext { ...@@ -54,6 +55,11 @@ typedef struct PerspectiveContext {
#define OFFSET(x) offsetof(PerspectiveContext, x) #define OFFSET(x) offsetof(PerspectiveContext, x)
#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM #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[] = { 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 }, { "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 }, { "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[] = { ...@@ -66,6 +72,12 @@ static const AVOption perspective_options[] = {
{ "interpolation", "set interpolation", OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=LINEAR}, 0, 1, FLAGS, "interpolation" }, { "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" }, { "linear", "", 0, AV_OPT_TYPE_CONST, {.i64=LINEAR}, 0, 0, FLAGS, "interpolation" },
{ "cubic", "", 0, AV_OPT_TYPE_CONST, {.i64=CUBIC}, 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 } { NULL }
}; };
...@@ -105,7 +117,8 @@ enum { VAR_W, VAR_H, VAR_VARS_NB }; ...@@ -105,7 +117,8 @@ enum { VAR_W, VAR_H, VAR_VARS_NB };
static int config_input(AVFilterLink *inlink) 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; AVFilterContext *ctx = inlink->dst;
PerspectiveContext *s = ctx->priv; PerspectiveContext *s = ctx->priv;
double (*ref)[2] = s->ref; double (*ref)[2] = s->ref;
...@@ -141,32 +154,64 @@ static int config_input(AVFilterLink *inlink) ...@@ -141,32 +154,64 @@ static int config_input(AVFilterLink *inlink)
if (!s->pv) if (!s->pv)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
x6 = ((ref[0][0] - ref[1][0] - ref[2][0] + ref[3][0]) * switch (s->sense) {
(ref[2][1] - ref[3][1]) - case PERSPECTIVE_SENSE_SOURCE:
( ref[0][1] - ref[1][1] - ref[2][1] + ref[3][1]) * x6 = ((ref[0][0] - ref[1][0] - ref[2][0] + ref[3][0]) *
(ref[2][0] - ref[3][0])) * h; (ref[2][1] - ref[3][1]) -
x7 = ((ref[0][1] - ref[1][1] - ref[2][1] + ref[3][1]) * ( ref[0][1] - ref[1][1] - ref[2][1] + ref[3][1]) *
(ref[1][0] - ref[3][0]) - (ref[2][0] - ref[3][0])) * h;
( ref[0][0] - ref[1][0] - ref[2][0] + ref[3][0]) * x7 = ((ref[0][1] - ref[1][1] - ref[2][1] + ref[3][1]) *
(ref[1][1] - ref[3][1])) * w; (ref[1][0] - ref[3][0]) -
q = ( ref[1][0] - ref[3][0]) * (ref[2][1] - ref[3][1]) - ( ref[0][0] - ref[1][0] - ref[2][0] + ref[3][0]) *
( ref[2][0] - ref[3][0]) * (ref[1][1] - ref[3][1]); (ref[1][1] - ref[3][1])) * w;
q = ( ref[1][0] - ref[3][0]) * (ref[2][1] - ref[3][1]) -
x0 = q * (ref[1][0] - ref[0][0]) * h + x6 * ref[1][0]; ( ref[2][0] - ref[3][0]) * (ref[1][1] - ref[3][1]);
x1 = q * (ref[2][0] - ref[0][0]) * w + x7 * ref[2][0];
x2 = q * ref[0][0] * w * h; x0 = q * (ref[1][0] - ref[0][0]) * h + x6 * ref[1][0];
x3 = q * (ref[1][1] - ref[0][1]) * h + x6 * ref[1][1]; x1 = q * (ref[2][0] - ref[0][0]) * w + x7 * ref[2][0];
x4 = q * (ref[2][1] - ref[0][1]) * w + x7 * ref[2][1]; x2 = q * ref[0][0] * w * h;
x5 = q * ref[0][1] * 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 (y = 0; y < h; y++){
for (x = 0; x < w; x++){ for (x = 0; x < w; x++){
int u, v; int u, v;
u = (int)floor(SUB_PIXELS * (x0 * x + x1 * y + x2) / 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) / 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][0] = u;
s->pv[x + y * w][1] = v; s->pv[x + y * w][1] = v;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment