VTK
vtkX3DExporterFIWriterHelper.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Visualization Toolkit
4  Module: vtkX3DExporterFIWriterHelper.h
5 
6  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7  All rights reserved.
8  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10  This software is distributed WITHOUT ANY WARRANTY; without even
11  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12  PURPOSE. See the above copyright notice for more information.
13 
14 =========================================================================*/
19 #ifndef vtkX3DExporterFIWriterHelper_h
20 #define vtkX3DExporterFIWriterHelper_h
21 
22 //#include "vtkX3DExporterFIByteWriter.h"
23 #include "vtkZLibDataCompressor.h"
24 #include <cassert>
25 
26 #define EXPONENT_MASK_32 0x7f800000
27 #define MANTISSA_MASK_32 0x007fffff
28 
29 #ifndef max
30 #define max(a,b) (((a) > (b)) ? (a) : (b))
31 #endif
33 {
34 public:
36  {
37  float f;
38  unsigned int ui;
39  unsigned char ub[4]; // unsigned bytes
40  };
41 
42  template<typename T>
43  static inline void EncodeFloatFI(vtkX3DExporterFIByteWriter* writer, T* value, size_t size)
44  {
45  // We want to start at position 3
46  assert(writer->CurrentBytePos == 2);
47 
48  // ITU C.19.3.4: If the alternative encoding-algorithm is present,
49  // then the two bits '11' (discriminant) are appended
50  writer->PutBits("11");
51  // ITU 10.8.1: This encoding algorithm has a vocabulary table index of 7,
52  writer->PutBits(7-1, 8);
53 
54  std::string bytes;
55  char byte[4];
56  for (size_t i = 0; i < size; i++)
57  {
59  v.f = value[i];
60 
61  // Avoid -0
62  if (v.ui == 0x80000000)
63  {
64  v.f = 0;
65  }
66 
67  byte[0] = v.ub[3];
68  byte[1] = v.ub[2];
69  byte[2] = v.ub[1];
70  byte[3] = v.ub[0];
71 
72  bytes.append(byte, 4);
73  }
74  EncodeNonEmptyByteString5(writer, bytes);
75  }
76 
77  template<typename T>
78  static inline void EncodeIntegerFI(vtkX3DExporterFIByteWriter* writer, T* value, size_t size)
79  {
80  // We want to start at position 3
81  assert(writer->CurrentBytePos == 2);
82 
83  // ITU C.19.3.4: If the alternative encoding-algorithm is present,
84  // then the two bits '11' (discriminant) are appended
85  writer->PutBits("11");
86  // ITU 10.8.1: This encoding algorithm has a vocabulary table index of 4,
87  writer->PutBits(4-1, 8);
88  std::string bytes;
89  for(size_t i = 0; i < size; i++)
90  {
91  int v = value[i];
92  int f = ReverseBytes(&v);
93  char *p = reinterpret_cast <char*> (&f);
94  bytes.append(p, 4);
95  }
96  EncodeNonEmptyByteString5(writer, bytes);
97  }
98 
99  static inline void EncodeCharacterString3(vtkX3DExporterFIByteWriter* writer, std::string value)
100  {
101  // We want to start at position 3
102  assert(writer->CurrentBytePos == 2);
103 
104  // ITU C.19.3.1 If the alternative utf-8 is present, then the two bits '00'
105  // are appended to the bit stream.
106  writer->PutBits("00");
107  // ITU C.19.4: The component bytes is encoded as described in C.23.
108  EncodeNonEmptyByteString5(writer, value);
109  }
110 
111  // ITU C.23: Encoding of the NonEmptyByteString starting
112  // on the fifth bit of an byte
113  static inline void EncodeNonEmptyByteString5(vtkX3DExporterFIByteWriter* writer, std::string value)
114  {
115  int length = static_cast<int>(value.length());
116  if (length <= 8)
117  {
118  writer->PutBit(0);
119  writer->PutBits(length - 1, 3);
120  }
121  else if (length <= 264)
122  {
123  writer->PutBits("1000");
124  writer->PutBits(length - 9, 8);
125  }
126  else
127  {
128  writer->PutBits("1100");
129  writer->PutBits(length - 265, 32);
130  }
131  writer->PutBytes(value.c_str(), length);
132  }
133 
134 
135  // ITU C.27: Encoding of integers in the range 1 to 2^20
136  // starting on the third bit of an byte
137  static inline void EncodeInteger3(vtkX3DExporterFIByteWriter* writer, unsigned int value)
138  {
139  // We want to start at position 3
140  assert(writer->CurrentBytePos == 2);
141 
142  if (value <= 32) // ITU C.27.2
143  {
144  writer->PutBit(0);
145  writer->PutBits(value - 1, 5);
146  }
147  else if (value <= 2080) // ITU C.27.3
148  {
149  writer->PutBits("100");
150  writer->PutBits(value - 33, 11);
151  }
152  else if (value < 526368) // ITU C.27.4
153  {
154  writer->PutBits("101");
155  writer->PutBits(value - 2081, 19);
156  }
157  else // ITU C.27.5
158  {
159  writer->PutBits("1100000000");
160  writer->PutBits(value - 526369, 20);
161  }
162  }
163 
164  // ITU C.25: Encoding of integers in the range 1 to 2^20
165  // starting on the second bit of an byte
166  static inline void EncodeInteger2(vtkX3DExporterFIByteWriter* writer, unsigned int value)
167  {
168  // We want to start at position 2
169  assert(writer->CurrentBytePos == 1);
170 
171  if (value <= 64) // ITU C.25.2
172  {
173  writer->PutBits("0");
174  writer->PutBits(value - 1, 6);
175  }
176  else if (value <= 8256) // ITU C.25.3
177  {
178  writer->PutBits("10");
179  writer->PutBits(value - 65, 13);
180  }
181  else // ITU C.25.4
182  {
183  writer->PutBits("110");
184  writer->PutBits(value - 8257, 20);
185  }
186  }
187 
188  static inline void EncodeLineFeed(vtkX3DExporterFIByteWriter* writer)
189  {
190  static bool firstTime = true;
191  writer->FillByte();
192  if (firstTime)
193  {
194  writer->PutBits("1001000000001010");
195  firstTime = false;
196  }
197  else
198  {
199  //cout << "Encode NOT the first time" << endl;
200  writer->PutBits("10100000");
201  }
202  }
203 
204 private:
205 
206  static int ReverseBytes(int* x) {
207  /* break x apart, then put it back together backwards */
208  int part1 = (*x) & 0xFF;
209  int part2 = ((*x) >> 8) & 0xFF;
210  int part3 = ((*x) >> 16) & 0xFF;
211  int part4 = ((*x) >> 24) & 0xFF;
212  return (part1 << 24) | ( part2 << 16) | (part3 << 8) | part4;
213  }
214 
215 
216  friend class X3DEncoderFunctions;
217 };
218 
220 
221 
222 
223 public:
224  template<typename T>
225  static inline void EncodeIntegerDeltaZ(vtkX3DExporterFIByteWriter* writer, T* value, size_t size, vtkZLibDataCompressor* compressor, bool image = false)
226  {
227  // We want to start at position 3
228  assert(writer->CurrentBytePos == 2);
229 
230  // ITU C.19.3.4: If the alternative encoding-algorithm is present,
231  // then the two bits '11' (discriminant) are appended
232  writer->PutBits("11");
233  // ITU 10.8.1: This encoding algorithm has a vocabulary table index of 33
234  writer->PutBits(34-1, 8);
235 
236  // compute delta
237  char span = 0;
238  size_t i = 0;
239  int f; unsigned char *p;
240  std::vector<unsigned char> deltas;
241 
242  if (image)
243  {
244  span = 0;
245  for(i = 0; i < size; i++)
246  {
247  int v = 1 + (value[i]);
248  int *vp = reinterpret_cast<int*>(&v);
249  f = vtkX3DExporterFIWriterHelper::ReverseBytes(vp);
250  p = reinterpret_cast <unsigned char*> (&f);
251  deltas.push_back(p[0]);
252  deltas.push_back(p[1]);
253  deltas.push_back(p[2]);
254  deltas.push_back(p[3]);
255  }
256  compressor->SetCompressionLevel(9);
257  }
258  else
259  {
260  for (i = 0; i < 20; i++)
261  {
262  if (value[i] == -1)
263  {
264  span = static_cast<char>(i) + 1;
265  break;
266  }
267  }
268  if (!span) span = 4;
269 
270  for(i = 0; i < static_cast<size_t>(span); i++)
271  {
272  int v = 1 + value[i];
273  int *vp = reinterpret_cast<int*>(&v);
274  f = vtkX3DExporterFIWriterHelper::ReverseBytes(vp);
275 
276  p = reinterpret_cast <unsigned char*> (&f);
277  deltas.push_back(p[0]);
278  deltas.push_back(p[1]);
279  deltas.push_back(p[2]);
280  deltas.push_back(p[3]);
281  }
282  for(i = span; i < size; i++)
283  {
284  int v = 1 + (value[i] - value[i-span]);
285  f = vtkX3DExporterFIWriterHelper::ReverseBytes(&v);
286 
287  p = reinterpret_cast <unsigned char*> (&f);
288  deltas.push_back(p[0]);
289  deltas.push_back(p[1]);
290  deltas.push_back(p[2]);
291  deltas.push_back(p[3]);
292  }
293  }
294 
295  size_t bufferSize = deltas.size() + static_cast<unsigned int>(ceil(deltas.size()*0.001)) + 12;
296  unsigned char* buffer = new unsigned char[bufferSize];
297  size_t newSize = compressor->Compress(&deltas[0],static_cast<unsigned long>(deltas.size()), buffer, static_cast<unsigned long>(bufferSize));
298 
299  std::string bytes;
300  int size32 = static_cast<int>(size);
301  int size32_reversed = vtkX3DExporterFIWriterHelper::ReverseBytes(&size32);
302  char *s = reinterpret_cast <char*> (&size32_reversed);
303  bytes.append(s, 4);
304  bytes.append(&span, 1);
305 
306  for (i = 0; i < newSize; i++)
307  {
308  unsigned char c = buffer[i];
309  bytes += c;
310  }
311  delete [] buffer;
312 
314  if (image)
315  {
316  compressor->SetCompressionLevel(5);
317  }
318  }
319 
320  static inline void EncodeQuantizedzlibFloatArray(vtkX3DExporterFIByteWriter* writer, const double* value, size_t size, vtkZLibDataCompressor* compressor)
321  {
322  // We want to start at position 3
323  assert(writer->CurrentBytePos == 2);
324 
325  // ITU C.19.3.4: If the alternative encoding-algorithm is present,
326  // then the two bits '11' (discriminant) are appended
327  writer->PutBits("11");
328  // ITU 10.8.1: This encoding algorithm has a vocabulary table index of 33
329  writer->PutBits(34, 8);
330 
331  unsigned char* bytes = new unsigned char[size*4];
332  unsigned char* bytepos = bytes;
333  std::string bytesCompressed;
334  size_t i;
335 
336  const double* vd = value;
337  for (i = 0; i < size; i++)
338  {
339  union float_to_unsigned_int_to_bytes
340  {
341  float f;
342  unsigned int ui;
343  unsigned char ub[4]; // unsigned bytes
344  };
345  float_to_unsigned_int_to_bytes v;
346  v.f = (*vd) * 2.0;
347 
348  // Avoid -0
349  if (v.ui == 0x80000000)
350  {
351  v.f = 0.0f;
352  }
353  //vtkGenericWarningMacro(<< "value: " << v << " bytes: " << (int)s[0] << " " << (int)s[1] << " " << (int)s[2] << " " << (int)s[3]);
354  *bytepos++ = v.ub[3];
355  *bytepos++ = v.ub[2];
356  *bytepos++ = v.ub[1];
357  *bytepos++ = v.ub[0];
358  vd++;
359  }
360 
361 
362  // Compress the data
363  size_t bufferSize = (size * 4) + static_cast<size_t>(ceil((size * 4)*0.001)) + 12;
364  unsigned char* buffer = new unsigned char[bufferSize];
365  size_t newSize = compressor->Compress(bytes,
366  static_cast<unsigned long>(size * 4), buffer,
367  static_cast<unsigned long>(bufferSize));
368 
369  char *s;
370  // Put the number of bits for exponent
371  bytesCompressed += static_cast<char>(8);
372  // Put the number of bits for mantissa
373  bytesCompressed += static_cast<char>(23);
374  // Put the length
375  int length = static_cast<int>(size*4);
376  int length_reversed = vtkX3DExporterFIWriterHelper::ReverseBytes(&length);
377  s = reinterpret_cast <char*> (&length_reversed);
378  bytesCompressed.append(s, 4);
379 
380  // Put the number of floats
381  int numFloats = static_cast<int>(size);
382  int numFloats_reversed = vtkX3DExporterFIWriterHelper::ReverseBytes(&numFloats);;
383  s = reinterpret_cast <char*> (&numFloats_reversed);
384  bytesCompressed.append(s, 4);
385 
386  for (i = 0; i < newSize; i++)
387  {
388  unsigned char c = buffer[i];
389  bytesCompressed += c;
390  }
392  delete [] buffer;
393  delete [] bytes;
394  }
395 
396 };
397 
398 #endif
399 // VTK-HeaderTest-Exclude: vtkX3DExporterFIWriterHelper.h
static void EncodeIntegerDeltaZ(vtkX3DExporterFIByteWriter *writer, T *value, size_t size, vtkZLibDataCompressor *compressor, bool image=false)
static void EncodeNonEmptyByteString5(vtkX3DExporterFIByteWriter *writer, std::string value)
virtual void SetCompressionLevel(int)
static void EncodeInteger2(vtkX3DExporterFIByteWriter *writer, unsigned int value)
Data compression using zlib.
size_t Compress(unsigned char const *uncompressedData, size_t uncompressedSize, unsigned char *compressedData, size_t compressionSpace)
static void EncodeInteger3(vtkX3DExporterFIByteWriter *writer, unsigned int value)
static void EncodeCharacterString3(vtkX3DExporterFIByteWriter *writer, std::string value)
static void EncodeFloatFI(vtkX3DExporterFIByteWriter *writer, T *value, size_t size)
static void EncodeQuantizedzlibFloatArray(vtkX3DExporterFIByteWriter *writer, const double *value, size_t size, vtkZLibDataCompressor *compressor)
static void EncodeIntegerFI(vtkX3DExporterFIByteWriter *writer, T *value, size_t size)
static void EncodeLineFeed(vtkX3DExporterFIByteWriter *writer)