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
This commit is contained in:
John Cupitt 2016-11-15 10:07:09 +00:00
parent 92c549e995
commit 3ef6a4695a
5 changed files with 63 additions and 38 deletions

4
TODO
View File

@ -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:

View File

@ -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

View File

@ -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[];

View File

@ -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 ) ) {

View File

@ -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
*