diff --git a/ChangeLog b/ChangeLog index 29436f5c..3ad4ef91 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,7 @@ - create funcs always make MULTIBAND (ie. no alpha) - use O_TMPFILE, if available [Alexander--] - set "interlaced=1" for interlaced JPG and PNG images +- add PDFium PDF loader 12/3/18 started 8.6.4 - better fitting of fonts with overhanging edges [AdriĆ ] diff --git a/README.md b/README.md index 9b924d97..a586fa75 100644 --- a/README.md +++ b/README.md @@ -212,7 +212,7 @@ If PDFium is not detected, libvips will look for poppler-glib instead. ### libpoppler The usual PDF loader. If this is not present, vips will try to load PDFs -via imagemagick instead. +via imagemagick. ### libgsf-1 diff --git a/libvips/foreign/pdfload.c b/libvips/foreign/pdfload.c index 89f1c960..e48a5920 100644 --- a/libvips/foreign/pdfload.c +++ b/libvips/foreign/pdfload.c @@ -55,6 +55,8 @@ #include #include +#include "pforeign.h" + #ifdef HAVE_POPPLER #include @@ -91,7 +93,7 @@ typedef struct _VipsForeignLoadPdf { */ int n_pages; - /* We need to read out the side of each page we will render, and lay + /* We need to read out the size of each page we will render, and lay * them out in the final image. */ VipsRect image; @@ -145,33 +147,6 @@ vips_foreign_load_pdf_get_flags( VipsForeignLoad *load ) return( VIPS_FOREIGN_PARTIAL ); } -static gboolean -vips_foreign_load_pdf_is_a_buffer( const void *buf, size_t len ) -{ - const guchar *str = (const guchar *) buf; - - if( len >= 4 && - str[0] == '%' && - str[1] == 'P' && - str[2] == 'D' && - str[3] == 'F' ) - return( 1 ); - - return( 0 ); -} - -static gboolean -vips_foreign_load_pdf_is_a( const char *filename ) -{ - unsigned char buf[4]; - - if( vips__get_bytes( filename, buf, 4 ) == 4 && - vips_foreign_load_pdf_is_a_buffer( buf, 4 ) ) - return( 1 ); - - return( 0 ); -} - static int vips_foreign_load_pdf_get_page( VipsForeignLoadPdf *pdf, int page_no ) { @@ -429,7 +404,7 @@ vips_foreign_load_pdf_load( VipsForeignLoad *load ) * (again) keep the number of calls to page_render low. */ if( vips_linecache( t[0], &t[1], - "tile_height", 5000, + "tile_height", VIPS_MIN( 5000, pdf->pages[0].height ), NULL ) ) return( -1 ); if( vips_image_write( t[1], load->real ) ) @@ -658,6 +633,37 @@ vips_foreign_load_pdf_buffer_init( VipsForeignLoadPdfBuffer *buffer ) #endif /*HAVE_POPPLER*/ +/* Also used by the pdfium loader. + */ +gboolean +vips_foreign_load_pdf_is_a_buffer( const void *buf, size_t len ) +{ + const guchar *str = (const guchar *) buf; + + if( len >= 4 && + str[0] == '%' && + str[1] == 'P' && + str[2] == 'D' && + str[3] == 'F' ) + return( 1 ); + + return( 0 ); +} + +/* Also used by the pdfium loader. + */ +gboolean +vips_foreign_load_pdf_is_a( const char *filename ) +{ + unsigned char buf[4]; + + if( vips__get_bytes( filename, buf, 4 ) == 4 && + vips_foreign_load_pdf_is_a_buffer( buf, 4 ) ) + return( 1 ); + + return( 0 ); +} + /** * vips_pdfload: * @filename: file to load diff --git a/libvips/foreign/pdfload_pdfium.c b/libvips/foreign/pdfload_pdfium.c index 5687283a..b9e6bd4f 100644 --- a/libvips/foreign/pdfload_pdfium.c +++ b/libvips/foreign/pdfload_pdfium.c @@ -33,14 +33,8 @@ /* TODO * - * - more code sharing with pdfload.c, eg. vips_foreign_load_pdf_is_a_buffer() - * and get_flags etc. - * - could share the page layout code too - * - make pdf.c with base stuff in? * - what about filename encodings - * - I guess we must write RGBA to match poppler output - * - new_from_buffer stuff - * + * - need to test on Windows */ /* @@ -57,14 +51,12 @@ #include #include -/* Just until we get rid of the final bits of poppler - */ -#include - #include #include #include +#include "pforeign.h" + #ifdef HAVE_PDFIUM #include @@ -97,7 +89,7 @@ typedef struct _VipsForeignLoadPdf { */ int n_pages; - /* We need to read out the side of each page we will render, and lay + /* We need to read out the size of each page we will render, and lay * them out in the final image. */ VipsRect image; @@ -137,8 +129,8 @@ vips_foreign_load_pdf_dispose( GObject *gobject ) { VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) gobject; - VIPS_FREEF( FPDF_CloseDocument, pdf->doc ); VIPS_FREEF( FPDF_ClosePage, pdf->page ); + VIPS_FREEF( FPDF_CloseDocument, pdf->doc ); G_OBJECT_CLASS( vips_foreign_load_pdf_parent_class )->dispose( gobject ); } @@ -180,7 +172,8 @@ vips_foreign_load_pdf_build( VipsObject *object ) static VipsForeignFlags vips_foreign_load_pdf_get_flags_filename( const char *filename ) { - /* We can render any part of the page on demand. + /* We can't render any part of the page on demand, but we can render + * separate pages. Might as well call ourselves partial. */ return( VIPS_FOREIGN_PARTIAL ); } @@ -191,33 +184,6 @@ vips_foreign_load_pdf_get_flags( VipsForeignLoad *load ) return( VIPS_FOREIGN_PARTIAL ); } -static gboolean -vips_foreign_load_pdf_is_a_buffer( const void *buf, size_t len ) -{ - const guchar *str = (const guchar *) buf; - - if( len >= 4 && - str[0] == '%' && - str[1] == 'P' && - str[2] == 'D' && - str[3] == 'F' ) - return( 1 ); - - return( 0 ); -} - -static gboolean -vips_foreign_load_pdf_is_a( const char *filename ) -{ - unsigned char buf[4]; - - if( vips__get_bytes( filename, buf, 4 ) == 4 && - vips_foreign_load_pdf_is_a_buffer( buf, 4 ) ) - return( 1 ); - - return( 0 ); -} - static int vips_foreign_load_pdf_get_page( VipsForeignLoadPdf *pdf, int page_no ) { @@ -246,8 +212,8 @@ vips_foreign_load_pdf_get_page( VipsForeignLoadPdf *pdf, int page_no ) /* String-based metadata fields we extract. */ typedef struct _VipsForeignLoadPdfMetadata { - char *tag; // as understood by PDFium - char *field; // as understood by libvips + char *tag; /* as understood by PDFium */ + char *field; /* as understood by libvips */ } VipsForeignLoadPdfMetadata; static VipsForeignLoadPdfMetadata vips_foreign_load_pdf_metadata[] = { @@ -257,7 +223,7 @@ static VipsForeignLoadPdfMetadata vips_foreign_load_pdf_metadata[] = { { "Keywords", "pdf-keywords" }, { "Creator", "pdf-creator" }, { "Producer", "pdf-producer" }, - // poppler has "metadata" as well, but pdfium does not support this + /* poppler has "metadata" as well, but pdfium does not support this */ }; static int n_metadata = VIPS_NUMBER( vips_foreign_load_pdf_metadata ); @@ -440,6 +406,8 @@ vips_foreign_load_pdf_generate( VipsRegion *or, } /* PDFium writes BRGA, we must swap. + * + * FIXME ... this is a bit slow. */ for( y = 0; y < r->height; y++ ) { VipsPel *p; @@ -634,17 +602,17 @@ G_DEFINE_TYPE( VipsForeignLoadPdfBuffer, vips_foreign_load_pdf_buffer, static int vips_foreign_load_pdf_buffer_header( VipsForeignLoad *load ) { - /* VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) load; VipsForeignLoadPdfBuffer *buffer = (VipsForeignLoadPdfBuffer *) load; - if( !(pdf->doc = poppler_document_new_from_data( - buffer->buf->data, buffer->buf->length, NULL, &error )) ) { - vips_g_error( &error ); + if( !(pdf->doc = FPDF_LoadMemDocument( buffer->buf->data, + buffer->buf->length, NULL )) ) { + vips_pdfium_error(); + vips_error( "pdfload", + "%s", _( "unable to load from buffer" ) ); return( -1 ); } - */ return( vips_foreign_load_pdf_header( load ) ); } diff --git a/libvips/foreign/pforeign.h b/libvips/foreign/pforeign.h index 08973569..a513f5b0 100644 --- a/libvips/foreign/pforeign.h +++ b/libvips/foreign/pforeign.h @@ -239,6 +239,9 @@ int vips__openslide_read( const char *filename, VipsImage *out, int vips__openslide_read_associated( const char *filename, VipsImage *out, const char *associated ); +gboolean vips_foreign_load_pdf_is_a_buffer( const void *buf, size_t len ); +gboolean vips_foreign_load_pdf_is_a( const char *filename ); + #ifdef __cplusplus } #endif /*__cplusplus*/