1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <ctype.h>
4 #include <string.h>
5 #include "gifti_io.h"
6
7 /*! global history and version strings, for printing */
8 static char * gifti_history[] =
9 {
10 "----------------------------------------------------------------------\n"
11 "history (of gifti library changes):\n"
12 "\n",
13 "0.0 18 July, 2007\n"
14 " (Rick Reynolds of the National Institutes of Health, SSCC/DIRP/NIMH)\n"
15 " - initial version\n"
16 "0.1 31 July, 2007\n",
17 " - changed dim0..dim5 to dims[]\n"
18 " - changed nvals to size_t\n"
19 " - added gifti_init_darray_from_attrs and some validation functions\n"
20 "0.2 29 October, 2007\n",
21 " - renamed gifti.[ch] to gifti_io.[ch]\n"
22 " - main data structures all start with gii (or gifti_)\n"
23 " - added user indenting\n"
24 "0.3 21 November, 2007\n",
25 " - added base64 encoding/decoding, via b64_en/decode_table\n"
26 " - added gifti_list_index2string, gifti_disp_hex_data, \n"
27 " gifti_check_swap, gifti_swap_Nbytes, etc.\n"
28 " - pop_darray: check for b64 errors and byte swapping\n"
29 " - dind is size_t\n",
30 "0.4 29 November, 2007\n"
31 " - added more checks and fixed nvpair value allocation\n"
32 "0.5 03 December, 2007: applied changes for GIFTI Format 1.0 (11/21)\n",
33 " - replaced Category with Intent\n"
34 " - replaced Location attribute with ExternalFileName/Offset\n"
35 " - added NumberOfDataArrays attribute to GIFTI element\n"
36 " - applied new index_order strings\n"
37 "0.6 10 December, 2007:\n",
38 " - can read/write Base64Binary datasets (can set compress level)\n"
39 " - removed datatype lists (have gifti_type_list)\n"
40 " - added gifti_read_da_list(), with only partial ability\n"
41 " - added GIFTI numDA attribute\n"
42 " - change size_t to long long\n"
43 "0.7 11 December, 2007:\n",
44 " - added GIFTI_B64_CHECK defines\n"
45 " - set b64_check default to SKIPNCOUNT\n"
46 " - added disp_gxml_data\n"
47 "0.8 12 December, 2007:\n",
48 " - added sub-surface selection, via dalist in gifti_read_da_list()\n"
49 " - added gifti_copy_DataArray, and other structures\n"
50 "0.9 28 December, 2007:\n",
51 " - made zlib optional, via -DHAVE_ZLIB in compile\n"
52 " (without zlib, the user will get warnings)\n"
53 " - now users only #include gifti_io.h, not gifti_xml, expat or zlib\n"
54 " - added more comments and made tables more readable\n"
55 " - added all user-variable access functions and reset_user_vars()\n",
56 " - added gifti_free_image_contents(), gifti_disp_raw_data(),\n"
57 " gifti_clear_float_zeros() and gifti_set_DA_atrs()\n"
58 " - changed gifti_gim_DA_size to long long\n"
59 " - added GIFTI_B64_CHECK_UNDEF as 0\n"
60 " - fixed 0-width indenting and accumulating base64 errors\n"
61 "0.10 03 January, 2008:\n",
62 " - added top-level gifti_create_image() interface\n"
63 " - must now link libniftiio\n"
64 " - gifti_add_empty_darray() now takes num_to_add\n"
65 " - if data was expected but not read, free it\n"
66 " (can add via gifti_alloc_DA_data())\n"
67 " - many minor changes\n"
68 "0.11 11 January, 2008:\n",
69 " - attribute/data setting functions are more flexible\n"
70 " - added gifti_disp_dtd_url, gifti_set_DA_meta, gifti_valid_int_list,\n"
71 " DA_data_exists, gifti_add_to_meta \n"
72 "0.12 16 January, 2008:\n",
73 " - added gifti_copy_gifti_image() and gifti_convert_to_float()\n"
74 " - added gifti_valid_LabelTable(), gifticlib_version(),\n"
75 " gifti_copy_LabelTable(), gifti_updaet_nbyper() and\n"
76 " gifti_valid_gifti_image()\n"
77 " - added control over library updates to metadata\n"
78 " - expanded checks in gifti_valid_dims\n"
79 "0.13 20 February, 2008:\n",
80 " - added gifti_get_meta_value() and gifti_image_has_data()\n"
81 "0.14 25 February, 2008:\n",
82 " - consider data-less metadata as valid\n"
83 "0.15 18 March, 2008: added comparison functions\n",
84 " - gifti_compare_gifti_images() is top-level function\n"
85 " - also added gifti_compare_gims_only(), gifti_compare_DA_pair(),\n"
86 " gifti_compare_nvpairs(), gifti_compare_labeltable(),\n"
87 " gifti_compare_coordsys()\n"
88 " gifti_strdiff() and gifti_compare_raw_data()\n"
89 "0.16 25 March, 2008\n",
90 " - separate data diffs in compare_gifti_images\n"
91 " - added gifti_compare_gifti_data() and gifti_compare_DA_data()\n"
92 " - NIFTI_INTENT_NONE is considered valid\n"
93 " - write LabelTables using CDATA\n"
94 "0.17 28 March, 2008 : added copy MetaData routines\n",
95 " - gifti_copy_gifti_meta, gifti_copy_DA_meta, gifti_copy_all_DA_meta,\n"
96 " - gifti_copy_DA_meta_many, gifti_copy_nvpairs\n"
97 "0.18 08 May, 2008 : DataArray can now contain a list of CoordSystems\n",
98 " - modified giiDataArray struct: new numCS, coordsys is now CS**\n"
99 " - added gifti_free_CS_list, gifti_add_empty_CS\n"
100 "\n"
101 "------------------------ initial release version -----------------------\n",
102 "1.00 13 May, 2008 : release version of gifticlib\n",
103 " - allowed external data\n"
104 " - added gifti_read/write_extern_DA_data() and\n"
105 " gifti_set_extern_filelist()\n"
106 "1.01 02 June, 2008 :\n",
107 " - added CMakeLists.txt and XMLCALL update from Simon Warfield\n"
108 " (define XMLCALL for pre-1.95.7 versions of expat)\n"
109 " - added LICENSE.gifti\n"
110 "1.02 02 October, 2008 :\n",
111 " - separate diffs in DAs from those in gifti_image\n"
112 " - decode additional data types: INT8, UINT16, INT64\n"
113 " - add link flags to libgiftiio_la target\n"
114 "1.03 17 April, 2009 : allow DA size to vary over each external file\n",
115 "1.04 27 October, 2009 : added support for LabelTable RGBA attributes\n"
116 " - valid LabelTable requires RGBA values in [0,1.0]\n"
117 " - compare_labeltable requires equality of RGBA values (no approx.)\n",
118 "1.05 08 December, 2009: ignore invalid GIFTI attrs by default\n"
119 "1.06 24 December, 2009: added approximate difference functions\n",
120 " - added gifti_approx_gifti_images, DA_pair, labeltables, diff_offset\n"
121 " - added gifti_triangle_diff_offset\n"
122 " - gifti_compare_coordsys takes comp_data param\n"
123 "1.07 04 March, 2010: minor changes (also see NITRC IDs 4619 and 4644)\n",
124 " - for integers, make default approx test to be equality\n"
125 " - small changes to zlib failure strings\n"
126 " - cast to avoid compile warning on some systems\n"
127 " - gifti_xml.h: made NITRC gifti.dtd link that will not change\n"
128 "1.08 08 March, 2010: GIfTI LabelTable format change: Index to Key\n",
129 " - both Index and Key work on read, Key is written out\n"
130 "1.09 28 June, 2010: verify that num_dim is not too big\n",
131 " - the most significant dimension cannot be 1 (req by N Schmansky)\n"
132 "1.10 19 October, 2011: \n",
133 " - can read/write ascii COMPLEX64, COMPLEX128, RGB24\n"
134 " (requested by H Breman, J Mulders, N Schmansky)\n"
135 "1.11 07 March, 2012: fixed sizeof in memset of gim (noted by B Cox)\n",
136 "1.12 15 June, 2012: make num_dim violation a warning (mris_convert)\n",
137 "1.13 17 June, 2015: added gifti_read_image_buf\n"
138 "1.14 24 July, 2015: added gifti_rotate_DAs_to_front\n"
139 "1.15 01 March, 2016:\n"
140 " - gifti_xml.c fix for Windows-style newline characters\n",
141 " - noticed and fixed by R Vincent\n"
142 "1.16 02 May, 2017: added control over array indexing order\n"
143 "1.17 19 Feb, 2021: promote fabs() args explicitly to avoid warnings\n"
144 };
145
146 static char gifti_version[] = "gifti library version 1.17, 19 Feb, 2021";
147
148 /* ---------------------------------------------------------------------- */
149 /*! global lists of XML strings */
150
151 /*! this should match GIFTI_IND_ORD_* */
152 char * gifti_index_order_list[] = {"Undefined", "RowMajorOrder",
153 "ColumnMajorOrder"};
154
155 /*! gifti_type_list is an array of gifti_type_ele structs which list, for
156 each type, the bytes per value, swapsize and corresponding name string
157 (these type values are defined in nifti1.h) */
158 static gifti_type_ele gifti_type_list[] = {
159 /* type nbyper swapsize name */
160 { DT_UNKNOWN, 0, 0, "Undefined" },
161 { NIFTI_TYPE_UINT8, 1, 0, "NIFTI_TYPE_UINT8" },
162 { NIFTI_TYPE_INT16, 2, 2, "NIFTI_TYPE_INT16" },
163 { NIFTI_TYPE_INT32, 4, 4, "NIFTI_TYPE_INT32" },
164 { NIFTI_TYPE_FLOAT32, 4, 4, "NIFTI_TYPE_FLOAT32" },
165 { NIFTI_TYPE_COMPLEX64, 8, 4, "NIFTI_TYPE_COMPLEX64" },
166 { NIFTI_TYPE_FLOAT64, 8, 8, "NIFTI_TYPE_FLOAT64" },
167 { NIFTI_TYPE_RGB24, 3, 0, "NIFTI_TYPE_RGB24" },
168 { NIFTI_TYPE_INT8, 1, 0, "NIFTI_TYPE_INT8" },
169 { NIFTI_TYPE_UINT16, 2, 2, "NIFTI_TYPE_UINT16" },
170 { NIFTI_TYPE_UINT32, 4, 4, "NIFTI_TYPE_UINT32" },
171 { NIFTI_TYPE_INT64, 8, 8, "NIFTI_TYPE_INT64" },
172 { NIFTI_TYPE_UINT64, 8, 8, "NIFTI_TYPE_UINT64" },
173 { NIFTI_TYPE_FLOAT128, 6, 16, "NIFTI_TYPE_FLOAT128" },
174 { NIFTI_TYPE_COMPLEX128, 16, 8, "NIFTI_TYPE_COMPLEX128" },
175 { NIFTI_TYPE_COMPLEX256, 32, 16, "NIFTI_TYPE_COMPLEX256" }
176 };
177
178 /*! this list provides a link between intent codes and their name strings */
179 typedef struct { int code; char * name; } gifti_intent_ele;
180 static gifti_intent_ele gifti_intent_list[] = {
181 { NIFTI_INTENT_NONE, "NIFTI_INTENT_NONE" },
182 { NIFTI_INTENT_CORREL, "NIFTI_INTENT_CORREL" },
183 { NIFTI_INTENT_TTEST, "NIFTI_INTENT_TTEST" },
184 { NIFTI_INTENT_FTEST, "NIFTI_INTENT_FTEST" },
185 { NIFTI_INTENT_ZSCORE, "NIFTI_INTENT_ZSCORE" },
186 { NIFTI_INTENT_CHISQ, "NIFTI_INTENT_CHISQ" },
187 { NIFTI_INTENT_BETA, "NIFTI_INTENT_BETA" },
188 { NIFTI_INTENT_BINOM, "NIFTI_INTENT_BINOM" },
189 { NIFTI_INTENT_GAMMA, "NIFTI_INTENT_GAMMA" },
190 { NIFTI_INTENT_POISSON, "NIFTI_INTENT_POISSON" },
191 { NIFTI_INTENT_NORMAL, "NIFTI_INTENT_NORMAL" },
192 { NIFTI_INTENT_FTEST_NONC, "NIFTI_INTENT_FTEST_NONC" },
193 { NIFTI_INTENT_CHISQ_NONC, "NIFTI_INTENT_CHISQ_NONC" },
194 { NIFTI_INTENT_LOGISTIC, "NIFTI_INTENT_LOGISTIC" },
195 { NIFTI_INTENT_LAPLACE, "NIFTI_INTENT_LAPLACE" },
196 { NIFTI_INTENT_UNIFORM, "NIFTI_INTENT_UNIFORM" },
197 { NIFTI_INTENT_TTEST_NONC, "NIFTI_INTENT_TTEST_NONC" },
198 { NIFTI_INTENT_WEIBULL, "NIFTI_INTENT_WEIBULL" },
199 { NIFTI_INTENT_CHI, "NIFTI_INTENT_CHI" },
200 { NIFTI_INTENT_INVGAUSS, "NIFTI_INTENT_INVGAUSS" },
201 { NIFTI_INTENT_EXTVAL, "NIFTI_INTENT_EXTVAL" },
202 { NIFTI_INTENT_PVAL, "NIFTI_INTENT_PVAL" },
203 { NIFTI_INTENT_LOGPVAL, "NIFTI_INTENT_LOGPVAL" },
204 { NIFTI_INTENT_LOG10PVAL, "NIFTI_INTENT_LOG10PVAL" },
205 { NIFTI_INTENT_ESTIMATE, "NIFTI_INTENT_ESTIMATE" },
206 { NIFTI_INTENT_LABEL, "NIFTI_INTENT_LABEL" },
207 { NIFTI_INTENT_NEURONAME, "NIFTI_INTENT_NEURONAME" },
208 { NIFTI_INTENT_GENMATRIX, "NIFTI_INTENT_GENMATRIX" },
209 { NIFTI_INTENT_SYMMATRIX, "NIFTI_INTENT_SYMMATRIX" },
210 { NIFTI_INTENT_DISPVECT, "NIFTI_INTENT_DISPVECT" },
211 { NIFTI_INTENT_VECTOR, "NIFTI_INTENT_VECTOR" },
212 { NIFTI_INTENT_POINTSET, "NIFTI_INTENT_POINTSET" },
213 { NIFTI_INTENT_TRIANGLE, "NIFTI_INTENT_TRIANGLE" },
214 { NIFTI_INTENT_QUATERNION, "NIFTI_INTENT_QUATERNION" },
215 { NIFTI_INTENT_DIMLESS, "NIFTI_INTENT_DIMLESS" },
216 { NIFTI_INTENT_TIME_SERIES, "NIFTI_INTENT_TIME_SERIES" },
217 { NIFTI_INTENT_NODE_INDEX, "NIFTI_INTENT_NODE_INDEX" },
218 { NIFTI_INTENT_RGB_VECTOR, "NIFTI_INTENT_RGB_VECTOR" },
219 { NIFTI_INTENT_RGBA_VECTOR, "NIFTI_INTENT_RGBA_VECTOR" },
220 { NIFTI_INTENT_SHAPE, "NIFTI_INTENT_SHAPE" }
221 };
222
223 /*! this should match GIFTI_ENCODING_* */
224 char * gifti_encoding_list[] = {
225 "Undefined", "ASCII", "Base64Binary", "GZipBase64Binary",
226 "ExternalFileBinary"
227 };
228
229 /*! this should match GIFTI_ENDIAN_* */
230 char * gifti_endian_list[] = {"Undefined", "BigEndian", "LittleEndian"};
231
232 /* ---------------------------------------------------------------------- */
233 /* local prototypes */
234 static int can_compare_DA_data(const giiDataArray *d1,const giiDataArray *d2,
235 int verb);
236 static int compare_labeltables(const giiLabelTable *t1, const giiLabelTable *t2,
237 int verb, int approx);
238 static int copy_data_as_float(void * dest, int dtype, void * src, int stype,
239 long long nvals);
240 static int DA_data_exists(gifti_image * gim, const int * dalist, int len);
241 static int str2list_index(char *list[], int max, const char *str);
242 static int permute_by_index_order(void * dest, int new_ord, giiDataArray * da);
243
244 /* ---------------------------------------------------------------------- */
245 /*! giftilib globals */
246 static gifti_globals G = { 1 };
247
248 /* ====================================================================== */
249
250 /* ---------------------------------------------------------------------- */
251 /*! user variable accessor functions - basically use gxml interface */
252
gifti_get_verb(void)253 int gifti_get_verb( void ) { return G.verb; }
gifti_set_verb(int level)254 int gifti_set_verb( int level ) { G.verb = level; return 1; }
gifti_get_indent(void)255 int gifti_get_indent( void ) { return gxml_get_indent(); }
gifti_set_indent(int level)256 int gifti_set_indent( int level ) { return gxml_set_indent(level); }
gifti_get_b64_check(void)257 int gifti_get_b64_check( void ) { return gxml_get_b64_check(); }
gifti_set_b64_check(int level)258 int gifti_set_b64_check( int level ){ return gxml_set_b64_check(level); }
gifti_get_update_ok(void)259 int gifti_get_update_ok( void ) { return gxml_get_update_ok(); }
gifti_set_update_ok(int level)260 int gifti_set_update_ok( int level ){ return gxml_set_update_ok(level); }
gifti_get_zlevel(void)261 int gifti_get_zlevel( void ) { return gxml_get_zlevel(); }
gifti_set_zlevel(int level)262 int gifti_set_zlevel( int level )
263 {
264 /* note that the default currently results in 6 */
265 if( level != GZ_DEFAULT_COMPRESSION && (level < 0 || level > 9 ) ) {
266 fprintf(stderr,"** invalid zlevel, must be %d (default) or {0..9}\n",
267 GZ_DEFAULT_COMPRESSION);
268 return 1;
269 }
270 return gxml_set_zlevel(level);
271 }
272
gifti_get_perm_by_iord(void)273 int gifti_get_perm_by_iord(void ) { return gxml_get_perm_by_iord(); }
gifti_set_perm_by_iord(int level)274 int gifti_set_perm_by_iord(int level ) { return gxml_set_perm_by_iord(level); }
gifti_get_xml_buf_size(void)275 int gifti_get_xml_buf_size(void) { return gxml_get_buf_size(); }
gifti_set_xml_buf_size(int buf_size)276 int gifti_set_xml_buf_size(int buf_size){ return gxml_set_buf_size(buf_size); }
277
278 /*! reset user variables to their defaults(via set to -1) */
gifti_reset_user_vars(void)279 int gifti_reset_user_vars(void)
280 {
281 gxml_set_verb(-1);
282 gxml_set_dstore(-1);
283 gxml_set_indent(-1);
284 gxml_set_buf_size(-1);
285 gxml_set_b64_check(-1);
286 gxml_set_update_ok(-1);
287 gxml_set_zlevel(-1);
288
289 return 0;
290 }
291 /* end user variable accessor functions */
292 /* ---------------------------------------------------------------------- */
293
294 /* ====================================================================== */
295
296 /* ---------------------------------------------------------------------- */
297 /* begin general library functions */
298
299 /*----------------------------------------------------------------------
300 *! apply the attr=value GIFTI attribute to the gifti_image
301 *
302 * return 0 on success
303 *//*-------------------------------------------------------------------*/
gifti_str2attr_gifti(gifti_image * gim,const char * attr,const char * val)304 int gifti_str2attr_gifti(gifti_image * gim, const char *attr, const char *val)
305 {
306 if( !gim || !attr || !val ) {
307 fprintf(stderr,"** GS2AG: bad params (%p,%p,%p)\n",
308 (void *)gim, (void *)attr, (void *)val);
309 return 1;
310 }
311
312 if( G.verb > 2 )
313 fprintf(stderr,"++ setting GIFTI attr '%s' from '%s'\n", attr, val);
314
315 if( !strcmp(attr, "Version") ) {
316 if( gim->version ) free( gim->version ); /* lose any old copy */
317 gim->version = gifti_strdup(val);
318 } else if( !strcmp(attr, "NumberOfDataArrays") ) {
319 gim->numDA = atol(val);
320 if( gim->numDA < 0 ) {
321 fprintf(stderr,"** invalid NumberOfDataArrays attribute: %s\n",val);
322 gim->numDA = 0;
323 return 1;
324 }
325 } else if( !strcmp(attr, "xmlns:xsi") ||
326 !strcmp(attr, "xsi:noNamespaceSchemaLocation") ) {
327 if( G.verb > 1 )
328 fprintf(stderr,"-- have GIFTI attr, '%s'='%s'\n",attr,val);
329 return 1;
330 } else {
331 if( G.verb > 1 )
332 fprintf(stderr,"** unknown GIFTI attrib, '%s'='%s'\n",attr,val);
333 return 1;
334 }
335
336 return 0;
337 }
338
339 /*----------------------------------------------------------------------
340 *! This is the main dataset reading routine. Read a GIFTI dataset
341 * and return the corresponding gifti_image structure.
342 *
343 * Reading data is optional, via the read_data flag.
344 * User variables should already be set (via accessor functions).
345 *
346 * return an allocated gifti_image struct on success,
347 * NULL on error
348 *//*-------------------------------------------------------------------*/
gifti_read_image(const char * fname,int read_data)349 gifti_image * gifti_read_image( const char * fname, int read_data )
350 {
351 if( !fname ) {
352 fprintf(stderr,"** gifti_read_image: missing filename\n");
353 return NULL;
354 }
355
356 gxml_set_verb(G.verb);
357
358 return gxml_read_image(fname, read_data, NULL, 0);
359 }
360
361 /*----------------------------------------------------------------------
362 *! Like gifti_read_image, but read from a buffer.
363 *
364 * return an allocated gifti_image struct on success,
365 * NULL on error
366 *//*-------------------------------------------------------------------*/
gifti_read_image_buf(const char * buf,long long bsize)367 gifti_image * gifti_read_image_buf(const char * buf, long long bsize)
368 {
369 if( !buf || bsize <= 0 ) {
370 fprintf(stderr,"** gifti_read_image: missing filename\n");
371 return NULL;
372 }
373
374 gxml_set_verb(G.verb);
375
376 return gxml_read_image_buf(buf, bsize, NULL, 0);
377 }
378
379 /*----------------------------------------------------------------------
380 *! Similar to gifti_read_data, this function also takes an integer list of
381 * DataArray indices to populate the gifti_image structure with.
382 *
383 * The indices are be zero-based, can have repeats and can be in any order.
384 * A simple example to read 3 DA elements (with 2 repeats) might be:
385 *
386 * gifti_image * gim;
387 * int ilist[5] = { 3, 0, 7, 7, 3 };
388 * gim = gifti_read_da_list("my_data.gii", 1, ilist, 5);
389 *
390 * return an allocated gifti_image struct on success,
391 * NULL on error
392 *//*-------------------------------------------------------------------*/
gifti_read_da_list(const char * fname,int read_data,const int * dalist,int len)393 gifti_image * gifti_read_da_list( const char * fname, int read_data,
394 const int * dalist, int len )
395 {
396 if( !fname ) {
397 fprintf(stderr,"** gifti_read_da_list: missing filename\n");
398 return NULL;
399 }
400
401 gxml_set_verb(G.verb);
402
403 return gxml_read_image(fname, read_data, dalist, len);
404 }
405
406 /*----------------------------------------------------------------------
407 *! This is the main dataset writing routine.
408 *
409 * User variables should be set before this point.
410 *
411 * return 0 on success
412 * 1 on error
413 *//*-------------------------------------------------------------------*/
gifti_write_image(gifti_image * gim,const char * fname,int write_data)414 int gifti_write_image(gifti_image *gim, const char *fname, int write_data)
415 {
416 int errs = 0;
417
418 if( !gim ) {
419 fprintf(stderr,"** gifti_write_image, missing gifti_image\n");
420 errs++;
421 } else if( !fname ) {
422 fprintf(stderr,"** gifti_write_image: missing filename\n");
423 errs++;
424 }
425
426 if( errs ) return 1;
427
428 gxml_set_verb(G.verb);
429
430 return gxml_write_image(gim, fname, write_data);
431 }
432
433
434 /*----------------------------------------------------------------------
435 *! free the gifti_image struct and all its contents
436 *
437 * passing NULL (to this and any child function) should be okay
438 *
439 * the pointer is garbage after this call
440 *//*-------------------------------------------------------------------*/
gifti_free_image(gifti_image * gim)441 int gifti_free_image( gifti_image * gim )
442 {
443 if( !gim ) {
444 if(G.verb > 2) fprintf(stderr,"** free gifti_image w/NULL pointer\n");
445 return 1;
446 }
447
448 if( G.verb > 2 ) fprintf(stderr,"-- freeing gifti_image\n");
449
450 if( gim->version ) { free(gim->version); gim->version = NULL; }
451
452 (void)gifti_free_nvpairs(&gim->meta);
453 (void)gifti_free_LabelTable(&gim->labeltable);
454 (void)gifti_free_DataArray_list(gim->darray, gim->numDA);
455 (void)gifti_free_nvpairs(&gim->ex_atrs);
456 free(gim);
457
458 return 0;
459 }
460
461 /*----------------------------------------------------------------------
462 *! free the contents of the gifti_image struct (but not the pointer)
463 *
464 * the pointer is garbage after this call
465 *//*-------------------------------------------------------------------*/
gifti_free_image_contents(gifti_image * gim)466 int gifti_free_image_contents( gifti_image * gim )
467 {
468 if( !gim ) {
469 if(G.verb > 2) fprintf(stderr,"** GFIC: free w/NULL gifti_image ptr\n");
470 return 1;
471 }
472
473 if( G.verb > 2 ) fprintf(stderr,"-- freeing gifti_image contents\n");
474
475 if( gim->version ) { free(gim->version); gim->version = NULL; }
476
477 (void)gifti_free_nvpairs(&gim->meta);
478 (void)gifti_free_LabelTable(&gim->labeltable);
479 (void)gifti_free_DataArray_list(gim->darray, gim->numDA);
480 (void)gifti_free_nvpairs(&gim->ex_atrs);
481
482 return 0;
483 }
484
485 /*----------------------------------------------------------------------
486 *! free the contents of the nvpairs struct (but not the pointer)
487 *
488 * passing NULL is okay
489 *//*-------------------------------------------------------------------*/
gifti_free_nvpairs(nvpairs * p)490 int gifti_free_nvpairs( nvpairs * p )
491 {
492 int c;
493
494 if( !p ) {
495 if( G.verb > 3 ) fprintf(stderr,"** free w/NULL nvpairs ptr\n");
496 return 1;
497 }
498
499 if( G.verb > 3 ) fprintf(stderr,"-- freeing %d nvpairs\n", p->length);
500
501 if( p->name && p->value ) {
502 for( c = 0; c < p->length; c++ ) {
503 if( p->name[c] ) free(p->name[c]);
504 if( p->value[c] ) free(p->value[c]);
505 }
506 free(p->name);
507 free(p->value);
508 p->name = NULL;
509 p->value = NULL;
510 }
511 p->length = 0;
512
513 return 0;
514 }
515
516 /*----------------------------------------------------------------------
517 *! free the contents of the LabelTable struct (but not the pointer)
518 *
519 * passing NULL is okay
520 *//*-------------------------------------------------------------------*/
gifti_free_LabelTable(giiLabelTable * T)521 int gifti_free_LabelTable( giiLabelTable * T )
522 {
523 int c;
524
525 if( !T ) {
526 if(G.verb > 3) fprintf(stderr,"** free w/NULL giiLabelTable ptr\n");
527 return 1;
528 }
529
530 if(G.verb > 3)
531 fprintf(stderr,"-- freeing %d giiLabelTable entries\n", T->length);
532
533 if( T->key && T->label ) {
534 for( c = 0; c < T->length; c++ )
535 if( T->label[c] ) free(T->label[c]);
536 free(T->key);
537 free(T->label);
538 T->key = NULL;
539 T->label = NULL;
540 }
541
542 if( T->rgba ) {
543 free(T->rgba);
544 T->rgba = NULL;
545 }
546
547 T->length = 0;
548
549 return 0;
550 }
551
552 /*----------------------------------------------------------------------
553 *! free the DataArray list (the array and all its contents)
554 *
555 * the darray list pointer is garbage after this call
556 *
557 * passing NULL is okay
558 *//*-------------------------------------------------------------------*/
gifti_free_DataArray_list(giiDataArray ** darray,int numDA)559 int gifti_free_DataArray_list(giiDataArray ** darray, int numDA)
560 {
561 int c;
562
563 if( !darray ) {
564 if( G.verb > 3 ) fprintf(stderr,"** GFDA: free NULL darray list\n");
565 return 1;
566 }
567
568 if( G.verb > 3 ) fprintf(stderr,"-- freeing %d giiDataArrays\n", numDA);
569
570 if( numDA < 0 ) return 1;
571
572 for( c = 0; c < numDA; c++ )
573 if( gifti_free_DataArray(darray[c]) ) return 1;
574
575 free(darray);
576
577 return 0;
578 }
579
580 /*----------------------------------------------------------------------
581 *! free the DataArray struct and all its contents
582 *
583 * the DataArray pointer is garbage after this call
584 *
585 * passing NULL is okay
586 *//*-------------------------------------------------------------------*/
gifti_free_DataArray(giiDataArray * darray)587 int gifti_free_DataArray( giiDataArray * darray )
588 {
589 if( !darray ) {
590 if( G.verb > 3 ) fprintf(stderr,"** tried to free NULL darray ptr\n");
591 return 1;
592 }
593
594 if( G.verb > 3 ) fprintf(stderr,"-- freeing giiDataArray\n");
595
596 if(darray->ext_fname) { free(darray->ext_fname); darray->ext_fname = NULL; }
597
598 (void)gifti_free_nvpairs(&darray->meta);
599 (void)gifti_free_CS_list(darray);
600 if( darray->data ) { free(darray->data); darray->data = NULL; }
601 (void)gifti_free_nvpairs(&darray->ex_atrs);
602 free(darray);
603
604 return 0;
605 }
606
607 /*----------------------------------------------------------------------
608 *! free the CoordSystem array from a DataArray
609 * passing NULL is okay
610 *//*-------------------------------------------------------------------*/
gifti_free_CS_list(giiDataArray * da)611 int gifti_free_CS_list( giiDataArray * da )
612 {
613 int c;
614
615 if( !da ) return 0;
616
617 if( G.verb > 3 ) fprintf(stderr,"-- freeing giiCoordSystem list\n");
618
619 if( da->coordsys && da->numCS > 0 ) {
620 for( c = 0; c < da->numCS; c++ )
621 gifti_free_CoordSystem(da->coordsys[c]);
622 free(da->coordsys);
623 }
624
625 da->coordsys = NULL;
626 da->numCS = 0;
627
628 return 0;
629 }
630
631 /*----------------------------------------------------------------------
632 *! free the CoordSystem struct and all its contents
633 *
634 * the CoordSystem pointer is garbage after this call
635 *
636 * passing NULL is okay
637 *//*-------------------------------------------------------------------*/
gifti_free_CoordSystem(giiCoordSystem * cs)638 int gifti_free_CoordSystem( giiCoordSystem * cs )
639 {
640 if( !cs ) return 0;
641
642 if( G.verb > 3 ) fprintf(stderr,"-- freeing giiCoordSystem\n");
643
644 if( cs->dataspace ) { free(cs->dataspace); cs->dataspace = NULL; }
645 if( cs->xformspace ) { free(cs->xformspace); cs->xformspace = NULL; }
646
647 free(cs);
648
649 return 0;
650 }
651
652 /*----------------------------------------------------------------------
653 *! initialize an existing DataArray structure given a list of name=value
654 * attribute pairs
655 *
656 * if alen > 0, consider it the length of the attr list
657 * else process until attr[i] == NULL
658 *
659 * if add_to_extras, add any bad attribute pairs to ex_atrs
660 * else whine about any bad ones and return
661 *//*-------------------------------------------------------------------*/
gifti_set_DA_atrs(giiDataArray * da,const char ** attr,int alen,int add_to_extras)662 int gifti_set_DA_atrs(giiDataArray * da, const char ** attr, int alen,
663 int add_to_extras )
664 {
665 int c, length = alen;
666
667 if( !da || !attr ) {
668 if(G.verb>1) fprintf(stderr,"** G_IDFA: bad params (%p,%p)\n",
669 (void *)da,(void *)attr);
670 return 1;
671 }
672
673 /* if length was not passed, compute it */
674 if( length <= 0 ) for( length = 0; attr[length]; length++ ) /* nada */ ;
675
676 if( G.verb > 5 )
677 fprintf(stderr,"++ init darray attrs, len %d, ex_atrs = %d\n",
678 length, add_to_extras);
679
680 /* insert attributes - if unknown, store with extras */
681 for(c = 0; c < length; c += 2 )
682 if( gifti_str2attr_darray(da, attr[c],attr[c+1]) ) {
683 /* a bad name=value pair, maybe add to ex_atrs */
684 if( add_to_extras ) {
685 if( gifti_add_to_nvpairs(&da->ex_atrs,attr[c],attr[c+1]) )
686 return 1;
687 }
688 else {
689 if( G.verb > 0 )
690 fprintf(stderr,"** set_darray_atrs, bad pair '%s'='%s'\n",
691 attr[c],attr[c+1]);
692 return 1;
693 }
694 }
695
696 /* and set computed values */
697
698 da->nvals = gifti_darray_nvals(da);
699 gifti_datatype_sizes(da->datatype, &da->nbyper, NULL); /* set nbyper */
700
701 return 0;
702 }
703
704 /*----------------------------------------------------------------------
705 *! determine whether the given DataArray struct seems valid
706 *
707 * if whine is set, print error messages for any failures
708 *
709 * return 1, if valid
710 * 0, if not
711 *//*-------------------------------------------------------------------*/
gifti_valid_DataArray(const giiDataArray * da,int whine)712 int gifti_valid_DataArray(const giiDataArray * da, int whine)
713 {
714 int errs = 0, nbyper;
715
716 if( !da ) {
717 if( whine || G.verb > 2 ) fprintf(stderr,"** invalid darray pointer\n");
718 return 0;
719 }
720
721 if( ! gifti_intent_is_valid(da->intent) ) {
722 if( whine || G.verb > 3 )
723 fprintf(stderr,"** invalid darray intent code = %d\n", da->intent);
724 errs++;
725 }
726
727 if( ! gifti_valid_datatype(da->datatype, whine) ) /* message printed */
728 errs++;
729
730 /* no checks for ext_fname and ext_offset (until reading) */
731
732 if( da->ind_ord<=GIFTI_IND_ORD_UNDEF || da->ind_ord>GIFTI_IND_ORD_MAX ) {
733 if( whine || G.verb > 3 )
734 fprintf(stderr,"** invalid darray ind_ord = %d\n", da->ind_ord);
735 errs++;
736 }
737
738 if( ! gifti_valid_num_dim(da->num_dim, whine) ) /* message printed */
739 errs++;
740
741 if( ! gifti_valid_dims(da, whine) ) /* message printed */
742 errs++;
743
744 if( da->encoding<=GIFTI_ENCODING_UNDEF || da->encoding>GIFTI_ENCODING_MAX ){
745 if( whine || G.verb > 3 )
746 fprintf(stderr,"** invalid darray encoding = %d\n", da->encoding);
747 errs++;
748 }
749
750 if( da->endian<=GIFTI_ENDIAN_UNDEF || da->endian>GIFTI_ENDIAN_MAX ) {
751 if( whine || G.verb > 3 )
752 fprintf(stderr,"** invalid darray endian = %d\n", da->endian);
753 errs++;
754 }
755
756 /* of sub-element, only verify giiMetaData */
757 if( ! gifti_valid_nvpairs(&da->meta, whine) ) /* message printed */
758 errs++;
759
760 if( da->nvals <= 0 ) {
761 if( whine || G.verb > 3 )
762 fprintf(stderr,"** invalid darray nvals = %u\n",
763 (unsigned)da->nvals );
764 errs++;
765 }
766
767 if( ! gifti_valid_nbyper(da->nbyper, whine) ) errs++;
768 if( ! gifti_valid_nvpairs(&da->ex_atrs, whine) ) errs++;
769
770 /* compare nbyper to what is expected for type */
771 errs += gifti_datatype_sizes(da->datatype, &nbyper, NULL);
772 if( gifti_valid_nbyper(nbyper, 0) && nbyper != da->nbyper ) {
773 if( whine || G.verb > 3 )
774 fprintf(stderr,"** nbyper %d, does not match type %s\n",
775 nbyper, gifti_datatype2str(da->datatype));
776 errs++;
777 }
778
779 if( errs ) return 0;
780
781 return 1;
782 }
783
784 /*----------------------------------------------------------------------
785 *! check whether pointers are valid and consistent with length
786 *//*-------------------------------------------------------------------*/
gifti_valid_nvpairs(const nvpairs * nvp,int whine)787 int gifti_valid_nvpairs(const nvpairs * nvp, int whine)
788 {
789 int c;
790
791 if( !nvp ) {
792 if( G.verb>3 || whine ) fprintf(stderr,"** invalid nvpairs pointer\n");
793 return 0;
794 }
795
796 if( nvp->length < 0 ) {
797 if( G.verb > 3 || whine )
798 fprintf(stderr,"** invalid nvpair length = %d\n", nvp->length);
799 return 0;
800 }
801
802 if( nvp->length == 0 ) return 1; /* quick case: valid */
803
804 if( !nvp->name || !nvp->value ){
805 if( G.verb > 3 || whine )
806 fprintf(stderr,"** invalid nvpair name, value lists = %p, %p\n",
807 (void *)nvp->name, (void *)nvp->value);
808 return 0;
809 }
810
811 /* quit on first error */
812 for( c = 0; c < nvp->length; c++ ) {
813 if( ! nvp->name[c] ) {
814 if( G.verb > 5 || whine )
815 fprintf(stderr,"** invalid nvpair, missing name @ %d\n", c);
816 return 0;
817 }
818
819 /* value string is not required 25 Feb 2008 */
820 if( ! nvp->value[c] && G.verb > 3 )
821 fprintf(stderr,"-- missing nvpair value[%d], name %s (is OK)\n",
822 c, nvp->name[c]);
823 }
824
825 return 1;
826 }
827
828 /*----------------------------------------------------------------------
829 *! check whether pointers are valid and consistent with length
830 *
831 * no check is done on the actual indices or labels
832 *//*-------------------------------------------------------------------*/
gifti_valid_LabelTable(const giiLabelTable * T,int whine)833 int gifti_valid_LabelTable(const giiLabelTable * T, int whine)
834 {
835 float * rgba;
836 int c, c2;
837
838 if( !T ) {
839 if(G.verb>2||whine) fprintf(stderr,"** invalid LabelTable pointer\n");
840 return 0;
841 }
842
843 if( T->length < 0 ) {
844 if( G.verb > 3 || whine )
845 fprintf(stderr,"** invalid LabelTable length = %d\n", T->length);
846 return 0;
847 }
848
849 if( T->length == 0 ) return 1; /* quick case: valid */
850
851 if( !T->key || !T->label ){
852 if( G.verb > 3 || whine )
853 fprintf(stderr,"** invalid nvpair key, label = %p, %p\n",
854 (void *)T->key, (void *)T->label);
855 return 0;
856 }
857
858 /* quit on first error */
859 rgba = T->rgba;
860 for( c = 0; c < T->length; c++ ) {
861 if( ! T->label[c] ) {
862 if( G.verb > 3 || whine )
863 fprintf(stderr,"** invalid nvpair label[%d]\n", c);
864 return 0;
865 }
866 if( rgba ) {
867 for( c2 = 0; c2 < 4; c2++ )
868 if( rgba[c2] < 0.0 || rgba[c2] > 1.0 ) {
869 if( G.verb > 3 || whine )
870 fprintf(stderr,"** RGBA values out of [0.0,1,0] at "
871 "Label[%d]\n", c);
872 return 0;
873 }
874 rgba += 4; /* if list exists, go to next set */
875 }
876 }
877
878 return 1;
879 }
880
881 /*----------------------------------------------------------------------
882 *! check the bounds on num_dim
883 *//*-------------------------------------------------------------------*/
gifti_valid_num_dim(int num_dim,int whine)884 int gifti_valid_num_dim(int num_dim, int whine)
885 {
886 if( num_dim <= 0 || num_dim > GIFTI_DARRAY_DIM_LEN ) {
887 if( G.verb > 3 || whine )
888 fprintf(stderr,"** invalid num_dim = %d\n", num_dim);
889 return 0;
890 }
891 return 1;
892 }
893
894 /*----------------------------------------------------------------------
895 *! check that the datatype is in the list
896 *//*-------------------------------------------------------------------*/
gifti_valid_datatype(int dtype,int whine)897 int gifti_valid_datatype(int dtype, int whine)
898 {
899 int c;
900
901 /* check for valid */
902 for( c = sizeof(gifti_type_list) / sizeof(gifti_type_ele) - 1; c > 0; c-- )
903 if( dtype == gifti_type_list[c].type ) return 1;
904
905 if( whine || G.verb > 3 )
906 fprintf(stderr,"** invalid datatype value %d\n", dtype);
907
908 return 0;
909 }
910
911 /*----------------------------------------------------------------------
912 *! check that nbyper is one of the values in gifti_type_list
913 *//*-------------------------------------------------------------------*/
gifti_valid_nbyper(int nbyper,int whine)914 int gifti_valid_nbyper(int nbyper, int whine)
915 {
916 int c;
917
918 /* check for valid */
919 for( c = sizeof(gifti_type_list) / sizeof(gifti_type_ele) - 1; c > 0; c-- )
920 if( nbyper == gifti_type_list[c].nbyper ) return 1;
921
922 if( whine || G.verb > 3 )
923 fprintf(stderr,"** invalid nbyper value %d\n", nbyper);
924
925 return 0;
926 }
927
928 /*----------------------------------------------------------------------
929 *! check that dimension values are consistent (and with datatype)
930 *
931 * - num_dim is in range
932 * - each dims[c] is postive (c < num_dim)
933 * - nvals is product of dims
934 * - datatype is valid (required to check nbyper)
935 * - nbyper is correct
936 *//*-------------------------------------------------------------------*/
gifti_valid_dims(const giiDataArray * da,int whine)937 int gifti_valid_dims(const giiDataArray * da, int whine)
938 {
939 long long vals = 1;
940 int c, nbyper;
941
942 if( !da ) {
943 if( G.verb > 2 || whine ) fprintf(stderr,"** GVD: no giiDataArray\n");
944 return 0;
945 }
946
947 if( ! gifti_valid_num_dim( da->num_dim, whine ) )
948 return 0;
949
950 for( c = 0; c < da->num_dim; c++ ) {
951 if( da->dims[c] <= 0 ) {
952 if( G.verb > 3 || whine )
953 fprintf(stderr,"** invalid dims[%d] = %d\n", c, da->dims[c]);
954 return 0;
955 }
956
957 vals *= da->dims[c];
958 }
959
960 /* verify computed vals and nbyper against stored ones */
961 if( vals != da->nvals ) {
962 if( G.verb > 3 ) {
963 fprintf(stderr,"** nvals = %lld does not match %lld for dims[%d]: ",
964 da->nvals, vals, da->num_dim);
965 gifti_disp_raw_data(da->dims, DT_INT32, da->num_dim, 1, stderr);
966 }
967 return 0;
968 }
969
970 gifti_datatype_sizes(da->datatype, &nbyper, NULL);
971 if( nbyper != da->nbyper ) {
972 fprintf(stderr,"** nbyper %d not correct for type %s\n",
973 da->nbyper, gifti_datatype2str(da->datatype));
974 return 0;
975 }
976
977 /* verify that num_dim is not too big, the most significant dimension
978 * is not allowed to be 1
979 * (requested by N Schmansky) 11 Mar 2010 */
980 if( da->num_dim > 1 && da->dims[da->num_dim-1] < 2 && whine ) {
981 fprintf(stderr,"** num_dim violation: num_dim = %d, yet dim[%d] = %d\n",
982 da->num_dim, da->num_dim-1, da->dims[da->num_dim-1]);
983 /* now FS is writing these in mris_convert, grrrr... 15 Jun 2012 */
984 /* return 0; */
985 }
986
987 return 1;
988 }
989
990 /*----------------------------------------------------------------------
991 *! set the DataArray attribute, based on the name=value string pair
992 *
993 * return 0 on success
994 * 1 on error
995 *//*-------------------------------------------------------------------*/
gifti_str2attr_darray(giiDataArray * DA,const char * attr,const char * value)996 int gifti_str2attr_darray(giiDataArray * DA, const char *attr,
997 const char *value)
998 {
999 if( !DA || !attr || !value ) {
1000 if( G.verb > 0 )
1001 fprintf(stderr,"** G_S2A_D: bad params (%p,%p,%p)\n",
1002 (void *)DA, (void *)attr, (void *)value);
1003 return 1;
1004 }
1005
1006 if(G.verb > 3) fprintf(stderr,"++ setting DA attr '%s'='%s'\n",attr,value);
1007
1008 if( !strcmp(attr, "Intent") )
1009 DA->intent = gifti_intent_from_string(value);
1010 else if( !strcmp(attr, "DataType") )
1011 DA->datatype = gifti_str2datatype(value);
1012 else if( !strcmp(attr, "ArrayIndexingOrder") )
1013 DA->ind_ord = gifti_str2ind_ord(value);
1014 else if( !strcmp(attr, "Dimensionality") ) DA->num_dim = atoi(value);
1015 else if( !strcmp(attr, "Dim0") ) DA->dims[0] = atoi(value);
1016 else if( !strcmp(attr, "Dim1") ) DA->dims[1] = atoi(value);
1017 else if( !strcmp(attr, "Dim2") ) DA->dims[2] = atoi(value);
1018 else if( !strcmp(attr, "Dim3") ) DA->dims[3] = atoi(value);
1019 else if( !strcmp(attr, "Dim4") ) DA->dims[4] = atoi(value);
1020 else if( !strcmp(attr, "Dim5") ) DA->dims[5] = atoi(value);
1021 else if( !strcmp(attr, "Encoding") )
1022 DA->encoding = gifti_str2encoding(value);
1023 else if( !strcmp(attr, "Endian") )
1024 DA->endian = gifti_str2endian(value);
1025 else if( !strcmp(attr, "ExternalFileName") )
1026 DA->ext_fname = gifti_strdup(value);
1027 else if( !strcmp(attr, "ExternalFileOffset") )
1028 #if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
1029 DA->ext_offset = atol(value); /* There is no atoll defined in MS VC++ */
1030 #else
1031 DA->ext_offset = atoll(value); /* assumes C99 */
1032 #endif
1033 else {
1034 if( G.verb > 1 ) /* might go into ex_atrs */
1035 fprintf(stderr,"** unknown giiDataArray attr, '%s'='%s'\n",
1036 G_CHECK_NULL_STR(attr),G_CHECK_NULL_STR(value));
1037 return 1;
1038 }
1039
1040 return 0;
1041 }
1042
1043 /* return 0 (UNDEFINED) on failure */
str2list_index(char * list[],int max,const char * str)1044 static int str2list_index( char * list[], int max, const char *str )
1045 {
1046 int index;
1047 if( !list || !str ) {
1048 if( G.verb > 0 ) fprintf(stderr,"** str2list: bad params (%p,%p)\n",
1049 (void *)list, (void *)str);
1050 return 0; /* should be *_UNDEFINED */
1051 }
1052
1053 for( index = max; index > 0; index-- )
1054 if( !strcmp(str, list[index]) ) return index;
1055
1056 return 0; /* failure */
1057 }
1058
1059 /*----------------------------------------------------------------------
1060 *! return the index for a GIFTI_IND_ORD_* string
1061 *//*-------------------------------------------------------------------*/
gifti_str2ind_ord(const char * str)1062 int gifti_str2ind_ord( const char * str )
1063 {
1064 int rv = str2list_index(gifti_index_order_list,GIFTI_IND_ORD_MAX,str);
1065 if( rv <= GIFTI_IND_ORD_UNDEF && G.verb > 1 )
1066 fprintf(stderr,"** bad index order, '%s'\n", str);
1067 return rv;
1068 }
1069
1070 /*----------------------------------------------------------------------
1071 *! return the GIFTI_IND_ORD_* string for the given index
1072 *//*-------------------------------------------------------------------*/
gifti_ind_ord2str(int ind_ord)1073 char * gifti_ind_ord2str( int ind_ord )
1074 {
1075 return gifti_list_index2string(gifti_index_order_list, ind_ord);
1076 }
1077
1078
1079 /*----------------------------------------------------------------------
1080 *! return the index for a GIFTI_ENDODING_* string
1081 *//*-------------------------------------------------------------------*/
gifti_str2encoding(const char * str)1082 int gifti_str2encoding( const char * str )
1083 {
1084 int rv = str2list_index(gifti_encoding_list, GIFTI_ENCODING_MAX, str);
1085 if( rv <= GIFTI_ENCODING_UNDEF && G.verb > 1 )
1086 fprintf(stderr,"** bad data encoding, '%s'\n", str);
1087 return rv;
1088 }
1089
1090 /*----------------------------------------------------------------------
1091 *! return the string at the given index of the given list
1092 *
1093 * This function is meant to index into one of the gifti_*_list arrays,
1094 * while being certain that the index is not out of range.
1095 *//*-------------------------------------------------------------------*/
gifti_list_index2string(char * list[],int index)1096 char * gifti_list_index2string(char * list[], int index)
1097 {
1098 int lsize; /* list size cannot be computed from the passed pointer */
1099
1100 if ( list == gifti_index_order_list )
1101 lsize = sizeof(gifti_index_order_list)/sizeof(char *);
1102
1103 else if( list == gifti_encoding_list )
1104 lsize = sizeof(gifti_encoding_list)/sizeof(char *);
1105
1106 else if( list == gifti_endian_list )
1107 lsize = sizeof(gifti_endian_list)/sizeof(char *);
1108
1109 else {
1110 fprintf(stderr,"** GLI2S: invalid list\n");
1111 return "UNKNOWN LIST";
1112 }
1113
1114 if( index < 0 || index >= lsize ) {
1115 if( G.verb > 0)
1116 fprintf(stderr,"** GLI2S: index %d out of range {0..%d}\n",
1117 index,lsize-1);
1118 return "INDEX OUT OF RANGE";
1119 }
1120
1121 /* all that work, just for the expected indexing... */
1122
1123 return list[index];
1124 }
1125
1126 /*----------------------------------------------------------------------
1127 *! return the NIFTI_TYPE_ value corresponding to the given string
1128 *//*-------------------------------------------------------------------*/
gifti_str2datatype(const char * str)1129 int gifti_str2datatype(const char * str)
1130 {
1131 int len = sizeof(gifti_type_list)/sizeof(gifti_type_ele);
1132 int c;
1133
1134 for( c = len - 1; c > 0; c-- )
1135 if( !strcmp(str, gifti_type_list[c].name) )
1136 break;
1137
1138 return gifti_type_list[c].type;
1139 }
1140
1141
1142 /*----------------------------------------------------------------------
1143 *! return the GIFTI_ENDIAN_ value corresponding to the given string
1144 *//*-------------------------------------------------------------------*/
gifti_str2endian(const char * str)1145 int gifti_str2endian( const char * str )
1146 {
1147 int rv = str2list_index(gifti_endian_list, GIFTI_ENDIAN_MAX, str);
1148 if( rv <= GIFTI_ENCODING_UNDEF && G.verb > 1 )
1149 fprintf(stderr,"** bad endian, '%s'\n", G_CHECK_NULL_STR(str));
1150 return rv;
1151 }
1152
1153
1154 /*----------------------------------------------------------------------
1155 *! return the NIFTI_TYPE_ value string corresponding to the given type
1156 *//*-------------------------------------------------------------------*/
gifti_datatype2str(int type)1157 char * gifti_datatype2str(int type)
1158 {
1159 int len = sizeof(gifti_type_list)/sizeof(gifti_type_ele);
1160 int c;
1161
1162 for( c = len - 1; c > 0; c-- )
1163 if( type == gifti_type_list[c].type)
1164 break;
1165
1166 return gifti_type_list[c].name;
1167 }
1168
1169
1170 /*----------------------------------------------------------------------
1171 *! simply set the struct contents to empty
1172 *//*-------------------------------------------------------------------*/
gifti_clear_nvpairs(nvpairs * p)1173 int gifti_clear_nvpairs(nvpairs * p)
1174 {
1175 if( !p ) return 1;
1176
1177 p->length = 0;
1178 p->name = NULL;
1179 p->value = NULL;
1180
1181 return 0;
1182 }
1183
1184 /*----------------------------------------------------------------------
1185 *! simply set the struct contents to empty
1186 *//*-------------------------------------------------------------------*/
gifti_clear_LabelTable(giiLabelTable * p)1187 int gifti_clear_LabelTable(giiLabelTable * p)
1188 {
1189 if( !p ) return 1;
1190
1191 p->length = 0;
1192 p->key = NULL;
1193 p->label = NULL;
1194 p->rgba = NULL;
1195
1196 return 0;
1197 }
1198
1199 /*----------------------------------------------------------------------
1200 *! simply set the struct contents to empty
1201 *//*-------------------------------------------------------------------*/
gifti_clear_CoordSystem(giiCoordSystem * p)1202 int gifti_clear_CoordSystem(giiCoordSystem * p)
1203 {
1204 if( !p ) return 1;
1205
1206 p->dataspace = NULL;
1207 p->xformspace = NULL;
1208 memset(p->xform,0,sizeof(p->xform));
1209
1210 return 0;
1211 }
1212
1213 /*----------------------------------------------------------------------
1214 *! add an empty CoordSystem struct to the DataArray
1215 *//*-------------------------------------------------------------------*/
gifti_add_empty_CS(giiDataArray * da)1216 int gifti_add_empty_CS(giiDataArray * da)
1217 {
1218 if( !da ) return 1;
1219
1220 /* be safe, if anything looks bad, start clean */
1221 if(da->numCS <= 0 || !da->coordsys) { da->numCS = 0; da->coordsys = NULL; }
1222
1223 if(G.verb > 3 )fprintf(stderr,"++ adding empty CS[%d]\n", da->numCS);
1224
1225 /* realloc coordsys pointer array, and add an empty structure */
1226 da->coordsys = (giiCoordSystem **)realloc(da->coordsys,
1227 (da->numCS+1) * sizeof(giiCoordSystem *));
1228 if( !da->coordsys ) {
1229 fprintf(stderr,"** AECS: failed to alloc %d CoordSys pointers\n",
1230 da->numCS+1);
1231 da->numCS = 0;
1232 return 1;
1233 }
1234
1235 da->coordsys[da->numCS] = (giiCoordSystem *)malloc(sizeof(giiCoordSystem));
1236 if( !da->coordsys[da->numCS] ) {
1237 fprintf(stderr,"** push_cstm: failed to alloc new CoordSystem\n");
1238 return 1;
1239 }
1240
1241 gifti_clear_CoordSystem(da->coordsys[da->numCS]);
1242
1243 da->numCS++;
1244
1245 return 0;
1246 }
1247
1248 /*----------------------------------------------------------------------
1249 *! rotate DA list, moving from the back to the front
1250 *
1251 * this (after add_empty) would allow one to add a new entry to the front
1252 *
1253 * - allocate for nrot temp pointers
1254 * - copy nrot trailing pointers to temp
1255 * - shift numDA-nrot pointers to end
1256 * - copy temp pointers to start
1257 * - free temp array
1258 *
1259 * return 0 on success
1260 * 1 on error
1261 *//*-------------------------------------------------------------------*/
gifti_rotate_DAs_to_front(gifti_image * gim,int nrot)1262 int gifti_rotate_DAs_to_front(gifti_image * gim, int nrot)
1263 {
1264 giiDataArray ** dtmp;
1265 int ind;
1266
1267 if( !gim || nrot < 0 || nrot >= gim->numDA) return 1;
1268
1269 if( nrot < 1 ) return 0;
1270
1271 if(G.verb > 3)fprintf(stderr,"++ rotate darray[%d] (%d)\n",gim->numDA,nrot);
1272
1273 /* allocate for temporary pointers */
1274 dtmp = (giiDataArray **)malloc(nrot*sizeof(giiDataArray *));
1275 if( !dtmp ) {
1276 fprintf(stderr,"** failed to alloc %d DA pointers\n", nrot);
1277 return 1;
1278 }
1279
1280 /* copy nrot into temp list (cleaner than memcpy?) */
1281 for( ind=0; ind < nrot; ind++ )
1282 dtmp[ind] = gim->darray[gim->numDA-nrot+ind];
1283
1284 /* shift numDA-nrot to end (index downward over destinations) */
1285 for( ind=gim->numDA-1; ind >= nrot; ind-- )
1286 gim->darray[ind] = gim->darray[ind-nrot];
1287
1288 /* copy nrot from temp list to start */
1289 for( ind=0; ind < nrot; ind++ )
1290 gim->darray[ind] = dtmp[ind];
1291
1292 free(dtmp);
1293
1294 return 0;
1295 }
1296
1297 /*----------------------------------------------------------------------
1298 *! add an empty DataArray struct to the gim->darray list
1299 *
1300 * this both reallocates gim->darray and allocates gim->darray[new]
1301 *
1302 * if num_to_add > 0: add that many elements
1303 * if defaults : init each element with default values
1304 *
1305 * return 0 on success
1306 * 1 on error
1307 *//*-------------------------------------------------------------------*/
gifti_add_empty_darray(gifti_image * gim,int num_to_add)1308 int gifti_add_empty_darray(gifti_image * gim, int num_to_add)
1309 {
1310 giiDataArray * dptr;
1311 int c, ntot, nnew = num_to_add > 0 ? num_to_add : 1;
1312
1313 if( !gim ) return 1;
1314
1315 if(G.verb > 3)fprintf(stderr,"++ alloc darray[%d] (+%d)\n",gim->numDA,nnew);
1316
1317 /* allocate for additional pointers */
1318 ntot = gim->numDA + nnew;
1319 gim->darray = (giiDataArray **)realloc(gim->darray,
1320 ntot*sizeof(giiDataArray *));
1321
1322 if( !gim->darray ) {
1323 fprintf(stderr,"** failed realloc darray, len %d\n", ntot);
1324 gim->numDA = 0;
1325 return 1;
1326 }
1327
1328 /* allocate the actual giiDataArray structs, inserted at the end */
1329 for( c = 0; c < nnew; c++ ) {
1330 dptr = (giiDataArray *)calloc(1, sizeof(giiDataArray));
1331 if( !dptr ) {
1332 fprintf(stderr,"** failed to alloc DA element #%d\n",gim->numDA);
1333 return 1; /* leave allocated list as is */
1334 }
1335 gim->darray[gim->numDA] = dptr;
1336 gim->numDA++;
1337
1338 /* clear any non-value attributes/elements */
1339 gifti_clear_DataArray(dptr);
1340 }
1341
1342 return 0;
1343 }
1344
1345 /*----------------------------------------------------------------------
1346 *! add the given name=value pair to the nvpairs struct
1347 *
1348 * this allocates memory for the p->name and p->value arrays, along
1349 * with duplicating the passed name/value strings
1350 *//*-------------------------------------------------------------------*/
gifti_add_to_nvpairs(nvpairs * p,const char * name,const char * value)1351 int gifti_add_to_nvpairs(nvpairs * p, const char * name, const char * value)
1352 {
1353 int index;
1354
1355 if( !p || !name || !value ) {
1356 if(G.verb > 1) fprintf(stderr,"** GATN: bad params(%p,%p,%p)\n",
1357 (void *)p, (void *)name, (void *)value);
1358 return 1;
1359 }
1360
1361 p->length++;
1362 p->name = (char **)realloc(p->name, p->length * sizeof(char *));
1363 p->value = (char **)realloc(p->value, p->length * sizeof(char *));
1364
1365 if( !p->name || !p->value ) {
1366 fprintf(stderr,"** GATN: failed to realloc %d pointers\n",p->length);
1367 return 1;
1368 } else if ( G.verb > 3 )
1369 fprintf(stderr,"++ add_nvp [%d]: '%s', '%s'\n", p->length,
1370 name ? name : "NULL", value ? value : "NULL");
1371
1372 index = p->length - 1;
1373 p->name[index] = gifti_strdup(name);
1374 p->value[index] = gifti_strdup(value);
1375
1376 if( !p->name[index] || !p->value[index] ) {
1377 fprintf(stderr,"** GATN: failed to copy pair '%s'='%s'\n",name,value);
1378 return 1;
1379 }
1380
1381 return 0;
1382 }
1383
1384 /*----------------------------------------------------------------------
1385 *! display the contents of the nvpairs struct
1386 *//*-------------------------------------------------------------------*/
gifti_disp_nvpairs(const char * mesg,const nvpairs * p)1387 int gifti_disp_nvpairs(const char * mesg, const nvpairs * p)
1388 {
1389 int c;
1390
1391 if( mesg ) { fputs(mesg, stderr); fputc(' ', stderr); }
1392
1393 if( !p ){ fputs("disp: nvpairs = NULL\n", stderr); return 1; }
1394
1395 fprintf(stderr,"nvpairs struct, len = %d :\n", p->length);
1396
1397 for(c = 0; c < p->length; c++ )
1398 fprintf(stderr," nvpair: '%s' = '%s'\n",
1399 G_CHECK_NULL_STR(p->name[c]), G_CHECK_NULL_STR(p->value[c]));
1400 if( p->length > 0 ) fputc('\n', stderr);
1401
1402 return 0;
1403 }
1404
1405 /*----------------------------------------------------------------------
1406 *! display the contents of the LabelTable struct
1407 *//*-------------------------------------------------------------------*/
gifti_disp_LabelTable(const char * mesg,const giiLabelTable * p)1408 int gifti_disp_LabelTable(const char * mesg, const giiLabelTable * p)
1409 {
1410 float * rgba;
1411 int c;
1412
1413 if( mesg ) { fputs(mesg, stderr); fputc(' ', stderr); }
1414
1415 if( !p ){ fputs("disp: giiLabelTable = NULL\n", stderr); return 1; }
1416
1417 fprintf(stderr,"giiLabelTable struct, len = %d :\n", p->length);
1418
1419 rgba = p->rgba;
1420 for(c = 0; c < p->length; c++ ) {
1421 fprintf(stderr," key %d, ", p->key[c]);
1422 if( rgba ) {
1423 fprintf(stderr,"rgba (%5.3f, %5.3f, %5.3f, %5.3f), ",
1424 rgba[0], rgba[1], rgba[2], rgba[3]);
1425 rgba += 4;
1426 }
1427 fprintf(stderr,"label '%s'\n", G_CHECK_NULL_STR(p->label[c]));
1428 }
1429
1430 if( p->length > 0 ) fputc('\n', stderr);
1431
1432 return 0;
1433 }
1434
1435 /*----------------------------------------------------------------------
1436 *! display the contents of the CoordSystem struct
1437 *//*-------------------------------------------------------------------*/
gifti_disp_CoordSystem(const char * mesg,const giiCoordSystem * p)1438 int gifti_disp_CoordSystem(const char * mesg, const giiCoordSystem * p)
1439 {
1440 int c1, c2;
1441
1442 if( mesg ) { fputs(mesg, stderr); fputc(' ', stderr); }
1443
1444 if( !p ){ fputs("disp: giiCoordSystem = NULL\n", stderr); return 1; }
1445
1446 fprintf(stderr,"giiCoordSystem struct\n"
1447 " dataspace = %s\n"
1448 " xformspace = %s\n",
1449 G_CHECK_NULL_STR(p->dataspace),
1450 G_CHECK_NULL_STR(p->xformspace));
1451 for( c1 = 0; c1 < 4; c1++ )
1452 {
1453 fprintf(stderr," xform[%d] :", c1);
1454 for( c2 = 0; c2 < 4; c2++ )
1455 fprintf(stderr," %f", p->xform[c1][c2]);
1456 fputc('\n', stderr);
1457 }
1458
1459 return 0;
1460 }
1461
1462 /*----------------------------------------------------------------------
1463 *! display the contents of the DataArray struct
1464 *
1465 * if 'subs' is set, display the contents of the sub-structures
1466 *//*-------------------------------------------------------------------*/
gifti_disp_DataArray(const char * mesg,const giiDataArray * p,int subs)1467 int gifti_disp_DataArray(const char * mesg, const giiDataArray * p, int subs)
1468 {
1469 int c;
1470 fprintf(stderr,"--------------------------------------------------\n");
1471
1472 if( mesg ) { fputs(mesg, stderr); fputc(' ', stderr); }
1473
1474 if( !p ){ fputs("disp: giiDataArray = NULL\n", stderr); return 1; }
1475
1476 fprintf(stderr,"giiDataArray struct\n"
1477 " intent %4d = %s\n"
1478 " datatype %2d = %s\n"
1479 " ind_ord %2d = %s\n"
1480 " num_dim = %d\n"
1481 " dims = %d, %d, %d, %d, %d, %d\n"
1482 " encoding %2d = %s\n"
1483 " endian %2d = %s\n"
1484 " ext_fname = %s\n"
1485 " ext_offset = %lld\n"
1486 , p->intent,
1487 gifti_intent_to_string(p->intent),
1488 p->datatype, gifti_datatype2str(p->datatype),
1489 p->ind_ord,
1490 gifti_list_index2string(gifti_index_order_list, p->ind_ord),
1491 p->num_dim,
1492 p->dims[0], p->dims[1], p->dims[2],
1493 p->dims[3], p->dims[4], p->dims[5],
1494 p->encoding,
1495 gifti_list_index2string(gifti_encoding_list, p->encoding),
1496 p->endian,
1497 gifti_list_index2string(gifti_endian_list, p->endian),
1498 G_CHECK_NULL_STR(p->ext_fname), p->ext_offset
1499 );
1500
1501 if( subs ) gifti_disp_nvpairs("darray->meta", &p->meta);
1502 if( subs ) for( c = 0; c < p->numCS; c++ )
1503 gifti_disp_CoordSystem("darray->coordsys", p->coordsys[c]);
1504
1505 fprintf(stderr," data = %s\n"
1506 " nvals = %u\n"
1507 " nbyper = %d\n"
1508 " numCS = %d\n",
1509 p->data ? "<set>" : "NULL", (unsigned)p->nvals,
1510 p->nbyper, p->numCS);
1511
1512 if( subs ) gifti_disp_nvpairs("darray->ex_atrs", &p->ex_atrs);
1513 fprintf(stderr,"--------------------------------------------------\n");
1514
1515 return 0;
1516 }
1517
1518 /*----------------------------------------------------------------------
1519 *! display the contents of the gifti_image struct
1520 *
1521 * if 'subs' is set, display the contents of the sub-structures, such
1522 * as all of the DataArray elements
1523 *//*-------------------------------------------------------------------*/
gifti_disp_gifti_image(const char * mesg,const gifti_image * p,int subs)1524 int gifti_disp_gifti_image(const char * mesg, const gifti_image * p, int subs)
1525 {
1526 fprintf(stderr,"==================================================\n");
1527
1528 if( mesg ) { fputs(mesg, stderr); fputc(' ', stderr); }
1529
1530 if( !p ){ fputs("disp: gifti_image = NULL\n", stderr); return 1; }
1531
1532 fprintf(stderr,"gifti_image struct\n"
1533 " version = %s\n"
1534 " numDA = %d\n",
1535 G_CHECK_NULL_STR(p->version), p->numDA);
1536
1537 if( subs ) {
1538 char buf[32];
1539 int c;
1540
1541 gifti_disp_nvpairs("gim->meta", &p->meta);
1542 gifti_disp_LabelTable("gim->labeltable", &p->labeltable);
1543 for( c = 0; c < p->numDA; c++ ) {
1544 sprintf(buf, "gim->darray[%d]", c);
1545 gifti_disp_DataArray(buf, p->darray[c], subs);
1546 }
1547 }
1548
1549 fprintf(stderr,"gifti_image struct\n"
1550 " swapped = %d\n"
1551 " compressed = %d\n", p->swapped, p->compressed);
1552
1553 fprintf(stderr," -- darray totals: %lld MB\n",gifti_gim_DA_size(p,1));
1554 if( subs ) gifti_disp_nvpairs("gim->ex_atrs" , &p->ex_atrs);
1555
1556 fprintf(stderr,"==================================================\n");
1557
1558 return 0;
1559 }
1560
1561 /*----------------------------------------------------------------------
1562 *! compute the number of bytes summed over all DataArray elements
1563 *
1564 * if in_mb is set, return the (rounded) number of megabytes
1565 * (i.e. 17 is 17 MB)
1566 *//*-------------------------------------------------------------------*/
gifti_gim_DA_size(const gifti_image * p,int in_mb)1567 long long gifti_gim_DA_size(const gifti_image * p, int in_mb)
1568 {
1569 long long bytes = 0;
1570 int c;
1571
1572 if( !p ) return -1;
1573 if( !p->darray || p->numDA <= 0 ) return 0;
1574
1575 for( c = 0; c < p->numDA; c++ ) {
1576 if( ! p->darray[c]->data ) continue; /* skip anything without data */
1577 if( p->darray[c]->nvals <= 0 || p->darray[c]->nbyper <= 0 ) {
1578 fprintf(stderr,"** have data[%d], but nvals = %lld, nbyper = %d\n",
1579 c, p->darray[c]->nvals, p->darray[c]->nbyper);
1580 return 0;
1581 }
1582 bytes += p->darray[c]->nvals * p->darray[c]->nbyper;
1583 }
1584
1585 if( bytes <= 0LL ) return 0;
1586
1587 if( in_mb ) bytes = (bytes + (1<<19) ) >> 20; /* round to nearest MB */
1588
1589 return bytes;
1590 }
1591
1592 /*----------------------------------------------------------------------
1593 *! given a datatype, return the corresponding bytes per value and swapsize
1594 *
1595 * nbyper and swapsize are filled only if the pointers are set
1596 *//*-------------------------------------------------------------------*/
gifti_datatype_sizes(int datatype,int * nbyper,int * swapsize)1597 int gifti_datatype_sizes(int datatype, int *nbyper, int *swapsize)
1598 {
1599 int c;
1600
1601 for( c = sizeof(gifti_type_list) / sizeof(gifti_type_ele) - 1; c > 0; c-- )
1602 if( datatype == gifti_type_list[c].type ) {
1603 if( nbyper ) *nbyper = gifti_type_list[c].nbyper;
1604 if( swapsize ) *swapsize = gifti_type_list[c].swapsize;
1605 return 0;
1606 }
1607
1608 if( G.verb > 0 ) fprintf(stderr,"** GDS with bad datatype %d\n", datatype);
1609 if( nbyper ) *nbyper = 0;
1610 if( swapsize ) *swapsize = 0;
1611
1612 return 1;
1613 }
1614
1615 /*----------------------------------------------------------------------
1616 *! compute the total number of data values in a DataArray element
1617 *//*-------------------------------------------------------------------*/
gifti_darray_nvals(const giiDataArray * da)1618 long long gifti_darray_nvals(const giiDataArray * da)
1619 {
1620 long long ndim = 1;
1621 int c;
1622
1623 if(!da){ fprintf(stderr,"** GDND, no ptr\n"); return 0; }
1624
1625 if( ! gifti_valid_num_dim(da->num_dim, 0) ) {
1626 fprintf(stderr,"** giiDataArray has illegal num_dim = %d\n",
1627 da->num_dim);
1628 return 0;
1629 }
1630
1631 for( c = 0; c < da->num_dim; c++ ) ndim *= da->dims[c];
1632
1633 if( ndim <= 0 ) {
1634 gifti_disp_DataArray("** bad Dim list in ", da, 0);
1635 return 0;
1636 }
1637
1638 return ndim;
1639 }
1640
1641 /*----------------------------------------------------------------------
1642 *! find giiDataArray element #index of the given intent
1643 *//*-------------------------------------------------------------------*/
gifti_find_DA(gifti_image * gim,int intent,int index)1644 giiDataArray * gifti_find_DA(gifti_image * gim, int intent, int index)
1645 {
1646 int c, nfound;
1647
1648 if( !gim || !gifti_intent_is_valid(intent) || index < 0 ) {
1649 fprintf(stderr,"** find_DA: bad inputs (%p, %d, %d)\n",
1650 (void*)gim, intent, index);
1651 return NULL;
1652 }
1653
1654 if ( !gim-> darray ) return NULL;
1655
1656 for( c = 0, nfound = 0; c < gim->numDA; c++ )
1657 if( gim->darray[c] && gim->darray[c]->intent == intent ) {
1658 if( nfound == index )
1659 return gim->darray[c]; /* success */
1660 nfound++; /* else, increment counter and keep looking */
1661 }
1662
1663 return NULL;
1664 }
1665
1666 /*----------------------------------------------------------------------
1667 *! return an allocated list of giiDataArray pointers of the given intent
1668 *
1669 * 'list' should be freed or taken
1670 *//*-------------------------------------------------------------------*/
gifti_find_DA_list(gifti_image * gim,int intent,giiDataArray *** list,int * len)1671 int gifti_find_DA_list(gifti_image * gim, int intent,
1672 giiDataArray *** list, int * len)
1673 {
1674 int c, nfound;
1675
1676 if( !gim || !gifti_intent_is_valid(intent) || !list || !len ) {
1677 fprintf(stderr,"** find_DA: bad inputs (%p, %d, %p, %p)\n",
1678 (void *)gim, intent, (void *)list, (void *)len);
1679 return 1;
1680 }
1681
1682 if ( !gim->darray ) return 1;
1683
1684 /* create one big enough to hold everything */
1685 *len = gim->numDA;
1686 *list = (giiDataArray **)calloc(*len, sizeof(giiDataArray *));
1687 if( !*list ) {
1688 fprintf(stderr,"** find_DA_list: failed to alloc %d ptrs\n",*len);
1689 *len = 0;
1690 return 1;
1691 }
1692
1693 for( c = 0, nfound = 0; c < gim->numDA; c++ )
1694 if( gim->darray[c] && gim->darray[c]->intent == intent )
1695 (*list)[nfound++] = gim->darray[c];
1696
1697 /* if we didn't find any, nuke list, but do not return an error */
1698 if( nfound == 0 ) { free(*list); *list = NULL; *len = 0; return 0; }
1699
1700 /* otherwise, reallocate a smaller list */
1701 if( nfound < *len ) {
1702 *len = nfound;
1703 *list = (giiDataArray**)realloc(*list,*len*sizeof(giiDataArray*));
1704 if( !*list ) {
1705 fprintf(stderr,"** find_DA_list: failed realloc of %d ptrs\n",*len);
1706 *len = 0;
1707 return 1;
1708 }
1709 }
1710
1711 return 0;
1712 }
1713
1714 /*----------------------------------------------------------------------
1715 *! given metadata name, return the corresponding value (or NULL)
1716 *
1717 * no allocation is done here
1718 *//*-------------------------------------------------------------------*/
gifti_get_meta_value(const nvpairs * nvp,const char * name)1719 char * gifti_get_meta_value(const nvpairs * nvp, const char * name)
1720 {
1721 int c;
1722
1723 if( !nvp || !name ) {
1724 if( G.verb > 3 )
1725 fprintf(stderr,"** get_meta_value: NULL input (%p, %p)\n",
1726 (void*)nvp, name);
1727 return NULL;
1728 }
1729
1730 if( G.verb > 5 )
1731 fprintf(stderr,"-- G_get_meta_value: looking for name = '%s'\n", name);
1732
1733 if ( !nvp->name || !nvp->value || nvp->length <= 0 ) {
1734 if( G.verb > 3 )
1735 fprintf(stderr,"-- G_get_meta_value: no name/value array\n");
1736 return NULL;
1737 }
1738
1739 for( c = 0; c < nvp->length; c++ )
1740 if( !strcmp(nvp->name[c], name) )
1741 break; /* found */
1742
1743 if( c >= nvp->length ) return NULL;
1744
1745 if( G.verb > 3 )
1746 fprintf(stderr,"++ found meta '%s'='%s'\n",nvp->name[c],nvp->value[c]);
1747
1748 return nvp->value[c];
1749 }
1750
1751 /*----------------------------------------------------------------------
1752 *! return the number of 'rows' and 'columns' of a DataArray element
1753 *
1754 * define rows to be along the first dimension, and collapse the
1755 * remaining dimensions as cols
1756 *//*-------------------------------------------------------------------*/
gifti_DA_rows_cols(giiDataArray * da,long long * rows,long long * cols)1757 int gifti_DA_rows_cols(giiDataArray * da, long long * rows, long long * cols)
1758 {
1759 *rows = da->dims[0]; /* init */
1760 *cols = 1;
1761
1762 if( da->num_dim == 1 ) return 0; /* use default */
1763
1764 /* ROW_MAJOR does not matter here 25 Apr 2017 [rickr] */
1765 /* treat Dim[0] as nodes (they change most slowly) */
1766 *rows = da->dims[0];
1767 *cols = (*rows) ? da->nvals / *rows : 1; /* be safe */
1768
1769 #if 0
1770 /* old COL_MAJOR case... */
1771 *rows = da->dims[da->num_dim-1]; /* take highest index */
1772 *cols = (*rows > 0) ? da->nvals / *rows : 1;
1773 #endif
1774
1775 return 0;
1776 }
1777
1778 /*----------------------------------------------------------------------
1779 *! print the gifti library history string
1780 *//*-------------------------------------------------------------------*/
gifti_disp_lib_hist(void)1781 void gifti_disp_lib_hist(void)
1782 {
1783 int c, len = sizeof(gifti_history)/sizeof(char *);
1784 for( c = 0; c < len; c++ )
1785 fputs(gifti_history[c], stdout);
1786 }
1787
1788 /*----------------------------------------------------------------------
1789 *! print the gifti library version string
1790 *//*-------------------------------------------------------------------*/
gifti_disp_lib_version(void)1791 void gifti_disp_lib_version(void)
1792 {
1793 printf("%s, compiled %s\n", gifti_version, __DATE__);
1794 }
1795
1796 /*----------------------------------------------------------------------
1797 *! return the gifti library version string
1798 *//*-------------------------------------------------------------------*/
gifticlib_version(void)1799 char * gifticlib_version(void)
1800 {
1801 return gifti_version;
1802 }
1803
1804 /*----------------------------------------------------------------------
1805 *! print the gifti DTD URL
1806 *//*-------------------------------------------------------------------*/
gifti_disp_dtd_url(void)1807 void gifti_disp_dtd_url(void)
1808 {
1809 printf("The GIFTI Document Type Definition (DTD) is at:\n %s\n",
1810 GIFTI_XML_DTD_SOURCE);
1811 }
1812
1813 /*----------------------------------------------------------------------
1814 *! display data in hexidecimal, on one line
1815 *
1816 * if mesg is set, print the message first
1817 * if fp is not set, print to stdout
1818 *//*-------------------------------------------------------------------*/
gifti_disp_hex_data(const char * mesg,const void * data,int len,FILE * fp)1819 int gifti_disp_hex_data(const char *mesg, const void *data, int len, FILE *fp)
1820 {
1821 const char * dp = (const char *)data;
1822 FILE * stream;
1823 int c;
1824
1825 stream = fp ? fp : stdout;
1826
1827 if( !data || len < 1 ) return -1;
1828
1829 if( mesg ) fputs(mesg, stream);
1830
1831 for( c = 0; c < len; c++ )
1832 fprintf(stream, " %02x", dp[c]);
1833
1834 return 0;
1835 }
1836
1837 /*----------------------------------------------------------------------
1838 *! swap sets of 2-byte values
1839 *//*-------------------------------------------------------------------*/
gifti_swap_2bytes(void * data,long long nsets)1840 int gifti_swap_2bytes(void * data, long long nsets)
1841 {
1842 char * cp1 = (char *)data, * cp2;
1843 char tval;
1844 long long c;
1845
1846 for( c = 0; c < nsets; c++ ) {
1847 cp2 = cp1 + 1;
1848 tval = *cp1; *cp1 = *cp2; *cp2 = tval;
1849 cp1 += 2;
1850 }
1851
1852 return 0;
1853 }
1854
1855 /*----------------------------------------------------------------------
1856 *! swap sets of 4-byte values
1857 *//*-------------------------------------------------------------------*/
gifti_swap_4bytes(void * data,long long nsets)1858 int gifti_swap_4bytes(void * data, long long nsets)
1859 {
1860 char * cp0 = (char *)data, * cp1, * cp2;
1861 char tval;
1862 long long c;
1863
1864 for( c = 0; c < nsets; c++ ) {
1865 cp1 = cp0;
1866 cp2 = cp0 + 3;
1867 tval = *cp1; *cp1 = *cp2; *cp2 = tval;
1868 cp1++; cp2--;
1869 tval = *cp1; *cp1 = *cp2; *cp2 = tval;
1870 cp0 += 4;
1871 }
1872
1873 return 0;
1874 }
1875
1876 /*----------------------------------------------------------------------
1877 *! swap sets of N-byte values
1878 *
1879 * if N < 2 : just return
1880 * if N = 2 or N = 4: call explicit function for that size (speed)
1881 * else : swap in a loop
1882 *//*-------------------------------------------------------------------*/
gifti_swap_Nbytes(void * data,long long nsets,int swapsize)1883 int gifti_swap_Nbytes(void * data, long long nsets, int swapsize)
1884 {
1885 char * cp0, * cp1, * cp2;
1886 char tval;
1887 long long c;
1888 int offset; /* swapsize - 1, for speed */
1889
1890 if( ! data || nsets < 0 || swapsize < 0 ) {
1891 fprintf(stderr,"** swap_Nbytes: bad params (%p,%lld,%d)\n",
1892 (void *)data, nsets, swapsize);
1893 return 1;
1894 }
1895
1896 if ( swapsize < 2 ) return 0; /* nothing to do */
1897 else if( swapsize == 2 ) return gifti_swap_2bytes(data, nsets);
1898 else if( swapsize == 4 ) return gifti_swap_4bytes(data, nsets);
1899
1900 /* peform a swap */
1901 cp0 = (char *)data;
1902 offset = swapsize-1; /* just for speed */
1903
1904 for( c = 0; c < nsets; c++ ) {
1905 cp1 = cp0;
1906 cp2 = cp0 + offset;
1907 while( cp2 > cp1 ) {
1908 tval = *cp1; *cp1 = *cp2; *cp2 = tval;
1909 cp1++; cp2--;
1910 }
1911 cp0 += swapsize;
1912 }
1913
1914 return 0;
1915 }
1916
1917 /*----------------------------------------------------------------------
1918 *! return the current CPU endian: GIFTI_ENDIAN_BIG or _LITTLE
1919 *//*-------------------------------------------------------------------*/
gifti_get_this_endian(void)1920 int gifti_get_this_endian(void)
1921 {
1922 int one = 1;
1923 char * cp = (char *)&one;
1924
1925 if( *cp ) return GIFTI_ENDIAN_LITTLE;
1926
1927 return GIFTI_ENDIAN_BIG;
1928 }
1929
1930 /*----------------------------------------------------------------------
1931 *! if endian does not match that of this CPU, swap the data bytes
1932 *
1933 * return whether bytes were swapped
1934 *//*-------------------------------------------------------------------*/
gifti_check_swap(void * data,int endian,long long nsets,int swapsize)1935 int gifti_check_swap(void * data, int endian, long long nsets, int swapsize)
1936 {
1937 if( !data || nsets < 0 || swapsize < 0 ) {
1938 fprintf(stderr,"** check_swap: bad params (%p,%lld, %d)\n",
1939 (void *)data, nsets, swapsize);
1940 return 0;
1941 } else if ( endian <= GIFTI_ENDIAN_UNDEF || endian > GIFTI_ENDIAN_MAX ) {
1942 fprintf(stderr, "** check_swap: invalid endian %d\n", endian);
1943 return 0;
1944 }
1945
1946 /* if endian is the same as this one, just return */
1947 if( endian == gifti_get_this_endian() ) {
1948 if( G.verb > 2 )
1949 fprintf(stderr,"-- darray no swap needed : %lld sets of %d bytes\n",
1950 nsets, swapsize);
1951 return 0;
1952 }
1953
1954 if( G.verb > 2 )
1955 fprintf(stderr,"++ darray swap: %lld sets of %d bytes\n",
1956 nsets, swapsize);
1957
1958 /* do the swap */
1959 (void)gifti_swap_Nbytes(data, nsets, swapsize);
1960
1961 return 1;
1962 }
1963
1964 #ifdef GIFTI_BAD_SIZEOF
1965 #undef GIFTI_BAD_SIZEOF
1966 #endif
1967 #define GIFTI_BAD_SIZEOF(mesg, type, size) \
1968 ((sizeof(type) == size) ? 0 : \
1969 (fprintf(stderr,"%s : sizeof(#type) != %d\n", mesg, size), 1))
1970
1971 /*---------------------------------------------------------------------*/
1972 /*! Convert the ArrayIndexingOrder of the gifti_image DA elements to
1973 * the given order. 28 Apr 2017 [rickr]
1974 *
1975 * This is not just a tranpose, but a more general permutation of
1976 * the data in memory, so allocate a new data pointer.
1977 *
1978 * Terminate on first DA failure.
1979 *
1980 * return 1 if convertion occurred, 0 if not, -1 on error
1981 *//*-------------------------------------------------------------------*/
gifti_convert_ind_ord(gifti_image * gim,int new_ord)1982 int gifti_convert_ind_ord(gifti_image * gim, int new_ord)
1983 {
1984 int dind, rv, perm=0;
1985
1986 if ( ! gim ) {
1987 fprintf(stderr,"** gifti_convert_ind_ord: no gifti_image\n");
1988 return 1;
1989 }
1990
1991 for( dind = 0; dind < gim->numDA; dind++ ) {
1992 rv = gifti_convert_DA_ind_ord(gim->darray[dind], new_ord);
1993 if( rv < 0 ) return rv; /* fail on any error */
1994 if( rv > 0 ) perm = 1; /* note that it happened */
1995 }
1996
1997 return perm;
1998 }
1999
2000 /*---------------------------------------------------------------------*/
2001 /*! Convert the ArrayIndexingOrder of the DataArry element to the
2002 * specified order. 27 Apr 2017 [rickr]
2003 *
2004 * This is not just a tranpose, but a more general permutation of
2005 * the data in memory, so allocate a new data pointer.
2006 *
2007 * return 1 if converted, 0 of not, -1 on error
2008 *//*-------------------------------------------------------------------*/
gifti_convert_DA_ind_ord(giiDataArray * da,int new_ord)2009 int gifti_convert_DA_ind_ord(giiDataArray * da, int new_ord)
2010 {
2011 char * fname = "convert_ind_ord";
2012 void * newdata = NULL;
2013
2014 if ( !gifti_valid_dims(da, 1) ) /* will whine */
2015 return -1;
2016
2017 if( new_ord <= GIFTI_IND_ORD_UNDEF || new_ord > GIFTI_IND_ORD_MAX ) {
2018 if( G.verb )
2019 fprintf(stderr,"** %s: invalid order %d\n", fname, new_ord);
2020 return -1;
2021 }
2022
2023 if( da->ind_ord == new_ord ) {
2024 if( G.verb > 4 )
2025 fprintf(stderr,"-- %s: order already %d = %s\n", fname, new_ord,
2026 gifti_list_index2string(gifti_index_order_list, new_ord));
2027 return 0;
2028 }
2029
2030 if( da->nvals == 0 ) return 0;
2031
2032 /*--- have something to do ---*/
2033
2034 if( G.verb > 3 )
2035 fprintf(stderr,"-- changing ind_ord from %d (%s) to %d (%s)...\n",
2036 da->ind_ord,
2037 gifti_list_index2string(gifti_index_order_list, da->ind_ord),
2038 new_ord,
2039 gifti_list_index2string(gifti_index_order_list, new_ord));
2040
2041 /* have something to do, but is it trivial? */
2042 if( da->num_dim == 1 ) {
2043 if( G.verb > 3 )
2044 fprintf(stderr,"-- %s: num_dim == 1, so simply change field\n",fname);
2045 da->ind_ord = new_ord;
2046 return 0;
2047 }
2048
2049 /*------ have something real to do, either RM->CM or the reverse ------*/
2050
2051 /* allocate output data array (or could overwrite input not to change it? */
2052 newdata = malloc(da->nvals * da->nbyper);
2053 if( ! newdata ) {
2054 fprintf(stderr,"** %s: failed to alloc %lld bytes for DA\n",
2055 fname, da->nvals*da->nbyper);
2056 return -1;
2057 }
2058
2059 /* actually permute the data */
2060 if( permute_by_index_order(newdata, new_ord, da) ) {
2061 free(newdata);
2062 return -1;
2063 }
2064
2065 /* insert result and clean up */
2066 free(da->data);
2067 da->data = newdata;
2068 da->ind_ord = new_ord;
2069
2070 return 1; /* change happened */
2071 }
2072
2073 /*===========================================================================
2074 * row major/column major index order permutation macros
2075 *===========================================================================*/
2076
2077 /* column major to row major conversion */
2078 #define GIFTI_PBIO_C2R_2(type, din, dout) \
2079 do { \
2080 type * dinp = (type *)din, * doutp = (type *)dout; \
2081 for( i0 = 0; i0 < m0; i0++ ) \
2082 for( i1 = 0; i1 < m1; i1++ ) \
2083 *doutp++ = dinp[i0 + m0 * i1]; \
2084 } while(0)
2085
2086
2087 #define GIFTI_PBIO_C2R_3(type, din, dout) \
2088 do { \
2089 type * dinp = (type *)din, * doutp = (type *)dout; \
2090 type * bp0, * bp1, * bp2; \
2091 for( i0 = 0; i0 < m0; i0++ ) { \
2092 bp0 = dinp + i0; \
2093 for( i1 = 0; i1 < m1; i1++ ) { \
2094 bp1 = bp0 + i1 * m0; \
2095 for( i2 = 0; i2 < m2; i2++ ) { \
2096 bp2 = bp1 + i2 * m0*m1; \
2097 *doutp++ = *bp2; \
2098 } } } \
2099 } while(0)
2100
2101 #define GIFTI_PBIO_C2R_4(type, din, dout) \
2102 do { \
2103 type * dinp = (type *)din, * doutp = (type *)dout; \
2104 type * bp0, * bp1, * bp2, * bp3; \
2105 for( i0 = 0; i0 < m0; i0++ ) { \
2106 bp0 = dinp + i0; \
2107 for( i1 = 0; i1 < m1; i1++ ) { \
2108 bp1 = bp0 + i1 * m0; \
2109 for( i2 = 0; i2 < m2; i2++ ) { \
2110 bp2 = bp1 + i2 * m0*m1; \
2111 for( i3 = 0; i3 < m3; i3++ ) { \
2112 bp3 = bp2 + i3 * m0*m1*m2; \
2113 *doutp++ = *bp3; \
2114 } } } } \
2115 } while(0)
2116
2117 #define GIFTI_PBIO_C2R_5(type, din, dout) \
2118 do { \
2119 type * dinp = (type *)din, * doutp = (type *)dout; \
2120 type * bp0, * bp1, * bp2, * bp3, * bp4; \
2121 for( i0 = 0; i0 < m0; i0++ ) { \
2122 bp0 = dinp + i0; \
2123 for( i1 = 0; i1 < m1; i1++ ) { \
2124 bp1 = bp0 + i1 * m0; \
2125 for( i2 = 0; i2 < m2; i2++ ) { \
2126 bp2 = bp1 + i2 * m0*m1; \
2127 for( i3 = 0; i3 < m3; i3++ ) { \
2128 bp3 = bp2 + i3 * m0*m1*m2; \
2129 for( i4 = 0; i4 < m4; i4++ ) { \
2130 bp4 = bp3 + i4 * m0*m1*m2*m3; \
2131 *doutp++ = *bp4; \
2132 } } } } } \
2133 } while(0)
2134
2135 #define GIFTI_PBIO_C2R_6(type, din, dout) \
2136 do { \
2137 type * dinp = (type *)din, * doutp = (type *)dout; \
2138 type * bp0, * bp1, * bp2, * bp3, * bp4, * bp5; \
2139 for( i0 = 0; i0 < m0; i0++ ) { \
2140 bp0 = dinp + i0; \
2141 for( i1 = 0; i1 < m1; i1++ ) { \
2142 bp1 = bp0 + i1 * m0; \
2143 for( i2 = 0; i2 < m2; i2++ ) { \
2144 bp2 = bp1 + i2 * m0*m1; \
2145 for( i3 = 0; i3 < m3; i3++ ) { \
2146 bp3 = bp2 + i3 * m0*m1*m2; \
2147 for( i4 = 0; i4 < m4; i4++ ) { \
2148 bp4 = bp3 + i4 * m0*m1*m2*m3; \
2149 for( i5 = 0; i5 < m5; i5++ ) { \
2150 bp5 = bp4 + i5 * m0*m1*m2*m3*m4; \
2151 *doutp++ = *bp5; \
2152 } } } } } } \
2153 } while(0)
2154
2155
2156 /* row major to column major conversions */
2157 /* same indexing, but switch application between in and out pointers */
2158 #define GIFTI_PBIO_R2C_2(type, din, dout) \
2159 do { \
2160 type * dinp = (type *)din, * doutp = (type *)dout; \
2161 for( i0 = 0; i0 < m0; i0++ ) \
2162 for( i1 = 0; i1 < m1; i1++ ) \
2163 doutp[i0 + m0 * i1] = *dinp++; \
2164 } while(0)
2165
2166
2167 #define GIFTI_PBIO_R2C_3(type, din, dout) \
2168 do { \
2169 type * dinp = (type *)din, * doutp = (type *)dout; \
2170 type * bp0, * bp1, * bp2; \
2171 for( i0 = 0; i0 < m0; i0++ ) { \
2172 bp0 = doutp + i0; \
2173 for( i1 = 0; i1 < m1; i1++ ) { \
2174 bp1 = bp0 + i1 * m0; \
2175 for( i2 = 0; i2 < m2; i2++ ) { \
2176 bp2 = bp1 + i2 * m0*m1; \
2177 *bp2 = *dinp++; \
2178 } } } \
2179 } while(0)
2180
2181 #define GIFTI_PBIO_R2C_4(type, din, dout) \
2182 do { \
2183 type * dinp = (type *)din, * doutp = (type *)dout; \
2184 type * bp0, * bp1, * bp2, * bp3; \
2185 for( i0 = 0; i0 < m0; i0++ ) { \
2186 bp0 = doutp + i0; \
2187 for( i1 = 0; i1 < m1; i1++ ) { \
2188 bp1 = bp0 + i1 * m0; \
2189 for( i2 = 0; i2 < m2; i2++ ) { \
2190 bp2 = bp1 + i2 * m0*m1; \
2191 for( i3 = 0; i3 < m3; i3++ ) { \
2192 bp3 = bp2 + i3 * m0*m1*m2; \
2193 *bp3 = *dinp++; \
2194 } } } } \
2195 } while(0)
2196
2197 #define GIFTI_PBIO_R2C_5(type, din, dout) \
2198 do { \
2199 type * dinp = (type *)din, * doutp = (type *)dout; \
2200 type * bp0, * bp1, * bp2, * bp3, * bp4; \
2201 for( i0 = 0; i0 < m0; i0++ ) { \
2202 bp0 = doutp + i0; \
2203 for( i1 = 0; i1 < m1; i1++ ) { \
2204 bp1 = bp0 + i1 * m0; \
2205 for( i2 = 0; i2 < m2; i2++ ) { \
2206 bp2 = bp1 + i2 * m0*m1; \
2207 for( i3 = 0; i3 < m3; i3++ ) { \
2208 bp3 = bp2 + i3 * m0*m1*m2; \
2209 for( i4 = 0; i4 < m4; i4++ ) { \
2210 bp4 = bp3 + i4 * m0*m1*m2*m3; \
2211 *bp4 = *dinp++; \
2212 } } } } } \
2213 } while(0)
2214
2215 #define GIFTI_PBIO_R2C_6(type, din, dout) \
2216 do { \
2217 type * dinp = (type *)din, * doutp = (type *)dout; \
2218 type * bp0, * bp1, * bp2, * bp3, * bp4, * bp5; \
2219 for( i0 = 0; i0 < m0; i0++ ) { \
2220 bp0 = doutp + i0; \
2221 for( i1 = 0; i1 < m1; i1++ ) { \
2222 bp1 = bp0 + i1 * m0; \
2223 for( i2 = 0; i2 < m2; i2++ ) { \
2224 bp2 = bp1 + i2 * m0*m1; \
2225 for( i3 = 0; i3 < m3; i3++ ) { \
2226 bp3 = bp2 + i3 * m0*m1*m2; \
2227 for( i4 = 0; i4 < m4; i4++ ) { \
2228 bp4 = bp3 + i4 * m0*m1*m2*m3; \
2229 for( i5 = 0; i5 < m5; i5++ ) { \
2230 bp5 = bp4 + i5 * m0*m1*m2*m3*m4; \
2231 *bp5 = *dinp++; \
2232 } } } } } } \
2233 } while(0)
2234
2235
2236 /*===========================================================================*/
2237
2238 /* decisions... slow and steady or fast and dangerous?
2239 * let's change to slow and steady, since this should be uncommon
2240 *
2241 * return 0 on success
2242 */
permute_by_index_order(void * dest,int new_ord,giiDataArray * da)2243 static int permute_by_index_order(void * dest, int new_ord, giiDataArray * da)
2244 {
2245 long long m0, m1, m2, m3, m4, m5;
2246 long long i0, i1, i2, i3, i4, i5;
2247 char * mesg = "permute index order";
2248
2249 /* avoid repetitive indexing (for speed) */
2250 m0 = da->dims[0]; m1 = da->dims[1]; m2 = da->dims[2];
2251 m3 = da->dims[3]; m4 = da->dims[4]; m5 = da->dims[5];
2252
2253 /* we checked before, but hey... */
2254 if( new_ord != GIFTI_IND_ORD_ROW_MAJOR &&
2255 new_ord != GIFTI_IND_ORD_COL_MAJOR ) {
2256 fprintf(stderr,"** PBIO: invalid index order %d\n", new_ord);
2257 return 1;
2258 }
2259
2260 if( G.verb > 3 ) {
2261 fprintf(stderr,"-- permute order: %d to %d, nbyper %d\n dims: ",
2262 da->ind_ord, new_ord, da->nbyper);
2263 gifti_disp_raw_data(da->dims, DT_INT32, da->num_dim, 1, stderr);
2264 }
2265
2266 switch( da->nbyper ) {
2267 default: {
2268 /* don't need to fail after malloc, but this should be rare,
2269 and this is a good place for a failure check */
2270 fprintf(stderr,"** %s: not prepared for nbyper = %d\n",
2271 mesg, da->nbyper);
2272 return 1;
2273 }
2274 case 1: { /* process as char (signed int8) */
2275 if( GIFTI_BAD_SIZEOF(mesg, char, 1) ) return 1;
2276
2277 if( new_ord == GIFTI_IND_ORD_ROW_MAJOR ) {
2278 switch( da->num_dim ) {
2279 default: break; /* do nothing for 1 or unknown */
2280 case 2: GIFTI_PBIO_C2R_2(char, da->data, dest); break;
2281 case 3: GIFTI_PBIO_C2R_3(char, da->data, dest); break;
2282 case 4: GIFTI_PBIO_C2R_4(char, da->data, dest); break;
2283 case 5: GIFTI_PBIO_C2R_5(char, da->data, dest); break;
2284 case 6: GIFTI_PBIO_C2R_6(char, da->data, dest); break;
2285 }
2286 } else { /* to GIFTI_IND_ORD_COL_MAJOR */
2287 switch( da->num_dim ) {
2288 default: break; /* do nothing for 1 or unknown */
2289 case 2: GIFTI_PBIO_R2C_2(char, da->data, dest); break;
2290 case 3: GIFTI_PBIO_R2C_3(char, da->data, dest); break;
2291 case 4: GIFTI_PBIO_R2C_4(char, da->data, dest); break;
2292 case 5: GIFTI_PBIO_R2C_5(char, da->data, dest); break;
2293 case 6: GIFTI_PBIO_R2C_6(char, da->data, dest); break;
2294 }
2295 }
2296 break;
2297 }
2298 case 2: { /* process as short (signed int16) */
2299 if( GIFTI_BAD_SIZEOF(mesg, short, 2) ) return 1;
2300
2301 if( new_ord == GIFTI_IND_ORD_ROW_MAJOR ) {
2302 switch( da->num_dim ) {
2303 default: break; /* do nothing for 1 or unknown */
2304 case 2: GIFTI_PBIO_C2R_2(short, da->data, dest); break;
2305 case 3: GIFTI_PBIO_C2R_3(short, da->data, dest); break;
2306 case 4: GIFTI_PBIO_C2R_4(short, da->data, dest); break;
2307 case 5: GIFTI_PBIO_C2R_5(short, da->data, dest); break;
2308 case 6: GIFTI_PBIO_C2R_6(short, da->data, dest); break;
2309 }
2310 } else { /* to GIFTI_IND_ORD_COL_MAJOR */
2311 switch( da->num_dim ) {
2312 default: break; /* do nothing for 1 or unknown */
2313 case 2: GIFTI_PBIO_R2C_2(short, da->data, dest); break;
2314 case 3: GIFTI_PBIO_R2C_3(short, da->data, dest); break;
2315 case 4: GIFTI_PBIO_R2C_4(short, da->data, dest); break;
2316 case 5: GIFTI_PBIO_R2C_5(short, da->data, dest); break;
2317 case 6: GIFTI_PBIO_R2C_6(short, da->data, dest); break;
2318 }
2319 }
2320 break;
2321 }
2322 case 4: { /* process as int (signed int32) */
2323 if( GIFTI_BAD_SIZEOF(mesg, int, 4) ) return 1;
2324
2325 if( new_ord == GIFTI_IND_ORD_ROW_MAJOR ) {
2326 switch( da->num_dim ) {
2327 default: break; /* do nothing for 1 or unknown */
2328 case 2: GIFTI_PBIO_C2R_2(int, da->data, dest); break;
2329 case 3: GIFTI_PBIO_C2R_3(int, da->data, dest); break;
2330 case 4: GIFTI_PBIO_C2R_4(int, da->data, dest); break;
2331 case 5: GIFTI_PBIO_C2R_5(int, da->data, dest); break;
2332 case 6: GIFTI_PBIO_C2R_6(int, da->data, dest); break;
2333 }
2334 } else { /* to GIFTI_IND_ORD_COL_MAJOR */
2335 switch( da->num_dim ) {
2336 default: break; /* do nothing for 1 or unknown */
2337 case 2: GIFTI_PBIO_R2C_2(int, da->data, dest); break;
2338 case 3: GIFTI_PBIO_R2C_3(int, da->data, dest); break;
2339 case 4: GIFTI_PBIO_R2C_4(int, da->data, dest); break;
2340 case 5: GIFTI_PBIO_R2C_5(int, da->data, dest); break;
2341 case 6: GIFTI_PBIO_R2C_6(int, da->data, dest); break;
2342 }
2343 }
2344 break;
2345 }
2346 case 8: { /* process as long long (signed int64) */
2347 if( GIFTI_BAD_SIZEOF(mesg, long long, 8) ) return 1;
2348
2349 if( new_ord == GIFTI_IND_ORD_ROW_MAJOR ) {
2350 switch( da->num_dim ) {
2351 default: break; /* do nothing for 1 or unknown */
2352 case 2: GIFTI_PBIO_C2R_2(long long, da->data, dest); break;
2353 case 3: GIFTI_PBIO_C2R_3(long long, da->data, dest); break;
2354 case 4: GIFTI_PBIO_C2R_4(long long, da->data, dest); break;
2355 case 5: GIFTI_PBIO_C2R_5(long long, da->data, dest); break;
2356 case 6: GIFTI_PBIO_C2R_6(long long, da->data, dest); break;
2357 }
2358 } else { /* to GIFTI_IND_ORD_COL_MAJOR */
2359 switch( da->num_dim ) {
2360 default: break; /* do nothing for 1 or unknown */
2361 case 2: GIFTI_PBIO_R2C_2(long long, da->data, dest); break;
2362 case 3: GIFTI_PBIO_R2C_3(long long, da->data, dest); break;
2363 case 4: GIFTI_PBIO_R2C_4(long long, da->data, dest); break;
2364 case 5: GIFTI_PBIO_R2C_5(long long, da->data, dest); break;
2365 case 6: GIFTI_PBIO_R2C_6(long long, da->data, dest); break;
2366 }
2367 }
2368 break;
2369 }
2370 }
2371
2372 return 0;
2373 }
2374
2375 /*---------------------------------------------------------------------*/
2376 /*! Allocate and fill the data array with data read from the given
2377 * external file.
2378 *
2379 * return 0 on success
2380 *//*-------------------------------------------------------------------*/
gifti_read_extern_DA_data(giiDataArray * da)2381 int gifti_read_extern_DA_data(giiDataArray * da)
2382 {
2383 FILE * fp;
2384 long long nbytes, nread;
2385
2386 if( !da || !da->ext_fname || !*da->ext_fname ) return 0;
2387
2388 if(G.verb > 4) fprintf(stderr,"-- external read of '%s'\n",da->ext_fname);
2389
2390 if( da->ext_offset < 0 ) {
2391 fprintf(stderr,"** want external DA data with bad offset %lld\n",
2392 da->ext_offset);
2393 return 1;
2394 } else if( da->data ) {
2395 fprintf(stderr,"** want external DA data but data already allocated\n");
2396 return 1;
2397 } else if ( !gifti_valid_dims(da, 1) ) {
2398 fprintf(stderr,"** cannot read external DA data with bad dims...\n");
2399 return 1;
2400 }
2401
2402 /* allocate data */
2403 nbytes = da->nvals * da->nbyper;
2404 da->data = calloc(da->nvals, da->nbyper); /* zero in case of read failure */
2405 if( !da->data ) {
2406 fprintf(stderr,"** failed to alloc %lld bytes for external read\n",
2407 nbytes);
2408 return 1;
2409 }
2410
2411 /* open file, jump to offset and read */
2412 fp = fopen(da->ext_fname, "r");
2413 if( !fp ) {
2414 fprintf(stderr,"** ext read: failed to open '%s'\n",da->ext_fname);
2415 return 1;
2416 }
2417
2418 if( fseek(fp, da->ext_offset, SEEK_SET) ) {
2419 fprintf(stderr,"** ext read: failed to seek to %lld in '%s'\n",
2420 da->ext_offset, da->ext_fname);
2421 fclose(fp); return 1;
2422 }
2423
2424 nread = fread(da->data, sizeof(char), nbytes, fp);
2425 fclose(fp); /* close now in any case */
2426
2427 if( nread != nbytes ) {
2428 fprintf(stderr,"** ext_read: read only %lld of %lld bytes from %s\n",
2429 nread, nbytes, da->ext_fname);
2430 return 1;
2431 }
2432
2433 if(G.verb > 2)
2434 fprintf(stderr,"-- read %lld bytes from external '%s' @ %lld\n",
2435 nbytes, da->ext_fname, da->ext_offset);
2436
2437 return 0;
2438 }
2439
2440 /*---------------------------------------------------------------------*/
2441 /*! Write DA data to the given external file.
2442 *
2443 * Note: the given ext_offset _must_ refer to the current end of file.
2444 *
2445 * return 0 on success
2446 *//*-------------------------------------------------------------------*/
gifti_write_extern_DA_data(giiDataArray * da)2447 int gifti_write_extern_DA_data(giiDataArray * da)
2448 {
2449 FILE * fp;
2450 long long nbytes, nwritten, posn;
2451
2452 if( !da || !da->ext_fname || !*da->ext_fname ) return 0;
2453
2454 if(G.verb > 4) fprintf(stderr,"-- external write to '%s'\n",da->ext_fname);
2455
2456 if( da->ext_offset < 0 ) {
2457 fprintf(stderr,"** bad offset for external DA data write, %lld\n",
2458 da->ext_offset);
2459 return 1;
2460 } else if( !da->data ) {
2461 fprintf(stderr,"** no data for external DA data write\n");
2462 return 1;
2463 } else if ( !gifti_valid_dims(da, 1) ) {
2464 fprintf(stderr,"** cannot write external DA data with bad dims...\n");
2465 return 1;
2466 }
2467
2468 nbytes = da->nvals * da->nbyper;
2469
2470 /* open file for append and verify that the file offset matches this one */
2471 fp = fopen(da->ext_fname, "a+");
2472 if( !fp ) {
2473 fprintf(stderr,"** ext write: failed to open '%s' for append\n",
2474 da->ext_fname);
2475 return 1;
2476 }
2477
2478 /* we should be at the end of the file, which measn posn da->ext_offset */
2479 fseek(fp, 0, SEEK_END); /* append should write to the end, but be sure */
2480 posn = ftell(fp);
2481 if( posn != da->ext_offset ) {
2482 fprintf(stderr,"** ext write: cur posn (%lld) not ext_offset (%lld)"
2483 " in file %s\n", posn, da->ext_offset, da->ext_fname);
2484 fclose(fp); return 1;
2485 }
2486
2487 nwritten = fwrite(da->data, sizeof(char), nbytes, fp);
2488
2489 fclose(fp); /* close now in any case */
2490
2491 if( nwritten != nbytes ) {
2492 fprintf(stderr,"** ext_write: appended only %lld of %lld bytes to %s\n",
2493 nwritten, nbytes, da->ext_fname);
2494 return 1;
2495 }
2496
2497 if(G.verb > 2)
2498 fprintf(stderr,"-- appended %lld bytes to external '%s' @ %lld\n",
2499 nbytes, da->ext_fname, da->ext_offset);
2500
2501 return 0;
2502 }
2503
2504 /*---------------------------------------------------------------------*/
2505 /*! Apply the file list as external files.
2506 *
2507 * The files are assumed to be partitioned by DataArray entries. So
2508 * the list length must divide numDA evenly.
2509 *
2510 * External files are not checked for her, as this is independent of any
2511 * read or write operation.
2512 *
2513 * return 0 on success
2514 *//*-------------------------------------------------------------------*/
gifti_set_extern_filelist(gifti_image * gim,int nfiles,char ** files)2515 int gifti_set_extern_filelist(gifti_image * gim, int nfiles, char ** files)
2516 {
2517 giiDataArray * da;
2518 long long nbytes, offset;
2519 int nper;
2520 int daindex, findex, oindex;
2521
2522 if(!gim || gim->numDA <= 0 || nfiles <= 0 || !files) {
2523 if(G.verb>1) fprintf(stderr,"-- set_extern_filelist: nothing to do\n");
2524 return 1;
2525 }
2526
2527 nper = gim->numDA / nfiles;
2528
2529 if(G.verb>4) fprintf(stderr,"-- set_extern_flist for %d files (nper=%d)\n",
2530 nfiles, nper);
2531
2532 if( nfiles * nper != gim->numDA ) { /* be sure division is integral */
2533 fprintf(stderr,"** Cannot evenly divide %d DataArrays by %d"
2534 " external files\n", gim->numDA, nfiles);
2535 return 1;
2536 }
2537
2538 daindex = 0; /* DataArray index */
2539 for( findex = 0; findex < nfiles; findex++ ) {
2540 if( !files[findex] || !*files[findex] ) {
2541 fprintf(stderr,"** set_extern_flist: missing filename %d\n",findex);
2542 return 1;
2543 }
2544
2545 /* note and check nbytes */
2546 nbytes = gim->darray[daindex]->nvals * gim->darray[daindex]->nbyper;
2547 if( nbytes <= 0 ) {
2548 fprintf(stderr,"** gifti_set_extern_filelist: bad nbytes\n");
2549 return 1;
2550 }
2551
2552 /* within this file, offset will be multiples of nbytes */
2553 for( oindex=0, offset=0; oindex < nper; oindex++, offset += nbytes ) {
2554 da = gim->darray[daindex];
2555
2556 if( nbytes != da->nvals * da->nbyper ) {
2557 fprintf(stderr,"** set_extern_flist: nbytes mismatch at DA[%d]\n"
2558 " (expected %lld, found %lld)\n",
2559 daindex, nbytes, da->nvals * da->nbyper);
2560 return 1;
2561 }
2562
2563 /* set encoding and external file fields */
2564 da->encoding = GIFTI_ENCODING_EXTBIN;
2565 da->ext_fname = gifti_strdup(files[findex]);
2566 da->ext_offset = offset;
2567
2568 daindex++; /* increment DataArray index every time */
2569 }
2570 }
2571
2572 if(G.verb > 2)
2573 fprintf(stderr,"++ set extern file list, %d files, %d DAs per file",
2574 nfiles, nper);
2575
2576 return 0;
2577 }
2578
2579 /*---------------------------------------------------------------------*/
2580 /*! Given a NIFTI_INTENT string, such as "NIFTI_INTENT_NODE_INDEX",
2581 * return the corresponding integral intent code. The intent code is
2582 * the macro value defined in nifti1.h.
2583 *
2584 * return 0 on failure (NIFTI_INTENT_NONE)
2585 *//*-------------------------------------------------------------------*/
gifti_intent_from_string(const char * name)2586 int gifti_intent_from_string( const char * name )
2587 {
2588 int tablen = sizeof(gifti_intent_list)/sizeof(gifti_intent_ele);
2589 int c;
2590
2591 if( !name ) return 0;
2592
2593 for( c = tablen-1; c > 0; c-- )
2594 if( !strcmp(name, gifti_intent_list[c].name) )
2595 break;
2596
2597 return gifti_intent_list[c].code;
2598 }
2599
2600
2601 /*---------------------------------------------------------------------*/
2602 /*! Given a NIFTI_TYPE value, such as NIFTI_TYPE_INT16, return the
2603 * corresponding macro label as a string. The dtype code is the
2604 * macro value defined in nifti1.h.
2605 *//*-------------------------------------------------------------------*/
gifti_intent_to_string(int code)2606 char * gifti_intent_to_string( int code )
2607 {
2608 int tablen = sizeof(gifti_intent_list)/sizeof(gifti_intent_ele);
2609 int c;
2610
2611 for( c = tablen-1; c > 0; c-- )
2612 if( gifti_intent_list[c].code == code )
2613 break;
2614
2615 return gifti_intent_list[c].name;
2616 }
2617
2618
2619 /*---------------------------------------------------------------------*/
2620 /*! Return whether the given code is a valid NIFTI_INTENT code.
2621 *//*-------------------------------------------------------------------*/
gifti_intent_is_valid(int code)2622 int gifti_intent_is_valid( int code )
2623 {
2624 int tablen = sizeof(gifti_intent_list)/sizeof(gifti_intent_ele);
2625 int c;
2626
2627 for( c = tablen-1; c > 0; c-- )
2628 if( gifti_intent_list[c].code == code )
2629 break;
2630
2631 return( c >= 0 );
2632 }
2633
2634
2635 /*---------------------------------------------------------------------*/
2636 /*! duplicate the given string
2637 *//*-------------------------------------------------------------------*/
gifti_strdup(const char * src)2638 char * gifti_strdup( const char * src )
2639 {
2640 char * newstr;
2641 int len;
2642
2643 if( !src ) return NULL; /* easy case */
2644
2645 len = strlen(src) + 1;
2646
2647 newstr = (char *)malloc(len * sizeof(char));
2648 if( !newstr ) {
2649 fprintf(stderr,"** failed gifti_strdup, len = %d\n", len);
2650 return NULL;
2651 }
2652
2653 strcpy(newstr, src);
2654
2655 return newstr;
2656 }
2657
2658 /*---------------------------------------------------------------------*/
2659 /*! duplicate the given giiDataArray struct, optionally including data
2660 *
2661 * Allocate for a new struct, and fill it so that the contents are
2662 * identical (sans pointers) to orig. Sub-structure arrays will need
2663 * to be allocated, also.
2664 *
2665 * If get_data is not set, gnew->data will be left as NULL.
2666 *
2667 * return the address of the newly allocated structure
2668 *//*-------------------------------------------------------------------*/
gifti_copy_DataArray(const giiDataArray * orig,int get_data)2669 giiDataArray * gifti_copy_DataArray(const giiDataArray * orig, int get_data)
2670 {
2671 giiDataArray * gnew;
2672 int c;
2673
2674 if( ! orig ){ fprintf(stderr,"** copy_DA: input is NULL\n"); return NULL; }
2675
2676 if(G.verb > 5) fprintf(stderr,"++ copying giiDataArray...\n");
2677
2678 gnew = (giiDataArray *)calloc(1, sizeof(giiDataArray));
2679 if(!gnew){fprintf(stderr,"** copy_DA, failed to alloc DA\n"); return NULL;}
2680
2681 /* cheat - start by copying the entire struct contents */
2682 *gnew = *orig;
2683
2684 /* copy any pointer data or structures */
2685 gnew->ext_fname = gifti_strdup(orig->ext_fname);
2686 gifti_copy_nvpairs(&gnew->meta, &orig->meta);
2687 if( orig->numCS > 0 && orig->coordsys ) {
2688 gnew->coordsys = (giiCoordSystem **)malloc(gnew->numCS *
2689 sizeof(giiCoordSystem *));
2690 if(!gnew->coordsys) {
2691 fprintf(stderr,"** copy_DA: failed to alloc %d CS pointers\n",
2692 gnew->numCS);
2693 gnew->numCS = 0;
2694 } else
2695 for( c = 0; c < gnew->numCS; c++ )
2696 gnew->coordsys[c] = gifti_copy_CoordSystem(orig->coordsys[c]);
2697 }
2698
2699 /* maybe the needy user wants data, too */
2700 if(orig->data && get_data) {
2701 if(G.verb > 5) fprintf(stderr,"++ copy_DA, adding data\n");
2702 gnew->data = malloc(gnew->nvals * gnew->nbyper);
2703 if(!gnew->data) /* continue? */
2704 fprintf(stderr,"** copy DA, failed to alloc %lld bytes for data\n",
2705 gnew->nvals * gnew->nbyper);
2706 memcpy(gnew->data, orig->data, gnew->nvals * gnew->nbyper);
2707 } else
2708 gnew->data = NULL;
2709
2710 /* last and certainly least, ex_atrs */
2711 gifti_copy_nvpairs(&gnew->ex_atrs, &orig->ex_atrs);
2712
2713 return gnew;
2714 }
2715
2716 /*---------------------------------------------------------------------*/
2717 /*! dupliate the giiCoordSystem struct (passing NULL is okay)
2718 *//*-------------------------------------------------------------------*/
gifti_copy_CoordSystem(const giiCoordSystem * src)2719 giiCoordSystem * gifti_copy_CoordSystem(const giiCoordSystem * src)
2720 {
2721 giiCoordSystem * csnew;
2722 int r, c;
2723
2724 if( !src ) return NULL; /* this may be okay */
2725
2726 if( G.verb > 6 ) fprintf(stderr,"++ copy_CS\n");
2727
2728 csnew = (giiCoordSystem *)malloc(sizeof(giiCoordSystem));
2729 if( !csnew ){ fprintf(stderr,"** copy_CS: failed alloc\n"); return NULL; }
2730
2731 csnew->dataspace = gifti_strdup(src->dataspace);
2732 csnew->xformspace = gifti_strdup(src->xformspace);
2733
2734 for( r = 0; r < 4; r++ )
2735 for( c = 0; c < 4; c++ )
2736 csnew->xform[r][c] = src->xform[r][c];
2737
2738 return csnew;
2739 }
2740
2741 /*---------------------------------------------------------------------*/
2742 /*! dupliate the contents of the giiLabelTable struct
2743 *//*-------------------------------------------------------------------*/
gifti_copy_LabelTable(giiLabelTable * dest,const giiLabelTable * src)2744 int gifti_copy_LabelTable(giiLabelTable * dest, const giiLabelTable * src)
2745 {
2746 int c;
2747
2748 if( !src || !dest ) {
2749 fprintf(stderr,"** copy_LabelTable: bad params (%p,%p)\n",
2750 (void *)src, (void *)dest);
2751 return 1;
2752 }
2753
2754 if( G.verb > 6 ) fprintf(stderr,"++ copy_LT\n");
2755
2756 /* quick case: empty table */
2757 if( src->length <= 0 ) return gifti_clear_LabelTable(dest);
2758
2759 /* otherwise, allocate and copy lists */
2760 dest->length = src->length;
2761
2762 dest->key = (int *)malloc(dest->length * sizeof(int));
2763 dest->label = (char **)malloc(dest->length * sizeof(char *));
2764 if( src->rgba )
2765 dest->rgba = (float *)malloc(dest->length * 4 * sizeof(float));
2766
2767 /* check for failure */
2768 if( !dest->key || !dest->label || (src->rgba && !dest->rgba) ) {
2769 fprintf(stderr,"** failed to dup label arrays of length %d\n",
2770 dest->length);
2771 gifti_free_LabelTable(dest);
2772 return 1;
2773 }
2774
2775 /* copy any rgba list */
2776 if( dest->rgba )
2777 memcpy(dest->rgba, src->rgba, dest->length * 4 * sizeof(float));
2778
2779 /* copy indices */
2780 for( c = 0; c < dest->length; c++ )
2781 dest->key[c] = src->key[c];
2782
2783 /* copy labels */
2784 for( c = 0; c < dest->length; c++ )
2785 dest->label[c] = gifti_strdup(src->label[c]);
2786
2787 return 0;
2788 }
2789
2790 /*---------------------------------------------------------------------*/
2791 /*! dupliate the contents of one nvpairs structure into an empty one
2792 *
2793 * return 0 on success
2794 *//*-------------------------------------------------------------------*/
gifti_copy_nvpairs(nvpairs * dest,const nvpairs * src)2795 int gifti_copy_nvpairs(nvpairs * dest, const nvpairs * src)
2796 {
2797 if( !dest || !src ){
2798 fprintf(stderr,"** copy_NVP, bad params (%p,%p)\n",
2799 (void*)dest,(void*)src);
2800 return 1;
2801 }
2802
2803 if( G.verb > 6 ) fprintf(stderr,"++ copy_nvp, length %d\n", src->length);
2804
2805 /* check for a simple case */
2806 if( src->length <= 0 || !src->name || !src->value ) {
2807 dest->length = 0;
2808 dest->name = dest->value = NULL;
2809 return 0;
2810 }
2811
2812 /* else, copy the lists */
2813 dest->length = src->length;
2814 dest->name = gifti_copy_char_list(src->name, src->length);
2815 dest->value = gifti_copy_char_list(src->value, src->length);
2816
2817 return 0;
2818 }
2819
2820 /*---------------------------------------------------------------------*/
2821 /*! dupliate the list of strings
2822 *//*-------------------------------------------------------------------*/
gifti_copy_char_list(char ** list,int len)2823 char ** gifti_copy_char_list(char ** list, int len)
2824 {
2825 char ** newlist = NULL;
2826 int c;
2827
2828 if( !list || len <= 0 ) return NULL;
2829
2830 newlist = (char **)malloc(len * sizeof(char *));
2831 if( !newlist ) {
2832 fprintf(stderr,"** copy_char_list fails for %d pointers\n", len);
2833 return NULL;
2834 }
2835
2836 for( c = 0; c < len; c++) /* big finish */
2837 newlist[c] = gifti_strdup(list[c]);
2838
2839 return newlist;
2840 }
2841
2842 /*---------------------------------------------------------------------*/
2843 /*! copy any GIFTI MetaData named 'name' from dest to src (replace old)
2844 *
2845 * return 0 on success, 1 on failure to find, -1 on error
2846 *//*-------------------------------------------------------------------*/
gifti_copy_gifti_meta(gifti_image * dest,gifti_image * src,const char * name)2847 int gifti_copy_gifti_meta(gifti_image * dest, gifti_image * src,
2848 const char * name)
2849 {
2850 char * value;
2851
2852 if( !dest || !src || !name ) {
2853 if( G.verb > 0 )
2854 fprintf(stderr,"** copy_gifti_meta: bad params(%p,%p,%p)\n",
2855 (void *)dest, (void *)src, name);
2856 return -1;
2857 }
2858
2859 value = gifti_get_meta_value(&src->meta, name);
2860 if( !value ) {
2861 if( G.verb > 4 )
2862 fprintf(stderr,"-- GCGM: did not find meta name '%s'\n", name);
2863 return 1;
2864 }
2865
2866 return gifti_add_to_meta(&dest->meta, name, value, 1);
2867 }
2868
2869 /*---------------------------------------------------------------------*/
2870 /*! copy any DataArray MetaData named 'name' from dest to src (replace old)
2871 * (apply to list of DAs, or to all)
2872 *
2873 * return 0 on success, 1 on failure to find, -1 on error
2874 *//*-------------------------------------------------------------------*/
gifti_copy_DA_meta_many(gifti_image * dest,gifti_image * src,const char * name,const int * dalist,int len)2875 int gifti_copy_DA_meta_many(gifti_image * dest, gifti_image * src,
2876 const char * name, const int * dalist, int len)
2877 {
2878 int c, index, use_list, numDA, rv = 0;
2879
2880 if( !dest || !dest->darray || !src || !src->darray || !name ) {
2881 if( G.verb > 1 ) fprintf(stderr,"** GCDAMM: bad params\n");
2882 return -1;
2883 }
2884
2885 /* if they are not equal, it is probably a user mistake to be here */
2886 if( dest->numDA != src->numDA ) {
2887 if(G.verb>0) fprintf(stderr,"-- cannot copy DA meta, numDA %d != %d\n",
2888 src->numDA, dest->numDA);
2889 return -1;
2890 }
2891
2892 /* the empty case is probably not an error */
2893 if( dest->numDA <= 0 || src->numDA <= 0 ) {
2894 if( G.verb > 4 ) fprintf(stderr,"-- GCDAMM: numDA %d, %d\n",
2895 src->numDA, dest->numDA);
2896 return 0;
2897 }
2898
2899 /* decide whether to use dalist or all DAs */
2900 use_list = gifti_valid_int_list(dalist, len, 0, src->numDA-1, G.verb);
2901
2902 if( use_list && G.verb > 2 )
2903 fprintf(stderr,"++ copy_DA_meta_many, %s (list length %d)\n",
2904 use_list ? "DA in list" : "all DAs", len);
2905
2906 /* finally, get to work */
2907 numDA = use_list ? len : src->numDA;
2908 for( c = 0; c < numDA; c++ ) {
2909 index = use_list ? dalist[c] : c; /* choose appropriate DA index */
2910
2911 /* note any failures */
2912 rv |= gifti_copy_DA_meta(dest->darray[index], src->darray[index], name);
2913 }
2914
2915 return rv;
2916 }
2917
2918 /*---------------------------------------------------------------------*/
2919 /*! copy any DataArray MetaData named 'name' from dest to src (replace old)
2920 *
2921 * return 0 on success, 1 on failure to find, -1 on error
2922 *//*-------------------------------------------------------------------*/
gifti_copy_DA_meta(giiDataArray * dest,giiDataArray * src,const char * name)2923 int gifti_copy_DA_meta(giiDataArray *dest, giiDataArray *src, const char *name)
2924 {
2925 char * value;
2926
2927 if( !dest || !src || !name ) {
2928 if( G.verb > 0 )
2929 fprintf(stderr,"** copy_DA_meta: bad params(%p,%p,%p)\n",
2930 (void *)dest, (void *)src, name);
2931 return -1;
2932 }
2933
2934 value = gifti_get_meta_value(&src->meta, name);
2935 if( !value ) {
2936 if( G.verb > 4 )
2937 fprintf(stderr,"-- GCDAM: did not find meta name '%s'\n", name);
2938 return 1;
2939 }
2940
2941 return gifti_add_to_meta(&dest->meta, name, value, 1);
2942 }
2943
2944 /*---------------------------------------------------------------------*/
2945 /*! copy ALL DataArray MetaData from dest to src (replace old)
2946 *
2947 * return 0 on success, 1 on failure to find, -1 on error
2948 *//*-------------------------------------------------------------------*/
gifti_copy_all_DA_meta(giiDataArray * dest,giiDataArray * src)2949 int gifti_copy_all_DA_meta(giiDataArray *dest, giiDataArray *src)
2950 {
2951 int c, rv = 0;
2952
2953 if( !dest || !src ) {
2954 if( G.verb > 0 )
2955 fprintf(stderr,"** copy_all_DA_meta: bad params(%p,%p)\n",
2956 (void *)dest, (void *)src);
2957 return -1;
2958 }
2959
2960 for( c = 0; c < src->meta.length; c++ )
2961 rv |= gifti_copy_DA_meta(dest, src, src->meta.name[c]);
2962
2963 return rv;
2964 }
2965
2966 /*---------------------------------------------------------------------*/
2967 /*! find any differences between the two images
2968 *
2969 * verb 0-3 = quiet, state diff, state per DA, state all diffs
2970 *
2971 * return 0 if they are the same, 1 if they differ
2972 *//*-------------------------------------------------------------------*/
gifti_compare_gifti_images(const gifti_image * g1,const gifti_image * g2,int comp_data,int verb)2973 int gifti_compare_gifti_images(const gifti_image * g1, const gifti_image * g2,
2974 int comp_data, int verb)
2975 {
2976 int diffs = 0, data_diffs = 0, gdiffs = 0, c, rv, numDA;
2977 int lverb = verb; /* possibly override passed 'verb' */
2978
2979 if( G.verb > lverb ) lverb = G.verb;
2980
2981 if( !g1 || !g2 ) {
2982 if( !g1 && !g2 ) return 0; /* both NULL means equal */
2983
2984 if(lverb) printf("-- gifti_images differ (exactly one is NULL)\n");
2985 return 1;
2986 }
2987
2988 /* check main structs */
2989 if( gifti_compare_gims_only(g1, g2, lverb) ) {
2990 if( lverb > 0 ) printf("++ gifti_images differ\n");
2991 if( lverb < 2 ) return 1; /* all we need to know */
2992 gdiffs++;
2993 }
2994
2995 /* get min numDA, just to be safe */
2996 numDA = g1->numDA < g2->numDA ? g1->numDA : g2->numDA;
2997 for( c = 0; c < numDA; c++ ) {
2998 rv = gifti_compare_DA_pair(g1->darray[c],g2->darray[c],comp_data,lverb);
2999 if( rv ) {
3000 diffs++;
3001 if( rv & 2 ) data_diffs++;
3002 if( lverb < 2 ) break;
3003 printf("++ DataArray[%d] - difference (data %s)\n",
3004 c, ! comp_data ? "untested" :
3005 data_diffs ? "differs" : "identical");
3006 }
3007 }
3008
3009 if( diffs && lverb > 0 )
3010 printf("-- differences found in %d of %d DAs\n", diffs, numDA);
3011
3012 /* state data diffs separately */
3013 if( lverb > 2 && comp_data ) {
3014 if( ! data_diffs ) printf("-- no data differences found\n");
3015 else printf("-- data differences found in %d of %d DAs\n",
3016 data_diffs, numDA);
3017 }
3018
3019 if( diffs || gdiffs ) return 1;
3020 return 0;
3021 }
3022
3023 /*---------------------------------------------------------------------*/
3024 /*! find any differences between the two sets of image data
3025 *
3026 * verb 0-2+ = quiet, state diff, state per DA
3027 *
3028 * return 0 if they are the same, 1 if they differ
3029 *//*-------------------------------------------------------------------*/
gifti_compare_gifti_data(const gifti_image * g1,const gifti_image * g2,int verb)3030 int gifti_compare_gifti_data(const gifti_image * g1, const gifti_image * g2,
3031 int verb)
3032 {
3033 int lverb = verb, c, diffs = 0, numDA;
3034
3035 if( G.verb > lverb ) lverb = G.verb;
3036
3037 if( !g1 || !g2 ) {
3038 if( !g1 && !g2 ) return 0; /* both NULL means equal */
3039 if(lverb) printf("-- gim data difference (exactly one gim is NULL)\n");
3040 return 1;
3041 }
3042
3043 /* if numDA does not match, they differ */
3044 if( g1->numDA != g2->numDA ) {
3045 if( lverb > 0 )
3046 printf("-- gim data differs: numDA differs, %d vs. %d\n",
3047 g1->numDA, g2->numDA);
3048 if( lverb < 2 ) return 1;
3049 }
3050
3051 /* even if they differ, we may want to continue, so use minimum */
3052 numDA = g1->numDA < g2->numDA ? g1->numDA : g2->numDA;
3053 for( c = 0; c < numDA; c++ ) {
3054 if( gifti_compare_DA_data(g1->darray[c],g2->darray[c],lverb) ) {
3055 diffs++;
3056 if( lverb > 0 ) printf("++ data difference at DataArray[%d]\n", c);
3057 if( lverb < 2 ) return 1;
3058 }
3059 }
3060
3061 if( diffs ) { /* verb must be 2, so print */
3062 printf("-- found data diffs in %d DataArrays\n", diffs);
3063 return 1;
3064 }
3065
3066 if( G.verb > 1 ) fprintf(stderr,"-- no data diffs found\n");
3067
3068 return 0;
3069 }
3070
gifti_compare_DA_data(const giiDataArray * d1,const giiDataArray * d2,int verb)3071 int gifti_compare_DA_data(const giiDataArray * d1, const giiDataArray * d2,
3072 int verb)
3073 {
3074 long long nbytes, offset;
3075
3076 if( !d1 || !d2 ) {
3077 if( !d1 && !d2 ) return 0; /* both NULL means equal */
3078 if(verb>1) printf("-- DA data difference (exactly one DA is NULL)\n");
3079 return 1;
3080 }
3081
3082 if( ! gifti_valid_dims(d1,verb>1) || ! gifti_valid_dims(d2,verb>1) ) {
3083 if(verb>1) printf("-- DA data diff: dims are not valid\n");
3084 return 1;
3085 }
3086
3087 nbytes = d1->nvals * d1->nbyper;
3088 if( nbytes != (d2->nvals * d2->nbyper) ) {
3089 if(verb>1) printf("-- DA data diff: nbytes differs, %lld vs. %lld\n",
3090 nbytes, d2->nvals * d2->nbyper);
3091 return 1;
3092 }
3093
3094 /* okay, let's test the data */
3095 offset = gifti_compare_raw_data(d1->data,d2->data,nbytes);
3096
3097 if ( offset >= 0 ) { /* difference in data */
3098 if(verb > 1) printf("-- diff in DA data at posn %lld\n",
3099 offset/d1->nbyper);
3100 return 1;
3101 }
3102
3103 return 0;
3104 }
3105
3106 /* compare everything but darray
3107 * (for diffs, only print if verb > 1)
3108 */
gifti_compare_gims_only(const gifti_image * g1,const gifti_image * g2,int verb)3109 int gifti_compare_gims_only(const gifti_image * g1, const gifti_image * g2,
3110 int verb)
3111 {
3112 int diffs = 0;
3113 int lverb = verb; /* possibly override passed 'verb' */
3114
3115 if( G.verb > lverb ) lverb = G.verb;
3116
3117 if( !g1 || !g2 ) {
3118 if( !g1 && !g2 ) return 0; /* equal */
3119 if( lverb > 1 )
3120 printf("-- comp gifti ims: have NULL %p, %p\n",(void*)g1,(void*)g2);
3121 return 1; /* not equal */
3122 }
3123
3124 if( g1->numDA != g2->numDA ) {
3125 diffs++;
3126 if( lverb > 1 )
3127 fprintf(stderr,"-- diff in GIFTI numDA: %d vs %d\n",
3128 g1->numDA, g2->numDA);
3129 if( lverb <= 1 ) return 1;
3130 }
3131
3132 if( !g1->version || !g2->version ) { /* handle at least one NULL */
3133 if( g1->version || g2->version ) {
3134 diffs++;
3135 if( lverb > 1 )
3136 fprintf(stderr,"-- diff in GIFTI version: one is NULL\n");
3137 if( lverb <= 1 ) return 1;
3138 }
3139 /* else both NULL, which means equal */
3140 } else if ( strcmp(g1->version, g2->version) ) {
3141 diffs++;
3142 if( lverb > 1 )
3143 fprintf(stderr,"-- diff in GIFTI version: %s vs. %s\n",
3144 g1->version, g2->version);
3145 if( lverb <= 1 ) return 1;
3146 }
3147
3148 if( gifti_compare_labeltable(&g1->labeltable, &g2->labeltable, verb) ) {
3149 diffs++;
3150 if( lverb > 1 ) printf("-- diff in gifti labeltable\n");
3151 if( lverb <= 1 ) return 1;
3152 }
3153
3154 if( gifti_compare_nvpairs(&g1->meta, &g2->meta, verb) ) {
3155 diffs++;
3156 if( lverb > 1 ) printf("-- diff in gifti meta\n");
3157 if( lverb <= 1 ) return 1;
3158 }
3159
3160
3161 if( g1->swapped != g2->swapped ) {
3162 diffs++;
3163 if( lverb > 1 )
3164 fprintf(stderr,"-- difference in GIM->swapped: %d vs %d\n",
3165 g1->swapped, g2->swapped);
3166 if( lverb <= 1 ) return 1;
3167 }
3168
3169 if( g1->compressed != g2->compressed ) {
3170 diffs++;
3171 if( lverb > 1 )
3172 fprintf(stderr,"-- difference in GIM->compressed: %d vs %d\n",
3173 g1->compressed, g2->compressed);
3174 if( lverb <= 1 ) return 1;
3175 }
3176
3177 if( gifti_compare_nvpairs(&g1->ex_atrs, &g2->ex_atrs, verb) ) {
3178 diffs++;
3179 if( lverb > 1 ) printf("-- diff in gifti ex_atrs\n");
3180 if( lverb <= 1 ) return 1;
3181 }
3182
3183 return diffs;
3184 }
3185
3186 /*! return 0 if equal, 1 if diffs, 2 if data diffs (and 3 if both diffs) */
gifti_compare_DA_pair(const giiDataArray * d1,const giiDataArray * d2,int comp_data,int verb)3187 int gifti_compare_DA_pair(const giiDataArray * d1, const giiDataArray * d2,
3188 int comp_data, int verb)
3189 {
3190 long long offset;
3191 int c, top, diffs = 0, data_diffs = 0;
3192 int lverb = verb; /* possibly override passed 'verb' */
3193
3194 if( G.verb > lverb ) lverb = G.verb;
3195
3196 if( !d1 || !d2 ) {
3197 if( !d1 && !d2 ) return 0; /* equal */
3198 if(lverb>2)
3199 printf("-- comp DA: have NULL: %p, %p\n", (void*)d1,(void*)d2);
3200 return 3; /* not equal */
3201 }
3202
3203 if( d1->intent != d2->intent ) {
3204 diffs = 1;
3205 if( lverb > 1 )
3206 printf("-- diff in DA intent: %d (%s) vs. %d (%s)\n",
3207 d1->intent, gifti_intent_to_string(d1->intent),
3208 d2->intent, gifti_intent_to_string(d2->intent));
3209 if( lverb < 3 ) return 1;
3210 }
3211
3212 if( d1->datatype != d2->datatype ) {
3213 diffs = 1;
3214 if( lverb > 1 )
3215 printf("-- diff in DA datatype: %d (%s) vs. %d (%s)\n",
3216 d1->datatype, gifti_datatype2str(d1->datatype),
3217 d2->datatype, gifti_datatype2str(d2->datatype));
3218 if( lverb < 3 ) return 1;
3219 }
3220
3221 if( d1->ind_ord != d2->ind_ord ) {
3222 diffs = 1;
3223 if( lverb > 1 )
3224 printf("-- diff in DA ind_ord: %d (%s) vs. %d (%s)\n",
3225 d1->ind_ord,
3226 gifti_list_index2string(gifti_index_order_list, d1->ind_ord),
3227 d2->ind_ord,
3228 gifti_list_index2string(gifti_index_order_list, d2->ind_ord));
3229 if( lverb < 3 ) return 1;
3230 }
3231
3232 if( d1->num_dim != d2->num_dim ) {
3233 diffs = 1;
3234 data_diffs = 1;
3235 if( lverb > 1 )
3236 printf("-- diff in DA num_dim: %d vs. %d\n",
3237 d1->num_dim, d2->num_dim );
3238 if( lverb < 3 ) return 3;
3239 }
3240
3241 /* get minimum num_dim */
3242 top = d1->num_dim < d2->num_dim ? d1->num_dim : d2->num_dim;
3243 for( c = 0; c < top; c++ ) if( d1->dims[c] != d2->dims[c] ) break;
3244 if( c < top ) {
3245 diffs = 1;
3246 data_diffs = 1;
3247 if( lverb > 1 ) {
3248 printf("-- diff in DA dims (length %d)\n ", top);
3249 gifti_disp_raw_data(d1->dims, NIFTI_TYPE_INT32, top, 0, stdout);
3250 printf(" vs ");
3251 gifti_disp_raw_data(d2->dims, NIFTI_TYPE_INT32, top, 1, stdout);
3252 }
3253 if( lverb < 3 ) return 3;
3254 }
3255
3256 if( d1->encoding != d2->encoding ) {
3257 diffs = 1;
3258 if( lverb > 1 )
3259 printf("-- diff in DA encoding: %d (%s) vs. %d (%s)\n",
3260 d1->encoding,
3261 gifti_list_index2string(gifti_encoding_list, d1->encoding),
3262 d2->encoding,
3263 gifti_list_index2string(gifti_encoding_list, d2->encoding));
3264 if( lverb < 3 ) return 1;
3265 }
3266
3267 if( d1->endian != d2->endian ) {
3268 diffs = 1;
3269 if( lverb > 1 )
3270 printf("-- diff in DA endian: %d (%s) vs. %d (%s)\n",
3271 d1->endian,
3272 gifti_list_index2string(gifti_endian_list, d1->endian),
3273 d2->endian,
3274 gifti_list_index2string(gifti_endian_list, d2->endian));
3275 if( lverb < 3 ) return 1;
3276 }
3277
3278 if( d1->ext_fname || d2->ext_fname ) {
3279 if( ! d1->ext_fname || !d2->ext_fname ||
3280 strcmp(d1->ext_fname, d2->ext_fname) ) {
3281 diffs = 1;
3282 if( lverb > 1 )
3283 printf("-- diff in DA ext_fname: %s vs. %s\n",
3284 G_CHECK_NULL_STR(d1->ext_fname),
3285 G_CHECK_NULL_STR(d2->ext_fname));
3286 if( lverb < 3 ) return 1;
3287 }
3288 }
3289
3290 if( d1->ext_offset != d2->ext_offset ) {
3291 diffs = 1;
3292 if( lverb > 1 )
3293 printf("-- diff in DA ext_offset: %lld vs. %lld\n",
3294 d1->ext_offset, d2->ext_offset);
3295 if( lverb < 3 ) return 1;
3296 }
3297
3298 if( gifti_compare_nvpairs(&d1->meta, &d2->meta, verb) ) {
3299 diffs = 1;
3300 if( lverb > 1 ) printf("-- diff in DA meta\n");
3301 if( lverb < 3 ) return 1;
3302 }
3303
3304 if( d1->numCS != d2->numCS ) {
3305 diffs = 1;
3306 if( lverb > 1 ) printf("-- diff in DA numCS\n");
3307 if( lverb < 3 ) return 1;
3308 }
3309
3310 /* compare each of the CoordSystem structs */
3311 top = d1->numCS < d2->numCS ? d1->numCS : d2->numCS;
3312 for( c = 0; c < top; c++ )
3313 if( gifti_compare_coordsys(d1->coordsys[c], d2->coordsys[c],1,verb) ) {
3314 diffs = 1;
3315 if( lverb > 1 ) printf("-- diff in DA coordsys[%d]\n", c);
3316 if( lverb < 3 ) return 1;
3317 }
3318
3319 if( d1->nvals != d2->nvals ) {
3320 diffs = 1;
3321 data_diffs = 1;
3322 if( lverb > 1 )
3323 printf("-- diff in DA nvals: %lld vs. %lld\n",
3324 d1->nvals, d2->nvals);
3325 if( lverb < 3 ) return 3;
3326 }
3327
3328 if( d1->nbyper != d2->nbyper ) {
3329 diffs = 1;
3330 data_diffs = 1;
3331 if( lverb > 1 )
3332 printf("-- diff in DA nbyper: %d vs. %d\n", d1->nbyper, d2->nbyper);
3333 if( lverb < 3 ) return 3;
3334 }
3335
3336 if( gifti_compare_nvpairs(&d1->ex_atrs, &d2->ex_atrs, verb) ) {
3337 diffs = 1;
3338 if( lverb > 1 ) printf("-- diff in DA ex_atrs\n");
3339 if( lverb < 3 ) return 1;
3340 }
3341
3342 /* check data last, and only if no data diffs and dims are valid */
3343 /* (set the 2^1 bit for a data diff) */
3344 if( comp_data && !data_diffs && gifti_valid_dims(d1, 0) ) {
3345 offset = gifti_compare_raw_data(d1->data,d2->data,d1->nvals*d1->nbyper);
3346 if ( offset >= 0 ) {
3347 diffs |= 2;
3348 if(lverb>1) printf("-- diff in DA data at position %lld\n",
3349 offset/d1->nbyper);
3350 if(lverb<3) return 3;
3351 }
3352 }
3353
3354 return diffs;
3355 }
3356
3357 /*---------------------------------------------------------------------*/
3358 /*! return 1 if gifti_images are approximately equal (from a data standpoint)
3359 * note: return value is opposite from gifti_compare_gifti_images
3360 *
3361 * verb 0-3 = quiet, state diff, state per DA, state all diffs
3362 *
3363 * compare information close to the data:
3364 * - numDA
3365 * - labeltable
3366 * - darray elements (pairwise)
3367 * ignore version, meta, swapped, encoding, endian, ext_*, ex_atrs, etc.
3368 *
3369 * return 1 if they are approximately the same, 0 if otherwise
3370 *//*-------------------------------------------------------------------*/
gifti_approx_gifti_images(const gifti_image * g1,const gifti_image * g2,int comp_data,int verb)3371 int gifti_approx_gifti_images(const gifti_image * g1, const gifti_image * g2,
3372 int comp_data, int verb)
3373 {
3374 int diffs = 0, c, numDA;
3375 int lverb = verb; /* possibly override passed 'verb' */
3376
3377 if( G.verb > lverb ) lverb = G.verb;
3378
3379 if( !g1 || !g2 ) {
3380 if( !g1 && !g2 ) return 1; /* both NULL means equal */
3381
3382 if(lverb) printf("-- gifti_images not approx (exactly one is NULL)\n");
3383 return 0;
3384 }
3385
3386 if( g1->numDA != g2->numDA ) {
3387 if( lverb ) printf("-- gifti_images differ in numDA\n");
3388 if( lverb < 2 ) return 0;
3389 diffs++;
3390 }
3391
3392 if( ! gifti_approx_labeltables(&g1->labeltable, &g2->labeltable, lverb) ) {
3393 if( lverb ) printf("-- gifti labeltables not approx. equal\n");
3394 if( lverb < 2 ) return 0;
3395 diffs++;
3396 }
3397
3398 /* get min numDA, just to be safe */
3399 numDA = g1->numDA < g2->numDA ? g1->numDA : g2->numDA;
3400 for( c = 0; c < numDA; c++ ) {
3401 if( !gifti_approx_DA_pair(g1->darray[c],g2->darray[c],comp_data,lverb)){
3402 diffs++;
3403 if(lverb) printf("++ DataArrays[%d] - not approximately equal\n",c);
3404 if( lverb < 2 ) break;
3405 }
3406 }
3407
3408 if( diffs && lverb > 0 ) printf("-- GIFTI: approx diffs found\n");
3409
3410 return ! diffs;
3411 }
3412
3413 /* ------------------------------------------------------------------------- */
3414 /*! return 1 if DAs are approximately equal (opposite of compare functions)
3415 *
3416 * test for difference in:
3417 *
3418 * transformation matrices : 16 values each (approx)
3419 * coordinates : 3 values per node (approx)
3420 * triangles : exact (starting node can be any of the 3)
3421 * data : approx
3422 *
3423 * lverb = 0 : no print (no print anywhere)
3424 * 1 : no print (print at higher level)
3425 * 2 : print DA level diff
3426 * 3 : print all diffs
3427 *
3428 */
gifti_approx_DA_pair(const giiDataArray * d1,const giiDataArray * d2,int comp_data,int verb)3429 int gifti_approx_DA_pair(const giiDataArray * d1, const giiDataArray * d2,
3430 int comp_data, int verb)
3431 {
3432 int c, top, can_comp, offset, diffs = 0;
3433 int lverb = verb; /* possibly override passed 'verb' */
3434
3435 if( G.verb > lverb ) lverb = G.verb;
3436
3437 /* deal with any NULLs for starter */
3438 if( !d1 && !d2 ) {
3439 if(lverb>2) printf("-- approx DA: have NULL\n");
3440 return 1; /* yes, these are equal */
3441 } else if( !d1 || !d2 ) {
3442 if(lverb>2) printf("-- approx DA: have one NULL\n");
3443 return 0; /* not approximately equal */
3444 }
3445
3446 /* do early, to put higher level whining first */
3447 can_comp = can_compare_DA_data(d1, d2, verb);
3448
3449 if( d1->numCS != d2->numCS ) {
3450 diffs = 1;
3451 if( lverb > 1 ) printf("-- approx DA: diff in numCS\n");
3452 if( lverb < 3 ) return 0;
3453 }
3454
3455 /* compare each of the CoordSystem structs */
3456 top = d1->numCS < d2->numCS ? d1->numCS : d2->numCS;
3457 for( c = 0; c < top; c++ ) {
3458 /* first compare without checking the data */
3459 if( gifti_compare_coordsys(d1->coordsys[c], d2->coordsys[c],1,verb) ) {
3460 diffs = 1;
3461 if( lverb > 1 ) printf("-- diff in DA coordsys[%d]\n", c);
3462 if( lverb < 3 ) return 0;
3463 }
3464 }
3465
3466 /* if we cannot or do not want to compare the data, return */
3467 if( ! comp_data || ! can_comp ) return !diffs;
3468
3469 /* if data is coordinates, compare percent diff
3470 * if trianges, compare exactly, but with any starting index
3471 * else, compare percent diff */
3472 if( d1->intent == d2->intent && d1->intent==NIFTI_INTENT_TRIANGLE ) {
3473 /* verify that these look like triangles */
3474 if( d1->num_dim < 2 || d1->dims[1] != 3 ) {
3475 if( lverb > 1 ) printf("-- approx DA: bad dims for TRIANGLEs: "
3476 "num_dim=%d, dims[1]=%d\n", d1->num_dim, d1->dims[1]);
3477 return 0;
3478 }
3479
3480 offset = gifti_triangle_diff_offset(d1->data, d2->data, d1->dims[0],
3481 d1->datatype);
3482 if( offset >= 0 ) {
3483 diffs |= 2;
3484 if(lverb > 1) printf("-- approx DA: triange diff at offset %d\n",
3485 offset);
3486 if(lverb < 3) return 0;
3487 }
3488 } else {
3489 offset = gifti_approx_diff_offset(d1->data, d2->data, d1->nvals,
3490 d1->datatype, 1.0);
3491 if( offset >= 0 ) {
3492 diffs |= 2;
3493 if(lverb>1) printf("-- approx DA: data diff at offset %d\n",offset);
3494 if(lverb<3) return 0;
3495 }
3496 }
3497
3498 return !diffs;
3499 }
3500
3501
3502 /* return whether the DA elements match so as to compare the data
3503 *
3504 * apply the same verb as above
3505 */
can_compare_DA_data(const giiDataArray * d1,const giiDataArray * d2,int verb)3506 static int can_compare_DA_data(const giiDataArray *d1,const giiDataArray *d2,
3507 int verb)
3508 {
3509 int c, top, rv = 1;
3510 int lverb = verb; /* possibly override passed 'verb' */
3511
3512 if( G.verb > lverb ) lverb = G.verb;
3513
3514 if( !d1 || !d2 ) {
3515 if(lverb>1) printf("-- comp DAs: have NULL DA(s) (%p, %p)\n",
3516 (void*)d1,(void*)d2);
3517 return 0; /* not equal */
3518 }
3519
3520 if( d1->datatype != d2->datatype ) {
3521 rv = 0;
3522 if( lverb > 1 )
3523 printf("-- comp DAs: DA datatype diff: %d (%s) vs. %d (%s)\n",
3524 d1->datatype, gifti_datatype2str(d1->datatype),
3525 d2->datatype, gifti_datatype2str(d2->datatype));
3526 if( lverb < 3 ) return 0;
3527 }
3528
3529 if( d1->ind_ord != d2->ind_ord ) {
3530 rv = 0;
3531 if( lverb > 1 )
3532 printf("-- comp DAs: ind_ord diff: %d (%s) vs. %d (%s)\n",
3533 d1->ind_ord,
3534 gifti_list_index2string(gifti_index_order_list, d1->ind_ord),
3535 d2->ind_ord,
3536 gifti_list_index2string(gifti_index_order_list, d2->ind_ord));
3537 if( lverb < 3 ) return 0;
3538 }
3539
3540 if( d1->num_dim != d2->num_dim ) {
3541 rv = 0;
3542 if( lverb > 1 ) printf("-- comp DAs: num_dim diff: %d vs. %d\n",
3543 d1->num_dim, d2->num_dim );
3544 if( lverb < 3 ) return 0;
3545 }
3546
3547 /* get minimum num_dim */
3548 top = d1->num_dim < d2->num_dim ? d1->num_dim : d2->num_dim;
3549 for( c = 0; c < top; c++ ) if( d1->dims[c] != d2->dims[c] ) break;
3550 if( c < top ) {
3551 rv = 0;
3552 if( lverb > 1 ) {
3553 printf("-- comp DAs: DA dims diff (length %d)\n ", top);
3554 gifti_disp_raw_data(d1->dims, NIFTI_TYPE_INT32, top, 0, stdout);
3555 printf(" vs ");
3556 gifti_disp_raw_data(d2->dims, NIFTI_TYPE_INT32, top, 1, stdout);
3557 }
3558 if( lverb < 3 ) return 0;
3559 }
3560
3561 if( d1->nvals != d2->nvals ) {
3562 rv = 0;
3563 if( lverb > 1 ) printf("-- comp DAs: nvals diff: %lld vs. %lld\n",
3564 d1->nvals, d2->nvals);
3565 if( lverb < 3 ) return 0;
3566 }
3567
3568 if( d1->nbyper != d2->nbyper ) {
3569 rv = 0;
3570 if( lverb > 1 ) printf("-- comp DAs: nbyper diff: %d vs. %d\n",
3571 d1->nbyper, d2->nbyper);
3572 if( lverb < 3 ) return 0;
3573 }
3574
3575 /* as a last test, make sure dims are valid, not just the same */
3576 if( ! gifti_valid_dims(d1, 0) ) {
3577 rv = 0;
3578 if( lverb > 1 ) printf("-- comp DAs: dims not valid\n");
3579 }
3580
3581 return rv;
3582 }
3583
3584 /*---------------------------------------------------------------------*/
3585 /*! check pointers, compare lengths, then check the Names in each list,
3586 * and see if there is a matching Name=Value pari
3587 *
3588 * only state diffs in the verb=3 case
3589 *//*-------------------------------------------------------------------*/
gifti_compare_nvpairs(const nvpairs * p1,const nvpairs * p2,int verb)3590 int gifti_compare_nvpairs(const nvpairs * p1, const nvpairs * p2, int verb)
3591 {
3592 char * value;
3593 int lverb = verb; /* possibly override passed verb */
3594 int c, diffs = 0;
3595
3596 if( G.verb > lverb ) lverb = G.verb;
3597
3598 if( !p1 || !p2 ) {
3599 if(!p1 && !p2) return 0; /* equal */
3600 if(lverb>2)
3601 printf("-- comp nvpairs: have NULL: %p, %p\n",(void*)p1,(void*)p2);
3602 return 1; /* not equal */
3603 }
3604
3605 /* they must be valid to proceed */
3606 if( ! gifti_valid_nvpairs(p1, 0) || ! gifti_valid_nvpairs(p2, 0) ) {
3607 if( lverb > 2 ) printf("-- cannot compare invalid nvpairs\n");
3608 return 1;
3609 }
3610
3611 if( p1->length != p2->length ) {
3612 if( lverb > 2 ) printf("-- nvp list lengths differ: %d vs %d\n",
3613 p1->length, p2->length);
3614 if( lverb < 3 ) return 1;
3615 }
3616
3617 /* search for mis-matches or non-existence from list 1 into list 2 */
3618 /* assume Names are unique (each that is not will show a mis-match) */
3619 for( c = 0; c < p1->length; c++ ) {
3620 if( ! p1->value[c] ) continue; /* skip anything that doesn't exist */
3621 value = gifti_get_meta_value(p2, p1->name[c]);
3622 if( !value ) {
3623 if( lverb > 2 )
3624 printf("-- nvp list 2 missing Name: '%s'\n",p1->name[c]);
3625 diffs++;
3626 }
3627 else if( strcmp(value, p1->value[c]) ) {
3628 if( lverb > 2 )
3629 printf("-- nvp diff for Name '%s':\n '%s' vs. '%s'\n",
3630 p1->name[c], p1->value[c], value);
3631 diffs++;
3632 }
3633 if( diffs && lverb < 3 ) return 1;
3634 }
3635
3636 /* now just search for non-existence (mis-matches have been found) */
3637 for( c = 0; c < p2->length; c++ ) {
3638 if( ! p2->value[c] ) continue; /* skip anything that doesn't exist */
3639 value = gifti_get_meta_value(p1, p2->name[c]);
3640 if( !value ) {
3641 if( lverb > 2 )
3642 printf("-- nvp list 1 missing Name: '%s'\n",p2->name[c]);
3643 if( lverb < 3 ) return 1;
3644 diffs++;
3645 }
3646 }
3647
3648 return diffs;
3649 }
3650
3651 /*---------------------------------------------------------------------*/
3652 /*! check pointers, lengths and contents
3653 *
3654 * return 0 if equal
3655 *
3656 * only state diffs in the verb=3 case
3657 *//*-------------------------------------------------------------------*/
gifti_compare_labeltable(const giiLabelTable * t1,const giiLabelTable * t2,int verb)3658 int gifti_compare_labeltable(const giiLabelTable *t1, const giiLabelTable *t2,
3659 int verb)
3660 {
3661 return compare_labeltables(t1, t2, verb, 0);
3662 }
3663
3664 /*---------------------------------------------------------------------*/
3665 /*! return 1 if tables are approximately equal (opposite of compare function)
3666 *
3667 * RGBA data is compared approximately
3668 *
3669 * only state diffs in the verb=3 case
3670 *//*-------------------------------------------------------------------*/
gifti_approx_labeltables(const giiLabelTable * t1,const giiLabelTable * t2,int verb)3671 int gifti_approx_labeltables(const giiLabelTable *t1, const giiLabelTable *t2,
3672 int verb)
3673 {
3674 return( ! compare_labeltables(t1, t2, verb, 1));
3675 }
3676
3677 /*---------------------------------------------------------------------*/
3678 /*! check pointers, lengths and contents
3679 *
3680 * only state diffs in the verb=3 case
3681 *
3682 * if approx, compare RBGA approximately
3683 *//*-------------------------------------------------------------------*/
compare_labeltables(const giiLabelTable * t1,const giiLabelTable * t2,int verb,int approx)3684 static int compare_labeltables(const giiLabelTable *t1, const giiLabelTable *t2,
3685 int verb, int approx)
3686 {
3687 int lverb = verb; /* possibly override passed verb */
3688 int c, offset, diffs = 0;
3689
3690 if( G.verb > lverb ) lverb = G.verb;
3691
3692 if( !t1 || !t2 ) {
3693 if(!t1 && !t2) return 0; /* equal */
3694 if(lverb>2)
3695 printf("-- Comp LabTab: have NULL: %p, %p\n",(void*)t1,(void*)t2);
3696 return 1; /* not */
3697 }
3698
3699 /* if empty, return 0 */
3700 if( t1->length <= 0 && t2->length <= 0 ) return 0;
3701
3702 if( t1->length != t2->length ) {
3703 if(lverb>2)printf("-- labeltable lengths diff: %d vs. %d\n",
3704 t1->length, t2->length);
3705 return 1; /* cannot compare without equal lengths */
3706 }
3707
3708 /* exactly 1 RGBA list is a difference */
3709 if( (t1->rgba && !t2->rgba) || (!t1->rgba && t2->rgba) ) {
3710 if(lverb>2)printf("-- only 1 labeltable has RGBA list\n");
3711 if(lverb<3) return 1;
3712 }
3713
3714 /* so lengths are positive and equal, compare index list and labels */
3715
3716 /* set limit to 0.0 to compare indicies exactly */
3717 offset = (int)gifti_approx_diff_offset(t1->key, t2->key,
3718 t1->length, NIFTI_TYPE_INT32, approx?1.0:0.0);
3719 if( offset >= 0 ) {
3720 if(lverb>2)printf("-- labeltable Key diff at index %d\n", offset);
3721 if(lverb<3) return 1;
3722 diffs++;
3723 }
3724
3725 /* walk through list to compare labels */
3726 for( c = 0; c < t1->length; c++ ) {
3727 if( gifti_strdiff(t1->label[c], t2->label[c]) ) {
3728 if(lverb>2)printf("-- labeltable Label diff at index %d\n", c);
3729 if(lverb<3) return 1;
3730 diffs++;
3731 break; /* stop at first difference */
3732 }
3733 }
3734
3735 if( t1->rgba && t2->rgba ) {
3736 /* if not approx, set limit to 0.0 to compare exactly */
3737 offset = (int)gifti_approx_diff_offset(t1->rgba, t2->rgba,
3738 4*t1->length, NIFTI_TYPE_FLOAT32, approx?1.0:0.0);
3739 if( offset >= 0 ) {
3740 offset /= 4; /* convert from float index to RGBA index */
3741 if(lverb>2)printf("-- labeltable RGBA diff at index %d\n", offset);
3742 if(lverb<3) return 1;
3743 diffs++;
3744 }
3745 }
3746
3747 return diffs;
3748 }
3749
3750 /*---------------------------------------------------------------------*/
3751 /*! like strcmp, but also return:
3752 * 0: if both pointers are NULL
3753 * 1: if exactly one is NULL
3754 *//*-------------------------------------------------------------------*/
gifti_strdiff(const char * s1,const char * s2)3755 int gifti_strdiff(const char * s1, const char * s2)
3756 {
3757 if( !s1 || !s2 ) {
3758 if( s1 || s2 ) return 1; /* one NULL means different */
3759 else return 0; /* both NULL mean equal */
3760 }
3761
3762 return strcmp(s1,s2); /* fall through to normal case */
3763 }
3764
3765 /*---------------------------------------------------------------------*/
3766 /*! check pointers, compare names and xforms
3767 *
3768 * only state diffs in the verb=3 case
3769 *//*-------------------------------------------------------------------*/
gifti_compare_coordsys(const giiCoordSystem * s1,const giiCoordSystem * s2,int comp_data,int verb)3770 int gifti_compare_coordsys(const giiCoordSystem *s1, const giiCoordSystem *s2,
3771 int comp_data, int verb)
3772 {
3773 long long offset;
3774 int lverb = verb; /* possibly override passed verb */
3775 int diffs = 0;
3776
3777 if( G.verb > lverb ) lverb = G.verb;
3778
3779 if( !s1 || !s2 ) {
3780 if(!s1 && !s2) return 0; /* equal */
3781 if(lverb>2)
3782 printf("-- Comp CoordSys: have NULL: %p, %p\n",(void*)s1,(void*)s2);
3783 return 1;
3784 }
3785
3786 if( !s1->dataspace || !s2->dataspace ) {
3787 if( s1->dataspace || s2->dataspace ) {
3788 if(lverb>2)printf("-- coordsys dspace diff: exactly one is NULL\n");
3789 if(lverb<3) return 1;
3790 diffs++;
3791 }
3792 } else if( strcmp(s1->dataspace, s2->dataspace) ) {
3793 if(lverb>2) printf("-- coordsys dspace diff: %s vs. %s\n",
3794 s1->dataspace, s2->dataspace);
3795 if( lverb < 3 ) return 1;
3796 diffs++;
3797 }
3798
3799 if( !s1->xformspace || !s2->xformspace ) {
3800 if( s1->xformspace || s2->xformspace ) {
3801 if(lverb>2)
3802 printf("-- coordsys xformspace diff: exactly one is NULL\n");
3803 if(lverb<3) return 1;
3804 diffs++;
3805 }
3806 } else if( strcmp(s1->xformspace, s2->xformspace) ) {
3807 if(lverb>2) printf("-- coordsys xformspace diff: %s vs. %s\n",
3808 s1->xformspace, s2->xformspace);
3809 if( lverb < 3 ) return 1;
3810 diffs++;
3811 }
3812
3813 if( ! comp_data ) return diffs; /* maybe we are done */
3814
3815 offset = gifti_compare_raw_data(s1->xform, s2->xform, sizeof(s1->xform));
3816 if( offset >= 0 ) {
3817 /* convert to index (to avoid printf warning) 2 Mar 2010 */
3818 offset /= (long long)sizeof(double);
3819 if(lverb>2) printf("-- coordsys xform diff at offset %lld\n", offset);
3820 if( lverb < 3 ) return 1;
3821 diffs++;
3822 }
3823
3824 return diffs;
3825 }
3826
3827 /*---------------------------------------------------------------------*/
3828 /*! compare raw data, returing the first location difference
3829 *
3830 * return byte position of difference, so that < 0 means no difference
3831 *//*-------------------------------------------------------------------*/
gifti_compare_raw_data(const void * p1,const void * p2,long long length)3832 long long gifti_compare_raw_data(const void * p1, const void * p2,
3833 long long length)
3834 {
3835 long long posn;
3836 char * d1 = (char *)p1, * d2 = (char *)p2;
3837
3838 if( !p1 || !p2 ) {
3839 if( !p1 && !p2 ) return -1; /* both NULL -> same */
3840 if( G.verb > 3 ) fprintf(stderr,"-- raw_data pointer diff\n");
3841 return 0; /* set difference */
3842 }
3843
3844 /* scan data until done or a difference is found */
3845 for( d1 = (char *)p1, d2 = (char *)p2, posn = 0;
3846 posn < length && *d1 == *d2;
3847 posn++, d1++, d2++ )
3848 ;
3849
3850 if( posn < length ) return posn; /* differ at posn */
3851
3852 return -1; /* equal */
3853 }
3854
3855
3856 /* make a local definition for this symmetric fractional difference */
3857 #undef GIFTI_SFD
3858 #define GIFTI_SFD(a,b) (fabs((double)(a)-(double)(b)) \
3859 / (fabs((double)(a))+fabs((double)(b))))
3860
3861 /*---------------------------------------------------------------------*/
3862 /*! approximate comparison of raw data, returing the first location difference
3863 * (>= 0 means difference, -1 means "approximately equal")
3864 *
3865 * Compute a symmetric fractional difference:
3866 *
3867 * SFD = abs(a-b)/(abs(a)+abs(b))
3868 *
3869 * length - number of contiguous elements to test
3870 * ni_type - NIFTI_TYPE_*, denoting the type of data to compare
3871 * limit - maximum SFD to be considered approximately equal
3872 *
3873 * * if limit = 0.0, check is faster
3874 *
3875 * * if limit >= 1.0, apply a default requiring almost all
3876 * significant bits
3877 *
3878 * * for integers, all bits are considered significant
3879 * * for real numbers, mantissa bits are considered significant
3880 *
3881 * return offset index, so that < 0 (-1) means no difference
3882 *
3883 * (return -1 if the pointers differ in whether they are set)
3884 *//*-------------------------------------------------------------------*/
gifti_approx_diff_offset(const void * p1,const void * p2,long long length,int ni_type,double limit)3885 long long gifti_approx_diff_offset(const void * p1, const void * p2,
3886 long long length, int ni_type, double limit)
3887 {
3888 long long posn;
3889 double llim = limit; /* local limit (passed limit or default) */
3890
3891 if( !p1 || !p2 ) {
3892 if( !p1 && !p2 ) return -1; /* same */
3893 return 0; /* different */
3894 }
3895
3896 switch( ni_type ) {
3897 default:
3898 fprintf(stderr,"** cannot test approx data with type %d (%s)\n",
3899 ni_type, nifti_datatype_to_string(ni_type));
3900 return 0;
3901
3902 case NIFTI_TYPE_INT8: {
3903 char * d1 = (char *)p1, * d2 = (char *)p2;
3904 if( llim >= 1.0 ) llim = 0.0; /* require equality for ints */
3905 for( posn = 0; posn < length; posn++, d1++, d2++ ) {
3906 if( *d1 == *d2 ) continue; /* fast check for equality */
3907 if( llim == 0.0 ) break; /* fast check for inequality */
3908 if( GIFTI_SFD(*d1,*d2) > llim ) break; /* not approximate */
3909 }
3910 break;
3911 }
3912 case NIFTI_TYPE_INT16: {
3913 short * d1 = (short *)p1, * d2 = (short *)p2;
3914 if( llim >= 1.0 ) llim = 0.0; /* require equality for ints */
3915 for( posn = 0; posn < length; posn++, d1++, d2++ ) {
3916 if( *d1 == *d2 ) continue; /* fast check for equality */
3917 if( llim == 0.0 ) break; /* fast check for inequality */
3918 if( GIFTI_SFD(*d1,*d2) > llim ) break; /* not approximate */
3919 }
3920 break;
3921 }
3922 case NIFTI_TYPE_INT32: {
3923 int * d1 = (int *)p1, * d2 = (int *)p2;
3924 if( llim >= 1.0 ) llim = 0.0; /* require equality for ints */
3925 for( posn = 0; posn < length; posn++, d1++, d2++ ) {
3926 if( *d1 == *d2 ) continue; /* fast check for equality */
3927 if( llim == 0.0 ) break; /* fast check for inequality */
3928 if( GIFTI_SFD(*d1,*d2) > llim ) break; /* not approximate */
3929 }
3930 break;
3931 }
3932 case NIFTI_TYPE_INT64: {
3933 long long * d1 = (long long *)p1, * d2 = (long long *)p2;
3934 if( llim >= 1.0 ) llim = 0.0; /* require equality for ints */
3935 for( posn = 0; posn < length; posn++, d1++, d2++ ) {
3936 if( *d1 == *d2 ) continue; /* fast check for equality */
3937 if( llim == 0.0 ) break; /* fast check for inequality */
3938 if( GIFTI_SFD(*d1,*d2) > llim ) break; /* not approximate */
3939 }
3940 break;
3941 }
3942 case NIFTI_TYPE_UINT8: {
3943 unsigned char *d1 = (unsigned char *)p1, *d2 = (unsigned char *)p2;
3944 if( llim >= 1.0 ) llim = 0.0; /* require equality for ints */
3945 for( posn = 0; posn < length; posn++, d1++, d2++ ) {
3946 if( *d1 == *d2 ) continue; /* fast check for equality */
3947 if( llim == 0.0 ) break; /* fast check for inequality */
3948 if( GIFTI_SFD(*d1,*d2) > llim ) break; /* not approximate */
3949 }
3950 break;
3951 }
3952 case NIFTI_TYPE_UINT16: {
3953 unsigned short *d1=(unsigned short *)p1, *d2=(unsigned short *)p2;
3954 if( llim >= 1.0 ) llim = 0.0; /* require equality for ints */
3955 for( posn = 0; posn < length; posn++, d1++, d2++ ) {
3956 if( *d1 == *d2 ) continue; /* fast check for equality */
3957 if( llim == 0.0 ) break; /* fast check for inequality */
3958 if( GIFTI_SFD(*d1,*d2) > llim ) break; /* not approximate */
3959 }
3960 break;
3961 }
3962 case NIFTI_TYPE_UINT32: {
3963 unsigned int * d1 = (unsigned int *)p1, * d2 = (unsigned int *)p2;
3964 if( llim >= 1.0 ) llim = 0.0; /* require equality for ints */
3965 for( posn = 0; posn < length; posn++, d1++, d2++ ) {
3966 if( *d1 == *d2 ) continue; /* fast check for equality */
3967 if( llim == 0.0 ) break; /* fast check for inequality */
3968 if( GIFTI_SFD(*d1,*d2) > llim ) break; /* not approximate */
3969 }
3970 break;
3971 }
3972 case NIFTI_TYPE_UINT64: {
3973 unsigned long long * d1 = (unsigned long long *)p1;
3974 unsigned long long * d2 = (unsigned long long *)p2;
3975 if( llim >= 1.0 ) llim = 0.0; /* require equality for ints */
3976 for( posn = 0; posn < length; posn++, d1++, d2++ ) {
3977 if( *d1 == *d2 ) continue; /* fast check for equality */
3978 if( llim == 0.0 ) break; /* fast check for inequality */
3979 if( GIFTI_SFD(*d1,*d2) > llim ) break; /* not approximate */
3980 }
3981 break;
3982 }
3983 case NIFTI_TYPE_FLOAT32: {
3984 float * d1 = (float *)p1, * d2 = (float *)p2;
3985 if( llim >= 1.0 ) llim = 1e-5;
3986 for( posn = 0; posn < length; posn++, d1++, d2++ ) {
3987 if( *d1 == *d2 ) continue; /* fast check for equality */
3988 if( llim == 0.0 ) break; /* fast check for inequality */
3989 if( GIFTI_SFD(*d1,*d2) > llim ) break; /* not approximate */
3990 }
3991 break;
3992 }
3993 case NIFTI_TYPE_FLOAT64: {
3994 double * d1 = (double *)p1, * d2 = (double *)p2;
3995 if( llim >= 1.0 ) llim = 1e-12;
3996 for( posn = 0; posn < length; posn++, d1++, d2++ ) {
3997 if( *d1 == *d2 ) continue; /* fast check for equality */
3998 if( llim == 0.0 ) break; /* fast check for inequality */
3999 if( GIFTI_SFD(*d1,*d2) > llim ) break; /* not approximate */
4000 }
4001 break;
4002 }
4003 }
4004
4005 if( posn < length ) return posn; /* differ at 1-based posn */
4006
4007 return -1; /* approximately equal */
4008 }
4009
4010 /*---------------------------------------------------------------------*/
4011 /*! compare triangles - return triangle index of first difference
4012 * - so -1 means no difference
4013 *
4014 * require the type to be 1, 2 or 4-byte integers
4015 * could cheat and compare as unsigned...
4016 *
4017 * require consistent wrapping, but allow for varying first vertex
4018 *//*-------------------------------------------------------------------*/
gifti_triangle_diff_offset(const void * p1,const void * p2,int ntri,int ni_type)4019 int gifti_triangle_diff_offset(const void *p1, const void *p2, int ntri,
4020 int ni_type)
4021 {
4022 int posn = -1;
4023
4024 /* if either pointer is not set, we're out of here */
4025 if( !p1 || !p2 ) {
4026 if( !p1 && !p2 ) return -1; /* same */
4027 return 0; /* different */
4028 }
4029
4030 if( ntri <= 0 ) return -1;
4031
4032 switch( ni_type ) {
4033 case NIFTI_TYPE_INT8: {
4034 char * d1 = (char *)p1, * d2 = (char *)p2;
4035 for( posn = 0; posn < ntri; posn++, d1+=3, d2+=3 ) {
4036 if( *d1 == *d2 ) { /* same first index */
4037 if( d1[1] != d2[1] || d1[2] != d2[2] ) break;
4038 } else if ( d1[0] == d2[1] ) { /* index off by 1 */
4039 if( d1[1] != d2[2] || d1[2] != d2[0] ) break;
4040 } else if ( d1[0] == d2[2] ) { /* index off by 2 */
4041 if( d1[1] != d2[0] || d1[2] != d2[1] ) break;
4042 }
4043 }
4044 break;
4045 }
4046 case NIFTI_TYPE_INT16: {
4047 short * d1 = (short *)p1, * d2 = (short *)p2;
4048 for( posn = 0; posn < ntri; posn++, d1+=3, d2+=3 ) {
4049 if( *d1 == *d2 ) { /* same first index */
4050 if( d1[1] != d2[1] || d1[2] != d2[2] ) break;
4051 } else if ( d1[0] == d2[1] ) { /* index off by 1 */
4052 if( d1[1] != d2[2] || d1[2] != d2[0] ) break;
4053 } else if ( d1[0] == d2[2] ) { /* index off by 2 */
4054 if( d1[1] != d2[0] || d1[2] != d2[1] ) break;
4055 }
4056 }
4057 break;
4058 }
4059 case NIFTI_TYPE_INT32: {
4060 int * d1 = (int *)p1, * d2 = (int *)p2;
4061 for( posn = 0; posn < ntri; posn++, d1+=3, d2+=3 ) {
4062 if( *d1 == *d2 ) { /* same first index */
4063 if( d1[1] != d2[1] || d1[2] != d2[2] ) break;
4064 } else if ( d1[0] == d2[1] ) { /* index off by 1 */
4065 if( d1[1] != d2[2] || d1[2] != d2[0] ) break;
4066 } else if ( d1[0] == d2[2] ) { /* index off by 2 */
4067 if( d1[1] != d2[0] || d1[2] != d2[1] ) break;
4068 }
4069 }
4070 break;
4071 }
4072 case NIFTI_TYPE_UINT8: {
4073 unsigned char *d1 = (unsigned char *)p1, *d2 = (unsigned char *)p2;
4074 for( posn = 0; posn < ntri; posn++, d1+=3, d2+=3 ) {
4075 if( *d1 == *d2 ) { /* same first index */
4076 if( d1[1] != d2[1] || d1[2] != d2[2] ) break;
4077 } else if ( d1[0] == d2[1] ) { /* index off by 1 */
4078 if( d1[1] != d2[2] || d1[2] != d2[0] ) break;
4079 } else if ( d1[0] == d2[2] ) { /* index off by 2 */
4080 if( d1[1] != d2[0] || d1[2] != d2[1] ) break;
4081 }
4082 }
4083 break;
4084 }
4085 case NIFTI_TYPE_UINT16: {
4086 unsigned short *d1=(unsigned short *)p1, *d2=(unsigned short *)p2;
4087 for( posn = 0; posn < ntri; posn++, d1+=3, d2+=3 ) {
4088 if( *d1 == *d2 ) { /* same first index */
4089 if( d1[1] != d2[1] || d1[2] != d2[2] ) break;
4090 } else if ( d1[0] == d2[1] ) { /* index off by 1 */
4091 if( d1[1] != d2[2] || d1[2] != d2[0] ) break;
4092 } else if ( d1[0] == d2[2] ) { /* index off by 2 */
4093 if( d1[1] != d2[0] || d1[2] != d2[1] ) break;
4094 }
4095 }
4096 break;
4097 }
4098 case NIFTI_TYPE_UINT32: {
4099 unsigned int * d1 = (unsigned int *)p1, * d2 = (unsigned int *)p2;
4100 for( posn = 0; posn < ntri; posn++, d1+=3, d2+=3 ) {
4101 if( *d1 == *d2 ) { /* same first index */
4102 if( d1[1] != d2[1] || d1[2] != d2[2] ) break;
4103 } else if ( d1[0] == d2[1] ) { /* index off by 1 */
4104 if( d1[1] != d2[2] || d1[2] != d2[0] ) break;
4105 } else if ( d1[0] == d2[2] ) { /* index off by 2 */
4106 if( d1[1] != d2[0] || d1[2] != d2[1] ) break;
4107 }
4108 }
4109 break;
4110 }
4111 default: {
4112 fprintf(stderr,"** gifti_tri_diff: invalid type %d\n", ni_type);
4113 return 1;
4114 }
4115 }
4116
4117 if( posn < ntri ) return posn; /* difference offset */
4118
4119 return -1; /* no difference */
4120 }
4121
4122 /*-----------------------------------------------------------------*/
4123 /*! print raw data (nvals of type 'type') to the given file stream
4124 *
4125 * possibly write a trailing newline
4126 *//*-------------------------------------------------------------------*/
gifti_disp_raw_data(const void * data,int type,int nvals,int newline,FILE * stream)4127 int gifti_disp_raw_data(const void * data, int type, int nvals, int newline,
4128 FILE * stream)
4129 {
4130 FILE * fp = stream ? stream : stdout;
4131 char * dp, fbuf[64];
4132 int c, size;
4133
4134 gifti_datatype_sizes(type, &size, NULL); /* get nbyper */
4135 if( size == 0 ) {
4136 fprintf(stderr,"** GDRD: cannot print with size 0, type %d\n", type);
4137 return 1;
4138 }
4139
4140 for( c = 0, dp = (char *)data; c < nvals; c++, dp += size ) {
4141 switch( type ) {
4142 case NIFTI_TYPE_INT8:
4143 fprintf(fp, "%d", *(char *)dp);
4144 break;
4145 case NIFTI_TYPE_INT16:
4146 fprintf(fp, "%d", *(short *)dp);
4147 break;
4148 case NIFTI_TYPE_INT32:
4149 fprintf(fp, "%d", *(int *)dp);
4150 break;
4151 case NIFTI_TYPE_INT64:
4152 fprintf(fp, "%lld", *(long long *)dp);
4153 break;
4154 case NIFTI_TYPE_UINT8:
4155 fprintf(fp, "%u", *(unsigned char *)dp);
4156 break;
4157 case NIFTI_TYPE_UINT16:
4158 fprintf(fp, "%u", *(unsigned short *)dp);
4159 break;
4160 case NIFTI_TYPE_UINT32:
4161 fprintf(fp, "%u", *(unsigned int *)dp);
4162 break;
4163 case NIFTI_TYPE_UINT64:
4164 fprintf(fp, "%llu", *(unsigned long long *)dp);
4165 break;
4166 case NIFTI_TYPE_FLOAT32:
4167 sprintf(fbuf,"%f", *(float *)dp);
4168 gifti_clear_float_zeros(fbuf);
4169 fprintf(fp, "%s", fbuf);
4170 break;
4171 case NIFTI_TYPE_FLOAT64:
4172 sprintf(fbuf,"%f", *(double *)dp);
4173 gifti_clear_float_zeros(fbuf);
4174 fprintf(fp, "%s", fbuf);
4175 break;
4176 default:
4177 fprintf(stderr,"** Gdisp_raw_data: invalid type %d\n", type);
4178 return 1;
4179 }
4180 if( c < nvals - 1 ) fputc(' ', fp);
4181 }
4182
4183 if ( newline ) fputc('\n', fp);
4184
4185 return 0;
4186 }
4187
4188 /*----------------------------------------------------------------------
4189 *! remove trailing zeros from string of printed float
4190 * return 1 if something was cleared
4191 * 0 if not
4192 *//*-------------------------------------------------------------------*/
gifti_clear_float_zeros(char * str)4193 int gifti_clear_float_zeros( char * str )
4194 {
4195 char * dp, * valp;
4196 int len;
4197
4198 if( !str || !*str ) return 0; /* that was easy */
4199
4200 dp = strchr(str, '.'); /* find '.' */
4201 if( !dp ) return 0; /* no '.', easy too */
4202
4203 len = strlen(dp);
4204
4205 /* never clear what is just to the right of '.' */
4206 for( valp = dp+len-1; (valp > dp+1) && (*valp==' ' || *valp=='0'); valp-- )
4207 *valp = '\0'; /* clear, so we don't worry about break conditions */
4208
4209 if( valp < dp + len - 1 ) return 1;
4210
4211 return 0;
4212 }
4213
4214 /*----------------------------------------------------------------------
4215 *! set all DataArray attributes of the given name to the given value
4216 *//*-------------------------------------------------------------------*/
gifti_set_atr_in_DAs(gifti_image * gim,const char * name,const char * value,const int * dalist,int len)4217 int gifti_set_atr_in_DAs(gifti_image *gim, const char *name, const char *value,
4218 const int * dalist, int len)
4219 {
4220 int c, ind;
4221
4222 if( !gim || !name || !value ) {
4223 fprintf(stderr,"** set_DA_atrs: bad params (%p,%p,%p)\n",
4224 (void *)gim, (void *)name, (void *)value);
4225 return 1;
4226 }
4227
4228 if( !gim->darray ) return 0; /* just leave */
4229
4230 if( dalist && len > 0 ) { /* set atrs for those DA in dalist */
4231 if( ! gifti_valid_int_list(dalist, len, 0, gim->numDA-1, 1) )
4232 return 1;
4233
4234 /* good to go */
4235 for( c = 0; c < len; c++ ) {
4236 ind = dalist[c]; /* for clarity */
4237 if( ! gim->darray[ind] ) continue; /* trioanoid */
4238 if( gifti_str2attr_darray(gim->darray[ind], name, value) ) {
4239 if( G.verb > 1 )
4240 fprintf(stderr,"** bad DA attr '%s'='%s'\n",name,value);
4241 return 1;
4242 }
4243 }
4244
4245 if( G.verb > 2 )
4246 fprintf(stderr,"++ set atrs in %d DAs, '%s'='%s'\n",len,name,value);
4247
4248 return 0;
4249 }
4250
4251 /* else continue, do all of them */
4252
4253 for( c = 0; c < gim->numDA; c++ ) {
4254 if( ! gim->darray[c] ) continue; /* trioanoid */
4255 if( gifti_str2attr_darray(gim->darray[c], name, value) ) {
4256 if(G.verb>1)fprintf(stderr,"** bad DA attr '%s'='%s'\n",name,value);
4257 return 1;
4258 }
4259 }
4260
4261 if( G.verb > 4 )
4262 fprintf(stderr,"++ set attr in all DAs, '%s'='%s'\n", name, value);
4263
4264 return 0;
4265 }
4266
4267 /*----------------------------------------------------------------------
4268 *! set MetaData name/value pairs in all DAs in list (or all in gim)
4269 *//*-------------------------------------------------------------------*/
gifti_set_DA_meta(gifti_image * gim,const char * name,const char * value,const int * dalist,int len,int replace)4270 int gifti_set_DA_meta( gifti_image *gim, const char *name, const char *value,
4271 const int * dalist, int len, int replace )
4272 {
4273 int c, ind;
4274
4275 if( !gim || !name || !value ) {
4276 fprintf(stderr,"** set_DA_meta: bad params (%p,%p,%p)\n",
4277 (void *)gim, (void *)name, (void *)value);
4278 return 1;
4279 }
4280
4281 if( !gim->darray ) return 0; /* just leave */
4282
4283 if( dalist && len > 0 ) { /* set meta for those DA in dalist */
4284 if( ! gifti_valid_int_list(dalist, len, 0, gim->numDA-1, 1) )
4285 return 1;
4286
4287 /* good to go */
4288 for( c = 0; c < len; c++ ) {
4289 ind = dalist[c]; /* for clarity */
4290 if( ! gim->darray[ind] ) continue; /* trioanoid */
4291 if( gifti_add_to_meta(&gim->darray[ind]->meta,name,value,replace) )
4292 return 1;
4293 }
4294
4295 if( G.verb > 2 )
4296 fprintf(stderr,"++ set meta in %d DAs, '%s'='%s'\n",len,name,value);
4297
4298 return 0;
4299 }
4300
4301 /* else continue, do all of them */
4302
4303 for( c = 0; c < gim->numDA; c++ ) {
4304 if( ! gim->darray[c] ) continue; /* trioanoid */
4305 if( gifti_add_to_meta(&gim->darray[c]->meta,name,value,replace) )
4306 return 1;
4307 }
4308
4309 if( G.verb > 4 )
4310 fprintf(stderr,"++ set MetaData in all DAs, '%s'='%s'\n", name, value);
4311
4312 return 0;
4313 }
4314
4315 /*----------------------------------------------------------------------
4316 *! allocate and return a newly created gifti_image_struct
4317 *
4318 * if numDA > 0, allocate and initialize gim->darray
4319 * if intent is a valid NIFTI_INTENT code, set it in all DataArray elements
4320 * if dtype is a valid NIFTI_TYPE, set it in all DA elements
4321 * if dims is set (MUST be of length 6), set the dims in all DA elements
4322 * if alloc_data, allocate zero-filled data in each DA element
4323 *
4324 * note that if numDA <= 0, the function returns an empty gifti_image
4325 *//*-------------------------------------------------------------------*/
gifti_create_image(int numDA,int intent,int dtype,int ndim,const int * dims,int alloc_data)4326 gifti_image * gifti_create_image( int numDA, int intent, int dtype, int ndim,
4327 const int * dims, int alloc_data )
4328 {
4329 gifti_image * gim;
4330 int c, errs = 0;
4331
4332 if( G.verb > 1 ) { /* maybe start with some chit-chat */
4333 fprintf(stderr,"++ creating gifti_image with %d DA elements\n", numDA);
4334 if( G.verb > 2 ) {
4335 fprintf(stderr," intent[%d] = %s, dtype[%d] = %s,\n"
4336 " alloc_data = %d, ndim = %d, dims: ",
4337 intent, gifti_intent_to_string(intent),
4338 dtype, gifti_datatype2str(dtype), alloc_data, ndim);
4339 if( !dims ) fprintf(stderr,"<empty>\n");
4340 else gifti_disp_raw_data(dims, DT_INT32, GIFTI_DARRAY_DIM_LEN,
4341 1, stderr);
4342 }
4343 }
4344
4345 /* basic step - create empty image (with a version string) */
4346 gim = (gifti_image *)calloc(1, sizeof(gifti_image));
4347 if(!gim){ fprintf(stderr,"** failed to alloc gifti_image\n"); return NULL; }
4348
4349 gifti_clear_gifti_image(gim);
4350 gim->version = gifti_strdup(GIFTI_XML_VERSION);
4351
4352 if( numDA <= 0 ) return gim; /* done */
4353
4354 /* apply numDA, which is incremented in add_empty_darray() */
4355 gim->numDA = 0;
4356 if( gifti_add_empty_darray(gim, numDA) ) { /* then cannot continue */
4357 gifti_free_image(gim);
4358 return NULL;
4359 }
4360
4361 /* init all to defaults */
4362 for( c = 0; c < gim->numDA; c++ )
4363 errs += gifti_set_DA_defaults(gim->darray[c]);
4364
4365 /* and fill in any other pieces */
4366
4367 if( gifti_intent_is_valid(intent) )
4368 errs += gifti_set_atr_in_DAs(gim,"Intent",
4369 gifti_intent_to_string(intent), NULL, 0);
4370
4371 if( gifti_valid_datatype(dtype, 1) ) {
4372 errs += gifti_set_atr_in_DAs(gim,"DataType", gifti_datatype2str(dtype),
4373 NULL, 0);
4374 errs += gifti_update_nbyper(gim);
4375 }
4376
4377 if( dims && ndim >= 0 ) errs += gifti_set_dims_all_DA(gim, ndim, dims);
4378
4379 /* don't try this if there are errors */
4380 if( !errs && alloc_data ) errs += gifti_alloc_DA_data(gim, NULL, 0);
4381
4382 if( errs ) { /* then fail out */
4383 gifti_free_image(gim);
4384 return NULL;
4385 }
4386
4387 return gim;
4388 }
4389
4390 /*----------------------------------------------------------------------
4391 *! allocate nvals*nbyper bytes of (zero-filled) data in each DataArray
4392 * (in dalist or simply in gim)
4393 *
4394 * return 0 on success
4395 * 1 on error
4396 *//*-------------------------------------------------------------------*/
gifti_alloc_DA_data(gifti_image * gim,const int * dalist,int len)4397 int gifti_alloc_DA_data(gifti_image * gim, const int * dalist, int len)
4398 {
4399 giiDataArray * da;
4400 long long nbytes, ntot = 0;
4401 int c, index, nset = 0, use_list, numDA;
4402
4403 if( !gim || !gim->darray || gim->numDA <= 0 ) return 0;
4404
4405 /* decide whether to use dalist or allocate all data */
4406 use_list = gifti_valid_int_list(dalist, len, 0, gim->numDA-1, 0);
4407
4408 if( use_list && G.verb > 2 )
4409 fprintf(stderr,"++ allocating data for %s\n",
4410 use_list ? "DA in list" : "all DAs");
4411
4412 if( use_list && DA_data_exists(gim, dalist, len) ) {
4413 fprintf(stderr,"** data already exists for some DAs in list\n");
4414 return 1;
4415 }
4416
4417 numDA = use_list ? len : gim->numDA;
4418 for( c = 0; c < numDA; c++ ) {
4419 index = use_list ? dalist[c] : c; /* choose appropriate DA index */
4420 da = gim->darray[index]; /* set convenient pointer */
4421
4422 if( ! da ) continue;
4423
4424 /* if dimensions do not make sense, fail out */
4425 if( ! gifti_valid_dims(da, G.verb > 0) ) return 1;
4426
4427 if( da->nvals < 0 || da->nbyper < 0 ) {
4428 fprintf(stderr,"** bad nvals, nbyper in DA[%d]\n",index);
4429 return 1;
4430 }
4431 nbytes = da->nvals * da->nbyper;
4432 if( nbytes <= 0 ) continue; /* skip empty data */
4433
4434 ntot += nbytes; /* compute total bytes */
4435 nset++;
4436
4437 da->data = calloc(nbytes, sizeof(char));
4438 if( !da->data ) {
4439 fprintf(stderr,"** gifti_alloc_DA_data: failed on DA %d of %d\n"
4440 " %lld bytes (%lld total)\n",
4441 index, numDA, nbytes, ntot);
4442 return 1;
4443 }
4444 }
4445
4446 if( G.verb > 3)
4447 fprintf(stderr,"++ alloc'd %lld bytes in %d DA elements\n", ntot, nset);
4448
4449 return 0;
4450 }
4451
4452 /*----------------------------------------------------------------------
4453 *! set num_dims, dims and nvals in every DataArray element
4454 *
4455 * return 0 on success
4456 * 1 on error
4457 *//*-------------------------------------------------------------------*/
gifti_set_dims_all_DA(gifti_image * gim,int ndim,const int * dims)4458 int gifti_set_dims_all_DA(gifti_image * gim, int ndim, const int * dims)
4459 {
4460 long long nvals;
4461 int c, d, nset = 0;
4462
4463 if(!gim || ndim < 0 || ndim > GIFTI_DARRAY_DIM_LEN || !dims) {
4464 fprintf(stderr,"** SDA_DA: bad params (%p, %d, %p)\n",
4465 (void *)gim, ndim, (void *)dims);
4466 return 1;
4467 }
4468
4469 if( !gim->darray || gim->numDA == 0 ) return 0;
4470
4471 /* first compute nvals */
4472 for( d = 0, nvals = 1; d < ndim; d++) nvals *= dims[d];
4473 if( nvals <= 0 ) {
4474 fprintf(stderr,"** GSDA_DA: malformed dims[%d]: ", ndim);
4475 gifti_disp_raw_data(dims, DT_INT32, GIFTI_DARRAY_DIM_LEN, 1, stderr);
4476 return 1;
4477 }
4478 if( ndim == 0 ) nvals = 0;
4479
4480 /* insert num_dim and fill dims (pad with 0s) */
4481 for( c = 0; c < gim->numDA; c++ ) {
4482 if( !gim->darray[c] ) continue; /* paranoid */
4483 gim->darray[c]->num_dim = ndim;
4484 for( d = 0; d < ndim; d++ )
4485 gim->darray[c]->dims[d] = dims[d];
4486 for( /* continue */ ; d < GIFTI_DARRAY_DIM_LEN; d++ )
4487 gim->darray[c]->dims[d] = 0;
4488 gim->darray[c]->nvals = nvals;
4489 nset++;
4490 }
4491
4492 if(G.verb > 3) {
4493 fprintf(stderr,"++ set dims in %d of %d DA elements to: ",
4494 nset, gim->numDA);
4495 gifti_disp_raw_data(dims, DT_INT32, GIFTI_DARRAY_DIM_LEN, 1, stderr);
4496 }
4497
4498 return 0;
4499 }
4500
4501 /*----------------------------------------------------------------------
4502 *! update nbyper/swapsize for all DataArray elements
4503 *
4504 * return 0 on success
4505 * 1 on error
4506 *//*-------------------------------------------------------------------*/
gifti_update_nbyper(gifti_image * gim)4507 int gifti_update_nbyper(gifti_image * gim)
4508 {
4509 giiDataArray * da;
4510 int c, errs = 0;
4511
4512 if( !gim ) return 1;
4513
4514 if( !gim->darray || gim->numDA == 0 ) return 0;
4515
4516 for( c = 0; c < gim->numDA; c++ ){
4517 da = gim->darray[c]; /* just to look cleaner */
4518 if( !da ) continue;
4519 errs += gifti_datatype_sizes(da->datatype, &da->nbyper, NULL);
4520 }
4521
4522 return errs;
4523 }
4524
4525 /*----------------------------------------------------------------------
4526 *! fill DataArray element with default values
4527 *
4528 * return 0 on success
4529 * 1 on error
4530 *//*-------------------------------------------------------------------*/
gifti_set_DA_defaults(giiDataArray * da)4531 int gifti_set_DA_defaults(giiDataArray * da)
4532 {
4533 int c;
4534
4535 if(!da) { fprintf(stderr,"** NULL in set_DA_defaults\n"); return 1; }
4536
4537 if( G.verb > 6 ) fprintf(stderr,"-- setting DA defaults\n");
4538
4539 gifti_clear_DataArray(da); /* start with empty struct */
4540
4541 /* and fill with any non-NULL, non-zero values */
4542
4543 da->intent = NIFTI_INTENT_NONE;
4544 da->datatype = NIFTI_TYPE_FLOAT32;
4545 da->ind_ord = GIFTI_IND_ORD_ROW_MAJOR;
4546 da->num_dim = 1; /* one value per node */
4547
4548 for( c = 0; c < GIFTI_DARRAY_DIM_LEN; c++ ) da->dims[c] = 0;
4549
4550 da->encoding = GIFTI_ENCODING_B64BIN; /* zlib may not be available */
4551 da->endian = gifti_get_this_endian();
4552 da->ext_offset = 0;
4553
4554 da->nvals = 0;
4555 da->nbyper = 0;
4556 gifti_datatype_sizes(da->datatype, &da->nbyper, NULL);
4557
4558 return 0;
4559 }
4560
4561 /*----------------------------------------------------------------------
4562 *! clear the DataArray element
4563 *//*-------------------------------------------------------------------*/
gifti_clear_DataArray(giiDataArray * da)4564 int gifti_clear_DataArray(giiDataArray * da)
4565 {
4566 if(!da) { fprintf(stderr,"** NULL in clear_DataArray\n"); return 1; }
4567
4568 if( G.verb > 5 ) fprintf(stderr,"-- clearing DataArray\n");
4569
4570 memset(da, 0, sizeof(giiDataArray));
4571
4572 da->ext_fname = NULL;
4573 gifti_clear_nvpairs(&da->meta);
4574 da->coordsys = NULL;
4575 da->data = NULL;
4576 gifti_clear_nvpairs(&da->ex_atrs);
4577
4578 return 0;
4579 }
4580
4581 /*----------------------------------------------------------------------
4582 *! simply clear all contents of the passed gifti_image
4583 * (being explicit with pointers)
4584 *
4585 * return 0 on success
4586 * 1 on error
4587 *//*-------------------------------------------------------------------*/
gifti_clear_gifti_image(gifti_image * gim)4588 int gifti_clear_gifti_image(gifti_image * gim)
4589 {
4590 if(!gim) { fprintf(stderr,"** NULL in clear_gifti_image\n"); return 1; }
4591
4592 if( G.verb > 5 ) fprintf(stderr,"-- clearing gifti_image\n");
4593
4594 /* set the version and clear all pointers */
4595 memset(gim, 0, sizeof(*gim));
4596
4597 gim->version = NULL;
4598 gifti_clear_nvpairs(&gim->meta);
4599 gifti_clear_LabelTable(&gim->labeltable);
4600 gim->darray = NULL;
4601 gifti_clear_nvpairs(&gim->ex_atrs);
4602
4603 return 0;
4604 }
4605
4606 /*----------------------------------------------------------------------
4607 *! read a dataset, just for numDA
4608 *
4609 * may write faster gxml function for this, if it seems important
4610 *//*-------------------------------------------------------------------*/
gifti_read_dset_numDA(const char * fname)4611 int gifti_read_dset_numDA(const char * fname)
4612 {
4613 gifti_image * gim;
4614 int numDA;
4615
4616 if( !fname ) {
4617 fprintf(stderr,"** NULL to gifti_read_dset_numDA\n");
4618 return -1;
4619 }
4620
4621 if( G.verb > 2 ) fprintf(stderr,"++ read dset numDA, file '%s'\n",fname);
4622
4623 gim = gifti_read_da_list(fname, 0, NULL, 0);
4624
4625 if( !gim ) return -1; /* errors already printed */
4626
4627 numDA = gim->numDA;
4628
4629 if(G.verb > 1)
4630 fprintf(stderr,"++ read dset numDA, file '%s', numDA = %d\n",
4631 fname, numDA);
4632
4633 gifti_free_image(gim); /* lose dataset and return */
4634
4635 return numDA;
4636 }
4637
4638 /*----------------------------------------------------------------------
4639 *! return whether the list values are from min to max
4640 *//*-------------------------------------------------------------------*/
gifti_valid_int_list(const int * list,int len,int min,int max,int whine)4641 int gifti_valid_int_list(const int *list, int len, int min, int max, int whine)
4642 {
4643 int c;
4644
4645 if( !list || len <= 0 ) return 0;
4646
4647 for( c = 0; c < len; c++ )
4648 if( list[c] < min || list[c] > max ) {
4649 if( whine )
4650 fprintf(stderr,"** bad list index [%d] = %d, not in [%d,%d]\n",
4651 c, list[c], min, max);
4652 return 0;
4653 }
4654
4655 return 1;
4656 }
4657
4658 /* return whether any DAs in list have data */
DA_data_exists(gifti_image * gim,const int * dalist,int len)4659 static int DA_data_exists(gifti_image * gim, const int * dalist, int len)
4660 {
4661 int length, uselist = 0;
4662 int c, ind;
4663
4664 if( !dalist || len <= 0 ) { /* then scan all DA elements */
4665 length = gim->numDA;
4666 if( length <= 0 ) return 0;
4667 } else if( !gifti_valid_int_list(dalist, len, 0, gim->numDA-1, 1) ) {
4668 return 0;
4669 } else {
4670 uselist = 1;
4671 length = len;
4672 }
4673
4674 for( c = 0; c < length; c++ ) {
4675 ind = uselist ? dalist[c] : c;
4676 if( gim->darray[ind] && gim->darray[ind]->data )
4677 return 1;
4678 }
4679
4680 return 0;
4681 }
4682
4683 /*----------------------------------------------------------------------
4684 *! add the name=value pair to the MetaData lists
4685 *
4686 * if the name already exists, fail, unless 'replace' is set
4687 *
4688 * return 0 on success, 1 on error
4689 *//*-------------------------------------------------------------------*/
gifti_add_to_meta(giiMetaData * md,const char * name,const char * value,int replace)4690 int gifti_add_to_meta( giiMetaData * md, const char * name, const char * value,
4691 int replace )
4692 {
4693 int c;
4694
4695 if( !md || !name || !value ) return 1;
4696
4697 if( G.verb > 5 )
4698 fprintf(stderr,"++ GA2M: name '%s', value '%s', replace = %d\n",
4699 name, value, replace);
4700
4701 /* see if 'name' is already here */
4702 for( c = 0; c < md->length; c++ )
4703 {
4704 if( !md->name[c] && G.verb > 2 ) {
4705 fprintf(stderr,"** G MD[%d]: no name to check for replacement\n",c);
4706 continue;
4707 }
4708
4709 if( !strcmp(md->name[c], name) ) { /* a match, apply and return */
4710 if( !md->value[c] && G.verb > 2 ) {
4711 fprintf(stderr,"** G MD[%d]: no value to replace\n",c);
4712 md->value[c] = gifti_strdup(value);
4713 return 0;
4714 }
4715
4716 if( replace ) {
4717 if( G.verb > 5 ) fprintf(stderr," (add via REPLACE)\n");
4718 if( md->value[c] ) free(md->value[c]);
4719 md->value[c] = gifti_strdup(value);
4720 return 0;
4721 } else {
4722 fprintf(stderr,"** G_add_to_meta: name '%s', already exists\n",
4723 name);
4724 return 1;
4725 }
4726 }
4727 }
4728
4729 /* name is new, so just add it */
4730
4731 if( G.verb > 5 ) fprintf(stderr," (adding new entry)\n");
4732
4733 md->length++;
4734 md->name = (char **)realloc(md->name, md->length * sizeof(char *));
4735 md->value = (char **)realloc(md->value, md->length * sizeof(char *));
4736
4737 if( !md->name || !md->value ) {
4738 fprintf(stderr,"** GA2M:failed to realloc %d MD pointers\n",md->length);
4739 md->length = 0;
4740 return 1;
4741 }
4742
4743 md->name[md->length-1] = gifti_strdup(name);
4744 md->value[md->length-1] = gifti_strdup(value);
4745
4746 if( ! md->name[md->length-1] || ! md->value[md->length-1] )
4747 return 1;
4748
4749 return 0;
4750 }
4751
4752 /*----------------------------------------------------------------------
4753 *! check for validity of the gifti_image (including sub-structures)
4754 *
4755 * if whine is set, complain about any errors
4756 *
4757 * return 1 if valid, 0 otherwise
4758 *//*-------------------------------------------------------------------*/
gifti_valid_gifti_image(gifti_image * gim,int whine)4759 int gifti_valid_gifti_image( gifti_image * gim, int whine )
4760 {
4761 int c, errs = 0;
4762
4763 if( !gim ) {
4764 if(whine) fprintf(stderr,"** invalid: gifti_image ptr is NULL\n");
4765 return 0;
4766 }
4767
4768 if( G.verb > 3 ) fprintf(stderr,"-- checking for valid gifti_image...\n");
4769
4770 if( gim->numDA < 0 ) {
4771 if(whine) fprintf(stderr,"** invalid: numDA = %d\n", gim->numDA);
4772 errs ++;
4773 }
4774
4775 if( !gim->version || strcmp(gim->version, GIFTI_XML_VERSION) ) {
4776 if(whine) fprintf(stderr, "** invalid: gim version = %s\n",
4777 G_CHECK_NULL_STR(gim->version));
4778 errs++;
4779 }
4780
4781 if( ! gifti_valid_nvpairs(&gim->meta, whine) ) errs ++;
4782
4783 if( ! gifti_valid_LabelTable(&gim->labeltable, whine) ) errs ++;
4784
4785 for( c = 0; c < gim->numDA; c++ ) {
4786 if( G.verb > 5 ) fprintf(stderr,"-- checking DA[%d]\n", c);
4787 if( ! gifti_valid_DataArray(gim->darray[c], whine) ) {
4788 if( G.verb > 3 ) fprintf(stderr,"-- DA[%d] has errors\n",c);
4789 errs++;
4790 } else if( G.verb > 4 )
4791 fprintf(stderr,"-- DA[%d] is VALID\n",c);
4792 }
4793
4794 /* no check on swapped or compressed */
4795
4796 if( ! gifti_valid_nvpairs(&gim->ex_atrs, whine) ) errs ++;
4797
4798 if( G.verb > 2 ) {
4799 fprintf(stderr,"-- gifti_image: errors = %d", errs);
4800 if( errs ) fprintf(stderr," (INVALID)\n");
4801 else fprintf(stderr," (VALID)\n");
4802 }
4803
4804 if( errs ) return 0;
4805 else return 1;
4806 }
4807
4808 /*---------------------------------------------------------------------*/
4809 /*! return whether data exists
4810 *
4811 * - darray, each darray[i] and darray[i]->data must be set
4812 *
4813 * return 1 if true, 0 otherwise
4814 *//*-------------------------------------------------------------------*/
gifti_image_has_data(const gifti_image * gim)4815 int gifti_image_has_data(const gifti_image * gim)
4816 {
4817 int c;
4818
4819 if( !gim || !gim->darray || gim->numDA <= 0 ) return 0;
4820
4821 for( c = 0; c < gim->numDA; c++ )
4822 if( !gim->darray[c] ) {
4823 if(G.verb > 3) fprintf(stderr,"** gim missing data at ind %d\n",c);
4824 return 0;
4825 }
4826
4827 return 1;
4828 }
4829
4830 /*---------------------------------------------------------------------*/
4831 /*! duplicate the given gifti_image struct, optionally including data
4832 *
4833 * Allocate and copy all contents of the gifti_image structure and
4834 * sub-structures. If copy_data is not set, all data pointers within
4835 * DataArray elements will be left as NULL.
4836 *
4837 * return a pointer to the newly allocated structure
4838 *//*-------------------------------------------------------------------*/
gifti_copy_gifti_image(const gifti_image * gold,int copy_data)4839 gifti_image * gifti_copy_gifti_image(const gifti_image * gold, int copy_data)
4840 {
4841 gifti_image * gnew;
4842 int c, errs = 0; /* check for errors at each step */
4843
4844 if( !gold ){ fprintf(stderr,"** copy_gim: input is NULL\n"); return NULL; }
4845
4846 if(G.verb > 3) fprintf(stderr,"++ copying gifti_image (%s data)...\n",
4847 copy_data ? "with" : "without" );
4848
4849 gnew = (gifti_image *)calloc(1, sizeof(gifti_image));
4850 if(!gnew){fprintf(stderr,"** copy_gim, failed alloc\n"); return NULL;}
4851
4852 /* copy one piece at a time */
4853 gnew->numDA = gold->numDA;
4854 gnew->version = gifti_strdup(gold->version);
4855
4856 errs = gifti_copy_nvpairs(&gnew->meta, &gold->meta);
4857 if(!errs) errs=gifti_copy_LabelTable(&gnew->labeltable, &gold->labeltable);
4858
4859 /* if needed, create and copy the DataArray list */
4860 if( !errs && gold->darray && gold->numDA > 0 ) {
4861 gnew->darray=(giiDataArray**)malloc(gold->numDA*sizeof(giiDataArray*));
4862 if( !gnew->darray ) {
4863 fprintf(stderr,"** copy_gim: failed to alloc darray of len %d\n",
4864 gold->numDA);
4865 errs = 1;
4866 }
4867
4868 for( c = 0; !errs && c < gold->numDA; c++ ) {
4869 gnew->darray[c] = gifti_copy_DataArray(gold->darray[c], copy_data);
4870 if( !gnew->darray[c]) errs++;
4871 }
4872 }
4873
4874 /* and copy the extras */
4875 if( !errs ) {
4876 gnew->swapped = gold->swapped;
4877 gnew->compressed = gold->compressed;
4878 errs = gifti_copy_nvpairs(&gnew->ex_atrs, &gold->ex_atrs);
4879 }
4880
4881 /* on failure, blow everything away */
4882 if( errs ) { gifti_free_image(gnew); return NULL; }
4883
4884 return gnew;
4885 }
4886
4887 /*---------------------------------------------------------------------*/
4888 /*! convert all data to NIFTI_TYPE_FLOAT32
4889 *
4890 * for each DataArray
4891 * if data exists, convert it (free old, allocate new)
4892 * else, leave as NULL
4893 *//*-------------------------------------------------------------------*/
gifti_convert_to_float(gifti_image * gim)4894 int gifti_convert_to_float(gifti_image * gim)
4895 {
4896 giiDataArray * da;
4897 void * olddata;
4898 int oldtype, newtype = NIFTI_TYPE_FLOAT32; /* for future? */
4899 int c, nbyper, oldnbyper;
4900
4901 if( !gim ) return 1;
4902
4903 if( !gim->darray || gim->numDA <= 0 ) {
4904 if( G.verb > 1 ) fprintf(stderr,"-- no darray to convert to float\n");
4905 return 0;
4906 }
4907
4908 if( G.verb > 1 ) fprintf(stderr,"++ converting gifti_image to float\n");
4909
4910 /* first, check for problems in any DA */
4911 for( c = 0; c < gim->numDA; c++ ) {
4912 da = gim->darray[c];
4913 if( !da ) continue;
4914
4915 /* if the data has an unknown type, panic into error */
4916 if( da->data && !gifti_valid_datatype(da->datatype, 0) ) {
4917 fprintf(stderr,"** unknown dtype %d, cannot convert to floats\n",
4918 da->datatype);
4919 return 1;
4920 }
4921
4922 /* dimension information must be consistent */
4923 if( !gifti_valid_dims(da, 1) ) return 1;
4924 }
4925
4926 /* will update nbyper in each DA, below */
4927 gifti_datatype_sizes(newtype, &nbyper, NULL);
4928
4929 /* all is well, update all DA elements */
4930 for( c = 0; c < gim->numDA; c++ ) {
4931 da = gim->darray[c];
4932 if( !da ) continue;
4933
4934 oldtype = da->datatype;
4935 oldnbyper = da->nbyper;
4936
4937 if( oldtype == newtype ) {
4938 if(G.verb > 3) fprintf(stderr,"++ convert DA[%d] already type %s\n",
4939 c, gifti_datatype2str(newtype));
4940 continue; /* no change needed */
4941 }
4942
4943 if(G.verb > 3)
4944 fprintf(stderr,"++ convert DA[%d] from %s to %s\n", c,
4945 gifti_datatype2str(oldtype), gifti_datatype2str(newtype));
4946
4947 if( oldtype == newtype ) continue; /* no change needed */
4948
4949 /* start trashing DataArray: adjust datatype and nbyper */
4950 da->datatype = newtype;
4951 da->nbyper = nbyper;
4952
4953 /* if there is no data, we are done with this DA */
4954 if( !da->data ) {
4955 if( G.verb > 4 ) fprintf(stderr,"-- no data to convert\n");
4956 continue;
4957 }
4958
4959 /* store old data pointer, and allocate new data space */
4960 olddata = da->data;
4961 da->data = NULL; /* so alloc_DA_data doesn't whine */
4962 if( gifti_alloc_DA_data(gim, &c, 1) ) return 1;
4963
4964 /* copy the data, and nuke the old stuff */
4965 if( copy_data_as_float(da->data,newtype,olddata,oldtype,da->nvals) ) {
4966 /* undo this copy and return */
4967 free(da->data);
4968 da->data = olddata; da->datatype = oldtype; da->nbyper = oldnbyper;
4969 return 1;
4970 }
4971
4972 free(olddata); /* done with this, data has been copied */
4973 }
4974
4975 return 0;
4976 }
4977
4978 /* copy old data to float array */
copy_data_as_float(void * dest,int dtype,void * src,int stype,long long nvals)4979 static int copy_data_as_float(void * dest, int dtype, void * src, int stype,
4980 long long nvals)
4981 {
4982 float * dptr = (float *)dest;
4983 long long c;
4984
4985 if( !dest || !src ) {
4986 fprintf(stderr,"** copy_data_as_float: missing pointers\n");
4987 return 1;
4988 }
4989
4990 if( dtype != NIFTI_TYPE_FLOAT32 ) {
4991 fprintf(stderr,"** can't copy to float with dest type %d\n", dtype);
4992 return 1;
4993 }
4994
4995 switch( stype ) {
4996 default: {
4997 fprintf(stderr,"** copy2float: can't handle src type %d\n",stype);
4998 return 1;
4999 }
5000
5001 case NIFTI_TYPE_INT8: {
5002 char * sptr = (char *)src;
5003 for( c = 0; c < nvals; c++ ) dptr[c] = (float)sptr[c];
5004 break;
5005 }
5006
5007 case NIFTI_TYPE_INT16: {
5008 short * sptr = (short *)src;
5009 for( c = 0; c < nvals; c++ ) dptr[c] = (float)sptr[c];
5010 break;
5011 }
5012
5013 case NIFTI_TYPE_INT32: {
5014 int * sptr = (int *)src;
5015 for( c = 0; c < nvals; c++ ) dptr[c] = (float)sptr[c];
5016 break;
5017 }
5018
5019 case NIFTI_TYPE_INT64: {
5020 long long * sptr = (long long *)src;
5021 for( c = 0; c < nvals; c++ ) dptr[c] = (float)sptr[c];
5022 break;
5023 }
5024
5025 case NIFTI_TYPE_UINT8: {
5026 unsigned char * sptr = (unsigned char *)src;
5027 for( c = 0; c < nvals; c++ ) dptr[c] = (float)sptr[c];
5028 break;
5029 }
5030
5031 case NIFTI_TYPE_UINT16: {
5032 unsigned short * sptr = (unsigned short *)src;
5033 for( c = 0; c < nvals; c++ ) dptr[c] = (float)sptr[c];
5034 break;
5035 }
5036
5037 case NIFTI_TYPE_UINT32: {
5038 unsigned int * sptr = (unsigned int *)src;
5039 for( c = 0; c < nvals; c++ ) dptr[c] = (float)sptr[c];
5040 break;
5041 }
5042
5043 case NIFTI_TYPE_UINT64: {
5044 unsigned long long * sptr = (unsigned long long *)src;
5045 for( c = 0; c < nvals; c++ ) dptr[c] = (float)sptr[c];
5046 break;
5047 }
5048
5049 case NIFTI_TYPE_FLOAT32: {
5050 float * sptr = (float *)src;
5051 for( c = 0; c < nvals; c++ ) dptr[c] = sptr[c];
5052 break;
5053 }
5054
5055 case NIFTI_TYPE_FLOAT64: {
5056 double * sptr = (double *)src;
5057 for( c = 0; c < nvals; c++ ) dptr[c] = (float)sptr[c];
5058 break;
5059 }
5060 }
5061
5062 return 0;
5063 }
5064