"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "libvips/foreign/pdfload.c" between
vips-8.10.6.tar.gz and vips-8.11.0.tar.gz

About: VIPS is a free image processing system (see also the GUI nip2).

pdfload.c  (vips-8.10.6):pdfload.c  (vips-8.11.0)
skipping to change at line 21 skipping to change at line 21
* 8/6/18 * 8/6/18
* - add background param * - add background param
* 16/8/18 [kleisauke] * 16/8/18 [kleisauke]
* - shut down the input file as soon as we can * - shut down the input file as soon as we can
* 19/9/19 * 19/9/19
* - reopen the input if we minimised too early * - reopen the input if we minimised too early
* 11/3/20 * 11/3/20
* - move on top of VipsSource * - move on top of VipsSource
* 21/9/20 * 21/9/20
* - allow dpi and scale to both be set [le0daniel] * - allow dpi and scale to both be set [le0daniel]
* 21/4/21 kleisauke
* - include GObject part from pdfload.c
*/ */
/* /*
This file is part of VIPS. This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
skipping to change at line 70 skipping to change at line 72
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <vips/vips.h> #include <vips/vips.h>
#include <vips/buf.h> #include <vips/buf.h>
#include <vips/internal.h> #include <vips/internal.h>
#include "pforeign.h" #include "pforeign.h"
/* TODO ... put minimise support back in. #ifdef HAVE_POPPLER
*/
#if defined(HAVE_POPPLER)
#include <cairo.h> #include <cairo.h>
#include <poppler.h> #include <poppler.h>
#define VIPS_TYPE_FOREIGN_LOAD_PDF (vips_foreign_load_pdf_get_type()) #define VIPS_TYPE_FOREIGN_LOAD_PDF (vips_foreign_load_pdf_get_type())
#define VIPS_FOREIGN_LOAD_PDF( obj ) \ #define VIPS_FOREIGN_LOAD_PDF( obj ) \
(G_TYPE_CHECK_INSTANCE_CAST( (obj), \ (G_TYPE_CHECK_INSTANCE_CAST( (obj), \
VIPS_TYPE_FOREIGN_LOAD_PDF, VipsForeignLoadPdf )) VIPS_TYPE_FOREIGN_LOAD_PDF, VipsForeignLoadPdf ))
#define VIPS_FOREIGN_LOAD_PDF_CLASS( klass ) \ #define VIPS_FOREIGN_LOAD_PDF_CLASS( klass ) \
(G_TYPE_CHECK_CLASS_CAST( (klass), \ (G_TYPE_CHECK_CLASS_CAST( (klass), \
skipping to change at line 226 skipping to change at line 225
!pdf->page ) { !pdf->page ) {
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( pdf ); VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( pdf );
VIPS_UNREF( pdf->page ); VIPS_UNREF( pdf->page );
pdf->current_page = -1; pdf->current_page = -1;
#ifdef DEBUG #ifdef DEBUG
printf( "vips_foreign_load_pdf_get_page: %d\n", page_no ); printf( "vips_foreign_load_pdf_get_page: %d\n", page_no );
#endif /*DEBUG*/ #endif /*DEBUG*/
if( !(pdf->page = poppler_document_get_page( pdf->doc, if( !(pdf->page = poppler_document_get_page( pdf->doc, page_no ))
page_no )) ) { ) {
vips_error( class->nickname, vips_error( class->nickname,
_( "unable to load page %d" ), page_no ); _( "unable to load page %d" ), page_no );
return( -1 ); return( -1 );
} }
pdf->current_page = page_no; pdf->current_page = page_no;
} }
return( 0 ); return( 0 );
} }
skipping to change at line 374 skipping to change at line 372
break; break;
if( vips_object_argument_isset( VIPS_OBJECT( pdf ), "n" ) ) if( vips_object_argument_isset( VIPS_OBJECT( pdf ), "n" ) )
vips_image_set_int( load->out, vips_image_set_int( load->out,
VIPS_META_PAGE_HEIGHT, pdf->pages[0].height ); VIPS_META_PAGE_HEIGHT, pdf->pages[0].height );
vips_foreign_load_pdf_set_image( pdf, load->out ); vips_foreign_load_pdf_set_image( pdf, load->out );
/* Convert the background to the image format. /* Convert the background to the image format.
* *
* FIXME ... we probably should convert this to pre-multiplied BGRA * FIXME ... we probably should convert this to pre-multiplied BGRA
* to match the Cairo convention. See vips__cairo2rgba(). * to match the Cairo convention. See vips__premultiplied_bgra2rgba().
*/ */
if( !(pdf->ink = vips__vector_to_ink( class->nickname, if( !(pdf->ink = vips__vector_to_ink( class->nickname,
load->out, load->out,
VIPS_AREA( pdf->background )->data, NULL, VIPS_AREA( pdf->background )->data, NULL,
VIPS_AREA( pdf->background )->n )) ) VIPS_AREA( pdf->background )->n )) )
return( -1 ); return( -1 );
vips_source_minimise( pdf->source ); vips_source_minimise( pdf->source );
return( 0 ); return( 0 );
} }
static void
vips_foreign_load_pdf_minimise( VipsImage *image, VipsForeignLoadPdf *pdf )
{
vips_source_minimise( pdf->source );
}
static int static int
vips_foreign_load_pdf_generate( VipsRegion *or, vips_foreign_load_pdf_generate( VipsRegion *or,
void *seq, void *a, void *b, gboolean *stop ) void *seq, void *a, void *b, gboolean *stop )
{ {
VipsForeignLoadPdf *pdf = VIPS_FOREIGN_LOAD_PDF( a ); VipsForeignLoadPdf *pdf = VIPS_FOREIGN_LOAD_PDF( a );
VipsRect *r = &or->valid; VipsRect *r = &or->valid;
int top; int top;
int i; int i;
int y; int y;
skipping to change at line 453 skipping to change at line 457
cairo_destroy( cr ); cairo_destroy( cr );
top += rect.height; top += rect.height;
i += 1; i += 1;
} }
/* Cairo makes pre-multipled BRGA, we must byteswap and unpremultiply. /* Cairo makes pre-multipled BRGA, we must byteswap and unpremultiply.
*/ */
for( y = 0; y < r->height; y++ ) for( y = 0; y < r->height; y++ )
vips__cairo2rgba( vips__premultiplied_bgra2rgba(
(guint32 *) VIPS_REGION_ADDR( or, r->left, r->top + y ), (guint32 *) VIPS_REGION_ADDR( or, r->left, r->top + y ),
r->width ); r->width );
return( 0 ); return( 0 );
} }
static int static int
vips_foreign_load_pdf_load( VipsForeignLoad *load ) vips_foreign_load_pdf_load( VipsForeignLoad *load )
{ {
VipsForeignLoadPdf *pdf = VIPS_FOREIGN_LOAD_PDF( load ); VipsForeignLoadPdf *pdf = VIPS_FOREIGN_LOAD_PDF( load );
skipping to change at line 475 skipping to change at line 479
vips_object_local_array( (VipsObject *) load, 2 ); vips_object_local_array( (VipsObject *) load, 2 );
#ifdef DEBUG #ifdef DEBUG
printf( "vips_foreign_load_pdf_load: %p\n", pdf ); printf( "vips_foreign_load_pdf_load: %p\n", pdf );
#endif /*DEBUG*/ #endif /*DEBUG*/
/* Read to this image, then cache to out, see below. /* Read to this image, then cache to out, see below.
*/ */
t[0] = vips_image_new(); t[0] = vips_image_new();
/* Don't minimise on ::minimise (end of computation): we support /* Close input immediately at end of read.
* threaded read, and minimise will happen outside the cache lock.
*/ */
g_signal_connect( t[0], "minimise",
G_CALLBACK( vips_foreign_load_pdf_minimise ), pdf );
/* Very large strips to limit render calls per page.
*/
vips_foreign_load_pdf_set_image( pdf, t[0] ); vips_foreign_load_pdf_set_image( pdf, t[0] );
if( vips_image_generate( t[0], if( vips_image_generate( t[0],
NULL, vips_foreign_load_pdf_generate, NULL, pdf, NULL ) ) NULL, vips_foreign_load_pdf_generate, NULL, pdf, NULL ) ||
return( -1 ); vips_sequential( t[0], &t[1],
"tile_height", VIPS_MIN( 5000, pdf->pages[0].height ),
/* Don't use tilecache to keep the number of calls to NULL ) ||
* pdf_page_render() low. Don't thread the cache, we rely on vips_image_write( t[1], load->real ) )
* locking to keep pdf single-threaded. Use a large strip size to
* (again) keep the number of calls to page_render low.
*/
if( vips_linecache( t[0], &t[1],
"tile_height", VIPS_MIN( 5000, pdf->pages[0].height ),
NULL ) )
return( -1 );
if( vips_image_write( t[1], load->real ) )
return( -1 ); return( -1 );
return( 0 ); return( 0 );
} }
static void static void
vips_foreign_load_pdf_class_init( VipsForeignLoadPdfClass *class ) vips_foreign_load_pdf_class_init( VipsForeignLoadPdfClass *class )
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS( class ); GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class; VipsObjectClass *object_class = (VipsObjectClass *) class;
skipping to change at line 645 skipping to change at line 644
if( !(pdf->source = if( !(pdf->source =
vips_source_new_from_file( file->filename )) ) vips_source_new_from_file( file->filename )) )
return( -1 ); return( -1 );
} }
return( VIPS_OBJECT_CLASS( vips_foreign_load_pdf_file_parent_class )-> return( VIPS_OBJECT_CLASS( vips_foreign_load_pdf_file_parent_class )->
build( object ) ); build( object ) );
} }
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 void static void
vips_foreign_load_pdf_file_class_init( vips_foreign_load_pdf_file_class_init(
VipsForeignLoadPdfFileClass *class ) VipsForeignLoadPdfFileClass *class )
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS( class ); GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class; VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignClass *foreign_class = (VipsForeignClass *) class; VipsForeignClass *foreign_class = (VipsForeignClass *) class;
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class; VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
gobject_class->dispose = vips_foreign_load_pdf_file_dispose; gobject_class->dispose = vips_foreign_load_pdf_file_dispose;
skipping to change at line 814 skipping to change at line 840
} }
static void static void
vips_foreign_load_pdf_source_init( VipsForeignLoadPdfSource *source ) vips_foreign_load_pdf_source_init( VipsForeignLoadPdfSource *source )
{ {
} }
#endif /*defined(HAVE_POPPLER)*/ #endif /*defined(HAVE_POPPLER)*/
/* Also used by the pdfium loader. /* The C API wrappers are defined in foreign.c.
*/ */
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
* @out: (out): output image
* @...: %NULL-terminated list of optional named arguments
*
* Optional arguments:
*
* * @page: %gint, load this page, numbered from zero
* * @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.
*
* The output image is always RGBA --- CMYK PDFs will be
* converted. If you need CMYK bitmaps, you should use vips_magickload()
* instead.
*
* Use @page to select a page to render, numbering from zero.
*
* Use @n to select the number of pages to render. The default is 1. Pages are
* rendered in a vertical column, with each individual page aligned to the
* left. Set to -1 to mean "until the end of the document". Use vips_grid()
* to change page layout.
*
* Use @dpi to set the rendering resolution. The default is 72. Additionally,
* you can scale by setting @scale. If you set both, they combine.
*
* Use @background to set the background RGBA colour. The default is 255
* (solid white), use eg. 0 for a transparent background.
*
* The operation fills a number of header fields with metadata, for example
* "pdf-author". They may be useful.
*
* This function only reads the image header and does not render any pixel
* data. Rendering occurs when pixels are accessed.
*
* See also: vips_image_new_from_file(), vips_magickload().
*
* Returns: 0 on success, -1 on error.
*/
int
vips_pdfload( const char *filename, VipsImage **out, ... )
{
va_list ap;
int result;
va_start( ap, out );
result = vips_call_split( "pdfload", ap, filename, out );
va_end( ap );
return( result );
}
/**
* vips_pdfload_buffer:
* @buf: (array length=len) (element-type guint8): memory area to load
* @len: (type gsize): size of memory area
* @out: (out): image to write
* @...: %NULL-terminated list of optional named arguments
*
* Optional arguments:
*
* * @page: %gint, load this page, numbered from zero
* * @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 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.
*
* See also: vips_pdfload().
*
* Returns: 0 on success, -1 on error.
*/
int
vips_pdfload_buffer( void *buf, size_t len, VipsImage **out, ... )
{
va_list ap;
VipsBlob *blob;
int result;
/* We don't take a copy of the data or free it.
*/
blob = vips_blob_new( NULL, buf, len );
va_start( ap, out );
result = vips_call_split( "pdfload_buffer", ap, blob, out );
va_end( ap );
vips_area_unref( VIPS_AREA( blob ) );
return( result );
}
/**
* vips_pdfload_source:
* @source: source to load from
* @out: (out): image to write
* @...: %NULL-terminated list of optional named arguments
*
* Optional arguments:
*
* * @page: %gint, load this page, numbered from zero
* * @n: %gint, load this many pages
* * @dpi: %gdouble, render at this DPI
* * @scale: %gdouble, scale render by this factor
* * @background: #VipsArrayDouble background colour
*
* Exactly as vips_pdfload(), but read from a source.
*
* See also: vips_pdfload()
*
* Returns: 0 on success, -1 on error.
*/
int
vips_pdfload_source( VipsSource *source, VipsImage **out, ... )
{
va_list ap;
int result;
va_start( ap, out );
result = vips_call_split( "pdfload_source", ap, source, out );
va_end( ap );
return( result );
}
 End of changes. 13 change blocks. 
24 lines changed or deleted 51 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)