Merge branch 'master' into new-tiff-save
This commit is contained in:
commit
36eaff0e15
@ -5,6 +5,8 @@
|
|||||||
- 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]
|
||||||
|
- added test_foreign.py, plus more test images
|
||||||
|
|
||||||
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
|
||||||
|
@ -226,6 +226,8 @@ static VImage openslideload( char * filename , VOption *options = 0 )
|
|||||||
throw( VError );
|
throw( VError );
|
||||||
static VImage magickload( char * filename , VOption *options = 0 )
|
static VImage magickload( char * filename , VOption *options = 0 )
|
||||||
throw( VError );
|
throw( VError );
|
||||||
|
static VImage magickload_buffer( VipsBlob * buffer , VOption *options = 0 )
|
||||||
|
throw( VError );
|
||||||
static VImage fitsload( char * filename , VOption *options = 0 )
|
static VImage fitsload( char * filename , VOption *options = 0 )
|
||||||
throw( VError );
|
throw( VError );
|
||||||
static VImage openexrload( char * filename , VOption *options = 0 )
|
static VImage openexrload( char * filename , VOption *options = 0 )
|
||||||
|
@ -1567,6 +1567,19 @@ VImage VImage::magickload( char * filename , VOption *options )
|
|||||||
return( out );
|
return( out );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VImage VImage::magickload_buffer( VipsBlob * buffer , VOption *options )
|
||||||
|
throw( VError )
|
||||||
|
{
|
||||||
|
VImage out;
|
||||||
|
|
||||||
|
call( "magickload_buffer" ,
|
||||||
|
(options ? options : VImage::option()) ->
|
||||||
|
set( "buffer", buffer ) ->
|
||||||
|
set( "out", &out ) );
|
||||||
|
|
||||||
|
return( out );
|
||||||
|
}
|
||||||
|
|
||||||
VImage VImage::fitsload( char * filename , VOption *options )
|
VImage VImage::fitsload( char * filename , VOption *options )
|
||||||
throw( VError )
|
throw( VError )
|
||||||
{
|
{
|
||||||
|
@ -641,6 +641,11 @@
|
|||||||
<entry>load file with ImageMagick</entry>
|
<entry>load file with ImageMagick</entry>
|
||||||
<entry>vips_magickload()</entry>
|
<entry>vips_magickload()</entry>
|
||||||
</row>
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>magickload_buffer</entry>
|
||||||
|
<entry>load image from buffer with ImageMagick</entry>
|
||||||
|
<entry>vips_magickload_buffer()</entry>
|
||||||
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry>fitsload</entry>
|
<entry>fitsload</entry>
|
||||||
<entry>load a FITS image</entry>
|
<entry>load a FITS image</entry>
|
||||||
|
@ -1545,7 +1545,8 @@ vips_foreign_operation_init( void )
|
|||||||
extern GType vips_foreign_load_raw_get_type( void );
|
extern GType vips_foreign_load_raw_get_type( void );
|
||||||
extern GType vips_foreign_save_raw_get_type( void );
|
extern GType vips_foreign_save_raw_get_type( void );
|
||||||
extern GType vips_foreign_save_raw_fd_get_type( void );
|
extern GType vips_foreign_save_raw_fd_get_type( void );
|
||||||
extern GType vips_foreign_load_magick_get_type( void );
|
extern GType vips_foreign_load_magick_file_get_type( void );
|
||||||
|
extern GType vips_foreign_load_magick_buffer_get_type( void );
|
||||||
extern GType vips_foreign_save_dz_get_type( void );
|
extern GType vips_foreign_save_dz_get_type( void );
|
||||||
extern GType vips_foreign_load_webp_file_get_type( void );
|
extern GType vips_foreign_load_webp_file_get_type( void );
|
||||||
extern GType vips_foreign_load_webp_buffer_get_type( void );
|
extern GType vips_foreign_load_webp_buffer_get_type( void );
|
||||||
@ -1609,7 +1610,8 @@ vips_foreign_operation_init( void )
|
|||||||
#endif /*HAVE_OPENSLIDE*/
|
#endif /*HAVE_OPENSLIDE*/
|
||||||
|
|
||||||
#ifdef HAVE_MAGICK
|
#ifdef HAVE_MAGICK
|
||||||
vips_foreign_load_magick_get_type();
|
vips_foreign_load_magick_file_get_type();
|
||||||
|
vips_foreign_load_magick_buffer_get_type();
|
||||||
#endif /*HAVE_MAGICK*/
|
#endif /*HAVE_MAGICK*/
|
||||||
|
|
||||||
#ifdef HAVE_CFITSIO
|
#ifdef HAVE_CFITSIO
|
||||||
@ -1668,6 +1670,48 @@ vips_magickload( const char *filename, VipsImage **out, ... )
|
|||||||
return( result );
|
return( result );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vips_magickload_buffer:
|
||||||
|
* @buf: memory area to load
|
||||||
|
* @len: size of memory area
|
||||||
|
* @out: image to write
|
||||||
|
* @...: %NULL-terminated list of optional named arguments
|
||||||
|
*
|
||||||
|
* Optional arguments:
|
||||||
|
*
|
||||||
|
* @all_frames: %gboolean, load all frames in sequence
|
||||||
|
* @density: string, canvas resolution for rendering vector formats like SVG
|
||||||
|
*
|
||||||
|
* Read an image memory block using libMagick into a VIPS image. Exactly as
|
||||||
|
* vips_magickload(), but read from a memory source.
|
||||||
|
*
|
||||||
|
* 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_magickload().
|
||||||
|
*
|
||||||
|
* Returns: 0 on success, -1 on error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
vips_magickload_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( "magickload_buffer", ap, blob, out );
|
||||||
|
va_end( ap );
|
||||||
|
|
||||||
|
vips_area_unref( VIPS_AREA( blob ) );
|
||||||
|
|
||||||
|
return( result );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* vips_tiffload:
|
* vips_tiffload:
|
||||||
* @filename: file to load
|
* @filename: file to load
|
||||||
|
@ -40,6 +40,11 @@ int vips__magick_read( const char *filename,
|
|||||||
int vips__magick_read_header( const char *filename,
|
int vips__magick_read_header( const char *filename,
|
||||||
VipsImage *out, gboolean all_frames, const char *density );
|
VipsImage *out, gboolean all_frames, const char *density );
|
||||||
|
|
||||||
|
int vips__magick_read_buffer( const void *buf, const size_t len,
|
||||||
|
VipsImage *out, gboolean all_frames, const char *density );
|
||||||
|
int vips__magick_read_buffer_header( const void *buf, const size_t len,
|
||||||
|
VipsImage *out, gboolean all_frames, const char *density );
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /*__cplusplus*/
|
#endif /*__cplusplus*/
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -160,7 +162,7 @@ read_new( const char *filename, VipsImage *im, gboolean all_frames,
|
|||||||
|
|
||||||
if( !(read = VIPS_NEW( im, Read )) )
|
if( !(read = VIPS_NEW( im, Read )) )
|
||||||
return( NULL );
|
return( NULL );
|
||||||
read->filename = g_strdup( filename );
|
read->filename = filename ? g_strdup( filename ) : NULL;
|
||||||
read->all_frames = all_frames;
|
read->all_frames = all_frames;
|
||||||
read->im = im;
|
read->im = im;
|
||||||
read->image = NULL;
|
read->image = NULL;
|
||||||
@ -176,7 +178,9 @@ read_new( const char *filename, VipsImage *im, gboolean all_frames,
|
|||||||
if( !read->image_info )
|
if( !read->image_info )
|
||||||
return( NULL );
|
return( NULL );
|
||||||
|
|
||||||
vips_strncpy( read->image_info->filename, filename, MaxTextExtent );
|
if( filename )
|
||||||
|
vips_strncpy( read->image_info->filename,
|
||||||
|
filename, MaxTextExtent );
|
||||||
|
|
||||||
/* Canvas resolution for rendering vector formats like SVG.
|
/* Canvas resolution for rendering vector formats like SVG.
|
||||||
*/
|
*/
|
||||||
@ -740,5 +744,88 @@ vips__magick_read_header( const char *filename, VipsImage *im,
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
vips__magick_read_buffer( const void *buf, const size_t len, VipsImage *out,
|
||||||
|
gboolean all_frames, const char *density )
|
||||||
|
{
|
||||||
|
Read *read;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf( "magick2vips: vips__magick_read_buffer: %p %zu\n", buf, len );
|
||||||
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
|
if( !(read = read_new( NULL, out, all_frames, density )) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
#ifdef HAVE_SETIMAGEOPTION
|
||||||
|
/* When reading DICOM images, we want to ignore any
|
||||||
|
* window_center/_width setting, since it may put pixels outside the
|
||||||
|
* 0-65535 range and lose data.
|
||||||
|
*
|
||||||
|
* These window settings are attached as vips metadata, so our caller
|
||||||
|
* can interpret them if it wants.
|
||||||
|
*/
|
||||||
|
SetImageOption( read->image_info, "dcm:display-range", "reset" );
|
||||||
|
#endif /*HAVE_SETIMAGEOPTION*/
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf( "magick2vips: calling BlobToImage() ...\n" );
|
||||||
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
|
read->image = BlobToImage( read->image_info,
|
||||||
|
buf, len, &read->exception );
|
||||||
|
if( !read->image ) {
|
||||||
|
vips_error( "magick2vips", _( "unable to read buffer\n"
|
||||||
|
"libMagick error: %s %s" ),
|
||||||
|
read->exception.reason, read->exception.description );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( parse_header( read ) )
|
||||||
|
return( -1 );
|
||||||
|
if( vips_image_generate( out,
|
||||||
|
NULL, magick_fill_region, NULL, read, NULL ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
vips__magick_read_buffer_header( const void *buf, const size_t len,
|
||||||
|
VipsImage *im, gboolean all_frames, const char *density )
|
||||||
|
{
|
||||||
|
Read *read;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf( "vips__magick_read_buffer_header: %p %zu\n", buf, len );
|
||||||
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
|
if( !(read = read_new( NULL, im, all_frames, density )) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf( "vips__magick_read_buffer_header: pinging blob ...\n" );
|
||||||
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
|
read->image = PingBlob( read->image_info, buf, len, &read->exception );
|
||||||
|
if( !read->image ) {
|
||||||
|
vips_error( "magick2vips", _( "unable to ping blob\n"
|
||||||
|
"libMagick error: %s %s" ),
|
||||||
|
read->exception.reason, read->exception.description );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( parse_header( read ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
if( im->Xsize <= 0 ||
|
||||||
|
im->Ysize <= 0 ) {
|
||||||
|
vips_error( "magick2vips", "%s", _( "bad image size" ) );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
#endif /*HAVE_MAGICK*/
|
#endif /*HAVE_MAGICK*/
|
||||||
|
|
||||||
|
@ -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,4 +124,167 @@ 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 {
|
||||||
|
VipsForeignLoadMagick parent_object;
|
||||||
|
|
||||||
|
VipsArea *buf;
|
||||||
|
|
||||||
|
} VipsForeignLoadMagickBuffer;
|
||||||
|
|
||||||
|
typedef VipsForeignLoadMagickClass VipsForeignLoadMagickBufferClass;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE( VipsForeignLoadMagickBuffer, vips_foreign_load_magick_buffer,
|
||||||
|
vips_foreign_load_magick_get_type() );
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
vips_foreign_load_magick_buffer_is_a_buffer ( void* buf, size_t len )
|
||||||
|
{
|
||||||
|
VipsImage *t;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
t = vips_image_new();
|
||||||
|
vips_error_freeze();
|
||||||
|
result = vips__magick_read_buffer_header( buf, len, 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_buffer_header( VipsForeignLoad *load )
|
||||||
|
{
|
||||||
|
VipsForeignLoadMagick *magick = (VipsForeignLoadMagick *) load;
|
||||||
|
VipsForeignLoadMagickBuffer *magick_buffer =
|
||||||
|
(VipsForeignLoadMagickBuffer *) load;
|
||||||
|
|
||||||
|
if( vips__magick_read_buffer(
|
||||||
|
magick_buffer->buf->data, magick_buffer->buf->length,
|
||||||
|
load->out, magick->all_frames, magick->density ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_load_magick_buffer_class_init(
|
||||||
|
VipsForeignLoadMagickBufferClass *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_buffer";
|
||||||
|
object_class->description = _( "load buffer with ImageMagick" );
|
||||||
|
|
||||||
|
load_class->is_a_buffer = vips_foreign_load_magick_buffer_is_a_buffer;
|
||||||
|
load_class->header = vips_foreign_load_magick_buffer_header;
|
||||||
|
load_class->load = NULL;
|
||||||
|
|
||||||
|
VIPS_ARG_BOXED( class, "buffer", 1,
|
||||||
|
_( "Buffer" ),
|
||||||
|
_( "Buffer to load from" ),
|
||||||
|
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsForeignLoadMagickBuffer, buf ),
|
||||||
|
VIPS_TYPE_BLOB );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_load_magick_buffer_init( VipsForeignLoadMagickBuffer *buffer )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
#endif /*HAVE_MAGICK*/
|
#endif /*HAVE_MAGICK*/
|
||||||
|
@ -435,6 +435,8 @@ int vips_matrixprint( VipsImage *in, ... )
|
|||||||
|
|
||||||
int vips_magickload( const char *filename, VipsImage **out, ... )
|
int vips_magickload( const char *filename, VipsImage **out, ... )
|
||||||
__attribute__((sentinel));
|
__attribute__((sentinel));
|
||||||
|
int vips_magickload_buffer( void *buf, size_t len, VipsImage **out, ... )
|
||||||
|
__attribute__((sentinel));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VipsForeignPngFilter:
|
* VipsForeignPngFilter:
|
||||||
|
@ -993,6 +993,7 @@ class_methods = [
|
|||||||
"tiffload_buffer",
|
"tiffload_buffer",
|
||||||
"openslideload",
|
"openslideload",
|
||||||
"magickload",
|
"magickload",
|
||||||
|
"magickload_buffer",
|
||||||
"fitsload",
|
"fitsload",
|
||||||
"openexrload"]
|
"openexrload"]
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ EXTRA_DIST = \
|
|||||||
test_conversion.py \
|
test_conversion.py \
|
||||||
test_convolution.py \
|
test_convolution.py \
|
||||||
test_create.py \
|
test_create.py \
|
||||||
|
test_foreign.py \
|
||||||
test_draw.py \
|
test_draw.py \
|
||||||
test_histogram.py \
|
test_histogram.py \
|
||||||
test_morphology.py \
|
test_morphology.py \
|
||||||
|
BIN
test/images/1.webp
Normal file
BIN
test/images/1.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
BIN
test/images/CMU-1-Small-Region.svs
Normal file
BIN
test/images/CMU-1-Small-Region.svs
Normal file
Binary file not shown.
1814
test/images/WFPC2u5780205r_c0fx.fits
Normal file
1814
test/images/WFPC2u5780205r_c0fx.fits
Normal file
File diff suppressed because one or more lines are too long
BIN
test/images/cramps.gif
Normal file
BIN
test/images/cramps.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
test/images/sample.exr
Normal file
BIN
test/images/sample.exr
Normal file
Binary file not shown.
BIN
test/images/sample.tif
Normal file
BIN
test/images/sample.tif
Normal file
Binary file not shown.
@ -8,6 +8,7 @@ from test_conversion import *
|
|||||||
from test_convolution import *
|
from test_convolution import *
|
||||||
from test_create import *
|
from test_create import *
|
||||||
from test_draw import *
|
from test_draw import *
|
||||||
|
from test_foreign import *
|
||||||
from test_histogram import *
|
from test_histogram import *
|
||||||
from test_morphology import *
|
from test_morphology import *
|
||||||
from test_resample import *
|
from test_resample import *
|
||||||
|
249
test/test_foreign.py
Executable file
249
test/test_foreign.py
Executable file
@ -0,0 +1,249 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
from __future__ import division
|
||||||
|
import unittest
|
||||||
|
import math
|
||||||
|
|
||||||
|
#import logging
|
||||||
|
#logging.basicConfig(level = logging.DEBUG)
|
||||||
|
|
||||||
|
from gi.repository import Vips
|
||||||
|
|
||||||
|
Vips.leak_set(True)
|
||||||
|
|
||||||
|
# an expanding zip ... if either of the args is not a list, duplicate it down
|
||||||
|
# the other
|
||||||
|
def zip_expand(x, y):
|
||||||
|
if isinstance(x, list) and isinstance(y, list):
|
||||||
|
return list(zip(x, y))
|
||||||
|
elif isinstance(x, list):
|
||||||
|
return [[i, y] for i in x]
|
||||||
|
elif isinstance(y, list):
|
||||||
|
return [[x, j] for j in y]
|
||||||
|
else:
|
||||||
|
return [[x, y]]
|
||||||
|
|
||||||
|
class TestForeign(unittest.TestCase):
|
||||||
|
# test a pair of things which can be lists for approx. equality
|
||||||
|
def assertAlmostEqualObjects(self, a, b, places = 4, msg = ''):
|
||||||
|
#print 'assertAlmostEqualObjects %s = %s' % (a, b)
|
||||||
|
for x, y in zip_expand(a, b):
|
||||||
|
self.assertAlmostEqual(x, y, places = places, msg = msg)
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.matlab_file = "images/sample.mat"
|
||||||
|
self.jpeg_file = "images/IMG_4618.jpg"
|
||||||
|
self.png_file = "images/sample.png"
|
||||||
|
self.tiff_file = "images/sample.tif"
|
||||||
|
self.profile_file = "images/sRGB.icm"
|
||||||
|
self.analyze_file = "images/t00740_tr1_segm.hdr"
|
||||||
|
self.gif_file = "images/cramps.gif"
|
||||||
|
self.webp_file = "images/1.webp"
|
||||||
|
self.exr_file = "images/sample.exr"
|
||||||
|
self.fits_file = "images/WFPC2u5780205r_c0fx.fits"
|
||||||
|
self.openslide_file = "images/CMU-1-Small-Region.svs"
|
||||||
|
|
||||||
|
self.colour = Vips.Image.jpegload(self.jpeg_file)
|
||||||
|
self.mono = self.colour.extract_band(1)
|
||||||
|
self.rad = self.colour.float2rad()
|
||||||
|
self.cmyk = self.colour.bandjoin(self.mono)
|
||||||
|
self.cmyk = self.cmyk.copy(interpretation = Vips.Interpretation.CMYK)
|
||||||
|
|
||||||
|
# we have test files for formats which have a clear standard
|
||||||
|
def file_loader(self, loader, test_file, validate):
|
||||||
|
im = Vips.call(loader, test_file)
|
||||||
|
validate(self, im)
|
||||||
|
im = Vips.Image.new_from_file(test_file)
|
||||||
|
validate(self, im)
|
||||||
|
|
||||||
|
def buffer_loader(self, loader, test_file, validate):
|
||||||
|
with open(test_file, 'rb') as f:
|
||||||
|
buf = f.read()
|
||||||
|
|
||||||
|
im = Vips.call(loader, buf)
|
||||||
|
validate(self, im)
|
||||||
|
im = Vips.Image.new_from_buffer(buf, "")
|
||||||
|
validate(self, im)
|
||||||
|
|
||||||
|
def save_load(self, format, im):
|
||||||
|
x = Vips.Image.new_temp_file(format)
|
||||||
|
im.write(x)
|
||||||
|
|
||||||
|
self.assertEqual(im.width, x.width)
|
||||||
|
self.assertEqual(im.height, x.height)
|
||||||
|
self.assertEqual(im.bands, x.bands)
|
||||||
|
max_diff = (im - x).abs().max()
|
||||||
|
self.assertEqual(max_diff, 0)
|
||||||
|
|
||||||
|
def test_jpeg(self):
|
||||||
|
if not Vips.type_find("VipsForeign", "jpegload"):
|
||||||
|
print("no jpeg support in this vips, skipping test")
|
||||||
|
return
|
||||||
|
|
||||||
|
def jpeg_valid(self, im):
|
||||||
|
a = im.getpoint(10, 10)
|
||||||
|
self.assertAlmostEqualObjects(a, [6, 5, 3])
|
||||||
|
profile = im.get_value("icc-profile-data")
|
||||||
|
self.assertEqual(len(profile), 1352)
|
||||||
|
self.assertEqual(im.width, 1024)
|
||||||
|
self.assertEqual(im.height, 768)
|
||||||
|
self.assertEqual(im.bands, 3)
|
||||||
|
|
||||||
|
self.file_loader("jpegload", self.jpeg_file, jpeg_valid)
|
||||||
|
self.buffer_loader("jpegload_buffer", self.jpeg_file, jpeg_valid)
|
||||||
|
self.save_load("%s.jpg", self.mono)
|
||||||
|
self.save_load("%s.jpg", self.colour)
|
||||||
|
|
||||||
|
def test_png(self):
|
||||||
|
if not Vips.type_find("VipsForeign", "pngload"):
|
||||||
|
print("no png support in this vips, skipping test")
|
||||||
|
return
|
||||||
|
|
||||||
|
def png_valid(self, im):
|
||||||
|
a = im.getpoint(10, 10)
|
||||||
|
self.assertAlmostEqualObjects(a, [38671.0, 33914.0, 26762.0])
|
||||||
|
self.assertEqual(im.width, 290)
|
||||||
|
self.assertEqual(im.height, 442)
|
||||||
|
self.assertEqual(im.bands, 3)
|
||||||
|
|
||||||
|
self.file_loader("pngload", self.png_file, png_valid)
|
||||||
|
self.buffer_loader("pngload_buffer", self.png_file, png_valid)
|
||||||
|
self.save_load("%s.png", self.mono)
|
||||||
|
self.save_load("%s.png", self.colour)
|
||||||
|
|
||||||
|
def test_tiff(self):
|
||||||
|
if not Vips.type_find("VipsForeign", "tiffload"):
|
||||||
|
print("no tiff support in this vips, skipping test")
|
||||||
|
return
|
||||||
|
|
||||||
|
def tiff_valid(self, im):
|
||||||
|
a = im.getpoint(10, 10)
|
||||||
|
self.assertAlmostEqualObjects(a, [38671.0, 33914.0, 26762.0])
|
||||||
|
self.assertEqual(im.width, 290)
|
||||||
|
self.assertEqual(im.height, 442)
|
||||||
|
self.assertEqual(im.bands, 3)
|
||||||
|
|
||||||
|
self.file_loader("tiffload", self.tiff_file, tiff_valid)
|
||||||
|
self.buffer_loader("tiffload_buffer", self.tiff_file, tiff_valid)
|
||||||
|
self.save_load("%s.tif", self.mono)
|
||||||
|
self.save_load("%s.tif", self.colour)
|
||||||
|
self.save_load("%s.tif", self.cmyk)
|
||||||
|
|
||||||
|
def test_magickload(self):
|
||||||
|
if not Vips.type_find("VipsForeign", "magickload"):
|
||||||
|
print("no magick support in this vips, skipping test")
|
||||||
|
return
|
||||||
|
|
||||||
|
def gif_valid(self, im):
|
||||||
|
a = im.getpoint(10, 10)
|
||||||
|
self.assertAlmostEqual(a, [33, 33, 33])
|
||||||
|
self.assertEqual(im.width, 159)
|
||||||
|
self.assertEqual(im.height, 203)
|
||||||
|
self.assertEqual(im.bands, 3)
|
||||||
|
|
||||||
|
self.file_loader("magickload", self.gif_file, gif_valid)
|
||||||
|
self.buffer_loader("magickload_buffer", self.gif_file, gif_valid)
|
||||||
|
|
||||||
|
def test_webp(self):
|
||||||
|
if not Vips.type_find("VipsForeign", "webpload"):
|
||||||
|
print("no webp support in this vips, skipping test")
|
||||||
|
return
|
||||||
|
|
||||||
|
def webp_valid(self, im):
|
||||||
|
a = im.getpoint(10, 10)
|
||||||
|
self.assertAlmostEqualObjects(a, [71, 166, 236])
|
||||||
|
self.assertEqual(im.width, 550)
|
||||||
|
self.assertEqual(im.height, 368)
|
||||||
|
self.assertEqual(im.bands, 3)
|
||||||
|
|
||||||
|
self.file_loader("webpload", self.webp_file, webp_valid)
|
||||||
|
self.buffer_loader("webpload_buffer", self.webp_file, webp_valid)
|
||||||
|
self.save_load("%s.webp", self.colour)
|
||||||
|
|
||||||
|
def test_analyzeload(self):
|
||||||
|
def analyze_valid(self, im):
|
||||||
|
a = im.getpoint(10, 10)
|
||||||
|
self.assertAlmostEqual(a[0], 3335)
|
||||||
|
self.assertEqual(im.width, 128)
|
||||||
|
self.assertEqual(im.height, 8064)
|
||||||
|
self.assertEqual(im.bands, 1)
|
||||||
|
|
||||||
|
self.file_loader("analyzeload", self.analyze_file, analyze_valid)
|
||||||
|
|
||||||
|
def test_matload(self):
|
||||||
|
if not Vips.type_find("VipsForeign", "matload"):
|
||||||
|
print("no matlab support in this vips, skipping test")
|
||||||
|
return
|
||||||
|
|
||||||
|
def matlab_valid(self, im):
|
||||||
|
a = im.getpoint(10, 10)
|
||||||
|
self.assertAlmostEqualObjects(a, [38671.0, 33914.0, 26762.0])
|
||||||
|
self.assertEqual(im.width, 290)
|
||||||
|
self.assertEqual(im.height, 442)
|
||||||
|
self.assertEqual(im.bands, 3)
|
||||||
|
|
||||||
|
self.file_loader("matload", self.matlab_file, matlab_valid)
|
||||||
|
|
||||||
|
def test_openexrload(self):
|
||||||
|
if not Vips.type_find("VipsForeign", "openexrload"):
|
||||||
|
print("no openexr support in this vips, skipping test")
|
||||||
|
return
|
||||||
|
|
||||||
|
def exr_valid(self, im):
|
||||||
|
a = im.getpoint(10, 10)
|
||||||
|
self.assertAlmostEqualObjects(a, [0.124512, 0.159668,
|
||||||
|
0.040375, 1.0],
|
||||||
|
places = 5)
|
||||||
|
self.assertEqual(im.width, 610)
|
||||||
|
self.assertEqual(im.height, 406)
|
||||||
|
self.assertEqual(im.bands, 4)
|
||||||
|
|
||||||
|
self.file_loader("openexrload", self.exr_file, exr_valid)
|
||||||
|
|
||||||
|
def test_fitsload(self):
|
||||||
|
if not Vips.type_find("VipsForeign", "fitsload"):
|
||||||
|
print("no fits support in this vips, skipping test")
|
||||||
|
return
|
||||||
|
|
||||||
|
def fits_valid(self, im):
|
||||||
|
a = im.getpoint(10, 10)
|
||||||
|
self.assertAlmostEqualObjects(a, [-0.165013, -0.148553, 1.09122,
|
||||||
|
-0.942242],
|
||||||
|
places = 5)
|
||||||
|
self.assertEqual(im.width, 200)
|
||||||
|
self.assertEqual(im.height, 200)
|
||||||
|
self.assertEqual(im.bands, 4)
|
||||||
|
|
||||||
|
self.file_loader("fitsload", self.fits_file, fits_valid)
|
||||||
|
self.save_load("%s.fits", self.mono)
|
||||||
|
|
||||||
|
def test_openslideload(self):
|
||||||
|
if not Vips.type_find("VipsForeign", "openslideload"):
|
||||||
|
print("no openslide support in this vips, skipping test")
|
||||||
|
return
|
||||||
|
|
||||||
|
def openslide_valid(self, im):
|
||||||
|
a = im.getpoint(10, 10)
|
||||||
|
self.assertAlmostEqualObjects(a, [244, 250, 243, 255])
|
||||||
|
self.assertEqual(im.width, 2220)
|
||||||
|
self.assertEqual(im.height, 2967)
|
||||||
|
self.assertEqual(im.bands, 4)
|
||||||
|
|
||||||
|
self.file_loader("openslideload", self.openslide_file, openslide_valid)
|
||||||
|
|
||||||
|
def test_csv(self):
|
||||||
|
self.save_load("%s.csv", self.mono)
|
||||||
|
|
||||||
|
def test_matrix(self):
|
||||||
|
self.save_load("%s.mat", self.mono)
|
||||||
|
|
||||||
|
def test_ppm(self):
|
||||||
|
self.save_load("%s.ppm", self.mono)
|
||||||
|
self.save_load("%s.ppm", self.colour)
|
||||||
|
|
||||||
|
def test_rad(self):
|
||||||
|
self.save_load("%s.hdr", self.colour)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
|
|
@ -1,5 +1,8 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
# this has now been mostly superceeded by test_foreign.py ... keep this around
|
||||||
|
# as a test of the command-line interface
|
||||||
|
|
||||||
# set -x
|
# set -x
|
||||||
|
|
||||||
. ./variables.sh
|
. ./variables.sh
|
||||||
|
Loading…
x
Reference in New Issue
Block a user