Old syntax has been kept for compatibility reasons.
Signed-off-by: Stefano Sabatini <stefasab@gmail.com>
... | ... |
@@ -2191,12 +2191,53 @@ a float number which specifies chroma temporal strength, defaults to |
2191 | 2191 |
|
2192 | 2192 |
Modify the hue and/or the saturation of the input. |
2193 | 2193 |
|
2194 |
-This filter accepts the optional parameters: @var{hue}:@var{saturation}. |
|
2194 |
+This filter accepts the following optional named options: |
|
2195 | 2195 |
|
2196 |
-@var{hue} must be a float number that specifies the hue angle as a |
|
2197 |
-number of degrees, and defaults to 0.0. |
|
2198 |
-@var{saturation} must be a float number that specifies the saturation |
|
2199 |
-in the [-10,10] range, and defaults to 1.0. |
|
2196 |
+@table @option |
|
2197 |
+@item h |
|
2198 |
+Specify the hue angle as a number of degrees. It accepts a float |
|
2199 |
+number or an expression, and defaults to 0.0. |
|
2200 |
+ |
|
2201 |
+@item H |
|
2202 |
+Specify the hue angle as a number of degrees. It accepts a float |
|
2203 |
+number or an expression, and defaults to 0.0. |
|
2204 |
+ |
|
2205 |
+@item s |
|
2206 |
+Specify the saturation in the [-10,10] range. It accepts a float number and |
|
2207 |
+defaults to 1.0. |
|
2208 |
+@end table |
|
2209 |
+ |
|
2210 |
+The options can also be set using the syntax: @var{hue}:@var{saturation} |
|
2211 |
+ |
|
2212 |
+In this case @var{hue} is expressed in degrees. |
|
2213 |
+ |
|
2214 |
+Some examples follow: |
|
2215 |
+@itemize |
|
2216 |
+@item |
|
2217 |
+Set the hue to 90 degrees and the saturation to 1.0: |
|
2218 |
+@example |
|
2219 |
+hue=h=90:s=1 |
|
2220 |
+@end example |
|
2221 |
+ |
|
2222 |
+@item |
|
2223 |
+Same command but expressing the hue in radians: |
|
2224 |
+@example |
|
2225 |
+hue=H=PI/2:s=1 |
|
2226 |
+@end example |
|
2227 |
+ |
|
2228 |
+@item |
|
2229 |
+Same command without named options, hue must be expressed in degrees: |
|
2230 |
+@example |
|
2231 |
+hue=90:1 |
|
2232 |
+@end example |
|
2233 |
+ |
|
2234 |
+@item |
|
2235 |
+Note that "h:s" syntax does not support expressions for the values of |
|
2236 |
+h and s, so the following example will issue an error: |
|
2237 |
+@example |
|
2238 |
+hue=PI/2:1 |
|
2239 |
+@end example |
|
2240 |
+@end itemize |
|
2200 | 2241 |
|
2201 | 2242 |
@section idet |
2202 | 2243 |
|
... | ... |
@@ -30,7 +30,7 @@ |
30 | 30 |
|
31 | 31 |
#define LIBAVFILTER_VERSION_MAJOR 3 |
32 | 32 |
#define LIBAVFILTER_VERSION_MINOR 9 |
33 |
-#define LIBAVFILTER_VERSION_MICRO 101 |
|
33 |
+#define LIBAVFILTER_VERSION_MICRO 102 |
|
34 | 34 |
|
35 | 35 |
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ |
36 | 36 |
LIBAVFILTER_VERSION_MINOR, \ |
... | ... |
@@ -25,7 +25,9 @@ |
25 | 25 |
* Ported from MPlayer libmpcodecs/vf_hue.c. |
26 | 26 |
*/ |
27 | 27 |
|
28 |
+#include <float.h> |
|
28 | 29 |
#include "libavutil/imgutils.h" |
30 |
+#include "libavutil/opt.h" |
|
29 | 31 |
#include "libavutil/pixdesc.h" |
30 | 32 |
|
31 | 33 |
#include "avfilter.h" |
... | ... |
@@ -33,8 +35,13 @@ |
33 | 33 |
#include "internal.h" |
34 | 34 |
#include "video.h" |
35 | 35 |
|
36 |
+#define HUE_DEFAULT_VAL 0 |
|
37 |
+#define SAT_DEFAULT_VAL 1 |
|
38 |
+ |
|
36 | 39 |
typedef struct { |
37 |
- float hue; |
|
40 |
+ const AVClass *class; |
|
41 |
+ float hue_deg; /* hue expressed in degrees */ |
|
42 |
+ float hue; /* hue expressed in radians */ |
|
38 | 43 |
float saturation; |
39 | 44 |
int hsub; |
40 | 45 |
int vsub; |
... | ... |
@@ -42,13 +49,44 @@ typedef struct { |
42 | 42 |
int32_t hue_cos; |
43 | 43 |
} HueContext; |
44 | 44 |
|
45 |
+#define OFFSET(x) offsetof(HueContext, x) |
|
46 |
+static const AVOption hue_options[] = { |
|
47 |
+ { "h", "set the hue angle degrees", OFFSET(hue_deg), AV_OPT_TYPE_FLOAT, |
|
48 |
+ { -FLT_MAX }, -FLT_MAX, FLT_MAX, AV_OPT_FLAG_VIDEO_PARAM }, |
|
49 |
+ { "H", "set the hue angle radians", OFFSET(hue), AV_OPT_TYPE_FLOAT, |
|
50 |
+ { -FLT_MAX }, -FLT_MAX, FLT_MAX, AV_OPT_FLAG_VIDEO_PARAM }, |
|
51 |
+ { "s", "set the saturation value", OFFSET(saturation), AV_OPT_TYPE_FLOAT, |
|
52 |
+ { SAT_DEFAULT_VAL }, -10, 10, AV_OPT_FLAG_VIDEO_PARAM }, |
|
53 |
+ { NULL } |
|
54 |
+}; |
|
55 |
+ |
|
56 |
+AVFILTER_DEFINE_CLASS(hue); |
|
57 |
+ |
|
45 | 58 |
static av_cold int init(AVFilterContext *ctx, const char *args) |
46 | 59 |
{ |
47 | 60 |
HueContext *hue = ctx->priv; |
48 |
- float h = 0, s = 1; |
|
49 |
- int n; |
|
61 |
+ float h = HUE_DEFAULT_VAL, s = SAT_DEFAULT_VAL; |
|
62 |
+ int n, ret; |
|
50 | 63 |
char c1 = 0, c2 = 0; |
64 |
+ char *equal; |
|
65 |
+ |
|
66 |
+ hue->class = &hue_class; |
|
51 | 67 |
|
68 |
+ /* named options syntax */ |
|
69 |
+ if (equal = strchr(args, '=')) { |
|
70 |
+ av_opt_set_defaults(hue); |
|
71 |
+ if ((ret = av_set_options_string(hue, args, "=", ":")) < 0) |
|
72 |
+ return ret; |
|
73 |
+ if (hue->hue != -FLT_MAX && hue->hue_deg != -FLT_MAX) { |
|
74 |
+ av_log(ctx, AV_LOG_ERROR, |
|
75 |
+ "H and h options are incompatible and cannot be specified " |
|
76 |
+ "at the same time\n"); |
|
77 |
+ return AVERROR(EINVAL); |
|
78 |
+ } |
|
79 |
+ if (hue->hue == -FLT_MAX) |
|
80 |
+ hue->hue = HUE_DEFAULT_VAL; |
|
81 |
+ /* compatibility syntax */ |
|
82 |
+ } else { |
|
52 | 83 |
if (args) { |
53 | 84 |
n = sscanf(args, "%f%c%f%c", &h, &c1, &s, &c2); |
54 | 85 |
if (n != 0 && n != 1 && (n != 3 || c1 != ':')) { |
... | ... |
@@ -57,7 +95,6 @@ static av_cold int init(AVFilterContext *ctx, const char *args) |
57 | 57 |
"must be in the form 'hue[:saturation]'\n", args); |
58 | 58 |
return AVERROR(EINVAL); |
59 | 59 |
} |
60 |
- } |
|
61 | 60 |
|
62 | 61 |
if (s < -10 || s > 10) { |
63 | 62 |
av_log(ctx, AV_LOG_ERROR, |
... | ... |
@@ -65,14 +102,25 @@ static av_cold int init(AVFilterContext *ctx, const char *args) |
65 | 65 |
"must be included between range -10 and +10\n", s); |
66 | 66 |
return AVERROR(EINVAL); |
67 | 67 |
} |
68 |
- |
|
69 |
- /* Convert angle from degree to radian */ |
|
70 |
- hue->hue = h * M_PI / 180; |
|
68 |
+ } |
|
69 |
+ hue->hue_deg = h; |
|
71 | 70 |
hue->saturation = s; |
71 |
+ } |
|
72 |
+ |
|
73 |
+ if (hue->hue_deg != -FLT_MAX) |
|
74 |
+ /* Convert angle from degrees to radians */ |
|
75 |
+ hue->hue = hue->hue_deg * M_PI / 180; |
|
72 | 76 |
|
73 | 77 |
return 0; |
74 | 78 |
} |
75 | 79 |
|
80 |
+static av_cold void uninit(AVFilterContext *ctx) |
|
81 |
+{ |
|
82 |
+ HueContext *hue = ctx->priv; |
|
83 |
+ |
|
84 |
+ av_opt_free(hue); |
|
85 |
+} |
|
86 |
+ |
|
76 | 87 |
static int query_formats(AVFilterContext *ctx) |
77 | 88 |
{ |
78 | 89 |
static const enum PixelFormat pix_fmts[] = { |
... | ... |
@@ -180,6 +228,7 @@ AVFilter avfilter_vf_hue = { |
180 | 180 |
.priv_size = sizeof(HueContext), |
181 | 181 |
|
182 | 182 |
.init = init, |
183 |
+ .uninit = uninit, |
|
183 | 184 |
.query_formats = query_formats, |
184 | 185 |
|
185 | 186 |
.inputs = (const AVFilterPad[]) { |