summaryrefslogtreecommitdiff
path: root/libavfilter/vf_curves.c
diff options
context:
space:
mode:
authorClément Bœsch <u@pkh.me>2016-07-16 13:46:32 +0200
committerClément Bœsch <u@pkh.me>2016-07-24 12:18:30 +0200
commit5c14018fc4f6ae9fcce7eaf8dd2d66cb6fbfc7bc (patch)
tree3b0d0dc0c10453b359696bcb2b7513d841535954 /libavfilter/vf_curves.c
parent783a2568b28dfb87cd6026191de46fda923cb6d0 (diff)
lavfi/curves: do not automatically insert points at x=0 and x=1
There is actually a need for the origin and end point not to be defined. We can not automatically insert them with the y value of the first and last point as it will influence the curves in a wrong way. Fixes #5397
Diffstat (limited to 'libavfilter/vf_curves.c')
-rw-r--r--libavfilter/vf_curves.c90
1 files changed, 48 insertions, 42 deletions
diff --git a/libavfilter/vf_curves.c b/libavfilter/vf_curves.c
index 1c51c1baf7..7128fbef2c 100644
--- a/libavfilter/vf_curves.c
+++ b/libavfilter/vf_curves.c
@@ -110,25 +110,25 @@ static const struct {
const char *master;
} curves_presets[] = {
[PRESET_COLOR_NEGATIVE] = {
- "0/1 0.129/1 0.466/0.498 0.725/0 1/0",
- "0/1 0.109/1 0.301/0.498 0.517/0 1/0",
- "0/1 0.098/1 0.235/0.498 0.423/0 1/0",
+ "0.129/1 0.466/0.498 0.725/0",
+ "0.109/1 0.301/0.498 0.517/0",
+ "0.098/1 0.235/0.498 0.423/0",
},
[PRESET_CROSS_PROCESS] = {
- "0.25/0.156 0.501/0.501 0.686/0.745",
- "0.25/0.188 0.38/0.501 0.745/0.815 1/0.815",
- "0.231/0.094 0.709/0.874",
+ "0/0 0.25/0.156 0.501/0.501 0.686/0.745 1/1",
+ "0/0 0.25/0.188 0.38/0.501 0.745/0.815 1/0.815",
+ "0/0 0.231/0.094 0.709/0.874 1/1",
},
- [PRESET_DARKER] = { .master = "0.5/0.4" },
- [PRESET_INCREASE_CONTRAST] = { .master = "0.149/0.066 0.831/0.905 0.905/0.98" },
- [PRESET_LIGHTER] = { .master = "0.4/0.5" },
- [PRESET_LINEAR_CONTRAST] = { .master = "0.305/0.286 0.694/0.713" },
- [PRESET_MEDIUM_CONTRAST] = { .master = "0.286/0.219 0.639/0.643" },
+ [PRESET_DARKER] = { .master = "0/0 0.5/0.4 1/1" },
+ [PRESET_INCREASE_CONTRAST] = { .master = "0/0 0.149/0.066 0.831/0.905 0.905/0.98 1/1" },
+ [PRESET_LIGHTER] = { .master = "0/0 0.4/0.5 1/1" },
+ [PRESET_LINEAR_CONTRAST] = { .master = "0/0 0.305/0.286 0.694/0.713 1/1" },
+ [PRESET_MEDIUM_CONTRAST] = { .master = "0/0 0.286/0.219 0.639/0.643 1/1" },
[PRESET_NEGATIVE] = { .master = "0/1 1/0" },
- [PRESET_STRONG_CONTRAST] = { .master = "0.301/0.196 0.592/0.6 0.686/0.737" },
+ [PRESET_STRONG_CONTRAST] = { .master = "0/0 0.301/0.196 0.592/0.6 0.686/0.737 1/1" },
[PRESET_VINTAGE] = {
"0/0.11 0.42/0.51 1/0.95",
- "0.50/0.48",
+ "0/0 0.50/0.48 1/1",
"0/0.22 0.49/0.44 1/0.8",
}
};
@@ -177,28 +177,11 @@ static int parse_points_str(AVFilterContext *ctx, struct keypoint **points, cons
last = point;
}
- /* auto insert first key point if missing at x=0 */
- if (!*points) {
- last = make_point(0, 0, NULL);
- if (!last)
- return AVERROR(ENOMEM);
- last->x = last->y = 0;
- *points = last;
- } else if ((*points)->x != 0.) {
- struct keypoint *newfirst = make_point(0, 0, *points);
- if (!newfirst)
- return AVERROR(ENOMEM);
- *points = newfirst;
- }
-
- av_assert0(last);
-
- /* auto insert last key point if missing at x=1 */
- if (last->x != 1.) {
- struct keypoint *point = make_point(1, 1, NULL);
- if (!point)
- return AVERROR(ENOMEM);
- last->next = point;
+ if (*points && !(*points)->next) {
+ av_log(ctx, AV_LOG_WARNING, "Only one point (at (%f;%f)) is defined, "
+ "this is unlikely to behave as you expect. You probably want"
+ "at least 2 points.",
+ (*points)->x, (*points)->y);
}
return 0;
@@ -222,14 +205,28 @@ static int get_nb_points(const struct keypoint *d)
static int interpolate(AVFilterContext *ctx, uint8_t *y, const struct keypoint *points)
{
int i, ret = 0;
- const struct keypoint *point;
+ const struct keypoint *point = points;
double xprev = 0;
+ double (*matrix)[3];
+ double *h, *r;
int n = get_nb_points(points); // number of splines
- double (*matrix)[3] = av_calloc(n, sizeof(*matrix));
- double *h = av_malloc((n - 1) * sizeof(*h));
- double *r = av_calloc(n, sizeof(*r));
+ if (n == 0) {
+ for (i = 0; i < 256; i++)
+ y[i] = i;
+ return 0;
+ }
+
+ if (n == 1) {
+ for (i = 0; i < 256; i++)
+ y[i] = av_clip_uint8(point->y * 255);
+ return 0;
+ }
+
+ matrix = av_calloc(n, sizeof(*matrix));
+ h = av_malloc((n - 1) * sizeof(*h));
+ r = av_calloc(n, sizeof(*r));
if (!matrix || !h || !r) {
ret = AVERROR(ENOMEM);
@@ -277,9 +274,14 @@ static int interpolate(AVFilterContext *ctx, uint8_t *y, const struct keypoint *
for (i = n - 2; i >= 0; i--)
r[i] = r[i] - matrix[i][AD] * r[i + 1];
- /* compute the graph with x=[0..255] */
- i = 0;
point = points;
+
+ /* left padding */
+ for (i = 0; i < (int)(point->x * 255); i++)
+ y[i] = av_clip_uint8(point->y * 255);
+
+ /* compute the graph with x=[x0..xN] */
+ i = 0;
av_assert0(point->next); // always at least 2 key points
while (point->next) {
double yc = point->y;
@@ -300,7 +302,7 @@ static int interpolate(AVFilterContext *ctx, uint8_t *y, const struct keypoint *
for (x = x_start; x <= x_end; x++) {
double xx = (x - x_start) * 1/255.;
double yy = a + b*xx + c*xx*xx + d*xx*xx*xx;
- y[x] = av_clipf(yy, 0, 1) * 255;
+ y[x] = av_clip_uint8(yy * 255);
av_log(ctx, AV_LOG_DEBUG, "f(%f)=%f -> y[%d]=%d\n", xx, yy, x, y[x]);
}
@@ -308,6 +310,10 @@ static int interpolate(AVFilterContext *ctx, uint8_t *y, const struct keypoint *
i++;
}
+ /* right padding */
+ for (i = (int)(point->x * 255); i <= 255; i++)
+ y[i] = av_clip_uint8(point->y * 255);
+
end:
av_free(matrix);
av_free(h);