cwebp: Don't premultiply during -resize if -exact

Fix issue where color data is discarded in fully transparent
areas when -resize -exact.
BUG=webp:397

Change-Id: I58ce8d5ae172d5d0f0138e07c7df3a3c6cbd0019
This commit is contained in:
Yannis Guyon 2018-09-25 13:02:30 +02:00
parent 637141bc7c
commit b2a867c038

View File

@ -1012,10 +1012,53 @@ int main(int argc, const char *argv[]) {
} }
} }
if ((resize_w | resize_h) > 0) { if ((resize_w | resize_h) > 0) {
WebPPicture picture_no_alpha;
if (config.exact) {
// If -exact, we can't premultiply RGB by A otherwise RGB is lost if A=0.
// We rescale an opaque copy and assemble scaled A and non-premultiplied
// RGB channels. This is slower but it's a very uncommon use case. Color
// leak at sharp alpha edges is possible.
if (!WebPPictureCopy(&picture, &picture_no_alpha)) {
fprintf(stderr, "Error! Cannot copy temporary picture\n");
goto Error;
}
// We enforced picture.use_argb = 1 above. Now, remove the alpha values.
{
int x, y;
uint32_t* argb_no_alpha = picture_no_alpha.argb;
for (y = 0; y < picture_no_alpha.height; ++y) {
for (x = 0; x < picture_no_alpha.width; ++x) {
argb_no_alpha[x] |= 0xff000000; // Opaque copy.
}
argb_no_alpha += picture_no_alpha.argb_stride;
}
}
if (!WebPPictureRescale(&picture_no_alpha, resize_w, resize_h)) {
fprintf(stderr, "Error! Cannot resize temporary picture\n");
goto Error;
}
}
if (!WebPPictureRescale(&picture, resize_w, resize_h)) { if (!WebPPictureRescale(&picture, resize_w, resize_h)) {
fprintf(stderr, "Error! Cannot resize picture\n"); fprintf(stderr, "Error! Cannot resize picture\n");
goto Error; goto Error;
} }
if (config.exact) { // Put back the alpha information.
int x, y;
uint32_t* argb_no_alpha = picture_no_alpha.argb;
uint32_t* argb = picture.argb;
for (y = 0; y < picture_no_alpha.height; ++y) {
for (x = 0; x < picture_no_alpha.width; ++x) {
argb[x] = (argb[x] & 0xff000000) | (argb_no_alpha[x] & 0x00ffffff);
}
argb_no_alpha += picture_no_alpha.argb_stride;
argb += picture.argb_stride;
}
WebPPictureFree(&picture_no_alpha);
}
} }
if (verbose && (crop != 0 || (resize_w | resize_h) > 0)) { if (verbose && (crop != 0 || (resize_w | resize_h) > 0)) {
const double preproc_time = StopwatchReadAndReset(&stop_watch); const double preproc_time = StopwatchReadAndReset(&stop_watch);