seems to make an OME pyramid correctly

```
$ vips tiffsave ../k2.jpg x.tif --tile --pyramid --subifd && tiffinfo x.tif
TIFF Directory at offset 0x900008 (9437192)
  Image Width: 1450 Image Length: 2048
  Tile Width: 128 Tile Length: 128
  Resolution: 72.009, 72.009 pixels/inch
  Bits/Sample: 8
  Sample Format: unsigned integer
  Compression Scheme: None
  Photometric Interpretation: RGB color
  Orientation: row 0 top, col 0 lhs
  Samples/Pixel: 3
  Planar Configuration: single image plane
  SubIFD Offsets: 11797898 12388230 12585130 12634526     0
```
This commit is contained in:
John Cupitt 2020-05-15 17:16:04 +01:00
parent 7deead8911
commit 84b9d1f638

View File

@ -1033,7 +1033,8 @@ wtiff_new( VipsImage *input, const char *filename,
VipsRegionShrink region_shrink, VipsRegionShrink region_shrink,
int level, int level,
gboolean lossless, gboolean lossless,
VipsForeignDzDepth depth ) VipsForeignDzDepth depth,
gboolean subifd )
{ {
Wtiff *wtiff; Wtiff *wtiff;
@ -1065,6 +1066,7 @@ wtiff_new( VipsImage *input, const char *filename,
wtiff->level = level; wtiff->level = level;
wtiff->lossless = lossless; wtiff->lossless = lossless;
wtiff->depth = depth; wtiff->depth = depth;
wtiff->subifd = subifd;
wtiff->toilet_roll = FALSE; wtiff->toilet_roll = FALSE;
wtiff->page_height = vips_image_get_page_height( input ); wtiff->page_height = vips_image_get_page_height( input );
wtiff->page_number = 0; wtiff->page_number = 0;
@ -1878,9 +1880,8 @@ wtiff_gather( Wtiff *wtiff )
#endif /*DEBUG*/ #endif /*DEBUG*/
if( layer->lname ) { if( layer->lname ) {
if( !(source = if( !(source = vips_source_new_from_file(
vips_source_new_from_file( layer->lname )) )
layer->lname )) )
return( -1 ); return( -1 );
} }
else { else {
@ -1893,12 +1894,14 @@ wtiff_gather( Wtiff *wtiff )
VIPS_UNREF( source ); VIPS_UNREF( source );
return( -1 ); return( -1 );
} }
VIPS_UNREF( source ); VIPS_UNREF( source );
if( wtiff_copy_tiff( wtiff, wtiff->layer->tif, in ) ) { if( wtiff_copy_tiff( wtiff, wtiff->layer->tif, in ) ) {
TIFFClose( in ); TIFFClose( in );
return( -1 ); return( -1 );
} }
TIFFClose( in ); TIFFClose( in );
if( !TIFFWriteDirectory( wtiff->layer->tif ) ) if( !TIFFWriteDirectory( wtiff->layer->tif ) )
@ -1947,6 +1950,46 @@ wtiff_write_image( Wtiff *wtiff )
return( -1 ); return( -1 );
} }
} }
else if( wtiff->pyramid &&
wtiff->subifd ) {
int n_layers;
toff_t *subifd_offsets;
Layer *p;
#ifdef DEBUG
printf( "wtiff_write_image: OME pyr mode\n" );
#endif /*DEBUG*/
/* This magic tag makes the n_layers directories we write
* after this one into subdirectories. We set the offsets to 0
* and libtiff will fill them in automatically.
*/
for( n_layers = 0, p = wtiff->layer; p; p = p->below )
n_layers += 1;
subifd_offsets = VIPS_ARRAY( NULL, n_layers, toff_t );
memset( subifd_offsets, 0, n_layers * sizeof( toff_t ) );
TIFFSetField( wtiff->layer->tif, TIFFTAG_SUBIFD,
n_layers, subifd_offsets );
if( vips_sink_disc( wtiff->ready, write_strip, wtiff ) )
return( -1 );
if( !TIFFWriteDirectory( wtiff->layer->tif ) )
return( -1 );
/* Free lower pyramid resources ... this will
* TIFFClose() (but not delete) the smaller layers
* ready for us to read from them again.
*/
if( wtiff->layer->below )
layer_free_all( wtiff->layer->below );
/* Append smaller layers to the main file.
*/
if( wtiff_gather( wtiff ) )
return( -1 );
}
else if( wtiff->pyramid ) { else if( wtiff->pyramid ) {
#ifdef DEBUG #ifdef DEBUG
printf( "wtiff_write_image: pyramid mode\n" ); printf( "wtiff_write_image: pyramid mode\n" );
@ -1958,19 +2001,18 @@ wtiff_write_image( Wtiff *wtiff )
if( !TIFFWriteDirectory( wtiff->layer->tif ) ) if( !TIFFWriteDirectory( wtiff->layer->tif ) )
return( -1 ); return( -1 );
if( wtiff->pyramid ) { /* Free lower pyramid resources ... this will
/* Free lower pyramid resources ... this will * TIFFClose() (but not delete) the smaller layers
* TIFFClose() (but not delete) the smaller layers * ready for us to read from them again.
* ready for us to read from them again. */
*/ if( wtiff->layer->below )
if( wtiff->layer->below ) layer_free_all( wtiff->layer->below );
layer_free_all( wtiff->layer->below );
/* Append smaller layers to the main file.
*/
if( wtiff_gather( wtiff ) )
return( -1 );
/* Append smaller layers to the main file.
*/
if( wtiff_gather( wtiff ) )
return( -1 );
}
} }
else { else {
#ifdef DEBUG #ifdef DEBUG
@ -2015,7 +2057,8 @@ vips__tiff_write( VipsImage *input, const char *filename,
compression, Q, predictor, profile, compression, Q, predictor, profile,
tile, tile_width, tile_height, pyramid, squash, tile, tile_width, tile_height, pyramid, squash,
miniswhite, resunit, xres, yres, bigtiff, rgbjpeg, miniswhite, resunit, xres, yres, bigtiff, rgbjpeg,
properties, strip, region_shrink, level, lossless, depth )) ) properties, strip, region_shrink, level, lossless, depth,
subifd )) )
return( -1 ); return( -1 );
if( wtiff_write_image( wtiff ) ) { if( wtiff_write_image( wtiff ) ) {
@ -2056,7 +2099,8 @@ vips__tiff_write_buf( VipsImage *input,
compression, Q, predictor, profile, compression, Q, predictor, profile,
tile, tile_width, tile_height, pyramid, squash, tile, tile_width, tile_height, pyramid, squash,
miniswhite, resunit, xres, yres, bigtiff, rgbjpeg, miniswhite, resunit, xres, yres, bigtiff, rgbjpeg,
properties, strip, region_shrink, level, lossless, depth )) ) properties, strip, region_shrink, level, lossless, depth,
subifd )) )
return( -1 ); return( -1 );
wtiff->obuf = obuf; wtiff->obuf = obuf;