From 7886180ae6dde9a591ec91b307351b44acca32c6 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 14 Dec 2011 13:18:50 +0000 Subject: [PATCH] fixes to fits load/save --- TODO | 9 +- libvips/foreign/fits.c | 45 +++--- libvips/foreign/fitsload.c | 7 +- libvips/foreign/fitssave.c | 8 +- libvips/iofuncs/object.c | 2 +- libvips/relational/im_ifthenelse.c | 243 ----------------------------- 6 files changed, 42 insertions(+), 272 deletions(-) delete mode 100644 libvips/relational/im_ifthenelse.c diff --git a/TODO b/TODO index 2a38ba8f..e9fe096f 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,10 @@ -- fits bandjoin is rubbish +- fits bandjoin is rubbish ... eg for WFPC2u5780205r_c0fx.fits we see last two + bands as all zero - perhaps we should always allocate the output in the loader? it's make fits - bandjoin simpler + suppression for the strspn() thing? + + leak check output should write a single line for each leaked image, not the + whole header diff --git a/libvips/foreign/fits.c b/libvips/foreign/fits.c index 100c7b2b..d3f4d770 100644 --- a/libvips/foreign/fits.c +++ b/libvips/foreign/fits.c @@ -473,42 +473,41 @@ vips__fits_read( const char *filename, VipsImage *out ) */ t = vips_image_new(); - vips_object_local( out, t ); - if( vips__fits_read_header( filename, t ) ) + if( vips__fits_read_header( filename, t ) ) { + g_object_unref( t ); return( -1 ); + } n_bands = t->Bands; + g_object_unref( t ); if( n_bands == 1 ) { - t = vips_image_new(); - vips_object_local( out, t ); - if( fits2vips( filename, t, 0 ) ) + if( fits2vips( filename, out, 0 ) ) return( -1 ); } else { - VipsImage *acc; + VipsImage **x; int i; - acc = NULL; - for( i = 0; i < n_bands; i++ ) { - t = vips_image_new(); - vips_object_local( out, t ); - if( fits2vips( filename, t, i ) ) - return( -1 ); + t = vips_image_new(); + x = (VipsImage **) vips_object_local_array( VIPS_OBJECT( t ), + n_bands + 1 ); - if( !acc ) - acc = t; - else { - if( vips_bandjoin2( acc, t, &acc, NULL ) ) - return( -1 ); - vips_object_local( out, acc ); + for( i = 0; i < n_bands; i++ ) { + x[i] = vips_image_new(); + if( fits2vips( filename, x[i], i ) ) { + g_object_unref( t ); + return( -1 ); } } - t = acc; - } + if( vips_bandjoin( x, &x[n_bands], n_bands, NULL ) || + vips_image_write( x[n_bands], out ) ) { + g_object_unref( t ); + return( -1 ); + } - if( vips_image_write( t, out ) ) - return( -1 ); + g_object_unref( t ); + } return( 0 ); } @@ -546,7 +545,7 @@ vips_fits_new_write( VipsImage *in, const char *filename ) if( !(fits = VIPS_NEW( in, VipsFits )) ) return( NULL ); - fits->filename = vips_strdup( in, filename ); + fits->filename = vips_strdup( VIPS_OBJECT( in ), filename ); fits->image = in; fits->fptr = NULL; fits->lock = NULL; diff --git a/libvips/foreign/fitsload.c b/libvips/foreign/fitsload.c index 71197492..49a6a5d2 100644 --- a/libvips/foreign/fitsload.c +++ b/libvips/foreign/fitsload.c @@ -78,8 +78,13 @@ static int vips_foreign_load_fits_load( VipsForeignLoad *load ) { VipsForeignLoadFits *fits = (VipsForeignLoadFits *) load; + VipsImage **t = (VipsImage **) + vips_object_local_array( VIPS_OBJECT( fits ), 2 ); - if( vips__fits_read( fits->filename, load->real ) ) + t[0] = vips_image_new(); + if( vips__fits_read( fits->filename, t[0] ) || + vips_flip( t[0], &t[1], VIPS_DIRECTION_VERTICAL, NULL ) || + vips_image_write( t[1], load->real ) ) return( -1 ); return( 0 ); diff --git a/libvips/foreign/fitssave.c b/libvips/foreign/fitssave.c index ca9a79c5..9d8975ef 100644 --- a/libvips/foreign/fitssave.c +++ b/libvips/foreign/fitssave.c @@ -67,13 +67,19 @@ vips_foreign_save_fits_build( VipsObject *object ) { VipsForeignSave *save = (VipsForeignSave *) object; VipsForeignSaveFits *fits = (VipsForeignSaveFits *) object; + VipsImage *t; if( VIPS_OBJECT_CLASS( vips_foreign_save_fits_parent_class )-> build( object ) ) return( -1 ); - if( vips__fits_write( save->ready, fits->filename ) ) + if( vips_flip( save->ready, &t, VIPS_DIRECTION_VERTICAL, NULL ) ) return( -1 ); + if( vips__fits_write( t, fits->filename ) ) { + g_object_unref( t ); + return( -1 ); + } + g_object_unref( t ); return( 0 ); } diff --git a/libvips/iofuncs/object.c b/libvips/iofuncs/object.c index 76acfc2e..b5d33df8 100644 --- a/libvips/iofuncs/object.c +++ b/libvips/iofuncs/object.c @@ -1905,7 +1905,7 @@ vips_object_local_array_cb( GObject *parent, VipsObjectLocal *local ) * |[ * VipsObject **t; * - * t = vips_object_local_array( out, 5 ); + * t = vips_object_local_array( a, 5 ); * if( * vips_add( a, b, &t[0], NULL ) || * vips_invert( t[0], &t[1], NULL ) || diff --git a/libvips/relational/im_ifthenelse.c b/libvips/relational/im_ifthenelse.c deleted file mode 100644 index c44be21b..00000000 --- a/libvips/relational/im_ifthenelse.c +++ /dev/null @@ -1,243 +0,0 @@ -/* im_ifthenelse.c --- use a condition image to join two images together - * - * Modified: - * 9/2/95 JC - * - partialed and ANSIfied - * 11/9/95 JC - * - return( 0 ) missing! oops - * 15/4/05 - * - now just evals left/right if all zero/all one - * 7/10/06 - * - set THINSTRIP - * 23/9/09 - * - gtkdoc comment - * 23/9/09 - * - use im_check*() - * - allow many-band conditional and single-band a/b - * - allow a/b to differ in format and bands - * 25/6/10 - * - let the conditional image be any format by adding a (!=0) if - * necessary - * 17/5/11 - * - added sizealike - */ - -/* - - This file is part of VIPS. - - VIPS is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - */ - -/* - - These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk - - */ - -#ifdef HAVE_CONFIG_H -#include -#endif /*HAVE_CONFIG_H*/ -#include - -#include -#include - -static int -ifthenelse_gen( REGION *or, void *seq, void *client1, void *client2 ) -{ - REGION **ir = (REGION **) seq; - Rect *r = &or->valid; - int le = r->left; - int to = r->top; - int bo = IM_RECT_BOTTOM(r); - - IMAGE *c = ir[0]->im; - IMAGE *a = ir[1]->im; - - int size, width; - int i, x, y, z; - - int all0, alln0; - - if( c->Bands == 1 ) { - /* Copying PEL-sized units with a one-band conditional. - */ - size = IM_IMAGE_SIZEOF_PEL( a ); - width = r->width; - } - else { - /* Copying ELEMENT sized-units with an n-band conditional. - */ - size = IM_IMAGE_SIZEOF_ELEMENT( a ); - width = r->width * a->Bands; - } - - if( im_prepare( ir[0], r ) ) - return( -1 ); - - /* Is the conditional all zero or all non-zero? We can avoid asking - * for one of the inputs to be calculated. - */ - all0 = *((PEL *) IM_REGION_ADDR( ir[0], le, to )) == 0; - alln0 = *((PEL *) IM_REGION_ADDR( ir[0], le, to )) != 0; - for( y = to; y < bo; y++ ) { - PEL *p = (PEL *) IM_REGION_ADDR( ir[0], le, y ); - - for( x = 0; x < width; x++ ) { - all0 &= p[x] == 0; - alln0 &= p[x] != 0; - } - - if( !all0 && !alln0 ) - break; - } - - if( alln0 ) { - /* All non-zero. Point or at the then image. - */ - if( im_prepare( ir[1], r ) || - im_region_region( or, ir[1], r, r->left, r->top ) ) - return( -1 ); - } - else if( all0 ) { - /* All zero. Point or at the else image. - */ - if( im_prepare( ir[2], r ) || - im_region_region( or, ir[2], r, r->left, r->top ) ) - return( -1 ); - } - else { - /* Mix of set and clear ... ask for both then and else parts - * and interleave. - */ - if( im_prepare( ir[1], r ) || im_prepare( ir[2], r ) ) - return( -1 ); - - for( y = to; y < bo; y++ ) { - PEL *cp = (PEL *) IM_REGION_ADDR( ir[0], le, y ); - PEL *ap = (PEL *) IM_REGION_ADDR( ir[1], le, y ); - PEL *bp = (PEL *) IM_REGION_ADDR( ir[2], le, y ); - PEL *q = (PEL *) IM_REGION_ADDR( or, le, y ); - - for( x = 0, i = 0; i < width; i++, x += size ) { - if( cp[i] ) - for( z = x; z < x + size; z++ ) - q[z] = ap[z]; - else - for( z = x; z < x + size; z++ ) - q[z] = bp[z]; - } - } - } - - return( 0 ); -} - -static int -ifthenelse( IMAGE *c, IMAGE *a, IMAGE *b, IMAGE *out ) -{ - IMAGE **in; - - /* Check args. - */ - if( im_check_uncoded( "im_ifthenelse", c ) || - im_check_coding_known( "im_ifthenelse", a ) || - im_check_coding_known( "im_ifthenelse", b ) || - im_check_format( "ifthenelse", c, IM_BANDFMT_UCHAR ) || - im_check_format_same( "ifthenelse", a, b ) || - im_check_bands_same( "ifthenelse", a, b ) || - im_check_bands_1orn( "im_ifthenelse", c, a ) || - im_check_size_same( "ifthenelse", a, b ) || - im_check_size_same( "ifthenelse", a, c ) || - im_piocheck( c, out ) || - im_pincheck( a ) || - im_pincheck( b ) ) - return( -1 ); - - /* Make output image. - */ - if( im_demand_hint( out, IM_THINSTRIP, c, a, b, NULL ) || - im_cp_descv( out, a, b, c, NULL ) || - !(in = im_allocate_input_array( out, c, a, b, NULL )) || - im_generate( out, - im_start_many, ifthenelse_gen, im_stop_many, - in, NULL ) ) - return( -1 ); - - return( 0 ); -} - -/** - * im_ifthenelse: - * @c: condition #IMAGE - * @a: then #IMAGE - * @b: else #IMAGE - * @out: output #IMAGE - * - * This operation scans the condition image @c - * and uses it to select pixels from either the then image @a or the else - * image @b. Non-zero means @a, 0 means @b. - * - * Any image can have either 1 band or n bands, where n is the same for all - * the non-1-band images. Single band images are then effectively copied to - * make n-band images. - * - * Images @a and @b are cast up to the smallest common format. - * - * If the images differ in size, the smaller images are enlarged to match the - * largest by adding zero pixels along the bottom and right. - * - * See also: im_blend(), im_equal(). - * - * Returns: 0 on success, -1 on error - */ -int -im_ifthenelse( IMAGE *c, IMAGE *a, IMAGE *b, IMAGE *out ) -{ - IMAGE *t[9]; - - if( im_open_local_array( out, t, 9, "im_ifthenelse", "p" ) ) - return( -1 ); - - /* Make a and b match in bands and format. Don't make c match: we - * special-case this in code above ^^^ for speed. - */ - if( im__formatalike( a, b, t[0], t[1] ) || - im__bandalike( "im_ifthenelse", t[0], t[1], t[2], t[3] ) ) - return( -1 ); - - /* All 3 must match in size. - */ - t[4] = c; - if( im__sizealike_vec( t + 2, t + 5, 3 ) ) - return( -1 ); - c = t[7]; - - /* If c is not uchar, do (!=0) to make a uchar image. - */ - if( c->BandFmt != IM_BANDFMT_UCHAR ) { - if( im_notequalconst( c, t[8], 0 ) ) - return( -1 ); - - c = t[8]; - } - - if( ifthenelse( c, t[5], t[6], out ) ) - return( -1 ); - - return( 0 ); -}