From 8f47c75a85cd1795115c304b510859e8f9a53c1a Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 28 Feb 2017 16:44:12 +0000 Subject: [PATCH] tiff uses vipdbuf --- TODO | 5 +++ libvips/foreign/radiance.c | 18 ++++----- libvips/foreign/tiff.c | 52 ++++---------------------- libvips/foreign/vipspng.c | 2 +- libvips/include/vips/dbuf.h | 8 ++-- libvips/iofuncs/dbuf.c | 31 +++++++++++----- libvips/iofuncs/vips.c | 74 ++++++++++++++++++------------------- 7 files changed, 85 insertions(+), 105 deletions(-) diff --git a/TODO b/TODO index e50960d6..95423cd2 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,10 @@ - verify xml data against master for vips save and dzsave +- curious + + $ vips tiffload_buffer images/sample.tif + (vips:18224): GLib-GObject-WARNING **: unable to set property 'buffer' of type 'VipsBlob' from value of type 'gchararray' + Trace/breakpoint trap (core dumped) diff --git a/libvips/foreign/radiance.c b/libvips/foreign/radiance.c index 69e80f59..cb62a4eb 100644 --- a/libvips/foreign/radiance.c +++ b/libvips/foreign/radiance.c @@ -1349,24 +1349,24 @@ vips2rad_put_header_buf( Write *write ) { vips2rad_make_header( write ); - vips_dbuf_appendf( &write->dbuf, "#?RADIANCE\n" ); - vips_dbuf_appendf( &write->dbuf, "%s%s\n", FMTSTR, write->format ); - vips_dbuf_appendf( &write->dbuf, "%s%e\n", EXPOSSTR, write->expos ); - vips_dbuf_appendf( &write->dbuf, "%s %f %f %f\n", + vips_dbuf_writef( &write->dbuf, "#?RADIANCE\n" ); + vips_dbuf_writef( &write->dbuf, "%s%s\n", FMTSTR, write->format ); + vips_dbuf_writef( &write->dbuf, "%s%e\n", EXPOSSTR, write->expos ); + vips_dbuf_writef( &write->dbuf, "%s %f %f %f\n", COLCORSTR, write->colcor[RED], write->colcor[GRN], write->colcor[BLU] ); - vips_dbuf_appendf( &write->dbuf, "SOFTWARE=vips %s\n", + vips_dbuf_writef( &write->dbuf, "SOFTWARE=vips %s\n", vips_version_string() ); - vips_dbuf_appendf( &write->dbuf, "%s%f\n", ASPECTSTR, write->aspect ); - vips_dbuf_appendf( &write->dbuf, + vips_dbuf_writef( &write->dbuf, "%s%f\n", ASPECTSTR, write->aspect ); + vips_dbuf_writef( &write->dbuf, "%s %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f\n", PRIMARYSTR, write->prims[RED][CIEX], write->prims[RED][CIEY], write->prims[GRN][CIEX], write->prims[GRN][CIEY], write->prims[BLU][CIEX], write->prims[BLU][CIEY], write->prims[WHT][CIEX], write->prims[WHT][CIEY] ); - vips_dbuf_appendf( &write->dbuf, "\n" ); - vips_dbuf_appendf( &write->dbuf, "%s", + vips_dbuf_writef( &write->dbuf, "\n" ); + vips_dbuf_writef( &write->dbuf, "%s", resolu2str( resolu_buf, &write->rs ) ); return( 0 ); diff --git a/libvips/foreign/tiff.c b/libvips/foreign/tiff.c index b083adc2..232409c1 100644 --- a/libvips/foreign/tiff.c +++ b/libvips/foreign/tiff.c @@ -298,10 +298,7 @@ vips__tiff_openin_buffer( VipsImage *image, const void *data, size_t length ) */ typedef struct _VipsTiffOpenoutBuffer { - size_t position; - void *data; - size_t allocated; - size_t length; + VipsDbuf dbuf; /* On close, consolidate and write the output here. */ @@ -321,37 +318,12 @@ static tsize_t openout_buffer_write( thandle_t st, tdata_t data, tsize_t size ) { VipsTiffOpenoutBuffer *buffer = (VipsTiffOpenoutBuffer *) st; - size_t new_length = VIPS_MAX( buffer->position + size, buffer->length ); #ifdef DEBUG printf( "openout_buffer_write: %zd bytes\n", size ); #endif /*DEBUG*/ - /* We could make a chain of blocks, but libtiff does a lot of seeking - * during writes, so we'd have to handle writes being - * split over blocks, which would be annoying. - * - * Instead, go for exponential realloc: the number of reallocs grows as - * log(final size), and we never over allocate by more than 30%. - * - * realloc can be very, very slow on Windows, but maybe g_realloc() is - * smarter. - */ - if( new_length > buffer->allocated ) { - buffer->allocated = VIPS_MAX( (16 + buffer->allocated) * 3 / 2, - new_length ); - buffer->data = g_try_realloc( buffer->data, buffer->allocated ); - - if( buffer->data == NULL ) { - vips_error( "tiff memory write", - "%s", _( "Out of memory." ) ); - return( 0 ); - } - } - - memcpy( buffer->data + buffer->position, data, size ); - buffer->position += size; - buffer->length = new_length; + vips_dbuf_write( &buffer->dbuf, data, size ); return( size ); } @@ -361,8 +333,8 @@ openout_buffer_close( thandle_t st ) { VipsTiffOpenoutBuffer *buffer = (VipsTiffOpenoutBuffer *) st; - *(buffer->out_data) = buffer->data; - *(buffer->out_length) = buffer->length; + *(buffer->out_data) = vips_dbuf_steal( &buffer->dbuf, + buffer->out_length); return( 0 ); } @@ -377,16 +349,9 @@ openout_buffer_seek( thandle_t st, toff_t position, int whence ) position, whence ); #endif /*DEBUG*/ - if( whence == SEEK_SET ) - buffer->position = position; - else if( whence == SEEK_CUR ) - buffer->position += position; - else if( whence == SEEK_END ) - buffer->position = buffer->length + position; - else - g_assert_not_reached(); + vips_dbuf_seek( &buffer->dbuf, position, whence ); - return( buffer->position ); + return( vips_dbuf_tell( &buffer->dbuf ) ); } static toff_t @@ -429,10 +394,7 @@ vips__tiff_openout_buffer( VipsImage *image, #endif /*DEBUG*/ buffer = VIPS_NEW( image, VipsTiffOpenoutBuffer ); - buffer->position = 0; - buffer->data = NULL; - buffer->allocated = 0; - buffer->length = 0; + vips_dbuf_init( &buffer->dbuf ); buffer->out_data = out_data; buffer->out_length = out_length; diff --git a/libvips/foreign/vipspng.c b/libvips/foreign/vipspng.c index 4de6fe3c..33bcd21c 100644 --- a/libvips/foreign/vipspng.c +++ b/libvips/foreign/vipspng.c @@ -1016,7 +1016,7 @@ user_write_data( png_structp png_ptr, png_bytep data, png_size_t length ) { Write *write = (Write *) png_get_io_ptr( png_ptr ); - vips_dbuf_append( &write->dbuf, data, length ); + vips_dbuf_write( &write->dbuf, data, length ); } int diff --git a/libvips/include/vips/dbuf.h b/libvips/include/vips/dbuf.h index 58cb5f47..3234dbbe 100644 --- a/libvips/include/vips/dbuf.h +++ b/libvips/include/vips/dbuf.h @@ -37,8 +37,7 @@ extern "C" { #include -/* A buffer in the process of being written to ... multiple calls to - * vips_dbuf_append add to it. +/* A buffer in the process of being written to. */ typedef struct _VipsDbuf { @@ -66,13 +65,14 @@ void vips_dbuf_destroy( VipsDbuf *buf ); void vips_dbuf_init( VipsDbuf *buf ); gboolean vips_dbuf_allocate( VipsDbuf *dbuf, size_t size ); unsigned char *vips_dbuf_get_write( VipsDbuf *dbuf, size_t *size ); -gboolean vips_dbuf_append( VipsDbuf *dbuf, +gboolean vips_dbuf_write( VipsDbuf *dbuf, const unsigned char *data, size_t size ); -gboolean vips_dbuf_appendf( VipsDbuf *dbuf, const char *fmt, ... ); +gboolean vips_dbuf_writef( VipsDbuf *dbuf, const char *fmt, ... ); void vips_dbuf_reset( VipsDbuf *dbuf ); void vips_dbuf_destroy( VipsDbuf *dbuf ); gboolean vips_dbuf_seek( VipsDbuf *dbuf, off_t offset, int whence ); void vips_dbuf_truncate( VipsDbuf *dbuf ); +off_t vips_dbuf_tell( VipsDbuf *dbuf ); unsigned char *vips_dbuf_string( VipsDbuf *dbuf, size_t *size ); unsigned char *vips_dbuf_steal( VipsDbuf *dbuf, size_t *size ); diff --git a/libvips/iofuncs/dbuf.c b/libvips/iofuncs/dbuf.c index f1b7b0e9..2bf9db8a 100644 --- a/libvips/iofuncs/dbuf.c +++ b/libvips/iofuncs/dbuf.c @@ -154,17 +154,17 @@ vips_dbuf_get_write( VipsDbuf *dbuf, size_t *size ) } /** - * vips_dbuf_append: + * vips_dbuf_write: * @dbuf: the buffer - * @data: the data to append to the buffer - * @size: the size of the len to append + * @data: the data to write to the buffer + * @size: the size of the len to write * * Append @size bytes from @data. @dbuf expands if necessary. * * Returns: %FALSE on out of memory, %TRUE otherwise. */ gboolean -vips_dbuf_append( VipsDbuf *dbuf, const unsigned char *data, size_t size ) +vips_dbuf_write( VipsDbuf *dbuf, const unsigned char *data, size_t size ) { if( !vips_dbuf_allocate( dbuf, size ) ) return( FALSE ); @@ -177,17 +177,17 @@ vips_dbuf_append( VipsDbuf *dbuf, const unsigned char *data, size_t size ) } /** - * vips_dbuf_appendf: + * vips_dbuf_writef: * @dbuf: the buffer * @fmt: printf()-style format string * @...: arguments to format string * - * Format the string and append to @dbuf. + * Format the string and write to @dbuf. * * Returns: %FALSE on out of memory, %TRUE otherwise. */ gboolean -vips_dbuf_appendf( VipsDbuf *dbuf, const char *fmt, ... ) +vips_dbuf_writef( VipsDbuf *dbuf, const char *fmt, ... ) { va_list ap; char *line; @@ -196,7 +196,7 @@ vips_dbuf_appendf( VipsDbuf *dbuf, const char *fmt, ... ) line = g_strdup_vprintf( fmt, ap ); va_end( ap ); - if( vips_dbuf_append( dbuf, (unsigned char *) line, strlen( line ) ) ) { + if( vips_dbuf_write( dbuf, (unsigned char *) line, strlen( line ) ) ) { g_free( line ); return( FALSE ); } @@ -278,7 +278,8 @@ vips_dbuf_seek( VipsDbuf *dbuf, off_t offset, int whence ) return( FALSE ); dbuf->write_point = new_write_point; if( dbuf->data_size < dbuf->write_point ) { - memset( dbuf->data, 0, dbuf->write_point - dbuf->data_size ); + memset( dbuf->data + dbuf->data_size, 0, + dbuf->write_point - dbuf->data_size ); dbuf->data_size = dbuf->write_point; } @@ -297,6 +298,18 @@ vips_dbuf_truncate( VipsDbuf *dbuf ) dbuf->data_size = dbuf->write_point; } +/** + * vips_dbuf_truncate: + * @dbuf: the buffer + * + * Truncate the data so that it ends at the write point. No memory is freed. + */ +off_t +vips_dbuf_tell( VipsDbuf *dbuf ) +{ + return( dbuf->write_point ); +} + /** * vips_dbuf_steal: * @dbuf: the buffer diff --git a/libvips/iofuncs/vips.c b/libvips/iofuncs/vips.c index 9b4c3935..a92aa273 100644 --- a/libvips/iofuncs/vips.c +++ b/libvips/iofuncs/vips.c @@ -648,7 +648,7 @@ parser_data_handler( void *user_data, const XML_Char *data, int len ) printf( "parser_data_handler: %d bytes\n", len ); #endif /*DEBUG*/ - vips_dbuf_append( &vep->dbuf, (unsigned char *) data, len ); + vips_dbuf_write( &vep->dbuf, (unsigned char *) data, len ); } /* Called at the end of vips open ... get any XML after the pixel data @@ -718,7 +718,7 @@ vips__write_extension_block( VipsImage *im, void *buf, int size ) /* Append a string to a buffer, but escape " as \". */ static void -dbuf_append_quotes( VipsDbuf *dbuf, const char *str ) +dbuf_write_quotes( VipsDbuf *dbuf, const char *str ) { const char *p; size_t len; @@ -726,16 +726,16 @@ dbuf_append_quotes( VipsDbuf *dbuf, const char *str ) for( p = str; *p; p += len ) { len = strcspn( p, "\"" ); - vips_dbuf_append( dbuf, (unsigned char *) p, len ); + vips_dbuf_write( dbuf, (unsigned char *) p, len ); if( p[len] == '"' ) - vips_dbuf_appendf( dbuf, "\\" ); + vips_dbuf_writef( dbuf, "\\" ); } } /* Append a string to a buffer, but escape &<>. */ static void -dbuf_append_amp( VipsDbuf *dbuf, const char *str ) +dbuf_write_amp( VipsDbuf *dbuf, const char *str ) { const char *p; size_t len; @@ -743,20 +743,20 @@ dbuf_append_amp( VipsDbuf *dbuf, const char *str ) for( p = str; *p; p += len ) { len = strcspn( p, "&<>" ); - vips_dbuf_append( dbuf, (unsigned char *) p, len ); + vips_dbuf_write( dbuf, (unsigned char *) p, len ); switch( p[len] ) { case '&': - vips_dbuf_appendf( dbuf, "&" ); + vips_dbuf_writef( dbuf, "&" ); len += 1; break; case '<': - vips_dbuf_appendf( dbuf, "<" ); + vips_dbuf_writef( dbuf, "<" ); len += 1; break; case '>': - vips_dbuf_appendf( dbuf, ">" ); + vips_dbuf_writef( dbuf, ">" ); len += 1; break; @@ -788,12 +788,12 @@ build_xml_meta( VipsMeta *meta, VipsDbuf *dbuf ) } str = vips_value_get_save_string( &save_value ); - vips_dbuf_appendf( dbuf, " name ); - vips_dbuf_appendf( dbuf, "\">" ); - dbuf_append_amp( dbuf, str ); - vips_dbuf_appendf( dbuf, "\n" ); + dbuf_write_quotes( dbuf, meta->name ); + vips_dbuf_writef( dbuf, "\">" ); + dbuf_write_amp( dbuf, str ); + vips_dbuf_writef( dbuf, "\n" ); g_value_unset( &save_value ); } @@ -811,20 +811,20 @@ build_xml( VipsImage *image ) vips_dbuf_init( &dbuf ); - vips_dbuf_appendf( &dbuf, "\n" ); - vips_dbuf_appendf( &dbuf, "\n", + vips_dbuf_writef( &dbuf, "\n" ); + vips_dbuf_writef( &dbuf, "\n", NAMESPACE_URI, VIPS_MAJOR_VERSION, VIPS_MINOR_VERSION, VIPS_MICRO_VERSION ); - vips_dbuf_appendf( &dbuf, "
\n" ); + vips_dbuf_writef( &dbuf, "
\n" ); str = vips_image_get_history( image ); - vips_dbuf_appendf( &dbuf, " ", + vips_dbuf_writef( &dbuf, " ", g_type_name( VIPS_TYPE_REF_STRING ) ); - dbuf_append_amp( &dbuf, str ); - vips_dbuf_appendf( &dbuf, "\n" ); + dbuf_write_amp( &dbuf, str ); + vips_dbuf_writef( &dbuf, "\n" ); - vips_dbuf_appendf( &dbuf, "
\n" ); - vips_dbuf_appendf( &dbuf, " \n" ); + vips_dbuf_writef( &dbuf, "
\n" ); + vips_dbuf_writef( &dbuf, " \n" ); if( vips_slist_map2( image->meta_traverse, (VipsSListMap2Fn) build_xml_meta, &dbuf, NULL ) ) { @@ -832,8 +832,8 @@ build_xml( VipsImage *image ) return( NULL ); } - vips_dbuf_appendf( &dbuf, " \n" ); - vips_dbuf_appendf( &dbuf, "
\n" ); + vips_dbuf_writef( &dbuf, " \n" ); + vips_dbuf_writef( &dbuf, "
\n" ); return( (char *) vips_dbuf_steal( &dbuf, NULL ) ); } @@ -863,15 +863,15 @@ vips__xml_properties_meta( VipsImage *image, str = vips_value_get_save_string( &save_value ); g_value_unset( &save_value ); - vips_dbuf_appendf( dbuf, " \n" ); - vips_dbuf_appendf( dbuf, " " ); - dbuf_append_amp( dbuf, field ); - vips_dbuf_appendf( dbuf, "\n" ); - vips_dbuf_appendf( dbuf, " ", + vips_dbuf_writef( dbuf, " \n" ); + vips_dbuf_writef( dbuf, " " ); + dbuf_write_amp( dbuf, field ); + vips_dbuf_writef( dbuf, "\n" ); + vips_dbuf_writef( dbuf, " ", g_type_name( type ) ); - dbuf_append_amp( dbuf, str ); - vips_dbuf_appendf( dbuf, "\n" ); - vips_dbuf_appendf( dbuf, " \n" ); + dbuf_write_amp( dbuf, str ); + vips_dbuf_writef( dbuf, "\n" ); + vips_dbuf_writef( dbuf, " \n" ); } return( NULL ); @@ -891,22 +891,22 @@ vips__xml_properties( VipsImage *image ) g_get_current_time( &now ); date = g_time_val_to_iso8601( &now ); - vips_dbuf_appendf( &dbuf, "\n" ); - vips_dbuf_appendf( &dbuf, "\n" ); + vips_dbuf_writef( &dbuf, "\n", NAMESPACE_URI, date, VIPS_MAJOR_VERSION, VIPS_MINOR_VERSION, VIPS_MICRO_VERSION ); g_free( date ); - vips_dbuf_appendf( &dbuf, " \n" ); + vips_dbuf_writef( &dbuf, " \n" ); if( vips_image_map( image, vips__xml_properties_meta, &dbuf ) ) { vips_dbuf_destroy( &dbuf ); return( NULL ); } - vips_dbuf_appendf( &dbuf, " \n" ); - vips_dbuf_appendf( &dbuf, "\n" ); + vips_dbuf_writef( &dbuf, " \n" ); + vips_dbuf_writef( &dbuf, "\n" ); return( (char *) vips_dbuf_steal( &dbuf, NULL ) ); }