Now it displays all color components (not just luma)
either in parade or overlay and also works with RGB colorspace.
Signed-off-by: Paul B Mahol <onemda@gmail.com>
... | ... |
@@ -3146,9 +3146,9 @@ chroma values in vectorscope, similar as @code{color} but actual chroma values |
3146 | 3146 |
are displayed. |
3147 | 3147 |
|
3148 | 3148 |
@item waveform |
3149 |
-per row/column luminance graph. In row mode the left side represents luma = 0 |
|
3150 |
-and right side represents luma = 255. In column mode top side represends |
|
3151 |
-luma = 0 and bottom side represents luma = 255. |
|
3149 |
+per row/column color component graph. In row mode graph in the left side represents |
|
3150 |
+color component value 0 and right side represents value = 255. In column mode top |
|
3151 |
+side represents color component value = 0 and bottom side represents value = 255. |
|
3152 | 3152 |
@end table |
3153 | 3153 |
Default value is @code{levels}. |
3154 | 3154 |
|
... | ... |
@@ -3168,6 +3168,33 @@ Default value is @code{10}. Allowed range is [1, 255]. |
3168 | 3168 |
@item waveform_mode |
3169 | 3169 |
Set mode for @code{waveform}. Can be either @code{row}, or @code{column}. |
3170 | 3170 |
Default is @code{row}. |
3171 |
+ |
|
3172 |
+@item display_mode |
|
3173 |
+Set display mode for @code{waveform}. |
|
3174 |
+It accepts the following values: |
|
3175 |
+@table @samp |
|
3176 |
+@item parade |
|
3177 |
+Display separate waveforms for the color components side by side in |
|
3178 |
+@code{row} mode or one below other in @code{column} mode. |
|
3179 |
+ |
|
3180 |
+In this display mode it is easy to spot color casts in the highlights and |
|
3181 |
+shadows of an image, by comparing the contours of the top and the bottom |
|
3182 |
+of each waveform. Since whites, grays, and blacks are characterized by |
|
3183 |
+exactly equal amounts of red, green, and blue, neutral areas of the |
|
3184 |
+picture should display three waveforms of roughly equal height. |
|
3185 |
+If not, the correction is easy to make by making adjustments to level the |
|
3186 |
+three waveforms. |
|
3187 |
+ |
|
3188 |
+@item overlay |
|
3189 |
+Presents information that's identical to that in the @code{parade}, except |
|
3190 |
+that the waveforms representing color components are superimposed directly |
|
3191 |
+over one another. |
|
3192 |
+ |
|
3193 |
+This display mode can make it easier to spot the relative differences or |
|
3194 |
+similarities in overlapping areas of the color components that are supposed |
|
3195 |
+to be identical, such as neutral whites, grays, or blacks. |
|
3196 |
+@end table |
|
3197 |
+Default is @code{parade}. |
|
3171 | 3198 |
@end table |
3172 | 3199 |
|
3173 | 3200 |
@subsection Examples |
... | ... |
@@ -47,6 +47,7 @@ typedef struct HistogramContext { |
47 | 47 |
int scale_height; |
48 | 48 |
int step; |
49 | 49 |
int waveform_mode; |
50 |
+ int display_mode; |
|
50 | 51 |
} HistogramContext; |
51 | 52 |
|
52 | 53 |
#define OFFSET(x) offsetof(HistogramContext, x) |
... | ... |
@@ -64,6 +65,9 @@ static const AVOption histogram_options[] = { |
64 | 64 |
{ "waveform_mode", "set waveform mode", OFFSET(waveform_mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "waveform_mode"}, |
65 | 65 |
{ "row", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "waveform_mode" }, |
66 | 66 |
{ "column", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "waveform_mode" }, |
67 |
+ { "display_mode", "set display mode", OFFSET(display_mode), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "display_mode"}, |
|
68 |
+ { "parade", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "display_mode" }, |
|
69 |
+ { "overlay", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "display_mode" }, |
|
67 | 70 |
{ NULL }, |
68 | 71 |
}; |
69 | 72 |
|
... | ... |
@@ -99,10 +103,10 @@ static int query_formats(AVFilterContext *ctx) |
99 | 99 |
const enum AVPixelFormat *pix_fmts; |
100 | 100 |
|
101 | 101 |
switch (h->mode) { |
102 |
+ case MODE_WAVEFORM: |
|
102 | 103 |
case MODE_LEVELS: |
103 | 104 |
pix_fmts = levels_pix_fmts; |
104 | 105 |
break; |
105 |
- case MODE_WAVEFORM: |
|
106 | 106 |
case MODE_COLOR: |
107 | 107 |
case MODE_COLOR2: |
108 | 108 |
pix_fmts = color_pix_fmts; |
... | ... |
@@ -153,9 +157,9 @@ static int config_output(AVFilterLink *outlink) |
153 | 153 |
break; |
154 | 154 |
case MODE_WAVEFORM: |
155 | 155 |
if (h->waveform_mode) |
156 |
- outlink->h = 256; |
|
156 |
+ outlink->h = 256 * FFMAX(h->ncomp * h->display_mode, 1); |
|
157 | 157 |
else |
158 |
- outlink->w = 256; |
|
158 |
+ outlink->w = 256 * FFMAX(h->ncomp * h->display_mode, 1); |
|
159 | 159 |
break; |
160 | 160 |
case MODE_COLOR: |
161 | 161 |
case MODE_COLOR2: |
... | ... |
@@ -223,23 +227,31 @@ static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) |
223 | 223 |
break; |
224 | 224 |
case MODE_WAVEFORM: |
225 | 225 |
if (h->waveform_mode) { |
226 |
- for (i = 0; i < inlink->w; i++) { |
|
227 |
- for (j = 0; j < inlink->h; j++) { |
|
228 |
- int pos = in->data[0][j * in->linesize[0] + i] * out->linesize[0] + i; |
|
229 |
- unsigned value = out->data[0][pos]; |
|
230 |
- value = FFMIN(value + h->step, 255); |
|
231 |
- out->data[0][pos] = value; |
|
226 |
+ for (k = 0; k < h->ncomp; k++) { |
|
227 |
+ int offset = k * 256 * h->display_mode; |
|
228 |
+ for (i = 0; i < inlink->w; i++) { |
|
229 |
+ for (j = 0; j < inlink->h; j++) { |
|
230 |
+ int pos = (offset + |
|
231 |
+ in->data[k][j * in->linesize[k] + i]) * |
|
232 |
+ out->linesize[k] + i; |
|
233 |
+ unsigned value = out->data[k][pos]; |
|
234 |
+ value = FFMIN(value + h->step, 255); |
|
235 |
+ out->data[k][pos] = value; |
|
236 |
+ } |
|
232 | 237 |
} |
233 | 238 |
} |
234 | 239 |
} else { |
235 |
- for (i = 0; i < inlink->h; i++) { |
|
236 |
- src = in ->data[0] + i * in ->linesize[0]; |
|
237 |
- dst = out->data[0] + i * out->linesize[0]; |
|
238 |
- for (j = 0; j < inlink->w; j++) { |
|
239 |
- int pos = src[j]; |
|
240 |
- unsigned value = dst[pos]; |
|
241 |
- value = FFMIN(value + h->step, 255); |
|
242 |
- dst[pos] = value; |
|
240 |
+ for (k = 0; k < h->ncomp; k++) { |
|
241 |
+ int offset = k * 256 * h->display_mode; |
|
242 |
+ for (i = 0; i < inlink->h; i++) { |
|
243 |
+ src = in ->data[k] + i * in ->linesize[k]; |
|
244 |
+ dst = out->data[k] + i * out->linesize[k]; |
|
245 |
+ for (j = 0; j < inlink->w; j++) { |
|
246 |
+ int pos = src[j] + offset; |
|
247 |
+ unsigned value = dst[pos]; |
|
248 |
+ value = FFMIN(value + h->step, 255); |
|
249 |
+ dst[pos] = value; |
|
250 |
+ } |
|
243 | 251 |
} |
244 | 252 |
} |
245 | 253 |
} |