From 6144aecccb972cd241e7e90b9c8c0d3f23ec68a2 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sat, 19 Apr 2014 16:14:54 +0100 Subject: [PATCH 1/6] start adding tiff load from buffer see https://github.com/jcupitt/libvips/issues/25 --- libvips/foreign/foreign.c | 123 +++++++++++++++-------- libvips/foreign/tiff.h | 9 +- libvips/foreign/tiff2vips.c | 60 ++++++++++++ libvips/foreign/tiffload.c | 173 ++++++++++++++++++++++++++------- libvips/include/vips/foreign.h | 2 + 5 files changed, 289 insertions(+), 78 deletions(-) diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index eb91a9b8..33a01577 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -1651,7 +1651,8 @@ vips_foreign_operation_init( void ) extern GType vips_foreign_save_jpeg_file_get_type( void ); extern GType vips_foreign_save_jpeg_buffer_get_type( void ); extern GType vips_foreign_save_jpeg_mime_get_type( void ); - extern GType vips_foreign_load_tiff_get_type( void ); + extern GType vips_foreign_load_tiff_file_get_type( void ); + extern GType vips_foreign_load_tiff_buffer_get_type( void ); extern GType vips_foreign_save_tiff_get_type( void ); extern GType vips_foreign_load_vips_get_type( void ); extern GType vips_foreign_save_vips_get_type( void ); @@ -1709,7 +1710,8 @@ vips_foreign_operation_init( void ) #endif /*HAVE_LIBWEBP*/ #ifdef HAVE_TIFF - vips_foreign_load_tiff_get_type(); + vips_foreign_load_tiff_file_get_type(); + vips_foreign_load_tiff_buffer_get_type(); vips_foreign_save_tiff_get_type(); #endif /*HAVE_TIFF*/ @@ -1807,6 +1809,44 @@ vips_tiffload( const char *filename, VipsImage **out, ... ) return( result ); } +/** + * vips_tiffload_buffer: + * @buf: memory area to load + * @len: size of memory area + * @out: image to write + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * @page: load this page + * + * Read a TIFF-formatted memory block into a VIPS image. Exactly as + * vips_tiffload(), but read from a memory source. + * + * See also: vips_tiffload(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_tiffload_buffer( void *buf, size_t len, VipsImage **out, ... ) +{ + va_list ap; + VipsArea *area; + int result; + + /* We don't take a copy of the data or free it. + */ + area = vips_area_new_blob( NULL, buf, len ); + + va_start( ap, out ); + result = vips_call_split( "tiffload_buffer", ap, area, out ); + va_end( ap ); + + vips_area_unref( area ); + + return( result ); +} + /** * vips_tiffsave: * @in: image to save @@ -1899,46 +1939,6 @@ vips_tiffsave( VipsImage *in, const char *filename, ... ) return( result ); } -/** - * vips_jpegload_buffer: - * @buf: memory area to load - * @len: size of memory area - * @out: image to write - * @...: %NULL-terminated list of optional named arguments - * - * Read a JPEG-formatted memory block into a VIPS image. It can read most - * 8-bit JPEG images, including CMYK and YCbCr. - * - * This function is handy for processing JPEG image thumbnails. - * - * Caution: on return only the header will have been read, the pixel data is - * not decompressed until the first pixel is read. Therefore you must not free - * @buf until you have read pixel data from @out. - * - * See also: vips_jpegload(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_jpegload_buffer( void *buf, size_t len, VipsImage **out, ... ) -{ - va_list ap; - VipsArea *area; - int result; - - /* We don't take a copy of the data or free it. - */ - area = vips_area_new_blob( NULL, buf, len ); - - va_start( ap, out ); - result = vips_call_split( "jpegload_buffer", ap, area, out ); - va_end( ap ); - - vips_area_unref( area ); - - return( result ); -} - /** * vips_jpegload: * @filename: file to load @@ -2008,6 +2008,45 @@ vips_jpegload( const char *filename, VipsImage **out, ... ) return( result ); } +/** + * vips_jpegload_buffer: + * @buf: memory area to load + * @len: size of memory area + * @out: image to write + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * @shrink: shrink by this much on load + * @fail: fail on warnings + * + * Read a JPEG-formatted memory block into a VIPS image. Exactly as + * vips_jpegload(), but read from a memory buffer. + * + * See also: vips_jpegload(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_jpegload_buffer( void *buf, size_t len, VipsImage **out, ... ) +{ + va_list ap; + VipsArea *area; + int result; + + /* We don't take a copy of the data or free it. + */ + area = vips_area_new_blob( NULL, buf, len ); + + va_start( ap, out ); + result = vips_call_split( "jpegload_buffer", ap, area, out ); + va_end( ap ); + + vips_area_unref( area ); + + return( result ); +} + /** * vips_jpegsave: * @in: image to save diff --git a/libvips/foreign/tiff.h b/libvips/foreign/tiff.h index 5090df53..0813230f 100644 --- a/libvips/foreign/tiff.h +++ b/libvips/foreign/tiff.h @@ -50,12 +50,17 @@ int vips__tiff_write( VipsImage *in, const char *filename, gboolean bigtiff, gboolean rgbjpeg ); -int vips__tiff_read( const char *filename, VipsImage *out, int page, - gboolean readbehind ); int vips__tiff_read_header( const char *filename, VipsImage *out, int page ); +int vips__tiff_read( const char *filename, VipsImage *out, + int page, gboolean readbehind ); gboolean vips__istifftiled( const char *filename ); gboolean vips__istiff( const char *filename ); +int vips__tiff_read_header_buffer( void *buf, size_t len, VipsImage *out, + int page ); +int vips__tiff_read_buffer( void *buf, size_t len, VipsImage *out, + int page, gboolean readbehind ); + #ifdef __cplusplus } #endif /*__cplusplus*/ diff --git a/libvips/foreign/tiff2vips.c b/libvips/foreign/tiff2vips.c index 8ffcc79b..1c0ce49a 100644 --- a/libvips/foreign/tiff2vips.c +++ b/libvips/foreign/tiff2vips.c @@ -1807,4 +1807,64 @@ vips__istiff( const char *filename ) return( FALSE ); } +int +vips__tiff_read_header_buffer( void *buf, size_t len, VipsImage *out, int page ) +{ + ReadTiff *rtiff; + + vips__tiff_init(); + + move the TIFFOpen into readtiff_new + + put the get_dir in there as well + + if( !(rtiff = readtiff_new_buffer( buf, len, out, page, FALSE )) ) + return( -1 ); + + if( !(rtiff->tiff = get_directory( rtiff, rtiff->page )) ) { + vips_error( "tiff2vips", + _( "TIFF does not contain page %d" ), rtiff->page ); + return( -1 ); + } + + if( parse_header( rtiff, out ) ) + return( -1 ); + + return( 0 ); +} + +int +vips__tiff_read_buffer( void *buf, size_t len, VipsImage *out, + int page, gboolean readbehind ) +{ + ReadTiff *rtiff; + +#ifdef DEBUG + printf( "tiff2vips: libtiff version is \"%s\"\n", TIFFGetVersion() ); + printf( "tiff2vips: libtiff starting for %s\n", filename ); +#endif /*DEBUG*/ + + vips__tiff_init(); + + if( !(rtiff = readtiff_new_buffer( buf, len, out, page, readbehind )) ) + return( -1 ); + + if( !(rtiff->tiff = get_directory( rtiff, rtiff->page )) ) { + vips_error( "tiff2vips", + _( "TIFF does not contain page %d" ), rtiff->page ); + return( -1 ); + } + + if( TIFFIsTiled( rtiff->tiff ) ) { + if( read_tilewise( rtiff, out ) ) + return( -1 ); + } + else { + if( read_stripwise( rtiff, out ) ) + return( -1 ); + } + + return( 0 ); +} + #endif /*HAVE_TIFF*/ diff --git a/libvips/foreign/tiffload.c b/libvips/foreign/tiffload.c index cbcff533..1672faf7 100644 --- a/libvips/foreign/tiffload.c +++ b/libvips/foreign/tiffload.c @@ -55,10 +55,6 @@ typedef struct _VipsForeignLoadTiff { VipsForeignLoad parent_object; - /* Filename for load. - */ - char *filename; - /* Load this page. */ int page; @@ -67,11 +63,58 @@ typedef struct _VipsForeignLoadTiff { typedef VipsForeignLoadClass VipsForeignLoadTiffClass; -G_DEFINE_TYPE( VipsForeignLoadTiff, vips_foreign_load_tiff, +G_DEFINE_ABSTRACT_TYPE( VipsForeignLoadTiff, vips_foreign_load_tiff, VIPS_TYPE_FOREIGN_LOAD ); +static void +vips_foreign_load_tiff_class_init( VipsForeignLoadTiffClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *object_class = (VipsObjectClass *) class; + + /* Other libraries may be using libtiff, we want to capture tiff + * warning and error as soon as we can. + * + * This class init will be triggered during startup. + */ + vips__tiff_init(); + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + object_class->nickname = "tiffload_base"; + object_class->description = _( "load tiff" ); + + VIPS_ARG_INT( class, "page", 10, + _( "Page" ), + _( "Load this page from the image" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsForeignLoadTiff, page ), + 0, 100000, 0 ); +} + +static void +vips_foreign_load_tiff_init( VipsForeignLoadTiff *tiff ) +{ + tiff->page = 0; +} + +typedef struct _VipsForeignLoadTiffFile { + VipsForeignLoadTiff parent_object; + + /* Filename for load. + */ + char *filename; + +} VipsForeignLoadTiffFile; + +typedef VipsForeignLoadTiffClass VipsForeignLoadTiffFileClass; + +G_DEFINE_TYPE( VipsForeignLoadTiffFile, vips_foreign_load_tiff_file, + vips_foreign_load_tiff_get_type() ); + static VipsForeignFlags -vips_foreign_load_tiff_get_flags_filename( const char *filename ) +vips_foreign_load_tiff_file_get_flags_filename( const char *filename ) { VipsForeignFlags flags; @@ -85,30 +128,33 @@ vips_foreign_load_tiff_get_flags_filename( const char *filename ) } static VipsForeignFlags -vips_foreign_load_tiff_get_flags( VipsForeignLoad *load ) +vips_foreign_load_tiff_file_get_flags( VipsForeignLoad *load ) { - VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load; + VipsForeignLoadTiffFile *file = (VipsForeignLoadTiffFile *) load; - return( vips_foreign_load_tiff_get_flags_filename( tiff->filename ) ); + return( vips_foreign_load_tiff_file_get_flags_filename( + file->filename ) ); } static int -vips_foreign_load_tiff_header( VipsForeignLoad *load ) +vips_foreign_load_tiff_file_header( VipsForeignLoad *load ) { VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load; + VipsForeignLoadTiffFile *file = (VipsForeignLoadTiffFile *) load; - if( vips__tiff_read_header( tiff->filename, load->out, tiff->page ) ) + if( vips__tiff_read_header( file->filename, load->out, tiff->page ) ) return( -1 ); return( 0 ); } static int -vips_foreign_load_tiff_load( VipsForeignLoad *load ) +vips_foreign_load_tiff_file_load( VipsForeignLoad *load ) { VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load; + VipsForeignLoadTiffFile *file = (VipsForeignLoadTiffFile *) load; - if( vips__tiff_read( tiff->filename, load->real, tiff->page, + if( vips__tiff_read( file->filename, load->real, tiff->page, load->access == VIPS_ACCESS_SEQUENTIAL ) ) return( -1 ); @@ -118,20 +164,13 @@ vips_foreign_load_tiff_load( VipsForeignLoad *load ) const char *vips__foreign_tiff_suffs[] = { ".tif", ".tiff", NULL }; static void -vips_foreign_load_tiff_class_init( VipsForeignLoadTiffClass *class ) +vips_foreign_load_tiff_file_class_init( VipsForeignLoadTiffFileClass *class ) { GObjectClass *gobject_class = G_OBJECT_CLASS( class ); VipsObjectClass *object_class = (VipsObjectClass *) class; VipsForeignClass *foreign_class = (VipsForeignClass *) class; VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class; - /* Other libraries may be using libtiff, we want to capture tiff - * warning and error as soon as we can. - * - * This class init will be triggered during startup. - */ - vips__tiff_init(); - gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; @@ -142,28 +181,94 @@ vips_foreign_load_tiff_class_init( VipsForeignLoadTiffClass *class ) load_class->is_a = vips__istiff; load_class->get_flags_filename = - vips_foreign_load_tiff_get_flags_filename; - load_class->get_flags = vips_foreign_load_tiff_get_flags; - load_class->header = vips_foreign_load_tiff_header; - load_class->load = vips_foreign_load_tiff_load; + vips_foreign_load_tiff_file_get_flags_filename; + load_class->get_flags = vips_foreign_load_tiff_file_get_flags; + load_class->header = vips_foreign_load_tiff_file_header; + load_class->load = vips_foreign_load_tiff_file_load; VIPS_ARG_STRING( class, "filename", 1, _( "Filename" ), _( "Filename to load from" ), VIPS_ARGUMENT_REQUIRED_INPUT, - G_STRUCT_OFFSET( VipsForeignLoadTiff, filename ), + G_STRUCT_OFFSET( VipsForeignLoadTiffFile, filename ), NULL ); - - VIPS_ARG_INT( class, "page", 10, - _( "Page" ), - _( "Load this page from the file" ), - VIPS_ARGUMENT_OPTIONAL_INPUT, - G_STRUCT_OFFSET( VipsForeignLoadTiff, page ), - 0, 100000, 0 ); } static void -vips_foreign_load_tiff_init( VipsForeignLoadTiff *tiff ) +vips_foreign_load_tiff_file_init( VipsForeignLoadTiffFile *file ) +{ +} + +typedef struct _VipsForeignLoadTiffBuffer { + VipsForeignLoadTiff parent_object; + + /* Load from a buffer. + */ + VipsArea *buf; + +} VipsForeignLoadTiffBuffer; + +typedef VipsForeignLoadTiffClass VipsForeignLoadTiffBufferClass; + +G_DEFINE_TYPE( VipsForeignLoadTiffBuffer, vips_foreign_load_tiff_buffer, + vips_foreign_load_tiff_get_type() ); + +static int +vips_foreign_load_tiff_buffer_header( VipsForeignLoad *load ) +{ + VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load; + VipsForeignLoadTiffBuffer *buffer = (VipsForeignLoadTiffBuffer *) load; + + if( vips__tiff_read_header_buffer( + buffer->buf->data, buffer->buf->length, load->out, + tiff->page ) ) + return( -1 ); + + return( 0 ); +} + +static int +vips_foreign_load_tiff_buffer_load( VipsForeignLoad *load ) +{ + VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load; + VipsForeignLoadTiffBuffer *buffer = (VipsForeignLoadTiffBuffer *) load; + + if( vips__tiff_read_buffer( + buffer->buf->data, buffer->buf->length, load->real, + tiff->page, + load->access == VIPS_ACCESS_SEQUENTIAL ) ) + return( -1 ); + + return( 0 ); +} + +static void +vips_foreign_load_tiff_buffer_class_init( + VipsForeignLoadTiffBufferClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class; + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + object_class->nickname = "tiffload_buffer"; + object_class->description = _( "load tiff from buffer" ); + + load_class->header = vips_foreign_load_tiff_buffer_header; + load_class->load = vips_foreign_load_tiff_buffer_load; + + VIPS_ARG_BOXED( class, "buffer", 1, + _( "Buffer" ), + _( "Buffer to load from" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsForeignLoadTiffBuffer, buf ), + VIPS_TYPE_BLOB ); +} + +static void +vips_foreign_load_tiff_buffer_init( VipsForeignLoadTiffBuffer *buffer ) { } diff --git a/libvips/include/vips/foreign.h b/libvips/include/vips/foreign.h index a2ab314f..0e13339a 100644 --- a/libvips/include/vips/foreign.h +++ b/libvips/include/vips/foreign.h @@ -397,6 +397,8 @@ typedef enum { int vips_tiffload( const char *filename, VipsImage **out, ... ) __attribute__((sentinel)); +int vips_tiffload_buffer( void *buf, size_t len, VipsImage **out, ... ) + __attribute__((sentinel)); int vips_tiffsave( VipsImage *in, const char *filename, ... ) __attribute__((sentinel)); From 070c9bd5a7124c9147b2a9738edb5d2cda6a3ba9 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 22 Apr 2014 10:43:13 +0100 Subject: [PATCH 2/6] add load from buffer --- ChangeLog | 1 + libvips/foreign/tiff2vips.c | 192 +++++++++++++++++++++++++++++------- 2 files changed, 159 insertions(+), 34 deletions(-) diff --git a/ChangeLog b/ChangeLog index fdfd72e4..7761c09a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -21,6 +21,7 @@ - vips_system() now supports many input images and you can change image argument order - support 16-bit palette TIFFs, plus palette TIFFs can have an alpha +- add vips_tiffload_buffer() 6/3/14 started 7.38.6 - grey ramp minimum was wrong diff --git a/libvips/foreign/tiff2vips.c b/libvips/foreign/tiff2vips.c index 1c0ce49a..9318679e 100644 --- a/libvips/foreign/tiff2vips.c +++ b/libvips/foreign/tiff2vips.c @@ -144,6 +144,8 @@ * 11/4/14 * - support 16 bits per sample palette images * - palette images can have an alpha + * 22/4/14 + * - add read from buffer */ /* @@ -208,6 +210,8 @@ typedef struct _ReadTiff { /* Parameters. */ char *filename; + void *buf; + size_t len; VipsImage *out; int page; gboolean readbehind; @@ -225,6 +229,10 @@ typedef struct _ReadTiff { */ gboolean memcpy; + /* The current 'file pointer' for memory buffers. + */ + size_t pos; + /* Geometry. */ uint32 twidth, theight; /* Tile size */ @@ -1635,15 +1643,16 @@ readtiff_destroy( VipsObject *object, ReadTiff *rtiff ) } static ReadTiff * -readtiff_new( const char *filename, VipsImage *out, int page, - gboolean readbehind ) +readtiff_new( VipsImage *out, int page, gboolean readbehind ) { ReadTiff *rtiff; if( !(rtiff = VIPS_NEW( out, ReadTiff )) ) return( NULL ); - rtiff->filename = vips_strdup( VIPS_OBJECT( out ), filename ); + rtiff->filename = NULL; + rtiff->buf = NULL; + rtiff->len = 0; rtiff->out = out; rtiff->page = page; rtiff->readbehind = readbehind; @@ -1651,6 +1660,7 @@ readtiff_new( const char *filename, VipsImage *out, int page, rtiff->sfn = NULL; rtiff->client = NULL; rtiff->memcpy = FALSE; + rtiff->pos = 0; rtiff->twidth = 0; rtiff->theight = 0; rtiff->separate = FALSE; @@ -1669,6 +1679,148 @@ readtiff_new( const char *filename, VipsImage *out, int page, return( rtiff ); } +static ReadTiff * +readtiff_new_filename( const char *filename, VipsImage *out, int page, + gboolean readbehind ) +{ + ReadTiff *rtiff; + int i; + + if( !(rtiff = readtiff_new_filename( out, page, readbehind )) ) + return( NULL ); + + rtiff->filename = vips_strdup( VIPS_OBJECT( out ), filename ); + + /* No mmap --- no performance advantage with libtiff, and it burns up + * our VM if the tiff file is large. + */ + if( !(rtiff->tiff = TIFFOpen( filename, "rm" )) ) { + vips_error( "tiff2vips", _( "unable to open \"%s\" for input" ), + filename ); + return( NULL ); + } + + for( i = 0; i < page; i++ ) + if( !TIFFReadDirectory( rtiff->tiff ) ) { + vips_error( "tiff2vips", + _( "TIFF does not contain page %d" ), + rtiff->page ); + return( NULL ); + } + + return( rtiff ); +} + +static tsize_t +my_tiff_read( thandle_t st, tdata_t buffer, tsize_t size ) +{ + ReadTiff *rtiff = (ReadTiff *) st; + + size_t available = rtiff->len - rtiff->pos; + size_t copy = VIPS_MIN( size, available ); + + memcpy( buffer, rtiff->buf + rtiff->pos, copy ); + rtiff->pos += copy; + + return( copy ); +} + +static tsize_t +my_tiff_write( thandle_t st, tdata_t buffer, tsize_t size ) +{ + ReadTiff *rtiff = (ReadTiff *) st; + + g_assert( 0 ); + + return( 0 ); +} + +static int +my_tiff_close( thandle_t ) +{ + ReadTiff *rtiff = (ReadTiff *) st; + + return 0; +} + +static toff_t +my_tiff_seek( thandle_t st, toff_t pos, int whence ) +{ + ReadTiff *rtiff = (ReadTiff *) st; + + if( whence == SEEK_SET ) + rtiff->pos = pos; + else if( whence == SEEK_CUR ) + rtiff->pos += pos; + else if( whence == SEEK_END ) + rtiff->pos = rtiff->len + pos; + else + g_assert( 0 ); + + return( rtiff->pos ); +} + +static toff_t +my_tiff_size( thandle_t st ) +{ + ReadTiff *rtiff = (ReadTiff *) st; + + return( rtiff->len ); +} + +static int +my_tiff_map( thandle_t, tdata_t *, toff_t * ) +{ + ReadTiff *rtiff = (ReadTiff *) st; + + g_assert( 0 ); + + return 0; +} + +static void +my_tiff_unmap( thandle_t, tdata_t, toff_t ) +{ + ReadTiff *rtiff = (ReadTiff *) st; + + g_assert( 0 ); + + return; +} + +static ReadTiff * +readtiff_new_buffer( void *buf, size_t len, VipsImage *out, int page, + gboolean readbehind ) +{ + ReadTiff *rtiff; + int i; + + if( !(rtiff = readtiff_new( out, page, readbehind )) ) + return( NULL ); + + rtiff->buf = buf; + rtiff->len = len; + + if( !(rtiff->tiff = TIFFClientOpen( "Memory", "w", + (thandle_t) rtiff, + my_tiff_read, my_tiff_write, my_tiff_seek, my_tiff_close, + my_tiff_size, my_tiff_map, my_tiff_unmap )) ) { + vips_error( "tiff2vips", "%s", + _( "unable to open memory buffer for input" ) ); + return( NULL ); + } + + for( i = 0; i < page; i++ ) + if( !TIFFReadDirectory( rtiff->tiff ) ) { + vips_error( "tiff2vips", + _( "TIFF does not contain page %d" ), + rtiff->page ); + return( NULL ); + } + + return( rtiff ); +} + /* Pull out the nth directory from a TIFF file. */ static TIFF * @@ -1732,15 +1884,10 @@ vips__tiff_read( const char *filename, VipsImage *out, int page, vips__tiff_init(); - if( !(rtiff = readtiff_new( filename, out, page, readbehind )) ) + if( !(rtiff = readtiff_new_filename( filename, + out, page, readbehind )) ) return( -1 ); - if( !(rtiff->tiff = get_directory( rtiff->filename, rtiff->page )) ) { - vips_error( "tiff2vips", _( "TIFF file does not " - "contain page %d" ), rtiff->page ); - return( -1 ); - } - if( TIFFIsTiled( rtiff->tiff ) ) { if( read_tilewise( rtiff, out ) ) return( -1 ); @@ -1760,16 +1907,9 @@ vips__tiff_read_header( const char *filename, VipsImage *out, int page ) vips__tiff_init(); - if( !(rtiff = readtiff_new( filename, out, page, FALSE )) ) + if( !(rtiff = readtiff_new_filename( filename, out, page, FALSE )) ) return( -1 ); - if( !(rtiff->tiff = get_directory( rtiff->filename, rtiff->page )) ) { - vips_error( "tiff2vips", - _( "TIFF file does not contain page %d" ), - rtiff->page ); - return( -1 ); - } - if( parse_header( rtiff, out ) ) return( -1 ); @@ -1814,19 +1954,9 @@ vips__tiff_read_header_buffer( void *buf, size_t len, VipsImage *out, int page ) vips__tiff_init(); - move the TIFFOpen into readtiff_new - - put the get_dir in there as well - if( !(rtiff = readtiff_new_buffer( buf, len, out, page, FALSE )) ) return( -1 ); - if( !(rtiff->tiff = get_directory( rtiff, rtiff->page )) ) { - vips_error( "tiff2vips", - _( "TIFF does not contain page %d" ), rtiff->page ); - return( -1 ); - } - if( parse_header( rtiff, out ) ) return( -1 ); @@ -1849,12 +1979,6 @@ vips__tiff_read_buffer( void *buf, size_t len, VipsImage *out, if( !(rtiff = readtiff_new_buffer( buf, len, out, page, readbehind )) ) return( -1 ); - if( !(rtiff->tiff = get_directory( rtiff, rtiff->page )) ) { - vips_error( "tiff2vips", - _( "TIFF does not contain page %d" ), rtiff->page ); - return( -1 ); - } - if( TIFFIsTiled( rtiff->tiff ) ) { if( read_tilewise( rtiff, out ) ) return( -1 ); From 39f3204537785bbc8d1b507d1264b7dd8d4f601c Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sun, 20 Apr 2014 10:16:34 +0100 Subject: [PATCH 3/6] fix for new ubuntu --- configure.ac | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index cbbe379d..1f1f0a7f 100644 --- a/configure.ac +++ b/configure.ac @@ -9,7 +9,8 @@ AC_PREREQ(2.62) # gobject-introspection recommends -Wno-portability # foreign stops complaints about a missing README (we use README.md instead) # and missing INSTALL (the standard Gnu INSTALL is not very useful) -AM_INIT_AUTOMAKE([-Wno-portability foreign]) +# subdir-objects lets us have dumy.cc in a subdir +AM_INIT_AUTOMAKE([-Wno-portability foreign subdir-objects]) AC_CONFIG_HEADERS(config.h) AC_CONFIG_MACRO_DIR([m4]) From eef84f8f64e4efd6ef45c7c91979f78f36081ed6 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Mon, 21 Apr 2014 19:24:14 +0100 Subject: [PATCH 4/6] use float div for sigma calc in gaussblur thanks aferrero2707 --- libvips/convolution/gaussblur.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libvips/convolution/gaussblur.c b/libvips/convolution/gaussblur.c index 8b1c253c..c41ea12b 100644 --- a/libvips/convolution/gaussblur.c +++ b/libvips/convolution/gaussblur.c @@ -73,7 +73,7 @@ vips_gaussblur_build( VipsObject *object ) /* Stop at 20% of max ... bit mean, but means mask radius is roughly * right. */ - if( vips_gaussmat( &t[0], gaussblur->radius / 2, 0.2, + if( vips_gaussmat( &t[0], gaussblur->radius / 2.0, 0.2, "separable", TRUE, "integer", gaussblur->precision != VIPS_PRECISION_FLOAT, NULL ) ) @@ -162,8 +162,8 @@ vips_gaussblur_init( VipsGaussblur *gaussblur ) * This operator runs vips_gaussmat() and vips_convsep() for you on an image. * * @radius is not used directly. Instead the standard deviation of - * vips_gaussmat() is set to @radius / 2 and the minimum amplitude set to 20%. - * This gives a mask radius of approximately @radius pixels. + * vips_gaussmat() is set to @radius / 2.0 and the minimum amplitude set to + * 20%. This gives a mask radius of approximately @radius pixels. * * See also: vips_gaussmat(), vips_conv(). * From 3f114033467b9bf2a7551d7372295bafb14c25d0 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 22 Apr 2014 09:29:02 +0100 Subject: [PATCH 5/6] add .vips as an alternative vips suffix helps imagemagick, see http://www.imagemagick.org/discourse-server/viewtopic.php?f=2&t=25445&p=110491#p110491 --- ChangeLog | 1 + libvips/deprecated/format.c | 2 +- libvips/foreign/vipsload.c | 4 ++-- libvips/foreign/vipssave.c | 6 ++++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7761c09a..04a1dffa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -21,6 +21,7 @@ - vips_system() now supports many input images and you can change image argument order - support 16-bit palette TIFFs, plus palette TIFFs can have an alpha +- add ".vips" as an alternative suffix for vips files - add vips_tiffload_buffer() 6/3/14 started 7.38.6 diff --git a/libvips/deprecated/format.c b/libvips/deprecated/format.c index be3849ec..36bbe1c0 100644 --- a/libvips/deprecated/format.c +++ b/libvips/deprecated/format.c @@ -346,7 +346,7 @@ vips_format_get_flags( VipsFormatClass *format, const char *filename ) /* VIPS format class. */ -static const char *vips_suffs[] = { ".v", NULL }; +static const char *vips_suffs[] = { ".v", ".vips", NULL }; int im_isvips( const char *filename ) diff --git a/libvips/foreign/vipsload.c b/libvips/foreign/vipsload.c index 54d7b324..dd8a445f 100644 --- a/libvips/foreign/vipsload.c +++ b/libvips/foreign/vipsload.c @@ -105,7 +105,7 @@ vips_foreign_load_vips_header( VipsForeignLoad *load ) return( 0 ); } -static const char *vips_suffs[] = { ".v", NULL }; +const char *vips__suffs[] = { ".v", ".vips", NULL }; static void vips_foreign_load_vips_class_init( VipsForeignLoadVipsClass *class ) @@ -121,7 +121,7 @@ vips_foreign_load_vips_class_init( VipsForeignLoadVipsClass *class ) object_class->nickname = "vipsload"; object_class->description = _( "load vips from file" ); - foreign_class->suffs = vips_suffs; + foreign_class->suffs = vips__suffs; load_class->is_a = vips_foreign_load_vips_is_a; load_class->get_flags = vips_foreign_load_vips_get_flags; diff --git a/libvips/foreign/vipssave.c b/libvips/foreign/vipssave.c index 47af18fc..74929a80 100644 --- a/libvips/foreign/vipssave.c +++ b/libvips/foreign/vipssave.c @@ -75,7 +75,9 @@ vips_foreign_save_vips_build( VipsObject *object ) return( 0 ); } -static const char *vips_suffs[] = { ".v", NULL }; +/* From vipsload.c. + */ +extern const char *vips__suffs[]; static void vips_foreign_save_vips_class_init( VipsForeignSaveVipsClass *class ) @@ -94,7 +96,7 @@ vips_foreign_save_vips_class_init( VipsForeignSaveVipsClass *class ) object_class->description = _( "save image to vips file" ); object_class->build = vips_foreign_save_vips_build; - foreign_class->suffs = vips_suffs; + foreign_class->suffs = vips__suffs; save_class->saveable = VIPS_SAVEABLE_ANY; for( i = 0; i < VIPS_CODING_LAST; i++ ) From 567487cb339b56fab4b3c71e3d9cc7d62edf9d50 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 22 Apr 2014 13:19:21 +0100 Subject: [PATCH 6/6] tiff load from buffer done --- libvips/foreign/tiff2vips.c | 47 ++++--------------------------------- libvips/iofuncs/util.c | 11 ++++----- 2 files changed, 9 insertions(+), 49 deletions(-) diff --git a/libvips/foreign/tiff2vips.c b/libvips/foreign/tiff2vips.c index 9318679e..fee5ff68 100644 --- a/libvips/foreign/tiff2vips.c +++ b/libvips/foreign/tiff2vips.c @@ -1686,7 +1686,7 @@ readtiff_new_filename( const char *filename, VipsImage *out, int page, ReadTiff *rtiff; int i; - if( !(rtiff = readtiff_new_filename( out, page, readbehind )) ) + if( !(rtiff = readtiff_new( out, page, readbehind )) ) return( NULL ); rtiff->filename = vips_strdup( VIPS_OBJECT( out ), filename ); @@ -1728,18 +1728,14 @@ my_tiff_read( thandle_t st, tdata_t buffer, tsize_t size ) static tsize_t my_tiff_write( thandle_t st, tdata_t buffer, tsize_t size ) { - ReadTiff *rtiff = (ReadTiff *) st; - g_assert( 0 ); return( 0 ); } static int -my_tiff_close( thandle_t ) +my_tiff_close( thandle_t st ) { - ReadTiff *rtiff = (ReadTiff *) st; - return 0; } @@ -1769,20 +1765,16 @@ my_tiff_size( thandle_t st ) } static int -my_tiff_map( thandle_t, tdata_t *, toff_t * ) +my_tiff_map( thandle_t st, tdata_t *start, toff_t *len ) { - ReadTiff *rtiff = (ReadTiff *) st; - g_assert( 0 ); return 0; } static void -my_tiff_unmap( thandle_t, tdata_t, toff_t ) +my_tiff_unmap( thandle_t st, tdata_t start, toff_t len ) { - ReadTiff *rtiff = (ReadTiff *) st; - g_assert( 0 ); return; @@ -1801,7 +1793,7 @@ readtiff_new_buffer( void *buf, size_t len, VipsImage *out, int page, rtiff->buf = buf; rtiff->len = len; - if( !(rtiff->tiff = TIFFClientOpen( "Memory", "w", + if( !(rtiff->tiff = TIFFClientOpen( "memory buffer", "rm", (thandle_t) rtiff, my_tiff_read, my_tiff_write, my_tiff_seek, my_tiff_close, my_tiff_size, my_tiff_map, my_tiff_unmap )) ) { @@ -1821,35 +1813,6 @@ readtiff_new_buffer( void *buf, size_t len, VipsImage *out, int page, return( rtiff ); } -/* Pull out the nth directory from a TIFF file. - */ -static TIFF * -get_directory( const char *filename, int page ) -{ - TIFF *tif; - int i; - - /* No mmap --- no performance advantage with libtiff, and it burns up - * our VM if the tiff file is large. - */ - if( !(tif = TIFFOpen( filename, "rm" )) ) { - vips_error( "tiff2vips", - _( "unable to open \"%s\" for input" ), - filename ); - return( NULL ); - } - - for( i = 0; i < page; i++ ) - if( !TIFFReadDirectory( tif ) ) { - /* Run out of directories. - */ - TIFFClose( tif ); - return( NULL ); - } - - return( tif ); -} - /* FIXME ... Unused for now, perhaps if we add another format flag. diff --git a/libvips/iofuncs/util.c b/libvips/iofuncs/util.c index 2a816b90..59ebc04d 100644 --- a/libvips/iofuncs/util.c +++ b/libvips/iofuncs/util.c @@ -765,16 +765,13 @@ vips__file_open_write( const char *filename, gboolean text_mode ) char * vips__file_read( FILE *fp, const char *filename, unsigned int *length_out ) { - long len; + gint64 len; size_t read; char *str; - /* Find length. - */ - fseek( fp, 0L, 2 ); - len = ftell( fp ); - if( len > 20 * 1024 * 1024 ) { - /* Seems crazy! + len = vips_file_length( fileno( fp ) ); + if( len > 1024 * 1024 * 1024 ) { + /* Over a gb? Seems crazy! */ vips_error( "vips__file_read", _( "\"%s\" too long" ), filename );