diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index f129a2d5..bba52f0d 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -1882,16 +1882,17 @@ vips_foreign_operation_init( void ) #ifdef HAVE_MAGICK vips_foreign_load_magick_file_get_type(); vips_foreign_load_magick_buffer_get_type(); - vips_foreign_save_magick_file_get_type(); - vips_foreign_save_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_MAGICKSAVE vips_foreign_save_magick_file_get_type(); vips_foreign_save_magick_buffer_get_type(); -#endif /*HAVE_MAGICK7*/ +#endif /*HAVE_MAGICKSAVE*/ #ifdef HAVE_CFITSIO vips_foreign_load_fits_get_type(); diff --git a/libvips/foreign/magick2vips.c b/libvips/foreign/magick2vips.c index 90c02bed..f0fa26aa 100644 --- a/libvips/foreign/magick2vips.c +++ b/libvips/foreign/magick2vips.c @@ -93,6 +93,8 @@ #endif /*HAVE_CONFIG_H*/ #include +#ifdef HAVE_MAGICK + #include #include #include @@ -100,36 +102,15 @@ #include -#if HAVE_MAGICK || HAVE_MAGICK7 +#include -#if HAVE_MAGICK - #include - /* pre-float Magick used to call this MaxRGB. - */ - #if !defined(QuantumRange) - # define QuantumRange MaxRGB - #endif - #define MaxPathExtent MaxTextExtent -#elif HAVE_MAGICK7 - #include - #define MaxPathExtent MagickPathExtent -#endif +#include "pforeign.h" -/* What we track during a write call. +/* pre-float Magick used to call this MaxRGB. */ -typedef struct _Write { - VipsImage *im; - - Image *images; - ImageInfo *image_info; - ExceptionInfo *exception; - - Image *current_image; - char *map; - StorageType storageType; -} Write; - -#if HAVE_MAGICK +#if !defined(QuantumRange) +# define QuantumRange MaxRGB +#endif /* And this used to be UseHDRI. */ @@ -137,8 +118,6 @@ typedef struct _Write { # define UseHDRI 1 #endif -#include "pforeign.h" - /* What we track during a read call. */ typedef struct _Read { @@ -232,7 +211,7 @@ read_new( const char *filename, VipsImage *im, if( filename ) vips_strncpy( read->image_info->filename, - filename, MaxPathExtent ); + filename, MaxTextExtent ); /* Canvas resolution for rendering vector formats like SVG. */ @@ -915,396 +894,3 @@ vips__magick_read_buffer_header( const void *buf, const size_t len, #endif /*HAVE_MAGICK*/ -#ifdef HAVE_MAGICK7 - -static Image* -magick_acquire_image( const ImageInfo *image_info, ExceptionInfo *exception ) -{ - return AcquireImage( image_info, exception ); -} - -static void -magick_acquire_next_image( const ImageInfo *image_info, Image *image, - ExceptionInfo *exception) -{ - AcquireNextImage( image_info, image, exception ); -} - -static int -magick_set_image_size( Image *image, const size_t width, const size_t height, - ExceptionInfo *exception) -{ - return SetImageExtent( image, width, height, exception ); -} - -static int -magick_import_pixels( Image *image, const ssize_t x, const ssize_t y, - const size_t width, const size_t height, const char *map, - const StorageType type,const void *pixels, ExceptionInfo *exception ) -{ - return ImportImagePixels( image, x, y, width, height, map, - type, pixels, exception ); -} - -static void -magick_set_property( Image *image, const char *property, const char *value, - ExceptionInfo *exception ) -{ - (void) SetImageProperty( image, property, value, exception ); -} - -static void -magick_inherit_exception( Write *write, Image *image ) { - (void) write; - (void) image; -} - -#endif /*HAVE_MAGICK7 */ - -#ifdef HAVE_MAGICK - -static Image* -magick_acquire_image(const ImageInfo *image_info, ExceptionInfo *exception) -{ - (void) exception; - return AcquireImage( image_info ); -} - -static void -magick_acquire_next_image( const ImageInfo *image_info, Image *image, - ExceptionInfo *exception ) -{ - (void) exception; - AcquireNextImage( image_info, image ); -} - -static int -magick_set_image_size( Image *image, const size_t width, const size_t height, - ExceptionInfo *exception ) -{ - (void) exception; - return SetImageExtent( image, width, height ); -} - -static int -magick_import_pixels( Image *image, const ssize_t x, const ssize_t y, - const size_t width, const size_t height, const char *map, - const StorageType type,const void *pixels, ExceptionInfo *exception ) -{ - (void) exception; - return ImportImagePixels( image, x, y, width, height, map, - type, pixels ); -} - -static void -magick_set_property( Image *image, const char *property, const char *value, - ExceptionInfo *exception ) -{ - (void) exception; - (void) SetImageProperty( image, property, value ); -} - -static void -magick_inherit_exception( Write *write, Image *image ) { - InheritException( write->exception, &image->exception ); -} - -#endif - -/* Can be called many times. - */ -static void -write_free( Write *write ) -{ - VIPS_FREE( write->map ); - VIPS_FREEF( DestroyImageList, write->images ); - VIPS_FREEF( DestroyImageInfo, write->image_info ); - VIPS_FREEF( DestroyExceptionInfo, write->exception ); -} - -/* Can be called many times. - */ -static int -write_close( VipsImage *im, Write *write ) -{ - write_free( write ); - - return( 0 ); -} - -static Write * -write_new( VipsImage *im, const char *filename, const char *format, - const size_t quality ) -{ - Write *write; - static int inited = 0; - - if( !inited ) { - MagickCoreGenesis( vips_get_argv0(), MagickFalse ); - inited = 1; - } - - if( !(write = VIPS_NEW( im, Write )) ) - return( NULL ); - write->im = im; - write->images = NULL; - - write->storageType = UndefinedPixel; - switch( im->BandFmt ) { - case VIPS_FORMAT_UCHAR: - write->storageType = CharPixel; - break; - case VIPS_FORMAT_USHORT: - write->storageType = ShortPixel; - break; - case VIPS_FORMAT_UINT: - write->storageType = LongPixel; - break; - case VIPS_FORMAT_FLOAT: - write->storageType = FloatPixel; - break; - case VIPS_FORMAT_DOUBLE: - write->storageType = DoublePixel; - break; - - default: - write_free(write); - return( NULL ); - } - - write->map = NULL; - switch( im->Bands ) { - case 1: - write->map = g_strdup("R"); - break; - case 2: - write->map = g_strdup("RA"); - break; - case 3: - write->map = g_strdup("RGB"); - break; - case 4: - if( im->Type == VIPS_INTERPRETATION_CMYK ) - write->map = g_strdup("CMYK"); - else - write->map = g_strdup("RGBA"); - break; - case 5: - write->map = g_strdup("CMYKA"); - break; - - default: - write_free(write); - return( NULL ); - } - - write->image_info = CloneImageInfo( NULL ); - if( !write->image_info) { - write_free(write); - return( NULL ); - } - - if( format ) { - vips_strncpy( write->image_info->magick, - format, MaxPathExtent ); - if ( filename ) { - (void) vips_snprintf( write->image_info->filename, - MaxPathExtent, "%s:%s", format, filename ); - } - } - else if ( filename ) { - vips_strncpy( write->image_info->filename, - filename, MaxPathExtent ); - } - - if ( quality > 0 ) { - write->image_info->quality = quality; - } - - write->exception = AcquireExceptionInfo(); - if( !write->exception) { - write_free(write); - return( NULL ); - } - - g_signal_connect( im, "close", G_CALLBACK( write_close ), write ); - - return( write ); -} - -static int -magick_set_properties( Write *write ) -{ - int number; - const char *str; - - if( vips_image_get_typeof( write->im, "gif-delay" ) && - !vips_image_get_int( write->im, "gif-delay", &number ) ) - write->current_image->delay = (size_t) number; - - if( vips_image_get_typeof( write->im, "gif-loop" ) && - !vips_image_get_int( write->im, "gif-loop", &number ) ) - write->current_image->iterations = (size_t) number; - - if( vips_image_get_typeof( write->im, "gif-comment" ) && - !vips_image_get_string( write->im, "gif-comment", &str ) ) - magick_set_property( write->current_image, "comment", - str, write->exception ); -} - -static int -magick_write_block( VipsRegion *region, VipsRect *area, void *a ) -{ - Write *write = (Write *) a; - MagickBooleanType status; - void *p; - - p = VIPS_REGION_ADDR(region, area->left, area->top); - - status=magick_import_pixels( write->current_image, area->left, area->top, - area->width, area->height, write->map, write->storageType, p, - write->exception ); - - return( status == MagickFalse ? -1 : 0 ); -} - -static int -magick_create_image( Write *write, VipsImage *im ) -{ - Image *image; - int status; - - if( write->images == NULL ) { - image = magick_acquire_image( write->image_info, write->exception ); - if( image == NULL ) - return( -1 ); - - write->images = image; - } - else { - image=GetLastImageInList( write->images ); - magick_acquire_next_image( write->image_info, image, write->exception ); - if( GetNextImageInList( image ) == NULL ) - return( -1 ); - - image=SyncNextImageInList( image ); - } - - if( !magick_set_image_size( image, im->Xsize, im->Ysize, write->exception ) ) - return( -1 ); - - write->current_image=image; - magick_set_properties( write ); - status = vips_sink_disc( im, magick_write_block, write ); - magick_inherit_exception( write, write->current_image ); - return( status ); -} - -static int -magick_create_images( Write *write ) -{ - int height; - int count; - int status; - - height = 0; - if( vips_image_get_typeof( write->im, VIPS_META_PAGE_HEIGHT ) && - vips_image_get_int( write->im, VIPS_META_PAGE_HEIGHT, &height ) ) - return( magick_create_image( write, write->im ) ); - - for( int top=0; top < write->im->Ysize ; top+=height ) { - VipsImage *im; - - if( vips_crop( write->im, &im, 0, top, write->im->Xsize, height, NULL ) ) - return( -1 ); - - status = magick_create_image( write, im ); - - g_object_unref( im ); - - if( status ) - break; - } - - return( status ); -} - -static int -magick_write_images( Write *write ) -{ - if( !WriteImages( write->image_info, write->images, - write->image_info->filename, write->exception ) ) - return( -1 ); - - return( 0 ); -} - -static int -magick_write_images_buf( Write *write, void **obuf, size_t *olen ) -{ - *obuf=ImagesToBlob( write->image_info, write->images, olen, - write->exception ); - - if( !*obuf ) - return( -1 ); - - return( 0 ); -} - -int -vips__magick_write( VipsImage *im, const char *filename, - const char *format, const size_t quality ) -{ - Write *write; - - if( !(write = write_new( im, filename, format, quality )) ) - return( -1 ); - - if ( magick_create_images( write ) ) { - vips_error( "magick2vips", _( "unable to write file \"%s\"\n" - "libMagick error: %s %s" ), - filename, - write->exception->reason, write->exception->description ); - return( -1 ); - } - - if( magick_write_images( write ) ) { - magick_inherit_exception( write, write->images ); - vips_error( "magick2vips", _( "unable to write file \"%s\"\n" - "libMagick error: %s %s" ), - filename, - write->exception->reason, write->exception->description ); - return( -1 ); - } - - return( 0 ); -} - -int -vips__magick_write_buf( VipsImage *im, void **obuf, size_t *olen, - const char *format, const size_t quality ) -{ - Write *write; - - if( !(write = write_new( im, NULL, format, quality )) ) - return( -1 ); - - if ( magick_create_images( write ) ) { - vips_error( "magick2vips", _( "unable to write buffer \n" - "libMagick error: %s %s" ), - write->exception->reason, write->exception->description ); - return( -1 ); - } - - if( magick_write_images_buf( write, obuf, olen ) ) { - vips_error( "magick2vips", _( "unable to write buffer \n" - "libMagick error: %s %s" ), - write->exception->reason, write->exception->description ); - return( -1 ); - } - - return( 0 ); -} - -#endif /*HAVE_MAGICK | HAVE_MAGICK7*/ - diff --git a/libvips/foreign/magicksave.c b/libvips/foreign/magicksave.c index e57fa6ef..0a843030 100644 --- a/libvips/foreign/magicksave.c +++ b/libvips/foreign/magicksave.c @@ -33,7 +33,11 @@ #endif /*HAVE_CONFIG_H*/ #include -#if HAVE_MAGICK || HAVE_MAGICK7 +/* Should be removed and added as a configure option */ +#define HAVE_MAGICKSAVE 1 +/* Should be removed and added as a configure option */ + +#ifdef HAVE_MAGICKSAVE #include #include @@ -43,6 +47,424 @@ #include "pforeign.h" +#ifdef HAVE_MAGICK + #include + /* pre-float Magick used to call this MaxRGB. + */ + #define MaxPathExtent MaxTextExtent +#endif +#ifdef HAVE_MAGICK7 + #include + #define MaxPathExtent MagickPathExtent +#endif + +/* What we track during a write call. + */ +typedef struct _Write { + VipsImage *im; + + Image *images; + ImageInfo *image_info; + ExceptionInfo *exception; + + Image *current_image; + char *map; + StorageType storageType; +} Write; + +#ifdef HAVE_MAGICK7 + +static Image* +magick_acquire_image( const ImageInfo *image_info, ExceptionInfo *exception ) +{ + return AcquireImage( image_info, exception ); +} + +static void +magick_acquire_next_image( const ImageInfo *image_info, Image *image, + ExceptionInfo *exception) +{ + AcquireNextImage( image_info, image, exception ); +} + +static int +magick_set_image_size( Image *image, const size_t width, const size_t height, + ExceptionInfo *exception) +{ + return SetImageExtent( image, width, height, exception ); +} + +static int +magick_import_pixels( Image *image, const ssize_t x, const ssize_t y, + const size_t width, const size_t height, const char *map, + const StorageType type,const void *pixels, ExceptionInfo *exception ) +{ + return ImportImagePixels( image, x, y, width, height, map, + type, pixels, exception ); +} + +static void +magick_set_property( Image *image, const char *property, const char *value, + ExceptionInfo *exception ) +{ + (void) SetImageProperty( image, property, value, exception ); +} + +static void +magick_inherit_exception( Write *write, Image *image ) { + (void) write; + (void) image; +} + +#endif /*HAVE_MAGICK7 */ + +#ifdef HAVE_MAGICK + +static Image* +magick_acquire_image(const ImageInfo *image_info, ExceptionInfo *exception) +{ + (void) exception; + return AcquireImage( image_info ); +} + +static void +magick_acquire_next_image( const ImageInfo *image_info, Image *image, + ExceptionInfo *exception ) +{ + (void) exception; + AcquireNextImage( image_info, image ); +} + +static int +magick_set_image_size( Image *image, const size_t width, const size_t height, + ExceptionInfo *exception ) +{ + (void) exception; + return SetImageExtent( image, width, height ); +} + +static int +magick_import_pixels( Image *image, const ssize_t x, const ssize_t y, + const size_t width, const size_t height, const char *map, + const StorageType type,const void *pixels, ExceptionInfo *exception ) +{ + (void) exception; + return ImportImagePixels( image, x, y, width, height, map, + type, pixels ); +} + +static void +magick_set_property( Image *image, const char *property, const char *value, + ExceptionInfo *exception ) +{ + (void) exception; + (void) SetImageProperty( image, property, value ); +} + +static void +magick_inherit_exception( Write *write, Image *image ) { + InheritException( write->exception, &image->exception ); +} + +#endif /*HAVE_MAGICK */ + +/* Can be called many times. + */ +static void +write_free( Write *write ) +{ + VIPS_FREE( write->map ); + VIPS_FREEF( DestroyImageList, write->images ); + VIPS_FREEF( DestroyImageInfo, write->image_info ); + VIPS_FREEF( DestroyExceptionInfo, write->exception ); +} + +/* Can be called many times. + */ +static int +write_close( VipsImage *im, Write *write ) +{ + write_free( write ); + + return( 0 ); +} + +static Write * +write_new( VipsImage *im, const char *filename, const char *format, + const size_t quality ) +{ + Write *write; + static int inited = 0; + + if( !inited ) { + MagickCoreGenesis( vips_get_argv0(), MagickFalse ); + inited = 1; + } + + if( !(write = VIPS_NEW( im, Write )) ) + return( NULL ); + write->im = im; + write->images = NULL; + + write->storageType = UndefinedPixel; + switch( im->BandFmt ) { + case VIPS_FORMAT_UCHAR: + write->storageType = CharPixel; + break; + case VIPS_FORMAT_USHORT: + write->storageType = ShortPixel; + break; + case VIPS_FORMAT_UINT: + write->storageType = LongPixel; + break; + case VIPS_FORMAT_FLOAT: + write->storageType = FloatPixel; + break; + case VIPS_FORMAT_DOUBLE: + write->storageType = DoublePixel; + break; + + default: + write_free(write); + return( NULL ); + } + + write->map = NULL; + switch( im->Bands ) { + case 1: + write->map = g_strdup("R"); + break; + case 2: + write->map = g_strdup("RA"); + break; + case 3: + write->map = g_strdup("RGB"); + break; + case 4: + if( im->Type == VIPS_INTERPRETATION_CMYK ) + write->map = g_strdup("CMYK"); + else + write->map = g_strdup("RGBA"); + break; + case 5: + write->map = g_strdup("CMYKA"); + break; + + default: + write_free(write); + return( NULL ); + } + + write->image_info = CloneImageInfo( NULL ); + if( !write->image_info) { + write_free(write); + return( NULL ); + } + + if( format ) { + vips_strncpy( write->image_info->magick, + format, MaxPathExtent ); + if ( filename ) { + (void) vips_snprintf( write->image_info->filename, + MaxPathExtent, "%s:%s", format, filename ); + } + } + else if ( filename ) { + vips_strncpy( write->image_info->filename, + filename, MaxPathExtent ); + } + + if ( quality > 0 ) { + write->image_info->quality = quality; + } + + write->exception = AcquireExceptionInfo(); + if( !write->exception) { + write_free(write); + return( NULL ); + } + + g_signal_connect( im, "close", G_CALLBACK( write_close ), write ); + + return( write ); +} + +static int +magick_set_properties( Write *write ) +{ + int number; + const char *str; + + if( vips_image_get_typeof( write->im, "gif-delay" ) && + !vips_image_get_int( write->im, "gif-delay", &number ) ) + write->current_image->delay = (size_t) number; + + if( vips_image_get_typeof( write->im, "gif-loop" ) && + !vips_image_get_int( write->im, "gif-loop", &number ) ) + write->current_image->iterations = (size_t) number; + + if( vips_image_get_typeof( write->im, "gif-comment" ) && + !vips_image_get_string( write->im, "gif-comment", &str ) ) + magick_set_property( write->current_image, "comment", + str, write->exception ); +} + +static int +magick_write_block( VipsRegion *region, VipsRect *area, void *a ) +{ + Write *write = (Write *) a; + MagickBooleanType status; + void *p; + + p = VIPS_REGION_ADDR(region, area->left, area->top); + + status=magick_import_pixels( write->current_image, area->left, area->top, + area->width, area->height, write->map, write->storageType, p, + write->exception ); + + return( status == MagickFalse ? -1 : 0 ); +} + +static int +magick_create_image( Write *write, VipsImage *im ) +{ + Image *image; + int status; + + if( write->images == NULL ) { + image = magick_acquire_image( write->image_info, write->exception ); + if( image == NULL ) + return( -1 ); + + write->images = image; + } + else { + image=GetLastImageInList( write->images ); + magick_acquire_next_image( write->image_info, image, write->exception ); + if( GetNextImageInList( image ) == NULL ) + return( -1 ); + + image=SyncNextImageInList( image ); + } + + if( !magick_set_image_size( image, im->Xsize, im->Ysize, write->exception ) ) + return( -1 ); + + write->current_image=image; + magick_set_properties( write ); + status = vips_sink_disc( im, magick_write_block, write ); + magick_inherit_exception( write, write->current_image ); + return( status ); +} + +static int +magick_create_images( Write *write ) +{ + int height; + int count; + int status; + + height = 0; + if( vips_image_get_typeof( write->im, VIPS_META_PAGE_HEIGHT ) && + vips_image_get_int( write->im, VIPS_META_PAGE_HEIGHT, &height ) ) + return( magick_create_image( write, write->im ) ); + + for( int top=0; top < write->im->Ysize ; top+=height ) { + VipsImage *im; + + if( vips_crop( write->im, &im, 0, top, write->im->Xsize, height, NULL ) ) + return( -1 ); + + status = magick_create_image( write, im ); + + g_object_unref( im ); + + if( status ) + break; + } + + return( status ); +} + +static int +magick_write_images( Write *write ) +{ + if( !WriteImages( write->image_info, write->images, + write->image_info->filename, write->exception ) ) + return( -1 ); + + return( 0 ); +} + +static int +magick_write_images_buf( Write *write, void **obuf, size_t *olen ) +{ + *obuf=ImagesToBlob( write->image_info, write->images, olen, + write->exception ); + + if( !*obuf ) + return( -1 ); + + return( 0 ); +} + +static int +magick_write( VipsImage *im, const char *filename, + const char *format, const size_t quality ) +{ + Write *write; + + if( !(write = write_new( im, filename, format, quality )) ) + return( -1 ); + + if ( magick_create_images( write ) ) { + vips_error( "magick2vips", _( "unable to write file \"%s\"\n" + "libMagick error: %s %s" ), + filename, + write->exception->reason, write->exception->description ); + return( -1 ); + } + + if( magick_write_images( write ) ) { + magick_inherit_exception( write, write->images ); + vips_error( "magick2vips", _( "unable to write file \"%s\"\n" + "libMagick error: %s %s" ), + filename, + write->exception->reason, write->exception->description ); + return( -1 ); + } + + return( 0 ); +} + +static int +magick_write_buf( VipsImage *im, void **obuf, size_t *olen, + const char *format, const size_t quality ) +{ + Write *write; + + if( !(write = write_new( im, NULL, format, quality )) ) + return( -1 ); + + if ( magick_create_images( write ) ) { + vips_error( "magick2vips", _( "unable to write buffer \n" + "libMagick error: %s %s" ), + write->exception->reason, write->exception->description ); + return( -1 ); + } + + if( magick_write_images_buf( write, obuf, olen ) ) { + vips_error( "magick2vips", _( "unable to write buffer \n" + "libMagick error: %s %s" ), + write->exception->reason, write->exception->description ); + return( -1 ); + } + + return( 0 ); +} + + + typedef struct _VipsForeignSaveMagick { VipsForeignSave parent_object; @@ -119,7 +541,7 @@ vips_foreign_save_magick_file_build( VipsObject *object ) build( object ) ) return( -1 ); - if( vips__magick_write( save->ready, file->filename, file->format, + if( magick_write( save->ready, file->filename, file->format, file->quality ) ) return( -1 ); @@ -199,7 +621,7 @@ vips_foreign_save_magick_buffer_build( VipsObject *object ) build( object ) ) return( -1 ); - if( vips__magick_write_buf( save->ready, &obuf, &olen, + if( magick_write_buf( save->ready, &obuf, &olen, buffer->format, buffer->quality ) ) return( -1 ); @@ -252,4 +674,4 @@ vips_foreign_save_magick_buffer_init( VipsForeignSaveMagickBuffer *buffer ) { } -#endif /*HAVE_MAGICK || HAVE_MAGICK7*/ +#endif /*HAVE_MAGICKSAVE*/ diff --git a/libvips/foreign/pforeign.h b/libvips/foreign/pforeign.h index cae6540c..08973569 100644 --- a/libvips/foreign/pforeign.h +++ b/libvips/foreign/pforeign.h @@ -132,11 +132,6 @@ int vips__magick_read_buffer( const void *buf, const size_t len, int vips__magick_read_buffer_header( const void *buf, const size_t len, VipsImage *out, const char *density, int page, int n ); -int vips__magick_write( VipsImage *in, const char *filename, - const char *format, const size_t quality ); -int vips__magick_write_buf( VipsImage *in, void **obuf, size_t *olen, - const char *format, const size_t quality ); - extern const char *vips__mat_suffs[]; int vips__mat_load( const char *filename, VipsImage *out );