fix low bitdepth PNG save of high bitdepth images
SOme combinations of high bitdepth images with low bitdepth PNG save could produce incorrect images, for example saving a 16-bit fourier image as 1-bit.
This commit is contained in:
parent
94d3f93a46
commit
1989203985
@ -5,6 +5,7 @@
|
|||||||
- add "unlimited" to jpegload
|
- add "unlimited" to jpegload
|
||||||
- better 0 detection in unpremultiply
|
- better 0 detection in unpremultiply
|
||||||
- fix low bitdepth spng save [jeffska]
|
- fix low bitdepth spng save [jeffska]
|
||||||
|
- fix PNG low bitdepth save of high bitdepth images
|
||||||
|
|
||||||
21/11/21 started 8.13
|
21/11/21 started 8.13
|
||||||
- configure fails for requested but unmet dependencies [remicollet]
|
- configure fails for requested but unmet dependencies [remicollet]
|
||||||
|
@ -112,12 +112,22 @@ vips_foreign_save_png_build( VipsObject *object )
|
|||||||
in = save->ready;
|
in = save->ready;
|
||||||
g_object_ref( in );
|
g_object_ref( in );
|
||||||
|
|
||||||
/* save->ready will have been converted to uint16 for high-bitdepth
|
/* If no output bitdepth has been specified, use input Type to pick.
|
||||||
* formats (eg. float) ... we need to check Type to see if we want
|
|
||||||
* to save as 8 or 16-bits. Eg. imagine a float image tagged as sRGB.
|
|
||||||
*/
|
*/
|
||||||
if( in->Type == VIPS_INTERPRETATION_sRGB ||
|
if( !vips_object_argument_isset( object, "bitdepth" ) )
|
||||||
in->Type == VIPS_INTERPRETATION_B_W ) {
|
png->bitdepth =
|
||||||
|
in->Type == VIPS_INTERPRETATION_RGB16 ||
|
||||||
|
in->Type == VIPS_INTERPRETATION_GREY16 ? 16 : 8;
|
||||||
|
|
||||||
|
/* Deprecated "colours" arg just sets bitdepth large enough to hold
|
||||||
|
* that many colours.
|
||||||
|
*/
|
||||||
|
if( vips_object_argument_isset( object, "colours" ) )
|
||||||
|
png->bitdepth = ceil( log2( png->colours ) );
|
||||||
|
|
||||||
|
/* Cast in down to 8 bit if we can.
|
||||||
|
*/
|
||||||
|
if( png->bitdepth <= 8 ) {
|
||||||
VipsImage *x;
|
VipsImage *x;
|
||||||
|
|
||||||
if( vips_cast( in, &x, VIPS_FORMAT_UCHAR, NULL ) ) {
|
if( vips_cast( in, &x, VIPS_FORMAT_UCHAR, NULL ) ) {
|
||||||
@ -128,15 +138,6 @@ vips_foreign_save_png_build( VipsObject *object )
|
|||||||
in = x;
|
in = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deprecated "colours" arg just sets bitdepth large enough to hold
|
|
||||||
* that many colours.
|
|
||||||
*/
|
|
||||||
if( vips_object_argument_isset( object, "colours" ) )
|
|
||||||
png->bitdepth = ceil( log2( png->colours ) );
|
|
||||||
|
|
||||||
if( !vips_object_argument_isset( object, "bitdepth" ) )
|
|
||||||
png->bitdepth = in->BandFmt == VIPS_FORMAT_UCHAR ? 8 : 16;
|
|
||||||
|
|
||||||
/* If this is a RGB or RGBA image and a low bit depth has been
|
/* If this is a RGB or RGBA image and a low bit depth has been
|
||||||
* requested, enable palettization.
|
* requested, enable palettization.
|
||||||
*/
|
*/
|
||||||
@ -144,6 +145,11 @@ vips_foreign_save_png_build( VipsObject *object )
|
|||||||
png->bitdepth < 8 )
|
png->bitdepth < 8 )
|
||||||
png->palette = TRUE;
|
png->palette = TRUE;
|
||||||
|
|
||||||
|
/* Disable palettization for >8 bit save.
|
||||||
|
*/
|
||||||
|
if( png->bitdepth >= 8 )
|
||||||
|
png->palette = FALSE;
|
||||||
|
|
||||||
if( vips__png_write_target( in, png->target,
|
if( vips__png_write_target( in, png->target,
|
||||||
png->compression, png->interlace, png->profile, png->filter,
|
png->compression, png->interlace, png->profile, png->filter,
|
||||||
save->strip, png->palette, png->Q, png->dither,
|
save->strip, png->palette, png->Q, png->dither,
|
||||||
|
@ -42,9 +42,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
*/
|
||||||
#define DEBUG_VERBOSE
|
#define DEBUG_VERBOSE
|
||||||
#define DEBUG
|
#define DEBUG
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
@ -485,7 +485,7 @@ vips_foreign_save_spng_write( VipsForeignSaveSpng *spng, VipsImage *in )
|
|||||||
spng_set_option( spng->ctx,
|
spng_set_option( spng->ctx,
|
||||||
SPNG_FILTER_CHOICE, spng->filter );
|
SPNG_FILTER_CHOICE, spng->filter );
|
||||||
|
|
||||||
/* Set resolution. libpng uses pixels per meter.
|
/* Set resolution. png uses pixels per meter.
|
||||||
*/
|
*/
|
||||||
phys.unit_specifier = 1;
|
phys.unit_specifier = 1;
|
||||||
phys.ppu_x = VIPS_RINT( in->Xres * 1000.0 );
|
phys.ppu_x = VIPS_RINT( in->Xres * 1000.0 );
|
||||||
@ -580,12 +580,22 @@ vips_foreign_save_spng_build( VipsObject *object )
|
|||||||
in = save->ready;
|
in = save->ready;
|
||||||
g_object_ref( in );
|
g_object_ref( in );
|
||||||
|
|
||||||
/* in will have been converted to uint16 for high-bitdepth
|
/* If no output bitdepth has been specified, use input Type to pick.
|
||||||
* formats (eg. float) ... we need to check Type to see if we want
|
|
||||||
* to save as 8 or 16-bits. Eg. imagine a float image tagged as sRGB.
|
|
||||||
*/
|
*/
|
||||||
if( in->Type == VIPS_INTERPRETATION_sRGB ||
|
if( !vips_object_argument_isset( object, "bitdepth" ) )
|
||||||
in->Type == VIPS_INTERPRETATION_B_W ) {
|
spng->bitdepth =
|
||||||
|
in->Type == VIPS_INTERPRETATION_RGB16 ||
|
||||||
|
in->Type == VIPS_INTERPRETATION_GREY16 ? 16 : 8;
|
||||||
|
|
||||||
|
/* Deprecated "colours" arg just sets bitdepth large enough to hold
|
||||||
|
* that many colours.
|
||||||
|
*/
|
||||||
|
if( vips_object_argument_isset( object, "colours" ) )
|
||||||
|
spng->bitdepth = ceil( log2( spng->colours ) );
|
||||||
|
|
||||||
|
/* Cast in down to 8 bit if we can.
|
||||||
|
*/
|
||||||
|
if( spng->bitdepth <= 8 ) {
|
||||||
VipsImage *x;
|
VipsImage *x;
|
||||||
|
|
||||||
if( vips_cast( in, &x, VIPS_FORMAT_UCHAR, NULL ) ) {
|
if( vips_cast( in, &x, VIPS_FORMAT_UCHAR, NULL ) ) {
|
||||||
@ -596,19 +606,6 @@ vips_foreign_save_spng_build( VipsObject *object )
|
|||||||
in = x;
|
in = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If no output bitdepth has been specified, use input Type to pick.
|
|
||||||
* We only go for 16 bits for the types where we know there's a
|
|
||||||
* 0-65535 range.
|
|
||||||
*/
|
|
||||||
if( !vips_object_argument_isset( object, "bitdepth" ) )
|
|
||||||
spng->bitdepth = in->BandFmt == VIPS_FORMAT_UCHAR ? 8 : 16;
|
|
||||||
|
|
||||||
/* Deprecated "colours" arg just sets bitdepth large enough to hold
|
|
||||||
* that many colours.
|
|
||||||
*/
|
|
||||||
if( vips_object_argument_isset( object, "colours" ) )
|
|
||||||
spng->bitdepth = ceil( log2( spng->colours ) );
|
|
||||||
|
|
||||||
/* If this is a RGB or RGBA image and a low bit depth has been
|
/* If this is a RGB or RGBA image and a low bit depth has been
|
||||||
* requested, enable palettisation.
|
* requested, enable palettisation.
|
||||||
*/
|
*/
|
||||||
@ -616,6 +613,11 @@ vips_foreign_save_spng_build( VipsObject *object )
|
|||||||
spng->bitdepth < 8 )
|
spng->bitdepth < 8 )
|
||||||
spng->palette = TRUE;
|
spng->palette = TRUE;
|
||||||
|
|
||||||
|
/* Disable palettization for >8 bit save.
|
||||||
|
*/
|
||||||
|
if( spng->bitdepth >= 8 )
|
||||||
|
spng->palette = FALSE;
|
||||||
|
|
||||||
if( vips_foreign_save_spng_write( spng, in ) ) {
|
if( vips_foreign_save_spng_write( spng, in ) ) {
|
||||||
g_object_unref( in );
|
g_object_unref( in );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
Loading…
Reference in New Issue
Block a user