1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
|
/* ----------------------------- MNI Header -----------------------------------
@NAME : mincresample.h
@DESCRIPTION: Header file for mincresample.c
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : February 8, 1993 (Peter Neelin)
@MODIFIED :
* $Log: mincresample.h,v $
* Revision 6.8 2008-01-13 09:38:54 stever
* Avoid compiler warnings about functions and variables that are defined
* but not used. Remove some such functions and variables,
* conditionalize some, and move static declarations out of header files
* into C files.
*
* Revision 6.7 2005/07/13 21:34:25 bert
* Add sinc interpolant (ported from 1.X branch)
*
* Revision 6.6 2004/11/01 22:38:39 bert
* Eliminate all references to minc_def.h
*
* Revision 6.5 2004/04/27 15:31:20 bert
* Added -2 option
*
* Revision 6.4 2002/11/06 13:32:23 jason
* Fixes to mincresample: setting the interpolation type is now done
* through an enum rather than function pointers.
*
* Revision 6.3 2001/04/17 18:40:23 neelin
* Modifications to work with NetCDF 3.x
* In particular, changed NC_LONG to NC_INT (and corresponding longs to ints).
* Changed NC_UNSPECIFIED to NC_NAT.
* A few fixes to the configure script.
*
* Revision 6.2 2001/04/02 14:58:09 neelin
* Added -keep_real_range option to prevent rescaling of slices on output
*
* Revision 6.1 1999/10/19 14:45:27 neelin
* Fixed Log subsitutions for CVS
*
* Revision 6.0 1997/09/12 13:23:21 neelin
* Release of minc version 0.6
*
* Revision 5.0 1997/08/21 13:24:22 neelin
* Release of minc version 0.5
*
* Revision 4.1 1997/08/13 15:41:12 neelin
* Fixed initialization problem that caused crashing under Linux.
*
* Revision 4.0 1997/05/07 19:59:42 neelin
* Release of minc version 0.4
*
* Revision 3.4 1996/01/31 15:22:02 neelin
* Fixed bug in transformation of input sampling.
*
* Revision 3.3 1995/12/12 19:15:35 neelin
* Added -spacetype, -talairach and -units options.
*
* Revision 3.2 1995/11/21 14:13:20 neelin
* Transform input sampling with transformation and use this as default.
* Added -tfm_input_sampling to specify above option.
* Added -use_input_sampling to get old behaviour (no longer the default).
* Added -origin option (to specify coordinate instead of start values).
* Added -standard_sampling option (to set standard values of start, step
* and direction cosines).
* Added -invert_transformation option.
*
* Revision 3.1 1995/11/07 15:04:02 neelin
* Modified argument parsing so that only one pass is done.
*
* Revision 3.0 1995/05/15 19:30:57 neelin
* Release of minc version 0.3
*
* Revision 2.0 1994/09/28 10:32:48 neelin
* Release of minc version 0.2
*
* Revision 1.11 94/09/28 10:32:40 neelin
* Pre-release
*
* Revision 1.10 93/11/04 15:13:40 neelin
* Added support for irregularly spaced dimensions.
*
* Revision 1.9 93/11/02 11:23:56 neelin
* Handle imagemax/min potentially varying over slices (for vector data, etc.)
*
* Revision 1.8 93/10/20 14:05:42 neelin
* Added VOXEL_COORD_EPS - an epsilon for doing voxel coordinate comparisons.
*
* Revision 1.7 93/08/11 14:31:50 neelin
* Changed prototype for check_imageminmax.
*
* Revision 1.6 93/08/11 13:34:20 neelin
* Converted to use Dave MacDonald's General_transform code.
* Fixed bug in get_slice - for non-linear transformations coord was
* transformed, then used again as a starting coordinate.
* Handle files that have image-max/min that doesn't vary over slices.
* Handle files that have image-max/min varying over row/cols.
* Allow volume to extend to voxel edge for -nearest_neighbour interpolation.
* Handle out-of-range values (-fill values from a previous mincresample, for
* example).
* Save transformation file as a string attribute to processing variable.
*
@COPYRIGHT :
Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre,
Montreal Neurological Institute, McGill University.
Permission to use, copy, modify, and distribute this
software and its documentation for any purpose and without
fee is hereby granted, provided that the above copyright
notice appear in all copies. The author and McGill University
make no representations about the suitability of this
software for any purpose. It is provided "as is" without
express or implied warranty.
---------------------------------------------------------------------------- */
/* Constants used in program */
/* Number of dimensions for various things */
#define VOL_NDIMS 3 /* Number of volume dimensions */
#define WORLD_NDIMS 3 /* Number of world spatial dimensions */
#define SLICE_NDIMS 2 /* Number of slice dimensions */
#define MAT_NDIMS WORLD_NDIMS+1 /* Number of dims for homogenous matrix */
/* For referring to world axes in arrays subscripted by WORLD_NDIMS */
#define NO_AXIS -1
#define XAXIS 0
#define YAXIS 1
#define ZAXIS 2
/* For referring to volume axes in arrays subscripted by VOL_NDIMS */
#define SLC_AXIS 0
#define ROW_AXIS 1
#define COL_AXIS 2
/* For referring to slice axes in arrays subscripted by SLICE_NDIMS */
#define SLICE_ROW 0
#define SLICE_COL 1
/* For referring to world coordinates in Coord_Vector */
#define XCOORD 0
#define YCOORD 1
#define ZCOORD 2
/* For referring to volume coordinates in Coord_Vector */
#define SLICE 0
#define ROW 1
#define COLUMN 2
/* Various constants */
#define NO_VALUE DBL_MAX /* Constant to flag fact that value not set */
#define DEFAULT_MAX 1.0
#define DEFAULT_MIN 0.0
#define FILL_DEFAULT DBL_MAX /* Fillvalue indicating -nofill */
#define SMALL_VALUE (100.0*FLT_MIN) /* A small floating-point value */
#define VOXEL_COORD_EPS (100.0*FLT_EPSILON) /* Epsilon for voxel coords */
#define TRANSFORM_BUFFER_INCREMENT 256
#define PROCESSING_VAR "processing"
#define TEMP_IMAGE_VAR "mincresample-temporary-image"
#ifndef TRUE
# define TRUE 1
# define FALSE 0
#endif
/* Types used in program */
enum Interpolant_type { TRILINEAR, TRICUBIC, N_NEIGHBOUR, WINDOWED_SINC };
typedef double Coord_Vector[WORLD_NDIMS];
typedef struct {
char *name;
int mincid;
int imgid;
int maxid;
int minid;
int ndims;
nc_type datatype;
int is_signed;
double vrange[2]; /* [0]=min, [1]=max */
long nelements[MAX_VAR_DIMS]; /* Size of each dimension */
int world_axes[MAX_VAR_DIMS]; /* Relates variable index to X, Y, Z
or NO_AXIS */
int indices[VOL_NDIMS]; /* Indices of volume dimenions (subscripted
from slowest to fastest) */
int axes[WORLD_NDIMS]; /* Relates world X,Y,Z (index) to dimension
order (value=0,1,2; 0=slowest varying) */
int using_icv; /* True if we are using an icv to read data */
int icvid; /* Id of icv (if used) */
long slices_per_image; /* Number of volume slices (row, column) per
minc file image */
long images_per_file; /* Number of minc file images in the file */
int do_slice_renormalization; /* Flag indicating that we need to
loop through the data a second time,
recomputing the slices to normalize
images properly */
int keep_real_range; /* Flag indicating whether we should keep
the real range of the input data or not */
} File_Info;
typedef struct {
long size[SLICE_NDIMS]; /* Size of each dimension */
double *data; /* Pointer to slice data */
} Slice_Data;
typedef struct Volume_Data_Struct Volume_Data;
typedef int (*Interpolating_Function)
(Volume_Data *volume, Coord_Vector coord, double *result);
struct Volume_Data_Struct {
nc_type datatype; /* Type of data in volume */
int is_signed; /* Sign of data (TRUE if signed) */
int use_fill; /* TRUE if fill values should be used in
calculation of output image max/min */
double fillvalue; /* Value to return when out of bounds */
double vrange[2]; /* [0]=min, [1]=max */
double real_range[2]; /* Real min and max for current volume */
int size[VOL_NDIMS]; /* Size of each dimension */
void *data; /* Pointer to volume data */
double *scale; /* Pointer to array of scales for slices */
double *offset; /* Pointer to array of offsets for slices */
Interpolating_Function interpolant; /* Function Pointer */
};
typedef struct {
File_Info *file; /* Information about associated file */
Volume_Data *volume; /* Volume data for (input volume) */
Slice_Data *slice; /* Slice data for (output volume) */
General_transform *voxel_to_world;
General_transform *world_to_voxel;
} VVolume;
typedef struct {
int axes[WORLD_NDIMS]; /* Relates world X,Y,Z (index) to dimension
order (value=0,1,2; 0=slowest varying) */
long nelements[WORLD_NDIMS]; /* These are subscripted by X, Y and Z */
double step[WORLD_NDIMS];
double start[WORLD_NDIMS];
double dircos[WORLD_NDIMS][WORLD_NDIMS];
double *coords[WORLD_NDIMS];
char units[WORLD_NDIMS][MI_MAX_ATTSTR_LEN];
char spacetype[WORLD_NDIMS][MI_MAX_ATTSTR_LEN];
} Volume_Definition;
typedef struct {
int verbose;
} Program_Flags;
typedef struct {
int invert_transform;
char *file_name;
char *file_contents;
long buffer_length;
General_transform *transformation;
} Transform_Info;
typedef struct {
int clobber;
int keep_real_range;
nc_type datatype;
int is_signed;
double vrange[2];
double fillvalue;
double origin[3];
Program_Flags flags;
enum Interpolant_type interpolant_type; /* Type of interpolation */
Transform_Info transform_info;
Volume_Definition volume_def;
int v2format; /* If non-zero, create a MINC 2.0 output */
} Arg_Data;
typedef struct {
long last_index[VOL_NDIMS];
long nelements[VOL_NDIMS];
double *coords[VOL_NDIMS];
} Irregular_Transform_Data;
/* Macros used in program */
#define DO_TRANSFORM(result, transformation, coord) \
general_transform_point(transformation, \
coord[XCOORD], coord[YCOORD], coord[ZCOORD], \
&result[XCOORD], &result[YCOORD], &result[ZCOORD])
#define DO_INVERSE_TRANSFORM(result, transformation, coord) \
general_inverse_transform_point(transformation, \
coord[XCOORD], coord[YCOORD], coord[ZCOORD], \
&result[XCOORD], &result[YCOORD], &result[ZCOORD])
#define IS_LINEAR(transformation) \
(get_transform_type(transformation)==LINEAR)
#define VECTOR_COPY(result, first) { \
result[XCOORD] = first[XCOORD]; \
result[YCOORD] = first[YCOORD]; \
result[ZCOORD] = first[ZCOORD]; \
}
#define VECTOR_DIFF(result, first, second) { \
result[XCOORD] = first[XCOORD] - second[XCOORD]; \
result[YCOORD] = first[YCOORD] - second[YCOORD]; \
result[ZCOORD] = first[ZCOORD] - second[ZCOORD]; \
}
#define VECTOR_ADD(result, first, second) { \
result[XCOORD] = first[XCOORD] + second[XCOORD]; \
result[YCOORD] = first[YCOORD] + second[YCOORD]; \
result[ZCOORD] = first[ZCOORD] + second[ZCOORD]; \
}
#define VECTOR_SCALAR_MULT(result, vector, scalar) { \
result[XCOORD] = vector[XCOORD] * (scalar); \
result[YCOORD] = vector[YCOORD] * (scalar); \
result[ZCOORD] = vector[ZCOORD] * (scalar); \
}
#ifdef INTERPOLATE
# undef INTERPOLATE
#endif
#define INTERPOLATE(volume, coord, result) \
(*volume->interpolant) (volume, coord, result)
#define VOLUME_VALUE(volume, slcind, rowind, colind, value) \
{ \
long offset; \
\
offset = ((slcind)*volume->size[ROW_AXIS] + \
(rowind))*volume->size[COL_AXIS] + (colind); \
switch (volume->datatype) { \
case NC_BYTE: \
if (volume->is_signed) \
value = *((signed char *) volume->data + offset); \
else \
value = *((unsigned char *) volume->data + offset); \
break; \
case NC_SHORT: \
if (volume->is_signed) \
value = *((signed short *) volume->data + offset); \
else \
value = *((unsigned short *) volume->data + offset); \
break; \
case NC_INT: \
if (volume->is_signed) \
value = *((signed int *) volume->data + offset); \
else \
value = *((unsigned int *) volume->data + offset); \
break; \
case NC_FLOAT: \
value = *((float *) volume->data + offset); \
break; \
case NC_DOUBLE: \
value = *((double *) volume->data + offset); \
break; \
} \
}
/* Function prototypes */
extern void resample_volumes(Program_Flags *program_flags,
VVolume *in_vol, VVolume *out_vol,
General_transform *transformation);
extern int trilinear_interpolant(Volume_Data *volume,
Coord_Vector coord, double *result);
extern int tricubic_interpolant(Volume_Data *volume,
Coord_Vector coord, double *result);
extern int nearest_neighbour_interpolant(Volume_Data *volume,
Coord_Vector coord, double *result);
extern int windowed_sinc_interpolant(Volume_Data *volume,
Coord_Vector coord, double *result);
#define SINC_HALF_WIDTH_MAX 10
#define SINC_HALF_WIDTH_MIN 1
enum sinc_interpolant_window_t {
SINC_WINDOW_NONE,
SINC_WINDOW_HANNING,
SINC_WINDOW_HAMMING
};
extern enum sinc_interpolant_window_t sinc_window_type;
extern int sinc_half_width;
|