almost done fixing dzsave

see

https://github.com/jcupitt/libvips/issues/326

see TODO, problem with bottom edge tiles
This commit is contained in:
John Cupitt 2015-09-09 14:53:10 +01:00
parent 75a0b5b789
commit 3d0108c3bd
2 changed files with 62 additions and 25 deletions

9
TODO
View File

@ -1,3 +1,12 @@
- try:
$ vips dzsave k2.jpg x --layout google --overlap 200
...
extract_area: bad extract area
bottom tiles are not being clipped?
- colour needs to split _build() into preprocess / process / postprocess - colour needs to split _build() into preprocess / process / postprocess
phases phases

View File

@ -112,9 +112,9 @@
/* /*
#define DEBUG_VERBOSE #define DEBUG_VERBOSE
*/
#define DEBUG #define DEBUG
#define VIPS_DEBUG #define VIPS_DEBUG
*/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include <config.h> #include <config.h>
@ -375,8 +375,7 @@ struct _Layer {
*/ */
VipsImage *image; VipsImage *image;
/* The top of this strip of tiles, excluding the overlap. Go up from /* The top of this strip of tiles.
* this to get to the top pixel we write in each one.
*/ */
int y; int y;
@ -414,6 +413,11 @@ struct _VipsForeignSaveDz {
Layer *layer; /* x2 shrink pyr layer */ Layer *layer; /* x2 shrink pyr layer */
/* We step by tile_size - overlap as we move across the image ...
* make a note of it.
*/
int tile_step;
/* Count zoomify tiles we write. /* Count zoomify tiles we write.
*/ */
int tile_count; int tile_count;
@ -481,7 +485,8 @@ vips_foreign_save_dz_dispose( GObject *gobject )
VIPS_FREE( dz->root_name ); VIPS_FREE( dz->root_name );
VIPS_FREE( dz->file_suffix ); VIPS_FREE( dz->file_suffix );
G_OBJECT_CLASS( vips_foreign_save_dz_parent_class )->dispose( gobject ); G_OBJECT_CLASS( vips_foreign_save_dz_parent_class )->
dispose( gobject );
} }
/* Build a pyramid. /* Build a pyramid.
@ -503,8 +508,8 @@ pyramid_build( VipsForeignSaveDz *dz, Layer *above,
layer->width = width; layer->width = width;
layer->height = height; layer->height = height;
layer->tiles_across = ROUND_UP( width, dz->tile_size ) / dz->tile_size; layer->tiles_across = ROUND_UP( width, dz->tile_step ) / dz->tile_step;
layer->tiles_down = ROUND_UP( height, dz->tile_size ) / dz->tile_size; layer->tiles_down = ROUND_UP( height, dz->tile_step ) / dz->tile_step;
layer->real_pixels = *real_pixels; layer->real_pixels = *real_pixels;
@ -543,8 +548,7 @@ pyramid_build( VipsForeignSaveDz *dz, Layer *above,
vips__region_no_ownership( layer->strip ); vips__region_no_ownership( layer->strip );
vips__region_no_ownership( layer->copy ); vips__region_no_ownership( layer->copy );
/* Build a line of tiles here. Normally strips are height + 2 * /* Build a line of tiles here.
* overlap, but the first row is missing the top edge.
* *
* Expand the strip if necessary to make sure we have an even * Expand the strip if necessary to make sure we have an even
* number of lines. * number of lines.
@ -554,7 +558,7 @@ pyramid_build( VipsForeignSaveDz *dz, Layer *above,
strip.left = 0; strip.left = 0;
strip.top = 0; strip.top = 0;
strip.width = layer->image->Xsize; strip.width = layer->image->Xsize;
strip.height = dz->tile_size + dz->overlap; strip.height = dz->tile_size;
if( (strip.height & 1) == 1 ) if( (strip.height & 1) == 1 )
strip.height += 1; strip.height += 1;
if( vips_region_buffer( layer->strip, &strip ) ) { if( vips_region_buffer( layer->strip, &strip ) ) {
@ -638,7 +642,8 @@ write_dzi( VipsForeignSaveDz *dz )
if( (p = (char *) vips__find_rightmost_brackets( buf )) ) if( (p = (char *) vips__find_rightmost_brackets( buf )) )
*p = '\0'; *p = '\0';
gsf_output_printf( out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ); gsf_output_printf( out, "<?xml "
"version=\"1.0\" encoding=\"UTF-8\"?>\n" );
gsf_output_printf( out, "<Image " gsf_output_printf( out, "<Image "
"xmlns=\"http://schemas.microsoft.com/deepzoom/2008\"\n" ); "xmlns=\"http://schemas.microsoft.com/deepzoom/2008\"\n" );
gsf_output_printf( out, " Format=\"%s\"\n", buf ); gsf_output_printf( out, " Format=\"%s\"\n", buf );
@ -923,9 +928,9 @@ strip_init( Strip *strip, Layer *layer )
image.height = layer->height; image.height = layer->height;
line.left = 0; line.left = 0;
line.top = layer->y - dz->overlap; line.top = layer->y;
line.width = image.width; line.width = image.width;
line.height = dz->tile_size + 2 * dz->overlap; line.height = dz->tile_size;
vips_rect_intersectrect( &image, &line, &line ); vips_rect_intersectrect( &image, &line, &line );
@ -963,16 +968,16 @@ strip_allocate( VipsThreadState *state, void *a, gboolean *stop )
/* Position this tile. /* Position this tile.
*/ */
state->pos.left = strip->x - dz->overlap; state->pos.left = strip->x;
state->pos.top = 0; state->pos.top = 0;
state->pos.width = dz->tile_size + 2 * dz->overlap; state->pos.width = dz->tile_size;
state->pos.height = state->im->Ysize; state->pos.height = dz->tile_size;
vips_rect_intersectrect( &image, &state->pos, &state->pos ); vips_rect_intersectrect( &image, &state->pos, &state->pos );
state->x = strip->x; state->x = strip->x;
state->y = layer->y; state->y = layer->y;
strip->x += dz->tile_size; strip->x += dz->tile_step;
if( vips_rect_isempty( &state->pos ) ) { if( vips_rect_isempty( &state->pos ) ) {
*stop = TRUE; *stop = TRUE;
@ -1055,6 +1060,10 @@ tile_name( Layer *layer, int x, int y )
return( NULL ); return( NULL );
} }
#ifdef DEBUG_VERBOSE
printf( "tile_name: writing to %s\n", name );
#endif /*DEBUG_VERBOSE*/
return( out ); return( out );
} }
@ -1124,10 +1133,6 @@ strip_work( VipsThreadState *state, void *a )
x = t; x = t;
} }
#ifdef DEBUG_VERBOSE
printf( "strip_work: writing to %s\n", buf );
#endif /*DEBUG_VERBOSE*/
vips_image_set_int( x, "hide-progress", 1 ); vips_image_set_int( x, "hide-progress", 1 );
if( vips_image_write_to_buffer( x, dz->suffix, &buf, &len, NULL ) ) { if( vips_image_write_to_buffer( x, dz->suffix, &buf, &len, NULL ) ) {
g_object_unref( x ); g_object_unref( x );
@ -1140,7 +1145,7 @@ strip_work( VipsThreadState *state, void *a )
g_mutex_lock( vips__global_lock ); g_mutex_lock( vips__global_lock );
out = tile_name( layer, out = tile_name( layer,
state->x / dz->tile_size, state->y / dz->tile_size ); state->x / dz->tile_step, state->y / dz->tile_step );
status = gsf_output_write( out, len, buf ); status = gsf_output_write( out, len, buf );
dz->bytes_written += len; dz->bytes_written += len;
@ -1197,10 +1202,15 @@ strip_save( Layer *layer )
vips_thread_state_new, strip_allocate, strip_work, NULL, vips_thread_state_new, strip_allocate, strip_work, NULL,
&strip ) ) { &strip ) ) {
strip_free( &strip ); strip_free( &strip );
printf( "strip_save: error: %s\n", vips_error_buffer() );
return( -1 ); return( -1 );
} }
strip_free( &strip ); strip_free( &strip );
#ifdef DEBUG
printf( "strip_save: success\n" );
#endif /*DEBUG*/
return( 0 ); return( 0 );
} }
@ -1272,6 +1282,11 @@ strip_shrink( Layer *layer )
VipsRect target; VipsRect target;
VipsRect source; VipsRect source;
#ifdef DEBUG
printf( "strip_shrink: %d lines in layer %d to layer %d\n",
from->valid.height, layer->n, below->n );
#endif/*DEBUG*/
/* We may have an extra column of pixels on the right or /* We may have an extra column of pixels on the right or
* bottom that need filling: generate them. * bottom that need filling: generate them.
*/ */
@ -1307,6 +1322,11 @@ strip_shrink( Layer *layer )
target.width = source.width / 2; target.width = source.width / 2;
target.height = source.height / 2; target.height = source.height / 2;
if( below->n == 0 ) {
printf( "strip_shrink: generating %d lines in layer 0\n",
target.height );
}
/* None? All done. /* None? All done.
*/ */
if( vips_rect_isempty( &target ) ) if( vips_rect_isempty( &target ) )
@ -1336,7 +1356,7 @@ strip_shrink( Layer *layer )
* *
* - write a line of tiles * - write a line of tiles
* - shrink what we can to the layer below * - shrink what we can to the layer below
* - move our strip down by the tile height * - move our strip down by the tile step
* - copy the overlap with the previous strip * - copy the overlap with the previous strip
*/ */
static int static int
@ -1348,6 +1368,11 @@ strip_arrived( Layer *layer )
VipsRect overlap; VipsRect overlap;
VipsRect image_area; VipsRect image_area;
#ifdef DEBUG
printf( "strip_arrived: layer %d, strip at %d, height %d\n",
layer->n, layer->y, layer->strip->valid.height );
#endif/*DEBUG*/
if( strip_save( layer ) ) if( strip_save( layer ) )
return( -1 ); return( -1 );
@ -1360,11 +1385,11 @@ strip_arrived( Layer *layer )
* Expand the strip if necessary to make sure we have an even * Expand the strip if necessary to make sure we have an even
* number of lines. * number of lines.
*/ */
layer->y += dz->tile_size; layer->y += dz->tile_step;
new_strip.left = 0; new_strip.left = 0;
new_strip.top = layer->y - dz->overlap; new_strip.top = layer->y;
new_strip.width = layer->image->Xsize; new_strip.width = layer->image->Xsize;
new_strip.height = dz->tile_size + 2 * dz->overlap; new_strip.height = dz->tile_size;
image_area.left = 0; image_area.left = 0;
image_area.top = 0; image_area.top = 0;
@ -1534,6 +1559,9 @@ vips_foreign_save_dz_build( VipsObject *object )
save->ready = z; save->ready = z;
} }
/* How much we step by as we write tiles.
*/
dz->tile_step = dz->tile_size - dz->overlap;
/* The real pixels we have from our input. This is about to get /* The real pixels we have from our input. This is about to get
* expanded with background. * expanded with background.