From 4fa9defc7fdec348d84be912745a166fa6635b8b Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 9 Feb 2013 16:05:28 +0000 Subject: [PATCH] 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 --- doc/filters.texi | 33 ++++++++++++++++++++++++--- libavfilter/vf_histogram.c | 46 ++++++++++++++++++++++++-------------- 2 files changed, 59 insertions(+), 20 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 0a2a374bf2..da80ff5356 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -3146,9 +3146,9 @@ chroma values in vectorscope, similar as @code{color} but actual chroma values are displayed. @item waveform -per row/column luminance graph. In row mode the left side represents luma = 0 -and right side represents luma = 255. In column mode top side represends -luma = 0 and bottom side represents luma = 255. +per row/column color component graph. In row mode graph in the left side represents +color component value 0 and right side represents value = 255. In column mode top +side represents color component value = 0 and bottom side represents value = 255. @end table Default value is @code{levels}. @@ -3168,6 +3168,33 @@ Default value is @code{10}. Allowed range is [1, 255]. @item waveform_mode Set mode for @code{waveform}. Can be either @code{row}, or @code{column}. Default is @code{row}. + +@item display_mode +Set display mode for @code{waveform}. +It accepts the following values: +@table @samp +@item parade +Display separate waveforms for the color components side by side in +@code{row} mode or one below other in @code{column} mode. + +In this display mode it is easy to spot color casts in the highlights and +shadows of an image, by comparing the contours of the top and the bottom +of each waveform. Since whites, grays, and blacks are characterized by +exactly equal amounts of red, green, and blue, neutral areas of the +picture should display three waveforms of roughly equal height. +If not, the correction is easy to make by making adjustments to level the +three waveforms. + +@item overlay +Presents information that's identical to that in the @code{parade}, except +that the waveforms representing color components are superimposed directly +over one another. + +This display mode can make it easier to spot the relative differences or +similarities in overlapping areas of the color components that are supposed +to be identical, such as neutral whites, grays, or blacks. +@end table +Default is @code{parade}. @end table @subsection Examples diff --git a/libavfilter/vf_histogram.c b/libavfilter/vf_histogram.c index 22de387587..ee9689f5e6 100644 --- a/libavfilter/vf_histogram.c +++ b/libavfilter/vf_histogram.c @@ -47,6 +47,7 @@ typedef struct HistogramContext { int scale_height; int step; int waveform_mode; + int display_mode; } HistogramContext; #define OFFSET(x) offsetof(HistogramContext, x) @@ -64,6 +65,9 @@ static const AVOption histogram_options[] = { { "waveform_mode", "set waveform mode", OFFSET(waveform_mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "waveform_mode"}, { "row", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "waveform_mode" }, { "column", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "waveform_mode" }, + { "display_mode", "set display mode", OFFSET(display_mode), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "display_mode"}, + { "parade", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "display_mode" }, + { "overlay", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "display_mode" }, { NULL }, }; @@ -99,10 +103,10 @@ static int query_formats(AVFilterContext *ctx) const enum AVPixelFormat *pix_fmts; switch (h->mode) { + case MODE_WAVEFORM: case MODE_LEVELS: pix_fmts = levels_pix_fmts; break; - case MODE_WAVEFORM: case MODE_COLOR: case MODE_COLOR2: pix_fmts = color_pix_fmts; @@ -153,9 +157,9 @@ static int config_output(AVFilterLink *outlink) break; case MODE_WAVEFORM: if (h->waveform_mode) - outlink->h = 256; + outlink->h = 256 * FFMAX(h->ncomp * h->display_mode, 1); else - outlink->w = 256; + outlink->w = 256 * FFMAX(h->ncomp * h->display_mode, 1); break; case MODE_COLOR: case MODE_COLOR2: @@ -223,23 +227,31 @@ static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) break; case MODE_WAVEFORM: if (h->waveform_mode) { - for (i = 0; i < inlink->w; i++) { - for (j = 0; j < inlink->h; j++) { - int pos = in->data[0][j * in->linesize[0] + i] * out->linesize[0] + i; - unsigned value = out->data[0][pos]; - value = FFMIN(value + h->step, 255); - out->data[0][pos] = value; + for (k = 0; k < h->ncomp; k++) { + int offset = k * 256 * h->display_mode; + for (i = 0; i < inlink->w; i++) { + for (j = 0; j < inlink->h; j++) { + int pos = (offset + + in->data[k][j * in->linesize[k] + i]) * + out->linesize[k] + i; + unsigned value = out->data[k][pos]; + value = FFMIN(value + h->step, 255); + out->data[k][pos] = value; + } } } } else { - for (i = 0; i < inlink->h; i++) { - src = in ->data[0] + i * in ->linesize[0]; - dst = out->data[0] + i * out->linesize[0]; - for (j = 0; j < inlink->w; j++) { - int pos = src[j]; - unsigned value = dst[pos]; - value = FFMIN(value + h->step, 255); - dst[pos] = value; + for (k = 0; k < h->ncomp; k++) { + int offset = k * 256 * h->display_mode; + for (i = 0; i < inlink->h; i++) { + src = in ->data[k] + i * in ->linesize[k]; + dst = out->data[k] + i * out->linesize[k]; + for (j = 0; j < inlink->w; j++) { + int pos = src[j] + offset; + unsigned value = dst[pos]; + value = FFMIN(value + h->step, 255); + dst[pos] = value; + } } } }