From 10d1aeb6f20760355e54d7e5f8ee4b3e8a509899 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Fri, 17 Aug 2018 11:14:06 +0100 Subject: [PATCH] make pdf load close early but only in seq mode --- README.md | 4 ++-- libvips/foreign/foreign.c | 2 +- libvips/foreign/pdfload.c | 26 +++++++++++++++++++++----- libvips/foreign/pdfload_pdfium.c | 23 ++++++++++++++++++++--- 4 files changed, 44 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index b80b9e86..49c0b0d7 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,8 @@ morphological operations, frequency filtering, colour, resampling, statistics and others. It supports a large range of numeric formats, from 8-bit int to 128-bit complex. It supports a good range of image formats, including JPEG, TIFF, PNG, WebP, FITS, Matlab, OpenEXR, PDF, SVG, HDR, PPM, CSV, GIF, -Analyze, DeepZoom, and OpenSlide. It can also load images via ImageMagick -or GraphicsMagick. +Analyze, Nifti, DeepZoom, and OpenSlide. It can also load and save images via +ImageMagick or GraphicsMagick. It has APIs for [C](http://jcupitt.github.io/libvips/API/current/using-from-c.html) and diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index 20d6dc74..26ba6e56 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -981,7 +981,7 @@ vips_foreign_load_build( VipsObject *object ) /* Tell downstream if we are reading sequentially. */ - if( sequential ) + if( sequential ) vips_image_set_area( load->out, VIPS_META_SEQUENTIAL, NULL, NULL ); diff --git a/libvips/foreign/pdfload.c b/libvips/foreign/pdfload.c index bcb1bd4c..9e537003 100644 --- a/libvips/foreign/pdfload.c +++ b/libvips/foreign/pdfload.c @@ -10,6 +10,8 @@ * - use a much larger strip size, thanks bubba * 8/6/18 * - add background param + * 16/8/18 + * - shut down the input file as soon as we can [kleisauke] */ /* @@ -116,13 +118,19 @@ typedef VipsForeignLoadClass VipsForeignLoadPdfClass; G_DEFINE_ABSTRACT_TYPE( VipsForeignLoadPdf, vips_foreign_load_pdf, VIPS_TYPE_FOREIGN_LOAD ); +static void +vips_foreign_load_pdf_close( VipsForeignLoadPdf *pdf ) +{ + VIPS_UNREF( pdf->page ); + VIPS_UNREF( pdf->doc ); +} + static void vips_foreign_load_pdf_dispose( GObject *gobject ) { VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) gobject; - VIPS_UNREF( pdf->page ); - VIPS_UNREF( pdf->doc ); + vips_foreign_load_pdf_close( pdf ); G_OBJECT_CLASS( vips_foreign_load_pdf_parent_class )-> dispose( gobject ); @@ -328,6 +336,7 @@ vips_foreign_load_pdf_generate( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) { VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) a; + VipsForeignLoad *load = (VipsForeignLoad *) pdf; VipsRect *r = &or->valid; int top; @@ -386,11 +395,18 @@ vips_foreign_load_pdf_generate( VipsRegion *or, i += 1; } + /* In seq mode, we can shut down the input when we render the last + * row. + */ + if( top >= or->im->Ysize && + load->access == VIPS_ACCESS_SEQUENTIAL ) + vips_foreign_load_pdf_close( pdf ); + /* Cairo makes pre-multipled BRGA, we must byteswap and unpremultiply. */ for( y = 0; y < r->height; y++ ) vips__cairo2rgba( - (guint32 *) VIPS_REGION_ADDR( or, r->left, r->top + y ), + (guint32 *) VIPS_REGION_ADDR( or, r->left, r->top + y ), r->width ); return( 0 ); @@ -763,8 +779,8 @@ vips_pdfload( const char *filename, VipsImage **out, ... ) * * @scale: %gdouble, scale render by this factor * * @background: #VipsArrayDouble background colour * - * Read a PDF-formatted memory block into a VIPS image. Exactly as - * vips_pdfload(), but read from a memory buffer. + * Read a PDF-formatted memory buffer into a VIPS image. Exactly as + * vips_pdfload(), but read from memory. * * You must not free the buffer while @out is active. The * #VipsObject::postclose signal on @out is a good place to free. diff --git a/libvips/foreign/pdfload_pdfium.c b/libvips/foreign/pdfload_pdfium.c index d683e3c8..041c9425 100644 --- a/libvips/foreign/pdfload_pdfium.c +++ b/libvips/foreign/pdfload_pdfium.c @@ -4,6 +4,8 @@ * - from pdfload.c * 8/6/18 * - add background param + * 16/8/18 + * - shut down the input file as soon as we can [kleisauke] */ /* @@ -134,15 +136,22 @@ vips_pdfium_error( void ) vips_error( "pdfload", "%s", _( "unknown error" ) ); } +static void +vips_foreign_load_pdf_close( VipsForeignLoadPdf *pdf ) +{ + VIPS_FREEF( FPDF_ClosePage, pdf->page ); + VIPS_FREEF( FPDF_CloseDocument, pdf->doc ); +} + static void vips_foreign_load_pdf_dispose( GObject *gobject ) { VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) gobject; - VIPS_FREEF( FPDF_ClosePage, pdf->page ); - VIPS_FREEF( FPDF_CloseDocument, pdf->doc ); + vips_foreign_load_pdf_close( pdf ); - G_OBJECT_CLASS( vips_foreign_load_pdf_parent_class )->dispose( gobject ); + G_OBJECT_CLASS( vips_foreign_load_pdf_parent_class )-> + dispose( gobject ); } static void * @@ -373,6 +382,7 @@ vips_foreign_load_pdf_generate( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) { VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) a; + VipsForeignLoad *load = (VipsForeignLoad *) pdf; VipsRect *r = &or->valid; int top; @@ -423,6 +433,13 @@ vips_foreign_load_pdf_generate( VipsRegion *or, i += 1; } + /* In seq mode, we can shut down the input when we render the last + * row. + */ + if( top >= or->im->Ysize && + load->access == VIPS_ACCESS_SEQUENTIAL ) + vips_foreign_load_pdf_close( pdf ); + /* PDFium writes BRGA, we must swap. * * FIXME ... this is a bit slow.