diff --git a/libvips/foreign/radiance.c b/libvips/foreign/radiance.c index e8f0dc2b..bdcf84c1 100644 --- a/libvips/foreign/radiance.c +++ b/libvips/foreign/radiance.c @@ -985,15 +985,10 @@ vips__rad_israd( const char *filename ) } static void -read_minimise( VipsObject *object, Read *read ) +read_destroy( VipsObject *object, Read *read ) { VIPS_FREEF( buffer_free, read->buffer ); VIPS_FREEF( fclose, read->fin ); -} - -static void -read_destroy( VipsObject *object, Read *read ) -{ VIPS_FREE( read->filename ); } @@ -1024,8 +1019,6 @@ read_new( const char *filename, VipsImage *out ) read->prims[3][1] = CIE_y_w; read->buffer = NULL; - g_signal_connect( out, "minimise", - G_CALLBACK( read_minimise ), read ); g_signal_connect( out, "close", G_CALLBACK( read_destroy ), read ); diff --git a/libvips/foreign/vipspng.c b/libvips/foreign/vipspng.c index 1ee5aba4..0d63b71f 100644 --- a/libvips/foreign/vipspng.c +++ b/libvips/foreign/vipspng.c @@ -73,6 +73,8 @@ * - support xmp read/write * 20/4/19 * - allow huge xmp metadata + * 7/10/19 + * - restart after minimise */ /* @@ -167,9 +169,11 @@ typedef struct { png_infop pInfo; png_bytep *row_pointer; - /* For FILE input. + /* For FILE input. If we close and reopen, save the ftell point in + * seek_position. */ FILE *fp; + long seek_position; /* For memory input. */ @@ -179,12 +183,42 @@ typedef struct { } Read; +/* This can be called many times. + */ +static void +read_close_input( Read *read ) +{ +#ifdef DEBUG + printf( "read_close_input:\n" ); +#endif /*DEBUG*/ + + if( read->fp ) { + read->seek_position = ftell( read->fp ); + VIPS_FREEF( fclose, read->fp ); + } +} + +static int +read_open_input( Read *read ) +{ + if( !read->fp && + read->name ) { + if( !(read->fp = + vips__file_open_read( read->name, NULL, FALSE )) ) + return( -1 ); + if( read->seek_position != -1 ) + fseek( read->fp, read->seek_position, SEEK_SET ); + } + + return( 0 ); +} + /* Can be called many times. */ static void read_destroy( Read *read ) { - VIPS_FREEF( fclose, read->fp ); + read_close_input( read ); if( read->pPng ) png_destroy_read_struct( &read->pPng, &read->pInfo, NULL ); VIPS_FREE( read->row_pointer ); @@ -199,17 +233,7 @@ read_close_cb( VipsImage *out, Read *read ) static void read_minimise_cb( VipsImage *out, Read *read ) { - /* Catch errors from png_read_end(). This can fail on a truncated - * file. - */ - if( read->pPng ) { - /* Catch and ignore error returns from png_read_end(). - */ - if( !setjmp( png_jmpbuf( read->pPng ) ) ) - png_read_end( read->pPng, NULL ); - } - - read_destroy( read ); + read_close_input( read ); } static Read * @@ -228,6 +252,7 @@ read_new( VipsImage *out, gboolean fail ) read->pInfo = NULL; read->row_pointer = NULL; read->fp = NULL; + read->seek_position = -1; read->buffer = NULL; read->length = 0; read->read_pos = 0; @@ -289,7 +314,7 @@ read_new_filename( VipsImage *out, const char *name, gboolean fail ) read->name = vips_strdup( VIPS_OBJECT( out ), name ); - if( !(read->fp = vips__file_open_read( name, NULL, FALSE )) ) + if( read_open_input( read ) ) return( NULL ); /* Catch PNG errors from png_read_info(). @@ -553,12 +578,11 @@ vips__png_header( const char *name, VipsImage *out ) Read *read; if( !(read = read_new_filename( out, name, TRUE )) || - png2vips_header( read, out ) ) + png2vips_header( read, out ) ) { + read_close_input( read ); return( -1 ); - - /* Just a header read: we can free the read early and save an fd. - */ - read_destroy( read ); + } + read_close_input( read ); return( 0 ); } @@ -621,6 +645,9 @@ png2vips_generate( VipsRegion *or, g_assert( r->height == VIPS_MIN( VIPS__FATSTRIP_HEIGHT, or->im->Ysize - r->top ) ); + if( read_open_input( read ) ) + return( -1 ); + /* And check that y_pos is correct. It should be, since we are inside * a vips_sequential(). */ @@ -738,6 +765,10 @@ png2vips_image( Read *read, VipsImage *out ) return( -1 ); } + /* _generate will reopen. + */ + read_close_input( read ); + return( 0 ); } diff --git a/test/test_descriptors.sh b/test/test_descriptors.sh index ad7c805f..4ce21404 100755 --- a/test/test_descriptors.sh +++ b/test/test_descriptors.sh @@ -22,3 +22,7 @@ fi if test_supported pdfload; then ./test_descriptors $test_images/ISO_12233-reschart.pdf fi + +if test_supported pngload; then + ./test_descriptors $test_images/sample.png +fi