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"
14 #include <sys/stat.h>
\r
18 //#define _read readfix
\r
20 #define AVSINT ptrdiff_t
\r
26 # if defined(__GNUC__) || defined(unix)
\r
27 typedef long long Q_INT64;
\r
28 typedef unsigned long long Q_UINT64;
\r
29 # define Q_INT64_CONST(x) (x##ll)
\r
30 # define Q_UINT64_CONST(x) (x##llu) /* gcc also allows ull */
\r
31 /* When using MINGW with MS(V)CRT DLL, use MS format modifier. */
\r
33 # define Q_INT64_FORMAT "I64"
\r
35 # define Q_INT64_FORMAT "L"
\r
37 # elif defined(__BORLANDC__) || defined(__WATCOMC__) || defined(_MSC_VER)
\r
38 typedef __int64 Q_INT64;
\r
39 typedef unsigned __int64 Q_UINT64;
\r
40 # define Q_INT64_CONST(x) (x##i64)
\r
41 # define Q_UINT64_CONST(x) (x##ui64) /* i64u is not allowed! */
\r
43 # define Q_INT64_FORMAT "I64"
\r
45 # define Q_INT64_FORMAT "L"
\r
48 # error No 64 bit integers known for this compiler, edit portdefs.h.
\r
52 bool clitk::XdrImageIO::CanWriteFile(const char* FileNameToWrite)
53 { std::string filename(FileNameToWrite);
54 std::string filenameext = GetExtension(filename);
55 if (filenameext != std::string("xdr")) return false;
59 void clitk::XdrImageIO::Write(const void* buffer)
61 WriteImage( m_FileName.c_str(), s, s, 0, -1, 0, 2, 0, 0, 0, 0, buffer);
64 /************************************************************************/
\r
66 /* file : AVS_WXDR.C */
\r
68 /* purpose : AVS module for writing XDR and RAW files */
\r
70 /* author : Lambert Zijp (based on a true story by */
\r
71 /* Marcel van Herk) */
\r
73 /* date : 19970716 */
\r
75 /* portability: AVS requires sizeof(void *)==sizeof(int) */
\r
76 /* This module assumes sizeof(int)>=4 */
\r
78 /* notes : This module has been integrated in QUIRT */
\r
80 /************************************************************************/
\r
83 19980212 ljz Creation (i.e. Removed from 'mbfield4.c')
\r
84 19980304 ljz Added QUIRT_NEXT_PARAMETER_FILE
\r
85 19980310 ljz Fix: XDRs were written in text-mode when
\r
86 quirt_init() is not called
\r
87 19980319 ljz Undone last change: _fmode is set in DllEntryPoint
\r
88 19980408 tp Moved M$-specific includes;
\r
89 removed AVS portability anyway
\r
90 19980611 mvh Added offset to write_raw (write into file)
\r
91 20000214 lsp Check file handle returned by open before use
\r
92 20000313 nd Two AVSerror messages added.
\r
93 20000322 lsp Matched compute func declaration with desc func
\r
94 20000630 ljz Added WRITE_RAW_LE, to write little-endian pixel-data
\r
95 20000806 lsp Compute func now 'int', conformal to ANSI C++
\r
96 20000821 ljz Added NkiCompression parameter to WRITE_XDR. If used,
\r
97 mode 2 is recommended.
\r
98 20000504 mvh Added write coordinates in header option to WRITE_XDR
\r
99 20010720 mvh Added option to write to stdout: pass "" as filename
\r
100 20010723 mvh Made it working by redefining write; setmode does not work
\r
101 20010725 bb Changed include order of windows.h and mbavs2q.h
\r
103 20020124 mvh+kg The datatype in the header is now e.g. "xdr_integer"
\r
104 The datatypes as "integer" were intended as having native
\r
105 byte order, while we wrote bigendian (high byte first). Our
\r
106 older files read therefore OK on HP and SUN but not on linux.
\r
107 20020124 mvh+kg On AVS5 xdr_byte is illegal. Replace only that one by 'byte'
\r
108 20030311 bb Added check on write errors. Disc full errors during a
\r
109 write have nasty side-effects for other programs' open files.
\r
110 Added check on file handle to prevent closing of stdout.
\r
111 20030430 mvh Added append mode for WRITE_XDR
\r
112 20030717 ljz Added support for NkiCompressionModes 3 and 4 (4 is recommended)
\r
113 20040426 mvh ELEKTA NKI-XVI0.1 RELEASE
\r
114 20040910 mvh Write uncompressed and warn if the compress malloc fails, layout
\r
115 20040920 mvh Fixed the above option (failed in append mode)
\r
116 20040924 mvh Fixed warn in option
\r
117 20041117 mvh ELEKTA NKI-XVI0.1g RELEASE
\r
118 20050302 ljz Merant tracker ID #1867: Check on bad compression-ratio causing
\r
120 20050308 ljz+mvh ELEKTA NKI-XVI0.1j RELEASE
\r
121 20050411 mvh Fails on I178_s1_4H.3d mode 1: compression fails and written file corrupted
\r
122 20060903 mvh Added WRITE_MEM_XDR and QUERY_MEM_XDR
\r
123 20070330 mvh WRITE_XDR failed on G:\20605104_hypo lung\20605104_incl corr+doseab3.PACK
\r
124 20071015 mvh ELEKTA NKI-XVI3.08 RELEASE
\r
125 20080411 lsp+mw NULL->0 in WriteImage() ; __sun__ doesn't know <io.h>
\r
126 20080825 mgw Corrected slash in sys/stat.h include
\r
127 20081031 lsp+mvh ELEKTA NKI-XVI4.15 RELEASE
\r
128 20081119 lsp+sr Removed tell(f) call for Linux
\r
129 20081203 lsp __sun__ -> unix
\r
130 20090114 mvh ELEKTA NKI-XVI4.22 RELEASE
\r
131 20090529 lsp+sr Work around the 64 MB limitation of write() in Windows
\r
132 20090802 mvh ELEKTA NKI-XVI4.29 RELEASE
\r
133 20091209 lsp Added WRITE_MEM_RAW
\r
134 20091214 lsp 64 bits adaptations: pass high address of buffer as well,
\r
135 replaced int by AVSINT when requested, process buffer in chunks
\r
136 to be able to interpret return value of write() (signed int) correctly,
\r
137 replaced out-of-range constants 0xc0 and 0x80 by their signed equivalents
\r
138 20091216 lsp+ljz Prepared compression for more than 4294967295 (UINT_MAX) shorts
\r
139 by using bigger NKI_MODE2_64BITS struct (backwards compatible)
\r
140 20091216 lsp Disabled #define write for clarity: checked_write() is used throughout
\r
141 Use more space for pCompressed to be able to call WRITE_XDR with compression
\r
142 on small fields (<10 pixels for mode 2 or 4, <2 pixels for mode 1 and 3)
\r
145 /************************************************************************/
\r
146 /* MODULE DOCUMENTATION */
\r
147 /************************************************************************/
\r
149 AVS Modules Lambert Zijp XDR writer & RAW writer
\r
152 XDR writer - Module for writing XDR and RAW files
\r
157 Availability : specify in which module libraries
\r
159 Source AVS_WXDR (C++ interface)
\r
161 Type Render / Output
\r
163 QUIRT name WRITE_XDR & WRITE_RAW
\r
165 Inputs Input field = field
\r
169 Parameters Name Type Default Min Max
\r
171 Header info string (WRITE_XDR only!)
\r
172 Header file string (WRITE_XDR only!)
\r
173 File Offset integer (WRITE_RAW only!)
\r
174 NKI compression integer (WRITE_XDR only!)
\r
175 Coords in header boolean (WRITE_XDR only!)
\r
176 Append boolean (WRITE_XDR only!)
\r
179 WRITE_RAW: No header, no coordinates.
\r
180 Data only are written (high byte first); optionally into an
\r
181 existing file (if you specify an offset)
\r
183 WRITE_RAW_LE: No header, no coordinates.
\r
184 Data only are written (low byte first);
\r
185 optionally into an existing file (if you specify an offset)
\r
187 WRITE_XDR: Successively is written to file:
\r
188 - The string '#AVS wants ...'.
\r
189 - The optional Header info
\r
190 - The contents of the optional Header file
\r
191 - An ascii description of the Input field
\r
192 - Optionally the coordinates (coord%axis%[%pixel%]=%coord%)
\r
193 (%axis% is 1 based, %pixel% 0 based, %coord% is float)
\r
194 - Two bytes containing ascii character 0x0c
\r
195 - The Data in binary (high byte first).
\r
196 Or, if NKI_Compression is greater than zero, compressed data.
\r
197 - The Coordinates in binary IEEE float (high byte first)
\r
200 Input field (Required; field)
\r
201 Describe input here....
\r
205 A string described here....
\r
208 A string described here....
\r
211 A string described here....
\r
214 An integer (default -1). If set, WRITE_RAW writes the data
\r
215 into an existing file.
\r
218 An integer described here....
\r
220 Write coordinates in header
\r
221 A boolean described here....
\r
224 A boolean described here....
\r
233 (optional): in which AVS libraries available
\r
237 (optional): further specify type of Render / Output module
\r
240 (optional): which type of files are read|written
\r
243 The following network shows how .....
\r
253 (optional): describe limitations here
\r
256 Modules that can provide input:
\r
258 Modules that could be used in place of XDR writer:
\r
260 Modules that can take output:
\r
264 (optional): The following files
\r
265 {are needed for|are output from|give examples of|further document}
\r
271 WRITE_XDR AVS module XDR writer
\r
272 numerical_expression Input field = field
\r
273 string_expression name of xdr file to create
\r
274 string_expression extra header info (default "")
\r
275 string_expression text file with more header info (default none)
\r
276 numerical_expression NKI compression (default 0)
\r
277 numerical_expression Coordinates in header (boolean, default 0)
\r
278 numerical_expression Append to file (boolean, default 0)
\r
280 WRITE_RAW AVS module Raw writer
\r
281 numerical_expression Input field = field
\r
282 string_expression name of file to write
\r
283 numerical_expression Offset; if not -1 (default) writes into file at offset
\r
285 WRITE_RAW_LE AVS module Raw writer little endian
\r
286 numerical_expression Input field = field
\r
287 string_expression name of file to write
\r
288 numerical_expression Offset; if not -1 (default) writes into file at offset
\r
291 numerical_expression Input field = field
\r
292 numerical_expression point to buffer to write xdr data into (use QUERY_MEM_XDR to find length)
\r
293 string_expression extra header info (default "")
\r
294 string_expression text file with more header info (default none)
\r
295 numerical_expression NKI compression (default 0)
\r
296 numerical_expression Coordinates in header (boolean, default 0)
\r
299 numerical_expression Input field = field
\r
300 name recieves required length for data
\r
301 string_expression extra header info (default "")
\r
302 string_expression text file with more header info (default none)
\r
303 numerical_expression NKI compression (default 0)
\r
304 numerical_expression Coordinates in header (boolean, default 0)
\r
306 Release 1.0 19980212 Lambert Zijp XDR writer & RAW writer
\r
308 /************************************************************************/
\r
309 /* INCLUDE FILES */
\r
310 /************************************************************************/
\r
312 #include <string.h>
\r
315 #include <stdlib.h>
\r
316 #include <limits.h>
\r
323 #include <algorithm>
\r
326 // don't use min() and max() macros indirectly defined by windows.h,
\r
327 // but use portable std::min() and std:max() instead
\r
331 #include <windows.h>
\r
334 /************************************************************************/
\r
335 /* DEFINES, ENUMERATED TYPES AND CONSTANTS */
\r
336 /************************************************************************/
\r
339 #define fileno _fileno
355 // Fields with data size>8GB (having UINT_MAX short pixels) cannot be compressed using
\r
356 // NKI_MODE2 struct because iOrgSize has type "unsigned int". In that case use NKI_MODE2_64BITS.
\r
357 // The type of structure is indicated as follows:
\r
359 // iOrgSize==0: NKI_MODE2_64BITS
\r
360 // otherwise : NKI_MODE2
\r
362 // Compression modes 1 and 3 (without CRCs) only use the first 2 members (iOrgSize and iMode).
\r
366 unsigned int iOrgSize; /* in pixels (i.e. shorts) */
\r
367 unsigned int iMode; /* 1, 2, 3 or 4 */
\r
368 unsigned int iCompressedSize; /* in bytes, excluding header */
\r
369 unsigned int iOrgCRC; /* CRC of the data (no coords etc) */
\r
370 unsigned int iCompressedCRC; /* CRC of the compressed data, excluding this header */
\r
375 unsigned int iOrgSize; /* in pixels (i.e. shorts) */
\r
376 unsigned int iMode; /* 1, 2, 3 or 4 */
\r
377 unsigned int iCompressedSize; /* in bytes, excluding header */
\r
378 unsigned int iOrgCRC; /* CRC of the data (no coords etc) */
\r
379 unsigned int iCompressedCRC; /* CRC of the compressed data, excluding this header */
\r
380 unsigned int iPad; /* unused */
\r
381 Q_UINT64 i64OrgSize; /* used for more than UINT_MAX pixels, indicated by iOrgSize==0 (0-vector not compressed) */
\r
382 Q_UINT64 i64CompressedSize; /* value in BYTES, used for more than UINT_MAX PIXELS, indicated by iCompressedSize==0 */
\r
383 Q_UINT64 i64Future1;
\r
384 Q_UINT64 i64Future2;
\r
385 } NKI_MODE2_64BITS;
\r
389 // Changed next to static function in stead of macro so it can
\r
390 // have a return value to check in the calling function.
\r
391 // It could be made inline as well, but there is no real time
\r
392 // punishment from the extra layer of function calls.
\r
394 // note: some compilers do not like comments ending in a backslash.
\r
395 // so use macro functions to exclude.
\r
398 /************************************************************************/
\r
399 /* GLOBAL VARIABLES */
\r
400 /************************************************************************/
\r
402 static const unsigned long CRC32_table[256] = {
\r
403 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
\r
404 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
\r
405 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
\r
406 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
\r
407 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
\r
408 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
\r
409 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
\r
410 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
\r
411 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
\r
412 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
\r
413 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
\r
414 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
\r
415 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
\r
416 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
\r
417 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
\r
418 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
\r
419 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
\r
420 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
\r
421 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
\r
422 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
\r
423 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
\r
424 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
\r
425 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
\r
426 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
\r
427 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
\r
428 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
\r
429 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
\r
430 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
\r
431 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
\r
432 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
\r
433 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
\r
434 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
\r
435 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
\r
436 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
\r
437 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
\r
438 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
\r
439 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
\r
440 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
\r
441 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
\r
442 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
\r
443 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
\r
444 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
\r
445 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
\r
448 /************************************************************************/
\r
449 /* MODULE FUNCTIONS */
\r
450 /************************************************************************/
\r
455 int writefix(int file, const void *buf, unsigned int count)
\r
456 { int i, j, k, total=0;
\r
458 for (i=0; i<count; i+=16384)
\r
460 if (j>16384) j=16384;
\r
462 k=_write(file, (char *)buf+i, j);
\r
463 if (k < 0) return k;
\r
475 Version of write() that takes special action in case of
\r
476 standard output. Based on commented out macro above.
\r
477 This function overloads the <cstdio> (or stdio.h for old style C++)
\r
481 // Like the original macro, we do /not/ want writefix from mbfield.c.
\r
485 static int wxdr_write(int handle, const void * buf, unsigned len)
\r
487 // if (handle == 1) // stdout
\r
488 if (handle == fileno(stdout))
\r
491 // Behave as C standard library write(): return number of bytes
\r
492 // written or -1 and errno set on error.
\r
494 DWORD dwBytesWritten;
\r
495 if (!WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, len,
\r
496 &dwBytesWritten, NULL))
\r
498 // There is no simple 1-to-1 mapping between GetLastError()
\r
499 // values that WriteFile() can return (quite a lot) and the two
\r
500 // errno values that write() can return. So return EACCES in
\r
501 // almost all cases.
\r
502 switch (GetLastError())
\r
503 { case ERROR_INVALID_HANDLE:
\r
504 errno = EBADF ; break;
\r
506 errno = EACCES; break;
\r
511 return (int)dwBytesWritten; // May still be < len!
\r
512 // And... write() may write a maximum of UINT_MAX-1 bytes, whereas
\r
513 // WriteFile() may write UINT_MAX bytes at once. But since
\r
514 // int(UINT_MAX) == -1 this will pose an actual problem in the
\r
517 const int oldmode = setmode(handle, O_BINARY);
\r
518 const int iBytesWritten = write(handle, buf, len);
\r
519 const int saveerrno = errno; // setmode() may change errno.
\r
520 if (oldmode != -1) setmode(handle, oldmode);
\r
522 return iBytesWritten;
\r
526 return _write(handle, buf, len);
\r
531 Behaves like win32 WriteFile() and returns a Boolean to indicate
\r
532 success or failure, where failure almost invariably means disc full.
\r
534 !!! SIDE EFFECT !!!
\r
536 In case of failure, this function issues an AVS error message
\r
537 and closes the file (if handle != 1). It is up to the calling
\r
538 function to return the AVS_ERROR state and before that do things
\r
539 like close other files, free memory etc. This way, there is less
\r
540 chance of erroneously duplicated code, like in:
\r
541 written = write(f, temp, strlen(temp));
\r
542 if (written == -1 || written != strlen(temp))
\r
544 if (f != fileno(stdout)) close(f);
\r
547 written = write(f, buf, buflength)
\r
548 if (written == -1 || written != strlen(temp)) {
\r
549 // oops, wrong length copy'n'pasted
\r
551 If more elaborate error handling is needed then the calling
\r
552 functuon should use the (overloaded) write() and act on its return
\r
553 value (and the value of errno) accordingly.
\r
555 It does /not/ close stdout.
\r
557 !!! SIDE EFFECT !!!
\r
559 Note that checked_write() takes a size_t for len, whereas write() takes
\r
560 an unsigned int of 4 bytes. On a 64 bits OS a size_t will be an 8 byte integer,
\r
561 enabling more than UINT_MAX bytes to write at once.
\r
563 static BOOL checked_write(int handle, const void * buf, size_t len, char **buffer)
\r
564 { if (buffer && !handle)
\r
565 { memcpy(*buffer, buf, len);
\r
569 if (buffer && handle)
\r
570 { (*buffer) += len;
\r
574 { for(int i=0; i<2; i++)
\r
575 { int byteswritten;
\r
579 //If write fails, test if not related to big buffer problem
\r
580 //Bug report http://support.microsoft.com/kb/899149 entitled
\r
581 //"You cannot call the fwrite function to write to a buffer
\r
582 // that is larger than 64 MB in Visual C++ 2005,
\r
583 // in Visual C++ .NET 2003, or in Visual C++ .NET 2002"
\r
584 // NB: same thing for write function in binary mode
\r
587 // call wxdr_write (for handle!=fileno(stdout) a wrapper for write) several times
\r
588 // to interpret the signed 32-bit return value correctly
\r
589 while (remaining>0)
\r
590 { chunksize = (int)std::min(remaining, (size_t)INT_MAX);
\r
591 byteswritten = wxdr_write(handle, buf, chunksize);
\r
592 if (byteswritten == chunksize)
\r
593 remaining -= chunksize;
\r
595 break; // try writefix in the next round
\r
597 if (remaining == 0)
\r
601 { remaining = len;
\r
602 // call writefix (in mbfield.c) several times to interpret the signed 32-bit
\r
603 // return value correctly. writefix uses chunks of 16384 bytes
\r
604 while (remaining>0)
\r
605 { chunksize = (int)std::min(remaining, (size_t)INT_MAX);
\r
606 byteswritten = writefix(handle, buf, chunksize);
\r
607 if (byteswritten == chunksize)
\r
608 remaining -= chunksize;
\r
610 break; // even writefix failed: return error
\r
612 if (remaining == 0)
\r
616 // Note: file is open in binary mode, no need to compensate
\r
617 // for a value of byteswritten > len due to \n -> \r\n conversions.
\r
618 // (write() on a text stream is implementation dependent.)
\r
619 if (handle != fileno(stdout)) close(handle);
\r
620 AVSerror("Avs_wxdr: write failed, disk full?");
\r
625 /* coder for NKI private compressed pixel data
\r
626 arguments: dest = (in) points to area where compressed destination data is written (byte)
\r
627 src = (in) points to uncompressed source data (short)
\r
628 npixels = (in) number of pixels to compress
\r
630 The return value is the number of bytes in the compressed data (maximal 3*npixels+10, typical 0.52*npixels)
\r
633 - The first 4 bytes contain the number of short-int pixels
\r
634 - The following 4 bytes contain iMode=1
\r
635 - The rest is the compressed image
\r
638 - The first 4 bytes contain the number of short-int pixels
\r
639 - The following 4 bytes contain iMode=2
\r
640 - The following 4 bytes contain the size of the compressed image (in bytes)
\r
641 - The following 4 bytes contain the CRC of the original image
\r
642 - The following 4 bytes contain the CRC of the compressed image
\r
643 - The rest is the compressed image
\r
644 - The compressed size will be even (padded by a zero if necessary).
\r
647 - The first 4 bytes contain the number of short-int pixels
\r
648 - The following 4 bytes contain iMode=3
\r
649 - The rest is the compressed image, including 4 bit differences
\r
652 - The first 4 bytes contain the number of short-int pixels
\r
653 - The following 4 bytes contain iMode=4
\r
654 - The following 4 bytes contain the size of the compressed image (in bytes)
\r
655 - The following 4 bytes contain the CRC of the original image
\r
656 - The following 4 bytes contain 0
\r
657 - The rest is the compressed image, including 4 bit differences
\r
658 - The compressed size will be even (padded by a zero if necessary).
\r
660 iMode 1 and iMode 2 are identical, except for the CRC data that is included for iMode 2
\r
661 iMode 3 and iMode 4 are identical, except for the CRC data that is included for iMode 4
\r
664 // optimized settings for the 4 bit run compressor (mode 3 and 4)
\r
666 #define MINZEROS 5 // shortest RLE (2 byte overhead, but breaks 4bit run)
\r
667 #define MIN4BIT 6 // shortest 4 bit run (6 bytes compressed to 5 bytes)
\r
669 // This internal routine converts an 8 bit difference string into a 4 bit one
\r
670 static signed char *recompress4bit(int n, signed char *dest)
\r
671 { signed char *p, *q;
\r
677 val = (((int)p[0])<<4) | (p[1]&15);
\r
679 *dest++ = -0x40; // 192 (0xc0) does not fit between -128..127: maps to -64 (0x40) in 2's complement
\r
680 *dest++ = (signed char)n;
\r
684 { *dest++ = (signed char)((((int)p[0])<<4) | (p[1]&15));
\r
688 q[0] = (signed char)val;
\r
694 static size_t nki_private_compress(signed char *dest, short int *src, size_t npixels, int iMode)
\r
695 { unsigned long iCRC;
\r
696 unsigned long iCRC2;
\r
697 unsigned int iHeaderSize=8; // value for iMode==1 and iMode==3
\r
700 NKI_MODE2* pHeader = (NKI_MODE2*)dest;
\r
701 NKI_MODE2_64BITS* pHeader_64bits = (NKI_MODE2_64BITS*)dest;
\r
702 size_t iBufferSize;
\r
704 iBufferSize = (npixels / 2) * 3; // Buffer is sizeof(NKI_MODE2_64BITS) + 10 bytes larger
\r
706 /* Up till now only Mode=1 .. 4 are supported */
\r
707 if ((iMode < 1) || (iMode > 4))
\r
710 /* Create the header */
\r
711 pHeader->iMode = iMode;
\r
713 if (sizeof(int*)>sizeof(int) && npixels>UINT_MAX) // On a 64 bits OS we want to store files>4GB
\r
714 { pHeader_64bits->iOrgSize = 0; // This indicates>4GB file (0-vector is not compressed)
\r
715 pHeader_64bits->i64OrgSize = npixels;
\r
716 iHeaderSize = sizeof(NKI_MODE2_64BITS);
\r
717 dest += sizeof(NKI_MODE2_64BITS);
\r
720 { pHeader->iOrgSize = (unsigned int)(npixels & UINT_MAX); // store 32 bit number as first member
\r
722 if (iMode==2 || iMode==4)
\r
723 iHeaderSize = sizeof(NKI_MODE2);
\r
724 dest += iHeaderSize;
\r
727 /* Create the compressed image */
\r
730 { *(short int *)dest = *src;
\r
736 { val = src[1] - src[0];
\r
739 if (val == 0) /* run length-encode zero differences */
\r
741 { if (i>=npixels || src[i-1]!=src[-1] || i==256)
\r
745 { *dest++ = -128; // hexadecimal 0x80
\r
746 *dest++ = (signed char)(i-1);
\r
754 else if (val >= -64 && val <= 63) /* small difference coded as one byte */
\r
755 { *dest = (signed char)val;
\r
758 else if (val >= -0x3F00 && val <= 0x3EFF) /* large differences coded as two bytes */
\r
759 { dest[0] = (signed char)((val>>8) ^ 0x40);
\r
760 dest[1] = (signed char)val;
\r
763 else /* if very large differences code abs val as three bytes */
\r
765 *dest++ = (signed char)(src[0]>>8);
\r
766 *dest++ = (signed char)(src[0]);
\r
768 /* Are we beyond the allocated memory? */
\r
769 if ((size_t)(dest - (signed char*)pHeader) > iBufferSize)
\r
775 else if (iMode == 2)
\r
779 *(short int *)dest = val = *src;
\r
780 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (unsigned char) val ] ^ ((iCRC2 >> 8));
\r
781 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (unsigned char)(val>>8)] ^ ((iCRC2 >> 8));
\r
782 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char) val ] ^ ((iCRC >> 8));
\r
783 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char)(val>>8)] ^ ((iCRC >> 8));
\r
788 { val = src[1] - src[0];
\r
790 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char) src[0] ] ^ ((iCRC >> 8));
\r
791 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char)(src[0]>>8)] ^ ((iCRC >> 8));
\r
793 if (val == 0) /* run length-encode zero differences */
\r
795 { if (i>=npixels || src[i-1]!=src[-1] || i==256)
\r
798 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ 0 ] ^ ((iCRC2 >> 8));
\r
801 { *dest++ = -128; // hexadecimal 0x80
\r
802 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ 0x80 ] ^ ((iCRC2 >> 8));
\r
803 *dest++ = (signed char)(i-1);
\r
804 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (i-1)] ^ ((iCRC2 >> 8));
\r
807 for (j=0; j<i-2; j++)
\r
809 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char) src[0] ] ^ ((iCRC >> 8));
\r
810 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char)(src[0]>>8)] ^ ((iCRC >> 8));
\r
817 else if (val >= -64 && val <= 63) /* small difference coded as one byte */
\r
818 { *dest = (signed char)val;
\r
819 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (unsigned char)val ] ^ ((iCRC2 >> 8));
\r
822 else if (val >= -0x3F00 && val <= 0x3EFF) /* large differences coded as two bytes */
\r
823 { dest[0] = (signed char)((val>>8) ^ 0x40);
\r
824 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (unsigned char)dest[0] ] ^ ((iCRC2 >> 8));
\r
825 dest[1] = (signed char)val;
\r
826 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (unsigned char)val ] ^ ((iCRC2 >> 8));
\r
829 else /* if very large differences code abs val as three bytes */
\r
831 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ 0x7f ] ^ ((iCRC2 >> 8));
\r
833 dest[1] = (signed char)(val>>8);
\r
834 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (unsigned char)(val>>8)] ^ ((iCRC2 >> 8));
\r
835 dest[2] = (signed char)val;
\r
836 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ (unsigned char)val ] ^ ((iCRC2 >> 8));
\r
839 /* Are we beyond the allocated memory? */
\r
840 if ((size_t)(dest - (signed char*)pHeader) > iBufferSize)
\r
845 if ((dest - (signed char*)pHeader - iHeaderSize)<UINT_MAX) // store 32 bit number as third member
\r
846 pHeader->iCompressedSize =
\r
847 (unsigned int)(dest - (signed char*)pHeader - iHeaderSize);
\r
848 else // store 64 bit number in extended structure
\r
849 pHeader_64bits->i64CompressedSize = dest - (signed char*)pHeader -iHeaderSize;
\r
851 /* Pad it to get an even length */
\r
852 if (pHeader->iCompressedSize & 1)
\r
854 iCRC2 = CRC32_table[(unsigned char)iCRC2 ^ 0] ^ ((iCRC2 >> 8));
\r
855 pHeader->iCompressedSize++;
\r
858 pHeader->iOrgCRC = iCRC;
\r
859 pHeader->iCompressedCRC = iCRC2;
\r
862 /* Create the compressed image - compressor with added 4 bit run */
\r
864 else if (iMode == 3)
\r
866 *(short int *)dest = *src;
\r
871 { val = src[1] - src[0];
\r
874 if (val == 0) /* run length-encode zero differences */
\r
876 { if (i>=npixels || src[i-1]!=src[-1] || i==256)
\r
877 { if (i<=MINZEROS) /* too short run -> write zeros */
\r
878 { for (j=0; j<i-1; j++)
\r
882 if(n4bit>=254) /* maximum length 4 bit run */
\r
883 { dest = recompress4bit(n4bit, dest);
\r
889 { if (n4bit>=MIN4BIT) /* end (and write) 4 bit run */
\r
890 dest = recompress4bit(n4bit, dest);
\r
893 *dest++ = -128; // hexadecimal 0x80
\r
894 *dest++ = (signed char)(i-1);
\r
903 else if (val >= -63 && val <= 63) /* small difference coded as one byte */
\r
904 { if (val >= -8 && val <= 7)
\r
905 { *dest++ = (signed char)val;
\r
908 if(n4bit>=254) /* maximum length 4 bit run */
\r
909 { dest = recompress4bit(n4bit, dest);
\r
913 else if(n4bit>=MIN4BIT) /* end and write 4 bit run */
\r
915 dest = recompress4bit(n4bit, dest);
\r
917 *dest++ = (signed char)j;
\r
920 { *dest++ = (signed char)val; /* end 4 bit run */
\r
924 else if (val >= -0x3F00 && val <= 0x3EFF) /* large differences coded as two bytes */
\r
927 if(n4bit>=MIN4BIT) /* end (and write) 4 bit run */
\r
928 dest = recompress4bit(n4bit, dest);
\r
931 dest[0] = (signed char)((j>>8) ^ 0x40);
\r
932 dest[1] = (signed char)j;
\r
935 else /* if very large differences code abs val as three bytes */
\r
938 if(n4bit>=MIN4BIT) /* end (and write) 4 bit run */
\r
939 dest = recompress4bit(n4bit, dest);
\r
943 *dest++ = (signed char)(j>>8);
\r
944 *dest++ = (signed char)j;
\r
946 /* Are we beyond the allocated memory? */
\r
947 if ((size_t)(dest - (signed char*)pHeader) > iBufferSize)
\r
953 /* Create the compressed image - compressor with added 4 bit run and CRC */
\r
955 else if (iMode == 4)
\r
959 *(short int *)dest = val = *src;
\r
960 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char) val ] ^ ((iCRC >> 8));
\r
961 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char)(val>>8)] ^ ((iCRC >> 8));
\r
966 { val = src[1] - src[0];
\r
968 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char) src[0] ] ^ ((iCRC >> 8));
\r
969 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char)(src[0]>>8)] ^ ((iCRC >> 8));
\r
971 if (val == 0) /* run length-encode zero differences */
\r
973 { if (i>=npixels || src[i-1]!=src[-1] || i==256)
\r
974 { if (i<=MINZEROS) /* too short run -> write zeros */
\r
975 { for (j=0; j<i-1; j++)
\r
979 if(n4bit>=254) /* maximum length 4 bit run */
\r
980 { dest = recompress4bit(n4bit, dest);
\r
986 { if (n4bit>=MIN4BIT) /* end (and write) 4 bit run */
\r
987 dest = recompress4bit(n4bit, dest);
\r
990 *dest++ = -128; // hexadecimal 0x80
\r
991 *dest++ = (signed char)(i-1);
\r
995 for (j=0; j<i-2; j++)
\r
997 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char) src[0] ] ^ ((iCRC >> 8));
\r
998 iCRC = CRC32_table[(unsigned char)iCRC ^ (unsigned char)(src[0]>>8)] ^ ((iCRC >> 8));
\r
1004 else if (val >= -63 && val <= 63) /* small difference coded as one byte */
\r
1005 { if (val >= -8 && val <= 7)
\r
1006 { *dest++ = (signed char)val;
\r
1009 if(n4bit>=254) /* maximum length 4 bit run */
\r
1010 { dest = recompress4bit(n4bit, dest);
\r
1014 else if(n4bit>=MIN4BIT) /* end and write 4 bit run */
\r
1016 dest = recompress4bit(n4bit, dest);
\r
1018 *dest++ = (signed char)j;
\r
1021 { *dest++ = (signed char)val; /* end 4 bit run */
\r
1025 else if (val >= -0x3F00 && val <= 0x3EFF) /* large differences coded as two bytes */
\r
1028 if(n4bit>=MIN4BIT) /* end (and write) 4 bit run */
\r
1029 dest = recompress4bit(n4bit, dest);
\r
1032 dest[0] = (signed char)((j>>8) ^ 0x40);
\r
1033 dest[1] = (signed char)j;
\r
1036 else /* if very large differences code abs val as three bytes */
\r
1039 if(n4bit>=MIN4BIT) /* end (and write) 4 bit run */
\r
1040 dest = recompress4bit(n4bit, dest);
\r
1044 *dest++ = (signed char)(j>>8);
\r
1045 *dest++ = (signed char)j;
\r
1047 /* Are we beyond the allocated memory? */
\r
1048 if ((size_t)(dest - (signed char*)pHeader) > iBufferSize)
\r
1051 while (--npixels);
\r
1053 if ((dest - (signed char*)pHeader - iHeaderSize)<UINT_MAX) // store 32 bit number as third member
\r
1054 pHeader->iCompressedSize =
\r
1055 (unsigned int)(dest - (signed char*)pHeader - iHeaderSize);
\r
1056 else // store 64 bit number in extended structure
\r
1057 { pHeader_64bits->iCompressedSize = 0;
\r
1058 pHeader_64bits->i64CompressedSize = dest - (signed char*)pHeader -iHeaderSize;
\r
1061 /* Pad it to get an even length */
\r
1062 if (pHeader->iCompressedSize & 1)
\r
1064 pHeader->iCompressedSize++;
\r
1067 pHeader->iOrgCRC = iCRC;
\r
1068 pHeader->iCompressedCRC = 0;
\r
1071 return dest - (signed char*)pHeader;
\r
1075 void clitk::XdrImageIO::WriteImage(const char* file, char* headerinfo, char* headerfile, int raw,
\r
1076 int offset, char bLittleEndian, int iNkiCompression,
\r
1077 int wcoords, int append, int getsize, char *tobuffer, const void* data)
\r
1086 long swap_test = 0x1000000;
\r
1087 signed char* pCompressed = NULL;
\r
1089 char **buffer = NULL;
\r
1094 if (bLittleEndian)
\r
1095 swap_test = 0x00000001;
\r
1098 { swap_test = 0xffffffff; // never swap to save time
\r
1099 buffer = (char **) &len;
\r
1104 { buf2 = (char *)tobuffer;
\r
1109 for (i=0; i<GetNumberOfDimensions(); i++)
\r
1110 { total *= GetDimensions(i);
\r
1111 coords += GetDimensions(i);
\r
1114 /* Try allocate the compressed fielddata - compression disabled if alloc fails */
\r
1115 if ((iNkiCompression > 0) &&
\r
1116 (GetComponentType() == itk::ImageIOBase::SHORT) &&
\r
1117 (GetPixelType() == itk::ImageIOBase::SCALAR))
\r
1118 { pCompressed = (signed char *)malloc((total/2) * 3 + sizeof(NKI_MODE2_64BITS) + 10);
\r
1119 if (pCompressed==NULL)
\r
1120 { iNkiCompression = 0;
\r
1121 AVSwarning("Avs_wxdr: not enough memory to compress data, saving uncompressed");
\r
1125 if (!(tobuffer || getsize))
\r
1126 { if (offset != -1)
\r
1127 { f = open(file, O_RDWR, 0);
\r
1130 AVSerror("Avs_wxdr: Opening " << file << "failed.\n" << strerror(errno));
\r
1131 free(pCompressed);
\r
1134 lseek(f, offset, SEEK_SET);
\r
1137 { if (strlen(file)==0)
\r
1138 f = fileno(stdout);
\r
1141 f = open(file, O_RDWR | O_APPEND, 0);
\r
1143 f = creat(file, S_IWRITE | S_IREAD);
\r
1147 { AVSerror("Avs_wxdr: Creating " << file << " failed.\n" << strerror(errno));
\r
1148 free(pCompressed);
\r
1155 { sprintf(temp, "# AVS wants to have the first line starting with its name\n");
\r
1156 slen = strlen(temp);
\r
1158 if (!checked_write(f, temp, slen, buffer))
\r
1159 { free(pCompressed);
\r
1164 slen = strlen(headerinfo);
\r
1165 if (slen && !checked_write(f, headerinfo, slen, buffer))
\r
1166 { free(pCompressed);
\r
1171 if (!checked_write(f, "\n", 1, buffer))
\r
1172 { free(pCompressed);
\r
1177 if (strlen(headerfile))
\r
1178 { fp = fopen(headerfile, "rt");
\r
1181 { if (fgets(temp, 255, fp) == NULL) break;
\r
1182 slen = strlen(temp);
\r
1183 if (!checked_write(f, temp, slen, buffer))
\r
1185 free(pCompressed);
\r
1191 if (!checked_write(f, "\n", 1, buffer))
\r
1192 { free(pCompressed);
\r
1199 sprintf(temp, "ndim=%d\n", GetNumberOfDimensions());
\r
1200 slen = strlen(temp);
\r
1201 if (!checked_write(f, temp, slen, buffer))
\r
1202 { free(pCompressed);
\r
1208 for (i=0; i<GetNumberOfDimensions(); i++)
\r
1210 { sprintf(temp, "dim%d=%d\n", i+1, GetDimensions(i));
\r
1211 slen = strlen(temp);
\r
1212 if (!checked_write(f, temp, slen, buffer))
\r
1213 { free(pCompressed);
\r
1221 { sprintf(temp, "nspace=%d\n", GetNumberOfDimensions());
\r
1222 slen = strlen(temp);
\r
1223 if (!checked_write(f, temp, slen, buffer))
\r
1224 { free(pCompressed);
\r
1229 sprintf(temp, "veclen=%d\n", GetNumberOfComponents());
\r
1230 slen = strlen(temp);
\r
1231 if (!checked_write(f, temp, slen, buffer))
\r
1232 { free(pCompressed);
\r
1237 switch(GetComponentType())
\r
1238 { case itk::ImageIOBase::CHAR : strcpy(temp, "data=byte\n"); break;
\r
1239 case itk::ImageIOBase::SHORT : strcpy(temp, "data=xdr_short\n"); break;
\r
1240 case itk::ImageIOBase::INT : strcpy(temp, "data=xdr_integer\n"); break;
\r
1241 case itk::ImageIOBase::FLOAT : strcpy(temp, "data=xdr_real\n"); break;
\r
1242 case itk::ImageIOBase::DOUBLE : strcpy(temp, "data=xdr_double\n"); break;
\r
1243 default : if (f != fileno(stdout)) close(f);
\r
1244 free(pCompressed);
\r
1247 slen = strlen(temp);
\r
1248 if (!checked_write(f, temp, slen, buffer))
\r
1249 { free(pCompressed);
\r
1256 //FilePos = tell(f);
\r
1260 //switch(input->uniform)
\r
1261 //{ case UNIFORM :
\r
1262 strcpy(temp, "field=uniform\n");
\r
1263 coords = GetNumberOfDimensions() * 2;
\r
1265 // case RECTILINEAR : strcpy(temp, "field=rectilinear\n");
\r
1267 // case IRREGULAR : strcpy(temp, "field=irregular\n");
\r
1268 // coords = total * input->nspace;
\r
1270 // default : if (f != fileno(stdout)) close(f);
\r
1271 // free(pCompressed);
\r
1276 { if (!checked_write(f, temp, strlen(temp), buffer))
\r
1277 { free(pCompressed);
\r
1281 if ((iNkiCompression > 0) &&
\r
1282 (GetComponentType() == itk::ImageIOBase::SHORT) &&
\r
1283 (GetPixelType() == itk::ImageIOBase::SCALAR))
\r
1284 { sprintf(temp, "nki_compression=%d", iNkiCompression);
\r
1285 if (!checked_write(f, temp, strlen(temp), buffer))
\r
1286 { free(pCompressed);
\r
1291 temp[0] = temp[1] = 12;
\r
1292 if (!checked_write(f, temp, 2, buffer))
\r
1293 { free(pCompressed);
\r
1298 total *= GetPixelSize();
\r
1300 if ((!raw) && (iNkiCompression > 0) &&
\r
1301 (GetComponentType() == itk::ImageIOBase::SHORT) &&
\r
1302 (GetPixelType() == itk::ImageIOBase::SCALAR))
\r
1303 { size_t iCompressedLength;
\r
1305 iCompressedLength = nki_private_compress(pCompressed,
\r
1306 (short int *)(data), total/2, iNkiCompression);
\r
1308 if (iCompressedLength > 0)
\r
1309 { if (!checked_write(f, pCompressed, iCompressedLength, buffer))
\r
1310 { free(pCompressed);
\r
1313 free(pCompressed);
\r
1314 goto WRITE_COORDS;
\r
1317 /* Compressionratio was poor: let's write uncompressed */
\r
1318 iNkiCompression = 0;
\r
1320 free(pCompressed);
\r
1321 pCompressed = NULL;
\r
1322 _lseeki64(f, (unsigned int)FilePos, SEEK_SET); // use _lseeki64 just in case header size > UINT_MAX bytes
\r
1326 /* swap data if required (xdr is low-endian) */
\r
1328 if (!(*(char *)(&swap_test)))
\r
1329 { if (GetComponentSize()==2)
\r
1330 { c = (char *)data;
\r
1331 for (i=0; i<total; i+=2)
\r
1332 { cSwap = c[i]; c[i] = c[i+1]; c[i+1] = cSwap;
\r
1335 else if (GetComponentSize()==4)
\r
1336 { c = (char *)data;
\r
1337 for (i=0; i<total; i+=4)
\r
1338 { cSwap = c[i]; c[i] = c[i+3]; c[i+3] = cSwap;
\r
1339 cSwap = c[i+1]; c[i+1] = c[i+2]; c[i+2] = cSwap;
\r
1342 else if (GetComponentSize()==8)
\r
1343 { c = (char *)data;
\r
1344 for (i=0; i<total; i+=8)
\r
1345 { cSwap = c[i]; c[i] = c[i+7]; c[i+7] = cSwap;
\r
1346 cSwap = c[i+1]; c[i+1] = c[i+6]; c[i+6] = cSwap;
\r
1347 cSwap = c[i+2]; c[i+2] = c[i+5]; c[i+5] = cSwap;
\r
1348 cSwap = c[i+3]; c[i+3] = c[i+4]; c[i+4] = cSwap;
\r
1354 { if (!checked_write(f, data, total, buffer))
\r
1358 /* swap data back if was swapped before writing */
\r
1360 if (!(*(char *)(&swap_test)))
\r
1361 { if (GetComponentSize()==2)
\r
1362 { c = (char *)data;
\r
1363 for (i=0; i<total; i+=2)
\r
1364 { cSwap = c[i]; c[i] = c[i+1]; c[i+1] = cSwap;
\r
1367 else if (GetComponentSize()==4)
\r
1368 { c = (char *)data;
\r
1369 for (i=0; i<total; i+=4)
\r
1370 { cSwap = c[i]; c[i] = c[i+3]; c[i+3] = cSwap;
\r
1371 cSwap = c[i+1]; c[i+1] = c[i+2]; c[i+2] = cSwap;
\r
1374 else if (GetComponentSize()==8)
\r
1375 { c = (char *)data;
\r
1376 for (i=0; i<total; i+=8)
\r
1377 { cSwap = c[i]; c[i] = c[i+7]; c[i+7] = cSwap;
\r
1378 cSwap = c[i+1]; c[i+1] = c[i+6]; c[i+6] = cSwap;
\r
1379 cSwap = c[i+2]; c[i+2] = c[i+5]; c[i+5] = cSwap;
\r
1380 cSwap = c[i+3]; c[i+3] = c[i+4]; c[i+4] = cSwap;
\r
1387 points = (float *)malloc(sizeof(float)*GetNumberOfDimensions()*2);
\r
1388 for (i=0; i<GetNumberOfDimensions(); i++)
1390 points[i*2 ] = 0.1 * GetOrigin(i);
1391 points[i*2+1] = 0.1 * (GetOrigin(i) + GetSpacing(i)*(GetDimensions(i)-1));
1394 if (coords && !raw) /* write AVS coordinates ? */
\r
1395 { coords *= sizeof(float);
\r
1396 if (!(*(char *)(&swap_test)))
\r
1397 { c = (char *)(points); /* swap bytes */
\r
1398 for (i=0; i<coords; i+=4)
\r
1399 { cSwap = c[i]; c[i] = c[i+3]; c[i+3] = cSwap;
\r
1400 cSwap = c[i+1]; c[i+1] = c[i+2]; c[i+2] = cSwap;
\r
1404 if (!checked_write(f, points, coords, buffer))
\r
1407 if (!(*(char *)(&swap_test)))
\r
1408 { c = (char *)(points); /* swap bytes back */
\r
1409 for (i=0; i<coords; i+=4)
\r
1410 { cSwap = c[i]; c[i] = c[i+3]; c[i+3] = cSwap;
\r
1411 cSwap = c[i+1]; c[i+1] = c[i+2]; c[i+2] = cSwap;
\r
1416 if (!(tobuffer || getsize))
\r
1417 if (f != fileno(stdout)) close(f);
\r
1419 if (getsize) return;
\r