Browse code

lavfi/histogram: make waveform mode more useful

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>

Paul B Mahol authored on 2013/02/10 01:05:28
Showing 2 changed files
... ...
@@ -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
         }