fits write done

fits write is working, tested read as well with valgrind, all fine, I
hope
This commit is contained in:
John Cupitt 2011-03-22 11:57:34 +00:00
parent cb53f47829
commit e66c2dc9a5
2 changed files with 107 additions and 31 deletions

View File

@ -38,6 +38,9 @@
- moved IMAGE and REGION to VipsImage and VipsRegion, classes over VipsObject
- Rect -> VipsRect
- libpng-1.5 supported
- better png read for 1-bit and palette images
- fits write
- better fits metadata support
30/11/10 started 7.24.0
- bump for new stable

View File

@ -17,6 +17,8 @@
* - fits write!
* 21/3/11
* - read/write metadata as whole records to avoid changing things
* - cast input to a supported format
* - bandsplit for write
*/
/*
@ -46,8 +48,8 @@
*/
/*
*/
#define VIPS_DEBUG
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
@ -82,14 +84,6 @@
- test performance
- allow more than 1 band for write
- cast vips types up to most-enclosing fits-supported types,
perhaps ban signed types?
- write with an area writer rather than repeatedly writing a
line at a time
*/
/* vips only supports 3 dimensions, but we allow up to MAX_DIMENSIONS as long
@ -115,6 +109,10 @@ typedef struct {
* band.
*/
int band_select;
/* We split bands up for write into this buffer.
*/
PEL *buffer;
} VipsFits;
static void
@ -144,6 +142,8 @@ vips_fits_close( VipsFits *fits )
fits->fptr = NULL;
}
VIPS_FREE( fits->buffer );
}
static VipsFits *
@ -160,6 +160,7 @@ vips_fits_new_read( const char *filename, VipsImage *out, int band_select )
fits->fptr = NULL;
fits->lock = NULL;
fits->band_select = band_select;
fits->buffer = NULL;
g_signal_connect( out, "close",
G_CALLBACK( vips_fits_close ), fits );
@ -457,7 +458,7 @@ fits2vips( const char *filename, VipsImage *out, int band_select )
*
* Read a FITS image file into a VIPS image.
*
* See also: #VipsFormat.
* See also: im_vips2fits(), #VipsFormat.
*
* Returns: 0 on success, -1 on error.
*/
@ -544,32 +545,77 @@ isfits( const char *filename )
return( 1 );
}
/* Save a bit of typing.
*/
#define UC IM_BANDFMT_UCHAR
#define C IM_BANDFMT_CHAR
#define US IM_BANDFMT_USHORT
#define S IM_BANDFMT_SHORT
#define UI IM_BANDFMT_UINT
#define I IM_BANDFMT_INT
#define F IM_BANDFMT_FLOAT
#define X IM_BANDFMT_COMPLEX
#define D IM_BANDFMT_DOUBLE
#define DX IM_BANDFMT_DPCOMPLEX
/* Type promotion for fits write. fits only has the unsigned int types, plus
* float and double.
*/
static int vips_fits_bandfmt[10] = {
/* UC C US S UI I F X D DX */
UC, UC, US, US, UI, UI, F, X, D, DX
};
static VipsFits *
vips_fits_new_write( VipsImage *in, const char *filename )
{
VipsImage *flip;
VipsImage *type;
VipsFits *fits;
int status;
status = 0;
/* FITS has (0,0) in the bottom left, we need to flip.
*/
if( !(flip = vips_image_new( "p" )) ||
vips_object_local( in, flip ) ||
im_flipver( in, flip ) ||
!(fits = VIPS_NEW( NULL, VipsFits )) )
if( im_check_noncomplex( "im_vips2fits", in ) ||
im_check_uncoded( "im_vips2fits", in ) )
return( NULL );
/* Cast to a supported format.
*/
if( !(type = vips_image_new( "p" )) ||
vips_object_local( in, type ) ||
im_clip2fmt( in, type, vips_fits_bandfmt[in->BandFmt] ) )
return( NULL );
in = type;
/* FITS has (0,0) in the bottom left, we need to flip.
*/
if( !(flip = vips_image_new( "p" )) ||
vips_object_local( in, flip ) ||
im_flipver( in, flip ) )
return( NULL );
in = flip;
if( !(fits = VIPS_NEW( in, VipsFits )) )
return( NULL );
fits->filename = im_strdup( NULL, filename );
fits->image = flip;
fits->image = in;
fits->fptr = NULL;
fits->lock = NULL;
fits->band_select = -1;
fits->buffer = NULL;
g_signal_connect( in, "close",
G_CALLBACK( vips_fits_close ), fits );
if( !(fits->filename = im_strdup( NULL, filename )) )
return( NULL );
/* We need to be able to hold one scanline of one band.
*/
if( !(fits->buffer = VIPS_ARRAY( NULL,
VIPS_IMAGE_SIZEOF_ELEMENT( in ) * in->Xsize, PEL )) )
return( NULL );
/* fits_create_file() will fail if there's a file of thet name, unless
* we put a "!" in front ofthe filename. This breaks conventions with
* the rest of vips, so just unlink explicitly.
@ -668,9 +714,12 @@ static int
vips_fits_write( VipsRegion *region, VipsRect *area, void *a )
{
VipsFits *fits = (VipsFits *) a;
VipsImage *image = fits->image;
int es = VIPS_IMAGE_SIZEOF_ELEMENT( image );
int ps = VIPS_IMAGE_SIZEOF_PEL( image );
int status;
int y;
int y, b, x, k;
status = 0;
@ -678,19 +727,42 @@ vips_fits_write( VipsRegion *region, VipsRect *area, void *a )
"writing left = %d, top = %d, width = %d, height = %d\n",
area->left, area->top, area->width, area->height );
/* We need to write a band at a time. We can't bandsplit in vips,
* since vips_sink_disc() can't loop over many images at once, sadly.
*/
for( y = 0; y < area->height; y++ ) {
long long int fpixel[3];
PEL *p = (PEL *) VIPS_REGION_ADDR( region,
area->left, area->top + y );
fpixel[0] = 1;
fpixel[1] = area->top + y + 1;
fpixel[2] = 1;
for( b = 0; b < image->Bands; b++ ) {
PEL *p1, *q;
long fpixel[3];
if( fits_write_pixll( fits->fptr, fits->datatype, fpixel,
VIPS_REGION_N_ELEMENTS( region ),
VIPS_REGION_ADDR( region, 0, area->top + y ),
&status ) ) {
vips_fits_error( status );
return( -1 );
p1 = p + b * es;
q = fits->buffer;
for( x = 0; x < area->width; x++ )
for( k = 0; k < es; k++ ) {
q[k] = p1[k];
q += es;
p1 += ps;
}
fpixel[0] = area->left + 1;
fpixel[1] = area->top + y + 1;
fpixel[2] = b + 1;
/* No need to lock, write functions are single-threaded.
*/
if( fits_write_pix( fits->fptr, fits->datatype,
fpixel, area->width, fits->buffer,
&status ) ) {
vips_fits_error( status );
return( -1 );
}
}
}
@ -702,9 +774,9 @@ vips_fits_write( VipsRegion *region, VipsRect *area, void *a )
* @in: image to write
* @filename: file to write to
*
* Write @in to @filename in FITS format.
* Write @in to @filename in FITS format.
*
* See also: #VipsFormat.
* See also: im_fits2vips(), #VipsFormat.
*
* Returns: 0 on success, -1 on error.
*/
@ -717,6 +789,7 @@ im_vips2fits( VipsImage *in, const char *filename )
if( !(fits = vips_fits_new_write( in, filename )) )
return( -1 );
if( vips_fits_set_header( fits, fits->image ) ||
vips_sink_disc( fits->image, vips_fits_write, fits ) ) {
vips_fits_close( fits );