fits reader is now lazy

The fits format reader now uses fits_read_subset() to erad pixels
lazilly. There are a few unresolved issues though:

- getting some streaking, try putting a lock around the read
  subarea call, perhaps it can't thread?

- add a tile cache, cf. tiff

- test colour read with valgrind

- ask Doug for a test colour image

- read whole tiles, if the alignment is right, again see tiff reader

- test performance

- remove the old scanline reader?
This commit is contained in:
John Cupitt 2011-01-27 14:43:33 +00:00
parent 1aea6a1347
commit 5e366bcaf3

View File

@ -36,8 +36,8 @@
*/ */
/* /*
#define DEBUG
*/ */
#define DEBUG
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include <config.h> #include <config.h>
@ -60,6 +60,27 @@
#include <dmalloc.h> #include <dmalloc.h>
#endif /*WITH_DMALLOC*/ #endif /*WITH_DMALLOC*/
/*
TODO
- getting some streaking, try putting a lock around the read
subarea call
- add a tile cache, cf. tiff
- test colour read with valgrind
- ask Doug for a test colour image
- read whole tiles, if the alignment is right
- test performance
- remove the old scanline reader?
*/
/* vips only supports 3 dimensions, but we allow up to MAX_DIMENSIONS as long /* vips only supports 3 dimensions, but we allow up to MAX_DIMENSIONS as long
* as the higher dimensions are all empty. If you change this value, change * as the higher dimensions are all empty. If you change this value, change
* fits2vips_get_header() as well. * fits2vips_get_header() as well.
@ -118,12 +139,17 @@ read_new( const char *filename, IMAGE *out )
read->out = out; read->out = out;
read->fptr = NULL; read->fptr = NULL;
if( im_add_close_callback( out,
(im_callback_fn) read_destroy, read, NULL ) ) {
read_destroy( read );
return( NULL );
}
status = 0; status = 0;
if( fits_open_file( &read->fptr, filename, READONLY, &status ) ) { if( fits_open_file( &read->fptr, filename, READONLY, &status ) ) {
im_error( "fits", _( "unable to open \"%s\"" ), filename ); im_error( "fits", _( "unable to open \"%s\"" ), filename );
read_error( status ); read_error( status );
read_destroy( read );
return( NULL ); return( NULL );
} }
@ -282,13 +308,9 @@ fits2vips_header( const char *filename, IMAGE *out )
printf( "fits2vips_header: reading \"%s\"\n", filename ); printf( "fits2vips_header: reading \"%s\"\n", filename );
#endif /*DEBUG*/ #endif /*DEBUG*/
if( !(read = read_new( filename, out )) ) if( !(read = read_new( filename, out )) ||
fits2vips_get_header( read ) )
return( -1 ); return( -1 );
if( fits2vips_get_header( read ) ) {
read_destroy( read );
return( -1 );
}
read_destroy( read );
return( 0 ); return( 0 );
} }
@ -362,12 +384,9 @@ fits2vips_generate( REGION *out, void *seq, void *a, void *b )
Rect *r = &out->valid; Rect *r = &out->valid;
IMAGE *im = read->out; IMAGE *im = read->out;
const int es = IM_IMAGE_SIZEOF_ELEMENT( im );
PEL *line_buffer; PEL *q;
PEL *band_buffer; int y, z;
PEL *p, *q;
int x, y, z, k;
int status; int status;
status = 0; status = 0;
@ -376,59 +395,35 @@ fits2vips_generate( REGION *out, void *seq, void *a, void *b )
long lpixel[MAX_DIMENSIONS]; long lpixel[MAX_DIMENSIONS];
long inc[MAX_DIMENSIONS]; long inc[MAX_DIMENSIONS];
if( !(line_buffer = IM_ARRAY( im, IM_IMAGE_SIZEOF_LINE( im ), PEL )) || /* We read the area a scanline at a time. If the REGION we are reading
!(band_buffer = IM_ARRAY( im, es * im->Xsize, PEL )) || * to has bpl set right we should be able to read all scanlines in one
im_outcheck( im ) || * go, experiment.
im_setupout( im ) )
return( -1 );
/* Read out the entire
for( b = 0; b < MAX_DIMENSIONS; b++ )
fpixel[b] = 1;
fpixel[1] = im->Ysize - y;
if( fits_read_subset( read->fptr, read->datatype,
long *fpixel,
long *lpixel, long *inc, void *nulval, void *array,
int *anynul, int *status)
*/ */
for( y = r->top; y < IM_RECT_BOTTOM( r ); y ++ ) {
for( y = 0; y < im->Ysize; y++ ) {
long int fpixel[MAX_DIMENSIONS];
/* Start of scanline. We have to read top-to-bottom.
*/
for( z = 0; z < MAX_DIMENSIONS; z++ ) for( z = 0; z < MAX_DIMENSIONS; z++ )
fpixel[z] = 1; fpixel[z] = 1;
fpixel[0] = r->left + 1;
fpixel[1] = im->Ysize - y; fpixel[1] = im->Ysize - y;
for( z = 0; z < im->Bands; z++ ) { for( z = 0; z < MAX_DIMENSIONS; z++ )
fpixel[2] = z + 1; lpixel[z] = 1;
lpixel[0] = IM_RECT_RIGHT( r );
lpixel[1] = im->Ysize - y;
lpixel[2] = im->Bands;
/* Read one band of one scanline, then scatter-write for( z = 0; z < MAX_DIMENSIONS; z++ )
* into the line buffer. inc[z] = 1;
*/
if( fits_read_pix( read->fptr,
read->datatype, fpixel, im->Xsize,
NULL, band_buffer, NULL, &status ) ) {
read_error( status );
return( -1 );
}
p = band_buffer; q = (PEL *) IM_REGION_ADDR( out, r->left, y );
q = line_buffer + z * es;
for( x = 0; x < im->Xsize; x++ ) {
for( k = 0; k < es; k++ )
q[k] = p[k];
p += es; /* Break on ffgsv() for this call.
q += im->Bands * es; */
} if( fits_read_subset( read->fptr, read->datatype,
} fpixel, lpixel, inc, NULL, q, NULL, &status ) ) {
read_error( status );
if( im_writeline( y, im, line_buffer ) )
return( -1 ); return( -1 );
}
} }
return( 0 ); return( 0 );
@ -439,8 +434,12 @@ fits2vips_generate( REGION *out, void *seq, void *a, void *b )
static int static int
fits2vips_get_data_lazy( Read *read ) fits2vips_get_data_lazy( Read *read )
{ {
return( im_generate( read->out, if( im_demand_hint( read->out, IM_SMALLTILE, NULL ) ||
NULL, fits2vips_generate, NULL, read, NULL ) ); im_generate( read->out,
NULL, fits2vips_generate, NULL, read, NULL ) )
return( -1 );
return( 0 );
} }
/** /**
@ -467,12 +466,9 @@ im_fits2vips( const char *filename, IMAGE *out )
if( !(read = read_new( filename, out )) ) if( !(read = read_new( filename, out )) )
return( -1 ); return( -1 );
if( fits2vips_get_header( read ) || if( fits2vips_get_header( read ) ||
fits2vips_get_data_scanlinewise( read ) ) { fits2vips_get_data_lazy( read ) )
read_destroy( read ); // fits2vips_get_data_scanlinewise( read ) )
return( -1 ); return( -1 );
}
read_destroy( read );
return( 0 ); return( 0 );
} }