diff --git a/ChangeLog b/ChangeLog index ea5f8e9b..8c88fe53 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,6 +7,7 @@ - revise vips_cast() to improve behaviour with uint images [erdmann] - add bandand()/or()/eor() to cplusplus binding [clcaalu] - implement shrink-on-load for tiff pyramids [jcupitt] +- added vips_image_set_blob_copy() [jcupitt] 23/9/18 started 8.7.1 - update function list in docs [janko-m] diff --git a/libvips/foreign/exif.c b/libvips/foreign/exif.c index eda5a3db..8987b9ef 100644 --- a/libvips/foreign/exif.c +++ b/libvips/foreign/exif.c @@ -447,22 +447,6 @@ vips_image_resolution_from_exif( VipsImage *image, ExifData *ed ) return( 0 ); } -static int -vips_exif_get_thumbnail( VipsImage *im, ExifData *ed ) -{ - if( ed->size > 0 ) { - char *thumb_copy; - - thumb_copy = g_malloc( ed->size ); - memcpy( thumb_copy, ed->data, ed->size ); - - vips_image_set_blob( im, "jpeg-thumbnail-data", - (VipsCallbackFn) g_free, thumb_copy, ed->size ); - } - - return( 0 ); -} - /* Need to fwd ref this. */ static int @@ -516,7 +500,9 @@ vips__exif_parse( VipsImage *image ) exif_data_foreach_content( ed, (ExifDataForeachContentFunc) vips_exif_get_content, ¶ms ); - vips_exif_get_thumbnail( image, ed ); + vips_image_set_blob_copy( image, + "jpeg-thumbnail-data", ed->data, ed->size ); + exif_data_free( ed ); /* Orientation handling. ifd0 has the Orientation tag for the main diff --git a/libvips/foreign/jpeg2vips.c b/libvips/foreign/jpeg2vips.c index 14f84c8e..43d9cb4b 100644 --- a/libvips/foreign/jpeg2vips.c +++ b/libvips/foreign/jpeg2vips.c @@ -309,8 +309,6 @@ find_chroma_subsample( struct jpeg_decompress_struct *cinfo ) static int attach_blob( VipsImage *im, const char *field, void *data, int data_length ) { - char *data_copy; - /* Only use the first one. */ if( vips_image_get_typeof( im, field ) ) { @@ -325,11 +323,7 @@ attach_blob( VipsImage *im, const char *field, void *data, int data_length ) printf( "attach_blob: attaching %d bytes of %s\n", data_length, field ); #endif /*DEBUG*/ - if( !(data_copy = vips_malloc( NULL, data_length )) ) - return( -1 ); - memcpy( data_copy, data, data_length ); - vips_image_set_blob( im, field, - (VipsCallbackFn) vips_free, data_copy, data_length ); + vips_image_set_blob_copy( im, field, data, data_length ); return( 0 ); } diff --git a/libvips/foreign/niftiload.c b/libvips/foreign/niftiload.c index eedc0f0c..fc945336 100644 --- a/libvips/foreign/niftiload.c +++ b/libvips/foreign/niftiload.c @@ -500,14 +500,9 @@ vips_foreign_load_nifti_set_header( VipsForeignLoadNifti *nifti, for( i = 0; i < nim->num_ext; i++ ) { nifti1_extension *ext = &nim->ext_list[i]; - char *data_copy; vips_snprintf( txt, 256, "nifti-ext-%d-%d", i, ext->ecode ); - if( !(data_copy = vips_malloc( NULL, ext->esize )) ) - return( -1 ); - memcpy( data_copy, ext->edata, ext->esize ); - vips_image_set_blob( out, txt, - (VipsCallbackFn) vips_free, data_copy, ext->esize ); + vips_image_set_blob_copy( out, txt, ext->edata, ext->esize ); } if( nim->ny > 1 ) diff --git a/libvips/foreign/tiff2vips.c b/libvips/foreign/tiff2vips.c index f7b47589..d19b9c88 100644 --- a/libvips/foreign/tiff2vips.c +++ b/libvips/foreign/tiff2vips.c @@ -1353,43 +1353,37 @@ rtiff_set_header( Rtiff *rtiff, VipsImage *out ) */ if( TIFFGetField( rtiff->tiff, TIFFTAG_ICCPROFILE, &data_length, &data ) ) { - if( vips_image_set_blob_copy( rtiff, out, - VIPS_META_ICC_NAME, data_length, data ) ) - return( -1 ); + vips_image_set_blob_copy( out, + VIPS_META_ICC_NAME, data, data_length ); } /* Read any XMP metadata. */ if( TIFFGetField( rtiff->tiff, TIFFTAG_XMLPACKET, &data_length, &data ) ) { - if( vips_image_set_blob_copy( rtiff, out, - VIPS_META_XMP_NAME, data_length, data ) ) - return( -1 ); + vips_image_set_blob_copy( out, + VIPS_META_XMP_NAME, data, data_length ); } /* Read any IPTC metadata. */ if( TIFFGetField( rtiff->tiff, TIFFTAG_RICHTIFFIPTC, &data_length, &data ) ) { - if( vips_image_set_blob_copy( rtiff, out, - VIPS_META_IPTC_NAME, data_length, data ) ) - return( -1 ); + vips_image_set_blob_copy( out, + VIPS_META_IPTC_NAME, data, data_length ); /* Older versions of libvips used this misspelt name :-( attach * under this name too for compatibility. */ - if( vips_image_set_blob_copy( rtiff, out, - "ipct-data", data_length, data ) ) - return( -1 ); + vips_image_set_blob_copy( out, "ipct-data", data, data_length ); } /* Read any photoshop metadata. */ if( TIFFGetField( rtiff->tiff, TIFFTAG_PHOTOSHOP, &data_length, &data ) ) { - if( vips_image_set_blob_copy( rtiff, out, - VIPS_META_PHOTOSHOP_NAME, data_length, data ) ) - return( -1 ); + vips_image_set_blob_copy( out, + VIPS_META_PHOTOSHOP_NAME, data, data_length ); } /* IMAGEDESCRIPTION often has useful metadata. diff --git a/libvips/foreign/vipspng.c b/libvips/foreign/vipspng.c index 058b1aa9..78301f44 100644 --- a/libvips/foreign/vipspng.c +++ b/libvips/foreign/vipspng.c @@ -448,19 +448,14 @@ png2vips_header( Read *read, VipsImage *out ) */ if( png_get_iCCP( read->pPng, read->pInfo, &name, &compression_type, &profile, &proflen ) ) { - void *profile_copy; - #ifdef DEBUG printf( "png2vips_header: attaching %d bytes of ICC profile\n", proflen ); printf( "png2vips_header: name = \"%s\"\n", name ); #endif /*DEBUG*/ - if( !(profile_copy = vips_malloc( NULL, proflen )) ) - return( -1 ); - memcpy( profile_copy, profile, proflen ); - vips_image_set_blob( out, VIPS_META_ICC_NAME, - (VipsCallbackFn) vips_free, profile_copy, proflen ); + vips_image_set_blob_copy( out, + VIPS_META_ICC_NAME, profile, proflen ); } /* Sanity-check line size. diff --git a/libvips/foreign/webp2vips.c b/libvips/foreign/webp2vips.c index 8e813e7f..20068bb6 100644 --- a/libvips/foreign/webp2vips.c +++ b/libvips/foreign/webp2vips.c @@ -254,18 +254,9 @@ read_header( Read *read, VipsImage *out ) WebPData data; - if( WebPMuxGetChunk( mux, webp, &data ) == WEBP_MUX_OK ) { - void *blob; - - if( !(blob = vips_malloc( NULL, data.size )) ) { - WebPMuxDelete( mux ); - return( -1 ); - } - - memcpy( blob, data.bytes, data.size ); - vips_image_set_blob( out, vips, - (VipsCallbackFn) vips_free, blob, data.size ); - } + if( WebPMuxGetChunk( mux, webp, &data ) == WEBP_MUX_OK ) + vips_image_set_blob_copy( out, + vips, data.bytes, data.size ); } WebPMuxDelete( mux ); diff --git a/libvips/include/vips/header.h b/libvips/include/vips/header.h index 8a1bda37..1b0e1305 100644 --- a/libvips/include/vips/header.h +++ b/libvips/include/vips/header.h @@ -196,7 +196,7 @@ int vips_image_get_area( const VipsImage *image, void vips_image_set_blob( VipsImage *image, const char *name, VipsCallbackFn free_fn, void *data, size_t length ); void vips_image_set_blob_copy( VipsImage *image, - const char *name, void *data, size_t length ); + const char *name, const void *data, size_t length ); int vips_image_get_blob( const VipsImage *image, const char *name, void **data, size_t *length ); diff --git a/libvips/iofuncs/header.c b/libvips/iofuncs/header.c index b12ccb9b..3cf55256 100644 --- a/libvips/iofuncs/header.c +++ b/libvips/iofuncs/header.c @@ -27,7 +27,7 @@ * - vips_image_get_*() all convert everything to target type if they can * - rename "field" as "name" in docs * 21/11/18 - * - get_string will allow BLOB, G_STRING and REF_STRING + * - get_string will allow G_STRING and REF_STRING */ /* @@ -1368,60 +1368,32 @@ vips_image_set_blob( VipsImage *image, * @length: length of memory area * * Attaches @blob as a metadata item on @image under the name @name, taking - * a copy of the memory area. A convenience function over vips_image_set_blob(). - * - * One more byte is allocated and a secret null added to the end, although - * this extra length is not recorded. This makes reading the value out later - * as a C string safer and more convenient. + * a copy of the memory area. A convenience function over + * vips_image_set_blob(). * * See also: vips_image_get_blob(), vips_image_set(). */ void vips_image_set_blob_copy( VipsImage *image, - const char *name, void *data, size_t length ) + const char *name, const void *data, size_t length ) { void *data_copy; if( !data || length == 0 ) - return( 0 ); + return; + /* We add an extra, secret null byte at the end, just in case this blob + * is read as a C string. The libtiff reader (for example) attaches + * XMP XML as a blob, for example. + */ if( !(data_copy = vips_malloc( NULL, length + 1 )) ) - return( -1 ); + return; memcpy( data_copy, data, length ); ((unsigned char *) data_copy)[length] = '\0'; - vips_image_set_blob( out, field, - (VipsCallbackFn) vips_free, data_copy, length ); - - return( 0 ); -} - -/* Set a blob on an image from a libtiff pointer/length. We don't null - * terminate, even though most of these things are strings, because we want to - * be able to write them back unaltered. - * - * Null-termination, checking for utf-8, checking for embedded null characters - * etc. must all be done on readout from the blob. - */ -static int -rtiff_set_blob( Rtiff *rtiff, VipsImage *out, const char *field, - uint32 data_length, unsigned char *data ) -{ - unsigned char *data_copy; - - if( !data || - data_length == 0 ) - return( 0 ); - - if( !(data_copy = vips_malloc( NULL, data_length )) ) - return( -1 ); - memcpy( data_copy, data, data_length ); - - vips_image_set_blob( out, field, - (VipsCallbackFn) vips_free, data_copy, data_length ); - - return( 0 ); + vips_image_set_blob( image, + name, (VipsCallbackFn) vips_free, data_copy, length ); } /** @@ -1564,8 +1536,7 @@ vips_image_set_double( VipsImage *image, const char *name, double d ) * * Gets @out from @im under the name @name. * The field must be of type - * G_STRING, VIPS_TYPE_REFSTRING or VIPS_TYPE_BLOB. If it's a BLOB, it must be - * null-terminated. + * G_STRING, VIPS_TYPE_REFSTRING. * * Do not free @out. * @@ -1583,24 +1554,8 @@ vips_image_get_string( const VipsImage *image, const char *name, if( vips_image_get( image, name, &value ) ) return( -1 ); - if( G_VALUE_TYPE( &value ) == VIPS_TYPE_BLOB ) { - char *str; - size_t length; - str = vips_value_get_blob( &value, &length ); - if( length <= 0 || - str[length] != '\0' ) { - g_value_unset( &value ); - vips_error( "VipsImage", - _( "field \"%s\" is not null-terminated" ), - name ); - - return( -1 ); - } - - *out = str; - } - else if( G_VALUE_TYPE( &value ) == VIPS_TYPE_REF_STRING ) { + if( G_VALUE_TYPE( &value ) == VIPS_TYPE_REF_STRING ) { VipsArea *area; area = g_value_get_boxed( &value );