started expanding strip read

This commit is contained in:
John Cupitt 2016-11-17 12:30:32 +00:00
parent 3ecb6d6c8b
commit 2475611b0d
2 changed files with 54 additions and 41 deletions

4
TODO
View File

@ -1,3 +1,7 @@
- test data
http://downloads.openmicroscopy.org/images/OME-TIFF/2016-06/bioformats-artificial/multi-channel-z-series.ome.tif
- all toilet roll loaders need to set "page-height" - all toilet roll loaders need to set "page-height"
magick, pdf and tiff need to use the same page/n interface magick, pdf and tiff need to use the same page/n interface

View File

@ -197,8 +197,8 @@
*/ */
/* /*
#define DEBUG
*/ */
#define DEBUG
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include <config.h> #include <config.h>
@ -271,6 +271,10 @@ typedef struct _Rtiff {
*/ */
TIFF *tiff; TIFF *tiff;
/* The current page we have set.
*/
int current_page;
/* Process for this image type. /* Process for this image type.
*/ */
scanline_process_fn sfn; scanline_process_fn sfn;
@ -280,10 +284,6 @@ typedef struct _Rtiff {
*/ */
gboolean memcpy; gboolean memcpy;
/* The current 'file pointer' for memory buffers.
*/
size_t pos;
/* Geometry as read from the TIFF header. This is read for the first /* Geometry as read from the TIFF header. This is read for the first
* page, and equal for all other pages. * page, and equal for all other pages.
*/ */
@ -436,11 +436,13 @@ get_orientation( TIFF *tiff )
} }
static int static int
set_directory( TIFF *tiff, int page ) strip_read( TIFF *tiff, int strip, tdata_t buf )
{ {
if( !TIFFSetDirectory( tiff, page ) ) { tsize_t length;
vips_error( "tiff2vips",
_( "TIFF does not contain page %d" ), page ); length = TIFFReadEncodedStrip( tiff, strip, buf, (tsize_t) -1 );
if( length == -1 ) {
vips_error( "tiff2vips", "%s", _( "read error" ) );
return( -1 ); return( -1 );
} }
@ -448,17 +450,19 @@ set_directory( TIFF *tiff, int page )
} }
static int static int
n_directories( TIFF *tiff ) rtiff_set_page( Rtiff *rtiff, int page )
{ {
int n; if( rtiff->current_page != page ) {
if( !TIFFSetDirectory( rtiff->tiff, page ) ) {
vips_error( "tiff2vips",
_( "TIFF does not contain page %d" ), page );
return( -1 );
}
/* Faster than doing set_directory() repeatedly. rtiff->current_page = page;
*/ }
set_directory( tiff, 0 );
for( n = 0; TIFFReadDirectory( tiff ); n++ )
;
return( n ); return( 0 );
} }
static int static int
@ -1174,7 +1178,10 @@ rtiff_set_header( Rtiff *rtiff, VipsImage *out )
void *data; void *data;
out->Xsize = rtiff->header.width; out->Xsize = rtiff->header.width;
out->Ysize = rtiff->header.height; out->Ysize = rtiff->header.height * rtiff->n;
if( rtiff->n > 1 )
vips_image_set_int( out, "page-height", rtiff->header.height );
/* Even though we could end up serving tiled data, always hint /* Even though we could end up serving tiled data, always hint
* THINSTRIP, since we're quite happy doing that too, and it could need * THINSTRIP, since we're quite happy doing that too, and it could need
@ -1554,20 +1561,6 @@ rtiff_read_tilewise( Rtiff *rtiff, VipsImage *out )
return( 0 ); return( 0 );
} }
static int
rtiff_strip_read( TIFF *tiff, int strip, tdata_t buf )
{
tsize_t length;
length = TIFFReadEncodedStrip( tiff, strip, buf, (tsize_t) -1 );
if( length == -1 ) {
vips_error( "tiff2vips", "%s", _( "read error" ) );
return( -1 );
}
return( 0 );
}
/* Read a strip. If the image is in separate planes, read each plane and /* Read a strip. If the image is in separate planes, read each plane and
* interleave to the output. * interleave to the output.
*/ */
@ -1593,7 +1586,7 @@ rtiff_strip_read_interleaved( Rtiff *rtiff, int y, tdata_t buf )
VipsPel *p; VipsPel *p;
VipsPel *q; VipsPel *q;
if( rtiff_strip_read( rtiff->tiff, if( strip_read( rtiff->tiff,
strips_per_plane * i + strip, strips_per_plane * i + strip,
rtiff->plane_buf ) ) rtiff->plane_buf ) )
return( -1 ); return( -1 );
@ -1610,7 +1603,7 @@ rtiff_strip_read_interleaved( Rtiff *rtiff, int y, tdata_t buf )
} }
} }
else { else {
if( rtiff_strip_read( rtiff->tiff, strip, buf ) ) if( strip_read( rtiff->tiff, strip, buf ) )
return( -1 ); return( -1 );
} }
@ -1639,12 +1632,12 @@ rtiff_stripwise_generate( VipsRegion *or,
g_assert( r->width == or->im->Xsize ); g_assert( r->width == or->im->Xsize );
g_assert( VIPS_RECT_BOTTOM( r ) <= or->im->Ysize ); g_assert( VIPS_RECT_BOTTOM( r ) <= or->im->Ysize );
/* Tiles should always be on a strip boundary. /* We can read many pages, so tiles won't always be on a strip
* boundary.
*/ */
g_assert( r->top % rtiff->header.rows_per_strip == 0 );
/* Tiles should always be a strip in height, unless it's the final /* Tiles should always be a strip in height, unless it's the final
* strip. * strip in the image.
*/ */
g_assert( r->height == g_assert( r->height ==
VIPS_MIN( rows_per_strip, or->im->Ysize - r->top ) ); VIPS_MIN( rows_per_strip, or->im->Ysize - r->top ) );
@ -1654,6 +1647,8 @@ rtiff_stripwise_generate( VipsRegion *or,
for( y = 0; y < r->height; y += rows_per_strip ) { for( y = 0; y < r->height; y += rows_per_strip ) {
tdata_t dst; tdata_t dst;
what page is this y, set that page
/* Read directly into the image if we can. Otherwise, we must /* Read directly into the image if we can. Otherwise, we must
* read to a temp buffer then unpack into the image. * read to a temp buffer then unpack into the image.
*/ */
@ -1826,10 +1821,10 @@ rtiff_new( VipsImage *out,
rtiff->autorotate = autorotate; rtiff->autorotate = autorotate;
rtiff->readbehind = readbehind; rtiff->readbehind = readbehind;
rtiff->tiff = NULL; rtiff->tiff = NULL;
rtiff->current_page = -1;
rtiff->sfn = NULL; rtiff->sfn = NULL;
rtiff->client = NULL; rtiff->client = NULL;
rtiff->memcpy = FALSE; rtiff->memcpy = FALSE;
rtiff->pos = 0;
rtiff->plane_buf = NULL; rtiff->plane_buf = NULL;
rtiff->contig_buf = NULL; rtiff->contig_buf = NULL;
@ -1842,6 +1837,12 @@ rtiff_new( VipsImage *out,
return( NULL ); return( NULL );
} }
if( rtiff->n < 1 || rtiff->n > 1000000 ) {
vips_error( "tiff2vips", _( "bad number of pages %d" ),
rtiff->n );
return( NULL );
}
return( rtiff ); return( rtiff );
} }
@ -1959,20 +1960,28 @@ rtiff_header_equal( RtiffHeader *h1, RtiffHeader *h2 )
static int static int
rtiff_header_read_all( Rtiff *rtiff ) rtiff_header_read_all( Rtiff *rtiff )
{ {
if( set_directory( rtiff->tiff, rtiff->page ) || #ifdef DEBUG
printf( "tiff2vips: reading header for page %d ...\n", rtiff->page );
#endif /*DEBUG*/
if( rtiff_set_page( rtiff, rtiff->page ) ||
rtiff_header_read( rtiff, &rtiff->header ) ) rtiff_header_read( rtiff, &rtiff->header ) )
return( -1 ); return( -1 );
/* If we're to read many pages, verify that they are all identical. /* If we're to read many pages, verify that they are all identical.
*/ */
if( rtiff->n > 1 ) { if( rtiff->n > 1 ) {
int i; int i;
for( i = 1; i < rtiff->n; i++ ) { for( i = 1; i < rtiff->n; i++ ) {
RtiffHeader header; RtiffHeader header;
if( set_directory( rtiff->tiff, rtiff->page + i ) || #ifdef DEBUG
printf( "tiff2vips: verifying header for page %d ...\n",
rtiff->page + i );
#endif /*DEBUG*/
if( rtiff_set_page( rtiff, rtiff->page + i ) ||
rtiff_header_read( rtiff, &header ) ) rtiff_header_read( rtiff, &header ) )
return( -1 ); return( -1 );