From 3ef6a4695ae59c7393f12643ecdd5120a4f72120 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 15 Nov 2016 10:07:09 +0000 Subject: [PATCH] start adding read many page support but it's not easy ... we'll need to be very strict about every page being identical if we want to share readers --- TODO | 4 +++ libvips/deprecated/im_tiff2vips.c | 4 +-- libvips/foreign/pforeign.h | 8 ++--- libvips/foreign/tiff2vips.c | 51 ++++++++++++++++--------------- libvips/foreign/tiffload.c | 34 ++++++++++++++++----- 5 files changed, 63 insertions(+), 38 deletions(-) diff --git a/TODO b/TODO index 715f4c8f..aada39c7 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,7 @@ +- all toilet roll loaders need to set "page-height" + + magick, pdf and tiff need to use the same page/n interface + - not sure about utf8 error messages on win - strange: diff --git a/libvips/deprecated/im_tiff2vips.c b/libvips/deprecated/im_tiff2vips.c index 6fa25122..74479115 100644 --- a/libvips/deprecated/im_tiff2vips.c +++ b/libvips/deprecated/im_tiff2vips.c @@ -94,11 +94,11 @@ tiff2vips( const char *name, IMAGE *out, gboolean header_only ) } if( header_only ) { - if( vips__tiff_read_header( filename, out, page, FALSE ) ) + if( vips__tiff_read_header( filename, out, page, 1, FALSE ) ) return( -1 ); } else { - if( vips__tiff_read( filename, out, page, FALSE, TRUE ) ) + if( vips__tiff_read( filename, out, page, 1, FALSE, TRUE ) ) return( -1 ); } #else diff --git a/libvips/foreign/pforeign.h b/libvips/foreign/pforeign.h index f0a8557a..0313ac8b 100644 --- a/libvips/foreign/pforeign.h +++ b/libvips/foreign/pforeign.h @@ -66,17 +66,17 @@ int vips__tiff_write_buf( VipsImage *in, gboolean properties, gboolean strip ); int vips__tiff_read_header( const char *filename, VipsImage *out, - int page, gboolean autorotate ); + int page, int n, gboolean autorotate ); int vips__tiff_read( const char *filename, VipsImage *out, - int page, gboolean autorotate, gboolean readbehind ); + int page, int n, gboolean autorotate, gboolean readbehind ); gboolean vips__istifftiled( const char *filename ); gboolean vips__istiff_buffer( const void *buf, size_t len ); gboolean vips__istiff( const char *filename ); int vips__tiff_read_header_buffer( const void *buf, size_t len, VipsImage *out, - int page, gboolean autorotate ); + int page, int n, gboolean autorotate ); int vips__tiff_read_buffer( const void *buf, size_t len, VipsImage *out, - int page, gboolean autorotate, gboolean readbehind ); + int page, int n, gboolean autorotate, gboolean readbehind ); extern const char *vips__foreign_tiff_suffs[]; diff --git a/libvips/foreign/tiff2vips.c b/libvips/foreign/tiff2vips.c index 550aab46..0d54cd79 100644 --- a/libvips/foreign/tiff2vips.c +++ b/libvips/foreign/tiff2vips.c @@ -1787,9 +1787,21 @@ readtiff_close( VipsObject *object, ReadTiff *rtiff ) readtiff_free( rtiff ); } +static int +readtiff_set_directory( ReadTiff *rtiff, int page ) +{ + if( !TIFFSetDirectory( rtiff->tiff, page ) ) { + vips_error( "tiff2vips", + _( "TIFF does not contain page %d" ), rtiff->page ); + return( -1 ); + } + + return( 0 ); +} + static ReadTiff * readtiff_new( VipsImage *out, - int page, gboolean autorotate, gboolean readbehind ) + int page, int n, gboolean autorotate, gboolean readbehind ) { ReadTiff *rtiff; @@ -1824,25 +1836,13 @@ readtiff_new( VipsImage *out, return( rtiff ); } -static int -readtiff_set_directory( ReadTiff *rtiff, int page ) -{ - if( !TIFFSetDirectory( rtiff->tiff, page ) ) { - vips_error( "tiff2vips", - _( "TIFF does not contain page %d" ), rtiff->page ); - return( -1 ); - } - - return( 0 ); -} - static ReadTiff * readtiff_new_filename( const char *filename, VipsImage *out, - int page, gboolean autorotate, gboolean readbehind ) + int page, int n, gboolean autorotate, gboolean readbehind ) { ReadTiff *rtiff; - if( !(rtiff = readtiff_new( out, page, autorotate, readbehind )) || + if( !(rtiff = readtiff_new( out, page, n, autorotate, readbehind )) || !(rtiff->tiff = vips__tiff_openin( filename )) || readtiff_set_directory( rtiff, page ) ) return( NULL ); @@ -1854,11 +1854,11 @@ readtiff_new_filename( const char *filename, VipsImage *out, static ReadTiff * readtiff_new_buffer( const void *buf, size_t len, VipsImage *out, - int page, gboolean autorotate, gboolean readbehind ) + int page, int n, gboolean autorotate, gboolean readbehind ) { ReadTiff *rtiff; - if( !(rtiff = readtiff_new( out, page, autorotate, readbehind )) || + if( !(rtiff = readtiff_new( out, page, n, autorotate, readbehind )) || !(rtiff->tiff = vips__tiff_openin_buffer( out, buf, len )) || readtiff_set_directory( rtiff, page ) ) return( NULL ); @@ -1889,7 +1889,7 @@ istiffpyramid( const char *name ) int vips__tiff_read( const char *filename, VipsImage *out, - int page, gboolean autorotate, gboolean readbehind ) + int page, int n, gboolean autorotate, gboolean readbehind ) { ReadTiff *rtiff; @@ -1901,7 +1901,7 @@ vips__tiff_read( const char *filename, VipsImage *out, vips__tiff_init(); if( !(rtiff = readtiff_new_filename( filename, - out, page, autorotate, readbehind )) ) + out, page, n, autorotate, readbehind )) ) return( -1 ); if( TIFFIsTiled( rtiff->tiff ) ) { @@ -1941,14 +1941,14 @@ vips__tiff_read_header_orientation( ReadTiff *rtiff, VipsImage *out ) int vips__tiff_read_header( const char *filename, VipsImage *out, - int page, gboolean autorotate ) + int page, int n, gboolean autorotate ) { ReadTiff *rtiff; vips__tiff_init(); if( !(rtiff = readtiff_new_filename( filename, out, - page, autorotate, FALSE )) ) + page, n, autorotate, FALSE )) ) return( -1 ); if( parse_header( rtiff, out ) ) @@ -2010,14 +2010,14 @@ vips__istiff( const char *filename ) int vips__tiff_read_header_buffer( const void *buf, size_t len, VipsImage *out, - int page, gboolean autorotate ) + int page, int n, gboolean autorotate ) { ReadTiff *rtiff; vips__tiff_init(); if( !(rtiff = readtiff_new_buffer( buf, len, out, - page, autorotate, FALSE )) ) + page, n, autorotate, FALSE )) ) return( -1 ); if( parse_header( rtiff, out ) ) @@ -2030,7 +2030,8 @@ vips__tiff_read_header_buffer( const void *buf, size_t len, VipsImage *out, int vips__tiff_read_buffer( const void *buf, size_t len, - VipsImage *out, int page, gboolean autorotate, gboolean readbehind ) + VipsImage *out, int page, int n, gboolean autorotate, + gboolean readbehind ) { ReadTiff *rtiff; @@ -2042,7 +2043,7 @@ vips__tiff_read_buffer( const void *buf, size_t len, vips__tiff_init(); if( !(rtiff = readtiff_new_buffer( buf, len, out, - page, autorotate, readbehind )) ) + page, n, autorotate, readbehind )) ) return( -1 ); if( TIFFIsTiled( rtiff->tiff ) ) { diff --git a/libvips/foreign/tiffload.c b/libvips/foreign/tiffload.c index d5aec59b..ccbd9501 100644 --- a/libvips/foreign/tiffload.c +++ b/libvips/foreign/tiffload.c @@ -59,6 +59,10 @@ typedef struct _VipsForeignLoadTiff { */ int page; + /* Load this many pages. + */ + int n; + /* Autorotate using orientation tag. */ gboolean autorotate; @@ -96,7 +100,14 @@ vips_foreign_load_tiff_class_init( VipsForeignLoadTiffClass *class ) G_STRUCT_OFFSET( VipsForeignLoadTiff, page ), 0, 100000, 0 ); - VIPS_ARG_BOOL( class, "autorotate", 11, + VIPS_ARG_INT( class, "n", 11, + _( "n" ), + _( "Load this many pages" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsForeignLoadTiff, n ), + -1, 100000, 1 ); + + VIPS_ARG_BOOL( class, "autorotate", 12, _( "Autorotate" ), _( "Rotate image using orientation tag" ), VIPS_ARGUMENT_OPTIONAL_INPUT, @@ -108,6 +119,7 @@ static void vips_foreign_load_tiff_init( VipsForeignLoadTiff *tiff ) { tiff->page = 0; + tiff->n = 1; } typedef struct _VipsForeignLoadTiffFile { @@ -154,7 +166,7 @@ vips_foreign_load_tiff_file_header( VipsForeignLoad *load ) VipsForeignLoadTiffFile *file = (VipsForeignLoadTiffFile *) load; if( vips__tiff_read_header( file->filename, load->out, - tiff->page, tiff->autorotate ) ) + tiff->page, tiff->n, tiff->autorotate ) ) return( -1 ); VIPS_SETSTR( load->out->filename, file->filename ); @@ -168,8 +180,9 @@ vips_foreign_load_tiff_file_load( VipsForeignLoad *load ) VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load; VipsForeignLoadTiffFile *file = (VipsForeignLoadTiffFile *) load; - if( vips__tiff_read( file->filename, load->real, tiff->page, - tiff->autorotate, load->access == VIPS_ACCESS_SEQUENTIAL ) ) + if( vips__tiff_read( file->filename, load->real, + tiff->page, tiff->n, tiff->autorotate, + load->access == VIPS_ACCESS_SEQUENTIAL ) ) return( -1 ); return( 0 ); @@ -239,7 +252,7 @@ vips_foreign_load_tiff_buffer_header( VipsForeignLoad *load ) if( vips__tiff_read_header_buffer( buffer->buf->data, buffer->buf->length, load->out, - tiff->page, tiff->autorotate ) ) + tiff->page, tiff->n, tiff->autorotate ) ) return( -1 ); return( 0 ); @@ -253,7 +266,7 @@ vips_foreign_load_tiff_buffer_load( VipsForeignLoad *load ) if( vips__tiff_read_buffer( buffer->buf->data, buffer->buf->length, load->real, - tiff->page, tiff->autorotate, + tiff->page, tiff->n, tiff->autorotate, load->access == VIPS_ACCESS_SEQUENTIAL ) ) return( -1 ); @@ -302,6 +315,7 @@ vips_foreign_load_tiff_buffer_init( VipsForeignLoadTiffBuffer *buffer ) * Optional arguments: * * * @page: %gint, load this page + * * @n: %gint, load this many pages * * @autorotate: %gboolean, use orientation tag to rotate the image * during load * @@ -310,7 +324,12 @@ vips_foreign_load_tiff_buffer_init( VipsForeignLoadTiffBuffer *buffer ) * pyramidal images and JPEG compression. including CMYK and YCbCr. * * @page means load this page from the file. By default the first page (page - * 0) is read. + * 0) is read. + * + * @n means load this many pages. By default a single page is read. All the + * pages must have the same dimensions, and they are loaded as a tall, thin + * "toilet roll" image. The "page-height" metadata tag gives the height in + * pixels of each page. Use -1 to load all pages. * * Setting @autorotate to %TRUE will make the loader interpret the * orientation tag and automatically rotate the image appropriately during @@ -357,6 +376,7 @@ vips_tiffload( const char *filename, VipsImage **out, ... ) * Optional arguments: * * * @page: %gint, load this page + * * @n: %gint, load this many pages * * @autorotate: %gboolean, use orientation tag to rotate the image * during load *