fix another dzsave corner case

better padding calculation fixes yet another corner case for dzsave,
thanks Martin
This commit is contained in:
John Cupitt 2013-02-26 12:32:01 +00:00
parent 008af5ca16
commit 61875a4bca
2 changed files with 65 additions and 49 deletions

17
TODO
View File

@ -1,3 +1,20 @@
- on tilecache region error, black out the dead tile and issue a warning,
don't pass the error up the chain
issue a warning too
- fix
$ header test.v
test.v: 14016x16448 uchar, 3 bands, srgb, openin VipsImage (0x907060)
the ", openin VipsImage (0x907060)" is annoying and useless
some hint about the image format might be useful perhaps?
- look at
There is an order 1 algorithm for doing medians over boxes (truly O(1)

View File

@ -30,6 +30,8 @@
* - add @depth option
* 21/1/13
* - add @centre option
* 26/2/13
* - fix another corner case, thanks Martin
*/
/*
@ -60,21 +62,37 @@
/*
we +1 valid.height to make sure that we always have ebnough lines for a x2
shrink, even if tile_size is odd, or (tile_size + overlap) is odd, or
(tile_size + 2 * overlap) is odd
This is difficult to test, there are so many options.
so valid->height cannot be used to tell whether we have enough rows to be
able to write a line of tiles, since we could be under but still OK:wq
It's failed in the past in these cases. These have layers with strips which
exactly align with image edges, or which have orphan scanlines which need
adding for the shrink.
1. $ header test.v
test.v: 14016x16448 uchar, 3 bands, srgb, openin VipsImage (0x11e7060)
$ time vips dzsave test.v x --overlap 0
*/
Not all layers written.
2. $ header ~/Desktop/leicaimage.scn
/home/john/Desktop/leicaimage.scn: 4225x7905 uchar, 4 bands, rgb
Not all layers written.
3. $ header ~/leicatest1.scn
/home/john/leicatest1.scn: 11585x8449 uchar, 4 bands, rgb
Not all layers written.
various combinations of odd and even tile-size and overlap need testing too.
*/
/*
#define DEBUG_VERBOSE
*/
#define DEBUG
#define VIPS_DEBUG
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
@ -242,15 +260,17 @@ pyramid_build( VipsForeignSaveDz *dz, Layer *above, int width, int height )
/* Build a line of tiles here. Normally strips are height + 2 *
* overlap, but the first row is missing the top edge.
*
* We add one so that we will have the extra scan line for the shrink
* in case tile_size is odd and there's no overlap.
* Expand the strip if necessary to make sure we have an even
* number of lines.
*/
layer->y = 0;
layer->write_y = 0;
strip.left = 0;
strip.top = 0;
strip.width = layer->image->Xsize;
strip.height = dz->tile_size + dz->overlap + 1;
strip.height = dz->tile_size + dz->overlap;
if( (strip.height & 1) == 1 )
strip.height += 1;
if( vips_region_buffer( layer->strip, &strip ) ) {
layer_free( layer );
return( NULL );
@ -862,8 +882,6 @@ layer_generate_extras( Layer *layer )
{
VipsRegion *strip = layer->strip;
printf( "layer_generate_extras: layer->n == %d\n", layer->n );
/* We only work for full-width strips.
*/
g_assert( strip->valid.width == layer->image->Xsize );
@ -873,8 +891,6 @@ layer_generate_extras( Layer *layer )
int b, y;
printf( "layer_generate_extras: adding column on right\n" );
/* Need to add a right-most column.
*/
for( y = 0; y < strip->valid.height; y++ ) {
@ -890,11 +906,6 @@ layer_generate_extras( Layer *layer )
if( layer->height < layer->image->Ysize ) {
VipsRect last;
printf( "layer->height = %d\n", layer->height );
printf( "layer->image->Ysize = %d\n", layer->image->Ysize );
printf( "strip->valid.top = %d\n", strip->valid.top );
printf( "strip->valid.height = %d\n", strip->valid.height );
/* The last two lines of the image.
*/
last.left = 0;
@ -908,8 +919,6 @@ layer_generate_extras( Layer *layer )
if( last.height == 2 ) {
last.height = 1;
printf( "layer_generate_extras: adding row on bot\n" );
vips_region_copy( strip, strip, &last,
0, last.top + 1 );
}
@ -918,8 +927,8 @@ layer_generate_extras( Layer *layer )
static int strip_arrived( Layer *layer );
/* Shrink what pixels we can from this layer into the layer below. If the
* layer below fills, recurse.
/* Shrink what pixels we can from this strip into the layer below. If the
* strip below fills, recurse.
*/
static int
strip_shrink( Layer *layer )
@ -950,14 +959,6 @@ strip_shrink( Layer *layer )
target.height = to->valid.height;
vips_rect_intersectrect( &target, &to->valid, &target );
printf( "strip_shrink: n == %d\n", layer->n );
printf( "from.top == %d\n", from->valid.top );
printf( "from.height == %d\n", from->valid.height );
printf( "target.top == %d\n", target.top );
printf( "target.height == %d\n", target.height );
/* Those pixels need this area of this layer.
*/
source.left = target.left * 2;
@ -969,9 +970,6 @@ strip_shrink( Layer *layer )
*/
vips_rect_intersectrect( &source, &from->valid, &source );
printf( "source.top == %d\n", source.top );
printf( "source.height == %d\n", source.height );
/* So these are the pixels in the layer below we can provide.
*/
target.left = source.left / 2;
@ -979,12 +977,9 @@ strip_shrink( Layer *layer )
target.width = source.width / 2;
target.height = source.height / 2;
printf( "target.top == %d\n", target.top );
printf( "target.height == %d\n", target.height );
/* None? All done.
*/
if( source.height < 2 )
if( vips_rect_isempty( &target ) )
break;
if( save->ready->Coding == VIPS_CODING_NONE )
@ -994,10 +989,10 @@ strip_shrink( Layer *layer )
below->write_y += target.height;
/* If we've filled the strip of the layer below, let it know.
/* If we've filled the strip below, let it know.
* We can either fill the region, if it's somewhere half-way
* down the image, or, if it's at the bottom, get to the last
* writeable line.
* real line of pixels.
*/
if( below->write_y == VIPS_RECT_BOTTOM( &to->valid ) ||
below->write_y == below->height ) {
@ -1009,12 +1004,13 @@ strip_shrink( Layer *layer )
return( 0 );
}
/* A new strip of pixels has arrived! The strip region has enough pixels in to
* write a line of tiles.
/* A new strip has arrived! The strip has enough pixels in to write a line of
* tiles.
*
* - write a line of tiles
* - shrink what we can to the layer below
* - move our strip down ready for more stuff, copying the overlap
* - move our strip down by the tile height
* - copy the overlap with the previous strip
*/
static int
strip_arrived( Layer *layer )
@ -1030,15 +1026,18 @@ strip_arrived( Layer *layer )
strip_shrink( layer ) )
return( -1 );
/* Position our strip down the image. We add one to the strip height
* to make sure we will have enough pixels for any shrinking even if
* tile_size is odd and there's no overlap.
/* Position our strip down the image.
*
* Expand the strip if necessary to make sure we have an even
* number of lines.
*/
layer->y += dz->tile_size;
new_strip.left = 0;
new_strip.top = layer->y - dz->overlap;
new_strip.width = layer->image->Xsize;
new_strip.height = dz->tile_size + 2 * dz->overlap + 1;
new_strip.height = dz->tile_size + 2 * dz->overlap;
if( (new_strip.height & 1) == 1 )
new_strip.height += 1;
/* We may exactly hit the bottom of the real image (ie. before borders
* have been possibly expanded by 1 pixel). In this case, we'll not
@ -1120,9 +1119,9 @@ pyramid_strip( VipsRegion *region, VipsRect *area, void *a )
layer->write_y += target.height;
/* We can either fill the region, if it's somewhere half-way
/* We can either fill the strip, if it's somewhere half-way
* down the image, or, if it's at the bottom, get to the last
* writeable line.
* real line of pixels.
*/
if( layer->write_y == VIPS_RECT_BOTTOM( to ) ||
layer->write_y == layer->height ) {