diff --git a/cplusplus/include/vips/VImage8.h b/cplusplus/include/vips/VImage8.h index 99b61a3b..b2f29c28 100644 --- a/cplusplus/include/vips/VImage8.h +++ b/cplusplus/include/vips/VImage8.h @@ -550,6 +550,23 @@ public: return( new_from_image( to_vectorv( 1, pixel ) ) ); } + static VImage + new_from_memory_steal( void *data, size_t size, + int width, int height, int bands, VipsBandFormat format ) + { + VipsImage *image; + + if( !(image = vips_image_new_from_memory( data, size, + width, height, bands, format )) ) + throw( VError() ); + + if( g_signal_connect( image, "postclose", + G_CALLBACK(vips_image_free_buffer), data) < 0 ) + throw( VError() ); + + return( VImage( image ) ); + } + VImage copy_memory() const { diff --git a/libvips/include/vips/image.h b/libvips/include/vips/image.h index 01b59968..e766b3fd 100644 --- a/libvips/include/vips/image.h +++ b/libvips/include/vips/image.h @@ -522,6 +522,8 @@ int vips_reorder_prepare_many( VipsImage *image, struct _VipsRegion **regions, VipsRect *r ); void vips_reorder_margin_hint( VipsImage *image, int margin ); +void vips_image_free_buffer( VipsImage* image, void* buffer ); + #ifdef __cplusplus } #endif /*__cplusplus*/ diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c index 2516351d..f115905c 100644 --- a/libvips/iofuncs/image.c +++ b/libvips/iofuncs/image.c @@ -3872,6 +3872,43 @@ vips_band_format_iscomplex( VipsBandFormat format ) } } +/** + * vips_image_free_buffer: + * @image: the image that contains the buffer + * @buffer: the orignal buffer that was stolen + * + * Free the externally allocated buffer found in the input image. This function + * is intened to be used with g_signal_connect, so it can free an externally + * allocated buffer. + */ +void +vips_image_free_buffer( VipsImage* image, void* buffer ) +{ + switch( vips_image_get_format( image ) ) { + case VIPS_FORMAT_UCHAR: + free( (unsigned char*)buffer ); break; + case VIPS_FORMAT_CHAR: + free( (char*)buffer ); break; + case VIPS_FORMAT_USHORT: + free( (unsigned short*)buffer ); break; + case VIPS_FORMAT_SHORT: + free( (short*)buffer ); break; + case VIPS_FORMAT_UINT: + free( (unsigned int*)buffer ); break; + case VIPS_FORMAT_INT: + free( (int*)buffer ); break; + case VIPS_FORMAT_FLOAT: + case VIPS_FORMAT_COMPLEX: + free( (float*)buffer ); break; + case VIPS_FORMAT_DOUBLE: + case VIPS_FORMAT_DPCOMPLEX: + free( (double*)buffer ); break; + + default: + g_assert_not_reached(); + } +} + /* Handy for debugging: view an image in nip2. */ int