From 11966af8099ea9aaf85059c831e98735383db241 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Fri, 25 Mar 2011 14:48:28 +0000 Subject: [PATCH] fix up im_incheck() and friends sorted out, moved to vips_ --- libvips/include/vips/check.h | 8 - libvips/include/vips/image.h | 6 + libvips/include/vips/vips7compat.h | 9 + libvips/iofuncs/check.c | 512 ++--------------------------- libvips/iofuncs/image.c | 371 ++++++++++++++++++++- libvips/iofuncs/sinkscreen.c | 5 +- libvips/iofuncs/vips7compat.c | 4 +- 7 files changed, 427 insertions(+), 488 deletions(-) diff --git a/libvips/include/vips/check.h b/libvips/include/vips/check.h index d2530797..384e42ab 100644 --- a/libvips/include/vips/check.h +++ b/libvips/include/vips/check.h @@ -36,14 +36,6 @@ extern "C" { #endif /*__cplusplus*/ -int im_rwcheck( VipsImage *im ); -int im_iocheck( VipsImage *in, VipsImage *out ); -int im_incheck( VipsImage *im ); -int im_outcheck( VipsImage *im ); -int im_piocheck( VipsImage *in, VipsImage *out ); -int im_pincheck( VipsImage *im ); -int im_poutcheck( VipsImage *im ); - int im_check_uncoded( const char *domain, VipsImage *im ); int im_check_coding_known( const char *domain, VipsImage *im ); int im_check_coding_labq( const char *domain, VipsImage *im ); diff --git a/libvips/include/vips/image.h b/libvips/include/vips/image.h index 96b6d380..d88ee7d1 100644 --- a/libvips/include/vips/image.h +++ b/libvips/include/vips/image.h @@ -368,6 +368,12 @@ gboolean vips_image_ispartial( VipsImage *image ); int vips_image_write_line( VipsImage *image, int ypos, PEL *linebuffer ); +int vips_image_wio_input( VipsImage *image ); +int vips_image_wio_output( VipsImage *image ); +int vips_image_inplace( VipsImage *image ); +int vips_image_pio_input( VipsImage *image ); +int vips_image_pio_output( VipsImage *image ); + #ifdef __cplusplus } #endif /*__cplusplus*/ diff --git a/libvips/include/vips/vips7compat.h b/libvips/include/vips/vips7compat.h index b2c7ffc2..4f26b541 100644 --- a/libvips/include/vips/vips7compat.h +++ b/libvips/include/vips/vips7compat.h @@ -307,6 +307,15 @@ VipsDemandStyle im_char2dhint( const char *str ); #define im_free vips_free #define im_strdup vips_strdup +#define im_incheck vips_image_wio_input +#define im_outcheck vips_image_wio_output +#define im_rwcheck vips_image_inplace +#define im_pincheck vips_image_pio_input +#define im_poutcheck vips_image_pio_output + +#define im_iocheck( I, O ) (im_incheck( I ) || im_outcheck( O )) +#define im_piocheck( I, O ) (im_pincheck( I ) || im_poutcheck( O )) + /* Buffer processing. */ typedef void (*im_wrapone_fn)( void *in, void *out, int width, diff --git a/libvips/iofuncs/check.c b/libvips/iofuncs/check.c index 58aa583e..c8554ee6 100644 --- a/libvips/iofuncs/check.c +++ b/libvips/iofuncs/check.c @@ -1,4 +1,4 @@ -/* check IMAGEs in various ways +/* check VipsImages in various ways * * im_iocheck() * Copyright: Nicos Dessipris @@ -40,6 +40,8 @@ * - all the above rolled into this file * - plus chunks of predicate.c * - gtkdoc comments + * 25/3/11 + * - move to vips_ namespace */ /* @@ -63,8 +65,7 @@ */ /* - - These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk +These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk */ @@ -100,462 +101,21 @@ * @see_also: image * @include: vips/vips.h * - * These functions perform simple checks on an #IMAGE, or indicate that you - * intend to use an #IMAGE in a certain way. + * These functions perform simple checks on an #VipsImage, or indicate that you + * intend to use an #VipsImage in a certain way. * - * im_incheck(), im_pincheck() and friends indicate the image IO style you - * intend to use, transforming the underlying #IMAGE structure if + * vips_incheck(), vips_pincheck() and friends indicate the image IO style you + * intend to use, transforming the underlying #VipsImage structure if * necessary. * - * im_check_mono() and friends and convenience functions that test an #IMAGE + * vips_check_mono() and friends and convenience functions that test an + * #VipsImage * for having various properties * and signal an error if the condition is not met. They are useful for * writing image processing operations which can only work on certain types of * image. */ -/* Convert a partial to a setbuf. - */ -static int -convert_ptob( IMAGE *im ) -{ - IMAGE *t1; - - /* Change to VIPS_IMAGE_SETBUF. First, make a memory buffer and copy - * into that. - */ - if( !(t1 = vips_image_new( "t" )) ) - return( -1 ); - if( im_copy( im, t1 ) ) { - g_object_unref( t1 ); - return( -1 ); - } - - /* Copy new stuff in. We can't im__close( im ) and free stuff, as this - * would kill of lots of regions and cause dangling pointers - * elsewhere. - */ - im->dtype = VIPS_IMAGE_SETBUF; - im->data = t1->data; - t1->data = NULL; - - /* Close temp image. - */ - g_object_unref( t1 ); - - return( 0 ); -} - -/* Convert an openin to a mmapin. - */ -static int -convert_otom( IMAGE *im ) -{ - /* just mmap() the whole thing. - */ - if( vips_mapfile( im ) ) - return( -1 ); - im->data = im->baseaddr + im->sizeof_header; - im->dtype = VIPS_IMAGE_MMAPIN; - - return( 0 ); -} - -/** - * im_incheck: - * @im: image to check - * - * Check that an image is readable via the VIPS_IMAGE_ADDR() macro. If it isn't, - * try to transform it so that VIPS_IMAGE_ADDR() can work. - * - * See also: im_outcheck(), im_pincheck(), im_rwcheck(), VIPS_IMAGE_ADDR(). - * - * Returns: 0 on succeess, or -1 on error. - */ -int -im_incheck( IMAGE *im ) -{ - g_assert( vips_object_sanity( VIPS_OBJECT( im ) ) ); - -#ifdef DEBUG_IO - printf( "im_incheck: old-style input for %s\n", im->filename ); -#endif/*DEBUG_IO*/ - - switch( im->dtype ) { - case VIPS_IMAGE_SETBUF: - case VIPS_IMAGE_SETBUF_FOREIGN: - /* Should have been written to. - */ - if( !im->data ) { - vips_error( "im_incheck", - "%s", _( "no image data" ) ); - return( -1 ); - } - - break; - - case VIPS_IMAGE_MMAPIN: - case VIPS_IMAGE_MMAPINRW: - /* Can read from all these, in principle anyway. - */ - break; - - case VIPS_IMAGE_PARTIAL: -#ifdef DEBUG_IO - printf( "im_incheck: converting partial image to WIO\n" ); -#endif/*DEBUG_IO*/ - - /* Change to a setbuf, so our caller can use it. - */ - if( convert_ptob( im ) ) - return( -1 ); - - break; - - case VIPS_IMAGE_OPENIN: -#ifdef DEBUG_IO - printf( "im_incheck: converting openin image for old-style input\n" ); -#endif/*DEBUG_IO*/ - - /* Change to a MMAPIN. - */ - if( convert_otom( im ) ) - return( -1 ); - - break; - - case VIPS_IMAGE_OPENOUT: - /* Close file down and reopen as input. I guess this will only - * work for vips files? - */ -#ifdef DEBUG_IO - printf( "im_incheck: auto-rewind of %s\n", im->filename ); -#endif/*DEBUG_IO*/ - - /* Free any resources the image holds and reset to a base - * state. - */ - vips_object_rewind( VIPS_OBJECT( im ) ); - - /* And reopen .. recurse to get a mmaped image. - */ - g_object_set( im, - "mode", "r", - NULL ); - if( vips_object_build( VIPS_OBJECT( im ) ) || - im_incheck( im ) ) { - vips_error( "im_incheck", - _( "auto-rewind for %s failed" ), - im->filename ); - return( -1 ); - } - - break; - - default: - vips_error( "im_incheck", - "%s", _( "image not readable" ) ); - return( -1 ); - } - - return( 0 ); -} - -/** - * im_outcheck: - * @im: image to check - * - * Check that an image is writeable by im_writeline(). If it isn't, - * try to transform it so that im_writeline() can work. - * - * Set the image properties (like size, type and so on), then call - * im_setupout(), then call im_writeline() for each scan line. - * - * See also: im_incheck(), im_poutcheck(). - * - * Returns: 0 on succeess, or -1 on error. - */ -int -im_outcheck( IMAGE *im ) -{ -#ifdef DEBUG_IO - printf( "im_outcheck: old-style output for %s\n", im->filename ); -#endif/*DEBUG_IO*/ - - switch( im->dtype ) { - case VIPS_IMAGE_PARTIAL: - /* Make sure nothing is attached. - */ - if( im->generate ) { - vips_error( "im_outcheck", - "%s", _( "image already written" ) ); - return( -1 ); - } - - /* Cannot do old-style write to PARTIAL. Turn to SETBUF. - */ - im->dtype = VIPS_IMAGE_SETBUF; - - /* Fall through to SETBUF case. - */ - - case VIPS_IMAGE_SETBUF: - /* Check that it has not been im_setupout(). - */ - if( im->data ) { - vips_error( "im_outcheck", - "%s", _( "image already written" ) ); - return( -1 ); - } - - break; - - case VIPS_IMAGE_OPENOUT: - case VIPS_IMAGE_SETBUF_FOREIGN: - /* Can write to this ok. - */ - break; - - default: - vips_error( "im_outcheck", - "%s", _( "image not writeable" ) ); - return( -1 ); - } - - return( 0 ); -} - -/** - * im_iocheck: - * @in: input image - * @out: output image - * - * A convenience function to check a pair of images for IO via VIPS_IMAGE_ADDR() - * and im_writeline(). - * - * See also: im_incheck(), im_outcheck(). - * - * Returns: 0 on succeess, or -1 on error. - */ -int -im_iocheck( IMAGE *in, IMAGE *out ) -{ - return( im_incheck( in ) || im_outcheck( out ) ); -} - -/** - * im_rwcheck: - * @im: image to make read-write - * - * Gets an image ready for an in-place operation, such as im_insertplace(). - * Operations like this both read and write with VIPS_IMAGE_ADDR(). - * - * See also: im_insertplace(), im_incheck(). - * - * Returns: 0 on succeess, or -1 on error. - */ -int -im_rwcheck( IMAGE *im ) -{ - /* Do an im_incheck(). This will rewind im_openout() files, and - * generate im_partial() files. - */ - if( im_incheck( im ) ) { - vips_error( "im_rwcheck", - "%s", _( "unable to rewind file" ) ); - return( -1 ); - } - - /* Look at the type. - */ - switch( im->dtype ) { - case VIPS_IMAGE_SETBUF: - case VIPS_IMAGE_SETBUF_FOREIGN: - case VIPS_IMAGE_MMAPINRW: - /* No action necessary. - */ - break; - - case VIPS_IMAGE_MMAPIN: - /* Try to remap read-write. - */ - if( vips_remapfilerw( im ) ) - return( -1 ); - - break; - - default: - vips_error( "im_rwcheck", - "%s", _( "bad file type" ) ); - return( -1 ); - } - - return( 0 ); -} - -/** - * im_pincheck: - * @im: image to check - * - * Check that an image is readable with im_prepare() and friends. If it isn't, - * try to transform the image so that im_prepare() can work. - * - * See also: im_incheck(), im_poutcheck(), im_prepare(). - * - * Returns: 0 on succeess, or -1 on error. - */ -int -im_pincheck( IMAGE *im ) -{ - g_assert( vips_object_sanity( VIPS_OBJECT( im ) ) ); - -#ifdef DEBUG_IO - printf( "im_pincheck: enabling partial input for %s\n", im->filename ); -#endif /*DEBUG_IO*/ - - switch( im->dtype ) { - case VIPS_IMAGE_SETBUF: - case VIPS_IMAGE_SETBUF_FOREIGN: - /* Should have been written to. - */ - if( !im->data ) { - vips_error( "im_pincheck", "%s", _( "no image data" ) ); - return( -1 ); - } - - /* Should be no generate functions now. - */ - im->start = NULL; - im->generate = NULL; - im->stop = NULL; - - break; - - case VIPS_IMAGE_PARTIAL: - /* Should have had generate functions attached. - */ - if( !im->generate ) { - vips_error( "im_pincheck", "%s", _( "no image data" ) ); - return( -1 ); - } - - break; - - case VIPS_IMAGE_MMAPIN: - case VIPS_IMAGE_MMAPINRW: - case VIPS_IMAGE_OPENIN: - break; - - case VIPS_IMAGE_OPENOUT: - /* Close file down and reopen as im_mmapin. - */ -#ifdef DEBUG_IO - printf( "im_pincheck: auto-rewind of %s\n", im->filename ); -#endif/*DEBUG_IO*/ - - /* Free any resources the image holds and reset to a base - * state. - */ - vips_object_rewind( VIPS_OBJECT( im ) ); - - g_object_set( im, - "mode", "r", - NULL ); - if( vips_object_build( VIPS_OBJECT( im ) ) ) { - vips_error( "im_pincheck", - _( "auto-rewind for %s failed" ), - im->filename ); - return( -1 ); - } - - break; - - default: - vips_error( "im_pincheck", "%s", _( "image not readable" ) ); - return( -1 ); - } - - return( 0 ); -} - -/** - * im_poutcheck: - * @im: image to check - * - * Check that an image is writeable with vips_image_generate(). If it isn't, - * try to transform the image so that vips_image_generate() can work. - * - * See also: im_incheck(), im_poutcheck(), vips_image_generate(). - * - * Returns: 0 on succeess, or -1 on error. - */ -int -im_poutcheck( IMAGE *im ) -{ - if( !im ) { - vips_error( "im_poutcheck", "%s", _( "null image descriptor" ) ); - return( -1 ); - } - -#ifdef DEBUG_IO - printf( "im_pincheck: enabling partial output for %s\n", im->filename ); -#endif /*DEBUG_IO*/ - - switch( im->dtype ) { - case VIPS_IMAGE_SETBUF: - /* Check that it has not been im_setupout(). - */ - if( im->data ) { - vips_error( "im_poutcheck", "%s", - _( "image already written" ) ); - return( -1 ); - } - - break; - - case VIPS_IMAGE_PARTIAL: - /* Make sure nothing is attached. - */ - if( im->generate ) { - vips_error( "im_poutcheck", "%s", - _( "image already written" ) ); - return( -1 ); - } - - break; - - case VIPS_IMAGE_OPENOUT: - case VIPS_IMAGE_SETBUF_FOREIGN: - /* Okeydoke. Not much checking here. - */ - break; - - default: - vips_error( "im_poutcheck", "%s", _( "image not writeable" ) ); - return( -1 ); - } - - return( 0 ); -} - -/** - * im_piocheck: - * @in: input image - * @out: output image - * - * A convenience function to check a pair of images for IO via - * vips_region_prepare() and vips_image_generate(). - * - * See also: im_pincheck(), im_poutcheck(). - * - * Returns: 0 on succeess, or -1 on error. - */ -int -im_piocheck( IMAGE *in, IMAGE *out ) -{ - return( im_pincheck( in ) || im_poutcheck( out ) ); -} - /** * im_check_uncoded: * @domain: the originating domain for the error message @@ -570,7 +130,7 @@ im_piocheck( IMAGE *in, IMAGE *out ) * Returns: 0 on OK, or -1 on error. */ int -im_check_uncoded( const char *domain, IMAGE *im ) +im_check_uncoded( const char *domain, VipsImage *im ) { if( im->Coding != VIPS_CODING_NONE ) { vips_error( domain, "%s", _( "image must be uncoded" ) ); @@ -594,7 +154,7 @@ im_check_uncoded( const char *domain, IMAGE *im ) * Returns: 0 on OK, or -1 on error. */ int -im_check_coding_noneorlabq( const char *domain, IMAGE *im ) +im_check_coding_noneorlabq( const char *domain, VipsImage *im ) { /* These all have codings that extract/ifthenelse/etc can ignore. */ @@ -622,7 +182,7 @@ im_check_coding_noneorlabq( const char *domain, IMAGE *im ) * Returns: 0 on OK, or -1 on error. */ int -im_check_coding_known( const char *domain, IMAGE *im ) +im_check_coding_known( const char *domain, VipsImage *im ) { /* These all have codings that extract/ifthenelse/etc can ignore. */ @@ -650,7 +210,7 @@ im_check_coding_known( const char *domain, IMAGE *im ) * Returns: 0 on OK, or -1 on error. */ int -im_check_coding_rad( const char *domain, IMAGE *im ) +im_check_coding_rad( const char *domain, VipsImage *im ) { if( im->Coding != VIPS_CODING_RAD || im->BandFmt != VIPS_FORMAT_UCHAR || @@ -676,7 +236,7 @@ im_check_coding_rad( const char *domain, IMAGE *im ) * Returns: 0 on OK, or -1 on error. */ int -im_check_coding_labq( const char *domain, IMAGE *im ) +im_check_coding_labq( const char *domain, VipsImage *im ) { if( im->Coding != VIPS_CODING_LABQ || im->BandFmt != VIPS_FORMAT_UCHAR || @@ -702,7 +262,7 @@ im_check_coding_labq( const char *domain, IMAGE *im ) * Returns: 0 if OK, -1 otherwise. */ int -im_check_mono( const char *domain, IMAGE *im ) +im_check_mono( const char *domain, VipsImage *im ) { if( im->Bands != 1 ) { vips_error( domain, "%s", _( "image must one band" ) ); @@ -727,7 +287,7 @@ im_check_mono( const char *domain, IMAGE *im ) * Returns: 0 if OK, -1 otherwise. */ int -im_check_bands( const char *domain, IMAGE *im, int bands ) +im_check_bands( const char *domain, VipsImage *im, int bands ) { if( im->Bands != bands ) { vips_error( domain, _( "image must have %d bands" ), bands ); @@ -751,7 +311,7 @@ im_check_bands( const char *domain, IMAGE *im, int bands ) * Returns: 0 if OK, -1 otherwise. */ int -im_check_bands_1or3( const char *domain, IMAGE *im ) +im_check_bands_1or3( const char *domain, VipsImage *im ) { if( im->Bands != 1 && im->Bands != 3 ) { vips_error( domain, "%s", @@ -778,7 +338,7 @@ im_check_bands_1or3( const char *domain, IMAGE *im ) * Returns: 0 on OK, or -1 on error. */ int -im_check_bands_1orn( const char *domain, IMAGE *im1, IMAGE *im2 ) +im_check_bands_1orn( const char *domain, VipsImage *im1, VipsImage *im2 ) { if( im1->Bands != im2->Bands && (im1->Bands != 1 && im2->Bands != 1) ) { @@ -807,7 +367,7 @@ im_check_bands_1orn( const char *domain, IMAGE *im1, IMAGE *im2 ) * Returns: 0 on OK, or -1 on error. */ int -im_check_bands_1orn_unary( const char *domain, IMAGE *im, int n ) +im_check_bands_1orn_unary( const char *domain, VipsImage *im, int n ) { if( im->Bands != 1 && im->Bands != n ) { vips_error( domain, _( "image must have 1 or %d bands" ), n ); @@ -831,7 +391,7 @@ im_check_bands_1orn_unary( const char *domain, IMAGE *im, int n ) * Returns: 0 if OK, -1 otherwise. */ int -im_check_noncomplex( const char *domain, IMAGE *im ) +im_check_noncomplex( const char *domain, VipsImage *im ) { if( vips_bandfmt_iscomplex( im->BandFmt ) ) { vips_error( domain, "%s", _( "image must be non-complex" ) ); @@ -855,7 +415,7 @@ im_check_noncomplex( const char *domain, IMAGE *im ) * Returns: 0 if OK, -1 otherwise. */ int -im_check_complex( const char *domain, IMAGE *im ) +im_check_complex( const char *domain, VipsImage *im ) { if( !vips_bandfmt_iscomplex( im->BandFmt ) ) { vips_error( domain, "%s", _( "image must be complex" ) ); @@ -880,7 +440,7 @@ im_check_complex( const char *domain, IMAGE *im ) * Returns: 0 if OK, -1 otherwise. */ int -im_check_format( const char *domain, IMAGE *im, VipsBandFormat fmt ) +im_check_format( const char *domain, VipsImage *im, VipsBandFormat fmt ) { if( im->BandFmt != fmt ) { vips_error( domain, @@ -906,7 +466,7 @@ im_check_format( const char *domain, IMAGE *im, VipsBandFormat fmt ) * Returns: 0 if OK, -1 otherwise. */ int -im_check_int( const char *domain, IMAGE *im ) +im_check_int( const char *domain, VipsImage *im ) { if( !vips_bandfmt_isint( im->BandFmt ) ) { vips_error( domain, "%s", _( "image must be integer" ) ); @@ -930,7 +490,7 @@ im_check_int( const char *domain, IMAGE *im ) * Returns: 0 if OK, -1 otherwise. */ int -im_check_uint( const char *domain, IMAGE *im ) +im_check_uint( const char *domain, VipsImage *im ) { if( !vips_bandfmt_isuint( im->BandFmt ) ) { vips_error( domain, "%s", _( "image must be unsigned integer" ) ); @@ -954,7 +514,7 @@ im_check_uint( const char *domain, IMAGE *im ) * Returns: 0 if OK, -1 otherwise. */ int -im_check_8or16( const char *domain, IMAGE *im ) +im_check_8or16( const char *domain, VipsImage *im ) { if( im->BandFmt != VIPS_FORMAT_UCHAR && im->BandFmt != VIPS_FORMAT_USHORT && @@ -983,7 +543,7 @@ im_check_8or16( const char *domain, IMAGE *im ) * Returns: 0 if OK, -1 otherwise. */ int -im_check_u8or16( const char *domain, IMAGE *im ) +im_check_u8or16( const char *domain, VipsImage *im ) { if( im->BandFmt != VIPS_FORMAT_UCHAR && im->BandFmt != VIPS_FORMAT_USHORT ) { @@ -1008,7 +568,7 @@ im_check_u8or16( const char *domain, IMAGE *im ) * Returns: 0 if OK, -1 otherwise. */ int -im_check_u8or16orf( const char *domain, IMAGE *im ) +im_check_u8or16orf( const char *domain, VipsImage *im ) { if( im->BandFmt != VIPS_FORMAT_UCHAR && im->BandFmt != VIPS_FORMAT_USHORT && @@ -1035,7 +595,7 @@ im_check_u8or16orf( const char *domain, IMAGE *im ) * Returns: 0 if OK, -1 otherwise. */ int -im_check_uintorf( const char *domain, IMAGE *im ) +im_check_uintorf( const char *domain, VipsImage *im ) { if( im->BandFmt != VIPS_FORMAT_UCHAR && im->BandFmt != VIPS_FORMAT_USHORT && @@ -1064,7 +624,7 @@ im_check_uintorf( const char *domain, IMAGE *im ) * Returns: 0 if OK, -1 otherwise. */ int -im_check_size_same( const char *domain, IMAGE *im1, IMAGE *im2 ) +im_check_size_same( const char *domain, VipsImage *im1, VipsImage *im2 ) { if( im1->Xsize != im2->Xsize || im1->Ysize != im2->Ysize ) { vips_error( domain, "%s", _( "images must match in size" ) ); @@ -1089,7 +649,7 @@ im_check_size_same( const char *domain, IMAGE *im1, IMAGE *im2 ) * Returns: 0 if OK, -1 otherwise. */ int -im_check_bands_same( const char *domain, IMAGE *im1, IMAGE *im2 ) +im_check_bands_same( const char *domain, VipsImage *im1, VipsImage *im2 ) { if( im1->Bands != im2->Bands ) { vips_error( domain, "%s", @@ -1116,7 +676,7 @@ im_check_bands_same( const char *domain, IMAGE *im1, IMAGE *im2 ) * Returns: 0 if OK, -1 otherwise. */ int -im_check_bandno( const char *domain, IMAGE *im, int bandno ) +im_check_bandno( const char *domain, VipsImage *im, int bandno ) { if( bandno < -1 || bandno > im->Bands - 1 ) { @@ -1143,7 +703,7 @@ im_check_bandno( const char *domain, IMAGE *im, int bandno ) * Returns: 0 if OK, -1 otherwise. */ int -im_check_format_same( const char *domain, IMAGE *im1, IMAGE *im2 ) +im_check_format_same( const char *domain, VipsImage *im1, VipsImage *im2 ) { if( im1->BandFmt != im2->BandFmt ) { vips_error( domain, "%s", @@ -1169,7 +729,7 @@ im_check_format_same( const char *domain, IMAGE *im1, IMAGE *im2 ) * Returns: 0 if OK, -1 otherwise. */ int -im_check_coding_same( const char *domain, IMAGE *im1, IMAGE *im2 ) +im_check_coding_same( const char *domain, VipsImage *im1, VipsImage *im2 ) { if( im1->Coding != im2->Coding ) { vips_error( domain, "%s", @@ -1194,7 +754,7 @@ im_check_coding_same( const char *domain, IMAGE *im1, IMAGE *im2 ) * Returns: 0 if OK, -1 otherwise. */ int -im_check_vector( const char *domain, int n, IMAGE *im ) +im_check_vector( const char *domain, int n, VipsImage *im ) { if( n != 1 && im->Bands != 1 && n != im->Bands ) { vips_error( domain, @@ -1219,7 +779,7 @@ im_check_vector( const char *domain, int n, IMAGE *im ) * Returns: 0 if OK, -1 otherwise. */ int -im_check_hist( const char *domain, IMAGE *im ) +im_check_hist( const char *domain, VipsImage *im ) { if( im->Xsize != 1 && im->Ysize != 1 ) { vips_error( domain, "%s", diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c index 9aae3aa8..1409139a 100644 --- a/libvips/iofuncs/image.c +++ b/libvips/iofuncs/image.c @@ -729,7 +729,7 @@ open_lazy_start( VipsImage *out, void *a, void *dummy ) if( !lazy->real ) { if( !(lazy->real = lazy_real_image( lazy )) || lazy->format->load( lazy->filename, lazy->real ) || - im_pincheck( lazy->real ) ) { + vips_image_pio_input( lazy->real ) ) { VIPS_UNREF( lazy->real ); return( NULL ); } @@ -1928,4 +1928,373 @@ vips_image_write_line( VipsImage *image, int ypos, PEL *linebuffer ) return( 0 ); } +/* Rewind an output file. + */ +static int +vips_image_rewind_output( VipsImage *image ) +{ +#ifdef DEBUG_IO + printf( "vips_image_rewind_output: %s\n", image->filename ); +#endif/*DEBUG_IO*/ + /* Free any resources the image holds and reset to a base + * state. + */ + vips_object_rewind( VIPS_OBJECT( image ) ); + + /* And reopen .. recurse to get a mmaped image. + */ + g_object_set( image, + "mode", "r", + NULL ); + if( vips_object_build( VIPS_OBJECT( image ) ) ) { + vips_error( "VipsImage", + _( "auto-rewind for %s failed" ), + image->filename ); + return( -1 ); + } + + return( 0 ); +} + +/** + * vips_image_wio_input: + * @image: image to transform + * + * Check that an image is readable via the VIPS_IMAGE_ADDR() macro, that is, + * that the entire image is in memory and all pixels can be read with + * VIPS_IMAGE_ADDR(). + * + * If it + * isn't, try to transform it so that VIPS_IMAGE_ADDR() can work. + * + * See also: vips_image_wio_output(), vips_image_pio_input(), + * vips_image_inplace(), VIPS_IMAGE_ADDR(). + * + * Returns: 0 on succeess, or -1 on error. + */ +int +vips_image_wio_input( VipsImage *image ) +{ + VipsImage *t1; + + g_assert( vips_object_sanity( VIPS_OBJECT( image ) ) ); + +#ifdef DEBUG_IO + printf( "vips_image_wio_input: wio input for %s\n", + image->filename ); +#endif/*DEBUG_IO*/ + + switch( image->dtype ) { + case VIPS_IMAGE_SETBUF: + case VIPS_IMAGE_SETBUF_FOREIGN: + /* Should have been written to. + */ + if( !image->data ) { + vips_error( "vips_image_wio_input", + "%s", _( "no image data" ) ); + return( -1 ); + } + + break; + + case VIPS_IMAGE_MMAPIN: + case VIPS_IMAGE_MMAPINRW: + /* Can read from all these, in principle anyway. + */ + break; + + case VIPS_IMAGE_PARTIAL: +#ifdef DEBUG_IO + printf( "im_incheck: converting partial image to WIO\n" ); +#endif/*DEBUG_IO*/ + + /* Change to VIPS_IMAGE_SETBUF. First, make a memory + * buffer and copy into that. + */ + if( !(t1 = vips_image_new( "t" )) ) + return( -1 ); + if( im_copy( image, t1 ) ) { + g_object_unref( t1 ); + return( -1 ); + } + + /* Copy new stuff in. We can't unref and free stuff, as this + * would kill of lots of regions and cause dangling pointers + * elsewhere. + */ + image->dtype = VIPS_IMAGE_SETBUF; + image->data = t1->data; + t1->data = NULL; + + /* Close temp image. + */ + g_object_unref( t1 ); + + break; + + case VIPS_IMAGE_OPENIN: +#ifdef DEBUG_IO + printf( "im_incheck: converting openin image for wio input\n" ); +#endif/*DEBUG_IO*/ + + /* just mmap() the whole thing. + */ + if( vips_mapfile( image ) ) + return( -1 ); + image->data = image->baseaddr + image->sizeof_header; + image->dtype = VIPS_IMAGE_MMAPIN; + + break; + + case VIPS_IMAGE_OPENOUT: + /* Close file down and reopen as input. I guess this will only + * work for vips files? + */ + if( vips_image_rewind_output( image ) || + vips_image_wio_input( image ) ) + return( -1 ); + + break; + + default: + vips_error( "vips_image_wio_input", + "%s", _( "image not readable" ) ); + return( -1 ); + } + + return( 0 ); +} + +/** + * vips_image_wio_output: + * @image: image to check + * + * Check that an image is writeable by vips_image_write_line(). If it isn't, + * try to transform it so that vips_image_write_line() can work. + * + * See also: vips_image_wio_input(). + * + * Returns: 0 on succeess, or -1 on error. + */ +int +vips_image_wio_output( VipsImage *image ) +{ +#ifdef DEBUG_IO + printf( "vips_image_wio_output: WIO output for %s\n", + image->filename ); +#endif/*DEBUG_IO*/ + + switch( image->dtype ) { + case VIPS_IMAGE_PARTIAL: + /* Make sure nothing is attached. + */ + if( image->generate ) { + vips_error( "vips_image_wio_output", + "%s", _( "image already written" ) ); + return( -1 ); + } + + /* Cannot do old-style write to PARTIAL. Turn to SETBUF. + */ + image->dtype = VIPS_IMAGE_SETBUF; + + /* Fall through to SETBUF case. + */ + + case VIPS_IMAGE_SETBUF: + if( image->data ) { + vips_error( "vips_image_wio_output", + "%s", _( "image already written" ) ); + return( -1 ); + } + + break; + + case VIPS_IMAGE_OPENOUT: + case VIPS_IMAGE_SETBUF_FOREIGN: + /* Can write to this ok. + */ + break; + + default: + vips_error( "vips_image_wio_output", + "%s", _( "image not writeable" ) ); + return( -1 ); + } + + return( 0 ); +} + +/** + * vips_image_inplace: + * @image: image to make read-write + * + * Gets @image ready for an in-place operation, such as im_insertplace(). + * Operations like this both read and write with VIPS_IMAGE_ADDR(). + * + * See also: im_insertplace(), vips_image_wio_input(). + * + * Returns: 0 on succeess, or -1 on error. + */ +int +vips_image_inplace( VipsImage *image ) +{ + /* Do an vips_image_wio_input(). This will rewind, generate, etc. + */ + if( vips_image_wio_input( image ) ) + return( -1 ); + + /* Look at the type. + */ + switch( image->dtype ) { + case VIPS_IMAGE_SETBUF: + case VIPS_IMAGE_SETBUF_FOREIGN: + case VIPS_IMAGE_MMAPINRW: + /* No action necessary. + */ + break; + + case VIPS_IMAGE_MMAPIN: + /* Try to remap read-write. + */ + if( vips_remapfilerw( image ) ) + return( -1 ); + + break; + + default: + vips_error( "vips_image_inplace", + "%s", _( "bad file type" ) ); + return( -1 ); + } + + return( 0 ); +} + +/** + * vips_image_pio_input: + * @image: image to check + * + * Check that an image is readable with vips_region_prepare() and friends. + * If it isn't, try to transform the image so that vips_region_prepare() can + * work. + * + * See also: vips_image_pio_output(), vips_region_prepare(). + * + * Returns: 0 on succeess, or -1 on error. + */ +int +vips_image_pio_input( VipsImage *image ) +{ + g_assert( vips_object_sanity( VIPS_OBJECT( image ) ) ); + +#ifdef DEBUG_IO + printf( "vips_image_pio_input: enabling partial input for %s\n", + image->filename ); +#endif /*DEBUG_IO*/ + + switch( image->dtype ) { + case VIPS_IMAGE_SETBUF: + case VIPS_IMAGE_SETBUF_FOREIGN: + /* Should have been written to. + */ + if( !image->data ) { + vips_error( "vips_image_pio_input", + "%s", _( "no image data" ) ); + return( -1 ); + } + + /* Should be no generate functions now. + */ + image->start = NULL; + image->generate = NULL; + image->stop = NULL; + + break; + + case VIPS_IMAGE_PARTIAL: + /* Should have had generate functions attached. + */ + if( !image->generate ) { + vips_error( "vips_image_pio_input", + "%s", _( "no image data" ) ); + return( -1 ); + } + + break; + + case VIPS_IMAGE_MMAPIN: + case VIPS_IMAGE_MMAPINRW: + case VIPS_IMAGE_OPENIN: + break; + + case VIPS_IMAGE_OPENOUT: + + /* Free any resources the image holds and reset to a base + * state. + */ + if( vips_image_rewind_output( image ) ) + return( -1 ); + + break; + + default: + vips_error( "im_pincheck", "%s", _( "image not readable" ) ); + return( -1 ); + } + + return( 0 ); +} + +/** + * vips_image_pio_output: + * @image: image to check + * + * Check that an image is writeable with vips_image_generate(). If it isn't, + * try to transform the image so that vips_image_generate() can work. + * + * See also: vips_image_pio_input(). + * + * Returns: 0 on succeess, or -1 on error. + */ +int +vips_image_pio_output( VipsImage *image ) +{ +#ifdef DEBUG_IO + printf( "vips_image_pio_output: enabling partial output for %s\n", + image->filename ); +#endif /*DEBUG_IO*/ + + switch( image->dtype ) { + case VIPS_IMAGE_SETBUF: + if( image->data ) { + vips_error( "im_poutcheck", "%s", + _( "image already written" ) ); + return( -1 ); + } + + break; + + case VIPS_IMAGE_PARTIAL: + if( image->generate ) { + vips_error( "im_poutcheck", "%s", + _( "image already written" ) ); + return( -1 ); + } + + break; + + case VIPS_IMAGE_OPENOUT: + case VIPS_IMAGE_SETBUF_FOREIGN: + break; + + default: + vips_error( "vips_image_pio_output", + "%s", _( "image not writeable" ) ); + return( -1 ); + } + + return( 0 ); +} + diff --git a/libvips/iofuncs/sinkscreen.c b/libvips/iofuncs/sinkscreen.c index 3460e8a9..56a47113 100644 --- a/libvips/iofuncs/sinkscreen.c +++ b/libvips/iofuncs/sinkscreen.c @@ -1087,12 +1087,13 @@ vips_sink_screen( VipsImage *in, VipsImage *out, VipsImage *mask, return( -1 ); } - if( im_piocheck( in, out ) || + if( vips_image_pio_input( in ) || + vips_image_pio_output( out ) || vips_image_copy_fields( out, in ) || vips_demand_hint( out, VIPS_DEMAND_STYLE_SMALLTILE, in, NULL ) ) return( -1 ); if( mask ) { - if( im_poutcheck( mask ) || + if( vips_image_pio_output( mask ) || vips_image_copy_fields( mask, in ) || vips_demand_hint( mask, VIPS_DEMAND_STYLE_SMALLTILE, in, NULL ) ) diff --git a/libvips/iofuncs/vips7compat.c b/libvips/iofuncs/vips7compat.c index 85a9ded1..0754677d 100644 --- a/libvips/iofuncs/vips7compat.c +++ b/libvips/iofuncs/vips7compat.c @@ -378,9 +378,11 @@ im_wrapmany( IMAGE **in, IMAGE *out, im_wrapmany_fn fn, void *a, void *b ) /* Check io style. */ - if( im_piocheck( in[i], out ) ) + if( vips_image_pio_input( in[i] ) ) return( -1 ); } + if( vips_image_pio_output( out ) ) + return( -1 ); /* Hint demand style. Being a buffer processor, we are happiest with * thin strips.