From ec093100fbbb7b9d9b7ba3a65710fe5b9793655a Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 26 Jan 2017 20:17:29 +0000 Subject: [PATCH 1/3] use fits_open_diskfile(), not fits_open_file() so we can open any filename ... fits_open_file() parses fits extended filename formats see https://github.com/jcupitt/libvips/issues/584 --- libvips/foreign/fits.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libvips/foreign/fits.c b/libvips/foreign/fits.c index a3ae6613..c7f28e41 100644 --- a/libvips/foreign/fits.c +++ b/libvips/foreign/fits.c @@ -28,6 +28,9 @@ * support for BSCALE / BZERO settings * 17/1/17 * - invalidate operation on read error + * 26/1/17 aferrero2707 + * - use fits_open_diskfile(), not fits_open_file() ... we don't want the + * extended filename syntax */ /* @@ -182,7 +185,7 @@ vips_fits_new_read( const char *filename, VipsImage *out, int band_select ) G_CALLBACK( vips_fits_close_cb ), fits ); status = 0; - if( fits_open_file( &fits->fptr, filename, READONLY, &status ) ) { + if( fits_open_diskfile( &fits->fptr, filename, READONLY, &status ) ) { vips_error( "fits", _( "unable to open \"%s\"" ), filename ); vips_fits_error( status ); return( NULL ); @@ -556,10 +559,11 @@ vips__fits_isfits( const char *filename ) status = 0; - if( fits_open_image( &fptr, filename, READONLY, &status ) ) { + if( fits_open_diskfile( &fptr, filename, READONLY, &status ) ) { VIPS_DEBUG_MSG( "isfits: error reading \"%s\"\n", filename ); #ifdef VIPS_DEBUG vips_fits_error( status ); + VIPS_DEBUG_MSG( "isfits: %s\n", vips_error_buffer() ); #endif /*VIPS_DEBUG*/ return( 0 ); From 94434c23594fec1bad4c6168b1fe5060b6afab8e Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Fri, 27 Jan 2017 10:32:47 +0000 Subject: [PATCH 2/3] tiff buffer loader supports get_flags the tiff buffer loader was not setting any flags, so seq was using a temp file (for example) see https://github.com/jcupitt/libvips/issues/590 --- libvips/foreign/foreign.c | 2 +- libvips/foreign/pforeign.h | 7 +++++-- libvips/foreign/tiff2vips.c | 25 +++++++++++++++++++++++++ libvips/foreign/tiffload.c | 19 +++++++++++++++++++ 4 files changed, 50 insertions(+), 3 deletions(-) diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index 1ae36130..921344df 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -1479,7 +1479,7 @@ vips_foreign_save_class_init( VipsForeignSaveClass *class ) object_class->nickname = "filesave"; object_class->description = _( "file savers" ); - /* All savers are seqential by definition. Things like tiled tiff + /* All savers are sequential by definition. Things like tiled tiff * write and interlaced png write, which are not, add extra caches * on their input. */ diff --git a/libvips/foreign/pforeign.h b/libvips/foreign/pforeign.h index 4dfe0380..26804bee 100644 --- a/libvips/foreign/pforeign.h +++ b/libvips/foreign/pforeign.h @@ -69,9 +69,12 @@ int vips__tiff_read_header( const char *filename, VipsImage *out, int page, int n, gboolean autorotate ); int vips__tiff_read( const char *filename, VipsImage *out, int page, int n, gboolean autorotate, gboolean readbehind ); -gboolean vips__istifftiled( const char *filename ); -gboolean vips__istiff_buffer( const void *buf, size_t len ); + gboolean vips__istiff( const char *filename ); +gboolean vips__istifftiled( const char *filename ); + +gboolean vips__istiff_buffer( const void *buf, size_t len ); +gboolean vips__istifftiled_buffer( const void *buf, size_t len ); int vips__tiff_read_header_buffer( const void *buf, size_t len, VipsImage *out, int page, int n, gboolean autorotate ); diff --git a/libvips/foreign/tiff2vips.c b/libvips/foreign/tiff2vips.c index b1733c9c..0ea3c541 100644 --- a/libvips/foreign/tiff2vips.c +++ b/libvips/foreign/tiff2vips.c @@ -2352,4 +2352,29 @@ vips__tiff_read_buffer( const void *buf, size_t len, return( 0 ); } +gboolean +vips__istifftiled_buffer( const void *buf, size_t len ) +{ + VipsImage *im; + TIFF *tif; + gboolean tiled; + + vips__tiff_init(); + + im = vips_image_new(); + + if( !(tif = vips__tiff_openin_buffer( im, buf, len )) ) { + g_object_unref( im ); + vips_error_clear(); + return( FALSE ); + } + + tiled = TIFFIsTiled( tif ); + + TIFFClose( tif ); + g_object_unref( im ); + + return( tiled ); +} + #endif /*HAVE_TIFF*/ diff --git a/libvips/foreign/tiffload.c b/libvips/foreign/tiffload.c index 29fd58c4..7e5fb9c2 100644 --- a/libvips/foreign/tiffload.c +++ b/libvips/foreign/tiffload.c @@ -2,6 +2,8 @@ * * 5/12/11 * - from tiffload.c + * 27/1/17 + * - add get_flags for buffer loader */ /* @@ -244,6 +246,22 @@ typedef VipsForeignLoadTiffClass VipsForeignLoadTiffBufferClass; G_DEFINE_TYPE( VipsForeignLoadTiffBuffer, vips_foreign_load_tiff_buffer, vips_foreign_load_tiff_get_type() ); +static VipsForeignFlags +vips_foreign_load_tiff_buffer_get_flags( VipsForeignLoad *load ) +{ + VipsForeignLoadTiffBuffer *buffer = (VipsForeignLoadTiffBuffer *) load; + + VipsForeignFlags flags; + + flags = 0; + if( vips__istifftiled_buffer( buffer->buf->data, buffer->buf->length ) ) + flags |= VIPS_FOREIGN_PARTIAL; + else + flags |= VIPS_FOREIGN_SEQUENTIAL; + + return( flags ); +} + static int vips_foreign_load_tiff_buffer_header( VipsForeignLoad *load ) { @@ -288,6 +306,7 @@ vips_foreign_load_tiff_buffer_class_init( object_class->description = _( "load tiff from buffer" ); load_class->is_a_buffer = vips__istiff_buffer; + load_class->get_flags = vips_foreign_load_tiff_file_get_flags; load_class->header = vips_foreign_load_tiff_buffer_header; load_class->load = vips_foreign_load_tiff_buffer_load; From 756e69cf96320c033d96517923061dfb6032af2e Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Fri, 27 Jan 2017 11:15:48 +0000 Subject: [PATCH 3/3] make pngload from buffer set flags and remove some dead code from jpegload --- libvips/foreign/jpegload.c | 10 ---------- libvips/foreign/pforeign.h | 1 + libvips/foreign/pngload.c | 27 ++++++++++++++++++++++----- libvips/foreign/vipspng.c | 22 ++++++++++++++++++++++ 4 files changed, 45 insertions(+), 15 deletions(-) diff --git a/libvips/foreign/jpegload.c b/libvips/foreign/jpegload.c index 9e53914e..bc0e2559 100644 --- a/libvips/foreign/jpegload.c +++ b/libvips/foreign/jpegload.c @@ -169,14 +169,6 @@ typedef VipsForeignLoadJpegClass VipsForeignLoadJpegFileClass; G_DEFINE_TYPE( VipsForeignLoadJpegFile, vips_foreign_load_jpeg_file, vips_foreign_load_jpeg_get_type() ); -static VipsForeignFlags -vips_foreign_load_jpeg_file_get_flags_filename( const char *filename ) -{ - /* The jpeg reader supports sequential read. - */ - return( VIPS_FOREIGN_SEQUENTIAL ); -} - static gboolean vips_foreign_load_jpeg_file_is_a( const char *filename ) { @@ -232,8 +224,6 @@ vips_foreign_load_jpeg_file_class_init( VipsForeignLoadJpegFileClass *class ) */ foreign_class->priority = 50; - load_class->get_flags_filename = - vips_foreign_load_jpeg_file_get_flags_filename; load_class->is_a = vips_foreign_load_jpeg_file_is_a; load_class->header = vips_foreign_load_jpeg_file_header; load_class->load = vips_foreign_load_jpeg_file_load; diff --git a/libvips/foreign/pforeign.h b/libvips/foreign/pforeign.h index 26804bee..796c1d38 100644 --- a/libvips/foreign/pforeign.h +++ b/libvips/foreign/pforeign.h @@ -183,6 +183,7 @@ int vips__png_read( const char *name, VipsImage *out, gboolean readbehind ); gboolean vips__png_ispng_buffer( const void *buf, size_t len ); int vips__png_ispng( const char *filename ); gboolean vips__png_isinterlaced( const char *filename ); +gboolean vips__png_isinterlaced_buffer( const void *buffer, size_t length ); extern const char *vips__png_suffs[]; int vips__png_read_buffer( const void *buffer, size_t length, VipsImage *out, gboolean readbehind ); diff --git a/libvips/foreign/pngload.c b/libvips/foreign/pngload.c index 7f2f8fc0..f2bb9328 100644 --- a/libvips/foreign/pngload.c +++ b/libvips/foreign/pngload.c @@ -167,12 +167,29 @@ typedef VipsForeignLoadClass VipsForeignLoadPngBufferClass; G_DEFINE_TYPE( VipsForeignLoadPngBuffer, vips_foreign_load_png_buffer, VIPS_TYPE_FOREIGN_LOAD ); +static VipsForeignFlags +vips_foreign_load_png_buffer_get_flags( VipsForeignLoad *load ) +{ + VipsForeignLoadPngBuffer *buffer = (VipsForeignLoadPngBuffer *) load; + + VipsForeignFlags flags; + + flags = 0; + if( vips__png_isinterlaced_buffer( buffer->buf->data, + buffer->buf->length ) ) + flags |= VIPS_FOREIGN_PARTIAL; + else + flags |= VIPS_FOREIGN_SEQUENTIAL; + + return( flags ); +} + static int vips_foreign_load_png_buffer_header( VipsForeignLoad *load ) { - VipsForeignLoadPngBuffer *png = (VipsForeignLoadPngBuffer *) load; + VipsForeignLoadPngBuffer *buffer = (VipsForeignLoadPngBuffer *) load; - if( vips__png_header_buffer( png->buf->data, png->buf->length, + if( vips__png_header_buffer( buffer->buf->data, buffer->buf->length, load->out ) ) return( -1 ); @@ -182,9 +199,9 @@ vips_foreign_load_png_buffer_header( VipsForeignLoad *load ) static int vips_foreign_load_png_buffer_load( VipsForeignLoad *load ) { - VipsForeignLoadPngBuffer *png = (VipsForeignLoadPngBuffer *) load; + VipsForeignLoadPngBuffer *buffer = (VipsForeignLoadPngBuffer *) load; - if( vips__png_read_buffer( png->buf->data, png->buf->length, + if( vips__png_read_buffer( buffer->buf->data, buffer->buf->length, load->real, load->access == VIPS_ACCESS_SEQUENTIAL ) ) return( -1 ); @@ -218,7 +235,7 @@ vips_foreign_load_png_buffer_class_init( VipsForeignLoadPngBufferClass *class ) } static void -vips_foreign_load_png_buffer_init( VipsForeignLoadPngBuffer *png ) +vips_foreign_load_png_buffer_init( VipsForeignLoadPngBuffer *buffer ) { } diff --git a/libvips/foreign/vipspng.c b/libvips/foreign/vipspng.c index cbd6b23f..46324377 100644 --- a/libvips/foreign/vipspng.c +++ b/libvips/foreign/vipspng.c @@ -710,6 +710,28 @@ vips__png_read_buffer( const void *buffer, size_t length, VipsImage *out, return( 0 ); } +/* Interlaced PNGs need to be entirely decompressed into memory then can be + * served partially from there. Non-interlaced PNGs may be read sequentially. + */ +gboolean +vips__png_isinterlaced_buffer( const void *buffer, size_t length ) +{ + VipsImage *image; + Read *read; + int interlace_type; + + image = vips_image_new(); + + if( !(read = read_new_buffer( image, buffer, length, FALSE )) ) { + g_object_unref( image ); + return( -1 ); + } + interlace_type = png_get_interlace_type( read->pPng, read->pInfo ); + g_object_unref( image ); + + return( interlace_type != PNG_INTERLACE_NONE ); +} + const char *vips__png_suffs[] = { ".png", NULL }; /* What we track during a PNG write.