works!
just needs some tests could be faster too
This commit is contained in:
parent
9179156132
commit
d03416d386
@ -31,6 +31,7 @@
|
|||||||
- add Mitchell kernel
|
- add Mitchell kernel
|
||||||
- pyramid builders have a choice of 2x2 shrinkers [harukizaemon]
|
- pyramid builders have a choice of 2x2 shrinkers [harukizaemon]
|
||||||
- add `palette` option to pngsave [felixbuenemann]
|
- add `palette` option to pngsave [felixbuenemann]
|
||||||
|
- add basic nifti load/save support
|
||||||
|
|
||||||
12/3/18 started 8.6.4
|
12/3/18 started 8.6.4
|
||||||
- better fitting of fonts with overhanging edges [Adrià]
|
- better fitting of fonts with overhanging edges [Adrià]
|
||||||
|
@ -103,6 +103,43 @@ vips_foreign_load_nifti_dispose( GObject *gobject )
|
|||||||
dispose( 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.
|
/* Map DT_* datatype values to VipsBandFormat.
|
||||||
*/
|
*/
|
||||||
typedef struct _VipsForeignDT2Vips {
|
typedef struct _VipsForeignDT2Vips {
|
||||||
@ -360,7 +397,7 @@ vips_foreign_load_nifti_set_header( VipsForeignLoadNifti *nifti,
|
|||||||
nim->ndim );
|
nim->ndim );
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
for( i = 1; i < 8; i++ ) {
|
for( i = 1; i < 8 && i < nim->ndim + 1; i++ ) {
|
||||||
if( nim->dim[i] <= 0 ) {
|
if( nim->dim[i] <= 0 ) {
|
||||||
vips_error( class->nickname,
|
vips_error( class->nickname,
|
||||||
"%s", _( "invalid dimension" ) );
|
"%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
|
/* 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.
|
* calculation.
|
||||||
*/
|
*/
|
||||||
if( nim->dim[i] > 1 &&
|
if( nim->dim[i] > 1 &&
|
||||||
@ -385,7 +422,7 @@ vips_foreign_load_nifti_set_header( VipsForeignLoadNifti *nifti,
|
|||||||
bands = 1;
|
bands = 1;
|
||||||
width = (guint) nim->nx;
|
width = (guint) nim->nx;
|
||||||
height = (guint) nim->ny;
|
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] ) ) {
|
if( !g_uint_checked_mul( &height, height, nim->dim[i] ) ) {
|
||||||
vips_error( class->nickname,
|
vips_error( class->nickname,
|
||||||
"%s", _( "dimension overflow" ) );
|
"%s", _( "dimension overflow" ) );
|
||||||
@ -568,7 +605,7 @@ vips_foreign_load_nifti_class_init( VipsForeignLoadNiftiClass *class )
|
|||||||
|
|
||||||
foreign_class->suffs = vips__nifti_suffs;
|
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->header = vips_foreign_load_nifti_header;
|
||||||
load_class->load = vips_foreign_load_nifti_load;
|
load_class->load = vips_foreign_load_nifti_load;
|
||||||
|
|
||||||
|
@ -86,7 +86,73 @@ static int
|
|||||||
vips_foreign_save_nifti_header_vips( VipsForeignSaveNifti *nifti,
|
vips_foreign_save_nifti_header_vips( VipsForeignSaveNifti *nifti,
|
||||||
VipsImage *image )
|
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 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
@ -183,6 +249,11 @@ vips_foreign_save_nifti_header_nifti( VipsForeignSaveNifti *nifti,
|
|||||||
guint height;
|
guint height;
|
||||||
int i;
|
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.image = image;
|
||||||
info.dims = dims;
|
info.dims = dims;
|
||||||
info.n = 0;
|
info.n = 0;
|
||||||
@ -190,8 +261,22 @@ vips_foreign_save_nifti_header_nifti( VipsForeignSaveNifti *nifti,
|
|||||||
vips_foreign_save_nifti_set_dims, &info, NULL ) )
|
vips_foreign_save_nifti_set_dims, &info, NULL ) )
|
||||||
return( -1 );
|
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;
|
height = 1;
|
||||||
for( i = 2; i < VIPS_NUMBER( dims ) && i < dims[0] + 1; i++ )
|
for( i = 2; i < VIPS_NUMBER( dims ) && i < dims[0] + 1; i++ )
|
||||||
|
Loading…
Reference in New Issue
Block a user