From fb64d3607a0797d178e5c505a47c4f4a5f519286 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Fri, 8 Jun 2018 10:28:00 +0100 Subject: [PATCH] add @background option to pdfload Add a "background" option to pdfload to help support PDFs with a transparent background. For example: vips copy transparent.pdf[background=0] x.png see https://github.com/jcupitt/libvips/issues/995 --- ChangeLog | 1 + libvips/foreign/pdfload.c | 36 +++++++++++++++++++++++++++++--- libvips/foreign/pdfload_pdfium.c | 31 ++++++++++++++++++++++++--- 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 906e6481..bfe9965e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -24,6 +24,7 @@ - remove vips7 stuff from default API ... you must now #include it explicitly - added vips_argument_get_id() to fix derived classes on win32 [angelmixu] - fix compile with MSVC 2017 [angelmixu] +- pdfload has a option for background 12/3/18 started 8.6.4 - better fitting of fonts with overhanging edges [AdriĆ ] diff --git a/libvips/foreign/pdfload.c b/libvips/foreign/pdfload.c index 980dd162..bcb1bd4c 100644 --- a/libvips/foreign/pdfload.c +++ b/libvips/foreign/pdfload.c @@ -8,6 +8,8 @@ * - set page-height, if we can * 28/6/17 * - use a much larger strip size, thanks bubba + * 8/6/18 + * - add background param */ /* @@ -81,6 +83,10 @@ typedef struct _VipsForeignLoadPdf { */ double scale; + /* Background colour. + */ + VipsArrayDouble *background; + /* Poppler is not thread-safe, so we run inside a single-threaded * cache. On the plus side, this means we only need one @page pointer, * even though we change this during _generate(). @@ -99,6 +105,10 @@ typedef struct _VipsForeignLoadPdf { VipsRect image; VipsRect *pages; + /* The [double] background converted to the image format. + */ + VipsPel *ink; + } VipsForeignLoadPdf; typedef VipsForeignLoadClass VipsForeignLoadPdfClass; @@ -302,6 +312,14 @@ vips_foreign_load_pdf_header( VipsForeignLoad *load ) vips_foreign_load_pdf_set_image( pdf, load->out ); + /* Convert the background to the image format. + */ + if( !(pdf->ink = vips__vector_to_ink( class->nickname, + load->out, + VIPS_AREA( pdf->background )->data, NULL, + VIPS_AREA( pdf->background )->n )) ) + return( -1 ); + return( 0 ); } @@ -322,10 +340,9 @@ vips_foreign_load_pdf_generate( VipsRegion *or, r->left, r->top, r->width, r->height ); */ - /* Poppler won't always paint the background. Use 255 (white) for the - * bg, PDFs generally assume a paper backgrocund colour. + /* Poppler won't always paint the background. */ - vips_region_paint( or, r, 255 ); + vips_region_paint_pel( or, r, pdf->ink ); /* Search through the pages we are drawing for the first containing * this rect. This could be quicker, perhaps a binary search, but who @@ -462,6 +479,13 @@ vips_foreign_load_pdf_class_init( VipsForeignLoadPdfClass *class ) G_STRUCT_OFFSET( VipsForeignLoadPdf, scale ), 0.001, 100000.0, 1.0 ); + VIPS_ARG_BOXED( class, "background", 14, + _( "Background" ), + _( "Background value" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsForeignLoadPdf, background ), + VIPS_TYPE_ARRAY_DOUBLE ); + } static void @@ -471,6 +495,7 @@ vips_foreign_load_pdf_init( VipsForeignLoadPdf *pdf ) pdf->scale = 1.0; pdf->n = 1; pdf->current_page = -1; + pdf->background = vips_array_double_newv( 1, 255.0 ); } typedef struct _VipsForeignLoadPdfFile { @@ -677,6 +702,7 @@ vips_foreign_load_pdf_is_a( const char *filename ) * * @n: %gint, load this many pages * * @dpi: %gdouble, render at this DPI * * @scale: %gdouble, scale render by this factor + * * @background: #VipsArrayDouble background colour * * Render a PDF file into a VIPS image. Rendering uses the libpoppler library * and should be fast. @@ -696,6 +722,9 @@ vips_foreign_load_pdf_is_a( const char *filename ) * you can scale the rendering from the default 1 point == 1 pixel by * setting @scale. * + * Use @background to set the background colour, including transparency. The + * default is 255 (solid white). + * * The operation fills a number of header fields with metadata, for example * "pdf-author". They may be useful. * @@ -732,6 +761,7 @@ vips_pdfload( const char *filename, VipsImage **out, ... ) * * @n: %gint, load this many pages * * @dpi: %gdouble, render at this DPI * * @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. diff --git a/libvips/foreign/pdfload_pdfium.c b/libvips/foreign/pdfload_pdfium.c index 79bb2598..d683e3c8 100644 --- a/libvips/foreign/pdfload_pdfium.c +++ b/libvips/foreign/pdfload_pdfium.c @@ -2,6 +2,8 @@ * * 5/4/18 * - from pdfload.c + * 8/6/18 + * - add background param */ /* @@ -81,6 +83,10 @@ typedef struct _VipsForeignLoadPdf { */ double scale; + /* Background colour. + */ + VipsArrayDouble *background; + FPDF_DOCUMENT *doc; FPDF_PAGE *page; int current_page; @@ -95,6 +101,10 @@ typedef struct _VipsForeignLoadPdf { VipsRect image; VipsRect *pages; + /* The [double] background converted to the image format. + */ + VipsPel *ink; + } VipsForeignLoadPdf; typedef VipsForeignLoadClass VipsForeignLoadPdfClass; @@ -347,6 +357,14 @@ vips_foreign_load_pdf_header( VipsForeignLoad *load ) vips_foreign_load_pdf_set_image( pdf, load->out ); + /* Convert the background to the image format. + */ + if( !(pdf->ink = vips__vector_to_ink( class->nickname, + load->out, + VIPS_AREA( pdf->background )->data, NULL, + VIPS_AREA( pdf->background )->n )) ) + return( -1 ); + return( 0 ); } @@ -367,10 +385,9 @@ vips_foreign_load_pdf_generate( VipsRegion *or, r->left, r->top, r->width, r->height ); */ - /* Poppler won't always paint the background. Use 255 (white) for the - * bg, PDFs generally assume a paper backgrocund colour. + /* PDFium won't always paint the background. */ - vips_region_paint( or, r, 255 ); + vips_region_paint_pel( or, r, pdf->ink ); /* Search through the pages we are drawing for the first containing * this rect. This could be quicker, perhaps a binary search, but who @@ -505,6 +522,13 @@ vips_foreign_load_pdf_class_init( VipsForeignLoadPdfClass *class ) G_STRUCT_OFFSET( VipsForeignLoadPdf, scale ), 0.001, 100000.0, 1.0 ); + VIPS_ARG_BOXED( class, "background", 14, + _( "Background" ), + _( "Background value" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsForeignLoadPdf, background ), + VIPS_TYPE_ARRAY_DOUBLE ); + } static void @@ -514,6 +538,7 @@ vips_foreign_load_pdf_init( VipsForeignLoadPdf *pdf ) pdf->scale = 1.0; pdf->n = 1; pdf->current_page = -1; + pdf->background = vips_array_double_newv( 1, 255.0 ); } typedef struct _VipsForeignLoadPdfFile {