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