Radium Engine  1.5.20
Loading...
Searching...
No Matches
pvmutils.cpp
1#include <IO/VolumesLoader/pvmutils.hpp>
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6
7namespace Ra {
8namespace IO {
9namespace PVMVolume {
10
11// source file extracted from http://www.stereofx.org/download/ V^3 Volume Renderer
12
13enum VR_ERROR {
14 VR_ERROR_NONFATAL = 0,
15 VR_ERROR_FATAL = 1,
16 VR_ERROR_MEM = 2,
17 VR_ERROR_IO = 3,
18 VR_ERROR_CODE = 4
19};
20
21#define ERRORMSG() vrerrormsg( __FILE__, __LINE__, VR_ERROR_FATAL )
22#define MEMERROR() vrerrormsg( __FILE__, __LINE__, VR_ERROR_MEM )
23#define IOERROR() vrerrormsg( __FILE__, __LINE__, VR_ERROR_IO )
24#define CODEERROR() vrerrormsg( __FILE__, __LINE__, VR_ERROR_CODE )
25#define WARNMSG( msg ) vrerrormsg( __FILE__, __LINE__, VR_ERROR_NONFATAL, msg )
26
27inline void vrerrormsg( const char* file, int line, int fatal, const char* msg = nullptr ) {
28 if ( fatal == VR_ERROR_NONFATAL )
29 fprintf( stderr, "warning" );
30 else if ( fatal == VR_ERROR_MEM )
31 fprintf( stderr, "insufficient memory" );
32 else if ( fatal == VR_ERROR_IO )
33 fprintf( stderr, "io error" );
34 else if ( fatal == VR_ERROR_CODE )
35 fprintf( stderr, "unimplemented code" );
36 else
37 fprintf( stderr, "fatal error" );
38 fprintf( stderr, " in <%s> at line %d!\n", file, line );
39 if ( msg != nullptr ) fprintf( stderr, "description: %s\n", msg );
40
41 if ( fatal != VR_ERROR_NONFATAL ) exit( 1 );
42}
43
44// Differential Data Stream defines and constants
45
46#define BOOLINT char
47
48#ifndef TRUE
49# define TRUE ( 1 )
50#endif
51#ifndef FALSE
52# define FALSE ( 0 )
53#endif
54
55#define DDS_MAXSTR ( 256 )
56#define DDS_BLOCKSIZE ( 1 << 20 )
57#define DDS_INTERLEAVE ( 1 << 24 )
58#define DDS_RL ( 7 )
59#define DDS_ISINTEL ( *( (unsigned char*)( &DDS_INTEL ) + 1 ) == 0 )
60
61char DDS_ID[] = "DDS v3d\n";
62char DDS_ID2[] = "DDS v3e\n";
63unsigned char* DDS_cache;
64unsigned int DDS_cachepos, DDS_cachesize;
65
66unsigned int DDS_buffer;
67unsigned int DDS_bufsize;
68
69unsigned short int DDS_INTEL = 1;
70
71inline int DDS_decode( int bits ) {
72 return bits >= 1 ? bits + 1 : bits;
73}
74
75// helper functions for DDS:
76inline unsigned int DDS_shiftl( const unsigned int value, const unsigned int bits ) {
77 return ( bits >= 32 ) ? 0 : value << bits;
78}
79
80inline unsigned int DDS_shiftr( const unsigned int value, const unsigned int bits ) {
81 return ( bits >= 32 ) ? 0 : value >> bits;
82}
83
84inline void DDS_swapuint( unsigned int* x ) {
85 unsigned int tmp = *x;
86
87 *x = ( ( tmp & 0xff ) << 24 ) | ( ( tmp & 0xff00 ) << 8 ) | ( ( tmp & 0xff0000 ) >> 8 ) |
88 ( ( tmp & 0xff000000 ) >> 24 );
89}
90
91void DDS_initbuffer() {
92 DDS_buffer = 0;
93 DDS_bufsize = 0;
94}
95
96inline void DDS_clearbits() {
97 DDS_cache = nullptr;
98 DDS_cachepos = 0;
99 DDS_cachesize = 0;
100}
101
102inline void DDS_loadbits( unsigned char* data, unsigned int size ) {
103 DDS_cache = data;
104 DDS_cachesize = size;
105
106 if ( ( DDS_cache = (unsigned char*)realloc( DDS_cache, DDS_cachesize + 4 ) ) == nullptr )
107 MEMERROR();
108 *( (unsigned int*)&DDS_cache[DDS_cachesize] ) = 0;
109
110 DDS_cachesize = 4 * ( ( DDS_cachesize + 3 ) / 4 );
111 if ( ( DDS_cache = (unsigned char*)realloc( DDS_cache, DDS_cachesize ) ) == nullptr )
112 MEMERROR();
113}
114
115inline unsigned int DDS_readbits( unsigned int bits ) {
116 unsigned int value;
117
118 if ( bits < DDS_bufsize ) {
119 DDS_bufsize -= bits;
120 value = DDS_shiftr( DDS_buffer, DDS_bufsize );
121 }
122 else {
123 value = DDS_shiftl( DDS_buffer, bits - DDS_bufsize );
124
125 if ( DDS_cachepos >= DDS_cachesize )
126 DDS_buffer = 0;
127 else {
128 DDS_buffer = *( (unsigned int*)&DDS_cache[DDS_cachepos] );
129 if ( DDS_ISINTEL ) DDS_swapuint( &DDS_buffer );
130 DDS_cachepos += 4;
131 }
132
133 DDS_bufsize += 32 - bits;
134 value |= DDS_shiftr( DDS_buffer, DDS_bufsize );
135 }
136
137 DDS_buffer &= DDS_shiftl( 1, DDS_bufsize ) - 1;
138
139 return value;
140}
141
142// deinterleave a byte stream
143void DDS_deinterleave( unsigned char* data,
144 unsigned int bytes,
145 unsigned int skip,
146 unsigned int block = 0,
147 BOOLINT restore = FALSE ) {
148 unsigned int i, j, k;
149
150 unsigned char *data2, *ptr;
151
152 if ( skip <= 1 ) return;
153
154 if ( block == 0 ) {
155 if ( ( data2 = (unsigned char*)malloc( bytes ) ) == nullptr ) MEMERROR();
156
157 if ( !restore )
158 for ( ptr = data2, i = 0; i < skip; i++ )
159 for ( j = i; j < bytes; j += skip )
160 *ptr++ = data[j];
161 else
162 for ( ptr = data, i = 0; i < skip; i++ )
163 for ( j = i; j < bytes; j += skip )
164 data2[j] = *ptr++;
165
166 memcpy( data, data2, bytes );
167 }
168 else {
169 if ( ( data2 = (unsigned char*)malloc(
170 ( bytes < skip * block ) ? bytes : skip * block ) ) == nullptr )
171 MEMERROR();
172
173 if ( !restore ) {
174 for ( k = 0; k < bytes / skip / block; k++ ) {
175 for ( ptr = data2, i = 0; i < skip; i++ )
176 for ( j = i; j < skip * block; j += skip )
177 *ptr++ = data[k * skip * block + j];
178
179 memcpy( data + k * skip * block, data2, skip * block );
180 }
181
182 for ( ptr = data2, i = 0; i < skip; i++ )
183 for ( j = i; j < bytes - k * skip * block; j += skip )
184 *ptr++ = data[k * skip * block + j];
185
186 memcpy( data + k * skip * block, data2, bytes - k * skip * block );
187 }
188 else {
189 for ( k = 0; k < bytes / skip / block; k++ ) {
190 for ( ptr = data + k * skip * block, i = 0; i < skip; i++ )
191 for ( j = i; j < skip * block; j += skip )
192 data2[j] = *ptr++;
193
194 memcpy( data + k * skip * block, data2, skip * block );
195 }
196
197 for ( ptr = data + k * skip * block, i = 0; i < skip; i++ )
198 for ( j = i; j < bytes - k * skip * block; j += skip )
199 data2[j] = *ptr++;
200
201 memcpy( data + k * skip * block, data2, bytes - k * skip * block );
202 }
203 }
204
205 free( data2 );
206}
207
208// interleave a byte stream
209void DDS_interleave( unsigned char* data,
210 unsigned int bytes,
211 unsigned int skip,
212 unsigned int block = 0 ) {
213 DDS_deinterleave( data, bytes, skip, block, TRUE );
214}
215
216// decode a Differential Data Stream
217void DDS_decode( unsigned char* chunk,
218 unsigned int size,
219 unsigned char** data,
220 unsigned int* bytes,
221 unsigned int block = 0 ) {
222 unsigned int skip, strip;
223
224 unsigned char *ptr1, *ptr2;
225
226 unsigned int cnt, cnt1, cnt2;
227 int bits, act;
228
229 DDS_initbuffer();
230
231 DDS_clearbits();
232 DDS_loadbits( chunk, size );
233
234 skip = DDS_readbits( 2 ) + 1;
235 strip = DDS_readbits( 16 ) + 1;
236
237 ptr1 = ptr2 = nullptr;
238 cnt = act = 0;
239
240 while ( ( cnt1 = DDS_readbits( DDS_RL ) ) != 0 ) {
241 bits = DDS_decode( DDS_readbits( 3 ) );
242
243 for ( cnt2 = 0; cnt2 < cnt1; cnt2++ ) {
244 if ( strip == 1 || cnt <= strip )
245 act += DDS_readbits( bits ) - ( 1 << bits ) / 2;
246 else
247 act += *( ptr2 - strip ) - *( ptr2 - strip - 1 ) + DDS_readbits( bits ) -
248 ( 1 << bits ) / 2;
249
250 while ( act < 0 )
251 act += 256;
252 while ( act > 255 )
253 act -= 256;
254
255 if ( ( cnt & ( DDS_BLOCKSIZE - 1 ) ) == 0 ) {
256 if ( ptr1 == nullptr ) {
257 if ( ( ptr1 = (unsigned char*)malloc( DDS_BLOCKSIZE ) ) == nullptr ) MEMERROR();
258 ptr2 = ptr1;
259 }
260 else {
261 if ( ( ptr1 = (unsigned char*)realloc( ptr1, cnt + DDS_BLOCKSIZE ) ) ==
262 nullptr )
263 MEMERROR();
264 ptr2 = &ptr1[cnt];
265 }
266 }
267
268 *ptr2++ = act;
269 cnt++;
270 }
271 }
272
273 if ( ptr1 != nullptr )
274 if ( ( ptr1 = (unsigned char*)realloc( ptr1, cnt ) ) == nullptr ) MEMERROR();
275
276 DDS_interleave( ptr1, cnt, skip, block );
277
278 *data = ptr1;
279 *bytes = cnt;
280}
281
282// read from a RAW file
283unsigned char* readRAWfiled( FILE* file, unsigned int* bytes ) {
284 unsigned char* data;
285 unsigned int cnt, blkcnt;
286
287 data = nullptr;
288 cnt = 0;
289
290 do {
291 if ( data == nullptr ) {
292 if ( ( data = (unsigned char*)malloc( DDS_BLOCKSIZE ) ) == nullptr ) MEMERROR();
293 }
294 else if ( ( data = (unsigned char*)realloc( data, cnt + DDS_BLOCKSIZE ) ) == nullptr )
295 MEMERROR();
296
297 blkcnt = fread( &data[cnt], 1, DDS_BLOCKSIZE, file );
298 cnt += blkcnt;
299 } while ( blkcnt == DDS_BLOCKSIZE );
300
301 if ( cnt == 0 ) {
302 free( data );
303 return nullptr;
304 }
305
306 if ( ( data = (unsigned char*)realloc( data, cnt ) ) == nullptr ) MEMERROR();
307
308 *bytes = cnt;
309
310 return data;
311}
312
313// read a RAW file
314unsigned char* readRAWfile( const char* filename, unsigned int* bytes ) {
315 FILE* file;
316
317 unsigned char* data;
318
319 if ( ( file = fopen( filename, "rb" ) ) == nullptr ) return nullptr;
320
321 data = readRAWfiled( file, bytes );
322
323 fclose( file );
324
325 return data;
326}
327
328// read a Differential Data Stream
329unsigned char* readDDSfile( const char* filename, unsigned int* bytes ) {
330 int version = 1;
331
332 FILE* file;
333
334 int cnt;
335
336 unsigned char *chunk, *data;
337 unsigned int size;
338
339 if ( ( file = fopen( filename, "rb" ) ) == nullptr ) return nullptr;
340
341 for ( cnt = 0; DDS_ID[cnt] != '\0'; cnt++ )
342 if ( fgetc( file ) != DDS_ID[cnt] ) {
343 fclose( file );
344 version = 0;
345 break;
346 }
347
348 if ( version == 0 ) {
349 if ( ( file = fopen( filename, "rb" ) ) == nullptr ) return nullptr;
350
351 for ( cnt = 0; DDS_ID2[cnt] != '\0'; cnt++ )
352 if ( fgetc( file ) != DDS_ID2[cnt] ) {
353 fclose( file );
354 return nullptr;
355 }
356
357 version = 2;
358 }
359
360 if ( ( chunk = readRAWfiled( file, &size ) ) == nullptr ) IOERROR();
361
362 fclose( file );
363
364 DDS_decode( chunk, size, &data, bytes, version == 1 ? 0 : DDS_INTERLEAVE );
365
366 free( chunk );
367
368 return data;
369}
370
371// read a compressed PVM volume
372unsigned char* readPVMvolume( const char* filename,
373 unsigned int* width,
374 unsigned int* height,
375 unsigned int* depth,
376 unsigned int* bytes,
377 float* scalex,
378 float* scaley,
379 float* scalez,
380 unsigned char** desc,
381 unsigned char** courtesy,
382 unsigned char** parameter,
383 unsigned char** comment ) {
384 unsigned char *data, *ptr;
385 unsigned int datasize, numc;
386
387 int version = 1;
388
389 unsigned char* volume;
390
391 float sx = 1.0f, sy = 1.0f, sz = 1.0f;
392
393 unsigned int len1 = 0, len2 = 0, len3 = 0, len4 = 0;
394
395 if ( ( data = readDDSfile( filename, &datasize ) ) == nullptr )
396 if ( ( data = readRAWfile( filename, &datasize ) ) == nullptr ) return nullptr;
397
398 if ( datasize < 5 ) return nullptr;
399
400 if ( ( data = (unsigned char*)realloc( data, datasize + 1 ) ) == nullptr ) MEMERROR();
401 data[datasize] = '\0';
402
403 if ( strncmp( (char*)data, "PVM\n", 4 ) != 0 ) {
404 if ( strncmp( (char*)data, "PVM2\n", 5 ) == 0 )
405 version = 2;
406 else if ( strncmp( (char*)data, "PVM3\n", 5 ) == 0 )
407 version = 3;
408 else
409 return nullptr;
410
411 ptr = &data[5];
412 if ( sscanf( (char*)ptr, "%u %u %u\n%g %g %g\n", width, height, depth, &sx, &sy, &sz ) !=
413 6 )
414 ERRORMSG();
415 if ( *width < 1 || *height < 1 || *depth < 1 || sx <= 0.0f || sy <= 0.0f || sz <= 0.0f )
416 ERRORMSG();
417 ptr = (unsigned char*)strchr( (char*)ptr, '\n' ) + 1;
418 }
419 else {
420 ptr = &data[4];
421 while ( *ptr == '#' )
422 while ( *ptr++ != '\n' )
423 ;
424
425 if ( sscanf( (char*)ptr, "%u %u %u\n", width, height, depth ) != 3 ) ERRORMSG();
426 if ( *width < 1 || *height < 1 || *depth < 1 ) ERRORMSG();
427 }
428
429 if ( scalex != nullptr && scaley != nullptr && scalez != nullptr ) {
430 *scalex = sx;
431 *scaley = sy;
432 *scalez = sz;
433 }
434
435 ptr = (unsigned char*)strchr( (char*)ptr, '\n' ) + 1;
436 if ( sscanf( (char*)ptr, "%u\n", &numc ) != 1 ) ERRORMSG();
437 if ( numc < 1 ) ERRORMSG();
438
439 if ( bytes != nullptr )
440 *bytes = numc;
441 else if ( numc != 1 )
442 ERRORMSG();
443
444 ptr = (unsigned char*)strchr( (char*)ptr, '\n' ) + 1;
445 if ( version == 3 )
446 len1 = strlen( (char*)( ptr + ( *width ) * ( *height ) * ( *depth ) * numc ) ) + 1;
447 if ( version == 3 )
448 len2 = strlen( (char*)( ptr + ( *width ) * ( *height ) * ( *depth ) * numc + len1 ) ) + 1;
449 if ( version == 3 )
450 len3 =
451 strlen( (char*)( ptr + ( *width ) * ( *height ) * ( *depth ) * numc + len1 + len2 ) ) +
452 1;
453 if ( version == 3 )
454 len4 = strlen( (char*)( ptr + ( *width ) * ( *height ) * ( *depth ) * numc + len1 + len2 +
455 len3 ) ) +
456 1;
457 if ( ( volume = (unsigned char*)malloc( ( *width ) * ( *height ) * ( *depth ) * numc + len1 +
458 len2 + len3 + len4 ) ) == nullptr )
459 MEMERROR();
460 if ( data + datasize !=
461 ptr + ( *width ) * ( *height ) * ( *depth ) * numc + len1 + len2 + len3 + len4 )
462 ERRORMSG();
463
464 memcpy( volume, ptr, ( *width ) * ( *height ) * ( *depth ) * numc + len1 + len2 + len3 + len4 );
465 free( data );
466
467 if ( desc != nullptr ) {
468 if ( len1 > 1 )
469 *desc = volume + ( *width ) * ( *height ) * ( *depth ) * numc;
470 else
471 *desc = nullptr;
472 }
473 if ( courtesy != nullptr ) {
474 if ( len2 > 1 )
475 *courtesy = volume + ( *width ) * ( *height ) * ( *depth ) * numc + len1;
476 else
477 *courtesy = nullptr;
478 }
479
480 if ( parameter != nullptr ) {
481 if ( len3 > 1 )
482 *parameter = volume + ( *width ) * ( *height ) * ( *depth ) * numc + len1 + len2;
483 else
484 *parameter = nullptr;
485 }
486
487 if ( comment != nullptr ) {
488 if ( len4 > 1 )
489 *comment = volume + ( *width ) * ( *height ) * ( *depth ) * numc + len1 + len2 + len3;
490 else
491 *comment = nullptr;
492 }
493
494 return volume;
495}
496
497} // namespace PVMVolume
498
499} // namespace IO
500} // namespace Ra
T exit(T... args)
T fclose(T... args)
T fgetc(T... args)
T fopen(T... args)
T fprintf(T... args)
T fread(T... args)
T free(T... args)
T sscanf(T... args)
T malloc(T... args)
T memcpy(T... args)
hepler function to manage enum as underlying types in VariableSet
Definition Cage.cpp:3
T realloc(T... args)
T strchr(T... args)
T strlen(T... args)
T strncmp(T... args)