From 7882602dfe47790350a4d6a5ae854c71d476b63e Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 26 Apr 2017 14:52:28 +0100 Subject: [PATCH] C/C++ done python next --- ChangeLog | 2 + TODO | 10 +++++ cplusplus/VImage.cpp | 34 ++------------- cplusplus/include/vips/VImage8.h | 17 +++++++- doc/using-cpp.xml | 23 +++++++++- libvips/include/vips/image.h | 3 ++ libvips/iofuncs/image.c | 74 ++++++++++++++++++++++++++++++++ 7 files changed, 128 insertions(+), 35 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4f7f1f1d..92d0226d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 15/4/17 started 8.6.0 - supports fits images with leading non-image HDUs, thanks benepo +- add vips_image_new_from_image() and vips_image_new_from_image1() ... make a + constant image 23/4/17 started 8.5.5 - doc polishing diff --git a/TODO b/TODO index 36f83c6e..1a7615c3 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,13 @@ +- can we change VImage::new_from_image() to not inherit bands? too awkward to + make a one-band image + + needs some docs + + add to python, C, ruby, php etc etc + +- does cpp image.bandjoin(12) work? how about + bandjoin(std::vector({1, 2})) + - not sure about utf8 error messages on win - strange: diff --git a/cplusplus/VImage.cpp b/cplusplus/VImage.cpp index 27b29fdf..93b2e56e 100644 --- a/cplusplus/VImage.cpp +++ b/cplusplus/VImage.cpp @@ -565,34 +565,6 @@ VImage::new_from_buffer( void *buf, size_t len, const char *option_string, return( out ); } -VImage -VImage::new_from_image( std::vector pixel ) -{ - VImage onepx = VImage::black( 1, 1, - VImage::option()->set( "bands", bands() ) ); - - onepx = (onepx + pixel).cast( format() ); - - VImage big = onepx.embed( 0, 0, width(), height(), - VImage::option()->set( "extend", VIPS_EXTEND_COPY ) ); - - big = big.copy( - VImage::option()-> - set( "interpretation", interpretation() )-> - set( "xres", xres() )-> - set( "yres", yres() )-> - set( "xoffset", xres() )-> - set( "yoffset", yres() ) ); - - return( big ); -} - -VImage -VImage::new_from_image( double pixel ) -{ - return( new_from_image( to_vectorv( 1, pixel ) ) ); -} - VImage VImage::new_matrix( int width, int height ) { @@ -693,10 +665,10 @@ VImage::bandsplit( VOption *options ) VImage VImage::bandjoin( VImage other, VOption *options ) { - VImage v[2] = { *this, other }; - std::vector vec( v, v + VIPS_NUMBER( v ) ); + VImage v[2] = { *this, other }; + std::vector vec( v, v + VIPS_NUMBER( v ) ); - return( bandjoin( vec, options ) ); + return( bandjoin( vec, options ) ); } std::complex diff --git a/cplusplus/include/vips/VImage8.h b/cplusplus/include/vips/VImage8.h index b23a76d8..97a4856f 100644 --- a/cplusplus/include/vips/VImage8.h +++ b/cplusplus/include/vips/VImage8.h @@ -468,8 +468,21 @@ public: static VImage new_matrixv( int width, int height, ... ); - VImage new_from_image( std::vector pixel ); - VImage new_from_image( double pixel ); + VImage new_from_image( std::vector pixel ) + { + VipsImage *image; + + if( !(image = vips_image_new_from_image( this->get_image(), + &pixel[0], pixel.size() )) ) + throw( VError() ); + + return( VImage( image ) ); + } + + VImage new_from_image( double pixel ) + { + return( new_from_image( to_vectorv( 1, pixel ) ) ); + } VImage write( VImage out ); diff --git a/doc/using-cpp.xml b/doc/using-cpp.xml index e739e176..413f4379 100644 --- a/doc/using-cpp.xml +++ b/doc/using-cpp.xml @@ -134,11 +134,30 @@ main( int argc, char **argv ) There are a series of similar constructors which parallel the other constructors in the C API, see VImage::new_from_memory(), - VImage::new_from_buffer(), and VImage::new_matrix(). There's also + VImage::new_from_buffer(), and VImage::new_matrix(). + + + + The convenience function `VImage::new_from_image()` makes a constant + image from an existing image. The image it returns will have the same + size, interpretation, resolution and format as the image you call it on, + but with every pixel having the constant value you specify. For example: + + + new_image = image.new_from_image(12); + + + Now `new_image` has the same size as `image`, but has one band, and every + pixel has the value 12. You can pass a `std::vector` as the + argument to make a constant image with a different number of bands. + + + + There's also VImage::new_memory() and VImage::new_temp_file(), which when written to with VImage::write() will create whole images on memory or on disc. - + The next line finds the average pixel value, it's the equivalent of the vips_avg() function. The differences from the C API are: diff --git a/libvips/include/vips/image.h b/libvips/include/vips/image.h index 3f9fe380..703716a2 100644 --- a/libvips/include/vips/image.h +++ b/libvips/include/vips/image.h @@ -452,6 +452,9 @@ VipsImage *vips_image_new_matrix_from_array( int width, int height, const double *array, int size ); VipsImage *vips_image_matrix_from_array( int width, int height, const double *array, int size ); +VipsImage *vips_image_new_from_image( VipsImage *image, const double *c, int n ); +VipsImage *vips_image_new_from_image1( VipsImage *image, double c ); + void vips_image_set_delete_on_close( VipsImage *image, gboolean delete_on_close ); guint64 vips_get_disc_threshold( void ); diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c index d8c7e743..f7deb53e 100644 --- a/libvips/iofuncs/image.c +++ b/libvips/iofuncs/image.c @@ -2292,6 +2292,80 @@ vips_image_matrix_from_array( int width, int height, array, size ) ); } +/** + * vips_image_new_from_image: + * @image: image to copy + * @c: (array length=n) (transfer none): array of constants + * @n: number of constants + * + * Creates a new image with width, height, format, interpretation, resolution + * and offset taken from @image, but with number of bands taken from @n and the + * value of each band element set from @c. + * + * See also: vips_image_new_from_image1() + * + * Returns: (transfer full): the new #VipsImage, or %NULL on error. + */ +VipsImage * +vips_image_new_from_image( VipsImage *image, const double *c, int n ) +{ + VipsObject *scope = (VipsObject *) vips_image_new(); + VipsImage **t = (VipsImage **) vips_object_local_array( scope, 5 ); + + double *ones; + int i; + VipsImage *result; + + if( !(ones = VIPS_ARRAY( scope, n, double )) ) { + g_object_unref( scope ); + return( NULL ); + } + for( i = 0; i < n; i++ ) + ones[i] = 1.0; + + if( vips_black( &t[0], 1, 1, NULL ) || + vips_linear( t[0], &t[1], ones, (double *) c, n, NULL ) || + vips_cast( t[1], &t[2], image->BandFmt, NULL ) || + vips_embed( t[2], &t[3], 0, 0, image->Xsize, image->Ysize, + "extend", VIPS_EXTEND_COPY, NULL ) || + vips_copy( t[3], &t[4], + "interpretation", image->Type, + "xres", image->Xres, + "yres", image->Yres, + "xoffset", image->Xoffset, + "yoffset", image->Yoffset, + NULL ) ) { + g_object_unref( scope ); + return( NULL ); + } + + result = t[4]; + g_object_ref( result ); + + g_object_unref( scope ); + + return( result ); +} + +/** + * vips_image_new_from_image1: + * @image: image to copy + * @c: constants + * + * Creates a new image with width, height, format, interpretation, resolution + * and offset taken from @image, but with one band and each pixel having the + * value @c. + * + * See also: vips_image_new_from_image() + * + * Returns: (transfer full): the new #VipsImage, or %NULL on error. + */ +VipsImage * +vips_image_new_from_image1( VipsImage *image, double c ) +{ + return( vips_image_new_from_image( image, (const double *) &c, 1 ) ); +} + /** * vips_image_set_delete_on_close: * @image: image to set