Loading [MathJax]/extensions/tex2jax.js
Radium Engine  1.5.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
pvmutils.cpp
1 #include <IO/VolumesLoader/pvmutils.hpp>
2 
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 
7 namespace Ra {
8 namespace IO {
9 namespace PVMVolume {
10 
11 // source file extracted from http://www.stereofx.org/download/ V^3 Volume Renderer
12 
13 enum 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 
27 inline 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 
61 char DDS_ID[] = "DDS v3d\n";
62 char DDS_ID2[] = "DDS v3e\n";
63 unsigned char* DDS_cache;
64 unsigned int DDS_cachepos, DDS_cachesize;
65 
66 unsigned int DDS_buffer;
67 unsigned int DDS_bufsize;
68 
69 unsigned short int DDS_INTEL = 1;
70 
71 inline int DDS_decode( int bits ) {
72  return bits >= 1 ? bits + 1 : bits;
73 }
74 
75 // helper functions for DDS:
76 inline unsigned int DDS_shiftl( const unsigned int value, const unsigned int bits ) {
77  return ( bits >= 32 ) ? 0 : value << bits;
78 }
79 
80 inline unsigned int DDS_shiftr( const unsigned int value, const unsigned int bits ) {
81  return ( bits >= 32 ) ? 0 : value >> bits;
82 }
83 
84 inline 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 
91 void DDS_initbuffer() {
92  DDS_buffer = 0;
93  DDS_bufsize = 0;
94 }
95 
96 inline void DDS_clearbits() {
97  DDS_cache = nullptr;
98  DDS_cachepos = 0;
99  DDS_cachesize = 0;
100 }
101 
102 inline 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 
115 inline 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
143 void 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
209 void 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
217 void 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
283 unsigned 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
314 unsigned 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
329 unsigned 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
372 unsigned 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
Definition: Cage.cpp:3