just needs some tests

could be faster too
This commit is contained in:
John Cupitt 2018-07-19 17:45:54 +01:00
parent 9179156132
commit d03416d386
3 changed files with 129 additions and 6 deletions

View File

@ -31,6 +31,7 @@
- add Mitchell kernel
- pyramid builders have a choice of 2x2 shrinkers [harukizaemon]
- add `palette` option to pngsave [felixbuenemann]
- add basic nifti load/save support
12/3/18 started 8.6.4
- better fitting of fonts with overhanging edges [Adrià]

View File

@ -103,6 +103,43 @@ vips_foreign_load_nifti_dispose( GObject *gobject )
dispose( gobject );
}
static int
vips_foreign_load_nifti_is_a( const char *filename )
{
char *hfile;
znzFile fp;
nifti_1_header nhdr;
/* Unfortunately is_nifti_file() is very slow and produces lots of
* output. We have to make our own.
*/
if( !(hfile = nifti_findhdrname( filename )) )
return( 0 );
fp = znzopen( hfile, "rb", nifti_is_gzfile( hfile ));
if( znz_isnull( fp ) ) {
free( hfile );
return( 0 );
}
free( hfile );
(void) znzread( &nhdr, 1, sizeof( nhdr ), fp );
znzclose( fp );
/* Test for sanity both ways around. There's a thing to test for byte
* order in niftilib, but it's static :(
*/
if( nifti_hdr_looks_good( &nhdr ) )
return( 1 );
swap_nifti_header( &nhdr, FALSE );
if( nifti_hdr_looks_good( &nhdr ) )
return( 1 );
return( 0 );
}
/* Map DT_* datatype values to VipsBandFormat.
*/
typedef struct _VipsForeignDT2Vips {
@ -360,7 +397,7 @@ vips_foreign_load_nifti_set_header( VipsForeignLoadNifti *nifti,
nim->ndim );
return( 0 );
}
for( i = 1; i < 8; i++ ) {
for( i = 1; i < 8 && i < nim->ndim + 1; i++ ) {
if( nim->dim[i] <= 0 ) {
vips_error( class->nickname,
"%s", _( "invalid dimension" ) );
@ -368,7 +405,7 @@ vips_foreign_load_nifti_set_header( VipsForeignLoadNifti *nifti,
}
/* If we have several images in a dimension, the spacing must
* be non-zero, or we'll get a /0 error in resolution
* be non-zero or we'll get a /0 error in resolution
* calculation.
*/
if( nim->dim[i] > 1 &&
@ -385,7 +422,7 @@ vips_foreign_load_nifti_set_header( VipsForeignLoadNifti *nifti,
bands = 1;
width = (guint) nim->nx;
height = (guint) nim->ny;
for( i = 3; i < 8; i++ )
for( i = 3; i < 8 && i < nim->ndim + 1; i++ )
if( !g_uint_checked_mul( &height, height, nim->dim[i] ) ) {
vips_error( class->nickname,
"%s", _( "dimension overflow" ) );
@ -568,7 +605,7 @@ vips_foreign_load_nifti_class_init( VipsForeignLoadNiftiClass *class )
foreign_class->suffs = vips__nifti_suffs;
load_class->is_a = is_nifti_file;
load_class->is_a = vips_foreign_load_nifti_is_a;
load_class->header = vips_foreign_load_nifti_header;
load_class->load = vips_foreign_load_nifti_load;

View File

@ -86,7 +86,73 @@ static int
vips_foreign_save_nifti_header_vips( VipsForeignSaveNifti *nifti,
VipsImage *image )
{
g_assert( FALSE );
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( nifti );
int dims[8];
int datatype;
int i;
/* Most nifti images have this defaulted as 1.
*/
for( i = 0; i < VIPS_NUMBER( dims ); i++ )
dims[i] = 1;
dims[0] = 2;
dims[1] = image->Xsize;
dims[2] = image->Ysize;
if( vips_image_get_typeof( image, VIPS_META_PAGE_HEIGHT ) ) {
int page_height;
if( vips_image_get_int( image,
VIPS_META_PAGE_HEIGHT, &page_height ) )
return( -1 );
if( image->Ysize % page_height == 0 ) {
dims[0] = 3;
dims[2] = page_height;
dims[3] = image->Ysize / page_height;
}
}
datatype = vips__foreign_nifti_BandFmt2datatype( image->BandFmt );
if( datatype == -1 ) {
vips_error( class->nickname,
"%s", _( "unsupported libvips image type" ) );
return( -1 );
}
if( image->Bands > 1 ) {
if( image->BandFmt != VIPS_FORMAT_UCHAR ) {
vips_error( class->nickname,
"%s", _( "8-bit colour images only" ) );
return( -1 );
}
if( image->Bands == 3 )
datatype = DT_RGB;
else if( image->Bands == 4 )
datatype = DT_RGBA32;
else {
vips_error( class->nickname,
"%s", _( "3 or 4 band colour images only" ) );
return( -1 );
}
}
if( !(nifti->nim = nifti_make_new_nim( dims, datatype, FALSE )) )
return( -1 );
nifti->nim->dx = 1.0 / image->Xres;
nifti->nim->dy = 1.0 / image->Yres;
nifti->nim->dz = 1.0 / image->Yres;
nifti->nim->xyz_units = NIFTI_UNITS_MM;
vips_snprintf( nifti->nim->descrip, sizeof( nifti->nim->descrip ),
"libvips-%s", VIPS_VERSION );
/* All other fields can stay at their default value.
*/
return( 0 );
}
@ -183,6 +249,11 @@ vips_foreign_save_nifti_header_nifti( VipsForeignSaveNifti *nifti,
guint height;
int i;
/* Most nifti images have this defaulted as 1.
*/
for( i = 0; i < VIPS_NUMBER( dims ); i++ )
dims[i] = 1;
info.image = image;
info.dims = dims;
info.n = 0;
@ -190,8 +261,22 @@ vips_foreign_save_nifti_header_nifti( VipsForeignSaveNifti *nifti,
vips_foreign_save_nifti_set_dims, &info, NULL ) )
return( -1 );
/* FIXME what about page-height? should check that too.
/* page-height overrides ny if it makes sense. This might not be
* correct :(
*/
if( vips_image_get_typeof( image, VIPS_META_PAGE_HEIGHT ) ) {
int page_height;
if( vips_image_get_int( image,
VIPS_META_PAGE_HEIGHT, &page_height ) )
return( -1 );
if( image->Ysize % page_height == 0 ) {
dims[0] = 3;
dims[2] = page_height;
dims[3] = image->Ysize / page_height;
}
}
height = 1;
for( i = 2; i < VIPS_NUMBER( dims ) && i < dims[0] + 1; i++ )