From 1ba188dc83aa8a51a0183dba091048fe329fef60 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 4 Jul 2013 09:43:57 +0100 Subject: [PATCH] better file format sniffing and vips_error_freeze/thaw() to stop errors from sniffing being logged plus better matrix sniffing --- ChangeLog | 2 ++ libvips/foreign/analyze2vips.c | 17 +++++++++----- libvips/foreign/csv.c | 28 +++++++++++++++++++++++ libvips/foreign/csv.h | 1 + libvips/foreign/magickload.c | 10 ++++---- libvips/foreign/matlab.c | 7 +++--- libvips/foreign/matrixload.c | 1 + libvips/foreign/openslide2vips.c | 6 ++++- libvips/include/vips/error.h | 3 +++ libvips/iofuncs/error.c | 39 +++++++++++++++++++++++++++++--- 10 files changed, 96 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4fdc1135..d8fa6c5a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,8 @@ - rename image arrays as image matrices ... INTERPRETATION_ARRAY -> INTERPRETATION_MATRIX etc. - convert im_buildlut(), im_identity*() to classes +- added vips_error_freeze()/vips_error_thaw() +- used freeze()/thaw() to stop file format sniffers logging spurious errors 3/7/13 started 7.34.2 - lower priority for Matlab load to reduce segvs from Mat_Open(), thanks diff --git a/libvips/foreign/analyze2vips.c b/libvips/foreign/analyze2vips.c index 9574bfa6..6413f79f 100644 --- a/libvips/foreign/analyze2vips.c +++ b/libvips/foreign/analyze2vips.c @@ -492,24 +492,29 @@ vips__isanalyze( const char *filename ) int width, height; int bands; VipsBandFormat fmt; + int result; generate_filenames( filename, header, image ); if( !vips_existsf( "%s", header ) ) return( 0 ); - if( !(d = read_header( header )) ) + + vips_error_freeze(); + d = read_header( header ); + vips_error_thaw(); + if( !d ) return( 0 ); #ifdef DEBUG print_dsr( d ); #endif /*DEBUG*/ - if( get_vips_properties( d, &width, &height, &bands, &fmt ) ) { - vips_free( d ); - return( 0 ); - } + vips_error_freeze(); + result = get_vips_properties( d, &width, &height, &bands, &fmt ); + vips_error_thaw(); + vips_free( d ); - return( 1 ); + return( result == 0 ); } int diff --git a/libvips/foreign/csv.c b/libvips/foreign/csv.c index 0c1cdde9..c6794d0d 100644 --- a/libvips/foreign/csv.c +++ b/libvips/foreign/csv.c @@ -482,6 +482,7 @@ read_ascii_double( FILE *fp, const char whitemap[256], double *out ) { int ch; char buf[256]; + char *p; ch = skip_white( fp, whitemap ); @@ -491,6 +492,16 @@ read_ascii_double( FILE *fp, const char whitemap[256], double *out ) fetch_nonwhite( fp, whitemap, buf, 256 ); + /* The str we fetched must contain at least 1 digit. This helps stop + * us trying to convert "MATLAB" (for example) to a number and + * getting zero. + */ + for( p = buf; *p; p++ ) + if( isdigit( *p ) ) + break; + if( !*p ) + return( *buf ); + *out = g_ascii_strtod( buf, NULL ); return( 0 ); @@ -603,6 +614,23 @@ vips__matrix_read_header( const char *filename, return( 0 ); } +int +vips__matrix_ismatrix( const char *filename ) +{ + int width; + int height; + double scale; + double offset; + int result; + + vips_error_freeze(); + result = vips__matrix_read_header( filename, + &width, &height, &scale, &offset ); + vips_error_thaw(); + + return( result == 0 ); +} + static int vips__matrix_body( char *whitemap, VipsImage *out, FILE *fp ) { diff --git a/libvips/foreign/csv.h b/libvips/foreign/csv.h index ed4d8d17..7f868c3c 100644 --- a/libvips/foreign/csv.h +++ b/libvips/foreign/csv.h @@ -47,6 +47,7 @@ int vips__csv_write( VipsImage *in, const char *filename, int vips__matrix_read_header( const char *filename, int *width, int *height, double *scale, double *offset ); +int vips__matrix_ismatrix( const char *filename ); VipsImage *vips__matrix_read( const char *filename ); int vips__matrix_write( VipsImage *in, const char *filename ); diff --git a/libvips/foreign/magickload.c b/libvips/foreign/magickload.c index 2f9bc3c0..5d9b1484 100644 --- a/libvips/foreign/magickload.c +++ b/libvips/foreign/magickload.c @@ -73,15 +73,15 @@ static gboolean ismagick( const char *filename ) { VipsImage *t; + int result; t = vips_image_new(); - if( vips__magick_read_header( filename, t, FALSE ) ) { - g_object_unref( t ); - return( FALSE ); - } + vips_error_freeze(); + result = vips__magick_read_header( filename, t, FALSE ); g_object_unref( t ); + vips_error_thaw(); - return( TRUE ); + return( result == 0 ); } static VipsForeignFlags diff --git a/libvips/foreign/matlab.c b/libvips/foreign/matlab.c index 91d11971..36e497a0 100644 --- a/libvips/foreign/matlab.c +++ b/libvips/foreign/matlab.c @@ -300,11 +300,12 @@ vips__mat_ismat( const char *filename ) { mat_t *mat; - if( !(mat = Mat_Open( filename, MAT_ACC_RDONLY )) ) - return( 0 ); + vips_error_freeze(); + mat = Mat_Open( filename, MAT_ACC_RDONLY ); Mat_Close( mat ); + vips_error_thaw(); - return( 1 ); + return( mat != NULL ); } const char *vips__mat_suffs[] = { ".mat", NULL }; diff --git a/libvips/foreign/matrixload.c b/libvips/foreign/matrixload.c index 78d5ec07..65a0dff1 100644 --- a/libvips/foreign/matrixload.c +++ b/libvips/foreign/matrixload.c @@ -136,6 +136,7 @@ vips_foreign_load_matrix_class_init( VipsForeignLoadMatrixClass *class ) foreign_class->suffs = vips__foreign_matrix_suffs; + load_class->is_a = vips__matrix_ismatrix; load_class->get_flags_filename = vips_foreign_load_matrix_get_flags_filename; load_class->get_flags = vips_foreign_load_matrix_get_flags; diff --git a/libvips/foreign/openslide2vips.c b/libvips/foreign/openslide2vips.c index 97afbb52..3d86cb2c 100644 --- a/libvips/foreign/openslide2vips.c +++ b/libvips/foreign/openslide2vips.c @@ -107,7 +107,11 @@ vips__openslide_isslide( const char *filename ) int ok; ok = 0; - if( (osr = openslide_open( filename )) ) { + vips_error_freeze(); + osr = openslide_open( filename ); + vips_error_thaw(); + + if( osr ) { const char *vendor; /* Generic tiled tiff images can be opened by openslide as diff --git a/libvips/include/vips/error.h b/libvips/include/vips/error.h index 7124cc83..625a17df 100644 --- a/libvips/include/vips/error.h +++ b/libvips/include/vips/error.h @@ -38,6 +38,9 @@ extern "C" { const char *vips_error_buffer( void ); void vips_error_clear( void ); +void vips_error_freeze( void ); +void vips_error_thaw( void ); + void vips_error( const char *domain, const char *fmt, ... ) __attribute__((format(printf, 2, 3))); void vips_verror( const char *domain, const char *fmt, va_list ap ); diff --git a/libvips/iofuncs/error.c b/libvips/iofuncs/error.c index 46c2002d..f91de350 100644 --- a/libvips/iofuncs/error.c +++ b/libvips/iofuncs/error.c @@ -110,10 +110,40 @@ #define VIPS_MAX_ERROR (10240) static char vips_error_text[VIPS_MAX_ERROR] = ""; static VipsBuf vips_error_buf = VIPS_BUF_STATIC( vips_error_text ); +static int vips_error_freeze_count = 0; #define IM_DIAGNOSTICS "IM_DIAGNOSTICS" #define IM_WARNING "IM_WARNING" +/** + * vips_error_freeze: + * + * Stop errors being logged. Use vips_error_thaw() to unfreeze. You can + * nest freeze/thaw pairs. + */ +void +vips_error_freeze( void ) +{ + g_mutex_lock( vips__global_lock ); + g_assert( vips_error_freeze_count >= 0 ); + vips_error_freeze_count += 1; + g_mutex_unlock( vips__global_lock ); +} + +/** + * vips_error_thaw: + * + * Reenable error logging. + */ +void +vips_error_thaw( void ) +{ + g_mutex_lock( vips__global_lock ); + vips_error_freeze_count -= 1; + g_assert( vips_error_freeze_count >= 0 ); + g_mutex_unlock( vips__global_lock ); +} + /** * vips_error_buffer: * @@ -173,9 +203,12 @@ vips_verror( const char *domain, const char *fmt, va_list ap ) #endif /*VIPS_DEBUG*/ g_mutex_lock( vips__global_lock ); - vips_buf_appendf( &vips_error_buf, "%s: ", domain ); - vips_buf_vappendf( &vips_error_buf, fmt, ap ); - vips_buf_appends( &vips_error_buf, "\n" ); + g_assert( vips_error_freeze_count >= 0 ); + if( !vips_error_freeze_count ) { + vips_buf_appendf( &vips_error_buf, "%s: ", domain ); + vips_buf_vappendf( &vips_error_buf, fmt, ap ); + vips_buf_appends( &vips_error_buf, "\n" ); + } g_mutex_unlock( vips__global_lock ); if( vips__fatal )