seems to work, needs more testing
This commit is contained in:
parent
40f8a8af85
commit
a5d9cf204c
@ -27,6 +27,7 @@
|
||||
- better quality for vips_resize() with linear/cubic kernels
|
||||
- pyvips8 can create new metadata
|
||||
- better upsizing with vips_resize()
|
||||
- add imagemagick v7 support, thanks sachinwalia2k8
|
||||
|
||||
18/5/16 started 8.3.2
|
||||
- more robust vips image reading
|
||||
|
@ -1760,6 +1760,11 @@ vips_foreign_operation_init( void )
|
||||
vips_foreign_load_magick_buffer_get_type();
|
||||
#endif /*HAVE_MAGICK*/
|
||||
|
||||
#ifdef HAVE_MAGICK7
|
||||
vips_foreign_load_magick7_file_get_type();
|
||||
vips_foreign_load_magick7_buffer_get_type();
|
||||
#endif /*HAVE_MAGICK7*/
|
||||
|
||||
#ifdef HAVE_CFITSIO
|
||||
vips_foreign_load_fits_get_type();
|
||||
vips_foreign_save_fits_get_type();
|
||||
|
@ -50,6 +50,8 @@
|
||||
|
||||
#ifdef HAVE_MAGICK7
|
||||
|
||||
#include <MagickWand/MagickWand.h>
|
||||
|
||||
typedef struct _VipsForeignLoadMagick7 {
|
||||
VipsForeignLoad parent_object;
|
||||
|
||||
@ -57,6 +59,19 @@ typedef struct _VipsForeignLoadMagick7 {
|
||||
char *density; /* Load at this resolution */
|
||||
int page; /* Load this page (frame) */
|
||||
|
||||
Image *image;
|
||||
ImageInfo *image_info;
|
||||
ExceptionInfo *exception;
|
||||
|
||||
int n_frames; /* Number of frames in file */
|
||||
Image **frames; /* An Image* for each frame */
|
||||
CacheView **cache_view; /* A CacheView for each frame */
|
||||
int frame_height;
|
||||
|
||||
/* Mutex to serialise calls to libMagick during threaded read.
|
||||
*/
|
||||
GMutex *lock;
|
||||
|
||||
} VipsForeignLoadMagick7;
|
||||
|
||||
typedef VipsForeignLoadClass VipsForeignLoadMagick7Class;
|
||||
@ -76,6 +91,100 @@ vips_foreign_load_magick7_get_flags( VipsForeignLoad *load )
|
||||
return( VIPS_FOREIGN_PARTIAL );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_magick7_dispose( GObject *gobject )
|
||||
{
|
||||
VipsForeignLoadMagick7 *magick7 = (VipsForeignLoadMagick7 *) gobject;
|
||||
|
||||
int i;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "vips_foreign_load_magick7_dispose: %p\n", gobject );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
for( i = 0; i < magick7->n_frames; i++ ) {
|
||||
VIPS_FREEF( DestroyCacheView, magick7->cache_view[i] );
|
||||
}
|
||||
VIPS_FREEF( DestroyImageList, magick7->image );
|
||||
VIPS_FREEF( DestroyImageInfo, magick7->image_info );
|
||||
VIPS_FREE( magick7->frames );
|
||||
VIPS_FREEF( DestroyExceptionInfo, magick7->exception );
|
||||
VIPS_FREEF( vips_g_mutex_free, magick7->lock );
|
||||
|
||||
G_OBJECT_CLASS( vips_foreign_load_magick7_parent_class )->
|
||||
dispose( gobject );
|
||||
}
|
||||
|
||||
static void *
|
||||
vips_foreign_load_magick7_genesis_cb( void *client )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf( "vips_foreign_load_magick7_genesis:\n" );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
MagickCoreGenesis( vips_get_argv0(), MagickFalse );
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_magick7_genesis( void )
|
||||
{
|
||||
static GOnce once = G_ONCE_INIT;
|
||||
|
||||
(void) g_once( &once, vips_foreign_load_magick7_genesis_cb, NULL );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_foreign_load_magick7_build( VipsObject *object )
|
||||
{
|
||||
VipsForeignLoadMagick7 *magick7 = (VipsForeignLoadMagick7 *) object;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "vips_foreign_load_magick7_build: %p\n", object );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
vips_foreign_load_magick7_genesis();
|
||||
|
||||
magick7->image_info = CloneImageInfo( NULL );
|
||||
magick7->exception = AcquireExceptionInfo();
|
||||
magick7->lock = vips_g_mutex_new();
|
||||
|
||||
if( !magick7->image_info )
|
||||
return( -1 );
|
||||
|
||||
/* Canvas resolution for rendering vector formats like SVG.
|
||||
*/
|
||||
VIPS_SETSTR( magick7->image_info->density, magick7->density );
|
||||
|
||||
/* 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( magick7->image_info, "dcm:display-range", "reset" );
|
||||
|
||||
if( !magick7->all_frames ) {
|
||||
/* I can't find docs for these fields, but this seems to work.
|
||||
*/
|
||||
char page[256];
|
||||
|
||||
magick7->image_info->scene = magick7->page;
|
||||
magick7->image_info->number_scenes = 1;
|
||||
|
||||
vips_snprintf( page, 256, "%d", magick7->page );
|
||||
magick7->image_info->scenes = strdup( page );
|
||||
}
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_foreign_load_magick7_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_magick7_class_init( VipsForeignLoadMagick7Class *class )
|
||||
{
|
||||
@ -84,11 +193,13 @@ vips_foreign_load_magick7_class_init( VipsForeignLoadMagick7Class *class )
|
||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
|
||||
gobject_class->dispose = vips_foreign_load_magick7_dispose;
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->nickname = "magickload_base";
|
||||
object_class->description = _( "load with ImageMagick7" );
|
||||
object_class->build = vips_foreign_load_magick7_build;
|
||||
|
||||
/* We need to be well to the back of the queue since vips's
|
||||
* dedicated loaders are usually preferable.
|
||||
@ -126,6 +237,297 @@ vips_foreign_load_magick7_init( VipsForeignLoadMagick7 *magick7 )
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_magick7_error( VipsForeignLoadMagick7 *magick7 )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( magick7 );
|
||||
|
||||
vips_error( class->nickname, _( "Magick: %s %s" ),
|
||||
magick7->exception->reason,
|
||||
magick7->exception->description );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_foreign_load_magick7_parse( VipsForeignLoadMagick7 *magick7,
|
||||
Image *image, VipsImage *out )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( magick7 );
|
||||
|
||||
const char *key;
|
||||
Image *p;
|
||||
int i;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "image->depth = %zd\n", image->depth );
|
||||
printf( "GetImageType() = %d\n", GetImageType( image ) );
|
||||
printf( "GetPixelChannels() = %zd\n", GetPixelChannels( image ) );
|
||||
printf( "image->columns = %zd\n", image->columns );
|
||||
printf( "image->rows = %zd\n", image->rows );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
out->Xsize = image->columns;
|
||||
out->Ysize = image->rows;
|
||||
out->Bands = GetPixelChannels( image );
|
||||
magick7->frame_height = image->rows;
|
||||
|
||||
/* Depth can be 'fractional'. You'd think we should use
|
||||
* GetImageDepth() but that seems to compute something very complex.
|
||||
*/
|
||||
out->BandFmt = -1;
|
||||
if( image->depth >= 1 && image->depth <= 8 )
|
||||
out->BandFmt = VIPS_FORMAT_UCHAR;
|
||||
if( image->depth >= 9 && image->depth <= 16 )
|
||||
out->BandFmt = VIPS_FORMAT_USHORT;
|
||||
if( image->depth == 32 )
|
||||
out->BandFmt = VIPS_FORMAT_FLOAT;
|
||||
if( image->depth == 64 )
|
||||
out->BandFmt = VIPS_FORMAT_DOUBLE;
|
||||
|
||||
if( out->BandFmt == -1 ) {
|
||||
vips_error( class->nickname,
|
||||
_( "unsupported bit depth %zd" ), image->depth );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
switch( image->colorspace ) {
|
||||
case GRAYColorspace:
|
||||
if( out->BandFmt == VIPS_FORMAT_USHORT )
|
||||
out->Type = VIPS_INTERPRETATION_GREY16;
|
||||
else
|
||||
out->Type = VIPS_INTERPRETATION_B_W;
|
||||
break;
|
||||
|
||||
case RGBColorspace:
|
||||
if( out->BandFmt == VIPS_FORMAT_USHORT )
|
||||
out->Type = VIPS_INTERPRETATION_RGB16;
|
||||
else
|
||||
out->Type = VIPS_INTERPRETATION_RGB;
|
||||
break;
|
||||
|
||||
case sRGBColorspace:
|
||||
if( out->BandFmt == VIPS_FORMAT_USHORT )
|
||||
out->Type = VIPS_INTERPRETATION_RGB16;
|
||||
else
|
||||
out->Type = VIPS_INTERPRETATION_sRGB;
|
||||
break;
|
||||
|
||||
case CMYKColorspace:
|
||||
out->Type = VIPS_INTERPRETATION_CMYK;
|
||||
break;
|
||||
|
||||
default:
|
||||
vips_error( class->nickname,
|
||||
_( "unsupported colorspace %d" ),
|
||||
(int) image->colorspace );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
switch( image->units ) {
|
||||
case PixelsPerInchResolution:
|
||||
out->Xres = image->resolution.x / 25.4;
|
||||
out->Yres = image->resolution.y / 25.4;
|
||||
vips_image_set_string( out, VIPS_META_RESOLUTION_UNIT, "in" );
|
||||
break;
|
||||
|
||||
case PixelsPerCentimeterResolution:
|
||||
out->Xres = image->resolution.x / 10.0;
|
||||
out->Yres = image->resolution.y / 10.0;
|
||||
vips_image_set_string( out, VIPS_META_RESOLUTION_UNIT, "cm" );
|
||||
break;
|
||||
|
||||
default:
|
||||
out->Xres = 1.0;
|
||||
out->Yres = 1.0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Other fields.
|
||||
*/
|
||||
out->Coding = VIPS_CODING_NONE;
|
||||
|
||||
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_SMALLTILE, NULL );
|
||||
|
||||
/* Get all the metadata.
|
||||
*/
|
||||
ResetImagePropertyIterator( image );
|
||||
while( (key = GetNextImageProperty( image )) ) {
|
||||
char name_text[256];
|
||||
VipsBuf name = VIPS_BUF_STATIC( name_text );
|
||||
const char *value;
|
||||
|
||||
value = GetImageProperty( image, key, magick7->exception );
|
||||
if( !value ) {
|
||||
vips_foreign_load_magick7_error( magick7 );
|
||||
return( -1 );
|
||||
}
|
||||
vips_buf_appendf( &name, "magick-%s", key );
|
||||
vips_image_set_string( out, vips_buf_all( &name ), value );
|
||||
}
|
||||
|
||||
/* Do we have a set of equal-sized frames? Append them.
|
||||
|
||||
FIXME ... there must be an attribute somewhere from dicom read
|
||||
which says this is a volumetric image
|
||||
|
||||
*/
|
||||
magick7->n_frames = 0;
|
||||
for( p = image; p; (p = GetNextImageInList( p )) ) {
|
||||
if( p->columns != (unsigned int) out->Xsize ||
|
||||
p->rows != (unsigned int) out->Ysize ||
|
||||
GetPixelChannels( p ) != out->Bands )
|
||||
break;
|
||||
|
||||
magick7->n_frames += 1;
|
||||
}
|
||||
if( p )
|
||||
/* Nope ... just do the first image in the list.
|
||||
*/
|
||||
magick7->n_frames = 1;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "image has %d frames\n", magick7->n_frames );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
/* If all_frames is off, just get the first one.
|
||||
*/
|
||||
if( !magick7->all_frames )
|
||||
magick7->n_frames = 1;
|
||||
|
||||
/* Record frame pointers.
|
||||
*/
|
||||
out->Ysize *= magick7->n_frames;
|
||||
if( !(magick7->frames = VIPS_ARRAY( NULL, magick7->n_frames, Image * )) )
|
||||
return( -1 );
|
||||
p = image;
|
||||
for( i = 0; i < magick7->n_frames; i++ ) {
|
||||
magick7->frames[i] = p;
|
||||
p = GetNextImageInList( p );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_magick7_unpack( VipsForeignLoadMagick7 *magick7,
|
||||
VipsImage *im, VipsPel *q, Quantum *p, int n )
|
||||
{
|
||||
const int ps = VIPS_IMAGE_SIZEOF_PEL( im );
|
||||
|
||||
int x, b;
|
||||
|
||||
for( x = 0; x < n; x++ ) {
|
||||
if( !GetPixelReadMask( magick7->image, p ) ) {
|
||||
p += im->Bands;
|
||||
q += ps;
|
||||
continue;
|
||||
}
|
||||
|
||||
for( b = 0; b < im->Bands; b++ ) {
|
||||
PixelChannel channel =
|
||||
GetPixelChannelChannel( magick7->image, b );
|
||||
PixelTrait traits =
|
||||
GetPixelChannelTraits( magick7->image, channel );
|
||||
|
||||
if( !(traits & UpdatePixelTrait) ) {
|
||||
printf( "vips_foreign_load_magick7_unpack: "
|
||||
"traits = %d\n", traits );
|
||||
continue;
|
||||
}
|
||||
|
||||
switch( im->BandFmt ) {
|
||||
case VIPS_FORMAT_UCHAR:
|
||||
((unsigned char *) q)[b] = p[b];
|
||||
break;
|
||||
|
||||
case VIPS_FORMAT_USHORT:
|
||||
((unsigned short *) q)[b] = p[b];
|
||||
break;
|
||||
|
||||
case VIPS_FORMAT_FLOAT:
|
||||
((float *) q)[b] = p[b];
|
||||
break;
|
||||
|
||||
case VIPS_FORMAT_DOUBLE:
|
||||
((double *) q)[b] = p[b];
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
p += im->Bands;
|
||||
q += ps;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
vips_foreign_load_magick7_fill_region( VipsRegion *or,
|
||||
void *seq, void *a, void *b, gboolean *stop )
|
||||
{
|
||||
VipsForeignLoadMagick7 *magick7 = (VipsForeignLoadMagick7 *) a;
|
||||
VipsRect *r = &or->valid;
|
||||
VipsImage *im = or->im;
|
||||
|
||||
int y;
|
||||
|
||||
for( y = 0; y < r->height; y++ ) {
|
||||
int top = r->top + y;
|
||||
int frame = top / magick7->frame_height;
|
||||
int line = top % magick7->frame_height;
|
||||
|
||||
Quantum *pixels;
|
||||
|
||||
g_mutex_lock( magick7->lock );
|
||||
pixels = GetCacheViewAuthenticPixels( magick7->cache_view[frame],
|
||||
r->left, line, r->width, 1,
|
||||
magick7->exception );
|
||||
g_mutex_unlock( magick7->lock );
|
||||
|
||||
if( !pixels ) {
|
||||
vips_foreign_load_magick7_error( magick7 );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
vips_foreign_load_magick7_unpack( magick7, im,
|
||||
VIPS_REGION_ADDR( or, r->left, top ), pixels,
|
||||
r->width );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_foreign_load_magick7_header( VipsForeignLoadMagick7 *magick7 )
|
||||
{
|
||||
VipsForeignLoad *load = (VipsForeignLoad *) magick7;
|
||||
|
||||
int i;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "vips_foreign_load_magick7_header: %p\n", magick7 );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
if( vips_foreign_load_magick7_parse( magick7,
|
||||
magick7->image, load->out ) )
|
||||
return( -1 );
|
||||
|
||||
if( !(magick7->cache_view = VIPS_ARRAY( NULL,
|
||||
magick7->n_frames, CacheView * )) )
|
||||
return( -1 );
|
||||
for( i = 0; i < magick7->n_frames; i++ ) {
|
||||
magick7->cache_view[i] = AcquireAuthenticCacheView(
|
||||
magick7->frames[i], magick7->exception );
|
||||
}
|
||||
|
||||
if( vips_image_generate( load->out,
|
||||
NULL, vips_foreign_load_magick7_fill_region, NULL,
|
||||
magick7, NULL ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
typedef struct _VipsForeignLoadMagick7File {
|
||||
VipsForeignLoadMagick7 parent_object;
|
||||
|
||||
@ -141,37 +543,57 @@ G_DEFINE_TYPE( VipsForeignLoadMagick7File, vips_foreign_load_magick7_file,
|
||||
static gboolean
|
||||
ismagick7( const char *filename )
|
||||
{
|
||||
VipsImage *t;
|
||||
Image *image;
|
||||
ImageInfo *image_info;
|
||||
ExceptionInfo *exception;
|
||||
int result;
|
||||
|
||||
t = vips_image_new();
|
||||
vips_error_freeze();
|
||||
result = vips__magick7_read_header( filename, t, FALSE, NULL, 0 );
|
||||
g_object_unref( t );
|
||||
vips_error_thaw();
|
||||
vips_foreign_load_magick7_genesis();
|
||||
|
||||
return( result == 0 );
|
||||
/* Horribly slow :-(
|
||||
*/
|
||||
image_info = CloneImageInfo( NULL );
|
||||
exception = AcquireExceptionInfo();
|
||||
vips_strncpy( image_info->filename, filename, MagickPathExtent );
|
||||
image = PingImage( image_info, exception );
|
||||
result = image != NULL;
|
||||
VIPS_FREEF( DestroyImageList, image );
|
||||
VIPS_FREEF( DestroyImageInfo, image_info );
|
||||
VIPS_FREEF( DestroyExceptionInfo, exception );
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
||||
/* Unfortunately, libMagick7 does not support header-only reads very well. See
|
||||
*
|
||||
* http://www.imagemagick7.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_magick7_file_header( VipsForeignLoad *load )
|
||||
{
|
||||
VipsForeignLoadMagick7 *magick7 = (VipsForeignLoadMagick7 *) load;
|
||||
VipsForeignLoadMagick7File *magick7_file =
|
||||
(VipsForeignLoadMagick7File *) load;
|
||||
VipsForeignLoadMagick7File *file = (VipsForeignLoadMagick7File *) load;
|
||||
|
||||
if( vips__magick7_read( magick7_file->filename,
|
||||
load->out, magick7->all_frames, magick7->density, magick7->page ) )
|
||||
#ifdef DEBUG
|
||||
printf( "vips_foreign_load_magick7_file_header: %p\n", load );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
vips_strncpy( magick7->image_info->filename, file->filename,
|
||||
MagickPathExtent );
|
||||
|
||||
/* We'd love to use PingImage() here but sadly GetPixelChannels() is
|
||||
* always zero after Ping, so we are forced to use ReadImage().
|
||||
*
|
||||
* See:
|
||||
*
|
||||
* http://www.imagemagick.org/discourse-server/viewtopic.php?f=2&t=30043
|
||||
*/
|
||||
magick7->image = ReadImage( magick7->image_info, magick7->exception );
|
||||
if( !magick7->image ) {
|
||||
vips_foreign_load_magick7_error( magick7 );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
VIPS_SETSTR( load->out->filename, magick7_file->filename );
|
||||
if( vips_foreign_load_magick7_header( magick7 ) )
|
||||
return( -1 );
|
||||
|
||||
VIPS_SETSTR( load->out->filename, file->filename );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -223,25 +645,26 @@ G_DEFINE_TYPE( VipsForeignLoadMagick7Buffer, vips_foreign_load_magick7_buffer,
|
||||
static gboolean
|
||||
vips_foreign_load_magick7_buffer_is_a_buffer( const void *buf, size_t len )
|
||||
{
|
||||
VipsImage *t;
|
||||
Image *image;
|
||||
ImageInfo *image_info;
|
||||
ExceptionInfo *exception;
|
||||
int result;
|
||||
|
||||
t = vips_image_new();
|
||||
vips_error_freeze();
|
||||
result = vips__magick7_read_buffer_header( buf, len, t, FALSE, NULL, 0 );
|
||||
g_object_unref( t );
|
||||
vips_error_thaw();
|
||||
vips_foreign_load_magick7_genesis();
|
||||
|
||||
return( result == 0 );
|
||||
/* Horribly slow :-(
|
||||
*/
|
||||
image_info = CloneImageInfo( NULL );
|
||||
exception = AcquireExceptionInfo();
|
||||
image = PingBlob( image_info, buf, len, exception );
|
||||
result = image != NULL;
|
||||
VIPS_FREEF( DestroyImageList, image );
|
||||
VIPS_FREEF( DestroyImageInfo, image_info );
|
||||
VIPS_FREEF( DestroyExceptionInfo, exception );
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
||||
/* Unfortunately, libMagick7 does not support header-only reads very well. See
|
||||
*
|
||||
* http://www.imagemagick7.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_magick7_buffer_header( VipsForeignLoad *load )
|
||||
{
|
||||
@ -249,10 +672,23 @@ vips_foreign_load_magick7_buffer_header( VipsForeignLoad *load )
|
||||
VipsForeignLoadMagick7Buffer *magick7_buffer =
|
||||
(VipsForeignLoadMagick7Buffer *) load;
|
||||
|
||||
if( vips__magick7_read_buffer(
|
||||
magick7_buffer->buf->data, magick7_buffer->buf->length,
|
||||
load->out, magick7->all_frames, magick7->density, magick7->page ) )
|
||||
/* We'd love to use PingBlob() here but sadly GetPixelChannels() is
|
||||
* always zero after Ping, so we are forced to use ReadImage().
|
||||
*
|
||||
* See:
|
||||
*
|
||||
* http://www.imagemagick.org/discourse-server/viewtopic.php?f=2&t=30043
|
||||
*/
|
||||
magick7->image = BlobToImage( magick7->image_info,
|
||||
magick7_buffer->buf->data, magick7_buffer->buf->length,
|
||||
magick7->exception );
|
||||
if( !magick7->image ) {
|
||||
vips_foreign_load_magick7_error( magick7 );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( vips_foreign_load_magick7_header( magick7 ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user