From 51dbf607dddbfcba391e6811a248a6082397f8c9 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 19 Dec 2018 14:52:33 +0000 Subject: [PATCH 1/6] add skip-blanks option to dzsave Skip-blanks was a feature of google layout. This patch makes it into an option you can control which defaults on in gm mode. See https://github.com/libvips/libvips/issues/1185 --- ChangeLog | 1 + libvips/foreign/dzsave.c | 38 ++++++++++++++++++++++++++++---------- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index a6db28c2..ceca3096 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,7 @@ - don't stop composite on first non-transparent image [felixbuenemann, GDmac] - add vips_rect_overlapsrect() - composite is much faster at positioning subimages +- dzsave has a new skip_blanks option 21/11/18 started 8.7.3 - fix infinite loop for autofit with non-scaleable font diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c index 54f97a1d..889c4e0a 100644 --- a/libvips/foreign/dzsave.c +++ b/libvips/foreign/dzsave.c @@ -76,6 +76,8 @@ * 24/11/17 * - output overlap-only tiles on edges for better deepzoom spec * compliance + * 19/12/18 + * - add @skip_blanks */ /* @@ -448,6 +450,7 @@ struct _VipsForeignSaveDz { VipsForeignDzContainer container; int compression; VipsRegionShrink region_shrink; + gboolean skip_blanks; /* Tile and overlap geometry. The members above are the parameters we * accept, this next set are the derived values which are actually @@ -1166,10 +1169,7 @@ strip_work( VipsThreadState *state, void *a ) state->pos.width, state->pos.height, NULL ) ) return( -1 ); - /* If we are writing a google map pyramid and the tile is equal to the - * background, don't save. The viewer will display blank.png for us. - */ - if( dz->layout == VIPS_FOREIGN_DZ_LAYOUT_GOOGLE && + if( dz->skip_blanks && tile_equal( x, dz->ink ) ) { g_object_unref( x ); @@ -1631,6 +1631,12 @@ vips_foreign_save_dz_build( VipsObject *object ) dz->tile_size = 256; } + /* skip_blanks defaults TRUE in google mode. + */ + if( dz->layout == VIPS_FOREIGN_DZ_LAYOUT_GOOGLE && + !vips_object_argument_isset( object, "skip_blanks" ) ) + dz->skip_blanks = TRUE; + /* Our tile layout. */ if( dz->layout == VIPS_FOREIGN_DZ_LAYOUT_DZ ) { @@ -1650,8 +1656,7 @@ vips_foreign_save_dz_build( VipsObject *object ) /* Default to white background. vips_foreign_save_init() defaults to * black. */ - if( dz->layout == VIPS_FOREIGN_DZ_LAYOUT_GOOGLE && - !vips_object_argument_isset( object, "background" ) ) { + if( !vips_object_argument_isset( object, "background" ) ) { VipsArrayDouble *background; /* Using g_object_set() to set an input param in build will @@ -1690,9 +1695,9 @@ vips_foreign_save_dz_build( VipsObject *object ) save->ready = z; } - /* We use ink in google mode to check for blank tiles. + /* We use ink to check for blank tiles. */ - if( dz->layout == VIPS_FOREIGN_DZ_LAYOUT_GOOGLE ) { + if( dz->skip_blanks ) { if( !(dz->ink = vips__vector_to_ink( class->nickname, save->ready, VIPS_AREA( save->background )->data, NULL, @@ -2105,6 +2110,13 @@ vips_foreign_save_dz_class_init( VipsForeignSaveDzClass *class ) G_STRUCT_OFFSET( VipsForeignSaveDz, region_shrink ), VIPS_TYPE_REGION_SHRINK, VIPS_REGION_SHRINK_MEAN ); + VIPS_ARG_BOOL( class, "skip_blanks", 19, + _( "Skip blanks" ), + _( "Skip tiles which are nearly equal to the background" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsForeignSaveDz, skip_blanks ), + FALSE ); + /* How annoying. We stupidly had these in earlier versions. */ @@ -2340,7 +2352,8 @@ vips_foreign_save_dz_buffer_init( VipsForeignSaveDzBuffer *buffer ) * * @container: #VipsForeignDzContainer set container type * * @properties: %gboolean write a properties file * * @compression: %gint zip deflate compression level - * * @shrink_region: #VipsRegionShrink How to shrink each 2x2 region. + * * @region_shrink: #VipsRegionShrink How to shrink each 2x2 region + * * @skip_blanks: %gboolean Skip tiles which are equal to the background * * Save an image as a set of tiles at various resolutions. By default dzsave * uses DeepZoom layout -- use @layout to pick other conventions. @@ -2387,6 +2400,10 @@ vips_foreign_save_dz_buffer_init( VipsForeignSaveDzBuffer *buffer ) * You can use @region_shrink to control the method for shrinking each 2x2 * region. This defaults to using the average of the 4 input pixels but you can * also use the median in cases where you want to preserve the range of values. + * + * If you set @skip_blanks, tiles which are almost equal to the background are + * skipped. This can save a lot of space for some image types. This option + * defaults %TRUE in Google layout mode. * * See also: vips_tiffsave(). * @@ -2426,7 +2443,8 @@ vips_dzsave( VipsImage *in, const char *name, ... ) * * @container: #VipsForeignDzContainer set container type * * @properties: %gboolean write a properties file * * @compression: %gint zip deflate compression level - * * @shrink_region: #VipsRegionShrink How to shrink each 2x2 region. + * * @region_shrink: #VipsRegionShrink How to shrink each 2x2 region. + * * @skip_blanks: %gboolean Skip tiles which are equal to the background * * As vips_dzsave(), but save to a memory buffer. * From d1989e4c948ec4fe7cc8896b493525a25fe14721 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 20 Dec 2018 17:07:07 +0000 Subject: [PATCH 2/6] make skip_blanks an int so you can adjust the threshold --- libvips/foreign/dzsave.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c index 889c4e0a..dd777a2b 100644 --- a/libvips/foreign/dzsave.c +++ b/libvips/foreign/dzsave.c @@ -450,7 +450,7 @@ struct _VipsForeignSaveDz { VipsForeignDzContainer container; int compression; VipsRegionShrink region_shrink; - gboolean skip_blanks; + int skip_blanks; /* Tile and overlap geometry. The members above are the parameters we * accept, this next set are the derived values which are actually @@ -1047,14 +1047,14 @@ tile_name( Layer *layer, int x, int y ) return( out ); } -/* Test for tile equal to background colour. In google maps mode, we skip - * blank background tiles. +/* Test for tile nearly equal to background colour. In google maps mode, we + * skip blank background tiles. * - * Don't use exactly equality, since compression artefacts or noise can upset + * Don't use exactly equality since compression artefacts or noise can upset * this. */ static gboolean -tile_equal( VipsImage *image, VipsPel * restrict ink ) +tile_equal( VipsImage *image, int threshold, VipsPel * restrict ink ) { const int bytes = VIPS_IMAGE_SIZEOF_PEL( image ); @@ -1080,7 +1080,7 @@ tile_equal( VipsImage *image, VipsPel * restrict ink ) for( x = 0; x < image->Xsize; x++ ) { for( b = 0; b < bytes; b++ ) - if( VIPS_ABS( p[b] - ink[b] ) > 5 ) { + if( VIPS_ABS( p[b] - ink[b] ) > threshold ) { g_object_unref( region ); return( FALSE ); } @@ -1169,8 +1169,8 @@ strip_work( VipsThreadState *state, void *a ) state->pos.width, state->pos.height, NULL ) ) return( -1 ); - if( dz->skip_blanks && - tile_equal( x, dz->ink ) ) { + if( dz->skip_blanks > 0 && + tile_equal( x, dz->skip_blanks, dz->ink ) ) { g_object_unref( x ); #ifdef DEBUG_VERBOSE @@ -1631,11 +1631,11 @@ vips_foreign_save_dz_build( VipsObject *object ) dz->tile_size = 256; } - /* skip_blanks defaults TRUE in google mode. + /* skip_blanks defaults to 5 in google mode. */ if( dz->layout == VIPS_FOREIGN_DZ_LAYOUT_GOOGLE && !vips_object_argument_isset( object, "skip_blanks" ) ) - dz->skip_blanks = TRUE; + dz->skip_blanks = 5; /* Our tile layout. */ @@ -1697,7 +1697,7 @@ vips_foreign_save_dz_build( VipsObject *object ) /* We use ink to check for blank tiles. */ - if( dz->skip_blanks ) { + if( dz->skip_blanks > 0 ) { if( !(dz->ink = vips__vector_to_ink( class->nickname, save->ready, VIPS_AREA( save->background )->data, NULL, @@ -2110,12 +2110,12 @@ vips_foreign_save_dz_class_init( VipsForeignSaveDzClass *class ) G_STRUCT_OFFSET( VipsForeignSaveDz, region_shrink ), VIPS_TYPE_REGION_SHRINK, VIPS_REGION_SHRINK_MEAN ); - VIPS_ARG_BOOL( class, "skip_blanks", 19, + VIPS_ARG_INT( class, "skip_blanks", 19, _( "Skip blanks" ), _( "Skip tiles which are nearly equal to the background" ), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET( VipsForeignSaveDz, skip_blanks ), - FALSE ); + 0, 65535, 5 ); /* How annoying. We stupidly had these in earlier versions. */ @@ -2353,7 +2353,7 @@ vips_foreign_save_dz_buffer_init( VipsForeignSaveDzBuffer *buffer ) * * @properties: %gboolean write a properties file * * @compression: %gint zip deflate compression level * * @region_shrink: #VipsRegionShrink How to shrink each 2x2 region - * * @skip_blanks: %gboolean Skip tiles which are equal to the background + * * @skip_blanks: %gint Skip tiles which are nearly equal to the background * * Save an image as a set of tiles at various resolutions. By default dzsave * uses DeepZoom layout -- use @layout to pick other conventions. @@ -2401,9 +2401,10 @@ vips_foreign_save_dz_buffer_init( VipsForeignSaveDzBuffer *buffer ) * region. This defaults to using the average of the 4 input pixels but you can * also use the median in cases where you want to preserve the range of values. * - * If you set @skip_blanks, tiles which are almost equal to the background are - * skipped. This can save a lot of space for some image types. This option - * defaults %TRUE in Google layout mode. + * If you set @skip_blanks to a value greater than zero, tiles which are + * all within that many pixel values to the background are skipped. This can + * save a lot of space for some image types. This option defaults to 5 in + * Google layout mode, 0 otherwise. * * See also: vips_tiffsave(). * @@ -2444,7 +2445,7 @@ vips_dzsave( VipsImage *in, const char *name, ... ) * * @properties: %gboolean write a properties file * * @compression: %gint zip deflate compression level * * @region_shrink: #VipsRegionShrink How to shrink each 2x2 region. - * * @skip_blanks: %gboolean Skip tiles which are equal to the background + * * @skip_blanks: %gint Skip tiles which are nearly equal to the background * * As vips_dzsave(), but save to a memory buffer. * From 74ee68fd79e33218f751bc08cfcecbf4c7ce8e0a Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Fri, 21 Dec 2018 14:08:54 +0000 Subject: [PATCH 3/6] use -1 for do-nothing so that users can have skip-only-exact-blanks see https://github.com/libvips/libvips/issues/1185#issuecomment-449115143 --- libvips/foreign/dzsave.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c index dd777a2b..c4394a3f 100644 --- a/libvips/foreign/dzsave.c +++ b/libvips/foreign/dzsave.c @@ -1169,7 +1169,7 @@ strip_work( VipsThreadState *state, void *a ) state->pos.width, state->pos.height, NULL ) ) return( -1 ); - if( dz->skip_blanks > 0 && + if( dz->skip_blanks >= 0 && tile_equal( x, dz->skip_blanks, dz->ink ) ) { g_object_unref( x ); @@ -1697,7 +1697,7 @@ vips_foreign_save_dz_build( VipsObject *object ) /* We use ink to check for blank tiles. */ - if( dz->skip_blanks > 0 ) { + if( dz->skip_blanks >= 0 ) { if( !(dz->ink = vips__vector_to_ink( class->nickname, save->ready, VIPS_AREA( save->background )->data, NULL, @@ -2115,7 +2115,7 @@ vips_foreign_save_dz_class_init( VipsForeignSaveDzClass *class ) _( "Skip tiles which are nearly equal to the background" ), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET( VipsForeignSaveDz, skip_blanks ), - 0, 65535, 5 ); + -1, 65535, 5 ); /* How annoying. We stupidly had these in earlier versions. */ @@ -2156,6 +2156,7 @@ vips_foreign_save_dz_init( VipsForeignSaveDz *dz ) dz->container = VIPS_FOREIGN_DZ_CONTAINER_FS; dz->compression = 0; dz->region_shrink = VIPS_REGION_SHRINK_MEAN; + dz->skip_blanks = -1; } typedef struct _VipsForeignSaveDzFile { @@ -2352,8 +2353,8 @@ vips_foreign_save_dz_buffer_init( VipsForeignSaveDzBuffer *buffer ) * * @container: #VipsForeignDzContainer set container type * * @properties: %gboolean write a properties file * * @compression: %gint zip deflate compression level - * * @region_shrink: #VipsRegionShrink How to shrink each 2x2 region - * * @skip_blanks: %gint Skip tiles which are nearly equal to the background + * * @region_shrink: #VipsRegionShrink how to shrink each 2x2 region + * * @skip_blanks: %gint skip tiles which are nearly equal to the background * * Save an image as a set of tiles at various resolutions. By default dzsave * uses DeepZoom layout -- use @layout to pick other conventions. @@ -2401,10 +2402,10 @@ vips_foreign_save_dz_buffer_init( VipsForeignSaveDzBuffer *buffer ) * region. This defaults to using the average of the 4 input pixels but you can * also use the median in cases where you want to preserve the range of values. * - * If you set @skip_blanks to a value greater than zero, tiles which are - * all within that many pixel values to the background are skipped. This can - * save a lot of space for some image types. This option defaults to 5 in - * Google layout mode, 0 otherwise. + * If you set @skip_blanks to a value greater than or equal to zero, tiles + * which are all within that many pixel values to the background are skipped. + * This can save a lot of space for some image types. This option defaults to + * 5 in Google layout mode, -1 otherwise. * * See also: vips_tiffsave(). * @@ -2444,8 +2445,8 @@ vips_dzsave( VipsImage *in, const char *name, ... ) * * @container: #VipsForeignDzContainer set container type * * @properties: %gboolean write a properties file * * @compression: %gint zip deflate compression level - * * @region_shrink: #VipsRegionShrink How to shrink each 2x2 region. - * * @skip_blanks: %gint Skip tiles which are nearly equal to the background + * * @region_shrink: #VipsRegionShrink how to shrink each 2x2 region. + * * @skip_blanks: %gint skip tiles which are nearly equal to the background * * As vips_dzsave(), but save to a memory buffer. * From b9c3dcd274525d381fa2cad28a0817a4581c56d1 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Fri, 28 Dec 2018 22:23:15 +0000 Subject: [PATCH 4/6] fix dzsave skip_blanks default the default value was not being declared correctly [felixbuenemann] see https://github.com/libvips/libvips/issues/1185#issuecomment-450427889 --- libvips/foreign/dzsave.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c index c4394a3f..65ea028b 100644 --- a/libvips/foreign/dzsave.c +++ b/libvips/foreign/dzsave.c @@ -2115,7 +2115,7 @@ vips_foreign_save_dz_class_init( VipsForeignSaveDzClass *class ) _( "Skip tiles which are nearly equal to the background" ), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET( VipsForeignSaveDz, skip_blanks ), - -1, 65535, 5 ); + -1, 65535, -1 ); /* How annoying. We stupidly had these in earlier versions. */ From 21bceb5c3854ca25d5b92e732bd01574bda6db6f Mon Sep 17 00:00:00 2001 From: Dimitri Bouron Date: Mon, 31 Dec 2018 17:03:47 +0100 Subject: [PATCH 5/6] Fix compilation error when lcms has not been found If HAVE_LCMS2 is not defined, VipsImage is not declared in both CMYK2XYZ and XYZ2CMYK source files. --- libvips/colour/CMYK2XYZ.c | 3 ++- libvips/colour/XYZ2CMYK.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libvips/colour/CMYK2XYZ.c b/libvips/colour/CMYK2XYZ.c index 83e2603c..0feac311 100644 --- a/libvips/colour/CMYK2XYZ.c +++ b/libvips/colour/CMYK2XYZ.c @@ -37,12 +37,13 @@ #endif /*HAVE_CONFIG_H*/ #include +#include + #ifdef HAVE_LCMS2 #include #include -#include #include #include "pcolour.h" diff --git a/libvips/colour/XYZ2CMYK.c b/libvips/colour/XYZ2CMYK.c index bf5cd2b3..e91699e1 100644 --- a/libvips/colour/XYZ2CMYK.c +++ b/libvips/colour/XYZ2CMYK.c @@ -37,12 +37,13 @@ #endif /*HAVE_CONFIG_H*/ #include +#include + #ifdef HAVE_LCMS2 #include #include -#include #include #include "pcolour.h" From 7854ead8776e26e7e5c6e876588eaa90e034a0db Mon Sep 17 00:00:00 2001 From: Lovell Fuller Date: Tue, 1 Jan 2019 15:26:35 +0000 Subject: [PATCH 6/6] PNG loader: attach palette bit depth, if any, as metadata --- libvips/foreign/vipspng.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libvips/foreign/vipspng.c b/libvips/foreign/vipspng.c index 89c65b50..5d980425 100644 --- a/libvips/foreign/vipspng.c +++ b/libvips/foreign/vipspng.c @@ -490,6 +490,11 @@ png2vips_header( Read *read, VipsImage *out ) return( -1 ); } + /* Attach original palette bit depth, if any, as metadata. + */ + if( color_type == PNG_COLOR_TYPE_PALETTE ) + vips_image_set_int( out, "palette-bit-depth", bit_depth ); + return( 0 ); }