add subifd select to tiff load

This commit is contained in:
John Cupitt 2020-05-28 12:40:31 +01:00
parent 9e4b78215e
commit dc29f8dde6
4 changed files with 70 additions and 12 deletions

View File

@ -76,7 +76,7 @@ im_tiff_read_header( const char *filename, VipsImage *out,
if( !(source = vips_source_new_from_file( filename )) )
return( -1 );
if( vips__tiff_read_header_source( source,
out, page, n, autorotate ) ) {
out, page, n, autorotate, -1 ) ) {
VIPS_UNREF( source );
return( -1 );
}
@ -93,7 +93,7 @@ im_tiff_read( const char *filename, VipsImage *out,
if( !(source = vips_source_new_from_file( filename )) )
return( -1 );
if( vips__tiff_read_source( source, out, page, n, autorotate ) ) {
if( vips__tiff_read_source( source, out, page, n, autorotate, -1 ) ) {
VIPS_UNREF( source );
return( -1 );
}

View File

@ -88,9 +88,9 @@ int vips__tiff_write_buf( VipsImage *in,
gboolean vips__istiff_source( VipsSource *source );
gboolean vips__istifftiled_source( VipsSource *source );
int vips__tiff_read_header_source( VipsSource *source, VipsImage *out,
int page, int n, gboolean autorotate );
int page, int n, gboolean autorotate, int subifd );
int vips__tiff_read_source( VipsSource *source, VipsImage *out,
int page, int n, gboolean autorotate );
int page, int n, gboolean autorotate, int subifd );
extern const char *vips__foreign_tiff_suffs[];

View File

@ -197,6 +197,8 @@
* - read logluv images as XYZ
* 11/4/20 petoor
* - better handling of aligned reads in multipage tiffs
* 28/5/20
* - add subifd
*/
/*
@ -320,6 +322,7 @@ typedef struct _Rtiff {
int page;
int n;
gboolean autorotate;
int subifd;
/* The TIFF we read.
*/
@ -527,7 +530,7 @@ rtiff_minimise_cb( VipsImage *image, Rtiff *rtiff )
static Rtiff *
rtiff_new( VipsSource *source, VipsImage *out,
int page, int n, gboolean autorotate )
int page, int n, gboolean autorotate, int subifd )
{
Rtiff *rtiff;
@ -540,6 +543,7 @@ rtiff_new( VipsSource *source, VipsImage *out,
rtiff->page = page;
rtiff->n = n;
rtiff->autorotate = autorotate;
rtiff->subifd = subifd;
rtiff->tiff = NULL;
rtiff->n_pages = 0;
rtiff->current_page = -1;
@ -608,7 +612,8 @@ rtiff_set_page( Rtiff *rtiff, int page )
{
if( rtiff->current_page != page ) {
#ifdef DEBUG
printf( "rtiff_set_page: selecting page %d\n", page );
printf( "rtiff_set_page: selecting page %d, subifd %d\n",
page, rtiff->subifd );
#endif /*DEBUG*/
if( !TIFFSetDirectory( rtiff->tiff, page ) ) {
@ -617,6 +622,35 @@ rtiff_set_page( Rtiff *rtiff, int page )
return( -1 );
}
if( rtiff->subifd >= 0 ) {
int subifd_count;
toff_t *subifd_offsets;
if( !TIFFGetField( rtiff->tiff, TIFFTAG_SUBIFD,
&subifd_count, &subifd_offsets ) ) {
vips_error( "tiff2vips",
"%s", _( "no SUBIFD tag" ) );
return( -1 );
}
if( subifd_count <= 0 ||
rtiff->subifd >= subifd_count ) {
vips_error( "tiff2vips",
_( "subifd %d out of range, "
"only %d available" ),
rtiff->subifd,
subifd_count );
return( -1 );
}
if( !TIFFSetSubDirectory( rtiff->tiff,
subifd_offsets[rtiff->subifd] ) ) {
vips_error( "tiff2vips",
"%s", _( "subdirectory unreadable" ) );
return( -1 );
}
}
rtiff->current_page = page;
}
@ -2646,13 +2680,13 @@ vips__istifftiled_source( VipsSource *source )
int
vips__tiff_read_header_source( VipsSource *source, VipsImage *out,
int page, int n, gboolean autorotate )
int page, int n, gboolean autorotate, int subifd )
{
Rtiff *rtiff;
vips__tiff_init();
if( !(rtiff = rtiff_new( source, out, page, n, autorotate )) ||
if( !(rtiff = rtiff_new( source, out, page, n, autorotate, subifd )) ||
rtiff_header_read_all( rtiff ) )
return( -1 );
@ -2671,7 +2705,7 @@ vips__tiff_read_header_source( VipsSource *source, VipsImage *out,
int
vips__tiff_read_source( VipsSource *source, VipsImage *out,
int page, int n, gboolean autorotate )
int page, int n, gboolean autorotate, int subifd )
{
Rtiff *rtiff;
@ -2681,7 +2715,7 @@ vips__tiff_read_source( VipsSource *source, VipsImage *out,
vips__tiff_init();
if( !(rtiff = rtiff_new( source, out, page, n, autorotate )) ||
if( !(rtiff = rtiff_new( source, out, page, n, autorotate, subifd )) ||
rtiff_header_read_all( rtiff ) )
return( -1 );

View File

@ -69,6 +69,10 @@ typedef struct _VipsForeignLoadTiff {
*/
int n;
/* Select subifd index. -1 for main image.
*/
int subifd;
/* Autorotate using orientation tag.
*/
gboolean autorotate;
@ -133,7 +137,7 @@ vips_foreign_load_tiff_header( VipsForeignLoad *load )
VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load;
if( vips__tiff_read_header_source( tiff->source, load->out,
tiff->page, tiff->n, tiff->autorotate ) )
tiff->page, tiff->n, tiff->autorotate, tiff->subifd ) )
return( -1 );
return( 0 );
@ -145,7 +149,7 @@ vips_foreign_load_tiff_load( VipsForeignLoad *load )
VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load;
if( vips__tiff_read_source( tiff->source, load->real,
tiff->page, tiff->n, tiff->autorotate ) )
tiff->page, tiff->n, tiff->autorotate, tiff->subifd ) )
return( -1 );
return( 0 );
@ -203,6 +207,14 @@ vips_foreign_load_tiff_class_init( VipsForeignLoadTiffClass *class )
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadTiff, autorotate ),
FALSE );
VIPS_ARG_INT( class, "subifd", 21,
_( "subifd" ),
_( "Select subifd index" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadTiff, subifd ),
-1, 100000, -1 );
}
static void
@ -210,6 +222,7 @@ vips_foreign_load_tiff_init( VipsForeignLoadTiff *tiff )
{
tiff->page = 0;
tiff->n = 1;
tiff->subifd = -1;
}
typedef struct _VipsForeignLoadTiffSource {
@ -454,6 +467,7 @@ vips_foreign_load_tiff_buffer_init( VipsForeignLoadTiffBuffer *buffer )
* * @n: %gint, load this many pages
* * @autorotate: %gboolean, use orientation tag to rotate the image
* during load
* * @subifd: %gint, select this subifd index
*
* Read a TIFF file into a VIPS image. It is a full baseline TIFF 6 reader,
* with extensions for tiled images, multipage images, XYZ and LAB colour
@ -478,6 +492,14 @@ vips_foreign_load_tiff_buffer_init( VipsForeignLoadTiffBuffer *buffer )
* operations will use #VIPS_META_ORIENTATION, if present, to set the
* orientation of output images.
*
* If @autorotate is TRUE, the image will be rotated upright during load and
* no metadata attached. This can be very slow.
*
* If @subifd is -1 (the default), the main image is selected for each page.
* If it is 0 or greater and there is a SUBIFD tag, the indexed SUBIFD is
* selected. This can be used to read lower resolution layers from
* bioformats-style image pyramids.
*
* Any ICC profile is read and attached to the VIPS image as
* #VIPS_META_ICC_NAME. Any XMP metadata is read and attached to the image
* as #VIPS_META_XMP_NAME. Any IPTC is attached as #VIPS_META_IPTC_NAME. The
@ -515,6 +537,7 @@ vips_tiffload( const char *filename, VipsImage **out, ... )
* * @n: %gint, load this many pages
* * @autorotate: %gboolean, use orientation tag to rotate the image
* during load
* * @subifd: %gint, select this subifd index
*
* Read a TIFF-formatted memory block into a VIPS image. Exactly as
* vips_tiffload(), but read from a memory source.
@ -558,6 +581,7 @@ vips_tiffload_buffer( void *buf, size_t len, VipsImage **out, ... )
* * @n: %gint, load this many pages
* * @autorotate: %gboolean, use orientation tag to rotate the image
* during load
* * @subifd: %gint, select this subifd index
*
* Exactly as vips_tiffload(), but read from a source.
*