seems to work!

This commit is contained in:
John Cupitt 2015-02-17 14:29:24 +00:00
parent 0f4efe22b9
commit 1fe29b52de

View File

@ -149,7 +149,7 @@
* 13/2/15 * 13/2/15
* - append later layers, don't copy the base image * - append later layers, don't copy the base image
* 14/2/15 * 14/2/15
* - use the nice dzsave pyramid code * - use the nice dzsave pyramid code, much faster and simpler
*/ */
/* /*
@ -242,10 +242,11 @@ struct _Layer {
*/ */
struct _Write { struct _Write {
VipsImage *im; /* Original input image */ VipsImage *im; /* Original input image */
char *name; /* Name we write to */ char *filename; /* Name we write to */
Layer *layer; /* Top of pyramid */ Layer *layer; /* Top of pyramid */
VipsPel *tbuf; /* TIFF output buffer */ VipsPel *tbuf; /* TIFF output buffer */
int tls; /* Tile line size */
int compression; /* Compression type */ int compression; /* Compression type */
int jpqual; /* JPEG q-factor */ int jpqual; /* JPEG q-factor */
@ -347,8 +348,8 @@ pyramid_new( Write *write, Layer *above, int width, int height )
* alive until after write_gather(). * alive until after write_gather().
*/ */
if( !above ) if( !above )
layer->lname = layer->lname = vips_strdup( VIPS_OBJECT( write->im ),
vips_strdup( VIPS_OBJECT( write->im ), write->name ); write->filename );
else { else {
char *lname; char *lname;
@ -567,7 +568,7 @@ write_tiff_header( Write *write, Layer *layer )
TIFFSetField( tif, TIFFTAG_TILELENGTH, write->tileh ); TIFFSetField( tif, TIFFTAG_TILELENGTH, write->tileh );
} }
else else
TIFFSetField( tif, TIFFTAG_ROWSPERSTRIP, 16 ); TIFFSetField( tif, TIFFTAG_ROWSPERSTRIP, write->tileh );
if( layer->above ) if( layer->above )
/* Pyramid layer. /* Pyramid layer.
@ -602,7 +603,7 @@ pyramid_fill( Write *write )
layer->image = vips_image_new(); layer->image = vips_image_new();
if( vips_image_pipelinev( layer->image, if( vips_image_pipelinev( layer->image,
VIPS_DEMAND_STYLE_ANY, write->in, NULL ) ) VIPS_DEMAND_STYLE_ANY, write->im, NULL ) )
return( -1 ); return( -1 );
layer->image->Xsize = layer->width; layer->image->Xsize = layer->width;
layer->image->Ysize = layer->height; layer->image->Ysize = layer->height;
@ -756,13 +757,11 @@ write_new( VipsImage *im, const char *filename,
gboolean rgbjpeg ) gboolean rgbjpeg )
{ {
Write *write; Write *write;
Layer *layer;
if( !(write = VIPS_NEW( im, Write )) ) if( !(write = VIPS_NEW( im, Write )) )
return( NULL ); return( NULL );
write->im = im; write->im = im;
write->name = vips_strdup( VIPS_OBJECT( im ), filename ); write->filename = vips_strdup( VIPS_OBJECT( im ), filename );
write->tif = NULL;
write->layer = NULL; write->layer = NULL;
write->tbuf = NULL; write->tbuf = NULL;
write->compression = get_compression( compression ); write->compression = get_compression( compression );
@ -776,7 +775,6 @@ write_new( VipsImage *im, const char *filename,
write->icc_profile = profile; write->icc_profile = profile;
write->bigtiff = bigtiff; write->bigtiff = bigtiff;
write->rgbjpeg = rgbjpeg; write->rgbjpeg = rgbjpeg;
write->cache = NULL;
write->resunit = get_resunit( resunit ); write->resunit = get_resunit( resunit );
write->xres = xres; write->xres = xres;
@ -836,17 +834,28 @@ write_new( VipsImage *im, const char *filename,
else else
write->tls = VIPS_IMAGE_SIZEOF_PEL( im ) * write->tilew; write->tls = VIPS_IMAGE_SIZEOF_PEL( im ) * write->tilew;
/* We always need at least a base layer. /* Build the pyramid framework.
*/ */
write->layer = pyramid_new( write, NULL, im->Xsize, im->Ysize ); write->layer = pyramid_new( write, NULL, im->Xsize, im->Ysize );
/* Build all the layer images. /* Fill all the layers.
*/ */
if( pyramid_fill( write ) ) { if( pyramid_fill( write ) ) {
write_free( write ); write_free( write );
return( NULL ); return( NULL );
} }
if( tile )
write->tbuf = vips_malloc( NULL,
TIFFTileSize( write->layer->tif ) );
else
write->tbuf = vips_malloc( NULL,
TIFFScanlineSize( write->layer->tif ) );
if( !write->tbuf ) {
write_free( write );
return( NULL );
}
return( write ); return( write );
} }
@ -916,10 +925,11 @@ LabS2Lab16( VipsPel *q, VipsPel *p, int n )
} }
} }
/* Pack a VIPS region into a TIFF tile buffer. /* Pack the pixels in @area from @in into a TIFF tile buffer.
*/ */
static void static void
pack2tiff( Write *write, VipsRegion *in, VipsPel *q, VipsRect *area ) pack2tiff( Write *write, Layer *layer,
VipsRegion *in, VipsRect *area, VipsPel *q )
{ {
int y; int y;
@ -933,21 +943,22 @@ pack2tiff( Write *write, VipsRegion *in, VipsPel *q, VipsRect *area )
if( write->compression == COMPRESSION_JPEG && if( write->compression == COMPRESSION_JPEG &&
(area->width < write->tilew || (area->width < write->tilew ||
area->height < write->tileh) ) area->height < write->tileh) )
memset( q, 0, TIFFTileSize( write->tif ) ); memset( q, 0, TIFFTileSize( layer->tif ) );
for( y = area->top; y < VIPS_RECT_BOTTOM( area ); y++ ) { for( y = area->top; y < VIPS_RECT_BOTTOM( area ); y++ ) {
VipsPel *p = (VipsPel *) VIPS_REGION_ADDR( in, area->left, y ); VipsPel *p = (VipsPel *) VIPS_REGION_ADDR( in, area->left, y );
if( in->im->Coding == VIPS_CODING_LABQ ) if( write->im->Coding == VIPS_CODING_LABQ )
LabQ2LabC( q, p, area->width ); LabQ2LabC( q, p, area->width );
else if( write->onebit ) else if( write->onebit )
eightbit2onebit( q, p, area->width ); eightbit2onebit( q, p, area->width );
else if( in->im->BandFmt == VIPS_FORMAT_SHORT && else if( write->im->BandFmt == VIPS_FORMAT_SHORT &&
in->im->Type == VIPS_INTERPRETATION_LABS ) write->im->Type == VIPS_INTERPRETATION_LABS )
LabS2Lab16( q, p, area->width ); LabS2Lab16( q, p, area->width );
else else
memcpy( q, p, memcpy( q, p,
area->width * VIPS_IMAGE_SIZEOF_PEL( in->im ) ); area->width *
VIPS_IMAGE_SIZEOF_PEL( write->im ) );
q += write->tls; q += write->tls;
} }
@ -956,23 +967,42 @@ pack2tiff( Write *write, VipsRegion *in, VipsPel *q, VipsRect *area )
/* Write a set of tiles across the strip. /* Write a set of tiles across the strip.
*/ */
static int static int
layer_write_tile( Layer *layer, VipsRegion *strip ) layer_write_tile( Write *write, Layer *layer, VipsRegion *strip )
{ {
VipsImage *im = layer->image;
VipsRect *area = &strip->valid;
VipsRect image;
int x; int x;
image.left = 0;
image.top = 0;
image.width = im->Xsize;
image.height = im->Ysize;
for( x = 0; x < im->Xsize; x += write->tilew ) { for( x = 0; x < im->Xsize; x += write->tilew ) {
VipsRect tile;
tile.left = x;
tile.top = area->top;
tile.width = write->tilew;
tile.height = write->tileh;
vips_rect_intersectrect( &tile, &image, &tile );
/* Have to repack pixels. /* Have to repack pixels.
*/ */
pack2tiff( write, reg, tbuf, area ); pack2tiff( write, layer, strip, &tile, write->tbuf );
#ifdef DEBUG_VERBOSE #ifdef DEBUG_VERBOSE
printf( "Writing %dx%d pixels at position %dx%d to image %s\n", printf( "Writing %dx%d tile at position %dx%d to image %s\n",
write->tilew, write->tileh, area->left, area->top, tile.width, tile.height, tile.left, tile.top,
TIFFFileName( tif ) ); TIFFFileName( layer->tif ) );
#endif /*DEBUG_VERBOSE*/ #endif /*DEBUG_VERBOSE*/
if( TIFFWriteTile( tif, tbuf, area->left, area->top, 0, 0 ) < 0 ) { if( TIFFWriteTile( layer->tif, write->tbuf,
vips_error( "vips2tiff", "%s", _( "TIFF write tile failed" ) ); tile.left, tile.top, 0, 0 ) < 0 ) {
vips_error( "vips2tiff",
"%s", _( "TIFF write tile failed" ) );
return( -1 ); return( -1 );
} }
} }
@ -983,14 +1013,19 @@ layer_write_tile( Layer *layer, VipsRegion *strip )
/* Write tileh scanlines, less for the last strip. /* Write tileh scanlines, less for the last strip.
*/ */
static int static int
layer_write_strip( Layer *layer, VipsRegion *strip ) layer_write_strip( Write *write, Layer *layer, VipsRegion *strip )
{ {
VipsImage *im = write->im; VipsImage *im = layer->image;
VipsRect *area = &strip->valid; VipsRect *area = &strip->valid;
int height = VIPS_MIN( write->tileh, area->height ); int height = VIPS_MIN( write->tileh, area->height );
int y; int y;
#ifdef DEBUG_VERBOSE
printf( "Writing %d pixel strip at height %d to image %s\n",
height, area->top, TIFFFileName( layer->tif ) );
#endif /*DEBUG_VERBOSE*/
for( y = 0; y < height; y++ ) { for( y = 0; y < height; y++ ) {
VipsPel *p = VIPS_REGION_ADDR( strip, 0, area->top + y ); VipsPel *p = VIPS_REGION_ADDR( strip, 0, area->top + y );
@ -1010,7 +1045,7 @@ layer_write_strip( Layer *layer, VipsRegion *strip )
p = write->tbuf; p = write->tbuf;
} }
if( TIFFWriteScanline( write->tif, p, area->top + y, 0 ) < 0 ) if( TIFFWriteScanline( layer->tif, p, area->top + y, 0 ) < 0 )
return( -1 ); return( -1 );
} }
@ -1025,7 +1060,6 @@ static int layer_strip_arrived( Layer *layer );
static int static int
layer_strip_shrink( Layer *layer ) layer_strip_shrink( Layer *layer )
{ {
Write *write = layer->write;
Layer *below = layer->below; Layer *below = layer->below;
VipsRegion *from = layer->strip; VipsRegion *from = layer->strip;
VipsRegion *to = below->strip; VipsRegion *to = below->strip;
@ -1100,13 +1134,16 @@ layer_strip_arrived( Layer *layer )
{ {
Write *write = layer->write; Write *write = layer->write;
int result;
VipsRect new_strip; VipsRect new_strip;
VipsRect overlap; VipsRect overlap;
if( write->tile ) if( write->tile )
res = layer_write_tile( layer, layer->strip ); result = layer_write_tile( write, layer, layer->strip );
else else
res = layer_write_strip( layer, layer->strip ); result = layer_write_strip( write, layer, layer->strip );
if( result )
return( -1 );
if( layer->below && if( layer->below &&
layer_strip_shrink( layer ) ) layer_strip_shrink( layer ) )