add "depth" param to tiffsave

Add a "depth" param to tiffsave to set pyramid depth, just like the
"depth" param on dzsave.

See https://github.com/libvips/libvips/issues/1485
This commit is contained in:
John Cupitt 2020-01-26 18:39:47 +00:00
parent f8c7f9dac9
commit 42930e8d87
4 changed files with 68 additions and 12 deletions

View File

@ -3,6 +3,7 @@
- add @id to dzsave to set IIIF id property [regisrob]
- add max and min to region shrink [rgluskin]
- allow \ as an escape character in vips_break_token() [akemrir]
- tiffsave has a "depth" param to set max pyr depth
20/6/19 started 8.9.1
- don't use the new source loaders for new_from_file or new_from_buffer, it

View File

@ -61,7 +61,9 @@ int vips__tiff_write( VipsImage *in, const char *filename,
gboolean properties,
gboolean strip,
VipsRegionShrink region_shrink,
int level, gboolean lossless );
int level,
gboolean lossless,
VipsForeignDzDepth depth );
int vips__tiff_write_buf( VipsImage *in,
void **obuf, size_t *olen,
@ -77,7 +79,9 @@ int vips__tiff_write_buf( VipsImage *in,
gboolean rgbjpeg,
gboolean properties, gboolean strip,
VipsRegionShrink region_shrink,
int level, gboolean lossless );
int level,
gboolean lossless,
VipsForeignDzDepth depth );
gboolean vips__istiff_source( VipsSource *source );
gboolean vips__istifftiled_source( VipsSource *source );

View File

@ -19,6 +19,8 @@
* - add @level and @lossless
* 4/9/18 [f--f]
* - xres/yres params were in pixels/cm
* 26/1/20
* - add "depth" to set pyr depth
*/
/*
@ -95,6 +97,7 @@ typedef struct _VipsForeignSaveTiff {
VipsRegionShrink region_shrink;
int level;
gboolean lossless;
VipsForeignDzDepth depth;
} VipsForeignSaveTiff;
typedef VipsForeignSaveClass VipsForeignSaveTiffClass;
@ -330,6 +333,13 @@ vips_foreign_save_tiff_class_init( VipsForeignSaveTiffClass *class )
G_STRUCT_OFFSET( VipsForeignSaveTiff, lossless ),
FALSE );
VIPS_ARG_ENUM( class, "depth", 25,
_( "Depth" ),
_( "Pyramid depth" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveTiff, depth ),
VIPS_TYPE_FOREIGN_DZ_DEPTH, VIPS_FOREIGN_DZ_DEPTH_ONETILE );
}
static void
@ -346,6 +356,7 @@ vips_foreign_save_tiff_init( VipsForeignSaveTiff *tiff )
tiff->region_shrink = VIPS_REGION_SHRINK_MEAN;
tiff->level = 10;
tiff->lossless = FALSE;
tiff->depth = VIPS_FOREIGN_DZ_DEPTH_ONETILE;
}
typedef struct _VipsForeignSaveTiffFile {
@ -384,7 +395,8 @@ vips_foreign_save_tiff_file_build( VipsObject *object )
save->strip,
tiff->region_shrink,
tiff->level,
tiff->lossless ) )
tiff->lossless,
tiff->depth ) )
return( -1 );
return( 0 );
@ -455,7 +467,8 @@ vips_foreign_save_tiff_buffer_build( VipsObject *object )
save->strip,
tiff->region_shrink,
tiff->level,
tiff->lossless ) )
tiff->lossless,
tiff->depth ) )
return( -1 );
/* vips__tiff_write_buf() makes a buffer that needs g_free(), not
@ -523,6 +536,7 @@ vips_foreign_save_tiff_buffer_init( VipsForeignSaveTiffBuffer *buffer )
* * @region_shrink: #VipsRegionShrink How to shrink each 2x2 region.
* * @level: %gint, Zstd compression level
* * @lossless: %gboolean, WebP losssless mode
* * @depth: #VipsForeignDzDepth how deep to make the pyramid
*
* Write a VIPS image to a file as TIFF.
*
@ -564,6 +578,10 @@ vips_foreign_save_tiff_buffer_init( VipsForeignSaveTiffBuffer *buffer )
* default each 2x2 block is just averaged, but you can set MODE or MEDIAN as
* well.
*
* By default, the pyramid stops when the image is small enough to fit in one
* tile. Use @depth to stop when the image fits in one pixel, or to only write
* a single layer.
*
* Set @squash to make 8-bit uchar images write as 1-bit TIFFs. Values >128
* are written as white, values <=128 as black. Normally vips will write
* MINISBLACK TIFFs where black is a 0 bit, but if you set @miniswhite, it
@ -642,6 +660,7 @@ vips_tiffsave( VipsImage *in, const char *filename, ... )
* * @region_shrink: #VipsRegionShrink How to shrink each 2x2 region.
* * @level: %gint, Zstd compression level
* * @lossless: %gboolean, WebP losssless mode
* * @depth: #VipsForeignDzDepth how deep to make the pyramid
*
* As vips_tiffsave(), but save to a memory buffer.
*

View File

@ -187,6 +187,8 @@
* - add @level and @lossless
* 18/12/19
* - "squash" now squashes 3-band float LAB down to LABQ
* 26/1/20
* - add "depth" to set pyr depth
*/
/*
@ -327,6 +329,7 @@ struct _Wtiff {
VipsRegionShrink region_shrink; /* How to shrink regions */
int level; /* zstd compression level */
gboolean lossless; /* webp lossless mode */
VipsForeignDzDepth depth; /* Pyr depth */
/* True if we've detected a toilet-roll image, plus the page height,
* which has been checked to be a factor of im->Ysize.
@ -420,19 +423,41 @@ wtiff_layer_new( Wtiff *wtiff, Layer *above, int width, int height )
layer->sub, width, height );
*/
if( wtiff->pyramid )
if( wtiff->pyramid ) {
int limitw, limith;
switch( wtiff->depth ) {
case VIPS_FOREIGN_DZ_DEPTH_ONEPIXEL:
limitw = limith = 1;
break;
case VIPS_FOREIGN_DZ_DEPTH_ONETILE:
limitw = wtiff->tilew;
limith = wtiff->tileh;
break;
case VIPS_FOREIGN_DZ_DEPTH_ONE:
limitw = wtiff->ready->Xsize;
limith = wtiff->ready->Ysize;
break;
default:
g_assert_not_reached();
}
/* We make another layer if the image is too large to fit in a
* single tile, and if neither axis is greater than 1.
*
* Very tall or wide images might end up with a smallest layer
* larger than one tile.
*/
if( (layer->width > wtiff->tilew ||
layer->height > wtiff->tileh) &&
if( (layer->width > limitw ||
layer->height > limith) &&
layer->width > 1 &&
layer->height > 1 )
layer->below = wtiff_layer_new( wtiff, layer,
width / 2, height / 2 );
}
/* The name for the top layer is the output filename.
*
@ -969,7 +994,9 @@ wtiff_new( VipsImage *input, const char *filename,
gboolean properties,
gboolean strip,
VipsRegionShrink region_shrink,
int level, gboolean lossless )
int level,
gboolean lossless,
VipsForeignDzDepth depth )
{
Wtiff *wtiff;
@ -1000,6 +1027,7 @@ wtiff_new( VipsImage *input, const char *filename,
wtiff->region_shrink = region_shrink;
wtiff->level = level;
wtiff->lossless = lossless;
wtiff->depth = depth;
wtiff->toilet_roll = FALSE;
wtiff->page_height = vips_image_get_page_height( input );
wtiff->image_height = input->Ysize;
@ -1889,7 +1917,9 @@ vips__tiff_write( VipsImage *input, const char *filename,
gboolean rgbjpeg,
gboolean properties, gboolean strip,
VipsRegionShrink region_shrink,
int level, gboolean lossless )
int level,
gboolean lossless,
VipsForeignDzDepth depth )
{
Wtiff *wtiff;
@ -1903,7 +1933,7 @@ vips__tiff_write( VipsImage *input, const char *filename,
compression, Q, predictor, profile,
tile, tile_width, tile_height, pyramid, squash,
miniswhite, resunit, xres, yres, bigtiff, rgbjpeg,
properties, strip, region_shrink, level, lossless )) )
properties, strip, region_shrink, level, lossless, depth )) )
return( -1 );
if( wtiff_write_image( wtiff ) ) {
@ -1931,7 +1961,9 @@ vips__tiff_write_buf( VipsImage *input,
gboolean rgbjpeg,
gboolean properties, gboolean strip,
VipsRegionShrink region_shrink,
int level, gboolean lossless )
int level,
gboolean lossless,
VipsForeignDzDepth depth )
{
Wtiff *wtiff;
@ -1941,7 +1973,7 @@ vips__tiff_write_buf( VipsImage *input,
compression, Q, predictor, profile,
tile, tile_width, tile_height, pyramid, squash,
miniswhite, resunit, xres, yres, bigtiff, rgbjpeg,
properties, strip, region_shrink, level, lossless )) )
properties, strip, region_shrink, level, lossless, depth )) )
return( -1 );
wtiff->obuf = obuf;