From da6f4fd04319677319173505b6a1ecc3ccf4c59f Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 26 Apr 2018 08:55:31 +0100 Subject: [PATCH] add n-pages metadata item tiff, magick and pdf load now attach an n-pages metadata item recording the number of pages in the orginal file see https://github.com/jcupitt/libvips/issues/953 --- ChangeLog | 1 + libvips/foreign/magick2vips.c | 13 +++++++++- libvips/foreign/magick7load.c | 43 +++++++++++--------------------- libvips/foreign/pdfload.c | 3 ++- libvips/foreign/pdfload_pdfium.c | 3 ++- libvips/foreign/tiff2vips.c | 12 ++++++++- libvips/include/vips/header.h | 7 ++++++ 7 files changed, 50 insertions(+), 32 deletions(-) diff --git a/ChangeLog b/ChangeLog index f52b3304..9ef70630 100644 --- a/ChangeLog +++ b/ChangeLog @@ -18,6 +18,7 @@ - add @format option to magickload - jpegload adds a jpeg-chroma-subsample field with eg. 4:4:4 for no chrominance subsampling. +- tiffload, pdfload, magickload set VIPS_META_N_PAGES "n-pages" metadata item 12/3/18 started 8.6.4 - better fitting of fonts with overhanging edges [AdriĆ ] diff --git a/libvips/foreign/magick2vips.c b/libvips/foreign/magick2vips.c index 7278b883..476910ce 100644 --- a/libvips/foreign/magick2vips.c +++ b/libvips/foreign/magick2vips.c @@ -134,7 +134,14 @@ typedef struct _Read { ImageInfo *image_info; ExceptionInfo exception; + /* Number of pages in image. + */ + int n_pages; + + /* Number of pages we will read. + */ int n_frames; + Image **frames; int frame_height; @@ -203,6 +210,7 @@ read_new( const char *filename, VipsImage *im, read->image = NULL; read->image_info = CloneImageInfo( NULL ); GetExceptionInfo( &read->exception ); + read->n_pages = 0; read->n_frames = 0; read->frames = NULL; read->frame_height = 0; @@ -488,6 +496,7 @@ parse_header( Read *read ) which says this is a volumetric image */ + read->n_pages = GetImageListLength( image ); read->n_frames = 0; for( p = image; p; (p = GetNextImageInList( p )) ) { if( p->columns != (unsigned int) im->Xsize || @@ -512,7 +521,7 @@ parse_header( Read *read ) read->n_frames = 1; #ifdef DEBUG - printf( "image has %d frames\n", read->n_frames ); + printf( "will read %d frames\n", read->n_frames ); #endif /*DEBUG*/ if( read->n != -1 ) @@ -533,6 +542,8 @@ parse_header( Read *read ) im->Ysize *= read->n_frames; } + vips_image_set_int( im, VIPS_META_N_PAGES, read->n_pages ); + return( 0 ); } diff --git a/libvips/foreign/magick7load.c b/libvips/foreign/magick7load.c index 34d261ec..e8361743 100644 --- a/libvips/foreign/magick7load.c +++ b/libvips/foreign/magick7load.c @@ -76,7 +76,11 @@ typedef struct _VipsForeignLoadMagick7 { ImageInfo *image_info; ExceptionInfo *exception; - int n_frames; /* Number of frames in file */ + /* Number of pages in image. + */ + int n_pages; + + int n_frames; /* Number of frames we will read */ Image **frames; /* An Image* for each frame */ CacheView **cache_view; /* A CacheView for each frame */ int frame_height; @@ -283,26 +287,6 @@ vips_foreign_load_magick7_dispose( GObject *gobject ) dispose( gobject ); } -static void * -vips_foreign_load_magick7_genesis_cb( void *client ) -{ -#ifdef DEBUG - printf( "vips_foreign_load_magick7_genesis:\n" ); -#endif /*DEBUG*/ - - MagickCoreGenesis( vips_get_argv0(), MagickFalse ); - - return( NULL ); -} - -static void -vips_foreign_load_magick7_genesis( void ) -{ - static GOnce once = G_ONCE_INIT; - - VIPS_ONCE( &once, vips_foreign_load_magick7_genesis_cb, NULL ); -} - static int vips_foreign_load_magick7_build( VipsObject *object ) { @@ -578,14 +562,15 @@ vips_foreign_load_magick7_parse( VipsForeignLoadMagick7 *magick7, which says this is a volumetric image */ - magick7->n_frames = GetImageListLength( GetFirstImageInList( image ) ); + magick7->n_pages = GetImageListLength( GetFirstImageInList( image ) ); #ifdef DEBUG - printf( "image has %d frames\n", magick7->n_frames ); + printf( "image has %d pages\n", magick7->n_pages ); #endif /*DEBUG*/ - if( magick7->n != -1 ) - magick7->n_frames = VIPS_MIN( magick7->n_frames, magick7->n ); + magick7->n_frames = magick7->n != -1 ? + VIPS_MIN( magick7->n_frames, magick7->n ) : + magick7->n_pages; /* So we can finally set the height. */ @@ -594,11 +579,13 @@ vips_foreign_load_magick7_parse( VipsForeignLoadMagick7 *magick7, out->Ysize *= magick7->n_frames; } + vips_image_set_int( out, VIPS_META_N_PAGES, magick7->n_pages ); + return( 0 ); } /* We don't bother with GetPixelReadMask(), assume it's everywhere. Don't - * bother with traits, assume taht's always update. + * bother with traits, assume that's always updated. * * We do skip index channels. Palette images add extra index channels * containing the index value from the file before colourmap lookup. @@ -753,7 +740,7 @@ ismagick7( const char *filename ) ExceptionInfo *exception; int result; - vips_foreign_load_magick7_genesis(); + magick_genesis(); /* Horribly slow :-( */ @@ -853,7 +840,7 @@ vips_foreign_load_magick7_buffer_is_a_buffer( const void *buf, size_t len ) ExceptionInfo *exception; int result; - vips_foreign_load_magick7_genesis(); + magick_genesis(); /* Horribly slow :-( */ diff --git a/libvips/foreign/pdfload.c b/libvips/foreign/pdfload.c index ae593c06..980dd162 100644 --- a/libvips/foreign/pdfload.c +++ b/libvips/foreign/pdfload.c @@ -204,9 +204,10 @@ vips_foreign_load_pdf_set_image( VipsForeignLoadPdf *pdf, VipsImage *out ) */ vips_image_pipelinev( out, VIPS_DEMAND_STYLE_FATSTRIP, NULL ); - /* Extract and attach metadata. + /* Extract and attach metadata. Set the old name too for compat. */ vips_image_set_int( out, "pdf-n_pages", pdf->n_pages ); + vips_image_set_int( out, VIPS_META_N_PAGES, pdf->n_pages ); for( i = 0; i < n_metadata; i++ ) { VipsForeignLoadPdfMetadata *metadata = diff --git a/libvips/foreign/pdfload_pdfium.c b/libvips/foreign/pdfload_pdfium.c index b9e6bd4f..79bb2598 100644 --- a/libvips/foreign/pdfload_pdfium.c +++ b/libvips/foreign/pdfload_pdfium.c @@ -241,9 +241,10 @@ vips_foreign_load_pdf_set_image( VipsForeignLoadPdf *pdf, VipsImage *out ) */ vips_image_pipelinev( out, VIPS_DEMAND_STYLE_FATSTRIP, NULL ); - /* Extract and attach metadata. + /* Extract and attach metadata. Set the old name too for compat. */ vips_image_set_int( out, "pdf-n_pages", pdf->n_pages ); + vips_image_set_int( out, VIPS_META_N_PAGES, pdf->n_pages ); for( i = 0; i < n_metadata; i++ ) { VipsForeignLoadPdfMetadata *metadata = diff --git a/libvips/foreign/tiff2vips.c b/libvips/foreign/tiff2vips.c index 49220307..70b7a810 100644 --- a/libvips/foreign/tiff2vips.c +++ b/libvips/foreign/tiff2vips.c @@ -177,6 +177,8 @@ * - remove missing res warning * 19/5/17 * - page > 0 could break edge tiles or strips + * 26/4/18 + * - add n-pages metadata item */ /* @@ -283,6 +285,10 @@ typedef struct _Rtiff { */ TIFF *tiff; + /* Number of pages (directories) in image. + */ + int n_pages; + /* The current page we have set. */ int current_page; @@ -1230,6 +1236,8 @@ rtiff_set_header( Rtiff *rtiff, VipsImage *out ) vips_image_set_int( out, VIPS_META_PAGE_HEIGHT, rtiff->header.height ); + vips_image_set_int( out, VIPS_META_N_PAGES, rtiff->n_pages ); + /* Even though we could end up serving tiled data, always hint * THINSTRIP, since we're quite happy doing that too, and it could need * a lot less memory. @@ -1984,6 +1992,7 @@ rtiff_new( VipsImage *out, int page, int n, gboolean autorotate ) rtiff->n = n; rtiff->autorotate = autorotate; rtiff->tiff = NULL; + rtiff->n_pages = 0; rtiff->current_page = -1; rtiff->sfn = NULL; rtiff->client = NULL; @@ -2167,8 +2176,9 @@ rtiff_header_read_all( Rtiff *rtiff ) /* -1 means "to the end". */ + rtiff->n_pages = rtiff_n_pages( rtiff ); if( rtiff->n == -1 ) - rtiff->n = rtiff_n_pages( rtiff ) - rtiff->page; + rtiff->n = rtiff->n_pages - rtiff->page; /* If we're to read many pages, verify that they are all identical. */ diff --git a/libvips/include/vips/header.h b/libvips/include/vips/header.h index 922f92ba..7fdf84f7 100644 --- a/libvips/include/vips/header.h +++ b/libvips/include/vips/header.h @@ -143,6 +143,13 @@ extern "C" { */ #define VIPS_META_PAGE_HEIGHT "page-height" +/** + * VIPS_META_N_PAGES: + * + * If set, the number of pages in the original file. + */ +#define VIPS_META_N_PAGES "n-pages" + guint64 vips_format_sizeof( VipsBandFormat format ); guint64 vips_format_sizeof_unsafe( VipsBandFormat format );