diff --git a/configure.ac b/configure.ac index d2d974055c..034667cac4 100644 --- a/configure.ac +++ b/configure.ac @@ -762,6 +762,16 @@ if test x"$magick6" = x"yes"; then LIBS="$save_LIBS" fi +if test x"$magick6" = x"yes"; then + # IM uses SetImageProfile() with StringInfo + save_LIBS="$LIBS" + LIBS="$LIBS $MAGICK_LIBS" + AC_CHECK_FUNCS(BlobToStringInfo, + AC_DEFINE(HAVE_BLOBTOSTRINGINFO,1, + [define if your magick has BlobToStringInfo().])) + LIBS="$save_LIBS" +fi + if test x"$magick6" = x"yes"; then # GM is missing InheritException save_LIBS="$LIBS" diff --git a/libvips/foreign/magick.c b/libvips/foreign/magick.c index c7d186434c..04c607a39c 100644 --- a/libvips/foreign/magick.c +++ b/libvips/foreign/magick.c @@ -92,6 +92,21 @@ magick_set_property( Image *image, const char *property, const char *value, (void) SetImageProperty( image, property, value, exception ); } +int +magick_set_profile( Image *image, + const char *name, const void *data, size_t length, + ExceptionInfo *exception ) +{ + StringInfo *string; + MagickBooleanType result; + + string = BlobToStringInfo( data, length ); + result = SetImageProfile( image, name, string, exception ); + DestroyStringInfo( string ); + + return( result ); +} + ExceptionInfo * magick_acquire_exception( void ) { @@ -227,6 +242,26 @@ magick_set_property( Image *image, const char *property, const char *value, #endif /*HAVE_SETIMAGEPROPERTY*/ } +int +magick_set_profile( Image *image, + const char *name, const void *data, size_t length, + ExceptionInfo *exception ) +{ + int result; + +#ifdef HAVE_BLOBTOSTRINGINFO + StringInfo *string; + + string = BlobToStringInfo( data, length ); + result = SetImageProfile( image, name, string ); + DestroyStringInfo( string ); +#else /*HAVE_BLOBTOSTRINGINFO*/ + result = SetImageProfile( image, name, data, length ); +#endif /*HAVE_BLOBTOSTRINGINFO*/ + + return( result ); +} + ExceptionInfo * magick_acquire_exception( void ) { diff --git a/libvips/foreign/magick.h b/libvips/foreign/magick.h index 1251175cdc..83d8a8df4e 100644 --- a/libvips/foreign/magick.h +++ b/libvips/foreign/magick.h @@ -53,7 +53,10 @@ int magick_import_pixels( Image *image, const ssize_t x, const ssize_t y, const StorageType type,const void *pixels, ExceptionInfo *exception ); void *magick_images_to_blob( const ImageInfo *image_info, Image *images, size_t *length, ExceptionInfo *exception ); -void magick_set_property( Image *image, const char *property, const char *value, +void magick_set_property( Image *image, + const char *property, const char *value, ExceptionInfo *exception ); +int magick_set_profile( Image *image, + const char *name, const void *data, size_t length, ExceptionInfo *exception ); void magick_set_image_option( ImageInfo *image_info, const char *name, const char *value ); diff --git a/libvips/foreign/magick2vips.c b/libvips/foreign/magick2vips.c index daa2473e13..0b7c7f97de 100644 --- a/libvips/foreign/magick2vips.c +++ b/libvips/foreign/magick2vips.c @@ -444,6 +444,8 @@ parse_header( Read *read ) vips_buf_appendf( &name, VIPS_META_IPTC_NAME ); else if( strcmp( key, "icc" ) == 0 ) vips_buf_appendf( &name, VIPS_META_ICC_NAME ); + else if( strcmp( key, "exif" ) == 0 ) + vips_buf_appendf( &name, VIPS_META_EXIF_NAME ); else vips_buf_appendf( &name, "magickprofile-%s", key ); @@ -452,6 +454,9 @@ parse_header( Read *read ) length = GetStringInfoLength( profile ); vips_image_set_blob_copy( im, vips_buf_all( &name ), data, length ); + + if( strcmp( key, "exif" ) == 0 ) + (void) vips__exif_parse( im ); } } #endif /*HAVE_RESETIMAGEPROFILEITERATOR*/ diff --git a/libvips/foreign/magick7load.c b/libvips/foreign/magick7load.c index 91ad86292a..d9e16fd20a 100644 --- a/libvips/foreign/magick7load.c +++ b/libvips/foreign/magick7load.c @@ -562,6 +562,8 @@ vips_foreign_load_magick7_parse( VipsForeignLoadMagick7 *magick7, vips_buf_appendf( &name, VIPS_META_IPTC_NAME ); else if( strcmp( key, "icc" ) == 0 ) vips_buf_appendf( &name, VIPS_META_ICC_NAME ); + else if( strcmp( key, "exif" ) == 0 ) + vips_buf_appendf( &name, VIPS_META_EXIF_NAME ); else vips_buf_appendf( &name, "magickprofile-%s", key ); @@ -570,6 +572,9 @@ vips_foreign_load_magick7_parse( VipsForeignLoadMagick7 *magick7, length = GetStringInfoLength( profile ); vips_image_set_blob_copy( out, vips_buf_all( &name ), data, length ); + + if( strcmp( key, "exif" ) == 0 ) + (void) vips__exif_parse( im ); } magick7->n_pages = GetImageListLength( GetFirstImageInList( image ) ); diff --git a/libvips/foreign/magicksave.c b/libvips/foreign/magicksave.c index 223395d47f..bedcae4ce8 100644 --- a/libvips/foreign/magicksave.c +++ b/libvips/foreign/magicksave.c @@ -89,12 +89,59 @@ vips_foreign_save_magick_dispose( GObject *gobject ) dispose( gobject ); } -static void +typedef struct { + VipsForeignSaveMagick *magick; + Image *image; +} CopyProfileInfo; + +static void * +vips_foreign_save_magick_copy_profile( VipsImage *im, + const char *name, GValue *value, CopyProfileInfo *info ) +{ + char txt[256]; + VipsBuf buf = VIPS_BUF_STATIC( txt ); + const void *data; + size_t length; + int result; + + if( strcmp( name, VIPS_META_XMP_NAME ) == 0 ) + vips_buf_appendf( &buf, "xmp" ); + else if( strcmp( name, VIPS_META_IPTC_NAME ) == 0 ) + vips_buf_appendf( &buf, "iptc" ); + else if( strcmp( name, VIPS_META_ICC_NAME ) == 0 ) + vips_buf_appendf( &buf, "icc" ); + else if( strcmp( name, VIPS_META_EXIF_NAME ) == 0 ) + vips_buf_appendf( &buf, "exif" ); + else if( vips_isprefix( "magickprofile-", name ) ) + vips_buf_appendf( &buf, + "%s", name + strlen( "magickprofile-" ) ); + + if( vips_buf_is_empty( &buf ) ) + return( NULL ); + if( !vips_image_get_typeof( im, name ) ) + return( NULL ); + if( vips_image_get_blob( im, name, &data, &length ) ) + return( im ); + + result = magick_set_profile( info->image, + vips_buf_all( &buf ), data, length, info->magick->exception ); + if( !result ) { + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( info->magick ); + + magick_vips_error( class->nickname, info->magick->exception ); + return( im ); + } + + return( NULL ); +} + +static int vips_foreign_save_magick_set_properties( VipsForeignSaveMagick *magick, Image *image, VipsImage *im ) { int number; const char *str; + CopyProfileInfo info; if( vips_image_get_typeof( im, "gif-delay" ) && !vips_image_get_int( im, "gif-delay", &number ) ) @@ -107,6 +154,15 @@ vips_foreign_save_magick_set_properties( VipsForeignSaveMagick *magick, if( vips_image_get_typeof( im, "gif-comment" ) && !vips_image_get_string( im, "gif-comment", &str ) ) magick_set_property( image, "comment", str, magick->exception ); + + info.magick = magick; + info.image = image; + if( vips_image_map( im, + (VipsImageMapFn) vips_foreign_save_magick_copy_profile, + &info ) ) + return( -1 ); + + return( 0 ); } static int @@ -155,7 +211,8 @@ vips_foreign_save_magick_create_one( VipsForeignSaveMagick *magick, if( !magick_set_image_size( image, im->Xsize, im->Ysize, magick->exception ) ) return( -1 ); - vips_foreign_save_magick_set_properties( magick, image, im ); + if( vips_foreign_save_magick_set_properties( magick, image, im ) ) + return( -1 ); magick->current_image = image; status = vips_sink_disc( im, magick_write_block, magick );