sort-of works

but can't set meta correctly, try:

	$ vipsheader -a sub-CC00050XX01_ses-7201_T2w.nii.gz

see all fields, but

	$ vips copy sub-CC00050XX01_ses-7201_T2w.nii.gz x.v
	$ vipsheader -a x.v

only see a few, odd
This commit is contained in:
John Cupitt 2018-07-18 17:09:53 +01:00
parent 1028907e58
commit 06a40cc7ee
5 changed files with 107 additions and 35 deletions

View File

@ -3,6 +3,7 @@ noinst_LTLIBRARIES = libforeign.la
libforeign_la_SOURCES = \
pforeign.h \
niftiload.c \
niftisave.c \
quantise.c \
exif.c \
gifload.c \

View File

@ -1837,6 +1837,7 @@ vips_foreign_operation_init( void )
extern GType vips_foreign_load_svg_file_get_type( void );
extern GType vips_foreign_load_svg_buffer_get_type( void );
extern GType vips_foreign_load_nifti_get_type( void );
extern GType vips_foreign_save_nifti_get_type( void );
extern GType vips_foreign_load_gif_get_type( void );
extern GType vips_foreign_load_gif_file_get_type( void );
extern GType vips_foreign_load_gif_buffer_get_type( void );
@ -1961,6 +1962,7 @@ vips_foreign_operation_init( void )
#ifdef HAVE_NIFTI
vips_foreign_load_nifti_get_type();
vips_foreign_save_nifti_get_type();
#endif /*HAVE_NIFTI*/
vips__foreign_load_operation =

View File

@ -338,16 +338,6 @@ vips_foreign_load_nifti_set( const char *name, GValue *value, glong offset,
return( NULL );
}
/* Slow and horrid version if there's no recent glib.
*/
#ifndef HAVE_CHECKED_MUL
#define g_uint_checked_mul( dest, a, b ) ( \
((guint64) a * b) > UINT_MAX ? \
(*dest = UINT_MAX, FALSE) : \
(*dest = a * b, TRUE) \
)
#endif /*HAVE_CHECKED_MUL*/
static int
vips_foreign_load_nifti_set_header( VipsForeignLoadNifti *nifti,
nifti_image *nim, VipsImage *out )
@ -406,7 +396,8 @@ vips_foreign_load_nifti_set_header( VipsForeignLoadNifti *nifti,
return( 0 );
}
if( !(fmt = vips__foreign_nifti_BandFmt2datatype( nim->datatype )) ) {
fmt = vips__foreign_nifti_datatype2BandFmt( nim->datatype );
if( fmt == VIPS_FORMAT_NOTSET ) {
vips_error( class->nickname,
_( "datatype %d not supported" ), nim->datatype );
return( -1 );
@ -459,7 +450,8 @@ vips_foreign_load_nifti_set_header( VipsForeignLoadNifti *nifti,
/* Set some vips metadata for every nifti header field.
*/
vips__foreign_nifti_map( vips_foreign_load_nifti_set, nim, out );
if( vips__foreign_nifti_map( vips_foreign_load_nifti_set, nim, out ) )
return( -1 );
/* One byte longer than the spec to leave space for any extra
* '\0' termination.
@ -494,7 +486,7 @@ vips_foreign_load_nifti_header( VipsForeignLoad *load )
VipsForeignLoadNifti *nifti = (VipsForeignLoadNifti *) load;
/* We can't use the (much faster) nifti_read_header() since it just
* reads the 348 bytes iof the analyze struct and does not read any of
* reads the 348 bytes of the analyze struct and does not read any of
* the extension fields.
*/
@ -552,7 +544,8 @@ const char *vips__nifti_suffs[] = {
".hdr", ".hdr.gz",
".img", ".img.gz",
".nia", ".nia.gz",
NULL };
NULL
};
static void
vips_foreign_load_nifti_class_init( VipsForeignLoadNiftiClass *class )

View File

@ -47,7 +47,9 @@
#include <vips/vips.h>
#ifdef HAVE_CFITSIO
#ifdef HAVE_NIFTI
#include <nifti1_io.h>
#include "pforeign.h"
@ -70,11 +72,11 @@ G_DEFINE_TYPE( VipsForeignSaveNifti, vips_foreign_save_nifti,
static void
vips_foreign_save_nifti_dispose( GObject *gobject )
{
VipsForeignLoadNifti *nifti = (VipsForeignLoadNifti *) gobject;
VipsForeignSaveNifti *nifti = (VipsForeignSaveNifti *) gobject;
VIPS_FREEF( nifti_image_free, nifti->nim );
G_OBJECT_CLASS( vips_foreign_load_nifti_parent_class )->
G_OBJECT_CLASS( vips_foreign_save_nifti_parent_class )->
dispose( gobject );
}
@ -91,24 +93,75 @@ vips_foreign_save_nifti_header_vips( VipsForeignSaveNifti *nifti,
typedef struct _VipsNdimInfo {
VipsImage *image;
nifti_image *nim;
int *dims;
int n;
} VipsNdimInfo;
static void *
vips_foreign_save_nifti_set_dims( const char *name, GValue *value, glong offset,
void *a, void *b )
vips_foreign_save_nifti_set_dims( const char *name,
GValue *value, glong offset, void *a, void *b )
{
VipsNdimInfo *info = (VipsNdimInfo *) a;
/* The first 8 members are the dims fields.
*/
if( info->n < 7 ) {
char txt[256];
if( info->n < 8 ) {
char vips_name[256];
int i;
vips_snprintf( txt, 256, "nifti-%s", name );
if( vips_image_get_int( image, name, &info->dims[i] ) )
vips_snprintf( vips_name, 256, "nifti-%s", name );
if( vips_image_get_int( info->image, vips_name, &i ) ||
i <= 0 ||
i > VIPS_MAX_COORD )
return( info );
info->dims[info->n] = i;
}
info->n += 1;
return( NULL );
}
/* How I wish glib had something like this :( Just implement the ones we need
* for vips_foreign_nifti_fields above.
*/
static void
vips_gvalue_write( GValue *value, void *p )
{
switch( G_VALUE_TYPE( value ) ) {
case G_TYPE_INT:
*((int *) p) = g_value_get_int( value );
break;
case G_TYPE_FLOAT:
*((float *) p) = g_value_get_float( value );
break;
default:
g_warning( "vips_gvalue_write: unsupported GType %s",
g_type_name( G_VALUE_TYPE( value ) ) );
}
}
static void *
vips_foreign_save_nifti_set_fields( const char *name,
GValue *value, glong offset, void *a, void *b )
{
VipsNdimInfo *info = (VipsNdimInfo *) a;
/* The first 8 members are the dims fields. We set them above ^^^ --
* do the others in this pass.
*/
if( info->n >= 8 ) {
char vips_name[256];
GValue value_copy = { 0 };
vips_snprintf( vips_name, 256, "nifti-%s", name );
if( vips_image_get( info->image, vips_name, &value_copy ) )
return( info );
vips_gvalue_write( &value_copy, (gpointer) info->nim + offset );
g_value_unset( &value_copy );
}
info->n += 1;
@ -127,7 +180,7 @@ vips_foreign_save_nifti_header_nifti( VipsForeignSaveNifti *nifti,
VipsNdimInfo info;
int dims[8];
int datatype;
int height;
guint height;
int i;
info.image = image;
@ -137,13 +190,18 @@ 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.
*/
height = 1;
for( i = 2; i < VIPS_NUMBER( dims ) && i < dims[0]; i++ )
height *= dims[i];
if( images->Xsize != dims[1] ||
images->Ysize != height ) {
for( i = 2; i < VIPS_NUMBER( dims ) && i < dims[0] + 1; i++ )
if( !g_uint_checked_mul( &height, height, dims[i] ) ) {
vips_error( class->nickname,
"%s", _( "dimension overflow" ) );
return( 0 );
}
if( image->Xsize != dims[1] ||
image->Ysize != height ) {
vips_error( class->nickname,
"%s", _( "bad image dimensions" ) );
return( -1 );
@ -156,9 +214,16 @@ vips_foreign_save_nifti_header_nifti( VipsForeignSaveNifti *nifti,
return( -1 );
}
if( !(nnifti->nim = nifti_make_new_nim( dims, datatype, FALSE )) )
if( !(nifti->nim = nifti_make_new_nim( dims, datatype, FALSE )) )
return( -1 );
info.image = image;
info.nim = nifti->nim;
info.n = 0;
if( vips__foreign_nifti_map(
vips_foreign_save_nifti_set_fields, &info, NULL ) )
return( -1 );
return( 0 );
}
@ -167,8 +232,6 @@ vips_foreign_save_nifti_build( VipsObject *object )
{
VipsForeignSave *save = (VipsForeignSave *) object;
VipsForeignSaveNifti *nifti = (VipsForeignSaveNifti *) object;
VipsImage **t = (VipsImage **)
vips_object_local_array( VIPS_OBJECT( nifti ), 2 );
if( VIPS_OBJECT_CLASS( vips_foreign_save_nifti_parent_class )->
build( object ) )
@ -192,7 +255,8 @@ vips_foreign_save_nifti_build( VipsObject *object )
/* set ext, plus other stuff
*/
if( !(nim->data = vips_image_write_memory( save->ready, NULL )) )
if( !(nifti->nim->data =
vips_image_write_to_memory( save->ready, NULL )) )
return( -1 );
/* No return code!??!?!!
@ -202,7 +266,7 @@ vips_foreign_save_nifti_build( VipsObject *object )
/* We must free and NULL the pointer or nifti will try to free it for
* us.
*/
VIPS_FREE( nim->data );
VIPS_FREE( nifti->nim->data );
return( 0 );
}
@ -259,7 +323,7 @@ vips_foreign_save_nifti_init( VipsForeignSaveNifti *nifti )
{
}
#endif /*HAVE_CFITSIO*/
#endif /*HAVE_NIFTI*/
/**
* vips_niftisave: (method)

View File

@ -35,6 +35,16 @@
extern "C" {
#endif /*__cplusplus*/
/* Slow and horrid version if there's no recent glib.
*/
#ifndef HAVE_CHECKED_MUL
#define g_uint_checked_mul( dest, a, b ) ( \
((guint64) a * b) > UINT_MAX ? \
(*dest = UINT_MAX, FALSE) : \
(*dest = a * b, TRUE) \
)
#endif /*HAVE_CHECKED_MUL*/
void vips__tiff_init( void );
int vips__tiff_write( VipsImage *in, const char *filename,
@ -256,6 +266,8 @@ int vips__quantise_image( VipsImage *in,
VipsImage **index_out, VipsImage **palette_out,
int colours, int Q, double dither );
extern const char *vips__nifti_suffs[];
VipsBandFormat vips__foreign_nifti_datatype2BandFmt( int datatype );
int vips__foreign_nifti_BandFmt2datatype( VipsBandFormat fmt );