mirror of https://git.ffmpeg.org/ffmpeg.git
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>
This commit is contained in:
parent
da726a8763
commit
4fa9defc7f
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue