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