1 /* ----------------------------- MNI Header -----------------------------------
2 @NAME       : minctoraw
3 @INPUT      : argc, argv - command line arguments
4 @OUTPUT     : (none)
5 @RETURNS    : status
6 @DESCRIPTION: Program to dump minc file data
7 @METHOD     :
8 @GLOBALS    :
9 @CALLS      :
10 @CREATED    : February 11, 1993 (Peter Neelin)
11 @MODIFIED   :
12  * $Log: minctoraw.c,v $
13  * Revision 6.12  2008-01-17 02:33:06  rotor
14  *  * removed all rcsids
15  *  * removed a bunch of ^L's that somehow crept in
16  *  * removed old (and outdated) BUGS file
17  *
18  * Revision 6.11  2008/01/12 19:08:15  stever
19  * Add __attribute__ ((unused)) to all rcsid variables.
20  *
21  * Revision 6.10  2007/12/11 12:43:01  rotor
22  *  * added static to all global variables in main programs to avoid linking
23  *       problems with libraries (compress in mincconvert and libz for example)
24  *
25  * Revision 6.9  2006/05/19 00:35:58  bert
26  * Add config.h to several files that might need it
27  *
28  * Revision 6.8  2004/11/01 22:38:39  bert
29  * Eliminate all references to minc_def.h
30  *
31  * Revision 6.7  2003/10/28 20:32:09  bert
32  * Get rid of a few compiler warnings
33  *
34  * Revision 6.6  2001/08/16 16:41:36  neelin
35  * Added library functions to handle reading of datatype, sign and valid range,
36  * plus writing of valid range and setting of default ranges. These functions
37  * properly handle differences between valid_range type and image type. Such
38  * difference can cause valid data to appear as invalid when double to float
39  * conversion causes rounding in the wrong direction (out of range).
40  * Modified voxel_loop, volume_io and programs to use these functions.
41  *
42  * Revision 6.5  2001/08/16 16:18:47  neelin
43  * Fixed typo for compile
44  *
45  * Revision 6.4  2001/08/16 16:17:22  neelin
46  * Added hint about normalization in error message of previous change.
47  *
48  * Revision 6.3  2001/08/16 16:10:50  neelin
49  * Force user to specify either -normalize or -nonormalize.
50  *
51  * Revision 6.2  2001/04/17 18:40:25  neelin
52  * Modifications to work with NetCDF 3.x
53  * In particular, changed NC_LONG to NC_INT (and corresponding longs to ints).
54  * Changed NC_UNSPECIFIED to NC_NAT.
55  * A few fixes to the configure script.
56  *
57  * Revision 6.1  1999/10/19 14:45:30  neelin
58  * Fixed Log subsitutions for CVS
59  *
60  * Revision 6.0  1997/09/12 13:23:26  neelin
61  * Release of minc version 0.6
62  *
63  * Revision 5.0  1997/08/21  13:24:27  neelin
64  * Release of minc version 0.5
65  *
66  * Revision 4.0  1997/05/07  20:00:01  neelin
67  * Release of minc version 0.4
68  *
69  * Revision 3.0  1995/05/15  19:31:01  neelin
70  * Release of minc version 0.3
71  *
72  * Revision 2.2  1995/01/23  09:05:31  neelin
73  * changed ncclose to miclose
74  *
75  * Revision 2.1  95/01/23  09:03:19  neelin
76  * Changed ncopen to miopen.
77  *
78  * Revision 2.0  94/09/28  10:33:06  neelin
79  * Release of minc version 0.2
80  *
81  * Revision 1.8  94/09/28  10:33:03  neelin
82  * Pre-release
83  *
84  * Revision 1.7  93/08/11  15:23:15  neelin
85  * Added RCS logging in source.
86  *
87 @COPYRIGHT  :
88               Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre,
89               Montreal Neurological Institute, McGill University.
90               Permission to use, copy, modify, and distribute this
91               software and its documentation for any purpose and without
92               fee is hereby granted, provided that the above copyright
93               notice appear in all copies.  The author and McGill University
94               make no representations about the suitability of this
95               software for any purpose.  It is provided "as is" without
96               express or implied warranty.
97 ---------------------------------------------------------------------------- */
98 
99 #if HAVE_CONFIG_H
100 #include "config.h"
101 #endif
102 
103 #include <stdlib.h>
104 #include <stdio.h>
105 #include <string.h>
106 #include <minc.h>
107 #include <limits.h>
108 #include <float.h>
109 #include <ParseArgv.h>
110 
111 /* Constants */
112 #ifndef TRUE
113 #  define TRUE 1
114 #  define FALSE 0
115 #endif
116 #define BOOLEAN_DEFAULT -1
117 
118 /* Variables used for argument parsing */
119 static int output_datatype = INT_MAX;
120 static int output_signed = INT_MAX;
121 static double valid_range[2] = {DBL_MAX, DBL_MAX};
122 static int normalize_output = BOOLEAN_DEFAULT;
123 
124 /* Argument table */
125 static ArgvInfo argTable[] = {
126    {"-byte", ARGV_CONSTANT, (char *) NC_BYTE, (char *) &output_datatype,
127        "Write out data as bytes"},
128    {"-short", ARGV_CONSTANT, (char *) NC_SHORT, (char *) &output_datatype,
129        "Write out data as short integers"},
130    {"-int", ARGV_CONSTANT, (char *) NC_INT, (char *) &output_datatype,
131        "Write out data as 32-bit integers"},
132    {"-long", ARGV_CONSTANT, (char *) NC_INT, (char *) &output_datatype,
133        "Superseded by -int"},
134    {"-float", ARGV_CONSTANT, (char *) NC_FLOAT, (char *) &output_datatype,
135        "Write out data as single precision floating-point values"},
136    {"-double", ARGV_CONSTANT, (char *) NC_DOUBLE, (char *) &output_datatype,
137        "Write out data as double precision floating-point values"},
138    {"-signed", ARGV_CONSTANT, (char *) TRUE, (char *) &output_signed,
139        "Write out signed data"},
140    {"-unsigned", ARGV_CONSTANT, (char *) FALSE, (char *) &output_signed,
141        "Write out unsigned data"},
142    {"-range", ARGV_FLOAT, (char *) 2, (char *) valid_range,
143        "Specify the range of output values"},
144    {"-normalize", ARGV_CONSTANT, (char *) TRUE, (char *) &normalize_output,
145        "Normalize integer pixel values to file max and min"},
146    {"-nonormalize", ARGV_CONSTANT, (char *) FALSE, (char *) &normalize_output,
147        "Turn off pixel normalization"},
148    {NULL, ARGV_END, NULL, NULL, NULL}
149 };
150 
151 /* Main program */
152 
main(int argc,char * argv[])153 int main(int argc, char *argv[])
154 {
155    char *filename;
156    int mincid, imgid, icvid, ndims, dims[MAX_VAR_DIMS];
157    nc_type datatype;
158    int is_signed;
159    long start[MAX_VAR_DIMS], count[MAX_VAR_DIMS], end[MAX_VAR_DIMS];
160    long size;
161    int idim;
162    void *data;
163    double temp;
164 
165    /* Check arguments */
166    if (ParseArgv(&argc, argv, argTable, 0) || (argc != 2)) {
167       (void) fprintf(stderr, "\nUsage: %s [<options>] <mincfile>\n", argv[0]);
168       (void) fprintf(stderr,   "       %s -help\n\n", argv[0]);
169       exit(EXIT_FAILURE);
170    }
171    filename = argv[1];
172 
173    /* Check that a normalization option was specified */
174    if (normalize_output == BOOLEAN_DEFAULT) {
175       (void) fprintf(stderr,
176                      "Please specify either -normalize or -nonormalize\n");
177       (void) fprintf(stderr, "Usually -normalize is most appropriate\n");
178       exit(EXIT_FAILURE);
179    }
180 
181    /* Open the file */
182    mincid = miopen(filename, NC_NOWRITE);
183 
184    /* Inquire about the image variable */
185    imgid = ncvarid(mincid, MIimage);
186    (void) ncvarinq(mincid, imgid, NULL, NULL, &ndims, dims, NULL);
187    (void)miget_datatype(mincid, imgid, &datatype, &is_signed);
188 
189    /* Check if arguments set */
190 
191    /* Get output data type */
192    if (output_datatype == INT_MAX) output_datatype = datatype;
193 
194    /* Get output sign */
195    if (output_signed == INT_MAX) {
196       if (output_datatype == datatype)
197          output_signed = is_signed;
198       else
199          output_signed = (output_datatype != NC_BYTE);
200    }
201 
202    /* Get output range */
203    if (valid_range[0] == DBL_MAX) {
204       if ((output_datatype == datatype) && (output_signed == is_signed)) {
205          (void) miget_valid_range(mincid, imgid, valid_range);
206       }
207       else {
208          (void) miget_default_range(output_datatype, output_signed,
209                                     valid_range);
210       }
211    }
212    if (valid_range[0] > valid_range[1]) {
213       temp = valid_range[0];
214       valid_range[0] = valid_range[1];
215       valid_range[1] = temp;
216    }
217 
218    /* Set up image conversion */
219    icvid = miicv_create();
220    (void) miicv_setint(icvid, MI_ICV_TYPE, output_datatype);
221    (void) miicv_setstr(icvid, MI_ICV_SIGN, (output_signed ?
222                                             MI_SIGNED : MI_UNSIGNED));
223    (void) miicv_setdbl(icvid, MI_ICV_VALID_MIN, valid_range[0]);
224    (void) miicv_setdbl(icvid, MI_ICV_VALID_MAX, valid_range[1]);
225    if ((output_datatype == NC_FLOAT) || (output_datatype == NC_DOUBLE)) {
226       (void) miicv_setint(icvid, MI_ICV_DO_NORM, TRUE);
227       (void) miicv_setint(icvid, MI_ICV_USER_NORM, TRUE);
228    }
229    else if (normalize_output) {
230       (void) miicv_setint(icvid, MI_ICV_DO_NORM, TRUE);
231    }
232    (void) miicv_attach(icvid, mincid, imgid);
233 
234    /* Set input file start, count and end vectors for reading a slice
235       at a time */
236    for (idim=0; idim < ndims; idim++) {
237       (void) ncdiminq(mincid, dims[idim], NULL, &end[idim]);
238    }
239    (void) miset_coords(ndims, (long) 0, start);
240    (void) miset_coords(ndims, (long) 1, count);
241    size = nctypelen(output_datatype);
242    for (idim=ndims-2; idim < ndims; idim++) {
243       count[idim] = end[idim];
244       size *= count[idim];
245    }
246 
247    /* Allocate space */
248    data = malloc(size);
249 
250    /* Loop over input slices */
251 
252    while (start[0] < end[0]) {
253 
254       /* Read in the slice */
255       (void) miicv_get(icvid, start, count, data);
256 
257       /* Write out the slice */
258       if (fwrite(data, sizeof(char), (size_t) size, stdout) != size) {
259          (void) fprintf(stderr, "Error writing data.\n");
260          exit(EXIT_FAILURE);
261       }
262 
263       /* Increment start counter */
264       idim = ndims-1;
265       start[idim] += count[idim];
266       while ( (idim>0) && (start[idim] >= end[idim])) {
267          start[idim] = 0;
268          idim--;
269          start[idim] += count[idim];
270       }
271 
272    }       /* End loop over slices */
273 
274    /* Clean up */
275    (void) miclose(mincid);
276    (void) miicv_free(icvid);
277    free(data);
278 
279    exit(EXIT_SUCCESS);
280 }
281 
282