vwebp: Add background color display option

Option -usebgcolor may be used to display ANIM background color (or white if no ANIM chunk), blended on top of checkerboard. By default this is disabled (old behavior) to easily see transparent areas. Spec says that "background color MAY be used", so it's an option.
Key b may be pressed to toggle ANIM background color display. There are visual artifacts (leftovers) when toggling during an animation. This is already the case for rescaling, toggling info etc. (fixing it implies storing viewport render or rendering whole animation from start till current frame).

BUG=webp:394

Change-Id: If9ab898b2eac77226f30f062d522f9861789ef8f
This commit is contained in:
Yannis Guyon 2018-07-20 12:54:30 +02:00
parent 78ad57a36a
commit 4649b3c422
3 changed files with 66 additions and 31 deletions

2
README
View File

@ -402,12 +402,14 @@ Options are:
-nofilter .... disable in-loop filtering -nofilter .... disable in-loop filtering
-dither <int> dithering strength (0..100), default=50 -dither <int> dithering strength (0..100), default=50
-noalphadither disable alpha plane dithering -noalphadither disable alpha plane dithering
-usebgcolor .. display background color
-mt .......... use multi-threading -mt .......... use multi-threading
-info ........ print info -info ........ print info
-h ........... this help message -h ........... this help message
Keyboard shortcuts: Keyboard shortcuts:
'c' ................ toggle use of color profile 'c' ................ toggle use of color profile
'b' ................ toggle background color display
'i' ................ overlay file information 'i' ................ overlay file information
'd' ................ disable blending & disposal (debug) 'd' ................ disable blending & disposal (debug)
'q' / 'Q' / ESC .... quit 'q' / 'Q' / ESC .... quit

View File

@ -56,6 +56,7 @@ static struct {
int print_info; int print_info;
int only_deltas; int only_deltas;
int use_color_profile; int use_color_profile;
int draw_anim_background_color;
int canvas_width, canvas_height; int canvas_width, canvas_height;
int loop_count; int loop_count;
@ -225,6 +226,9 @@ static void decode_callback(int what) {
// Callbacks // Callbacks
static void HandleKey(unsigned char key, int pos_x, int pos_y) { static void HandleKey(unsigned char key, int pos_x, int pos_y) {
// Note: rescaling the window or toggling some features during an animation
// generates visual artifacts. This is not fixed because refreshing the frame
// may require rendering the whole animation from start till current frame.
(void)pos_x; (void)pos_x;
(void)pos_y; (void)pos_y;
if (key == 'q' || key == 'Q' || key == 27 /* Esc */) { if (key == 'q' || key == 'Q' || key == 27 /* Esc */) {
@ -252,9 +256,11 @@ static void HandleKey(unsigned char key, int pos_x, int pos_y) {
glutPostRedisplay(); glutPostRedisplay();
} }
} }
} else if (key == 'b') {
kParams.draw_anim_background_color = 1 - kParams.draw_anim_background_color;
if (!kParams.has_animation) ClearPreviousFrame();
glutPostRedisplay();
} else if (key == 'i') { } else if (key == 'i') {
// Note: doesn't handle refresh of animation's last-frame (it's quite
// more involved to do, since you need to save the previous frame).
kParams.print_info = 1 - kParams.print_info; kParams.print_info = 1 - kParams.print_info;
if (!kParams.has_animation) ClearPreviousFrame(); if (!kParams.has_animation) ClearPreviousFrame();
glutPostRedisplay(); glutPostRedisplay();
@ -309,6 +315,25 @@ static void DrawCheckerBoard(void) {
glPopMatrix(); glPopMatrix();
} }
static void DrawBackground(void) {
// Whole window cleared with clear color, checkerboard rendered on top of it.
glClear(GL_COLOR_BUFFER_BIT);
DrawCheckerBoard();
// ANIM background color rendered (blend) on top. Default is white for still
// images (without ANIM chunk). glClear() can't be used for that (no blend).
if (kParams.draw_anim_background_color) {
glPushMatrix();
glLoadIdentity();
glColor4f(GetColorf(kParams.bg_color, 16), // BGRA from spec
GetColorf(kParams.bg_color, 8),
GetColorf(kParams.bg_color, 0),
GetColorf(kParams.bg_color, 24));
glRecti(-1, -1, +1, +1);
glPopMatrix();
}
}
static void HandleDisplay(void) { static void HandleDisplay(void) {
const WebPDecBuffer* const pic = kParams.pic; const WebPDecBuffer* const pic = kParams.pic;
const WebPIterator* const curr = &kParams.curr_frame; const WebPIterator* const curr = &kParams.curr_frame;
@ -325,7 +350,7 @@ static void HandleDisplay(void) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, pic->u.RGBA.stride / 4); glPixelStorei(GL_UNPACK_ROW_LENGTH, pic->u.RGBA.stride / 4);
if (kParams.only_deltas) { if (kParams.only_deltas) {
DrawCheckerBoard(); DrawBackground();
} else if (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND || } else if (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND ||
curr->blend_method == WEBP_MUX_NO_BLEND) { curr->blend_method == WEBP_MUX_NO_BLEND) {
// glScissor() takes window coordinates (0,0 at bottom left). // glScissor() takes window coordinates (0,0 at bottom left).
@ -353,8 +378,7 @@ static void HandleDisplay(void) {
frame_h = frame_h * kParams.viewport_height / kParams.canvas_height; frame_h = frame_h * kParams.viewport_height / kParams.canvas_height;
glScissor(window_x, window_y, frame_w, frame_h); glScissor(window_x, window_y, frame_w, frame_h);
glClear(GL_COLOR_BUFFER_BIT); // use clear color DrawBackground();
DrawCheckerBoard();
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);
} }
@ -408,37 +432,35 @@ static void StartDisplay(void) {
glutKeyboardFunc(HandleKey); glutKeyboardFunc(HandleKey);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glClearColor(GetColorf(kParams.bg_color, 16), // BGRA from spec glClearColor(0, 0, 0, 0); // window will be cleared to black (no blend)
GetColorf(kParams.bg_color, 8), DrawBackground();
GetColorf(kParams.bg_color, 0),
GetColorf(kParams.bg_color, 24));
glClear(GL_COLOR_BUFFER_BIT);
DrawCheckerBoard();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Main // Main
static void Help(void) { static void Help(void) {
printf("Usage: vwebp in_file [options]\n\n" printf(
"Decodes the WebP image file and visualize it using OpenGL\n" "Usage: vwebp in_file [options]\n\n"
"Options are:\n" "Decodes the WebP image file and visualize it using OpenGL\n"
" -version ..... print version number and exit\n" "Options are:\n"
" -noicc ....... don't use the icc profile if present\n" " -version ..... print version number and exit\n"
" -nofancy ..... don't use the fancy YUV420 upscaler\n" " -noicc ....... don't use the icc profile if present\n"
" -nofilter .... disable in-loop filtering\n" " -nofancy ..... don't use the fancy YUV420 upscaler\n"
" -dither <int> dithering strength (0..100), default=50\n" " -nofilter .... disable in-loop filtering\n"
" -noalphadither disable alpha plane dithering\n" " -dither <int> dithering strength (0..100), default=50\n"
" -mt .......... use multi-threading\n" " -noalphadither disable alpha plane dithering\n"
" -info ........ print info\n" " -usebgcolor .. display background color\n"
" -h ........... this help message\n" " -mt .......... use multi-threading\n"
"\n" " -info ........ print info\n"
"Keyboard shortcuts:\n" " -h ........... this help message\n"
" 'c' ................ toggle use of color profile\n" "\n"
" 'i' ................ overlay file information\n" "Keyboard shortcuts:\n"
" 'd' ................ disable blending & disposal (debug)\n" " 'c' ................ toggle use of color profile\n"
" 'q' / 'Q' / ESC .... quit\n" " 'b' ................ toggle background color display\n"
); " 'i' ................ overlay file information\n"
" 'd' ................ disable blending & disposal (debug)\n"
" 'q' / 'Q' / ESC .... quit\n");
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
@ -453,6 +475,8 @@ int main(int argc, char *argv[]) {
config->options.dithering_strength = 50; config->options.dithering_strength = 50;
config->options.alpha_dithering_strength = 100; config->options.alpha_dithering_strength = 100;
kParams.use_color_profile = 1; kParams.use_color_profile = 1;
// Background color hidden by default to see transparent areas.
kParams.draw_anim_background_color = 0;
for (c = 1; c < argc; ++c) { for (c = 1; c < argc; ++c) {
int parse_error = 0; int parse_error = 0;
@ -467,6 +491,8 @@ int main(int argc, char *argv[]) {
config->options.bypass_filtering = 1; config->options.bypass_filtering = 1;
} else if (!strcmp(argv[c], "-noalphadither")) { } else if (!strcmp(argv[c], "-noalphadither")) {
config->options.alpha_dithering_strength = 0; config->options.alpha_dithering_strength = 0;
} else if (!strcmp(argv[c], "-usebgcolor")) {
kParams.draw_anim_background_color = 1;
} else if (!strcmp(argv[c], "-dither") && c + 1 < argc) { } else if (!strcmp(argv[c], "-dither") && c + 1 < argc) {
config->options.dithering_strength = config->options.dithering_strength =
ExUtilGetInt(argv[++c], 0, &parse_error); ExUtilGetInt(argv[++c], 0, &parse_error);

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH VWEBP 1 "November 25, 2016" .TH VWEBP 1 "July 20, 2018"
.SH NAME .SH NAME
vwebp \- decompress a WebP file and display it in a window vwebp \- decompress a WebP file and display it in a window
.SH SYNOPSIS .SH SYNOPSIS
@ -38,6 +38,10 @@ It helps by smoothing gradients and avoiding banding artifacts. Default: 50.
By default, quantized transparency planes are dithered during decompression, By default, quantized transparency planes are dithered during decompression,
to smooth the gradients. This flag will prevent this dithering. to smooth the gradients. This flag will prevent this dithering.
.TP .TP
.B \-usebgcolor
Fill transparent areas with the bitstream's own background color instead of
checkerboard only. Default is white for non-animated images.
.TP
.B \-mt .B \-mt
Use multi-threading for decoding, if possible. Use multi-threading for decoding, if possible.
.TP .TP
@ -56,6 +60,9 @@ the data will be read from \fIstdin\fP instead of a file.
.B 'c' .B 'c'
Toggle use of color profile. Toggle use of color profile.
.TP .TP
.B 'b'
Toggle display of background color.
.TP
.B 'i' .B 'i'
Overlay file information. Overlay file information.
.TP .TP