2 * @file clitkXdrImageIO.cxx
3 * @author Simon Rit <simon.rit@gmail.com>
4 * @date Sun Jun 1 22:12:20 2008
11 #include "clitkXdrImageIO.h"
12 #include "clitkCommon.h"
18 //#define _read readfix
20 #define AVSINT ptrdiff_t
27 #define setmode(a,b) 0
31 # if defined(__GNUC__) || defined(unix)
32 typedef long long Q_INT64;
33 typedef unsigned long long Q_UINT64;
34 # define Q_INT64_CONST(x) (x##ll)
35 # define Q_UINT64_CONST(x) (x##llu) /* gcc also allows ull */
36 /* When using MINGW with MS(V)CRT DLL, use MS format modifier. */
38 # define Q_INT64_FORMAT "I64"
40 # define Q_INT64_FORMAT "L"
42 # elif defined(__BORLANDC__) || defined(__WATCOMC__) || defined(_MSC_VER)
43 typedef __int64 Q_INT64;
44 typedef unsigned __int64 Q_UINT64;
45 # define Q_INT64_CONST(x) (x##i64)
46 # define Q_UINT64_CONST(x) (x##ui64) /* i64u is not allowed! */
48 # define Q_INT64_FORMAT "I64"
50 # define Q_INT64_FORMAT "L"
53 # error No 64 bit integers known for this compiler, edit portdefs.h.
57 bool clitk::XdrImageIO::CanWriteFile(const char* FileNameToWrite)
58 { std::string filename(FileNameToWrite);
59 std::string filenameext = GetExtension(filename);
60 if (filenameext != std::string("xdr")) return false;
64 void clitk::XdrImageIO::Write(const void* buffer)
65 { char *s = const_cast<char*>("");
66 WriteImage( m_FileName.c_str(), s, s, 0, -1, 0, 2, 0, 0, 0, 0, buffer);
69 // Based on a true story by the Nederlands Kanker Instituut (AVS_WXDR.CPP from the 20091216)
71 /************************************************************************/
73 /************************************************************************/
89 // don't use min() and max() macros indirectly defined by windows.h,
90 // but use portable std::min() and std:max() instead
97 /************************************************************************/
98 /* DEFINES, ENUMERATED TYPES AND CONSTANTS */
99 /************************************************************************/
103 // Fields with data size>8GB (having UINT_MAX short pixels) cannot be compressed using
104 // NKI_MODE2 struct because iOrgSize has type "unsigned int". In that case use NKI_MODE2_64BITS.
105 // The type of structure is indicated as follows:
107 // iOrgSize==0: NKI_MODE2_64BITS
108 // otherwise : NKI_MODE2
110 // Compression modes 1 and 3 (without CRCs) only use the first 2 members (iOrgSize and iMode).
114 unsigned int iOrgSize; /* in pixels (i.e. shorts) */
115 unsigned int iMode; /* 1, 2, 3 or 4 */
116 unsigned int iCompressedSize; /* in bytes, excluding header */
117 unsigned int iOrgCRC; /* CRC of the data (no coords etc) */
118 unsigned int iCompressedCRC; /* CRC of the compressed data, excluding this header */
123 unsigned int iOrgSize; /* in pixels (i.e. shorts) */
124 unsigned int iMode; /* 1, 2, 3 or 4 */
125 unsigned int iCompressedSize; /* in bytes, excluding header */
126 unsigned int iOrgCRC; /* CRC of the data (no coords etc) */
127 unsigned int iCompressedCRC; /* CRC of the compressed data, excluding this header */
128 unsigned int iPad; /* unused */
129 Q_UINT64 i64OrgSize; /* used for more than UINT_MAX pixels, indicated by iOrgSize==0 (0-vector not compressed) */
130 Q_UINT64 i64CompressedSize; /* value in BYTES, used for more than UINT_MAX PIXELS, indicated by iCompressedSize==0 */
137 // Changed next to static function in stead of macro so it can
138 // have a return value to check in the calling function.
139 // It could be made inline as well, but there is no real time
140 // punishment from the extra layer of function calls.
142 // note: some compilers do not like comments ending in a backslash.
143 // so use macro functions to exclude.
146 /************************************************************************/
147 /* GLOBAL VARIABLES */
148 /************************************************************************/
150 static const unsigned long CRC32_table[256] = {
151 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
152 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
153 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
154 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
155 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
156 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
157 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
158 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
159 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
160 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
161 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
162 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
163 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
164 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
165 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
166 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
167 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
168 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
169 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
170 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
171 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
172 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
173 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
174 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
175 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
176 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
177 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
178 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
179 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
180 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
181 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
182 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
183 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
184 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
185 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
186 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
187 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
188 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
189 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
190 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
191 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
192 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
193 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
196 /************************************************************************/
197 /* MODULE FUNCTIONS */
198 /************************************************************************/
203 int writefix(int file, const void *buf, unsigned int count)
206 for (unsigned i=0; i<count; i+=16384)
208 if (j>16384) j=16384;
210 k=write(file, (char *)buf+i, j);
223 Version of write() that takes special action in case of
224 standard output. Based on commented out macro above.
225 This function overloads the <cstdio> (or stdio.h for old style C++)
229 // Like the original macro, we do /not/ want writefix from mbfield.c.
233 static int wxdr_write(int handle, const void * buf, unsigned len)
235 // if (handle == 1) // stdout
236 if (handle == fileno(stdout))
239 // Behave as C standard library write(): return number of bytes
240 // written or -1 and errno set on error.
242 DWORD dwBytesWritten;
243 if (!WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, len,
244 &dwBytesWritten, NULL))
246 // There is no simple 1-to-1 mapping between GetLastError()
247 // values that WriteFile() can return (quite a lot) and the two
248 // errno values that write() can return. So return EACCES in
250 switch (GetLastError())
251 { case ERROR_INVALID_HANDLE:
252 errno = EBADF ; break;
254 errno = EACCES; break;
259 return (int)dwBytesWritten; // May still be < len!
260 // And... write() may write a maximum of UINT_MAX-1 bytes, whereas
261 // WriteFile() may write UINT_MAX bytes at once. But since
262 // int(UINT_MAX) == -1 this will pose an actual problem in the
265 //const int oldmode = setmode(handle, O_BINARY);//commented out by joel
266 const int iBytesWritten = write(handle, buf, len);
267 const int saveerrno = errno; // setmode() may change errno.
268 //if (oldmode != -1) setmode(handle, oldmode); //commented out by joel
270 return iBytesWritten;
274 return write(handle, buf, len);
279 Behaves like win32 WriteFile() and returns a Boolean to indicate
280 success or failure, where failure almost invariably means disc full.
284 In case of failure, this function issues an AVS error message
285 and closes the file (if handle != 1). It is up to the calling
286 function to return the AVS_ERROR state and before that do things
287 like close other files, free memory etc. This way, there is less
288 chance of erroneously duplicated code, like in:
289 written = write(f, temp, strlen(temp));
290 if (written == -1 || written != strlen(temp))
292 if (f != fileno(stdout)) close(f);
295 written = write(f, buf, buflength)
296 if (written == -1 || written != strlen(temp)) {
297 // oops, wrong length copy'n'pasted
299 If more elaborate error handling is needed then the calling
300 functuon should use the (overloaded) write() and act on its return
301 value (and the value of errno) accordingly.
303 It does /not/ close stdout.
307 Note that checked_write() takes a size_t for len, whereas write() takes
308 an unsigned int of 4 bytes. On a 64 bits OS a size_t will be an 8 byte integer,
309 enabling more than UINT_MAX bytes to write at once.
311 static bool checked_write(int handle, const void * buf, size_t len, char **buffer)
312 { if (buffer && !handle)
313 { memcpy(*buffer, buf, len);
317 if (buffer && handle)
322 { for(int i=0; i<2; i++)
327 //If write fails, test if not related to big buffer problem
328 //Bug report http://support.microsoft.com/kb/899149 entitled
329 //"You cannot call the fwrite function to write to a buffer
330 // that is larger than 64 MB in Visual C++ 2005,
331 // in Visual C++ .NET 2003, or in Visual C++ .NET 2002"
332 // NB: same thing for write function in binary mode
335 // call wxdr_write (for handle!=fileno(stdout) a wrapper for write) several times
336 // to interpret the signed 32-bit return value correctly
338 { chunksize = (int)std::min(remaining, (size_t)INT_MAX);
339 byteswritten = wxdr_write(handle, buf, chunksize);
340 if (byteswritten == chunksize)
341 remaining -= chunksize;
343 break; // try writefix in the next round
350 // call writefix (in mbfield.c) several times to interpret the signed 32-bit
351 // return value correctly. writefix uses chunks of 16384 bytes
353 { chunksize = (int)std::min(remaining, (size_t)INT_MAX);
354 byteswritten = writefix(handle, buf, chunksize);
355 if (byteswritten == chunksize)
356 remaining -= chunksize;
358 break; // even writefix failed: return error
364 // Note: file is open in binary mode, no need to compensate
365 // for a value of byteswritten > len due to \n -> \r\n conversions.
366 // (write() on a text stream is implementation dependent.)
367 if (handle != fileno(stdout)) close(handle);
368 AVSerror("Avs_wxdr: write failed, disk full?");
373 /* coder for NKI private compressed pixel data
374 arguments: dest = (in) points to area where compressed destination data is written (byte)
375 src = (in) points to uncompressed source data (short)
376 npixels = (in) number of pixels to compress
378 The return value is the number of bytes in the compressed data (maximal 3*npixels+10, typical 0.52*npixels)
381 - The first 4 bytes contain the number of short-int pixels
382 - The following 4 bytes contain iMode=1
383 - The rest is the compressed image
386 - The first 4 bytes contain the number of short-int pixels
387 - The following 4 bytes contain iMode=2
388 - The following 4 bytes contain the size of the compressed image (in bytes)
389 - The following 4 bytes contain the CRC of the original image
390 - The following 4 bytes contain the CRC of the compressed image
391 - The rest is the compressed image
392 - The compressed size will be even (padded by a zero if necessary).
395 - The first 4 bytes contain the number of short-int pixels
396 - The following 4 bytes contain iMode=3
397 - The rest is the compressed image, including 4 bit differences
400 - The first 4 bytes contain the number of short-int pixels
401 - The following 4 bytes contain iMode=4
402 - The following 4 bytes contain the size of the compressed image (in bytes)
403 - The following 4 bytes contain the CRC of the original image
404 - The following 4 bytes contain 0
405 - The rest is the compressed image, including 4 bit differences
406 - The compressed size will be even (padded by a zero if necessary).
408 iMode 1 and iMode 2 are identical, except for the CRC data that is included for iMode 2
409 iMode 3 and iMode 4 are identical, except for the CRC data that is included for iMode 4
412 // optimized settings for the 4 bit run compressor (mode 3 and 4)
414 #define MINZEROS 5 // shortest RLE (2 byte overhead, but breaks 4bit run)
415 #define MIN4BIT 6 // shortest 4 bit run (6 bytes compressed to 5 bytes)
417 // This internal routine converts an 8 bit difference string into a 4 bit one
418 static signed char *recompress4bit(int n, signed char *dest)
419 { signed char *p, *q;
425 val = (((int)p[0])<<4) | (p[1]&15);
427 *dest++ = -0x40; // 192 (0xc0) does not fit between -128..127: maps to -64 (0x40) in 2's complement
428 *dest++ = (signed char)n;
432 { *dest++ = (signed char)((((int)p[0])<<4) | (p[1]&15));
436 q[0] = (signed char)val;
442 static size_t nki_private_compress(signed char *dest, short int *src, size_t npixels, int iMode)
443 { unsigned long iCRC;
445 unsigned int iHeaderSize=8; // value for iMode==1 and iMode==3
448 NKI_MODE2* pHeader = (NKI_MODE2*)dest;
449 NKI_MODE2_64BITS* pHeader_64bits = (NKI_MODE2_64BITS*)dest;
452 iBufferSize = (npixels / 2) * 3; // Buffer is sizeof(NKI_MODE2_64BITS) + 10 bytes larger
454 /* Up till now only Mode=1 .. 4 are supported */
455 if ((iMode < 1) || (iMode > 4))
458 /* Create the header */
459 pHeader->iMode = iMode;
461 if (sizeof(int*)>sizeof(int) && npixels>UINT_MAX) // On a 64 bits OS we want to store files>4GB
462 { pHeader_64bits->iOrgSize = 0; // This indicates>4GB file (0-vector is not compressed)
463 pHeader_64bits->i64OrgSize = npixels;
464 iHeaderSize = sizeof(NKI_MODE2_64BITS);
465 dest += sizeof(NKI_MODE2_64BITS);
468 { pHeader->iOrgSize = (unsigned int)(npixels & UINT_MAX); // store 32 bit number as first member
470 if (iMode==2 || iMode==4)
471 iHeaderSize = sizeof(NKI_MODE2);
475 /* Create the compressed image */
478 { *(short int *)dest = *src;
484 { val = src[1] - src[0];
487 if (val == 0) /* run length-encode zero differences */
489 { if (i>=npixels || src[i-1]!=src[-1] || i==256)
493 { *dest++ = -128; // hexadecimal 0x80
494 *dest++ = (signed char)(i-1);
502 else if (val >= -64 && val <= 63) /* small difference coded as one byte */
503 { *dest = (signed char)val;
506 else if (val >= -0x3F00 && val <= 0x3EFF) /* large differences coded as two bytes */
507 { dest[0] = (signed char)((val>>8) ^ 0x40);
508 dest[1] = (signed char)val;
511 else /* if very large differences code abs val as three bytes */
513 *dest++ = (signed char)(src[0]>>8);
514 *dest++ = (signed char)(src[0]);
516 /* Are we beyond the allocated memory? */
517 if ((size_t)(dest - (signed char*)pHeader) > iBufferSize)
527 *(short int *)dest = val = *src;
528 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (unsigned char) val ] ^ ((iCRC2 >> 8));
529 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (unsigned char)(val>>8)] ^ ((iCRC2 >> 8));
530 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char) val ] ^ ((iCRC >> 8));
531 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char)(val>>8)] ^ ((iCRC >> 8));
536 { val = src[1] - src[0];
538 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char) src[0] ] ^ ((iCRC >> 8));
539 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char)(src[0]>>8)] ^ ((iCRC >> 8));
541 if (val == 0) /* run length-encode zero differences */
543 { if (i>=npixels || src[i-1]!=src[-1] || i==256)
546 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ 0 ] ^ ((iCRC2 >> 8));
549 { *dest++ = -128; // hexadecimal 0x80
550 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ 0x80 ] ^ ((iCRC2 >> 8));
551 *dest++ = (signed char)(i-1);
552 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (i-1)] ^ ((iCRC2 >> 8));
555 for (j=0; j<i-2; j++)
557 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char) src[0] ] ^ ((iCRC >> 8));
558 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char)(src[0]>>8)] ^ ((iCRC >> 8));
565 else if (val >= -64 && val <= 63) /* small difference coded as one byte */
566 { *dest = (signed char)val;
567 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (unsigned char)val ] ^ ((iCRC2 >> 8));
570 else if (val >= -0x3F00 && val <= 0x3EFF) /* large differences coded as two bytes */
571 { dest[0] = (signed char)((val>>8) ^ 0x40);
572 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (unsigned char)dest[0] ] ^ ((iCRC2 >> 8));
573 dest[1] = (signed char)val;
574 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (unsigned char)val ] ^ ((iCRC2 >> 8));
577 else /* if very large differences code abs val as three bytes */
579 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ 0x7f ] ^ ((iCRC2 >> 8));
581 dest[1] = (signed char)(val>>8);
582 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (unsigned char)(val>>8)] ^ ((iCRC2 >> 8));
583 dest[2] = (signed char)val;
584 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (unsigned char)val ] ^ ((iCRC2 >> 8));
587 /* Are we beyond the allocated memory? */
588 if ((size_t)(dest - (signed char*)pHeader) > iBufferSize)
593 if ((dest - (signed char*)pHeader - iHeaderSize)<UINT_MAX) // store 32 bit number as third member
594 pHeader->iCompressedSize =
595 (unsigned int)(dest - (signed char*)pHeader - iHeaderSize);
596 else // store 64 bit number in extended structure
597 pHeader_64bits->i64CompressedSize = dest - (signed char*)pHeader -iHeaderSize;
599 /* Pad it to get an even length */
600 if (pHeader->iCompressedSize & 1)
602 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ 0] ^ ((iCRC2 >> 8));
603 pHeader->iCompressedSize++;
606 pHeader->iOrgCRC = iCRC;
607 pHeader->iCompressedCRC = iCRC2;
610 /* Create the compressed image - compressor with added 4 bit run */
614 *(short int *)dest = *src;
619 { val = src[1] - src[0];
622 if (val == 0) /* run length-encode zero differences */
624 { if (i>=npixels || src[i-1]!=src[-1] || i==256)
625 { if (i<=MINZEROS) /* too short run -> write zeros */
626 { for (j=0; j<i-1; j++)
630 if(n4bit>=254) /* maximum length 4 bit run */
631 { dest = recompress4bit(n4bit, dest);
637 { if (n4bit>=MIN4BIT) /* end (and write) 4 bit run */
638 dest = recompress4bit(n4bit, dest);
641 *dest++ = -128; // hexadecimal 0x80
642 *dest++ = (signed char)(i-1);
651 else if (val >= -63 && val <= 63) /* small difference coded as one byte */
652 { if (val >= -8 && val <= 7)
653 { *dest++ = (signed char)val;
656 if(n4bit>=254) /* maximum length 4 bit run */
657 { dest = recompress4bit(n4bit, dest);
661 else if(n4bit>=MIN4BIT) /* end and write 4 bit run */
663 dest = recompress4bit(n4bit, dest);
665 *dest++ = (signed char)j;
668 { *dest++ = (signed char)val; /* end 4 bit run */
672 else if (val >= -0x3F00 && val <= 0x3EFF) /* large differences coded as two bytes */
675 if(n4bit>=MIN4BIT) /* end (and write) 4 bit run */
676 dest = recompress4bit(n4bit, dest);
679 dest[0] = (signed char)((j>>8) ^ 0x40);
680 dest[1] = (signed char)j;
683 else /* if very large differences code abs val as three bytes */
686 if(n4bit>=MIN4BIT) /* end (and write) 4 bit run */
687 dest = recompress4bit(n4bit, dest);
691 *dest++ = (signed char)(j>>8);
692 *dest++ = (signed char)j;
694 /* Are we beyond the allocated memory? */
695 if ((size_t)(dest - (signed char*)pHeader) > iBufferSize)
701 /* Create the compressed image - compressor with added 4 bit run and CRC */
707 *(short int *)dest = val = *src;
708 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char) val ] ^ ((iCRC >> 8));
709 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char)(val>>8)] ^ ((iCRC >> 8));
714 { val = src[1] - src[0];
716 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char) src[0] ] ^ ((iCRC >> 8));
717 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char)(src[0]>>8)] ^ ((iCRC >> 8));
719 if (val == 0) /* run length-encode zero differences */
721 { if (i>=npixels || src[i-1]!=src[-1] || i==256)
722 { if (i<=MINZEROS) /* too short run -> write zeros */
723 { for (j=0; j<i-1; j++)
727 if(n4bit>=254) /* maximum length 4 bit run */
728 { dest = recompress4bit(n4bit, dest);
734 { if (n4bit>=MIN4BIT) /* end (and write) 4 bit run */
735 dest = recompress4bit(n4bit, dest);
738 *dest++ = -128; // hexadecimal 0x80
739 *dest++ = (signed char)(i-1);
743 for (j=0; j<i-2; j++)
745 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char) src[0] ] ^ ((iCRC >> 8));
746 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char)(src[0]>>8)] ^ ((iCRC >> 8));
752 else if (val >= -63 && val <= 63) /* small difference coded as one byte */
753 { if (val >= -8 && val <= 7)
754 { *dest++ = (signed char)val;
757 if(n4bit>=254) /* maximum length 4 bit run */
758 { dest = recompress4bit(n4bit, dest);
762 else if(n4bit>=MIN4BIT) /* end and write 4 bit run */
764 dest = recompress4bit(n4bit, dest);
766 *dest++ = (signed char)j;
769 { *dest++ = (signed char)val; /* end 4 bit run */
773 else if (val >= -0x3F00 && val <= 0x3EFF) /* large differences coded as two bytes */
776 if(n4bit>=MIN4BIT) /* end (and write) 4 bit run */
777 dest = recompress4bit(n4bit, dest);
780 dest[0] = (signed char)((j>>8) ^ 0x40);
781 dest[1] = (signed char)j;
784 else /* if very large differences code abs val as three bytes */
787 if(n4bit>=MIN4BIT) /* end (and write) 4 bit run */
788 dest = recompress4bit(n4bit, dest);
792 *dest++ = (signed char)(j>>8);
793 *dest++ = (signed char)j;
795 /* Are we beyond the allocated memory? */
796 if ((size_t)(dest - (signed char*)pHeader) > iBufferSize)
801 if ((dest - (signed char*)pHeader - iHeaderSize)<UINT_MAX) // store 32 bit number as third member
802 pHeader->iCompressedSize =
803 (unsigned int)(dest - (signed char*)pHeader - iHeaderSize);
804 else // store 64 bit number in extended structure
805 { pHeader_64bits->iCompressedSize = 0;
806 pHeader_64bits->i64CompressedSize = dest - (signed char*)pHeader -iHeaderSize;
809 /* Pad it to get an even length */
810 if (pHeader->iCompressedSize & 1)
812 pHeader->iCompressedSize++;
815 pHeader->iOrgCRC = iCRC;
816 pHeader->iCompressedCRC = 0;
819 return dest - (signed char*)pHeader;
823 void clitk::XdrImageIO::WriteImage(const char* file, char* headerinfo, char* headerfile, int raw,
824 int offset, char bLittleEndian, int iNkiCompression,
825 int wcoords, int append, int getsize, char *tobuffer, const void* data)
834 long swap_test = 0x1000000;
835 signed char* pCompressed = NULL;
837 char **buffer = NULL;
843 swap_test = 0x00000001;
846 { swap_test = 0xffffffff; // never swap to save time
847 buffer = (char **) &len;
852 { buf2 = (char *)tobuffer;
857 for (i=0; i<GetNumberOfDimensions(); i++)
858 { total *= GetDimensions(i);
859 coords += GetDimensions(i);
862 /* Try allocate the compressed fielddata - compression disabled if alloc fails */
863 if ((iNkiCompression > 0) &&
864 (GetComponentType() == itk::ImageIOBase::SHORT) &&
865 (GetPixelType() == itk::ImageIOBase::SCALAR))
866 { pCompressed = (signed char *)malloc((total/2) * 3 + sizeof(NKI_MODE2_64BITS) + 10);
867 if (pCompressed==NULL)
868 { iNkiCompression = 0;
869 AVSwarning("Avs_wxdr: not enough memory to compress data, saving uncompressed");
873 if (!(tobuffer || getsize))
875 { f = open(file, O_RDWR, 0);
878 AVSerror("Avs_wxdr: Opening " << file << "failed.\n" << strerror(errno));
882 lseek(f, offset, SEEK_SET);
885 { if (strlen(file)==0)
889 f = open(file, O_RDWR | O_APPEND, 0);
891 f = creat(file, S_IWRITE | S_IREAD);
895 { AVSerror("Avs_wxdr: Creating " << file << " failed.\n" << strerror(errno));
903 { sprintf(temp, "# AVS wants to have the first line starting with its name\n");
906 if (!checked_write(f, temp, slen, buffer))
912 slen = strlen(headerinfo);
913 if (slen && !checked_write(f, headerinfo, slen, buffer))
919 if (!checked_write(f, "\n", 1, buffer))
925 if (strlen(headerfile))
926 { fp = fopen(headerfile, "rt");
929 { if (fgets(temp, 255, fp) == NULL) break;
931 if (!checked_write(f, temp, slen, buffer))
939 if (!checked_write(f, "\n", 1, buffer))
947 sprintf(temp, "ndim=%d\n", GetNumberOfDimensions());
949 if (!checked_write(f, temp, slen, buffer))
956 for (i=0; i<GetNumberOfDimensions(); i++)
958 { sprintf(temp, "dim%d=%d\n", i+1, GetDimensions(i));
960 if (!checked_write(f, temp, slen, buffer))
969 { sprintf(temp, "nspace=%d\n", GetNumberOfDimensions());
971 if (!checked_write(f, temp, slen, buffer))
977 sprintf(temp, "veclen=%d\n", GetNumberOfComponents());
979 if (!checked_write(f, temp, slen, buffer))
985 switch(GetComponentType())
986 { case itk::ImageIOBase::CHAR : strcpy(temp, "data=byte\n"); break;
987 case itk::ImageIOBase::SHORT : strcpy(temp, "data=xdr_short\n"); break;
988 case itk::ImageIOBase::INT : strcpy(temp, "data=xdr_integer\n"); break;
989 case itk::ImageIOBase::FLOAT : strcpy(temp, "data=xdr_real\n"); break;
990 case itk::ImageIOBase::DOUBLE : strcpy(temp, "data=xdr_double\n"); break;
991 default : if (f != fileno(stdout)) close(f);
996 if (!checked_write(f, temp, slen, buffer))
1004 //FilePos = tell(f);
1008 //switch(input->uniform)
1010 strcpy(temp, "field=uniform\n");
1011 coords = GetNumberOfDimensions() * 2;
1013 // case RECTILINEAR : strcpy(temp, "field=rectilinear\n");
1015 // case IRREGULAR : strcpy(temp, "field=irregular\n");
1016 // coords = total * input->nspace;
1018 // default : if (f != fileno(stdout)) close(f);
1019 // free(pCompressed);
1024 { if (!checked_write(f, temp, strlen(temp), buffer))
1025 { free(pCompressed);
1029 if ((iNkiCompression > 0) &&
1030 (GetComponentType() == itk::ImageIOBase::SHORT) &&
1031 (GetPixelType() == itk::ImageIOBase::SCALAR))
1032 { sprintf(temp, "nki_compression=%d", iNkiCompression);
1033 if (!checked_write(f, temp, strlen(temp), buffer))
1034 { free(pCompressed);
1039 temp[0] = temp[1] = 12;
1040 if (!checked_write(f, temp, 2, buffer))
1041 { free(pCompressed);
1046 total *= GetPixelSize();
1048 if ((!raw) && (iNkiCompression > 0) &&
1049 (GetComponentType() == itk::ImageIOBase::SHORT) &&
1050 (GetPixelType() == itk::ImageIOBase::SCALAR))
1051 { size_t iCompressedLength;
1053 iCompressedLength = nki_private_compress(pCompressed,
1054 (short int *)(data), total/2, iNkiCompression);
1056 if (iCompressedLength > 0)
1057 { if (!checked_write(f, pCompressed, iCompressedLength, buffer))
1058 { free(pCompressed);
1065 /* Compressionratio was poor: let's write uncompressed */
1066 iNkiCompression = 0;
1070 lseek(f, (unsigned int)FilePos, SEEK_SET); // use _lseeki64 just in case header size > UINT_MAX bytes
1074 /* swap data if required (xdr is low-endian) */
1076 if (!(*(char *)(&swap_test)))
1077 { if (GetComponentSize()==2)
1079 for (i=0; i<total; i+=2)
1080 { cSwap = c[i]; c[i] = c[i+1]; c[i+1] = cSwap;
1083 else if (GetComponentSize()==4)
1085 for (i=0; i<total; i+=4)
1086 { cSwap = c[i]; c[i] = c[i+3]; c[i+3] = cSwap;
1087 cSwap = c[i+1]; c[i+1] = c[i+2]; c[i+2] = cSwap;
1090 else if (GetComponentSize()==8)
1092 for (i=0; i<total; i+=8)
1093 { cSwap = c[i]; c[i] = c[i+7]; c[i+7] = cSwap;
1094 cSwap = c[i+1]; c[i+1] = c[i+6]; c[i+6] = cSwap;
1095 cSwap = c[i+2]; c[i+2] = c[i+5]; c[i+5] = cSwap;
1096 cSwap = c[i+3]; c[i+3] = c[i+4]; c[i+4] = cSwap;
1102 { if (!checked_write(f, data, total, buffer))
1106 /* swap data back if was swapped before writing */
1108 if (!(*(char *)(&swap_test)))
1109 { if (GetComponentSize()==2)
1111 for (i=0; i<total; i+=2)
1112 { cSwap = c[i]; c[i] = c[i+1]; c[i+1] = cSwap;
1115 else if (GetComponentSize()==4)
1117 for (i=0; i<total; i+=4)
1118 { cSwap = c[i]; c[i] = c[i+3]; c[i+3] = cSwap;
1119 cSwap = c[i+1]; c[i+1] = c[i+2]; c[i+2] = cSwap;
1122 else if (GetComponentSize()==8)
1124 for (i=0; i<total; i+=8)
1125 { cSwap = c[i]; c[i] = c[i+7]; c[i+7] = cSwap;
1126 cSwap = c[i+1]; c[i+1] = c[i+6]; c[i+6] = cSwap;
1127 cSwap = c[i+2]; c[i+2] = c[i+5]; c[i+5] = cSwap;
1128 cSwap = c[i+3]; c[i+3] = c[i+4]; c[i+4] = cSwap;
1135 points = (float *)malloc(sizeof(float)*GetNumberOfDimensions()*2);
1136 for (i=0; i<GetNumberOfDimensions(); i++)
1138 points[i*2 ] = 0.1 * GetOrigin(i);
1139 points[i*2+1] = 0.1 * (GetOrigin(i) + GetSpacing(i)*(GetDimensions(i)-1));
1142 if (coords && !raw) /* write AVS coordinates ? */
1143 { coords *= sizeof(float);
1144 if (!(*(char *)(&swap_test)))
1145 { c = (char *)(points); /* swap bytes */
1146 for (i=0; i<coords; i+=4)
1147 { cSwap = c[i]; c[i] = c[i+3]; c[i+3] = cSwap;
1148 cSwap = c[i+1]; c[i+1] = c[i+2]; c[i+2] = cSwap;
1152 if (!checked_write(f, points, coords, buffer))
1155 if (!(*(char *)(&swap_test)))
1156 { c = (char *)(points); /* swap bytes back */
1157 for (i=0; i<coords; i+=4)
1158 { cSwap = c[i]; c[i] = c[i+3]; c[i+3] = cSwap;
1159 cSwap = c[i+1]; c[i+1] = c[i+2]; c[i+2] = cSwap;
1164 if (!(tobuffer || getsize))
1165 if (f != fileno(stdout)) close(f);
1167 if (getsize) return;