add png load from buffer
though untested as yet
This commit is contained in:
parent
1dbff8f5c0
commit
005984226e
@ -1583,6 +1583,7 @@ vips_foreign_operation_init( void )
|
|||||||
extern GType vips_foreign_load_ppm_get_type( void );
|
extern GType vips_foreign_load_ppm_get_type( void );
|
||||||
extern GType vips_foreign_save_ppm_get_type( void );
|
extern GType vips_foreign_save_ppm_get_type( void );
|
||||||
extern GType vips_foreign_load_png_get_type( void );
|
extern GType vips_foreign_load_png_get_type( void );
|
||||||
|
extern GType vips_foreign_load_png_buffer_get_type( void );
|
||||||
extern GType vips_foreign_save_png_file_get_type( void );
|
extern GType vips_foreign_save_png_file_get_type( void );
|
||||||
extern GType vips_foreign_save_png_buffer_get_type( void );
|
extern GType vips_foreign_save_png_buffer_get_type( void );
|
||||||
extern GType vips_foreign_load_csv_get_type( void );
|
extern GType vips_foreign_load_csv_get_type( void );
|
||||||
@ -1623,6 +1624,7 @@ vips_foreign_operation_init( void )
|
|||||||
|
|
||||||
#ifdef HAVE_PNG
|
#ifdef HAVE_PNG
|
||||||
vips_foreign_load_png_get_type();
|
vips_foreign_load_png_get_type();
|
||||||
|
vips_foreign_load_png_buffer_get_type();
|
||||||
vips_foreign_save_png_file_get_type();
|
vips_foreign_save_png_file_get_type();
|
||||||
vips_foreign_save_png_buffer_get_type();
|
vips_foreign_save_png_buffer_get_type();
|
||||||
#endif /*HAVE_PNG*/
|
#endif /*HAVE_PNG*/
|
||||||
@ -2224,6 +2226,47 @@ vips_pngload( const char *filename, VipsImage **out, ... )
|
|||||||
return( result );
|
return( result );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vips_pngload_buffer:
|
||||||
|
* @buf: memory area to load
|
||||||
|
* @len: size of memory area
|
||||||
|
* @out: image to write
|
||||||
|
* @...: %NULL-terminated list of optional named arguments
|
||||||
|
*
|
||||||
|
* Read a PNG-formatted memory block into a VIPS image. It can read all png
|
||||||
|
* images, including 8- and 16-bit images, 1 and 3 channel, with and without
|
||||||
|
* an alpha channel.
|
||||||
|
*
|
||||||
|
* Any ICC profile is read and attached to the VIPS image.
|
||||||
|
*
|
||||||
|
* Caution: on return only the header will have been read, the pixel data is
|
||||||
|
* not decompressed until the first pixel is read. Therefore you must not free
|
||||||
|
* @buf until you have read pixel data from @out.
|
||||||
|
*
|
||||||
|
* See also: vips_pngload().
|
||||||
|
*
|
||||||
|
* Returns: 0 on success, -1 on error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
vips_pngload_buffer( void *buf, size_t len, VipsImage **out, ... )
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
VipsArea *area;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
/* We don't take a copy of the data or free it.
|
||||||
|
*/
|
||||||
|
area = vips_area_new_blob( NULL, buf, len );
|
||||||
|
|
||||||
|
va_start( ap, out );
|
||||||
|
result = vips_call_split( "pngload_buffer", ap, area, out );
|
||||||
|
va_end( ap );
|
||||||
|
|
||||||
|
vips_area_unref( area );
|
||||||
|
|
||||||
|
return( result );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* vips_pngsave:
|
* vips_pngsave:
|
||||||
* @in: image to save
|
* @in: image to save
|
||||||
|
@ -73,9 +73,9 @@ vips_foreign_load_png_get_flags_filename( const char *filename )
|
|||||||
|
|
||||||
flags = 0;
|
flags = 0;
|
||||||
if( vips__png_isinterlaced( filename ) )
|
if( vips__png_isinterlaced( filename ) )
|
||||||
flags = VIPS_FOREIGN_PARTIAL;
|
flags |= VIPS_FOREIGN_PARTIAL;
|
||||||
else
|
else
|
||||||
flags = VIPS_FOREIGN_SEQUENTIAL;
|
flags |= VIPS_FOREIGN_SEQUENTIAL;
|
||||||
|
|
||||||
return( flags );
|
return( flags );
|
||||||
}
|
}
|
||||||
@ -146,4 +146,72 @@ vips_foreign_load_png_init( VipsForeignLoadPng *png )
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct _VipsForeignLoadPngBuffer {
|
||||||
|
VipsForeignLoad parent_object;
|
||||||
|
|
||||||
|
/* Load from a buffer.
|
||||||
|
*/
|
||||||
|
VipsArea *buf;
|
||||||
|
|
||||||
|
} VipsForeignLoadPngBuffer;
|
||||||
|
|
||||||
|
typedef VipsForeignLoadClass VipsForeignLoadPngBufferClass;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE( VipsForeignLoadPngBuffer, vips_foreign_load_png_buffer,
|
||||||
|
VIPS_TYPE_FOREIGN_LOAD );
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_load_png_buffer_header( VipsForeignLoad *load )
|
||||||
|
{
|
||||||
|
VipsForeignLoadPngBuffer *png = (VipsForeignLoadPngBuffer *) load;
|
||||||
|
|
||||||
|
if( vips__png_header_buffer( load->out,
|
||||||
|
png->buf->data, png->buf->length ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_load_png_buffer_load( VipsForeignLoad *load )
|
||||||
|
{
|
||||||
|
VipsForeignLoadPngBuffer *png = (VipsForeignLoadPngBuffer *) load;
|
||||||
|
|
||||||
|
if( vips__png_read_buffer( load->out,
|
||||||
|
png->buf->data, png->buf->length ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_load_png_buffer_class_init( VipsForeignLoadPngBufferClass *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 = "pngload_buffer";
|
||||||
|
object_class->description = _( "load png from buffer" );
|
||||||
|
|
||||||
|
load_class->header = vips_foreign_load_png_buffer_header;
|
||||||
|
load_class->load = vips_foreign_load_png_buffer_load;
|
||||||
|
|
||||||
|
VIPS_ARG_BOXED( class, "buffer", 1,
|
||||||
|
_( "Buffer" ),
|
||||||
|
_( "Buffer to load from" ),
|
||||||
|
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsForeignLoadPngBuffer, buf ),
|
||||||
|
VIPS_TYPE_BLOB );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_load_png_buffer_init( VipsForeignLoadPngBuffer *png )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
#endif /*HAVE_PNG*/
|
#endif /*HAVE_PNG*/
|
||||||
|
|
||||||
|
@ -125,11 +125,20 @@ typedef struct {
|
|||||||
char *name;
|
char *name;
|
||||||
VipsImage *out;
|
VipsImage *out;
|
||||||
|
|
||||||
FILE *fp;
|
|
||||||
int y_pos;
|
int y_pos;
|
||||||
png_structp pPng;
|
png_structp pPng;
|
||||||
png_infop pInfo;
|
png_infop pInfo;
|
||||||
png_bytep *row_pointer;
|
png_bytep *row_pointer;
|
||||||
|
|
||||||
|
/* For FILE input.
|
||||||
|
*/
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
/* For memory input.
|
||||||
|
*/
|
||||||
|
char *buffer;
|
||||||
|
size_t length;
|
||||||
|
size_t read_pos;
|
||||||
} Read;
|
} Read;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -142,27 +151,27 @@ read_destroy( VipsImage *out, Read *read )
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Read *
|
static Read *
|
||||||
read_new( const char *name, VipsImage *out )
|
read_new( VipsImage *out )
|
||||||
{
|
{
|
||||||
Read *read;
|
Read *read;
|
||||||
|
|
||||||
if( !(read = VIPS_NEW( out, Read )) )
|
if( !(read = VIPS_NEW( out, Read )) )
|
||||||
return( NULL );
|
return( NULL );
|
||||||
|
|
||||||
read->name = vips_strdup( VIPS_OBJECT( out ), name );
|
read->name = NULL;
|
||||||
read->out = out;
|
read->out = out;
|
||||||
read->fp = NULL;
|
|
||||||
read->y_pos = 0;
|
read->y_pos = 0;
|
||||||
read->pPng = NULL;
|
read->pPng = NULL;
|
||||||
read->pInfo = NULL;
|
read->pInfo = NULL;
|
||||||
read->row_pointer = NULL;
|
read->row_pointer = NULL;
|
||||||
|
read->fp = NULL;
|
||||||
|
read->buffer = NULL;
|
||||||
|
read->length = 0;
|
||||||
|
read->read_pos = 0;
|
||||||
|
|
||||||
g_signal_connect( out, "close",
|
g_signal_connect( out, "close",
|
||||||
G_CALLBACK( read_destroy ), read );
|
G_CALLBACK( read_destroy ), read );
|
||||||
|
|
||||||
if( !(read->fp = vips__file_open_read( name, NULL, FALSE )) )
|
|
||||||
return( NULL );
|
|
||||||
|
|
||||||
if( !(read->pPng = png_create_read_struct(
|
if( !(read->pPng = png_create_read_struct(
|
||||||
PNG_LIBPNG_VER_STRING, NULL,
|
PNG_LIBPNG_VER_STRING, NULL,
|
||||||
user_error_function, user_warning_function )) )
|
user_error_function, user_warning_function )) )
|
||||||
@ -176,6 +185,22 @@ read_new( const char *name, VipsImage *out )
|
|||||||
if( !(read->pInfo = png_create_info_struct( read->pPng )) )
|
if( !(read->pInfo = png_create_info_struct( read->pPng )) )
|
||||||
return( NULL );
|
return( NULL );
|
||||||
|
|
||||||
|
return( read );
|
||||||
|
}
|
||||||
|
|
||||||
|
static Read *
|
||||||
|
read_new_filename( VipsImage *out, const char *name )
|
||||||
|
{
|
||||||
|
Read *read;
|
||||||
|
|
||||||
|
if( !(read = read_new( out )) )
|
||||||
|
return( NULL );
|
||||||
|
|
||||||
|
read->name = vips_strdup( VIPS_OBJECT( out ), name );
|
||||||
|
|
||||||
|
if( !(read->fp = vips__file_open_read( name, NULL, FALSE )) )
|
||||||
|
return( NULL );
|
||||||
|
|
||||||
/* Read enough of the file that png_get_interlace_type() will start
|
/* Read enough of the file that png_get_interlace_type() will start
|
||||||
* working.
|
* working.
|
||||||
*/
|
*/
|
||||||
@ -366,7 +391,7 @@ vips__png_header( const char *name, VipsImage *out )
|
|||||||
{
|
{
|
||||||
Read *read;
|
Read *read;
|
||||||
|
|
||||||
if( !(read = read_new( name, out )) ||
|
if( !(read = read_new_filename( out, name )) ||
|
||||||
png2vips_header( read, out ) )
|
png2vips_header( read, out ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
@ -465,7 +490,7 @@ vips__png_isinterlaced( const char *filename )
|
|||||||
int interlace_type;
|
int interlace_type;
|
||||||
|
|
||||||
image = vips_image_new();
|
image = vips_image_new();
|
||||||
if( !(read = read_new( filename, image )) ) {
|
if( !(read = read_new_filename( image, filename )) ) {
|
||||||
g_object_unref( image );
|
g_object_unref( image );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
@ -475,24 +500,13 @@ vips__png_isinterlaced( const char *filename )
|
|||||||
return( interlace_type != PNG_INTERLACE_NONE );
|
return( interlace_type != PNG_INTERLACE_NONE );
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
vips__png_read( const char *filename, VipsImage *out )
|
read_all( Read *read, VipsImage *out )
|
||||||
{
|
{
|
||||||
|
int interlace_type = png_get_interlace_type( read->pPng, read->pInfo );
|
||||||
VipsImage **t = (VipsImage **)
|
VipsImage **t = (VipsImage **)
|
||||||
vips_object_local_array( VIPS_OBJECT( out ), 3 );
|
vips_object_local_array( VIPS_OBJECT( out ), 3 );
|
||||||
|
|
||||||
Read *read;
|
|
||||||
int interlace_type;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf( "vips__png_read: reading \"%s\"\n", filename );
|
|
||||||
#endif /*DEBUG*/
|
|
||||||
|
|
||||||
if( !(read = read_new( filename, out )) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
interlace_type = png_get_interlace_type( read->pPng, read->pInfo );
|
|
||||||
|
|
||||||
if( interlace_type != PNG_INTERLACE_NONE ) {
|
if( interlace_type != PNG_INTERLACE_NONE ) {
|
||||||
/* Arg awful interlaced image. We have to load to a huge mem
|
/* Arg awful interlaced image. We have to load to a huge mem
|
||||||
* buffer, then copy to out.
|
* buffer, then copy to out.
|
||||||
@ -516,6 +530,22 @@ vips__png_read( const char *filename, VipsImage *out )
|
|||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
vips__png_read( const char *filename, VipsImage *out )
|
||||||
|
{
|
||||||
|
Read *read;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf( "vips__png_read: reading \"%s\"\n", filename );
|
||||||
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
|
if( !(read = read_new_filename( out, filename )) ||
|
||||||
|
read_all( read, out ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf( "vips__png_read: done\n" );
|
printf( "vips__png_read: done\n" );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
@ -532,6 +562,63 @@ vips__png_ispng( const char *filename )
|
|||||||
!png_sig_cmp( buf, 0, 8 ) );
|
!png_sig_cmp( buf, 0, 8 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_png_read_buffer( png_structp pPng, png_bytep data, png_size_t length )
|
||||||
|
{
|
||||||
|
Read *read = png_get_io_ptr( pPng );
|
||||||
|
|
||||||
|
if( read->read_pos + length > read->length )
|
||||||
|
png_error( pPng, "not enough data in buffer" );
|
||||||
|
|
||||||
|
memcpy( data, read->buffer + read->read_pos, length );
|
||||||
|
read->read_pos += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Read *
|
||||||
|
read_new_buffer( VipsImage *out, char *buffer, size_t length )
|
||||||
|
{
|
||||||
|
Read *read;
|
||||||
|
|
||||||
|
if( !(read = read_new( out )) )
|
||||||
|
return( NULL );
|
||||||
|
|
||||||
|
read->buffer = buffer;
|
||||||
|
read->length = length;
|
||||||
|
|
||||||
|
png_set_read_fn( read->pPng, read, vips_png_read_buffer );
|
||||||
|
|
||||||
|
/* Read enough of the file that png_get_interlace_type() will start
|
||||||
|
* working.
|
||||||
|
*/
|
||||||
|
png_read_info( read->pPng, read->pInfo );
|
||||||
|
|
||||||
|
return( read );
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
vips__png_header_buffer( VipsImage *out, char *buffer, size_t length )
|
||||||
|
{
|
||||||
|
Read *read;
|
||||||
|
|
||||||
|
if( !(read = read_new_buffer( out, buffer, length )) ||
|
||||||
|
png2vips_header( read, out ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
vips__png_read_buffer( VipsImage *out, char *buffer, size_t length )
|
||||||
|
{
|
||||||
|
Read *read;
|
||||||
|
|
||||||
|
if( !(read = read_new_buffer( out, buffer, length )) ||
|
||||||
|
read_all( read, out ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
const char *vips__png_suffs[] = { ".png", NULL };
|
const char *vips__png_suffs[] = { ".png", NULL };
|
||||||
|
|
||||||
/* What we track during a PNG write.
|
/* What we track during a PNG write.
|
||||||
|
@ -40,6 +40,8 @@ int vips__png_read( const char *name, VipsImage *out );
|
|||||||
int vips__png_ispng( const char *filename );
|
int vips__png_ispng( const char *filename );
|
||||||
gboolean vips__png_isinterlaced( const char *filename );
|
gboolean vips__png_isinterlaced( const char *filename );
|
||||||
extern const char *vips__png_suffs[];
|
extern const char *vips__png_suffs[];
|
||||||
|
int vips__png_read_buffer( VipsImage *out, char *buffer, size_t length );
|
||||||
|
int vips__png_header_buffer( VipsImage *out, char *buffer, size_t length );
|
||||||
|
|
||||||
int vips__png_write( VipsImage *in, const char *filename,
|
int vips__png_write( VipsImage *in, const char *filename,
|
||||||
int compress, int interlace );
|
int compress, int interlace );
|
||||||
|
@ -407,6 +407,8 @@ int vips_magickload( const char *filename, VipsImage **out, ... )
|
|||||||
|
|
||||||
int vips_pngload( const char *filename, VipsImage **out, ... )
|
int vips_pngload( const char *filename, VipsImage **out, ... )
|
||||||
__attribute__((sentinel));
|
__attribute__((sentinel));
|
||||||
|
int vips_pngload_buffer( void *buf, size_t len, VipsImage **out, ... )
|
||||||
|
__attribute__((sentinel));
|
||||||
int vips_pngsave( VipsImage *in, const char *filename, ... )
|
int vips_pngsave( VipsImage *in, const char *filename, ... )
|
||||||
__attribute__((sentinel));
|
__attribute__((sentinel));
|
||||||
int vips_pngsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
|
int vips_pngsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
|
||||||
|
Loading…
x
Reference in New Issue
Block a user