1 /* ----------------------------------------------------------------------------
2 @COPYRIGHT :
3 Copyright 1993,1994,1995 David MacDonald,
4 McConnell Brain Imaging Centre,
5 Montreal Neurological Institute, McGill University.
6 Permission to use, copy, modify, and distribute this
7 software and its documentation for any purpose and without
8 fee is hereby granted, provided that the above copyright
9 notice appear in all copies. The author and McGill University
10 make no representations about the suitability of this
11 software for any purpose. It is provided "as is" without
12 express or implied warranty.
13 ---------------------------------------------------------------------------- */
14
15 #ifdef HAVE_CONFIG_H
16 #include "config.h"
17 #endif /*HAVE_CONFIG_H*/
18
19
20
21 #include <internal_volume_io.h>
22 #include <minc_config.h>
23
24 #ifdef HAVE_MINC1
25 #include <minc_basic.h>
26
27 #define INVALID_AXIS -1
28
29 static VIO_BOOL match_dimension_names(
30 int n_volume_dims,
31 VIO_STR volume_dimension_names[],
32 int n_file_dims,
33 VIO_STR file_dimension_names[],
34 int to_volume_index[] );
35
36 /* ----------------------------- MNI Header -----------------------------------
37 @NAME : get_minc_file_n_dimensions
38 @INPUT : filename
39 @OUTPUT :
40 @RETURNS : n_dims
41 @DESCRIPTION: Returns the number of dimensions in the minc file.
42 @METHOD :
43 @GLOBALS :
44 @CALLS :
45 @CREATED : Nov. 4, 1995 David MacDonald
46 @MODIFIED :
47 ---------------------------------------------------------------------------- */
48
get_minc_file_n_dimensions(VIO_STR filename)49 VIOAPI int get_minc_file_n_dimensions(
50 VIO_STR filename )
51 {
52 int cdfid, img_var, n_dims;
53 int dim_vars[MAX_VAR_DIMS];
54 nc_type file_datatype;
55 VIO_STR expanded;
56
57 set_ncopts(NC_VERBOSE);
58
59 expanded = expand_filename( filename );
60
61 cdfid = miopen( expanded, NC_NOWRITE );
62
63 if( cdfid == MI_ERROR )
64 {
65 print_error( "Error opening %s\n", expanded );
66
67 delete_string( expanded );
68
69 return( -1 );
70 }
71
72 delete_string( expanded );
73
74 img_var = ncvarid( cdfid, MIimage );
75
76 ncvarinq( cdfid, img_var, (char *) NULL, &file_datatype,
77 &n_dims, dim_vars, (int *) NULL );
78
79 (void) miclose( cdfid );
80
81 return( n_dims );
82 }
83
84 /* ----------------------------- MNI Header -----------------------------------
85 @NAME : initialize_minc_input_from_minc_id
86 @INPUT : minc_id
87 volume
88 options
89 @OUTPUT :
90 @RETURNS : Minc_file
91 @DESCRIPTION: Initializes input of volumes from an already opened MINC file.
92 @METHOD :
93 @GLOBALS :
94 @CALLS :
95 @CREATED : 1993 David MacDonald
96 @MODIFIED : Nov. 15, 1996 D. MacDonald - added handling of space type
97 @MODIFIED : May 20, 1997 D. MacDonald - removed float arithmetic in
98 transformations and made volumes
99 store starts/steps/dircos
100 ---------------------------------------------------------------------------- */
101
initialize_minc_input_from_minc_id(int minc_id,VIO_Volume volume,minc_input_options * options)102 VIOAPI Minc_file initialize_minc_input_from_minc_id(
103 int minc_id,
104 VIO_Volume volume,
105 minc_input_options *options )
106 {
107 minc_file_struct *file;
108 int dim_vars[MAX_VAR_DIMS], n_vol_dims;
109 int i, slab_size, prev_sizes[MAX_VAR_DIMS];
110 nc_type prev_nc_type;
111 VIO_BOOL different;
112 VIO_BOOL range_specified;
113 double valid_range[2];
114 long long_size;
115 VIO_BOOL converted_sign, space_type_consensus;
116 nc_type converted_type;
117 char signed_flag[MI_MAX_ATTSTR_LEN+1], *ptr;
118 char dim_name[MI_MAX_ATTSTR_LEN+1];
119 char prev_space_type[MI_MAX_ATTSTR_LEN+1];
120 char space_type[MI_MAX_ATTSTR_LEN+1];
121 nc_type file_datatype;
122 int sizes[MAX_VAR_DIMS];
123 double file_separations[MAX_VAR_DIMS];
124 VIO_Real volume_separations[MAX_VAR_DIMS];
125 VIO_Real volume_starts[MAX_VAR_DIMS];
126 VIO_Real voxel_zero;
127 double start_position[MAX_VAR_DIMS];
128 double dir_cosines[MAX_VAR_DIMS][MI_NUM_SPACE_DIMS];
129 double tmp_cosines[MI_NUM_SPACE_DIMS];
130 VIO_BOOL spatial_dim_flags[MAX_VAR_DIMS];
131 double real_min, real_max;
132 int d, dimvar, which_valid_axis, axis;
133 int spatial_axis_indices[MAX_VAR_DIMS];
134 minc_input_options default_options;
135 VIO_BOOL no_volume_data_type;
136 char spacing_type[MI_MAX_ATTSTR_LEN+1];
137 double *irr_starts[MAX_VAR_DIMS];
138 double *irr_widths[MAX_VAR_DIMS];
139
140 ALLOC( file, 1 );
141
142 file->cdfid = minc_id;
143 file->file_is_being_read = TRUE;
144 file->volume = volume;
145 file->using_minc2_api = FALSE;
146
147 if( options == (minc_input_options *) NULL )
148 {
149 set_default_minc_input_options( &default_options );
150 set_default_minc_input_options( &file->original_input_options );
151 options = &default_options;
152 }
153 else
154 file->original_input_options = *options;
155
156 get_volume_sizes( volume, prev_sizes );
157 prev_nc_type = volume->nc_data_type;
158
159 /* --- find the image variable */
160
161 file->img_var = ncvarid( file->cdfid, MIimage );
162
163 ncvarinq( file->cdfid, file->img_var, (char *) NULL, &file_datatype,
164 &file->n_file_dimensions, dim_vars, (int *) NULL );
165
166 for_less( d, 0, file->n_file_dimensions )
167 {
168 (void) ncdiminq( file->cdfid, dim_vars[d], dim_name, &long_size );
169 file->dim_names[d] = create_string( dim_name );
170 file->sizes_in_file[d] = long_size;
171 }
172
173 file->converting_to_colour = FALSE;
174
175 if( equal_strings( file->dim_names[file->n_file_dimensions-1],
176 MIvector_dimension ) )
177 {
178 if( options->convert_vector_to_colour_flag &&
179 file->sizes_in_file[file->n_file_dimensions-1] >=
180 (long) options->dimension_size_for_colour_data &&
181 file->sizes_in_file[file->n_file_dimensions-1] <=
182 (long) options->max_dimension_size_for_colour_data )
183 {
184 for_less( i, 0, 4 )
185 {
186 file->rgba_indices[i] = options->rgba_indices[i];
187
188 if( (long) options->rgba_indices[i] >=
189 file->sizes_in_file[file->n_file_dimensions-1] )
190 {
191 file->rgba_indices[i] = -1;
192 if( i != 3 )
193 print_error( "Warning: rgba indices out of range.\n" );
194 }
195 }
196
197 set_volume_type( volume, NC_INT, FALSE, 0.0, 0.0 );
198 set_rgb_volume_flag( volume, TRUE );
199 file->converting_to_colour = TRUE;
200 delete_string( file->dim_names[file->n_file_dimensions-1] );
201 --file->n_file_dimensions;
202 }
203 else if( options->convert_vector_to_scalar_flag )
204 {
205 delete_string( file->dim_names[file->n_file_dimensions-1] );
206 --file->n_file_dimensions;
207 }
208 }
209
210 /* Set the number of dimensions iff the file has fewer dimensions
211 * than the initially created volume.
212 */
213 if (get_volume_n_dimensions( volume ) > file->n_file_dimensions)
214 {
215 set_volume_n_dimensions( volume, file->n_file_dimensions );
216 }
217
218 n_vol_dims = get_volume_n_dimensions( volume );
219 if( file->n_file_dimensions < n_vol_dims )
220 {
221 print_error( "Error: MINC file has only %d dims, volume requires %d.\n",
222 file->n_file_dimensions, n_vol_dims );
223 FREE( file );
224 return( (Minc_file) 0 );
225 }
226 else if( file->n_file_dimensions > MAX_VAR_DIMS )
227 {
228 print_error( "Error: MINC file has %d dims, can only handle %d.\n",
229 file->n_file_dimensions, MAX_VAR_DIMS );
230 FREE( file );
231 return( (Minc_file) NULL );
232 }
233
234 /* --- match the dimension names of the volume with those in the file */
235
236 if( !match_dimension_names( get_volume_n_dimensions(volume),
237 volume->dimension_names,
238 file->n_file_dimensions, file->dim_names,
239 file->to_volume_index ) )
240 {
241 print_error( "Error: dimension names did not match: \n" );
242
243 print_error( "\n" );
244 print_error( "Requested:\n" );
245 for_less( d, 0, n_vol_dims )
246 print_error( "%d: %s\n", d+1, volume->dimension_names[d] );
247
248 print_error( "\n" );
249 print_error( "In File:\n" );
250 for_less( d, 0, file->n_file_dimensions )
251 print_error( "%d: %s\n", d+1, file->dim_names[d] );
252
253 FREE( file );
254 return( (Minc_file) NULL );
255 }
256
257 for_less( d, 0, n_vol_dims )
258 file->to_file_index[d] = INVALID_AXIS;
259
260 for_less( d, 0, file->n_file_dimensions )
261 {
262 if( file->to_volume_index[d] != INVALID_AXIS )
263 file->to_file_index[file->to_volume_index[d]] = d;
264 }
265
266 file->n_volumes_in_file = 1;
267
268 /* --- find the spatial axes (x,y,z) */
269
270 which_valid_axis = 0;
271
272 for_less( d, 0, VIO_N_DIMENSIONS )
273 {
274 volume->spatial_axes[d] = INVALID_AXIS;
275 file->spatial_axes[d] = INVALID_AXIS;
276 }
277
278 for_less( d, 0, file->n_file_dimensions )
279 {
280 if( convert_dim_name_to_spatial_axis( file->dim_names[d], &axis ) )
281 {
282 spatial_axis_indices[d] = axis;
283 file->spatial_axes[axis] = d;
284 }
285 else
286 spatial_axis_indices[d] = INVALID_AXIS;
287
288 spatial_dim_flags[d] = (spatial_axis_indices[d] != INVALID_AXIS);
289
290 if( file->to_volume_index[d] != INVALID_AXIS )
291 {
292 file->valid_file_axes[which_valid_axis] = d;
293
294 if( spatial_dim_flags[d] )
295 {
296 volume->spatial_axes[spatial_axis_indices[d]] =
297 file->to_volume_index[d];
298 }
299
300 ++which_valid_axis;
301 }
302 }
303
304 /* --- get the spatial axis info, slice separation, start pos, etc. */
305
306 prev_space_type[0] = (char) 0;
307 space_type_consensus = TRUE;
308
309 for_less( d, 0, file->n_file_dimensions )
310 {
311 file_separations[d] = 1.0;
312 start_position[d] = 0.0;
313
314 irr_starts[d] = NULL;
315 irr_widths[d] = NULL;
316
317 if( spatial_dim_flags[d] )
318 {
319 dir_cosines[d][0] = 0.0;
320 dir_cosines[d][1] = 0.0;
321 dir_cosines[d][2] = 0.0;
322 dir_cosines[d][spatial_axis_indices[d]] = 1.0;
323 }
324
325 dimvar = ncvarid( file->cdfid, file->dim_names[d] );
326 if( dimvar != MI_ERROR )
327 {
328 (void) miattget1( file->cdfid, dimvar, MIstep, NC_DOUBLE,
329 (void *) (&file_separations[d]) );
330
331 if( spatial_dim_flags[d] )
332 {
333 if( miattget1( file->cdfid, dimvar, MIstart, NC_DOUBLE,
334 (void *) (&start_position[d]) ) == MI_ERROR )
335 start_position[d] = 0.0;
336
337 if( miattget( file->cdfid, dimvar, MIdirection_cosines,
338 NC_DOUBLE, MI_NUM_SPACE_DIMS,
339 (void *) tmp_cosines, (int *) NULL )
340 != MI_ERROR )
341 {
342 dir_cosines[d][0] = tmp_cosines[0];
343 dir_cosines[d][1] = tmp_cosines[1];
344 dir_cosines[d][2] = tmp_cosines[2];
345 }
346
347 ptr = miattgetstr( file->cdfid, dimvar, MIspacetype,
348 MI_MAX_ATTSTR_LEN+1, space_type );
349
350 if( ptr != NULL )
351 {
352 if( string_length( prev_space_type ) > 0 &&
353 string_length( space_type ) > 0 &&
354 !equal_strings( prev_space_type, space_type ) )
355 {
356 space_type_consensus = FALSE;
357 }
358
359 if( string_length( space_type ) > 0 )
360 (void) strcpy( prev_space_type, space_type );
361 }
362 }
363 else if (!strcmp(MItime, file->dim_names[d])) {
364 /* For the moment this is implemented for time dimensions
365 * only.
366 */
367 miattgetstr(file->cdfid, dimvar, MIspacing,
368 MI_MAX_ATTSTR_LEN+1, spacing_type);
369 if (!strcmp(spacing_type, MI_IRREGULAR)) {
370 long start[1];
371 long count[1];
372
373 irr_starts[d] = malloc(sizeof(VIO_Real) * file->sizes_in_file[d]);
374 irr_widths[d] = malloc(sizeof(VIO_Real) * file->sizes_in_file[d]);
375
376 start[0] = 0;
377 count[0] = file->sizes_in_file[d];
378
379 mivarget(file->cdfid, dimvar, start, count,
380 NC_DOUBLE, MI_SIGNED, irr_starts[d]);
381
382 dimvar = ncvarid(file->cdfid, MItime_width);
383 if (dimvar < 0) {
384 for (i = 0; i < count[0]; i++) {
385 irr_widths[d][i] = file_separations[d];
386 }
387 }
388 else {
389 mivarget(file->cdfid, dimvar, start, count,
390 NC_DOUBLE, MI_SIGNED, irr_widths[d]);
391 }
392 }
393 else {
394 if( miattget1(file->cdfid, dimvar, MIstart, NC_DOUBLE,
395 (void *) (&start_position[d]) ) == MI_ERROR )
396 start_position[d] = 0.0;
397 }
398 }
399 }
400
401 if( file->to_volume_index[d] == INVALID_AXIS )
402 {
403 file->n_volumes_in_file *= (int) file->sizes_in_file[d];
404 }
405 else
406 {
407 sizes[file->to_volume_index[d]] = (int) file->sizes_in_file[d];
408 volume_separations[file->to_volume_index[d]] =
409 file_separations[d];
410
411 if( file->to_volume_index[d] != INVALID_AXIS )
412 {
413 volume_starts[file->to_volume_index[d]] = start_position[d];
414 set_volume_direction_unit_cosine( volume,
415 file->to_volume_index[d], dir_cosines[d] );
416 }
417
418 }
419 }
420
421 /* --- create the world transform stored in the volume */
422
423 set_volume_separations( volume, volume_separations );
424 set_volume_starts( volume, volume_starts );
425
426 if( space_type_consensus )
427 set_volume_space_type( volume, prev_space_type );
428
429 /* --- create the file world transform */
430
431 compute_world_transform( file->spatial_axes, file_separations,
432 dir_cosines, start_position,
433 &file->voxel_to_world_transform );
434
435 /* --- decide on type conversion */
436
437 if( file->converting_to_colour )
438 {
439 converted_type = NC_FLOAT;
440 converted_sign = FALSE;
441 }
442 else
443 {
444 no_volume_data_type = (get_volume_data_type(volume) == VIO_NO_DATA_TYPE);
445 if( no_volume_data_type ) /* --- use type of file */
446 {
447 if( miattgetstr( file->cdfid, file->img_var, MIsigntype,
448 MI_MAX_ATTSTR_LEN, signed_flag ) != NULL )
449 {
450 converted_sign = equal_strings( signed_flag, MI_SIGNED );
451 }
452 else
453 converted_sign = file_datatype != NC_BYTE;
454
455 converted_type = file_datatype;
456 set_volume_type( volume, converted_type, converted_sign, 0.0, 0.0 );
457 }
458 else /* --- use specified type */
459 {
460 converted_type = get_volume_nc_data_type( volume, &converted_sign );
461 }
462 }
463
464 set_volume_sizes( volume, sizes );
465
466 for_less( d, 0, file->n_file_dimensions )
467 {
468 if (file->to_volume_index[d] == INVALID_AXIS) {
469 continue;
470 }
471
472 if (irr_starts[d] != NULL) {
473 set_volume_irregular_starts(volume, file->to_volume_index[d],
474 file->sizes_in_file[d],
475 irr_starts[d]);
476 FREE( irr_starts[d] );
477 }
478
479 if (irr_widths[d] != NULL) {
480 set_volume_irregular_widths(volume, file->to_volume_index[d],
481 file->sizes_in_file[d],
482 irr_widths[d]);
483 FREE( irr_widths[d] );
484 }
485 }
486
487 /* --- create the image conversion variable */
488
489 file->minc_icv = miicv_create();
490
491 (void) miicv_setint( file->minc_icv, MI_ICV_TYPE, (int) converted_type );
492 (void) miicv_setstr( file->minc_icv, MI_ICV_SIGN,
493 converted_sign ? MI_SIGNED : MI_UNSIGNED );
494 (void) miicv_setint( file->minc_icv, MI_ICV_DO_NORM, TRUE );
495 (void) miicv_setint( file->minc_icv, MI_ICV_DO_FILLVALUE, TRUE );
496
497 get_volume_voxel_range( volume, &valid_range[0], &valid_range[1] );
498 range_specified = (valid_range[0] < valid_range[1]);
499
500 valid_range[0] = 0.0;
501 valid_range[1] = 0.0;
502
503 if( file->converting_to_colour )
504 {
505 valid_range[0] = 0.0;
506 valid_range[1] = 2.0 * (double) (1ul << 31ul) - 1.0;
507 set_volume_voxel_range( volume, valid_range[0], valid_range[1] );
508 }
509 else if( no_volume_data_type )
510 {
511 if (miget_valid_range( file->cdfid, file->img_var,
512 valid_range) == MI_ERROR) {
513 valid_range[0] = valid_range[1] = 0.0;
514 }
515 }
516
517 if( !file->converting_to_colour &&
518 (no_volume_data_type || !range_specified) )
519 {
520 set_volume_voxel_range( volume, valid_range[0], valid_range[1] );
521 }
522
523 if( !file->converting_to_colour )
524 {
525 get_volume_voxel_range( volume, &valid_range[0], &valid_range[1] );
526
527 (void) miicv_setdbl( file->minc_icv, MI_ICV_VALID_MIN, valid_range[0]);
528 (void) miicv_setdbl( file->minc_icv, MI_ICV_VALID_MAX, valid_range[1]);
529 }
530 else
531 {
532 (void) miicv_setdbl( file->minc_icv, MI_ICV_VALID_MIN, 0.0 );
533 (void) miicv_setdbl( file->minc_icv, MI_ICV_VALID_MAX, 1.0 );
534 }
535
536 if (options->user_real_range[0] < options->user_real_range[1]) {
537 (void) miicv_setint( file->minc_icv, MI_ICV_USER_NORM, TRUE );
538 (void) miicv_setdbl( file->minc_icv, MI_ICV_IMAGE_MIN,
539 options->user_real_range[0] );
540 (void) miicv_setdbl( file->minc_icv, MI_ICV_IMAGE_MAX,
541 options->user_real_range[1] );
542 }
543
544 if( options->convert_vector_to_scalar_flag && !file->converting_to_colour )
545 {
546 (void) miicv_setint( file->minc_icv, MI_ICV_DO_DIM_CONV, TRUE );
547 (void) miicv_setint( file->minc_icv, MI_ICV_DO_SCALAR, TRUE );
548 (void) miicv_setint( file->minc_icv, MI_ICV_XDIM_DIR, FALSE );
549 (void) miicv_setint( file->minc_icv, MI_ICV_YDIM_DIR, FALSE );
550 (void) miicv_setint( file->minc_icv, MI_ICV_ZDIM_DIR, FALSE );
551 (void) miicv_setint( file->minc_icv, MI_ICV_KEEP_ASPECT, FALSE );
552 }
553
554 (void) miicv_attach( file->minc_icv, file->cdfid, file->img_var );
555
556 /* --- compute the mapping to real values */
557
558 (void) miicv_inqdbl( file->minc_icv, MI_ICV_NORM_MIN, &real_min );
559 (void) miicv_inqdbl( file->minc_icv, MI_ICV_NORM_MAX, &real_max );
560
561 if( !file->converting_to_colour )
562 set_volume_real_range( volume, real_min, real_max );
563
564 /* --- if promoting invalid values to zero, then we need to detach and
565 reattach in order to change the fillvalue in the icv */
566
567 if( options->promote_invalid_to_zero_flag )
568 {
569 (void) miicv_detach( file->minc_icv );
570
571 if( !file->converting_to_colour )
572 {
573 if( real_min == real_max )
574 voxel_zero = valid_range[0];
575 else if( real_min > 0.0 )
576 voxel_zero = valid_range[0];
577 else if( real_max < 0.0 )
578 voxel_zero = valid_range[1];
579 else
580 {
581 voxel_zero = valid_range[0] +
582 (valid_range[1] - valid_range[0]) *
583 (0.0 - real_min) / (real_max - real_min);
584 }
585
586 (void) miicv_setdbl( file->minc_icv, MI_ICV_FILLVALUE, voxel_zero );
587 }
588 else
589 (void) miicv_setdbl( file->minc_icv, MI_ICV_FILLVALUE, 0.0 );
590
591 (void) miicv_attach( file->minc_icv, file->cdfid, file->img_var );
592 }
593
594 for_less( d, 0, file->n_file_dimensions )
595 file->indices[d] = 0;
596
597 file->end_volume_flag = FALSE;
598
599 set_ncopts(NC_VERBOSE | NC_FATAL);
600
601 /* --- decide how many full dimensions to read in at a time
602 to max out the read/write buffer and make it like the
603 chunking dimensions for compression */
604
605 file->n_slab_dims = 0;
606 slab_size = 1;
607 int unit_size = get_type_size( get_volume_data_type(volume) );
608 int full_dim = 1;
609
610 for( d = file->n_file_dimensions-1; d >= 0; d-- ) {
611 if( file->to_volume_index[d] != INVALID_AXIS ) {
612 if( MI_MAX_VAR_BUFFER_SIZE > file->sizes_in_file[d] * slab_size * unit_size && full_dim ) {
613 slab_size *= file->sizes_in_file[d];
614 file->n_slab_dims++; /* integral number of complete dimensions */
615 } else {
616 slab_size *= MIN( file->sizes_in_file[d],
617 (long)( MI_MAX_VAR_BUFFER_SIZE / ( slab_size * unit_size ) ) );
618 full_dim = 0;
619 }
620 }
621 }
622
623 /* --- decide whether the volume data must be freed (if it changed size) */
624
625 different = FALSE;
626 for_less( d, 0, n_vol_dims )
627 {
628 if( sizes[d] != prev_sizes[d] )
629 different = TRUE;
630 }
631
632 if( prev_nc_type != converted_type )
633 different = TRUE;
634
635 if( different && volume_is_alloced( volume ) && !volume_is_cached(volume) )
636 free_volume_data( volume );
637
638 return( file );
639 }
640
641 /* ----------------------------- MNI Header -----------------------------------
642 @NAME : initialize_minc_input
643 @INPUT : filename
644 volume
645 @OUTPUT :
646 @RETURNS : Minc_file
647 @DESCRIPTION: Initializes the input of a MINC file, passing back a MINC
648 file pointer. It assumes that the volume has been created,
649 with the desired type, or MI_ORIGINAL_TYPE type if it is desired
650 to use whatever type is in the file.
651 @METHOD :
652 @GLOBALS :
653 @CALLS :
654 @CREATED : June, 1993 David MacDonald
655 @MODIFIED :
656 ---------------------------------------------------------------------------- */
657
initialize_minc_input(VIO_STR filename,VIO_Volume volume,minc_input_options * options)658 VIOAPI Minc_file initialize_minc_input(
659 VIO_STR filename,
660 VIO_Volume volume,
661 minc_input_options *options )
662 {
663 Minc_file file;
664 int minc_id;
665 VIO_STR expanded;
666
667 set_ncopts(0);
668
669 expanded = expand_filename( filename );
670
671 minc_id = miopen( expanded, NC_NOWRITE );
672
673 if( minc_id == MI_ERROR )
674 {
675 print_error( "Error: opening MINC file \"%s\".\n", expanded );
676 return( (Minc_file) 0 );
677 }
678
679 file = initialize_minc_input_from_minc_id( minc_id, volume, options );
680
681 if( file == (Minc_file) NULL )
682 (void) miclose( minc_id );
683 else
684 file->filename = create_string( expanded );
685
686 delete_string( expanded );
687
688 return( file );
689 }
690
691 /* ----------------------------- MNI Header -----------------------------------
692 @NAME : get_n_input_volumes
693 @INPUT : file
694 @OUTPUT :
695 @RETURNS : number of input volumes
696 @DESCRIPTION: After initializing the file input with a specified volume,
697 the user calls this function to decide how many volumes are
698 stored in the file.
699 @METHOD :
700 @GLOBALS :
701 @CALLS :
702 @CREATED : June, 1993 David MacDonald
703 @MODIFIED :
704 ---------------------------------------------------------------------------- */
705
get_n_input_volumes(Minc_file file)706 VIOAPI int get_n_input_volumes(
707 Minc_file file )
708 {
709 return( file->n_volumes_in_file );
710 }
711
712 /* ----------------------------- MNI Header -----------------------------------
713 @NAME : close_minc_input
714 @INPUT : file
715 @OUTPUT :
716 @RETURNS : VIO_OK or VIO_ERROR
717 @DESCRIPTION: Closes the minc input file.
718 @METHOD :
719 @GLOBALS :
720 @CALLS :
721 @CREATED : June, 1993 David MacDonald
722 @MODIFIED :
723 ---------------------------------------------------------------------------- */
724
close_minc_input(Minc_file file)725 VIOAPI VIO_Status close_minc_input(
726 Minc_file file )
727 {
728 int d;
729
730 if( file == (Minc_file) NULL )
731 {
732 print_error( "close_minc_input(): NULL file.\n" );
733 return( VIO_ERROR );
734 }
735
736 (void) miclose( file->cdfid );
737 (void) miicv_free( file->minc_icv );
738
739 for_less( d, 0, file->n_file_dimensions )
740 delete_string( file->dim_names[d] );
741
742 delete_string( file->filename );
743
744 delete_general_transform( &file->voxel_to_world_transform );
745 FREE( file );
746
747 return( VIO_OK );
748 }
749
750 /* ----------------------------- MNI Header -----------------------------------
751 @NAME : input_minc_hyperslab
752 @INPUT : file
753 data_type
754 n_array_dims
755 array_sizes
756 array_data_ptr
757 to_array
758 start
759 count
760 @OUTPUT :
761 @RETURNS : VIO_OK or VIO_ERROR
762 @DESCRIPTION: Inputs a hyperslab from the file into the array pointer.
763 @METHOD :
764 @GLOBALS :
765 @CALLS :
766 @CREATED : Sep. 1, 1995 David MacDonald
767 @MODIFIED :
768 ---------------------------------------------------------------------------- */
769
input_minc_hyperslab(Minc_file file,VIO_Data_types data_type,int n_array_dims,int array_sizes[],void * array_data_ptr,int to_array[],int start[],int count[])770 VIOAPI VIO_Status input_minc_hyperslab(
771 Minc_file file,
772 VIO_Data_types data_type,
773 int n_array_dims,
774 int array_sizes[],
775 void *array_data_ptr,
776 int to_array[],
777 int start[],
778 int count[] )
779 {
780 VIO_Status status;
781 int ind, expected_ind, file_ind, d, i, dim;
782 int size0, size1, size2, size3, size4;
783 int n_tmp_dims, n_file_dims;
784 void *void_ptr;
785 VIO_BOOL direct_to_array, non_full_size_found;
786 int tmp_ind, tmp_sizes[MAX_VAR_DIMS];
787 int vol1_indices[VIO_MAX_DIMENSIONS];
788 int v[VIO_MAX_DIMENSIONS], voxel[VIO_MAX_DIMENSIONS];
789 long used_start[MAX_VAR_DIMS], used_count[MAX_VAR_DIMS];
790 VIO_Real rgb[4];
791 VIO_Colour colour;
792 VIO_multidim_array buffer_array, rgb_array;
793
794 n_file_dims = file->n_file_dimensions;
795 direct_to_array = TRUE;
796 expected_ind = n_array_dims-1;
797 tmp_ind = n_file_dims-1;
798 non_full_size_found = FALSE;
799
800 for_less( ind, 0, n_array_dims )
801 vol1_indices[ind] = -1;
802
803 /*--- check if the hyperslab is a continuous chunk of memory in the array */
804
805 for( file_ind = n_file_dims-1; file_ind >= 0; --file_ind )
806 {
807 used_start[file_ind] = (long) start[file_ind];
808 used_count[file_ind] = (long) count[file_ind];
809
810 ind = to_array[file_ind];
811
812 if( ind != INVALID_AXIS )
813 {
814 if( !non_full_size_found &&
815 (long) count[file_ind] < file->sizes_in_file[file_ind] )
816 non_full_size_found = TRUE;
817 else if( non_full_size_found && count[file_ind] > 1 )
818 direct_to_array = FALSE;
819
820 if( count[file_ind] > 1 && ind != expected_ind )
821 direct_to_array = FALSE;
822
823 if( count[file_ind] != 1 || file->sizes_in_file[file_ind] == 1 )
824 {
825 tmp_sizes[tmp_ind] = count[file_ind];
826 vol1_indices[tmp_ind] = ind;
827 --tmp_ind;
828 }
829
830 --expected_ind;
831 }
832 }
833
834 if( !direct_to_array || file->converting_to_colour )
835 {
836 /*--- make a temporary buffer array, so that there is a continuous
837 chunk */
838
839 n_tmp_dims = n_file_dims - tmp_ind - 1;
840 for_less( dim, 0, n_tmp_dims )
841 {
842 tmp_sizes[dim] = tmp_sizes[dim+tmp_ind+1];
843 vol1_indices[dim] = vol1_indices[dim+tmp_ind+1];
844 }
845
846 create_multidim_array( &buffer_array, n_tmp_dims, tmp_sizes, data_type);
847
848 if( file->converting_to_colour )
849 {
850 used_start[n_file_dims] = 0;
851 used_count[n_file_dims] = file->sizes_in_file[n_file_dims];
852 tmp_sizes[n_tmp_dims] = (int) used_count[n_file_dims];
853
854 create_multidim_array( &rgb_array, n_tmp_dims+1, tmp_sizes, VIO_FLOAT );
855
856 GET_MULTIDIM_PTR( void_ptr, rgb_array, 0, 0, 0, 0, 0 );
857 }
858 else
859 {
860 GET_MULTIDIM_PTR( void_ptr, buffer_array, 0, 0, 0, 0, 0 );
861 }
862 }
863 else
864 {
865 void_ptr = array_data_ptr;
866 }
867
868 if( miicv_get( file->minc_icv, used_start, used_count, void_ptr ) ==
869 MI_ERROR )
870 {
871 status = VIO_ERROR;
872 if( file->converting_to_colour )
873 delete_multidim_array( &rgb_array );
874 if( !direct_to_array || file->converting_to_colour )
875 delete_multidim_array( &buffer_array );
876 }
877 else
878 status = VIO_OK;
879
880 if( status == VIO_OK && (!direct_to_array || file->converting_to_colour) )
881 {
882 if( file->converting_to_colour )
883 {
884 for_less( dim, n_tmp_dims, VIO_MAX_DIMENSIONS )
885 tmp_sizes[dim] = 1;
886
887 size0 = tmp_sizes[0];
888 size1 = tmp_sizes[1];
889 size2 = tmp_sizes[2];
890 size3 = tmp_sizes[3];
891 size4 = tmp_sizes[4];
892
893 for_less( v[4], 0, size4 )
894 for_less( v[3], 0, size3 )
895 for_less( v[2], 0, size2 )
896 for_less( v[1], 0, size1 )
897 for_less( v[0], 0, size0 )
898 {
899 for_less( d, 0, n_tmp_dims )
900 voxel[d] = v[d];
901
902 for_less( i, 0, 4 )
903 {
904 if( file->rgba_indices[i] < 0 )
905 {
906 if( i < 3 )
907 rgb[i] = 0.0;
908 else
909 rgb[i] = 1.0;
910 }
911 else
912 {
913 voxel[n_tmp_dims] = file->rgba_indices[i];
914 GET_MULTIDIM( rgb[i], (VIO_Real), rgb_array,
915 voxel[0], voxel[1],
916 voxel[2], voxel[3], voxel[4] );
917 }
918 }
919
920 colour = make_rgba_Colour_0_1( rgb[0], rgb[1], rgb[2], rgb[3] );
921 SET_MULTIDIM( buffer_array,
922 voxel[0], voxel[1],
923 voxel[2], voxel[3], voxel[4], colour );
924 }
925
926 delete_multidim_array( &rgb_array );
927 }
928
929 GET_MULTIDIM_PTR( void_ptr, buffer_array, 0, 0, 0, 0, 0 );
930 copy_multidim_data_reordered( get_type_size(data_type),
931 array_data_ptr, n_array_dims, array_sizes,
932 void_ptr, n_tmp_dims, tmp_sizes,
933 tmp_sizes, vol1_indices, FALSE );
934
935 delete_multidim_array( &buffer_array );
936 }
937
938 return( status );
939 }
940
941 /* ----------------------------- MNI Header -----------------------------------
942 @NAME : input_slab
943 @INPUT : file
944 volume
945 start
946 count
947 @OUTPUT :
948 @RETURNS :
949 @DESCRIPTION: Inputs a multidimensional slab from the file and copies it
950 into the appropriate part of the volume.
951 @METHOD :
952 @GLOBALS :
953 @CALLS :
954 @CREATED : June, 1993 David MacDonald
955 @MODIFIED :
956 ---------------------------------------------------------------------------- */
957
input_slab(Minc_file file,VIO_Volume volume,int to_volume[],long start[],long count[])958 static int input_slab(
959 Minc_file file,
960 VIO_Volume volume,
961 int to_volume[],
962 long start[],
963 long count[] )
964 {
965 int file_ind, ind;
966 int volume_start[MAX_VAR_DIMS];
967 int file_start[VIO_MAX_DIMENSIONS];
968 int file_count[VIO_MAX_DIMENSIONS];
969 int array_sizes[VIO_MAX_DIMENSIONS];
970 void *array_data_ptr;
971
972 for_less( ind, 0, VIO_MAX_DIMENSIONS )
973 {
974 volume_start[ind] = 0;
975 }
976
977 for_less( file_ind, 0, file->n_file_dimensions )
978 {
979 file_start[file_ind] = (int) start[file_ind];
980 file_count[file_ind] = (int) count[file_ind];
981
982 ind = to_volume[file_ind];
983 if( ind != INVALID_AXIS )
984 volume_start[ind] = file_start[file_ind];
985 }
986
987 get_multidim_sizes( &volume->array, array_sizes );
988 GET_MULTIDIM_PTR( array_data_ptr, volume->array,
989 volume_start[0], volume_start[1], volume_start[2],
990 volume_start[3], volume_start[4] );
991
992 return input_minc_hyperslab( file,
993 get_multidim_data_type(&volume->array),
994 get_multidim_n_dimensions(&volume->array),
995 array_sizes, array_data_ptr, to_volume,
996 file_start, file_count );
997 }
998
999 /* ----------------------------- MNI Header -----------------------------------
1000 @NAME : input_more_minc_file
1001 @INPUT : file
1002 @OUTPUT : fraction_done - amount of file read
1003 @RETURNS : TRUE if volume has more left to read
1004 @DESCRIPTION: Reads another chunk from the input file, passes back the
1005 total fraction read so far, and returns FALSE when the whole
1006 volume has been read.
1007 @METHOD :
1008 @GLOBALS :
1009 @CALLS :
1010 @CREATED : June, 1993 David MacDonald
1011 @MODIFIED :
1012 ---------------------------------------------------------------------------- */
1013
input_more_minc_file(Minc_file file,VIO_Real * fraction_done)1014 VIOAPI VIO_BOOL input_more_minc_file(
1015 Minc_file file,
1016 VIO_Real *fraction_done )
1017 {
1018 int d, ind, n_done, total, n_slab;
1019 long count[MAX_VAR_DIMS];
1020 VIO_Volume volume;
1021 VIO_BOOL increment;
1022
1023 if( file->end_volume_flag )
1024 {
1025 print_error( "End of file in input_more_minc_file()\n" );
1026 return( FALSE );
1027 }
1028
1029 volume = file->volume;
1030
1031 if( !volume_is_alloced( volume ) )
1032 {
1033 alloc_volume_data( volume );
1034 if( volume->is_cached_volume )
1035 {
1036 open_cache_volume_input_file( &volume->cache, volume,
1037 file->filename,
1038 &file->original_input_options );
1039 }
1040 if( !volume_is_alloced( volume ) ) return( FALSE );
1041 }
1042
1043 if( volume->is_cached_volume )
1044 {
1045 *fraction_done = 1.0;
1046 file->end_volume_flag = TRUE;
1047 }
1048 else
1049 {
1050 /* --- set the counts for reading, actually these will be the same
1051 every time */
1052
1053 for_less( ind, 0, file->n_file_dimensions )
1054 count[ind] = 1;
1055
1056 n_slab = 0;
1057
1058 for( d = file->n_file_dimensions-1;
1059 d >= 0 && n_slab < file->n_slab_dims;
1060 --d )
1061 {
1062 if( file->to_volume_index[d] != INVALID_AXIS )
1063 {
1064 count[d] = file->sizes_in_file[d];
1065 ++n_slab;
1066 }
1067 }
1068
1069 if (input_slab( file, volume, file->to_volume_index, file->indices,
1070 count ) != VIO_OK)
1071 {
1072 return FALSE;
1073 }
1074
1075 /* --- advance to next slab */
1076
1077 increment = TRUE;
1078 n_slab = 0;
1079 total = 1;
1080 n_done = 0;
1081
1082 for( d = file->n_file_dimensions-1; d >= 0; --d )
1083 {
1084 if( n_slab >= file->n_slab_dims &&
1085 file->to_volume_index[d] != INVALID_AXIS )
1086 {
1087 if( increment )
1088 {
1089 ++file->indices[d];
1090 if( file->indices[d] < file->sizes_in_file[d] )
1091 increment = FALSE;
1092 else
1093 file->indices[d] = 0;
1094 }
1095 n_done += total * (int) file->indices[d];
1096 total *= (int) file->sizes_in_file[d];
1097 }
1098
1099 if( file->to_volume_index[d] != INVALID_AXIS )
1100 ++n_slab;
1101 }
1102
1103 if( increment )
1104 {
1105 *fraction_done = 1.0;
1106 file->end_volume_flag = TRUE;
1107 }
1108 else
1109 {
1110 *fraction_done = (VIO_Real) n_done / (VIO_Real) total;
1111 }
1112 }
1113
1114 return( !file->end_volume_flag );
1115 }
1116
1117 /* ----------------------------- MNI Header -----------------------------------
1118 @NAME : advance_input_volume
1119 @INPUT : file
1120 @OUTPUT :
1121 @RETURNS : TRUE if more volumes to read
1122 @DESCRIPTION: Advances the file indices to prepare for reading the next
1123 volume from the file.
1124 @METHOD :
1125 @GLOBALS :
1126 @CALLS :
1127 @CREATED : 1993 David MacDonald
1128 @MODIFIED :
1129 ---------------------------------------------------------------------------- */
1130
advance_input_volume(Minc_file file)1131 VIOAPI VIO_BOOL advance_input_volume(
1132 Minc_file file )
1133 {
1134 int ind, c, axis;
1135 VIO_Real voxel[VIO_MAX_DIMENSIONS], world_space[VIO_N_DIMENSIONS];
1136 VIO_Real vol_world_space[VIO_N_DIMENSIONS];
1137 VIO_Transform offset;
1138 VIO_General_transform offset_transform, new_transform;
1139
1140 ind = file->n_file_dimensions-1;
1141
1142 while( ind >= 0 )
1143 {
1144 if( file->to_volume_index[ind] == INVALID_AXIS )
1145 {
1146 ++file->indices[ind];
1147 if( file->indices[ind] < file->sizes_in_file[ind] )
1148 break;
1149
1150 file->indices[ind] = 0;
1151 }
1152 --ind;
1153 }
1154
1155 if( ind >= 0 )
1156 {
1157 file->end_volume_flag = FALSE;
1158
1159 for_less( ind, 0, get_volume_n_dimensions( file->volume ) )
1160 file->indices[file->valid_file_axes[ind]] = 0;
1161
1162 /*--- update the volume's voxel-to-world transform */
1163
1164 for_less( c, 0, VIO_N_DIMENSIONS )
1165 {
1166 axis = file->spatial_axes[c];
1167 if( axis != INVALID_AXIS )
1168 voxel[c] = (VIO_Real) file->indices[axis];
1169 else
1170 voxel[c] = 0.0;
1171 }
1172
1173 general_transform_point( &file->voxel_to_world_transform,
1174 voxel[0], voxel[1], voxel[2],
1175 &world_space[VIO_X], &world_space[VIO_Y],
1176 &world_space[VIO_Z]);
1177
1178 for_less( c, 0, get_volume_n_dimensions(file->volume) )
1179 voxel[c] = 0.0;
1180
1181 convert_voxel_to_world( file->volume, voxel,
1182 &vol_world_space[VIO_X], &vol_world_space[VIO_Y],
1183 &vol_world_space[VIO_Z]);
1184
1185 make_identity_transform( &offset );
1186 for_less( c, 0, VIO_N_DIMENSIONS )
1187 Transform_elem(offset,c,3) = world_space[c] - vol_world_space[c];
1188 create_linear_transform( &offset_transform, &offset );
1189 concat_general_transforms( get_voxel_to_world_transform(file->volume),
1190 &offset_transform, &new_transform );
1191 set_voxel_to_world_transform( file->volume, &new_transform );
1192 delete_general_transform( &offset_transform );
1193
1194 /*--- update the volume if it is cached */
1195
1196 if( file->volume->is_cached_volume )
1197 set_cache_volume_file_offset( &file->volume->cache, file->volume,
1198 file->indices );
1199 }
1200 else
1201 file->end_volume_flag = TRUE;
1202
1203 return( file->end_volume_flag );
1204 }
1205
1206 /* ----------------------------- MNI Header -----------------------------------
1207 @NAME : reset_input_volume
1208 @INPUT : file
1209 @OUTPUT :
1210 @RETURNS :
1211 @DESCRIPTION: Rewinds the file indices to start inputting volumes from the
1212 file.
1213 @METHOD :
1214 @GLOBALS :
1215 @CALLS :
1216 @CREATED : 1993 David MacDonald
1217 @MODIFIED :
1218 ---------------------------------------------------------------------------- */
1219
reset_input_volume(Minc_file file)1220 VIOAPI void reset_input_volume(
1221 Minc_file file )
1222 {
1223 int d;
1224
1225 for_less( d, 0, file->n_file_dimensions )
1226 file->indices[d] = 0;
1227 file->end_volume_flag = FALSE;
1228
1229 set_cache_volume_file_offset( &file->volume->cache, file->volume,
1230 file->indices );
1231 }
1232
1233 /* ----------------------------- MNI Header -----------------------------------
1234 @NAME : match_dimension_names
1235 @INPUT : n_volume_dims
1236 volume_dimension_names
1237 n_file_dims
1238 file_dimension_names
1239 @OUTPUT : to_volume_index
1240 @RETURNS : TRUE if match found
1241 @DESCRIPTION: Attempts to match all the volume dimensions with the file
1242 dimensions. This is done in 3 passes. In the first pass,
1243 exact matches are found. In the second pass, volume dimensions
1244 of "any_spatial_dimension" are matched. On the final pass,
1245 volume dimension names which are empty strings are matched
1246 to any remaining file dimensions. If a dimension matches
1247 on "any_spatial_dimension" or empty string, then the name from
1248 the file is copied to the volume.
1249 @METHOD :
1250 @GLOBALS :
1251 @CALLS :
1252 @CREATED : 1993 David MacDonald
1253 @MODIFIED : Oct. 22, 1995 D. MacDonald - copies the name from the file
1254 to the volume
1255 ---------------------------------------------------------------------------- */
1256
match_dimension_names(int n_volume_dims,VIO_STR volume_dimension_names[],int n_file_dims,VIO_STR file_dimension_names[],int to_volume_index[])1257 static VIO_BOOL match_dimension_names(
1258 int n_volume_dims,
1259 VIO_STR volume_dimension_names[],
1260 int n_file_dims,
1261 VIO_STR file_dimension_names[],
1262 int to_volume_index[] )
1263 {
1264 int i, j, iteration, n_matches, dummy;
1265 int to_file_index[VIO_MAX_DIMENSIONS];
1266 VIO_BOOL match;
1267 VIO_BOOL volume_dim_found[VIO_MAX_DIMENSIONS];
1268
1269 n_matches = 0;
1270
1271 for_less( i, 0, n_file_dims )
1272 to_volume_index[i] = INVALID_AXIS;
1273
1274 for_less( i, 0, n_volume_dims )
1275 {
1276 volume_dim_found[i] = FALSE;
1277 to_file_index[i] = -1;
1278 }
1279
1280 for_less( iteration, 0, 3 )
1281 {
1282 for( i = n_volume_dims-1; i >= 0; --i )
1283 {
1284 if( !volume_dim_found[i] )
1285 {
1286 for( j = n_file_dims-1; j >= 0; --j )
1287 {
1288 if( to_volume_index[j] == INVALID_AXIS )
1289 {
1290 switch( iteration )
1291 {
1292 case 0:
1293 match = equal_strings( volume_dimension_names[i],
1294 file_dimension_names[j] );
1295 break;
1296 case 1:
1297 match = equal_strings( volume_dimension_names[i],
1298 ANY_SPATIAL_DIMENSION ) &&
1299 convert_dim_name_to_spatial_axis(
1300 file_dimension_names[j], &dummy );
1301 break;
1302 case 2:
1303 match = string_length(volume_dimension_names[i])
1304 == 0;
1305 break;
1306 }
1307
1308 if( match )
1309 {
1310 to_volume_index[j] = i;
1311 to_file_index[i] = j;
1312 volume_dim_found[i] = TRUE;
1313 ++n_matches;
1314 break;
1315 }
1316 }
1317 }
1318 }
1319 }
1320 }
1321
1322 if( n_matches == n_volume_dims )
1323 {
1324 for_less( i, 0, n_volume_dims )
1325 {
1326 if( equal_strings( volume_dimension_names[i],
1327 ANY_SPATIAL_DIMENSION ) ||
1328 string_length(volume_dimension_names[i]) == 0 )
1329 {
1330 replace_string( &volume_dimension_names[i],
1331 create_string( file_dimension_names[to_file_index[i]] ) );
1332 }
1333 }
1334 }
1335
1336 return( n_matches == n_volume_dims );
1337 }
1338
1339
1340 #endif /*HAVE_MINC1*/
1341
1342
1343 /* ----------------------------- MNI Header -----------------------------------
1344 @NAME : get_minc_file_id
1345 @INPUT : file
1346 @OUTPUT :
1347 @RETURNS : minc file id
1348 @DESCRIPTION: Returns the minc file id to allow user to perform MINC calls on
1349 this file.
1350 @METHOD :
1351 @GLOBALS :
1352 @CALLS :
1353 @CREATED : 1993 David MacDonald
1354 @MODIFIED :
1355 ---------------------------------------------------------------------------- */
1356
get_minc_file_id(Minc_file file)1357 VIOAPI int get_minc_file_id(
1358 Minc_file file )
1359 {
1360 return( file->cdfid );
1361 }
1362
1363 /* ----------------------------- MNI Header -----------------------------------
1364 @NAME : set_default_minc_input_options
1365 @INPUT :
1366 @OUTPUT : options
1367 @RETURNS :
1368 @DESCRIPTION: Sets the default minc input options.
1369 @METHOD :
1370 @GLOBALS :
1371 @CALLS :
1372 @CREATED : 1993 David MacDonald
1373 @MODIFIED :
1374 ---------------------------------------------------------------------------- */
1375
set_default_minc_input_options(minc_input_options * options)1376 VIOAPI void set_default_minc_input_options(
1377 minc_input_options *options )
1378 {
1379 static int default_rgba_indices[4] = { 0, 1, 2, 3 };
1380
1381 /*mostly for debugging*/
1382 options->prefer_minc2_api=miget_cfg_bool(MICFG_MINC_PREFER_V2_API);
1383
1384 set_minc_input_promote_invalid_to_zero_flag( options, TRUE );
1385 set_minc_input_vector_to_scalar_flag( options, TRUE );
1386 set_minc_input_vector_to_colour_flag( options, FALSE );
1387 set_minc_input_colour_dimension_size( options, 3 );
1388 set_minc_input_colour_max_dimension_size( options, 4 );
1389 set_minc_input_colour_indices( options, default_rgba_indices );
1390 set_minc_input_user_real_range(options, 0.0, 0.0);
1391 }
1392
1393 /* ----------------------------- MNI Header -----------------------------------
1394 @NAME : set_minc_input_promote_invalid_to_zero_flag
1395 @INPUT : flag
1396 @OUTPUT : options
1397 @RETURNS :
1398 @DESCRIPTION: Sets the invalid promotion flag of the input options.
1399 @METHOD :
1400 @GLOBALS :
1401 @CALLS :
1402 @CREATED : 1993 David MacDonald
1403 @MODIFIED : Oct. 25, 1996 D. MacDonald - changed to promote to 0,
1404 used to be min_valid
1405 ---------------------------------------------------------------------------- */
1406
set_minc_input_promote_invalid_to_zero_flag(minc_input_options * options,VIO_BOOL flag)1407 VIOAPI void set_minc_input_promote_invalid_to_zero_flag(
1408 minc_input_options *options,
1409 VIO_BOOL flag )
1410 {
1411 options->promote_invalid_to_zero_flag = flag;
1412 }
1413
1414 /* ----------------------------- MNI Header -----------------------------------
1415 @NAME : set_minc_input_promote_invalid_to_zero_flag
1416 @INPUT : flag
1417 @OUTPUT : options
1418 @RETURNS :
1419 @DESCRIPTION: Sets the invalid promotion flag of the input options. Maintained
1420 for functional interface backward compatibility. Programmers
1421 should now be calling set_minc_input_promote_invalid_to_zero_flag.
1422 @METHOD :
1423 @GLOBALS :
1424 @CALLS :
1425 @CREATED : 1993 David MacDonald
1426 @MODIFIED : Oct. 25, 1996 D. MacDonald - replaced with above function
1427 ---------------------------------------------------------------------------- */
1428
set_minc_input_promote_invalid_to_min_flag(minc_input_options * options,VIO_BOOL flag)1429 VIOAPI void set_minc_input_promote_invalid_to_min_flag(
1430 minc_input_options *options,
1431 VIO_BOOL flag )
1432 {
1433 set_minc_input_promote_invalid_to_zero_flag( options, flag );
1434 }
1435
1436 /* ----------------------------- MNI Header -----------------------------------
1437 @NAME : set_minc_input_vector_to_scalar_flag
1438 @INPUT : flag
1439 @OUTPUT : options
1440 @RETURNS :
1441 @DESCRIPTION: Sets the vector conversion flag of the input options.
1442 @METHOD :
1443 @GLOBALS :
1444 @CALLS :
1445 @CREATED : 1993 David MacDonald
1446 @MODIFIED :
1447 ---------------------------------------------------------------------------- */
1448
set_minc_input_vector_to_scalar_flag(minc_input_options * options,VIO_BOOL flag)1449 VIOAPI void set_minc_input_vector_to_scalar_flag(
1450 minc_input_options *options,
1451 VIO_BOOL flag )
1452 {
1453 options->convert_vector_to_scalar_flag = flag;
1454 }
1455
1456 /* ----------------------------- MNI Header -----------------------------------
1457 @NAME : set_minc_input_vector_to_colour_flag
1458 @INPUT : flag
1459 @OUTPUT : options
1460 @RETURNS :
1461 @DESCRIPTION: Sets the colour conversion flag of the input options. Any
1462 volume with a vector dimension of length 3 will be converted
1463 to a 32 bit colour.
1464 @METHOD :
1465 @GLOBALS :
1466 @CALLS :
1467 @CREATED : 1993 David MacDonald
1468 @MODIFIED :
1469 ---------------------------------------------------------------------------- */
1470
set_minc_input_vector_to_colour_flag(minc_input_options * options,VIO_BOOL flag)1471 VIOAPI void set_minc_input_vector_to_colour_flag(
1472 minc_input_options *options,
1473 VIO_BOOL flag )
1474 {
1475 options->convert_vector_to_colour_flag = flag;
1476 }
1477
1478 /* ----------------------------- MNI Header -----------------------------------
1479 @NAME : set_minc_input_colour_dimension_size
1480 @INPUT : size
1481 @OUTPUT : options
1482 @RETURNS :
1483 @DESCRIPTION: Sets the required number of vector components in a file that
1484 contains colour data.
1485 @METHOD :
1486 @GLOBALS :
1487 @CALLS :
1488 @CREATED : 1993 David MacDonald
1489 @MODIFIED :
1490 ---------------------------------------------------------------------------- */
1491
set_minc_input_colour_dimension_size(minc_input_options * options,int size)1492 VIOAPI void set_minc_input_colour_dimension_size(
1493 minc_input_options *options,
1494 int size )
1495 {
1496 if( size > 0 )
1497 options->dimension_size_for_colour_data = size;
1498 else
1499 {
1500 print_error( "Warning: set_minc_input_colour_dimension_size:\n" );
1501 print_error( " illegal size: %d\n", size );
1502 }
1503 }
1504
1505 /* ----------------------------- MNI Header -----------------------------------
1506 @NAME : set_minc_input_colour_max_dimension_size
1507 @INPUT : size
1508 @OUTPUT : options
1509 @RETURNS :
1510 @DESCRIPTION: Sets the maximum number of vector components in a file that
1511 contains colour data.
1512 @METHOD :
1513 @GLOBALS :
1514 @CALLS :
1515 @CREATED : 1993 David MacDonald
1516 @MODIFIED :
1517 ---------------------------------------------------------------------------- */
1518
set_minc_input_colour_max_dimension_size(minc_input_options * options,int size)1519 VIOAPI void set_minc_input_colour_max_dimension_size(
1520 minc_input_options *options,
1521 int size )
1522 {
1523 if( size > 0 )
1524 options->max_dimension_size_for_colour_data = size;
1525 else
1526 {
1527 print_error( "Warning: set_minc_input_colour_max_dimension_size:\n" );
1528 print_error( " illegal size: %d\n", size );
1529 }
1530 }
1531
1532 /* ----------------------------- MNI Header -----------------------------------
1533 @NAME : set_minc_input_colour_indices
1534 @INPUT : indices
1535 @OUTPUT : options
1536 @RETURNS :
1537 @DESCRIPTION: Sets the indices of the red, green, blue, and alpha in
1538 files that contain colours as the vector dimension.
1539 @METHOD :
1540 @GLOBALS :
1541 @CALLS :
1542 @CREATED : 1993 David MacDonald
1543 @MODIFIED :
1544 ---------------------------------------------------------------------------- */
1545
set_minc_input_colour_indices(minc_input_options * options,int indices[4])1546 VIOAPI void set_minc_input_colour_indices(
1547 minc_input_options *options,
1548 int indices[4] )
1549 {
1550 int i;
1551
1552 for_less( i, 0, 4 )
1553 options->rgba_indices[i] = indices[i];
1554 }
1555
1556 /* ----------------------------- MNI Header -----------------------------------
1557 @NAME : set_minc_input_user_real_range
1558 @INPUT : minimum, maximum - real range for scaling of input
1559 @OUTPUT : options
1560 @RETURNS :
1561 @DESCRIPTION: Sets the user-defined real range for scaling input when
1562 the Volume type is integer. The max must be greater than
1563 the min for this option to take effect. Setting this
1564 will force the Volume to have a particular real range,
1565 rather than using the full range of the input file.
1566 @METHOD :
1567 @GLOBALS :
1568 @CALLS :
1569 @CREATED : 2001 Peter Neelin
1570 @MODIFIED :
1571 ---------------------------------------------------------------------------- */
1572
set_minc_input_user_real_range(minc_input_options * options,double minimum,double maximum)1573 VIOAPI void set_minc_input_user_real_range(
1574 minc_input_options *options,
1575 double minimum,
1576 double maximum )
1577 {
1578 options->user_real_range[0] = minimum;
1579 options->user_real_range[1] = maximum;
1580 }
1581
1582