1%
2% Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre,
3% Montreal Neurological Institute, McGill University.
4% Permission to use, copy, modify, and distribute this
5% software and its documentation for any purpose and without
6% fee is hereby granted, provided that the above copyright
7% notice appear in all copies.  The author and McGill University
8% make no representations about the suitability of this
9% software for any purpose.  It is provided "as is" without
10% express or implied warranty.
11%
12\documentclass{article}
13\title{MINC Programmer's Guide}
14\author{Peter Neelin}
15\date{May 14, 1993}
16\textwidth 6.0in
17\oddsidemargin 0.125in
18\textheight 8.5in
19\topmargin -0.75in
20
21\begin{document}
22
23\maketitle
24
25\tableofcontents
26
27\clearpage
28
29\section{Introduction}
30
31The MINC file format (Medical Image NetCDF) is based on the NetCDF
32file format (Network Common Data Form) distributed by the Unidata
33Program Center. NetCDF provides a software interface for storing
34named, multi-dimensional variables in files in a machine-independent
35way. This interface removes applications from the concerns of
36portability and file structure and encourages a self-describing form
37of data.
38
39Each NetCDF multi-dimensional variable in a file is described by a
40name, by its dimensions and by attributes. For example, an image
41stored in a file might be stored as byte data in a variable called
42``\verb+image+'', with dimensions ``\verb+x+'' and ``\verb+y+'' (each
43of length 256) and with an attribute called ``\verb+long_name+'' which
44is a string describing the content of the image. Many variables can be
45stored in one file and each variable can have many attributes.
46Dimensions exist independently of variables and can subscript more
47than one variable.
48
49MINC provides three things on top of the NetCDF interface. It provides
50a standard for dimension, variable and attribute names suitable for
51medical imaging, it provides some convenience functions to complement
52the NetCDF interface (not specific to the MINC conventions) and it
53provides convenience functions for using MINC files.
54
55\section{An Introduction to NetCDF}
56
57(For a complete description, see the ``NetCDF User's Guide'').
58
59\subsection{The NetCDF file}
60
61It is useful to look at an example file while considering the NetCDF
62interface. Fortunately, the NetCDF package provides utilities (ncdump
63and ncgen) for converting the binary NetCDF files to an ascii format
64call CDL. A simple NetCDF file, converted to CDL notation by ncdump,
65is given below:
66
67\begin{verbatim}
68netcdf test {
69dimensions:
70	ycoord = 3 ;
71	xcoord = 4 ;
72
73variables:
74	double image(ycoord, xcoord) ;
75		image:long_name = "My favorite tiny image" ;
76	double xcoord(xcoord) ;
77
78data:
79
80 image =
81  1, 2, 3, 4,
82  5, 6, 7, 8,
83  9, 10, 11, 12 ;
84
85 xcoord = 100, 200, 300, 400 ;
86}
87\end{verbatim}
88
89The sample file stores a 3 by 4 image of double precision values. The
90first thing defined are the dimensions : \verb+xcoord+ and
91\verb+ycoord+. Dimensions can represent physical dimensions like x
92coordinate, y coordinate etc., or they can represent abstract things
93like lookup-table index.  Each dimension has a name and a length and
94when joined with other dimensions defines the shape of a variable ---
95the variable image is subscripted by \verb+ycoord+ and \verb+xcoord+.
96Dimensions can also be used across variables, relating them to each
97other. For example, if the file contained another image also
98subscripted by \verb+ycoord+ and \verb+xcoord+, we would have the
99important information that the two variables were sampled on the same
100grid.  Also, coordinate systems can be defined by creating variables
101by the same name as the dimension, like \verb+xcoord+ in the example
102above, giving the x coordinate of each point in the image.
103
104Variables are the next thing defined in the cdl file. Each variable
105has a name, data type and a shape specified by a list of dimensions
106(up to a maximum of \verb+MAX_VAR_DIMS+ = 32 dimensions per variable).
107The data types are \verb+NC_CHAR+, \verb+NC_BYTE+, \verb+NC_SHORT+,
108\verb+NC_INT+, \verb+NC_FLOAT+ and \verb+NC_DOUBLE+. Information
109about each variable is stored in attributes.  The attribute
110``\verb+long_name+'' gives a character string describing the variable
111``\verb+image+''. Attributes are either scalars or vectors of one of
112the six types listed above (a character string is a vector of type
113\verb+NC_CHAR+).
114
115\subsection{Programming with NetCDF}
116
117Programming with NetCDF can be quite simple. The file listed above was
118produced by the following program:
119
120\begin{verbatim}
121#include <netcdf.h>
122
123#define THE_NAME "My favorite tiny image"
124static double vals[][4]={
125   1.0, 2.0, 3.0, 4.0,
126   5.0, 6.0, 7.0, 8.0,
127   9.0,10.0,11.0,12.0
128};
129static int ysize=sizeof(vals)/sizeof(vals[0]);
130static int xsize=sizeof(vals[0])/sizeof(vals[0][0]);
131
132static double xcoord[]={100.,200.,300.,400.};
133
134main()
135{
136   int cdf, img, xvar;
137   int dim[MAX_VAR_DIMS];
138   long count[MAX_VAR_DIMS], start[MAX_VAR_DIMS];
139
140   /* Create the file */
141   cdf=nccreate("test.cdf",NC_CLOBBER);
142
143   /* Define the dimensions */
144   dim[0]=ncdimdef(cdf, "ycoord", ysize);
145   dim[1]=ncdimdef(cdf, "xcoord", xsize);
146
147   /* Define the variables */
148   img=ncvardef(cdf, "image", NC_DOUBLE, 2, dim);
149   xvar=ncvardef(cdf,"xcoord", NC_DOUBLE, 1, &dim[1]);
150
151   /* Add an attribute */
152   ncattput(cdf, img, "long_name", NC_CHAR, strlen(THE_NAME)+1, THE_NAME);
153
154   /* End definition mode */
155   ncendef(cdf);
156
157   /* Write the variable values */
158   start[0]=start[1]=0;
159   count[0]=ysize; count[1]=xsize;
160   ncvarput(cdf, img, start, count, vals);
161   ncvarput(cdf, xvar, &start[1], &count[1], xcoord);
162   ncclose(cdf);
163}
164\end{verbatim}
165
166The first executable line of the program creates a new NetCDF file. An
167open file is either in ``define'' mode or in ``data'' mode. In define
168mode, dimensions, variables and attributes can be defined, but data
169cannot be written to or read from variables. In data mode, variable
170values can be written or read, but no changes to dimensions or
171variables can be made and attributes can only be written if they exist
172already and will not get larger with the write. Newly created files
173are automatically in define mode.
174
175The lines following the call to nccreate define the dimensions and
176variables in the file. Notice that the NetCDF file, dimensions and
177variables are all identified by an integer returned when they are
178created. These id's are subsequently used to refer to each object. The
179attribute ``\verb+long_name+'' for the image variable is identified
180only by its name.
181
182Once everything is defined, ncendef puts the file into data mode and
183values are written. The values to write are defined by a vector of
184starting indices and a vector of the number of values to write in each
185dimension. This defines a multi-dimensional rectangle within the
186variable called a hyperslab. In the C interface, the first element of
187the vector refers to the slowest varying index of the variable, so in
188this example, the array vals has the \verb+xcoord+ varying fastest. In
189the FORTRAN interface, the convention has the first subscript varying
190fastest. These conventions follow the language conventions for
191multi-dimensional arrays.
192
193\section{The MINC format}
194
195It is possible to build MINC format files using only NetCDF function
196calls, however a C include file is provided to facilitate (and help
197ensure) adherence to the standard. This file defines useful constants,
198standard dimension, variable and attribute names and some attribute
199values. It also declares the functions defined in a library of minc
200convenience functions, designed to make an application programmer's
201life easier.
202
203\subsection{The MINC standard}
204
205Various requirements for file formats have been put forward. One such
206list is as follows: A protocol should be: 1) simple, 2) self
207describing, 3) maintainable, 4) extensible, 5) N dimensional, and 6)
208have a universal data structure. The NetCDF format meets all of these
209requirements, suggesting that it is a good place to start. I would,
210however, add some more requirements to the list. Implied in the above
211list is the requirement that there be a standard for accessing data
212(how do I get the patient name) --- this is not provided by NetCDF.
213Furthermore, a useful format should come with a software interface
214that makes it easy to use, particularly in a development environment.
215Finally, a format that stores many associated pieces of information
216should also provide some data organization.
217
218The MINC format attempts to add these things to the NetCDF format.
219
220\subsubsection{MINC variable types}
221
222Medical imaging tends to produce files with a large amount of
223ancillary data (patient information, image information, acquisition
224information, etc.). To organise this information in a useful fashion,
225MINC uses variables to group together related attributes. The variable
226itself may or may not contain useful data. For example, the variable
227\verb+MIimage+ contains the image data and has attributes relevant to this
228data. The variable \verb+MIpatient+ has no relevant variable data, but
229serves to group together all attributes describing the patient (name,
230birthdate, etc.). This sort of variable is called a group variable.
231
232Variables that correspond to dimensions are called dimension variables
233and describe the coordinate system corresponding to the dimension. An
234example is MIxspace --- both a dimension and a variable describing the
235x coordinate of other variables.
236
237The NetCDF conventions allow for these dimension variables to specify
238the coordinate at each point, but there is nothing to describe the
239width of the sample at that point. MINC provides the convention of
240dimension width variables, e.g. \verb+MIxspace_width+, to give this
241information.
242
243Finally, it is possible to have attributes that vary over some of the
244dimensions of the variable. For example, if we have a volume of image
245data, varying over \verb+MIxspace+, \verb+MIyspace+ and
246\verb+MIzspace+, we may want an attribute giving the maximum value of
247the each image, varying over \verb+MIzspace+. To achieve this we use a
248variable, called a variable attribute, pointed to by an attribute of
249the image variable.
250
251Thus MINC introduces a number of types of variables: group variables,
252dimension variables, dimension width variables and variable
253attributes.
254
255\subsubsection{Data organization}
256
257MINC attempts to provide some level of data organization through a
258hierarchy of group variables. As mentioned above, attributes are
259grouped according to type in group variables. Each group variable can
260have an \verb+MIparent+ and an \verb+MIchildren+ attribute --- the
261former specifying the name of another variable that is above this one
262in the hierarchy, the latter specifying a newline-separated list of
263variables that come below this one in the hierarchy. At the root of
264the hierarchy is the \verb+MIrootvariable+ variable, with no parent.
265Although it is not necessary to make use of this structure, it can
266provide a mechanism for ordering large amounts of information.
267
268\subsubsection{MINC dimension, variable and attribute names}
269
270The NetCDF format says nothing about variable and dimension naming
271conventions and little about attribute names. It does provide a few
272standards, such as the attribute ``\verb+long_name+'' for describing a
273variable, which have been adopted by the MINC standard. MINC defines a
274set of standard names for commonly used entities and the include file
275defines constants specifying these names. These are described at
276length in the MINC reference manual. The most interesting of these is
277\verb+MIimage+, the name of the variable used for storing the actual image
278data in the file.
279
280\subsubsection{Image dimensions}
281
282The MINC standard gives some special status to the concept of an
283image. There is nothing inherent in NetCDF that suggests any special
284status for particular dimensions, but it can be convenient to place
285limitations on what can vary over which dimensions in an imaging
286context. For example, the requirement that the variables that specify
287how to rescale images (see later section on pixel values) not vary
288with image dimensions means that we can treat the image as a simple
289unit. In the simplest case, the image dimensions are simply the two
290fastest varying dimensions of the \verb+MIimage+ variable.
291
292It can also be helpful to allow for vector fields --- images or image
293volumes that have a vector of values at each point. A simple example
294of a vector field is an RGB image. At each point in space, there are
295three values: red, green and blue. The dimension
296\verb+MIvector_dimension+ is used for the components of the vector and
297it should be the fastest varying dimension in the \verb+MIimage+ variable. If
298it is present, then the three fastest varying dimensions of \verb+MIimage+
299are the image dimensions.
300
301\subsubsection{MINC coordinate system}
302
303The MINC standard defines how spatial coordinates should be oriented
304relative to patients. Files are free to have data stored in the
305desired direction, but positive world coordinates are given a definite
306meaning in the medical imaging context. The standard is that the
307positive x axis points from the patient's left to right, the positive
308y axis points from posterior to anterior and the positive z axis
309points from inferior to superior.
310
311The conversion of element index to world coordinates is done using the
312dimension variable attributes \verb+MIdirection_cosines+,
313\verb+MIstep+ and \verb+MIstart+. If the direction cosines are
314${\bf c}=(c_x, c_y, c_z)$, then the vector between adjacent elements
315along an axis is $step\times {\bf c}$. If $start(i)$ and
316${\bf c}(i)$ are the \verb+MIstart+ and
317\verb+MIdirection_cosines+ attributes for dimension $i$ (one of
318\verb+MIxspace+, \verb+MIyspace+ and \verb+MIzspace+),
319then the first element of the image variable is at world coordinate
320$ \sum_i start(i) {\bf c}(i) $.
321
322If the direction cosines are not present, then they are
323assumed to be $(1,0,0)$ for \verb+MIxspace+, $(0,1,0)$ for
324\verb+MIyspace+ and $(0,0,1)$ for \verb+MIzspace+. Direction cosines are
325unit vectors and should be normalized. As well, the step attribute
326should carry the information about axis flipping (negative or
327positive) rather than the direction cosine.
328
329\subsubsection{Pixel values and real values}
330
331In medical imaging, pixel values are frequently stored as bytes or
332shorts, but there is a generally a real value associated with each
333pixel as well. This real value is obtained by a scale factor and
334offset associated with each image or image volume. The MINC standard
335indicates how pixel values should be interpreted.
336
337Image data in the \verb+MIimage+ variable can be stored as bytes, shorts,
338ints (32-bit), floats or doubles. NetCDF conventions use the attributes
339\verb+MIvalid_range+ or \verb+MIvalid_max+ and \verb+MIvalid_min+ to
340indicate the range of values that can be found in the variable. For
341short values, for example, we might have a valid range of 0 to 32000.
342To convert these integers to real values, we could use a scale and
343offset. However, these values would have to change if the data where
344converted to bytes in the range 23 to 228. If we specify an image
345maximum and minimum to which \verb+MIvalid_max+ and \verb+MIvalid_min+
346should be mapped by an appropriate scale and offset, then we can
347convert type and valid range without having to change the real maximum
348and minimum.  To allow the maximum dynamic range in an image, we use
349the variables \verb+MIimagemax+ and \verb+MIimagemin+ to store the
350real maximum and minimum --- these can vary over any of the non-image
351dimensions of \verb+MIimage+.
352
353\subsection{General convenience functions}
354
355MINC provides a number of convenience functions that have nothing to
356do with medical imaging, but that make the use of NetCDF files a
357little easier. One of the drawbacks of the NetCDF format is that data
358can come in any form (byte, short, int, float, double) and the
359calling program must handle the general case. Rather than restrict
360this, MINC provides functions to convert types.
361
362The first set of convenience functions are for type conversion. A list
363follows :
364\begin{itemize}
365   \item {\bf \verb+miattget+} - reads an attribute vector, specifying
366      the numeric type desired and the maximum number of values to read.
367   \item {\bf \verb+miattget1+} - reads one attribute value of the
368      specified type.
369   \item {\bf \verb+miattgetstr+} - read a character attribute of a specified
370      maximum length.
371   \item {\bf \verb+miattputdbl+} - write a double precision attribute.
372   \item {\bf \verb+miattputstr+} - write a string attribute.
373   \item {\bf \verb+mivarget+} - get a hyperslab of values of the
374      specified type.
375   \item {\bf \verb+mivarget1+} - get a single value of the specified type.
376   \item {\bf \verb+mivarput+} - put a hyperslab of values of the
377      specified type.
378   \item {\bf \verb+mivarput1+} - put a single value of the specified type.
379\end{itemize}
380
381Next we have some functions for handling coordinate vectors :
382\begin{itemize}
383   \item {\bf \verb+miset_coords+} - set a vector of coordinates to a
384      single value.
385   \item {\bf \verb+mitranslate_coords+} - translate the coordinates for one
386      variable to a vector for subscripting another variable.
387\end{itemize}
388
389Finally, there are functions for dealing with variables as groups of
390attributes, making it easier to modify a file while keeping ancillary
391information :
392\begin{itemize}
393   \item {\bf \verb+micopy_all_atts+} - copy all of the attributes of
394      one variable to another (possibly across files).
395   \item {\bf \verb+micopy_var_def+} - copy a variable definition (including
396      attributes) from one file to another.
397   \item {\bf \verb+micopy_var_vals+} - copy a variable's values from
398      one variable to another (possibly across files).
399   \item {\bf \verb+micopy_all_var_defs+} - copy all variable
400      definitions from one file to another, excluding a list of variables.
401   \item {\bf \verb+micopy_all_var_vals+} - copy all variable values
402      from one file to another, excluding a list of variables.
403\end{itemize}
404
405\subsection{MINC specific convenience functions}
406
407A few routines are provided to deal with some of the minc structures.
408\verb+miattput_pointer+ and \verb+miattget_pointer+ put/get a pointer to a
409variable attribute. \verb+miadd_child+ helps maintain the hierarchy of
410variables by handling the \verb+MIparent+ and \verb+MIchildren+
411attributes of two variables. Finally \verb+micreate_std_variable+ and
412\verb+micreate_group_variable+ create some of the standard variables
413and fill in a few of the default attributes.
414
415\subsection{Image conversion variables}
416
417One of the requirements for file formats mentioned earlier was
418a software interface to make the interface easy to use. The biggest
419difficulty in using a flexible format is that the application must
420handle many possibilities. Where images are concerned, this means
421various data types and scale factors, and images of differing sizes.
422The image conversion variable functions of MINC attempt to remove this
423complication for the programmer.
424
425An image conversion variable (icv) is essentially a specification of what
426the program wants images to look like, in type, scale and dimension.
427When an MINC image is read through an icv, it is converted for the
428calling program to a standard format regardless of how data is stored
429in the file.
430
431There are two categories of conversion: Type and range conversions
432change the datatype (and sign) of image values and optionally scale
433them for proper normalization. Dimension conversions allow programs to
434specify image dimension size and image axis orientation (should
435\verb+MIxspace+ coordinates be increasing or decreasing? should the
436patient's left side appear on the left or right of the image?).
437
438\subsubsection{ICV routines}
439
440Accessing a file through an icv is a straight-forward process.
441Create the icv with \verb+miicv_create+, set properties
442(like desired datatype) with the \verb+miicv_set+ routines, attach the
443icv to a NetCDF
444variable with \verb+miicv_attach+ and access the data with
445\verb+miicv_get+ or \verb+miicv_put+. The icv can be detached from a
446NetCDF variable with \verb+miicv_detach+ and can be freed with
447\verb+miicv_free+.
448
449Icv properties are strings, integers, long integers or doubles. For
450example, \verb+MI_ICV_SIGN+ (the sign of variable values) is a string,
451while \verb+MI_ICV_IMAGE_MAX+ (image maximum) is a double precision
452value.  Four functions --- \verb+miicv_setint+, \verb+miicv_setlong+,
453\verb+miicv_setdbl+ and \verb+miicv_setstr+ ---
454are provided to simplify the setting of property values. Programs can
455inquire about property values with \verb+miicv_inqint+,
456\verb+miicv_inqlong+, \verb+miicv_inqdbl+ and \verb+miicv_inqstr+.
457
458\subsubsection{Type and range conversion}
459
460Pixel values are converted for type and sign by specifying values for
461the properties \verb+MI_ICV_TYPE+ and \verb+MI_ICV_SIGN+ (they default
462to \verb+NC_SHORT+ and \verb+MI_SIGNED+). Values can also be converted
463for valid range and for normalization. These conversions are enabled
464by setting \verb+MI_ICV_DO_RANGE+ to \verb+TRUE+ (the default).
465
466If \verb+MI_ICV_DO_NORM+ is \verb+FALSE+ (the default) then only
467conversions for valid range are made. This means that if the input
468file has shorts in the range 0 to 4095, then they can be converted to
469bytes in the range 64 to 248 (for example). The real image maximum and
470minimum (\verb+MIimagemax+ and \verb+MIimagemin+) are ignored. The
471valid range is specified by the properties \verb+MI_ICV_VALID_MAX+ and
472\verb+MI_ICV_VALID_MIN+, which default to the legal range for the type
473and sign.
474
475We may want to scale values so that they are normalized either to all
476values in the \verb+MIimage+ variable or to some user-defined range.
477To do normalization, set \verb+MI_ICV_DO_NORM+ to \verb+TRUE+. Setting
478\verb+MI_ICV_USER_NORM+ to \verb+FALSE+ (the default) causes normalization to
479the real maximum and minimum of the variable (the maximum of
480\verb+MIimagemax+ and the minimum of \verb+MIimagemin+). If
481\verb+MI_ICV_USER_NORM+ is true then the values of \verb+MI_ICV_IMAGE_MAX+
482and \verb+MI_ICV_IMAGE_MIN+ are used (defaulting to 1.0 and 0.0).
483
484When either \verb+MI_ICV_TYPE+ or the file type is floating-point,
485then the conversion to and from real values is always done using the
486real image maximum and minimum information. If the internal type is
487integer and \verb+MI_ICV_DO_NORM+ is \verb+FALSE+, then the rescaling
488is done so that the slice maximum maps to the valid range of the
489internal values.
490
491Note that when converting to integer types, values are rounded to the
492nearest integer and limited to be within the legal range for the data
493type.
494
495The above transformations are simple enough, but the use of
496floating-point values adds to the complexity, since in general we do
497not want to rescale these values to get the real values. The various
498possibilities are described in greater detail below.
499
500\subsubsection{The details of pixel value conversion}
501
502The easiest way to think about the rescaling is through four ranges
503(maximum-minimum pairs). In the file variable, values have a
504valid range \verb+var_vrange+ and these correspond to real values
505\verb+var_imgrange+. The user/application wants to convert real values
506\verb+usr_imgrange+ to a useful valid range \verb+usr_vrange+. From
507\verb+var_vrange+, \verb+var_imgrange+, \verb+usr_imgrange+ and
508\verb+usr_vrange+, we can determine a scale and offset for converting
509pixel values: Input values are scaled to real values by
510\verb+var_vrange+ to \verb+var_imgrange+ and then scaled again to user
511values by \verb+usr_imgrange+ to \verb+usr_vrange+.
512
513If either of the \verb+vrange+ variables are not specified, they default to
514maximum possible range for integer types. For floating
515point types, \verb+usr_vrange+ is set equal to \verb+usr_imgrange+
516so that no conversion of real values is done.
517
518If normalization is not being done, then for integer types
519\verb+var_imgrange+ and \verb+usr_imgrange+ are set to [0,1] (scale
520down to [0,1] and scale up again).  When normalizibng,
521\verb+usr_imgrange+ is set to either the full range of the variable
522([0,1] if not found) or the user's requested range. If the variable
523values are floating point, then \verb+var_imgrange+ is set to
524\verb+var_vrange+ (no scaling to real values), otherwise
525\verb+var_imgrange+ is read for each image (again, [0,1] if not
526found).
527
528What this means for reading and writing images is discussed below.
529
530\subsubsection{Reading with pixel conversion}
531
532When reading into internal floating point values, normalization has no
533effect. When reading integers without normalization, each image is
534scaled to full range. With normalization they are scaled to the
535specified range and slices can be compared.
536
537When the input file is missing either
538\verb+MIimagemax+/\verb+MIimagemin+ (\verb+var_imgrange+ information)
539or \verb+MIvalid_range+, the routines try to provide sensible
540defaults, but funny things can still happen. The biggest problem is
541the absence of \verb+MIvalid_range+ if the defaults are not correct
542(full range for integer values and [0,1] for floating point). When
543converting floating point values to an integer type, there will be
544overflows if values are outside the range [0,1].
545
546\subsubsection{Writing with pixel conversion}
547
548The conversion routines can be used for writing values. This can be
549useful for data compression --- e.g. converting internal floats to
550byte values in the file, or converting internal shorts to bytes. When
551doing this with normalization (to rescale bytes to the slice maximum,
552for example) it is important to write the slice maximum and minimum in
553\verb+MIimagemax+ and \verb+MIimagemin+ before writing the slice.
554
555The other concern is that \verb+MIvalid_range+ or \verb+MIvalid_max+
556and \verb+MIvalid_min+ be written properly (especially if the defaults
557are not correct). When writing floating point values,
558\verb+MIvalid_range+ should be set to the full range of values in the
559variable. In this case, the attribute does not have to be set
560correctly before writing the variable, but if it exists, the values
561should be reasonable (maximum greater than minimum and values not
562likely to cause overflow). These will be set automatically if the
563routine \verb+micreate_std_variable+ is used with
564\verb+NC_FILL+ mode on (the default).
565
566\subsubsection{Example: Reading values}
567
568Read an image without normalization:
569\begin{verbatim}
570   /* Create the icv */
571   icv=miicv_create();
572   (void) miicv_setint(icv, MI_ICV_TYPE, NC_SHORT);
573   (void) miicv_setstr(icv, MI_ICV_SIGN, MI_UNSIGNED);
574   (void) miicv_setint(icv, MI_ICV_VALID_MAX, 32000);
575   (void) miicv_setint(icv, MI_ICV_VALID_MIN, 0);
576
577   /* Open the file, attach the image variable */
578   cdfid=ncopen(filename, NC_NOWRITE);
579
580   /* Attach image variable */
581   img=ncvarid(cdfid, MIimage);
582   (void) miicv_attach(icv, cdfid, img);
583
584   /* Get the data - we assume that coord and count are set properly */
585   (void) miicv_get(icv, coord, count, image);
586
587   /* Close the file and free the icv */
588   (void) ncclose(cdfid);
589   (void) miicv_free(icv);
590\end{verbatim}
591
592Read an integer image with normalization:
593\begin{verbatim}
594   /* Create the icv */
595   icv=miicv_create();
596   (void) miicv_setint(icv, MI_ICV_TYPE, NC_SHORT);
597   (void) miicv_setstr(icv, MI_ICV_SIGN, MI_UNSIGNED);
598   (void) miicv_setint(icv, MI_ICV_VALID_MAX, 32000);
599   (void) miicv_setint(icv, MI_ICV_VALID_MIN, 0);
600   (void) miicv_setint(icv, MI_ICV_DO_NORM, TRUE);
601   (void) miicv_setint(icv, MI_ICV_USER_NORM, TRUE);
602   (void) miicv_setdbl(icv, MI_ICV_IMAGE_MAX, 1.83);
603   (void) miicv_setdbl(icv, MI_ICV_IMAGE_MIN, -0.57);
604   ...
605\end{verbatim}
606
607Read a floating point image :
608\begin{verbatim}
609   /* Create the icv. We don't have to set MI_ICV_USER_NORM to TRUE,
610      but doing so ensures that the conversion is done properly
611      without looking at file values (the defaults for
612      MI_ICV_IMAGE_MAX and MI_ICV_IMAGE_MIN are 1 and 0) */
613   icv=miicv_create();
614   (void) miicv_setint(icv, MI_ICV_TYPE, NC_FLOAT);
615   (void) miicv_setint(icv, MI_ICV_DO_NORM, TRUE);
616   (void) miicv_setint(icv, MI_ICV_USER_NORM, TRUE);
617   ...
618\end{verbatim}
619
620\subsubsection{Example: Writing values}
621
622Writing from floating point to byte values :
623
624\begin{verbatim}
625   /* Create the icv */
626   icv=miicv_create();
627   (void) miicv_setint(icv, MI_ICV_TYPE, NC_FLOAT);
628   (void) miicv_setint(icv, MI_ICV_DO_NORM, TRUE);
629
630   /* Create the file */
631   cdf=nccreate(filename, NC_CLOBBER);
632
633   /* Define the dimensions */
634   dim[0]=ncdimdef(cdf, MIyspace, ysize);
635   dim[1]=ncdimdef(cdf, MIxspace, xsize);
636
637   /* Define the variables */
638   img=micreate_std_variable(cdf, MIimage, NC_BYTE, 2, dim);
639   (void) miattputstr(cdf, img, MIsigntype, MI_UNSIGNED);
640   vrange[0]=0; vrange[1]=200;
641   (void) ncattput(cdf, img, MIvalid_range, NC_DOUBLE, 2, vrange);
642   max=micreate_std_variable(cdf, MIimagemax, NC_DOUBLE, 0, NULL);
643   min=micreate_std_variable(cdf, MIimagemin, NC_DOUBLE, 0, NULL);
644
645   /* End definition mode */
646   ncendef(cdf);
647
648   /* Attach image variable */
649   (void) miicv_attach(icv, cdf, img);
650
651   /* Write the image max and min */
652   ncvarput1(cdf, max, NULL, &image_maximum);
653   ncvarput1(cdf, min, NULL, &image_minimum);
654
655   /* Write the image */
656   start[0]=start[1]=0;
657   count[0]=ysize; count[1]=xsize;
658   miicv_put(icv, start, count, vals);
659
660   /* Close the file and free the icv */
661   (void) ncclose(cdf);
662   (void) miicv_free(icv);
663\end{verbatim}
664
665If we were writing a floating point image, the only difference (apart
666from changing \verb+NC_BYTE+ to \verb+NC_FLOAT+) would be that we
667would rewrite \verb+MIvalid_range+ at the end of the file with the
668full range of floating point values.
669
670\subsubsection{Dimension conversion}
671
672One of the problems of arbitrary dimensioned images is that it becomes
673necessary for software to handle the general case. It is easier to write
674application software if it is known in advance that all images will
675have a specific size (e.g. $256\times 256$) and a specific orientation
676(e.g. the first pixel is at the patient's anterior, right side).
677
678By setting the icv property \verb+MI_ICV_DO_DIM_CONV+ to \verb+TRUE+
679these conversions can be done automatically. The orientation of
680spatial axes is determined by the properties \verb+MI_ICV_XDIM_DIR+,
681\verb+MI_ICV_YDIM_DIR+ and \verb+MI_ICV_ZDIM_DIR+. These affect any
682image dimensions that are \verb+MI?space+ or \verb+MI?frequency+ where
683\verb+?+ corresponds to \verb+x+, \verb+y+ or \verb+z+. These
684properties can have values \verb+MI_ICV_POSITIVE+,
685\verb+MI_ICV_NEGATIVE+ or \verb+MI_ICV_ANYDIR+. The last of these will
686prevent flipping of the dimension. The first two will flip the
687dimension if necessary so that the attribute \verb+MIstep+ of the
688dimension variable will have the correct sign.
689
690The two image dimensions are referred to as dimensions A and B.
691Dimension A is the fastest varying dimension of the two. Setting
692properties \verb+MI_ICV_ADIM_SIZE+ and \verb+MI_ICV_BDIM_SIZE+ specify
693the desired size for the image dimension. Dimensions are resized so
694that the file image will fit entirely in the calling program's image,
695and is centred in the image. The size \verb+MI_ICV_ANYSIZE+ allows
696one of the dimensions to have a variable size. If property
697\verb+MI_ICV_KEEP_ASPECT+ is set to \verb+TRUE+, then the two
698dimensions are rescaled by the same amount. It is possible to inquire
699about the new step and start, corresponding to attributes
700\verb+MIstep+ and \verb+MIstart+ (where pixel position = ipixel*step +
701start, with ipixel counting from zero). The properties
702\verb+MI_ICV_?DIM_STEP+ and \verb+MI_ICV_?DIM_START+ (\verb+?+ =
703\verb+A+ or \verb+B+) are set automatically and can be inquired but
704not set.
705
706Although vector images are allowed, many applications would rather
707only deal with scalar images (one intensity value at each point).
708Setting \verb+MI_ICV_DO_SCALAR+ to \verb+TRUE+ (the default) will
709cause vector images to be converted to scalar images by averaging the
710components.  (Thus, RGB images are automatically converted to
711gray-scale images in this simple way).
712
713It can sometimes be useful for a program to perform dimension
714conversions on three (or perhaps more) dimensions, not just the two
715standard image dimensions. To perform dimension flipping and/or
716resizing on dimensions beyond the usual two, the property
717\verb+MI_ICV_NUM_IMGDIMS+ can be set to an integer value between
718one and \verb+MI_MAX_IMGDIMS+. To set the size of a dimension,
719set the property \verb+MI_ICV_DIM_SIZE+ (analogous to
720\verb+MI_ICV_ADIM_SIZE+). To specify the dimension to be set, add
721the dimension to the property (adding zero corresponds to the fastest
722varying dimension --- add zero for the ``A'' dimension, one for the
723``B'' dimension, etc.). Voxel separation and
724location can be inquired about through the properties
725\verb+MI_ICV_DIM_STEP+ and \verb+MI_ICV_DIM_START+ (analogous to
726\verb+MI_ICV_ADIM_STEP+ and \verb+MI_ICV_ADIM_START+), again
727adding the dimension number to the property.
728
729\subsubsection{Example: Reading with dimension conversion}
730
731Reading a $256 \times 256$ image with the first pixel at the patient's
732inferior, posterior, left side as short values between 0 and 32000:
733\begin{verbatim}
734   /* Create the icv */
735   icv=miicv_create();
736   (void) miicv_setint(icv, MI_ICV_TYPE, NC_SHORT);
737   (void) miicv_setstr(icv, MI_ICV_SIGN, MI_UNSIGNED);
738   (void) miicv_setint(icv, MI_ICV_VALID_MAX, 32000);
739   (void) miicv_setint(icv, MI_ICV_VALID_MIN, 0);
740   (void) miicv_setint(icv, MI_ICV_DO_DIM_CONV, TRUE);
741   (void) miicv_setint(icv, MI_ICV_ADIM_SIZE, 256);
742   (void) miicv_setint(icv, MI_ICV_BDIM_SIZE, 256);
743   (void) miicv_setint(icv, MI_ICV_KEEP_ASPECT, TRUE);
744   (void) miicv_setint(icv, MI_ICV_XDIM_DIR, MI_POSITIVE);
745   (void) miicv_setint(icv, MI_ICV_YDIM_DIR, MI_POSITIVE);
746   (void) miicv_setint(icv, MI_ICV_ZDIM_DIR, MI_POSITIVE);
747
748   /* Open the file, attach the image variable */
749   cdfid=ncopen(filename, NC_NOWRITE);
750
751   /* Attach image variable */
752   img=ncvarid(cdfid, MIimage);
753   (void) miicv_attach(icv, cdfid, img);
754
755   /* Get the data - we assume that coord and count are set properly */
756   (void) miicv_get(icv, coord, count, image);
757
758   /* Close the file and free the icv */
759   (void) ncclose(cdfid);
760   (void) miicv_free(icv);
761\end{verbatim}
762
763
764\end{document}
765
766