dzsave outputs extra tiles along right and bottom

the deepzoom spec wants tiles to be written along the right and bottom,
even of those tiles contain no new pixels

this patch seems to work, but needs testing

see: https://github.com/jcupitt/libvips/issues/795
This commit is contained in:
John Cupitt 2017-11-24 15:54:22 +00:00
parent f9f717a843
commit 5664a0d9b1
2 changed files with 46 additions and 15 deletions

View File

@ -39,6 +39,8 @@
- fix nasty jaggies on the edges of affine output, thanks chregu
- add gif-delay, gif-comment and gif-loop metadata
- add dispose handling to gifload
- dzsave outputs extra right and bottom overlap-only tiles, for closer spec
adherence
29/8/17 started 8.5.9
- make --fail stop jpeg read on any libjpeg warning, thanks @mceachen

View File

@ -73,6 +73,8 @@
* - better >4gb detection for zip output on older libgsfs
* 18/8/17
* - shut down the output earlier to flush zip output
* 24/11/17
* - output overlap-only tiles on edges, for better deepzoom spec
*/
/*
@ -442,10 +444,10 @@ struct _VipsForeignSaveDz {
int compression;
/* Tile and overlap geometry. The members above are the parameters we
* accept, this nest set are the derived values which are actually
* accept, this next set are the derived values which are actually
* used in pyramid generation.
*
* Tiles have a base size. Imagine a square placed at the top left.
* Tiles have a base tile_size. Imagine a square placed at the top left.
* This is the size of that square.
*
* Tiles have a margin. The square from tile_size is expanded outward
@ -569,8 +571,6 @@ pyramid_build( VipsForeignSaveDz *dz, Layer *above,
VipsForeignSave *save = VIPS_FOREIGN_SAVE( dz );
Layer *layer = VIPS_NEW( dz, Layer );
int right;
int bottom;
VipsRect strip;
int limit;
@ -578,17 +578,12 @@ pyramid_build( VipsForeignSaveDz *dz, Layer *above,
layer->width = width;
layer->height = height;
/* The 0 position of the right-most possible tile.
/* We need to output all possible tiles, even if they give no new pixels.
*/
right = VIPS_MAX( 0, width - dz->tile_margin - dz->tile_size );
/* Tiles from that to the left edge will be spaced by tile step. The +1
* is the tile we subtracted above.
*/
layer->tiles_across = ceil( (double) right / dz->tile_step ) + 1;
bottom = VIPS_MAX( 0, height - dz->tile_margin - dz->tile_size );
layer->tiles_down = ceil( (double) bottom / dz->tile_step ) + 1;
layer->tiles_across = VIPS_ROUND_UP( width, dz->tile_step ) /
dz->tile_step;
layer->tiles_down = VIPS_ROUND_UP( height, dz->tile_step ) /
dz->tile_step;
layer->real_pixels = *real_pixels;
@ -1508,6 +1503,23 @@ strip_arrived( Layer *layer )
return( 0 );
}
/* The image has been completely written. Flush any strips which might have
* overlaps in.
*/
static int
strip_flush( Layer *layer )
{
if( layer->y < layer->height )
if( strip_save( layer ) )
return( -1 );
if( layer->below )
if( strip_flush( layer->below ) )
return( -1 );
return( 0 );
}
/* Another strip of image pixels from vips_sink_disc(). Write into the top
* pyramid layer.
*/
@ -1538,7 +1550,7 @@ pyramid_strip( VipsRegion *region, VipsRect *area, void *a )
*/
vips_rect_intersectrect( &target, area, &target );
/* Are we empty? All done.
/* Have we written all the pixels we were given? We are done.
*/
if( vips_rect_isempty( &target ) )
break;
@ -1565,6 +1577,23 @@ pyramid_strip( VipsRegion *region, VipsRect *area, void *a )
}
}
/* If we've reached the bottom of the image, we won't get called again.
*
* However, there may be some unwritten pixels in the pyramid still!
* Suppose a layer is exactly a multiple of tile_step in height.
* When we finished that last strip, we will have copied the last few
* lines of overlap over into the top of the next row. Deepzoom says we
* must flush these half-written strips to the output.
*/
if( layer->write_y == layer->height ) {
#ifdef DEBUG
printf( "pyramid_strip: flushing ..\n" );
#endif/*DEBUG*/
if( strip_flush( layer ) )
return( -1 );
}
return( 0 );
}