move pdfload on top of source API
and add pdfload_source see https://github.com/libvips/libvips/issues/1541
This commit is contained in:
parent
d4f12a9999
commit
764b196d50
@ -6,7 +6,7 @@
|
||||
- tiffsave has a "depth" param to set max pyr depth
|
||||
- libtiff LOGLUV images load and save as libvips XYZ
|
||||
- add gifload_source, csvload_source, csvsave_target, matrixload_source,
|
||||
matrixsave_source
|
||||
matrixsave_source, pdfload_source
|
||||
- revise vipsthumbnail flags
|
||||
- add VIPS_LEAK env var
|
||||
- add vips_pipe_read_limit_set(), --vips-pipe-read-limit,
|
||||
|
@ -2097,9 +2097,9 @@ vips_foreign_operation_init( void )
|
||||
extern GType vips_foreign_save_webp_buffer_get_type( void );
|
||||
extern GType vips_foreign_save_webp_target_get_type( void );
|
||||
|
||||
extern GType vips_foreign_load_pdf_get_type( void );
|
||||
extern GType vips_foreign_load_pdf_file_get_type( void );
|
||||
extern GType vips_foreign_load_pdf_buffer_get_type( void );
|
||||
extern GType vips_foreign_load_pdf_source_get_type( void );
|
||||
|
||||
extern GType vips_foreign_load_svg_file_get_type( void );
|
||||
extern GType vips_foreign_load_svg_buffer_get_type( void );
|
||||
@ -2151,14 +2151,13 @@ vips_foreign_operation_init( void )
|
||||
vips_foreign_save_rad_target_get_type();
|
||||
#endif /*HAVE_RADIANCE*/
|
||||
|
||||
#ifdef HAVE_POPPLER
|
||||
vips_foreign_load_pdf_get_type();
|
||||
#if defined(HAVE_POPPLER) && defined(HAVE_GIO)
|
||||
vips_foreign_load_pdf_file_get_type();
|
||||
vips_foreign_load_pdf_buffer_get_type();
|
||||
vips_foreign_load_pdf_source_get_type();
|
||||
#endif /*HAVE_POPPLER*/
|
||||
|
||||
#ifdef HAVE_PDFIUM
|
||||
vips_foreign_load_pdf_get_type();
|
||||
vips_foreign_load_pdf_file_get_type();
|
||||
vips_foreign_load_pdf_buffer_get_type();
|
||||
#endif /*HAVE_PDFIUM*/
|
||||
|
@ -14,6 +14,8 @@
|
||||
* - shut down the input file as soon as we can
|
||||
* 19/9/19
|
||||
* - reopen the input if we minimised too early
|
||||
* 11/3/20
|
||||
* - move on top of VipsSource
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -63,7 +65,10 @@
|
||||
|
||||
#include "pforeign.h"
|
||||
|
||||
#ifdef HAVE_POPPLER
|
||||
/* TODO ... put minimise support back in.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_POPPLER) && defined(HAVE_GIO)
|
||||
|
||||
#include <cairo.h>
|
||||
#include <poppler.h>
|
||||
@ -86,6 +91,12 @@
|
||||
typedef struct _VipsForeignLoadPdf {
|
||||
VipsForeignLoad parent_object;
|
||||
|
||||
/* The VipsSource we load from, and the GInputStream we wrap around
|
||||
* it. Set from subclasses.
|
||||
*/
|
||||
VipsSource *source;
|
||||
GInputStream *stream;
|
||||
|
||||
/* Load this page.
|
||||
*/
|
||||
int page_no;
|
||||
@ -133,9 +144,6 @@ typedef struct _VipsForeignLoadPdf {
|
||||
typedef struct _VipsForeignLoadPdfClass {
|
||||
VipsForeignLoadClass parent_class;
|
||||
|
||||
int (*open)( VipsForeignLoadPdf *pdf );
|
||||
|
||||
void (*close)( VipsForeignLoadPdf *pdf );
|
||||
} VipsForeignLoadPdfClass;
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE( VipsForeignLoadPdf, vips_foreign_load_pdf,
|
||||
@ -145,9 +153,11 @@ static void
|
||||
vips_foreign_load_pdf_dispose( GObject *gobject )
|
||||
{
|
||||
VipsForeignLoadPdf *pdf = VIPS_FOREIGN_LOAD_PDF( gobject );
|
||||
VipsForeignLoadPdfClass *class = VIPS_FOREIGN_LOAD_PDF_GET_CLASS( pdf );
|
||||
|
||||
class->close( pdf );
|
||||
VIPS_UNREF( pdf->page );
|
||||
VIPS_UNREF( pdf->doc );
|
||||
VIPS_UNREF( pdf->source );
|
||||
VIPS_UNREF( pdf->stream );
|
||||
|
||||
G_OBJECT_CLASS( vips_foreign_load_pdf_parent_class )->
|
||||
dispose( gobject );
|
||||
@ -158,9 +168,18 @@ vips_foreign_load_pdf_build( VipsObject *object )
|
||||
{
|
||||
VipsForeignLoadPdf *pdf = VIPS_FOREIGN_LOAD_PDF( object );
|
||||
|
||||
GError *error = NULL;
|
||||
|
||||
if( !vips_object_argument_isset( object, "scale" ) )
|
||||
pdf->scale = pdf->dpi / 72.0;
|
||||
|
||||
pdf->stream = vips_g_input_stream_new_from_source( pdf->source );
|
||||
if( !(pdf->doc = poppler_document_new_from_stream( pdf->stream,
|
||||
vips_source_length( pdf->source ), NULL, NULL, &error )) ) {
|
||||
vips_g_error( &error );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_foreign_load_pdf_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
@ -274,8 +293,6 @@ vips_foreign_load_pdf_header( VipsForeignLoad *load )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( load );
|
||||
VipsForeignLoadPdf *pdf = VIPS_FOREIGN_LOAD_PDF( load );
|
||||
VipsForeignLoadPdfClass *pdf_class =
|
||||
VIPS_FOREIGN_LOAD_PDF_GET_CLASS( pdf );
|
||||
|
||||
int top;
|
||||
int i;
|
||||
@ -284,9 +301,6 @@ vips_foreign_load_pdf_header( VipsForeignLoad *load )
|
||||
printf( "vips_foreign_load_pdf_header: %p\n", pdf );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
if( pdf_class->open( pdf ) )
|
||||
return( -1 );
|
||||
|
||||
pdf->n_pages = poppler_document_get_n_pages( pdf->doc );
|
||||
|
||||
/* @n == -1 means until the end of the doc.
|
||||
@ -357,7 +371,7 @@ vips_foreign_load_pdf_header( VipsForeignLoad *load )
|
||||
VIPS_AREA( pdf->background )->n )) )
|
||||
return( -1 );
|
||||
|
||||
pdf_class->close( pdf );
|
||||
vips_source_minimise( pdf->source );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -367,7 +381,6 @@ vips_foreign_load_pdf_generate( VipsRegion *or,
|
||||
void *seq, void *a, void *b, gboolean *stop )
|
||||
{
|
||||
VipsForeignLoadPdf *pdf = VIPS_FOREIGN_LOAD_PDF( a );
|
||||
VipsForeignLoadPdfClass *class = VIPS_FOREIGN_LOAD_PDF_GET_CLASS( pdf );
|
||||
VipsRect *r = &or->valid;
|
||||
|
||||
int top;
|
||||
@ -380,11 +393,6 @@ vips_foreign_load_pdf_generate( VipsRegion *or,
|
||||
r->left, r->top, r->width, r->height );
|
||||
*/
|
||||
|
||||
/* We may have been minimised. Make sure the doc is open.
|
||||
*/
|
||||
if( class->open( pdf ) )
|
||||
return( -1 );
|
||||
|
||||
/* Poppler won't always paint the background.
|
||||
*/
|
||||
vips_region_paint_pel( or, r, pdf->ink );
|
||||
@ -445,7 +453,6 @@ static int
|
||||
vips_foreign_load_pdf_load( VipsForeignLoad *load )
|
||||
{
|
||||
VipsForeignLoadPdf *pdf = VIPS_FOREIGN_LOAD_PDF( load );
|
||||
VipsForeignLoadPdfClass *class = VIPS_FOREIGN_LOAD_PDF_GET_CLASS( pdf );
|
||||
VipsImage **t = (VipsImage **)
|
||||
vips_object_local_array( (VipsObject *) load, 2 );
|
||||
|
||||
@ -453,9 +460,6 @@ vips_foreign_load_pdf_load( VipsForeignLoad *load )
|
||||
printf( "vips_foreign_load_pdf_load: %p\n", pdf );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
if( class->open( pdf ) )
|
||||
return( -1 );
|
||||
|
||||
/* Read to this image, then cache to out, see below.
|
||||
*/
|
||||
t[0] = vips_image_new();
|
||||
@ -484,23 +488,6 @@ vips_foreign_load_pdf_load( VipsForeignLoad *load )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_foreign_load_pdf_open( VipsForeignLoadPdf *pdf )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_pdf_close( VipsForeignLoadPdf *pdf )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf( "vips_foreign_load_pdf_file_close:\n" );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
VIPS_UNREF( pdf->page );
|
||||
VIPS_UNREF( pdf->doc );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_pdf_class_init( VipsForeignLoadPdfClass *class )
|
||||
{
|
||||
@ -522,9 +509,6 @@ vips_foreign_load_pdf_class_init( VipsForeignLoadPdfClass *class )
|
||||
load_class->header = vips_foreign_load_pdf_header;
|
||||
load_class->load = vips_foreign_load_pdf_load;
|
||||
|
||||
class->open = vips_foreign_load_pdf_open;
|
||||
class->close = vips_foreign_load_pdf_close;
|
||||
|
||||
VIPS_ARG_INT( class, "page", 20,
|
||||
_( "Page" ),
|
||||
_( "Load this page from the file" ),
|
||||
@ -617,19 +601,18 @@ static const char *vips_foreign_pdf_suffs[] = {
|
||||
};
|
||||
|
||||
static int
|
||||
vips_foreign_load_pdf_file_open( VipsForeignLoadPdf *pdf )
|
||||
vips_foreign_load_pdf_file_build( VipsObject *object )
|
||||
{
|
||||
VipsForeignLoadPdf *pdf = VIPS_FOREIGN_LOAD_PDF( object );
|
||||
VipsForeignLoadPdfFile *file = (VipsForeignLoadPdfFile *) pdf;
|
||||
|
||||
GError *error = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "vips_foreign_load_pdf_file_open: %s\n", file->filename );
|
||||
printf( "vips_foreign_load_pdf_file_build: %s\n", file->filename );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
if( !file->uri &&
|
||||
file->filename ) {
|
||||
if( file->filename ) {
|
||||
char *path;
|
||||
GError *error = NULL;
|
||||
|
||||
/* We need an absolute path for a URI.
|
||||
*/
|
||||
@ -640,18 +623,15 @@ vips_foreign_load_pdf_file_open( VipsForeignLoadPdf *pdf )
|
||||
return( -1 );
|
||||
}
|
||||
g_free( path );
|
||||
|
||||
if( !(pdf->source =
|
||||
vips_source_new_from_file( file->filename )) )
|
||||
return( -1 );
|
||||
|
||||
}
|
||||
|
||||
if( !pdf->doc &&
|
||||
file->uri &&
|
||||
!(pdf->doc = poppler_document_new_from_file(
|
||||
file->uri, NULL, &error )) ) {
|
||||
vips_g_error( &error );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
return( VIPS_FOREIGN_LOAD_PDF_CLASS(
|
||||
vips_foreign_load_pdf_file_parent_class )->open( pdf ) );
|
||||
return( VIPS_OBJECT_CLASS( vips_foreign_load_pdf_file_parent_class )->
|
||||
build( object ) );
|
||||
}
|
||||
|
||||
static void
|
||||
@ -668,14 +648,14 @@ vips_foreign_load_pdf_file_class_init(
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->nickname = "pdfload";
|
||||
object_class->description = _( "load PDF from file" );
|
||||
object_class->build = vips_foreign_load_pdf_file_build;
|
||||
|
||||
foreign_class->suffs = vips_foreign_pdf_suffs;
|
||||
|
||||
load_class->is_a = vips_foreign_load_pdf_is_a;
|
||||
load_class->header = vips_foreign_load_pdf_file_header;
|
||||
|
||||
class->open = vips_foreign_load_pdf_file_open;
|
||||
|
||||
VIPS_ARG_STRING( class, "filename", 1,
|
||||
_( "Filename" ),
|
||||
_( "Filename to load from" ),
|
||||
@ -705,21 +685,19 @@ G_DEFINE_TYPE( VipsForeignLoadPdfBuffer, vips_foreign_load_pdf_buffer,
|
||||
vips_foreign_load_pdf_get_type() );
|
||||
|
||||
static int
|
||||
vips_foreign_load_pdf_buffer_open( VipsForeignLoadPdf *pdf )
|
||||
vips_foreign_load_pdf_buffer_build( VipsObject *object )
|
||||
{
|
||||
VipsForeignLoadPdf *pdf = VIPS_FOREIGN_LOAD_PDF( object );
|
||||
VipsForeignLoadPdfBuffer *buffer = (VipsForeignLoadPdfBuffer *) pdf;
|
||||
|
||||
GError *error = NULL;
|
||||
if( buffer->buf &&
|
||||
!(pdf->source = vips_source_new_from_memory(
|
||||
VIPS_AREA( buffer->buf )->data,
|
||||
VIPS_AREA( buffer->buf )->length )) )
|
||||
return( -1 );
|
||||
|
||||
if( !pdf->doc &&
|
||||
!(pdf->doc = poppler_document_new_from_data(
|
||||
buffer->buf->data, buffer->buf->length, NULL, &error )) ) {
|
||||
vips_g_error( &error );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
return( VIPS_FOREIGN_LOAD_PDF_CLASS(
|
||||
vips_foreign_load_pdf_buffer_parent_class )->open( pdf ) );
|
||||
return( VIPS_OBJECT_CLASS( vips_foreign_load_pdf_buffer_parent_class )->
|
||||
build( object ) );
|
||||
}
|
||||
|
||||
static void
|
||||
@ -734,11 +712,11 @@ vips_foreign_load_pdf_buffer_class_init(
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->nickname = "pdfload_buffer";
|
||||
object_class->description = _( "load PDF from buffer" );
|
||||
object_class->build = vips_foreign_load_pdf_buffer_build;
|
||||
|
||||
load_class->is_a_buffer = vips_foreign_load_pdf_is_a_buffer;
|
||||
|
||||
class->open = vips_foreign_load_pdf_buffer_open;
|
||||
|
||||
VIPS_ARG_BOXED( class, "buffer", 1,
|
||||
_( "Buffer" ),
|
||||
_( "Buffer to load from" ),
|
||||
@ -753,7 +731,77 @@ vips_foreign_load_pdf_buffer_init( VipsForeignLoadPdfBuffer *buffer )
|
||||
{
|
||||
}
|
||||
|
||||
#endif /*HAVE_POPPLER*/
|
||||
typedef struct _VipsForeignLoadPdfSource {
|
||||
VipsForeignLoadPdf parent_object;
|
||||
|
||||
VipsSource *source;
|
||||
|
||||
} VipsForeignLoadPdfSource;
|
||||
|
||||
typedef VipsForeignLoadPdfClass VipsForeignLoadPdfSourceClass;
|
||||
|
||||
G_DEFINE_TYPE( VipsForeignLoadPdfSource, vips_foreign_load_pdf_source,
|
||||
vips_foreign_load_pdf_get_type() );
|
||||
|
||||
static int
|
||||
vips_foreign_load_pdf_source_build( VipsObject *object )
|
||||
{
|
||||
VipsForeignLoadPdf *pdf = VIPS_FOREIGN_LOAD_PDF( object );
|
||||
VipsForeignLoadPdfSource *source = (VipsForeignLoadPdfSource *) pdf;
|
||||
|
||||
if( source->source ) {
|
||||
pdf->source = source->source;
|
||||
g_object_ref( pdf->source );
|
||||
}
|
||||
|
||||
return( VIPS_OBJECT_CLASS( vips_foreign_load_pdf_source_parent_class )->
|
||||
build( object ) );
|
||||
}
|
||||
|
||||
static gboolean
|
||||
vips_foreign_load_pdf_source_is_a_source( VipsSource *source )
|
||||
{
|
||||
const unsigned char *p;
|
||||
|
||||
return( (p = vips_source_sniff( source, 4 )) &&
|
||||
p[0] == '%' &&
|
||||
p[1] == 'P' &&
|
||||
p[2] == 'D' &&
|
||||
p[3] == 'F' );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_pdf_source_class_init(
|
||||
VipsForeignLoadPdfSourceClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->nickname = "pdfload_source";
|
||||
object_class->description = _( "load PDF from source" );
|
||||
object_class->build = vips_foreign_load_pdf_source_build;
|
||||
|
||||
load_class->is_a_source = vips_foreign_load_pdf_source_is_a_source;
|
||||
|
||||
VIPS_ARG_OBJECT( class, "source", 1,
|
||||
_( "Source" ),
|
||||
_( "Source to load from" ),
|
||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||
G_STRUCT_OFFSET( VipsForeignLoadPdfSource, source ),
|
||||
VIPS_TYPE_SOURCE );
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_pdf_source_init( VipsForeignLoadPdfSource *source )
|
||||
{
|
||||
}
|
||||
|
||||
#endif /*defined(HAVE_POPPLER) && defined(HAVE_GIO)*/
|
||||
|
||||
/* Also used by the pdfium loader.
|
||||
*/
|
||||
@ -889,3 +937,36 @@ vips_pdfload_buffer( void *buf, size_t len, VipsImage **out, ... )
|
||||
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 );
|
||||
}
|
||||
|
||||
|
@ -610,6 +610,8 @@ int vips_pdfload( const char *filename, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_pdfload_buffer( void *buf, size_t len, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_pdfload_source( VipsSource *source, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
|
||||
int vips_svgload( const char *filename, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
|
Loading…
Reference in New Issue
Block a user