From: glennrp Date: Tue, 22 Mar 2011 19:42:23 +0000 (+0000) Subject: Preserve colors better using 4-4-4 palette when possible when reducing to PNG8. X-Git-Tag: 7.0.1-0~7918 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d337164012450d70d62e71cf4a308a29004f7d57;p=imagemagick Preserve colors better using 4-4-4 palette when possible when reducing to PNG8. --- diff --git a/ChangeLog b/ChangeLog index 3a4e51599..9eab4dfac 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,8 +2,8 @@ * Revised the PNG8 encoder to use 50% threshold instead of 0% when reducing transparency to binary. Collapse all resulting fully transparent colors into one (the background color), to reduce the compressed filesize. - * First try the 3-3-3 palette instead of 3-3-2, to preserve gray better, - when reducing to PNG8. + * First try the 4-4-4 and 3-3-3 palettes instead of 3-3-2, to preserve + colors (especially gray) better, when reducing to PNG8. 2011-03-18 6.6.8-7 Anthony Thyssen * Another fix for -sparse-color and unused color channels diff --git a/coders/png.c b/coders/png.c index c7f098a84..11d25e457 100644 --- a/coders/png.c +++ b/coders/png.c @@ -6814,7 +6814,8 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info, ping_need_colortype_warning, status, - tried_333; + tried_333, + tried_444; QuantumInfo *quantum_info; @@ -6975,8 +6976,9 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info, */ tried_333 = MagickFalse; + tried_444 = MagickFalse; - for (j=0; j<4; j++) + for (j=0; j<5; j++) { /* BUILD_PALETTE * @@ -7518,9 +7520,103 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info, } /* PNG8 can't have more than 256 colors so we quantize the pixels and - * background color to the 3-3-3 or 3-3-2 palette. If the image is - * mostly gray, the 3-3-3 palette should end up with 256 colors or less. + * background color to the 4-4-4, 3-3-3 or 3-3-2 palette. If the image is + * mostly gray, the 4-4-4 palette should end up with 256 colors or less. */ + if (tried_444 == MagickFalse && (image_colors == 0 || image_colors > 256)) + { + if (logging != MagickFalse) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + " Quantizing the background color to 4-4-4"); + + tried_444 = MagickTrue; + + image->background_color.red= + ((((((size_t) + image->background_color.red) >> PNGK) & 0xf0) ) | + (((((size_t) + image->background_color.red) >> PNGK) & 0xf0) >> 4)) * PNGM; + image->background_color.green= + ((((((size_t) + image->background_color.green) >> PNGK) & 0xf0) ) | + (((((size_t) + image->background_color.green) >> PNGK) & 0xf0) >> 4)) * PNGM; + image->background_color.blue= + ((((((size_t) + image->background_color.blue) >> PNGK) & 0xf0) ) | + (((((size_t) + image->background_color.blue) >> PNGK) & 0xf0) >> 4)) * PNGM; + + if (logging != MagickFalse) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + " Quantizing the pixel colors to 4-4-4"); + + if (image->colormap == NULL) + { + for (y=0; y < (ssize_t) image->rows; y++) + { + r=GetAuthenticPixels(image,0,y,image->columns,1, + exception); + + if (r == (PixelPacket *) NULL) + break; + + for (x=0; x < (ssize_t) image->columns; x++) + { + if (r->opacity == TransparentOpacity) + { + r->red = image->background_color.red; + r->green = image->background_color.green; + r->blue = image->background_color.blue; + } + else + { + r->red= + ((((((size_t) r->red) >> PNGK) & 0xf0) ) | + (((((size_t) r->red) >> PNGK) & 0xf0) >> 4)) * PNGM; + r->green= + ((((((size_t) r->green) >> PNGK) & 0xf0) ) | + (((((size_t) r->green) >> PNGK) & 0xf0) >> 4)) * PNGM; + r->blue= + ((((((size_t) r->blue) >> PNGK) & 0xf0) ) | + (((((size_t) r->blue) >> PNGK) & 0xf0) >> 4)) * PNGM; + } + r++; + } + + if (SyncAuthenticPixels(image,exception) == MagickFalse) + break; + } + } + + else /* Should not reach this; colormap already exists and + must be <= 256 */ + { + if (logging != MagickFalse) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + " Quantizing the colormap to 4-4-4"); + for (i=0; icolormap[i].red= + ((((((size_t) + image->colormap[i].red) >> PNGK) & 0xf0) ) | + (((((size_t) + image->colormap[i].red) >> PNGK) & 0xf0) >> 4)) * PNGM; + image->colormap[i].green= + ((((((size_t) + image->colormap[i].green) >> PNGK) & 0xf0) ) | + (((((size_t) + image->colormap[i].green) >> PNGK) & 0xf0) >> 4)) * PNGM; + image->colormap[i].blue= + ((((((size_t) + image->colormap[i].blue) >> PNGK) & 0xf0) ) | + (((((size_t) + image->colormap[i].blue) >> PNGK) & 0xf0) >> 4)) * PNGM; + } + } + continue; + } + if (tried_333 == MagickFalse && (image_colors == 0 || image_colors > 256)) { if (logging != MagickFalse) @@ -7626,9 +7722,9 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info, (((((size_t) image->colormap[i].blue) >> PNGK) & 0xc0) >> 6)) * PNGM; } + } + continue; } - continue; - } if (image_colors == 0 || image_colors > 256) {