small cleanups

split magicload up into a base class plus file and buffer subclasses

magickload_buffer should do all reading in header method
This commit is contained in:
John Cupitt 2015-02-16 10:45:56 +00:00
parent 972bb41012
commit 99b4bcb838
4 changed files with 116 additions and 109 deletions

View File

@ -5,6 +5,7 @@
- add shift option to cast - add shift option to cast
- sRGB2scRGB and scRGB2sRGB scale 16-bit alpha to and from 8-bit - sRGB2scRGB and scRGB2sRGB scale 16-bit alpha to and from 8-bit
- tiff pyramid writer no longer copies base image - tiff pyramid writer no longer copies base image
- add magicload_buffer() [mcuelenaere]
6/2/15 started 7.42.3 6/2/15 started 7.42.3
- bump version for back-compat ABI change - bump version for back-compat ABI change

View File

@ -1674,7 +1674,7 @@ vips_magickload( const char *filename, VipsImage **out, ... )
* vips_magickload_buffer: * vips_magickload_buffer:
* @buf: memory area to load * @buf: memory area to load
* @len: size of memory area * @len: size of memory area
* @out: decompressed image * @out: image to write
* @...: %NULL-terminated list of optional named arguments * @...: %NULL-terminated list of optional named arguments
* *
* Optional arguments: * Optional arguments:

View File

@ -42,6 +42,8 @@
* - add @all_frames option, off by default * - add @all_frames option, off by default
* 4/12/14 Lovell * 4/12/14 Lovell
* - add @density option * - add @density option
* 16/2/15 mcuelenaere
* - add blob read
*/ */
/* /*
@ -176,9 +178,9 @@ read_new( const char *filename, VipsImage *im, gboolean all_frames,
if( !read->image_info ) if( !read->image_info )
return( NULL ); return( NULL );
if (filename) { if( filename )
vips_strncpy( read->image_info->filename, filename, MaxTextExtent ); vips_strncpy( read->image_info->filename,
} filename, MaxTextExtent );
/* Canvas resolution for rendering vector formats like SVG. /* Canvas resolution for rendering vector formats like SVG.
*/ */
@ -770,7 +772,8 @@ vips__magick_read_buffer( const void *buf, const size_t len, VipsImage *out,
printf( "magick2vips: calling BlobToImage() ...\n" ); printf( "magick2vips: calling BlobToImage() ...\n" );
#endif /*DEBUG*/ #endif /*DEBUG*/
read->image = BlobToImage( read->image_info, buf, len, &read->exception ); read->image = BlobToImage( read->image_info,
buf, len, &read->exception );
if( !read->image ) { if( !read->image ) {
vips_error( "magick2vips", _( "unable to read buffer\n" vips_error( "magick2vips", _( "unable to read buffer\n"
"libMagick error: %s %s" ), "libMagick error: %s %s" ),
@ -815,7 +818,8 @@ vips__magick_read_buffer_header( const void *buf, const size_t len,
if( parse_header( read ) ) if( parse_header( read ) )
return( -1 ); return( -1 );
if( im->Xsize <= 0 || im->Ysize <= 0 ) { if( im->Xsize <= 0 ||
im->Ysize <= 0 ) {
vips_error( "magick2vips", "%s", _( "bad image size" ) ); vips_error( "magick2vips", "%s", _( "bad image size" ) );
return( -1 ); return( -1 );
} }

View File

@ -59,7 +59,6 @@
typedef struct _VipsForeignLoadMagick { typedef struct _VipsForeignLoadMagick {
VipsForeignLoad parent_object; VipsForeignLoad parent_object;
char *filename;
gboolean all_frames; gboolean all_frames;
char *density; char *density;
@ -67,24 +66,9 @@ typedef struct _VipsForeignLoadMagick {
typedef VipsForeignLoadClass VipsForeignLoadMagickClass; typedef VipsForeignLoadClass VipsForeignLoadMagickClass;
G_DEFINE_TYPE( VipsForeignLoadMagick, vips_foreign_load_magick, G_DEFINE_ABSTRACT_TYPE( VipsForeignLoadMagick, vips_foreign_load_magick,
VIPS_TYPE_FOREIGN_LOAD ); VIPS_TYPE_FOREIGN_LOAD );
static gboolean
ismagick( const char *filename )
{
VipsImage *t;
int result;
t = vips_image_new();
vips_error_freeze();
result = vips__magick_read_header( filename, t, FALSE, NULL );
g_object_unref( t );
vips_error_thaw();
return( result == 0 );
}
static VipsForeignFlags static VipsForeignFlags
vips_foreign_load_magick_get_flags_filename( const char *filename ) vips_foreign_load_magick_get_flags_filename( const char *filename )
{ {
@ -94,32 +78,7 @@ vips_foreign_load_magick_get_flags_filename( const char *filename )
static VipsForeignFlags static VipsForeignFlags
vips_foreign_load_magick_get_flags( VipsForeignLoad *load ) vips_foreign_load_magick_get_flags( VipsForeignLoad *load )
{ {
VipsForeignLoadMagick *magick = (VipsForeignLoadMagick *) load; return( VIPS_FOREIGN_PARTIAL );
return( vips_foreign_load_magick_get_flags_filename(
magick->filename ) );
}
/*
* Unfortunately, libMagick does not support header-only reads very well. See
*
* http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=20017
*
* Test especially with BMP, GIF, TGA. So we are forced to read the entire
* image in the @header() method.
*/
static int
vips_foreign_load_magick_header( VipsForeignLoad *load )
{
VipsForeignLoadMagick *magick = (VipsForeignLoadMagick *) load;
if( vips__magick_read( magick->filename,
load->out, magick->all_frames, magick->density ) )
return( -1 );
VIPS_SETSTR( load->out->filename, magick->filename );
return( 0 );
} }
static void static void
@ -133,27 +92,17 @@ vips_foreign_load_magick_class_init( VipsForeignLoadMagickClass *class )
gobject_class->set_property = vips_object_set_property; gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property; gobject_class->get_property = vips_object_get_property;
object_class->nickname = "magickload"; object_class->nickname = "magickload_base";
object_class->description = _( "load file with ImageMagick" ); object_class->description = _( "load with ImageMagick" );
/* We need to be well to the back of the queue since the vips's /* We need to be well to the back of the queue since vips's
* dedicated loaders are usually preferable. * dedicated loaders are usually preferable.
*/ */
foreign_class->priority = -100; foreign_class->priority = -100;
load_class->is_a = ismagick;
load_class->get_flags_filename = load_class->get_flags_filename =
vips_foreign_load_magick_get_flags_filename; vips_foreign_load_magick_get_flags_filename;
load_class->get_flags = vips_foreign_load_magick_get_flags; load_class->get_flags = vips_foreign_load_magick_get_flags;
load_class->header = vips_foreign_load_magick_header;
load_class->load = NULL;
VIPS_ARG_STRING( class, "filename", 1,
_( "Filename" ),
_( "Filename to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadMagick, filename ),
NULL );
VIPS_ARG_BOOL( class, "all_frames", 3, VIPS_ARG_BOOL( class, "all_frames", 3,
_( "all_frames" ), _( "all_frames" ),
@ -175,19 +124,99 @@ vips_foreign_load_magick_init( VipsForeignLoadMagick *magick )
{ {
} }
typedef struct _VipsForeignLoadMagickFile {
VipsForeignLoadMagick parent_object;
char *filename;
} VipsForeignLoadMagickFile;
typedef VipsForeignLoadMagickClass VipsForeignLoadMagickFileClass;
G_DEFINE_TYPE( VipsForeignLoadMagickFile, vips_foreign_load_magick_file,
vips_foreign_load_magick_get_type() );
static gboolean
ismagick( const char *filename )
{
VipsImage *t;
int result;
t = vips_image_new();
vips_error_freeze();
result = vips__magick_read_header( filename, t, FALSE, NULL );
g_object_unref( t );
vips_error_thaw();
return( result == 0 );
}
/* Unfortunately, libMagick does not support header-only reads very well. See
*
* http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=20017
*
* Test especially with BMP, GIF, TGA. So we are forced to read the entire
* image in the @header() method.
*/
static int
vips_foreign_load_magick_file_header( VipsForeignLoad *load )
{
VipsForeignLoadMagick *magick = (VipsForeignLoadMagick *) load;
VipsForeignLoadMagickFile *magick_file =
(VipsForeignLoadMagickFile *) load;
if( vips__magick_read( magick_file->filename,
load->out, magick->all_frames, magick->density ) )
return( -1 );
VIPS_SETSTR( load->out->filename, magick_file->filename );
return( 0 );
}
static void
vips_foreign_load_magick_file_class_init(
VipsForeignLoadMagickFileClass *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 = "magickload";
object_class->description = _( "load file with ImageMagick" );
load_class->is_a = ismagick;
load_class->header = vips_foreign_load_magick_file_header;
load_class->load = NULL;
VIPS_ARG_STRING( class, "filename", 1,
_( "Filename" ),
_( "Filename to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadMagickFile, filename ),
NULL );
}
static void
vips_foreign_load_magick_file_init( VipsForeignLoadMagickFile *magick_file )
{
}
typedef struct _VipsForeignLoadMagickBuffer { typedef struct _VipsForeignLoadMagickBuffer {
VipsForeignLoad parent_object; VipsForeignLoadMagick parent_object;
VipsArea *buf; VipsArea *buf;
gboolean all_frames;
char *density;
} VipsForeignLoadMagickBuffer; } VipsForeignLoadMagickBuffer;
typedef VipsForeignLoadClass VipsForeignLoadMagickBufferClass; typedef VipsForeignLoadMagickClass VipsForeignLoadMagickBufferClass;
G_DEFINE_TYPE( VipsForeignLoadMagickBuffer, vips_foreign_load_magick_buffer, G_DEFINE_TYPE( VipsForeignLoadMagickBuffer, vips_foreign_load_magick_buffer,
VIPS_TYPE_FOREIGN_LOAD ); vips_foreign_load_magick_get_type() );
static gboolean static gboolean
vips_foreign_load_magick_buffer_is_a_buffer ( void* buf, size_t len ) vips_foreign_load_magick_buffer_is_a_buffer ( void* buf, size_t len )
@ -204,42 +233,34 @@ vips_foreign_load_magick_buffer_is_a_buffer ( void* buf, size_t len )
return( result == 0 ); return( result == 0 );
} }
static VipsForeignFlags /* Unfortunately, libMagick does not support header-only reads very well. See
vips_foreign_load_magick_buffer_get_flags( VipsForeignLoad *load ) *
{ * http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=20017
return( VIPS_FOREIGN_PARTIAL ); *
} * Test especially with BMP, GIF, TGA. So we are forced to read the entire
* image in the @header() method.
*/
static int static int
vips_foreign_load_magick_buffer_header( VipsForeignLoad *load ) vips_foreign_load_magick_buffer_header( VipsForeignLoad *load )
{ {
VipsForeignLoadMagickBuffer *magick = (VipsForeignLoadMagickBuffer *) load; VipsForeignLoadMagick *magick = (VipsForeignLoadMagick *) load;
VipsForeignLoadMagickBuffer *magick_buffer =
(VipsForeignLoadMagickBuffer *) load;
if( vips__magick_read_buffer_header( magick->buf->data, magick->buf->length, if( vips__magick_read_buffer(
magick_buffer->buf->data, magick_buffer->buf->length,
load->out, magick->all_frames, magick->density ) ) load->out, magick->all_frames, magick->density ) )
return( -1 ); return( -1 );
return( 0 ); return( 0 );
} }
static int
vips_foreign_load_magick_buffer_load( VipsForeignLoad *load )
{
VipsForeignLoadMagickBuffer *magick = (VipsForeignLoadMagickBuffer *) load;
if( vips__magick_read_buffer( magick->buf->data, magick->buf->length,
load->real, magick->all_frames, magick->density ) )
return( -1 );
return( 0 );
}
static void static void
vips_foreign_load_magick_buffer_class_init( VipsForeignLoadMagickBufferClass *class ) vips_foreign_load_magick_buffer_class_init(
VipsForeignLoadMagickBufferClass *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;
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class; VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
gobject_class->set_property = vips_object_set_property; gobject_class->set_property = vips_object_set_property;
@ -248,15 +269,9 @@ vips_foreign_load_magick_buffer_class_init( VipsForeignLoadMagickBufferClass *cl
object_class->nickname = "magickload_buffer"; object_class->nickname = "magickload_buffer";
object_class->description = _( "load buffer with ImageMagick" ); object_class->description = _( "load buffer with ImageMagick" );
/* We need to be well to the back of the queue since the vips's
* dedicated loaders are usually preferable.
*/
foreign_class->priority = -100;
load_class->is_a_buffer = vips_foreign_load_magick_buffer_is_a_buffer; load_class->is_a_buffer = vips_foreign_load_magick_buffer_is_a_buffer;
load_class->get_flags = vips_foreign_load_magick_buffer_get_flags;
load_class->header = vips_foreign_load_magick_buffer_header; load_class->header = vips_foreign_load_magick_buffer_header;
load_class->load = vips_foreign_load_magick_buffer_load; load_class->load = NULL;
VIPS_ARG_BOXED( class, "buffer", 1, VIPS_ARG_BOXED( class, "buffer", 1,
_( "Buffer" ), _( "Buffer" ),
@ -265,19 +280,6 @@ vips_foreign_load_magick_buffer_class_init( VipsForeignLoadMagickBufferClass *cl
G_STRUCT_OFFSET( VipsForeignLoadMagickBuffer, buf ), G_STRUCT_OFFSET( VipsForeignLoadMagickBuffer, buf ),
VIPS_TYPE_BLOB ); VIPS_TYPE_BLOB );
VIPS_ARG_BOOL( class, "all_frames", 3,
_( "all_frames" ),
_( "Read all frames from an image" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadMagickBuffer, all_frames ),
FALSE );
VIPS_ARG_STRING( class, "density", 4,
_( "Density" ),
_( "Canvas resolution for rendering vector formats like SVG" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadMagickBuffer, density ),
NULL );
} }
static void static void