]> Creatis software - clitk.git/blob - common/clitkXdrImageIOWriter.cxx
DDS: print standard containers
[clitk.git] / common / clitkXdrImageIOWriter.cxx
1 /*=========================================================================
2   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4   Authors belong to: 
5   - University of LYON              http://www.universite-lyon.fr/
6   - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
7   - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
8
9   This software is distributed WITHOUT ANY WARRANTY; without even
10   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11   PURPOSE.  See the copyright notices for more information.
12
13   It is distributed under dual licence
14
15   - BSD        See included LICENSE.txt file
16   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ======================================================================-====*/
18 /**
19  * @file   clitkXdrImageIO.cxx
20  * @author Simon Rit <simon.rit@gmail.com>
21  * @date   Sun Jun  1 22:12:20 2008
22  *
23  * @brief
24  *
25  *
26  */
27
28 #include "clitkXdrImageIO.h"
29 #include "clitkCommon.h"
30
31 #include <sys/stat.h>
32
33 //From mbfield.h
34 #if !defined(unix) && !defined(__APPLE__)
35 //#define _read  readfix
36 #endif
37 #define AVSINT ptrdiff_t
38 #define AVS_ERROR
39 #define AVS_OK
40
41 //From portdefs.h
42 #if defined(unix) || defined(__APPLE__)
43 #define O_BINARY 0
44 #define setmode(a,b) 0
45 #endif
46
47 #ifndef __LARGE__
48 #  if defined(__GNUC__) || defined(unix) || defined(__APPLE__)
49
50      typedef long long Q_INT64;
51      typedef unsigned long long Q_UINT64;
52 #    define Q_INT64_CONST(x) (x##ll)
53 #    define Q_UINT64_CONST(x) (x##llu) /* gcc also allows ull */
54      /* When using MINGW with MS(V)CRT DLL, use MS format modifier. */
55 #    ifdef __MSVCRT__
56 #      define Q_INT64_FORMAT "I64"
57 #    else
58 #      define Q_INT64_FORMAT "L"
59 #    endif
60 #  elif defined(__BORLANDC__) || defined(__WATCOMC__) || defined(_MSC_VER)
61      typedef __int64 Q_INT64;
62      typedef unsigned __int64 Q_UINT64;
63 #    define Q_INT64_CONST(x) (x##i64)
64 #    define Q_UINT64_CONST(x) (x##ui64) /* i64u is not allowed! */
65 #    ifdef _MSC_VER
66 #      define Q_INT64_FORMAT "I64"
67 #    else
68 #      define Q_INT64_FORMAT "L"
69 #    endif
70 #  else
71 #    error No 64 bit integers known for this compiler, edit portdefs.h.
72 #  endif
73 #endif
74
75 bool clitk::XdrImageIO::CanWriteFile(const char* FileNameToWrite)
76 { std::string filename(FileNameToWrite);
77   std::string filenameext = GetExtension(filename);
78   if (filenameext != std::string("xdr")) return false;
79   return true;
80 }
81
82 void clitk::XdrImageIO::Write(const void* buffer)
83 { char *s = const_cast<char*>("");
84   WriteImage( m_FileName.c_str(), s, s, 0, -1, 0, 2, 0, 0, 0, 0, buffer);
85 }
86
87 // Based on a true story by the Nederlands Kanker Instituut (AVS_WXDR.CPP from the 20091216)
88
89 /************************************************************************/
90 /*                             INCLUDE FILES                            */
91 /************************************************************************/
92
93 #include <string.h>
94 #include <stdio.h>
95 #include <math.h>
96 #include <stdlib.h>
97 #include <limits.h>
98 #if !defined(unix) && !defined(__APPLE__)
99 #include <io.h>
100 #endif
101 #include <fcntl.h>
102 #include <errno.h>
103
104 #include <algorithm>
105
106 #ifdef WIN32
107 // don't use min() and max() macros indirectly defined by windows.h, 
108 // but use portable std::min() and std:max() instead
109 #ifndef NOMINMAX
110 #define NOMINMAX
111 #endif
112 #include <windows.h>
113 #endif
114
115 /************************************************************************/
116 /*                    DEFINES, ENUMERATED TYPES AND CONSTANTS           */
117 /************************************************************************/
118
119 #pragma pack (1)
120
121 // Fields with data size>8GB (having UINT_MAX short pixels) cannot be compressed using
122 // NKI_MODE2 struct because iOrgSize has type "unsigned int". In that case use NKI_MODE2_64BITS.
123 // The type of structure is indicated as follows:
124 //
125 // iOrgSize==0: NKI_MODE2_64BITS
126 // otherwise  : NKI_MODE2
127 //
128 // Compression modes 1 and 3 (without CRCs) only use the first 2 members (iOrgSize and iMode).
129
130 typedef struct
131 {
132   unsigned int iOrgSize;          /* in pixels (i.e. shorts) */
133   unsigned int iMode;             /* 1, 2, 3 or 4 */
134   unsigned int iCompressedSize;   /* in bytes, excluding header */
135   unsigned int iOrgCRC;           /* CRC of the data (no coords etc) */
136   unsigned int iCompressedCRC;    /* CRC of the compressed data, excluding this header */
137 } NKI_MODE2;
138
139 typedef struct
140 {
141   unsigned int iOrgSize;          /* in pixels (i.e. shorts) */
142   unsigned int iMode;             /* 1, 2, 3 or 4 */
143   unsigned int iCompressedSize;   /* in bytes, excluding header */
144   unsigned int iOrgCRC;           /* CRC of the data (no coords etc) */
145   unsigned int iCompressedCRC;    /* CRC of the compressed data, excluding this header */
146   unsigned int iPad;              /* unused */
147   Q_UINT64     i64OrgSize;        /* used for more than UINT_MAX pixels, indicated by iOrgSize==0 (0-vector not compressed) */ 
148   Q_UINT64     i64CompressedSize; /* value in BYTES, used for more than UINT_MAX PIXELS, indicated by iCompressedSize==0 */ 
149   Q_UINT64     i64Future1;
150   Q_UINT64     i64Future2;
151 } NKI_MODE2_64BITS;
152
153 #pragma pack ()
154
155 // Changed next to static function in stead of macro so it can
156 // have a return value to check in the calling function.
157 // It could be made inline as well, but there is no real time
158 // punishment from the extra layer of function calls.
159
160 // note: some compilers do not like comments ending in a backslash.
161 // so use macro functions to exclude.
162
163
164 /************************************************************************/
165 /*                             GLOBAL VARIABLES                         */
166 /************************************************************************/
167
168 static const unsigned long CRC32_table[256] = {
169       0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
170       0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
171       0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
172       0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
173       0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
174       0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
175       0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
176       0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
177       0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
178       0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
179       0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
180       0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
181       0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
182       0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
183       0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
184       0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
185       0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
186       0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
187       0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
188       0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
189       0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
190       0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
191       0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
192       0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
193       0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
194       0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
195       0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
196       0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
197       0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
198       0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
199       0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
200       0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
201       0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
202       0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
203       0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
204       0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
205       0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
206       0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
207       0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
208       0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
209       0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
210       0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
211       0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
212 };
213
214 /************************************************************************/
215 /*                             MODULE FUNCTIONS                         */
216 /************************************************************************/
217
218 #ifdef __WATCOMC__
219 _WCRTLINK
220 #endif
221 int writefix(int file, const void *buf, unsigned int count)
222 { int j, k, total=0;
223
224   for (unsigned i=0; i<count; i+=16384)
225   { j = count - i;
226     if (j>16384) j=16384;
227
228     k=write(file, (char *)buf+i, j);
229     if (k < 0) return k;
230
231     total += k;
232
233     if (k != j) break;
234   }
235
236   return total;
237 }
238
239
240 /*
241   Version of write() that takes special action in case of
242   standard output.  Based on commented out macro above.
243   This function overloads the <cstdio> (or stdio.h for old style C++)
244   write() function.
245 */
246
247 // Like the original macro, we do /not/ want writefix from mbfield.c.
248 #ifdef write
249 #undef write
250 #endif
251 static int wxdr_write(int handle, const void * buf, unsigned len)
252 {
253   // if (handle == 1) // stdout
254   if (handle == fileno(stdout))
255   {
256 #ifdef WIN32
257     // Behave as C standard library write(): return number of bytes
258     // written or -1 and errno set on error.
259     fflush(stdout);
260     DWORD dwBytesWritten;
261     if (!WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, len,
262                    &dwBytesWritten, NULL))
263     {
264       // There is no simple 1-to-1 mapping between GetLastError()
265       // values that WriteFile() can return (quite a lot) and the two
266       // errno values that write() can return.  So return EACCES in
267       // almost all cases.
268       switch (GetLastError())
269       { case ERROR_INVALID_HANDLE:
270           errno = EBADF ; break;
271         default:
272           errno = EACCES; break;
273       }
274       return -1;
275     }
276     else
277       return (int)dwBytesWritten; // May still be < len!
278       // And... write() may write a maximum of UINT_MAX-1 bytes, whereas
279       // WriteFile() may write UINT_MAX bytes at once.  But since
280       // int(UINT_MAX) == -1 this will pose an actual problem in the
281       // (far?) future.
282 #else // !WIN32
283     //const int oldmode = setmode(handle, O_BINARY);//commented out by joel
284     const int iBytesWritten = write(handle, buf, len);
285     const int saveerrno = errno; // setmode() may change errno.
286     //if (oldmode != -1) setmode(handle, oldmode); //commented out by joel
287     errno = saveerrno;
288     return iBytesWritten;
289 #endif // !WIN32
290   }
291   else
292     return write(handle, buf, len);
293 }
294
295 /*
296   Checked write().
297   Behaves like win32 WriteFile() and returns a Boolean to indicate
298   success or failure, where failure almost invariably means disc full.
299
300   !!! SIDE EFFECT !!!
301
302   In case of failure, this function issues an AVS error message
303   and closes the file (if handle != 1).  It is up to the calling
304   function to return the AVS_ERROR state and before that do things
305   like close other files, free memory etc.  This way, there is less
306   chance of erroneously duplicated code, like in:
307     written = write(f, temp, strlen(temp));
308     if (written == -1 || written != strlen(temp))
309     { AVSerror(...);
310       if (f != fileno(stdout)) close(f);
311       return AVS_ERROR;
312     }
313     written = write(f, buf, buflength)
314     if (written == -1 || written != strlen(temp)) {
315       // oops, wrong length copy'n'pasted
316
317   If more elaborate error handling is needed then the calling
318   functuon should use the (overloaded) write() and act on its return
319   value (and the value of errno) accordingly.
320
321   It does /not/ close stdout.
322
323   !!! SIDE EFFECT !!!
324
325   Note that checked_write() takes a size_t for len, whereas write() takes
326   an unsigned int of 4 bytes. On a 64 bits OS a size_t will be an 8 byte integer, 
327   enabling more than UINT_MAX bytes to write at once.
328 */
329 static bool checked_write(int handle, const void * buf, size_t len, char **buffer)
330 { if (buffer && !handle)
331   { memcpy(*buffer, buf, len);
332     (*buffer) += len;
333     return true;
334   }
335   if (buffer && handle)
336   { (*buffer) += len;
337     return true;
338   }
339   else
340   { for(int i=0; i<2; i++)
341     { int byteswritten;
342       size_t remaining;
343       int chunksize;
344
345       //If write fails, test if not related to big buffer problem
346       //Bug report http://support.microsoft.com/kb/899149 entitled
347       //"You cannot call the fwrite function to write to a buffer
348       // that is larger than 64 MB in Visual C++ 2005,
349       // in Visual C++ .NET 2003, or in Visual C++ .NET 2002"
350       // NB: same thing for write function in binary mode
351       if (i==0)
352       { remaining = len;
353         // call wxdr_write (for handle!=fileno(stdout) a wrapper for write) several times 
354         // to interpret the signed 32-bit return value correctly
355         while (remaining>0)
356         { chunksize = (int)std::min(remaining, (size_t)INT_MAX);
357           byteswritten = wxdr_write(handle, buf, chunksize);
358           if (byteswritten == chunksize)
359             remaining -= chunksize;
360           else
361             break; // try writefix in the next round
362         }
363         if (remaining == 0)
364           return true;
365       }
366       else
367       { remaining = len;   
368         // call writefix (in mbfield.c) several times to interpret the signed 32-bit 
369         // return value correctly. writefix uses chunks of 16384 bytes
370         while (remaining>0)
371         { chunksize = (int)std::min(remaining, (size_t)INT_MAX);
372           byteswritten = writefix(handle, buf, chunksize);
373           if (byteswritten == chunksize)
374             remaining -= chunksize;
375           else
376             break; // even writefix failed: return error        
377         }
378         if (remaining == 0)
379           return true;
380       }
381     }
382     // Note: file is open in binary mode, no need to compensate
383     // for a value of byteswritten > len due to \n -> \r\n conversions.
384     // (write() on a text stream is implementation dependent.)
385     if (handle != fileno(stdout)) close(handle);
386     AVSerror("Avs_wxdr: write failed, disk full?");
387     return false;
388   }
389 }
390
391 /* coder for NKI private compressed pixel data
392    arguments: dest    = (in) points to area where compressed destination data is written (byte)
393               src     = (in) points to uncompressed source data (short)
394               npixels = (in) number of pixels to compress
395
396    The return value is the number of bytes in the compressed data (maximal 3*npixels+10, typical 0.52*npixels)
397
398    if iMode == 1 then
399    - The first 4 bytes contain the number of short-int pixels
400    - The following 4 bytes contain iMode=1
401    - The rest is the compressed image
402
403    if iMode == 2 then
404    - The first 4 bytes contain the number of short-int pixels
405    - The following 4 bytes contain iMode=2
406    - The following 4 bytes contain the size of the compressed image (in bytes)
407    - The following 4 bytes contain the CRC of the original image
408    - The following 4 bytes contain the CRC of the compressed image
409    - The rest is the compressed image
410    - The compressed size will be even (padded by a zero if necessary).
411
412    if iMode == 3 then
413    - The first 4 bytes contain the number of short-int pixels
414    - The following 4 bytes contain iMode=3
415    - The rest is the compressed image, including 4 bit differences
416
417    if iMode == 4 then
418    - The first 4 bytes contain the number of short-int pixels
419    - The following 4 bytes contain iMode=4
420    - The following 4 bytes contain the size of the compressed image (in bytes)
421    - The following 4 bytes contain the CRC of the original image
422    - The following 4 bytes contain 0
423    - The rest is the compressed image, including 4 bit differences
424    - The compressed size will be even (padded by a zero if necessary).
425
426    iMode 1 and iMode 2 are identical, except for the CRC data that is included for iMode 2
427    iMode 3 and iMode 4 are identical, except for the CRC data that is included for iMode 4
428 */
429
430 // optimized settings for the 4 bit run compressor (mode 3 and 4)
431
432 #define MINZEROS 5              // shortest RLE (2 byte overhead, but breaks 4bit run)
433 #define MIN4BIT  6              // shortest 4 bit run (6 bytes compressed to 5 bytes)
434
435 // This internal routine converts an 8 bit difference string into a 4 bit one
436 static signed char *recompress4bit(int n, signed char *dest)
437 { signed char *p, *q;
438   int val;
439
440   n = n & 0xfe;
441   dest -= n;
442   p = dest;
443   val = (((int)p[0])<<4) | (p[1]&15);
444   p += 2;
445   *dest++ = -0x40; // 192 (0xc0) does not fit between -128..127: maps to -64 (0x40) in 2's complement
446   *dest++ = (signed char)n;
447   q = dest++;
448   n -= 2;
449   while(n>0)
450   { *dest++ = (signed char)((((int)p[0])<<4) | (p[1]&15));
451     p += 2;
452     n -= 2;
453   }
454   q[0] = (signed char)val;
455
456   return dest;
457 }
458
459
460 static size_t nki_private_compress(signed char  *dest, short int  *src, size_t npixels, int iMode)
461 { unsigned long         iCRC;
462   unsigned long         iCRC2;
463   unsigned int          iHeaderSize=8;                      // value for iMode==1 and iMode==3
464   register int          val;
465   size_t                i,j;
466   NKI_MODE2*            pHeader = (NKI_MODE2*)dest;
467   NKI_MODE2_64BITS*     pHeader_64bits = (NKI_MODE2_64BITS*)dest;
468   size_t                iBufferSize;
469
470   iBufferSize = (npixels / 2) * 3;                          // Buffer is sizeof(NKI_MODE2_64BITS) + 10 bytes larger
471
472   /* Up till now only Mode=1 .. 4 are supported */
473   if ((iMode < 1) || (iMode > 4))
474     return 0;
475
476   /* Create the header */
477   pHeader->iMode = iMode;
478
479   if (sizeof(int*)>sizeof(int) && npixels>UINT_MAX)         // On a 64 bits OS we want to store files>4GB 
480   { pHeader_64bits->iOrgSize   = 0;                         // This indicates>4GB file (0-vector is not compressed)
481     pHeader_64bits->i64OrgSize = npixels;    
482     iHeaderSize = sizeof(NKI_MODE2_64BITS);
483     dest += sizeof(NKI_MODE2_64BITS);
484   }
485   else
486   { pHeader->iOrgSize = (unsigned int)(npixels & UINT_MAX); // store 32 bit number as first member
487
488     if (iMode==2 || iMode==4)
489       iHeaderSize = sizeof(NKI_MODE2);
490     dest += iHeaderSize;
491   }
492
493   /* Create the compressed image */
494
495   if (iMode == 1)
496   { *(short int *)dest = *src;
497     dest+=2;
498
499     npixels--;
500
501     do
502     { val = src[1] - src[0];
503       src++;
504
505       if (val == 0)                            /* run length-encode zero differences */
506       { for (i=2;; i++)
507         { if (i>=npixels || src[i-1]!=src[-1] || i==256)
508           { if (i==2)
509               *dest++=0;
510             else
511             { *dest++  =  -128; // hexadecimal 0x80
512               *dest++  = (signed char)(i-1);
513               npixels -= (i-2);
514               src     += (i-2);
515             }
516             break;
517           }
518         }
519       }
520       else if (val >= -64 && val <= 63)         /* small difference coded as one byte */
521       { *dest = (signed char)val;
522         dest++;
523       }
524       else if (val >= -0x3F00 && val <= 0x3EFF) /* large differences coded as two bytes */
525       { dest[0] = (signed char)((val>>8) ^ 0x40);
526         dest[1] = (signed char)val;
527         dest+=2;
528       }
529       else                                      /* if very large differences code abs val as three bytes */
530       { *dest++ = 0x7F;
531         *dest++ = (signed char)(src[0]>>8);
532         *dest++ = (signed char)(src[0]);
533       }
534       /* Are we beyond the allocated memory? */
535       if ((size_t)(dest - (signed char*)pHeader) > iBufferSize)
536         return 0;
537     }
538     while (--npixels);
539   }
540
541   else if (iMode == 2)
542   { iCRC  = 0;
543     iCRC2 = 0;
544
545     *(short int *)dest = val = *src;
546     iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (unsigned char) val    ] ^ ((iCRC2 >> 8));
547     iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (unsigned char)(val>>8)] ^ ((iCRC2 >> 8));
548     iCRC  = CRC32_table[(unsigned char)iCRC  ^ (unsigned char) val    ] ^ ((iCRC  >> 8));
549     iCRC  = CRC32_table[(unsigned char)iCRC  ^ (unsigned char)(val>>8)] ^ ((iCRC  >> 8));
550     dest+=2;
551     npixels--;
552
553     do
554     { val = src[1] - src[0];
555       src++;
556       iCRC  = CRC32_table[(unsigned char)iCRC  ^ (unsigned char) src[0]    ] ^ ((iCRC  >> 8));
557       iCRC  = CRC32_table[(unsigned char)iCRC  ^ (unsigned char)(src[0]>>8)] ^ ((iCRC  >> 8));
558
559       if (val == 0)                            /* run length-encode zero differences */
560       { for (i=2;; i++)
561         { if (i>=npixels || src[i-1]!=src[-1] || i==256)
562           { if (i==2)
563             { *dest++=0;
564               iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ 0    ] ^ ((iCRC2 >> 8));
565             }
566             else
567             { *dest++  =  -128; // hexadecimal 0x80
568               iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ 0x80 ] ^ ((iCRC2 >> 8));
569               *dest++  = (signed char)(i-1);
570               iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (i-1)] ^ ((iCRC2 >> 8));
571               npixels -= (i-2);
572
573               for (j=0; j<i-2; j++)
574               { src++;
575                 iCRC = CRC32_table[(unsigned char)iCRC  ^ (unsigned char) src[0]    ] ^ ((iCRC  >> 8));
576                 iCRC = CRC32_table[(unsigned char)iCRC  ^ (unsigned char)(src[0]>>8)] ^ ((iCRC  >> 8));
577               }
578             }
579             break;
580           }
581         }
582       }
583       else if (val >= -64 && val <= 63)         /* small difference coded as one byte */
584       { *dest = (signed char)val;
585         iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (unsigned char)val     ] ^ ((iCRC2 >> 8));
586         dest++;
587       }
588       else if (val >= -0x3F00 && val <= 0x3EFF) /* large differences coded as two bytes */
589       { dest[0] = (signed char)((val>>8) ^ 0x40);
590         iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (unsigned char)dest[0] ] ^ ((iCRC2 >> 8));
591         dest[1] = (signed char)val;
592         iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (unsigned char)val     ] ^ ((iCRC2 >> 8));
593         dest+=2;
594       }
595       else                                      /* if very large differences code abs val as three bytes */
596       { dest[0] = 0x7F;
597         iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ 0x7f                   ] ^ ((iCRC2 >> 8));
598         val     = src[0];
599         dest[1] = (signed char)(val>>8);
600         iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (unsigned char)(val>>8)] ^ ((iCRC2 >> 8));
601         dest[2] = (signed char)val;
602         iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (unsigned char)val     ] ^ ((iCRC2 >> 8));
603         dest+=3;
604       }
605       /* Are we beyond the allocated memory? */
606       if ((size_t)(dest - (signed char*)pHeader) > iBufferSize)
607         return 0;
608     }
609     while (--npixels);
610     
611     if ((dest - (signed char*)pHeader - iHeaderSize)<UINT_MAX) // store 32 bit number as third member
612       pHeader->iCompressedSize = 
613         (unsigned int)(dest - (signed char*)pHeader - iHeaderSize);
614     else                                                       // store 64 bit number in extended structure
615       pHeader_64bits->i64CompressedSize = dest - (signed char*)pHeader -iHeaderSize;
616
617     /* Pad it to get an even length */
618     if (pHeader->iCompressedSize & 1)
619     { *dest++ = 0;
620       iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ 0] ^ ((iCRC2 >> 8));
621       pHeader->iCompressedSize++;
622     }
623
624     pHeader->iOrgCRC        = iCRC;
625     pHeader->iCompressedCRC = iCRC2;
626   }
627
628   /* Create the compressed image - compressor with added 4 bit run */
629
630   else if (iMode == 3)
631   { int n4bit=0;
632     *(short int *)dest = *src;
633     dest+=2;
634     npixels--;
635
636     do
637     { val = src[1] - src[0];
638       src++;
639
640       if (val == 0)                             /* run length-encode zero differences */
641       { for (i=2;; i++)
642         { if (i>=npixels || src[i-1]!=src[-1] || i==256)
643           { if (i<=MINZEROS)                    /* too short run -> write zeros */
644             { for (j=0; j<i-1; j++)
645               { *dest++=0;
646                 n4bit++;
647
648                 if(n4bit>=254)                  /* maximum length 4 bit run */
649                 { dest  = recompress4bit(n4bit, dest);
650                   n4bit = 0;
651                 }
652               }
653             }
654             else
655             { if (n4bit>=MIN4BIT)               /* end (and write) 4 bit run */
656                 dest  = recompress4bit(n4bit, dest);
657
658               n4bit=0;
659               *dest++  = -128; // hexadecimal 0x80
660               *dest++  = (signed char)(i-1);
661             }
662
663             npixels -= (i-2);
664             src     += (i-2);
665             break;
666           }
667         }
668       }
669       else if (val >= -63 && val <= 63)         /* small difference coded as one byte */
670       { if (val >= -8 && val <= 7)
671         { *dest++ = (signed char)val;
672           n4bit++;
673
674           if(n4bit>=254)                        /* maximum length 4 bit run */
675           { dest  = recompress4bit(n4bit, dest);
676             n4bit=0;
677           }
678         }
679         else if(n4bit>=MIN4BIT)                 /* end and write 4 bit run */
680         { j = val;
681           dest  = recompress4bit(n4bit, dest);
682           n4bit=0;
683           *dest++ = (signed char)j;
684         }
685         else
686         { *dest++ = (signed char)val;                   /* end 4 bit run */
687            n4bit  = 0;
688         }
689       }
690       else if (val >= -0x3F00 && val <= 0x3EFF) /* large differences coded as two bytes */
691       { j = val;
692
693         if(n4bit>=MIN4BIT)                      /* end (and write) 4 bit run */
694           dest  = recompress4bit(n4bit, dest);
695
696         n4bit=0;
697         dest[0] = (signed char)((j>>8) ^ 0x40);
698         dest[1] = (signed char)j;
699         dest+=2;
700       }
701       else                                      /* if very large differences code abs val as three bytes */
702       { j = src[0];
703
704         if(n4bit>=MIN4BIT)                      /* end (and write) 4 bit run */
705           dest  = recompress4bit(n4bit, dest);
706
707         n4bit=0;
708         *dest++ = 0x7F;
709         *dest++ = (signed char)(j>>8);
710         *dest++ = (signed char)j;
711       }
712       /* Are we beyond the allocated memory? */
713       if ((size_t)(dest - (signed char*)pHeader) > iBufferSize)
714         return 0;
715     }
716     while (--npixels);
717   }
718
719   /* Create the compressed image - compressor with added 4 bit run and CRC */
720
721   else if (iMode == 4)
722   { int n4bit=0;
723     iCRC  = 0;
724
725     *(short int *)dest = val = *src;
726     iCRC  = CRC32_table[(unsigned char)iCRC  ^ (unsigned char) val    ] ^ ((iCRC  >> 8));
727     iCRC  = CRC32_table[(unsigned char)iCRC  ^ (unsigned char)(val>>8)] ^ ((iCRC  >> 8));
728     dest+=2;
729     npixels--;
730
731     do
732     { val = src[1] - src[0];
733       src++;
734       iCRC  = CRC32_table[(unsigned char)iCRC  ^ (unsigned char) src[0]    ] ^ ((iCRC  >> 8));
735       iCRC  = CRC32_table[(unsigned char)iCRC  ^ (unsigned char)(src[0]>>8)] ^ ((iCRC  >> 8));
736
737       if (val == 0)                             /* run length-encode zero differences */
738       { for (i=2;; i++)
739         { if (i>=npixels || src[i-1]!=src[-1] || i==256)
740           { if (i<=MINZEROS)                    /* too short run -> write zeros */
741             { for (j=0; j<i-1; j++)
742               { *dest++=0;
743                 n4bit++;
744
745                 if(n4bit>=254)                  /* maximum length 4 bit run */
746                 { dest  = recompress4bit(n4bit, dest);
747                   n4bit = 0;
748                 }
749               }
750             }
751             else
752             { if (n4bit>=MIN4BIT)               /* end (and write) 4 bit run */
753                 dest  = recompress4bit(n4bit, dest);
754
755               n4bit=0;
756               *dest++  = -128; // hexadecimal 0x80
757               *dest++  = (signed char)(i-1);
758             }
759
760             npixels -= (i-2);
761             for (j=0; j<i-2; j++)
762             { src++;
763               iCRC = CRC32_table[(unsigned char)iCRC  ^ (unsigned char) src[0]    ] ^ ((iCRC  >> 8));
764               iCRC = CRC32_table[(unsigned char)iCRC  ^ (unsigned char)(src[0]>>8)] ^ ((iCRC  >> 8));
765             }
766             break;
767           }
768         }
769       }
770       else if (val >= -63 && val <= 63)         /* small difference coded as one byte */
771       { if (val >= -8 && val <= 7)
772         { *dest++ = (signed char)val;
773           n4bit++;
774
775           if(n4bit>=254)                        /* maximum length 4 bit run */
776           { dest  = recompress4bit(n4bit, dest);
777             n4bit=0;
778           }
779         }
780         else if(n4bit>=MIN4BIT)                 /* end and write 4 bit run */
781         { j = val;
782           dest  = recompress4bit(n4bit, dest);
783           n4bit=0;
784           *dest++ = (signed char)j;
785         }
786         else
787         { *dest++ = (signed char)val;           /* end 4 bit run */
788            n4bit  = 0;
789         }
790       }
791       else if (val >= -0x3F00 && val <= 0x3EFF) /* large differences coded as two bytes */
792       { j = val;
793
794         if(n4bit>=MIN4BIT)                      /* end (and write) 4 bit run */
795           dest  = recompress4bit(n4bit, dest);
796
797         n4bit=0;
798         dest[0] = (signed char)((j>>8) ^ 0x40);
799         dest[1] = (signed char)j;
800         dest+=2;
801       }
802       else                                      /* if very large differences code abs val as three bytes */
803       { j = src[0];
804
805         if(n4bit>=MIN4BIT)                      /* end (and write) 4 bit run */
806           dest  = recompress4bit(n4bit, dest);
807
808         n4bit=0;
809         *dest++ = 0x7F;
810         *dest++ = (signed char)(j>>8);
811         *dest++ = (signed char)j;
812       }
813       /* Are we beyond the allocated memory? */
814       if ((size_t)(dest - (signed char*)pHeader) > iBufferSize)
815         return 0;
816     }
817     while (--npixels);
818
819     if ((dest - (signed char*)pHeader - iHeaderSize)<UINT_MAX) // store 32 bit number as third member
820       pHeader->iCompressedSize = 
821         (unsigned int)(dest - (signed char*)pHeader - iHeaderSize);
822     else                                                       // store 64 bit number in extended structure
823     { pHeader_64bits->iCompressedSize = 0;
824       pHeader_64bits->i64CompressedSize = dest - (signed char*)pHeader -iHeaderSize;
825     }
826
827     /* Pad it to get an even length */
828     if (pHeader->iCompressedSize & 1)
829     { *dest++ = 0;
830       pHeader->iCompressedSize++;
831     }
832
833     pHeader->iOrgCRC        = iCRC;
834     pHeader->iCompressedCRC = 0;
835   }
836
837   return dest - (signed char*)pHeader;
838 }
839
840
841 void clitk::XdrImageIO::WriteImage(const char* file, char* headerinfo, char* headerfile, int raw,
842                                    int offset, char bLittleEndian, int iNkiCompression,
843                                    int wcoords, int append, int getsize, char *tobuffer, const void* data)
844 { AVSINT   total=1;
845   unsigned int      i;
846   AVSINT   coords=0;
847   int      f=0;
848   char     temp[256];
849   char     *c;
850   char     cSwap;
851   FILE     *fp;
852   long     swap_test = 0x1000000;
853   signed char*  pCompressed = NULL;
854   size_t   FilePos=0;
855   char     **buffer = NULL;
856   int      len=0;
857   char     *buf2;
858   size_t   slen;
859
860   if (bLittleEndian)
861     swap_test = 0x00000001;
862
863   if (getsize)
864   { swap_test = 0xffffffff;     // never swap to save time
865     buffer    = (char **) &len;
866     f         = 1;
867   }
868
869   if (tobuffer)
870   { buf2   = (char *)tobuffer;
871     buffer = &buf2;
872     f      = 0;
873   }
874
875   for (i=0; i<GetNumberOfDimensions(); i++)
876   { total  *= GetDimensions(i);
877     coords += GetDimensions(i);
878   }
879
880   /* Try allocate the compressed fielddata - compression disabled if alloc fails */
881   if ((iNkiCompression > 0) &&
882         (GetComponentType() == itk::ImageIOBase::SHORT) &&
883         (GetPixelType() == itk::ImageIOBase::SCALAR))
884   { pCompressed = (signed char *)malloc((total/2) * 3 + sizeof(NKI_MODE2_64BITS) + 10);
885     if (pCompressed==NULL)
886     { iNkiCompression = 0;
887       AVSwarning("Avs_wxdr: not enough memory to compress data, saving uncompressed");
888     }
889   }
890
891   if (!(tobuffer || getsize))
892   { if (offset != -1)
893     { f = open(file, O_RDWR, 0);
894       if (f < 0)
895       {
896         AVSerror("Avs_wxdr: Opening " << file << "failed.\n" << strerror(errno));
897         free(pCompressed);
898         return AVS_ERROR;
899       }
900       lseek(f, offset, SEEK_SET);
901     }
902     else
903     { if (strlen(file)==0)
904         f = fileno(stdout);
905       else
906       { if (append)
907           f = open(file, O_RDWR | O_APPEND, 0);
908         else
909           f = creat(file, S_IWRITE | S_IREAD);
910       }
911
912       if (f < 0)
913       { AVSerror("Avs_wxdr: Creating " << file << " failed.\n" << strerror(errno));
914         free(pCompressed);
915         return AVS_ERROR;
916       }
917     }
918   }
919
920   if (!raw)
921   { sprintf(temp, "# AVS wants to have the first line starting with its name\n");
922     slen = strlen(temp);
923
924     if (!checked_write(f, temp, slen, buffer))
925     { free(pCompressed);
926       return AVS_ERROR;
927     }
928     FilePos += slen;
929
930     slen = strlen(headerinfo);
931     if (slen && !checked_write(f, headerinfo, slen, buffer))
932     { free(pCompressed);
933       return AVS_ERROR;
934     }
935     FilePos += slen;
936
937     if (!checked_write(f, "\n", 1, buffer))
938     { free(pCompressed);
939       return AVS_ERROR;
940     }
941     FilePos++;
942
943     if (strlen(headerfile))
944     { fp = fopen(headerfile, "rt");
945       if (fp)
946       { for (;;)
947         { if (fgets(temp, 255, fp) == NULL) break;
948           slen = strlen(temp);
949           if (!checked_write(f, temp, slen, buffer))
950           { fclose(fp);
951             free(pCompressed);
952             return AVS_ERROR;
953           }
954           FilePos += slen;
955         }
956         fclose(fp);
957         if (!checked_write(f, "\n", 1, buffer))
958         { free(pCompressed);
959           return AVS_ERROR;
960         }
961         FilePos++;
962       }
963     }
964
965     sprintf(temp, "ndim=%d\n", GetNumberOfDimensions());
966     slen = strlen(temp);
967     if (!checked_write(f, temp, slen, buffer))
968     { free(pCompressed);
969       return AVS_ERROR;
970     }
971     FilePos += slen;
972   }
973
974   for (i=0; i<GetNumberOfDimensions(); i++)
975   { if (!raw)
976     { sprintf(temp, "dim%d=%d\n", i+1, GetDimensions(i));
977       slen = strlen(temp);
978       if (!checked_write(f, temp, slen, buffer))
979       { free(pCompressed);
980         return AVS_ERROR;
981       }
982       FilePos += slen;
983     }
984   }
985
986   if (!raw)
987   { sprintf(temp, "nspace=%d\n", GetNumberOfDimensions());
988     slen = strlen(temp);
989     if (!checked_write(f, temp, slen, buffer))
990     { free(pCompressed);
991       return AVS_ERROR;
992     }
993     FilePos += slen;
994
995     sprintf(temp, "veclen=%d\n", GetNumberOfComponents());
996     slen = strlen(temp);
997     if (!checked_write(f, temp, slen, buffer))
998     { free(pCompressed);
999       return AVS_ERROR;
1000     }
1001     FilePos += slen;
1002
1003     switch(GetComponentType())
1004     { case itk::ImageIOBase::CHAR   : strcpy(temp, "data=byte\n"); break;
1005       case itk::ImageIOBase::SHORT  : strcpy(temp, "data=xdr_short\n"); break;
1006       case itk::ImageIOBase::INT    : strcpy(temp, "data=xdr_integer\n"); break;
1007       case itk::ImageIOBase::FLOAT  : strcpy(temp, "data=xdr_real\n"); break;
1008       case itk::ImageIOBase::DOUBLE : strcpy(temp, "data=xdr_double\n"); break;
1009       default               : if (f != fileno(stdout)) close(f);
1010                               free(pCompressed);
1011                               return AVS_ERROR;
1012     }
1013     slen = strlen(temp);
1014     if (!checked_write(f, temp, slen, buffer))
1015     { free(pCompressed);
1016       return AVS_ERROR;
1017     }
1018     FilePos += slen;
1019   }
1020
1021
1022   //FilePos = tell(f);
1023 ONCE_AGAIN:
1024
1025
1026   //switch(input->uniform)
1027   //{ case UNIFORM     : 
1028   strcpy(temp, "field=uniform\n");
1029   coords = GetNumberOfDimensions() * 2;
1030                 //       break;
1031   //  case RECTILINEAR : strcpy(temp, "field=rectilinear\n");
1032                 //       break;
1033   //  case IRREGULAR   : strcpy(temp, "field=irregular\n");
1034                 //       coords = total * input->nspace;
1035                 //       break;
1036   //  default          : if (f != fileno(stdout)) close(f);
1037   //                     free(pCompressed);
1038   //                           return;
1039   //}
1040
1041   if (!raw)
1042   { if (!checked_write(f, temp, strlen(temp), buffer))
1043     { free(pCompressed);
1044       return AVS_ERROR;
1045     }
1046
1047     if ((iNkiCompression > 0) &&
1048       (GetComponentType() == itk::ImageIOBase::SHORT) &&
1049       (GetPixelType() == itk::ImageIOBase::SCALAR))
1050     { sprintf(temp, "nki_compression=%d", iNkiCompression);
1051       if (!checked_write(f, temp, strlen(temp), buffer))
1052       { free(pCompressed);
1053         return AVS_ERROR;
1054       }
1055     }
1056
1057     temp[0] = temp[1] = 12;
1058     if (!checked_write(f, temp, 2, buffer))
1059     { free(pCompressed);
1060       return AVS_ERROR;
1061     }
1062   }
1063
1064   total *= GetPixelSize();
1065
1066   if ((!raw) && (iNkiCompression > 0) &&
1067         (GetComponentType() == itk::ImageIOBase::SHORT) &&
1068         (GetPixelType() == itk::ImageIOBase::SCALAR))
1069   { size_t      iCompressedLength;
1070
1071     iCompressedLength = nki_private_compress(pCompressed,
1072       (short int *)(data), total/2, iNkiCompression);
1073
1074     if (iCompressedLength > 0)
1075     { if (!checked_write(f, pCompressed, iCompressedLength, buffer))
1076       { free(pCompressed);
1077         return AVS_ERROR;
1078       }
1079       free(pCompressed);
1080       goto WRITE_COORDS;
1081     }
1082
1083     /* Compressionratio was poor: let's write uncompressed */
1084     iNkiCompression = 0;
1085     total /= 2;
1086     free(pCompressed);
1087     pCompressed = NULL;
1088     lseek(f, (unsigned int)FilePos, SEEK_SET); // use _lseeki64 just in case header size > UINT_MAX bytes
1089     goto ONCE_AGAIN;
1090   }
1091
1092   /* swap data if required (xdr is low-endian) */
1093
1094   if (!(*(char *)(&swap_test)))
1095   { if (GetComponentSize()==2)
1096     { c = (char *)data;
1097       for (i=0; i<total; i+=2)
1098       { cSwap  = c[i];  c[i]   = c[i+1]; c[i+1] = cSwap;
1099       }
1100     }
1101     else if (GetComponentSize()==4)
1102     { c = (char *)data;
1103       for (i=0; i<total; i+=4)
1104       { cSwap = c[i];   c[i]   = c[i+3]; c[i+3] = cSwap;
1105         cSwap = c[i+1]; c[i+1] = c[i+2]; c[i+2] = cSwap;
1106       }
1107     }
1108     else if (GetComponentSize()==8)
1109     { c = (char *)data;
1110       for (i=0; i<total; i+=8)
1111       { cSwap = c[i];   c[i]   = c[i+7]; c[i+7] = cSwap;
1112         cSwap = c[i+1]; c[i+1] = c[i+6]; c[i+6] = cSwap;
1113         cSwap = c[i+2]; c[i+2] = c[i+5]; c[i+5] = cSwap;
1114         cSwap = c[i+3]; c[i+3] = c[i+4]; c[i+4] = cSwap;
1115       }
1116     }
1117   }
1118
1119   if (total)
1120   { if (!checked_write(f, data, total, buffer))
1121       return AVS_ERROR;
1122   }
1123
1124   /* swap data back if was swapped before writing */
1125
1126   if (!(*(char *)(&swap_test)))
1127   { if (GetComponentSize()==2)
1128     { c = (char *)data;
1129       for (i=0; i<total; i+=2)
1130       { cSwap = c[i];   c[i]   = c[i+1]; c[i+1] = cSwap;
1131       }
1132     }
1133     else if (GetComponentSize()==4)
1134     { c = (char *)data;
1135       for (i=0; i<total; i+=4)
1136       { cSwap = c[i];   c[i]   = c[i+3]; c[i+3] = cSwap;
1137         cSwap = c[i+1]; c[i+1] = c[i+2]; c[i+2] = cSwap;
1138       }
1139     }
1140     else if (GetComponentSize()==8)
1141     { c = (char *)data;
1142       for (i=0; i<total; i+=8)
1143       { cSwap = c[i];   c[i]   = c[i+7]; c[i+7] = cSwap;
1144         cSwap = c[i+1]; c[i+1] = c[i+6]; c[i+6] = cSwap;
1145         cSwap = c[i+2]; c[i+2] = c[i+5]; c[i+5] = cSwap;
1146         cSwap = c[i+3]; c[i+3] = c[i+4]; c[i+4] = cSwap;
1147       }
1148     }
1149   }
1150
1151 WRITE_COORDS:
1152   float *points;
1153   points = (float *)malloc(sizeof(float)*GetNumberOfDimensions()*2);
1154   for (i=0; i<GetNumberOfDimensions(); i++)
1155   {
1156     points[i*2  ] = 0.1 *  GetOrigin(i);
1157     points[i*2+1] = 0.1 * (GetOrigin(i) + GetSpacing(i)*(GetDimensions(i)-1));
1158   }
1159
1160   if (coords && !raw)                           /* write AVS coordinates ? */
1161   { coords *= sizeof(float);
1162     if (!(*(char *)(&swap_test)))
1163     { c = (char *)(points);              /* swap bytes */
1164       for (i=0; i<coords; i+=4)
1165       { cSwap = c[i];   c[i]   = c[i+3]; c[i+3] = cSwap;
1166         cSwap = c[i+1]; c[i+1] = c[i+2]; c[i+2] = cSwap;
1167       }
1168     }
1169
1170     if (!checked_write(f, points, coords, buffer))
1171       return AVS_ERROR;
1172
1173     if (!(*(char *)(&swap_test)))
1174     { c = (char *)(points);              /* swap bytes back */
1175       for (i=0; i<coords; i+=4)
1176       { cSwap = c[i];   c[i]   = c[i+3]; c[i+3] = cSwap;
1177         cSwap = c[i+1]; c[i+1] = c[i+2]; c[i+2] = cSwap;
1178       }
1179     }
1180   }
1181
1182   if (!(tobuffer || getsize))
1183     if (f != fileno(stdout)) close(f);
1184
1185   if (getsize) return;
1186   return AVS_OK;
1187 }