1 /*
2   NrrdIO: stand-alone code for basic nrrd functionality
3   Copyright (C) 2013, 2012, 2011, 2010, 2009  University of Chicago
4   Copyright (C) 2008, 2007, 2006, 2005  Gordon Kindlmann
5   Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998  University of Utah
6 
7   This software is provided 'as-is', without any express or implied
8   warranty.  In no event will the authors be held liable for any
9   damages arising from the use of this software.
10 
11   Permission is granted to anyone to use this software for any
12   purpose, including commercial applications, and to alter it and
13   redistribute it freely, subject to the following restrictions:
14 
15   1. The origin of this software must not be misrepresented; you must
16      not claim that you wrote the original software. If you use this
17      software in a product, an acknowledgment in the product
18      documentation would be appreciated but is not required.
19 
20   2. Altered source versions must be plainly marked as such, and must
21      not be misrepresented as being the original software.
22 
23   3. This notice may not be removed or altered from any source distribution.
24 */
25 
26 #include "NrrdIO.h"
27 
28 static void
_nrrdSwap16Endian(void * _data,size_t N)29 _nrrdSwap16Endian(void *_data, size_t N) {
30   unsigned short *data, dd, fix, mask;
31   size_t I;
32 
33   if (!_data) {
34     return;
35   }
36   data = AIR_CAST(unsigned short *, _data);
37   mask = AIR_CAST(unsigned short, 0x00FFu);
38   for (I=0; I<N; I++) {
39     dd = data[I];
40     fix = (dd & mask); dd >>= 0x08;
41     fix = (dd & mask) | AIR_CAST(unsigned short, fix << 0x08);
42     data[I] = fix;
43   }
44 }
45 
46 static void
_nrrdSwap32Endian(void * _data,size_t N)47 _nrrdSwap32Endian(void *_data, size_t N) {
48   unsigned int *data, dd, fix, mask;
49   size_t I;
50 
51   if (!_data) {
52     return;
53   }
54   data = AIR_CAST(unsigned int *, _data);
55   mask = 0x000000FFu;
56   for (I=0; I<N; I++) {
57     dd = data[I];
58     fix = (dd & mask);                 dd >>= 0x08;
59     fix = (dd & mask) | (fix << 0x08); dd >>= 0x08;
60     fix = (dd & mask) | (fix << 0x08); dd >>= 0x08;
61     fix = (dd & mask) | (fix << 0x08);
62     data[I] = fix;
63   }
64 }
65 
66 static void
_nrrdSwap64Endian(void * _data,size_t N)67 _nrrdSwap64Endian(void *_data, size_t N) {
68   airULLong *data, dd, fix, mask;
69   size_t I;
70 
71   if (!_data) {
72     return;
73   }
74   data = AIR_CAST(airULLong *, _data);
75   mask = AIR_ULLONG(0x00000000000000FF);
76   for (I=0; I<N; I++) {
77     dd = data[I];
78     fix = (dd & mask);                 dd >>= 0x08;
79     fix = (dd & mask) | (fix << 0x08); dd >>= 0x08;
80     fix = (dd & mask) | (fix << 0x08); dd >>= 0x08;
81     fix = (dd & mask) | (fix << 0x08); dd >>= 0x08;
82     fix = (dd & mask) | (fix << 0x08); dd >>= 0x08;
83     fix = (dd & mask) | (fix << 0x08); dd >>= 0x08;
84     fix = (dd & mask) | (fix << 0x08); dd >>= 0x08;
85     fix = (dd & mask) | (fix << 0x08);
86     data[I] = fix;
87   }
88 }
89 
90 static void
_nrrdNoopEndian(void * data,size_t N)91 _nrrdNoopEndian(void *data, size_t N) {
92   AIR_UNUSED(data);
93   AIR_UNUSED(N);
94   return;
95 }
96 
97 static void
_nrrdBlockEndian(void * data,size_t N)98 _nrrdBlockEndian(void *data, size_t N) {
99   char me[]="_nrrdBlockEndian";
100 
101   AIR_UNUSED(data);
102   AIR_UNUSED(N);
103   fprintf(stderr, "%s: WARNING: can't fix endiannes of nrrd type %s\n", me,
104           airEnumStr(nrrdType, nrrdTypeBlock));
105 }
106 
107 static void
108 (*_nrrdSwapEndian[])(void *, size_t) = {
109   _nrrdNoopEndian,         /*  0: nobody knows! */
110   _nrrdNoopEndian,         /*  1:   signed 1-byte integer */
111   _nrrdNoopEndian,         /*  2: unsigned 1-byte integer */
112   _nrrdSwap16Endian,       /*  3:   signed 2-byte integer */
113   _nrrdSwap16Endian,       /*  4: unsigned 2-byte integer */
114   _nrrdSwap32Endian,       /*  5:   signed 4-byte integer */
115   _nrrdSwap32Endian,       /*  6: unsigned 4-byte integer */
116   _nrrdSwap64Endian,       /*  7:   signed 8-byte integer */
117   _nrrdSwap64Endian,       /*  8: unsigned 8-byte integer */
118   _nrrdSwap32Endian,       /*  9:          4-byte floating point */
119   _nrrdSwap64Endian,       /* 10:          8-byte floating point */
120   _nrrdBlockEndian         /* 11: size user defined at run time */
121 };
122 
123 void
nrrdSwapEndian(Nrrd * nrrd)124 nrrdSwapEndian(Nrrd *nrrd) {
125 
126   if (nrrd
127       && nrrd->data
128       && !airEnumValCheck(nrrdType, nrrd->type)) {
129     _nrrdSwapEndian[nrrd->type](nrrd->data, nrrdElementNumber(nrrd));
130   }
131   return;
132 }
133