VTK  9.0.20200704
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 =========================================================================*/
20 #ifndef vtkX3DExporterFIWriterHelper_h
21 #define vtkX3DExporterFIWriterHelper_h
22 
23 //#include "vtkX3DExporterFIByteWriter.h"
24 #include "vtkZLibDataCompressor.h"
25 #include <cassert>
26 
27 #define EXPONENT_MASK_32 0x7f800000
28 #define MANTISSA_MASK_32 0x007fffff
29 
30 #ifndef max
31 #define max(a, b) (((a) > (b)) ? (a) : (b))
32 #endif
34 {
35 public:
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(
100  vtkX3DExporterFIByteWriter* writer, const std::string& value)
101  {
102  // We want to start at position 3
103  assert(writer->CurrentBytePos == 2);
104 
105  // ITU C.19.3.1 If the alternative utf-8 is present, then the two bits '00'
106  // are appended to the bit stream.
107  writer->PutBits("00");
108  // ITU C.19.4: The component bytes is encoded as described in C.23.
110  }
111 
112  // ITU C.23: Encoding of the NonEmptyByteString starting
113  // on the fifth bit of an byte
114  static inline void EncodeNonEmptyByteString5(
115  vtkX3DExporterFIByteWriter* writer, const std::string& value)
116  {
117  int length = static_cast<int>(value.length());
118  if (length <= 8)
119  {
120  writer->PutBit(false);
121  writer->PutBits(length - 1, 3);
122  }
123  else if (length <= 264)
124  {
125  writer->PutBits("1000");
126  writer->PutBits(length - 9, 8);
127  }
128  else
129  {
130  writer->PutBits("1100");
131  writer->PutBits(length - 265, 32);
132  }
133  writer->PutBytes(value.c_str(), length);
134  }
135 
136  // ITU C.27: Encoding of integers in the range 1 to 2^20
137  // starting on the third bit of an byte
138  static inline void EncodeInteger3(vtkX3DExporterFIByteWriter* writer, unsigned int value)
139  {
140  // We want to start at position 3
141  assert(writer->CurrentBytePos == 2);
142 
143  if (value <= 32) // ITU C.27.2
144  {
145  writer->PutBit(false);
146  writer->PutBits(value - 1, 5);
147  }
148  else if (value <= 2080) // ITU C.27.3
149  {
150  writer->PutBits("100");
151  writer->PutBits(value - 33, 11);
152  }
153  else if (value < 526368) // ITU C.27.4
154  {
155  writer->PutBits("101");
156  writer->PutBits(value - 2081, 19);
157  }
158  else // ITU C.27.5
159  {
160  writer->PutBits("1100000000");
161  writer->PutBits(value - 526369, 20);
162  }
163  }
164 
165  // ITU C.25: Encoding of integers in the range 1 to 2^20
166  // starting on the second bit of an byte
167  static inline void EncodeInteger2(vtkX3DExporterFIByteWriter* writer, unsigned int value)
168  {
169  // We want to start at position 2
170  assert(writer->CurrentBytePos == 1);
171 
172  if (value <= 64) // ITU C.25.2
173  {
174  writer->PutBits("0");
175  writer->PutBits(value - 1, 6);
176  }
177  else if (value <= 8256) // ITU C.25.3
178  {
179  writer->PutBits("10");
180  writer->PutBits(value - 65, 13);
181  }
182  else // ITU C.25.4
183  {
184  writer->PutBits("110");
185  writer->PutBits(value - 8257, 20);
186  }
187  }
188 
189  static inline void EncodeLineFeed(vtkX3DExporterFIByteWriter* writer)
190  {
191  static bool firstTime = true;
192  writer->FillByte();
193  if (firstTime)
194  {
195  writer->PutBits("1001000000001010");
196  firstTime = false;
197  }
198  else
199  {
200  // cout << "Encode NOT the first time" << endl;
201  writer->PutBits("10100000");
202  }
203  }
204 
205 private:
206  static int ReverseBytes(int* x)
207  {
208  /* break x apart, then put it back together backwards */
209  int part1 = (*x) & 0xFF;
210  int part2 = ((*x) >> 8) & 0xFF;
211  int part3 = ((*x) >> 16) & 0xFF;
212  int part4 = ((*x) >> 24) & 0xFF;
213  return (part1 << 24) | (part2 << 16) | (part3 << 8) | part4;
214  }
215 
216  friend class X3DEncoderFunctions;
217 };
218 
220 {
221 
222 public:
223  template <typename T>
224  static inline void EncodeIntegerDeltaZ(vtkX3DExporterFIByteWriter* writer, T* value, size_t size,
225  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;
240  unsigned char* p;
241  std::vector<unsigned char> deltas;
242 
243  if (image)
244  {
245  span = 0;
246  for (i = 0; i < size; i++)
247  {
248  int v = 1 + (value[i]);
249  int* vp = reinterpret_cast<int*>(&v);
250  f = vtkX3DExporterFIWriterHelper::ReverseBytes(vp);
251  p = reinterpret_cast<unsigned char*>(&f);
252  deltas.push_back(p[0]);
253  deltas.push_back(p[1]);
254  deltas.push_back(p[2]);
255  deltas.push_back(p[3]);
256  }
257  compressor->SetCompressionLevel(9);
258  }
259  else
260  {
261  for (i = 0; i < 20; i++)
262  {
263  if (value[i] == -1)
264  {
265  span = static_cast<char>(i) + 1;
266  break;
267  }
268  }
269  if (!span)
270  span = 4;
271 
272  for (i = 0; i < static_cast<size_t>(span); i++)
273  {
274  int v = 1 + value[i];
275  int* vp = reinterpret_cast<int*>(&v);
276  f = vtkX3DExporterFIWriterHelper::ReverseBytes(vp);
277 
278  p = reinterpret_cast<unsigned char*>(&f);
279  deltas.push_back(p[0]);
280  deltas.push_back(p[1]);
281  deltas.push_back(p[2]);
282  deltas.push_back(p[3]);
283  }
284  for (i = span; i < size; i++)
285  {
286  int v = 1 + (value[i] - value[i - span]);
287  f = vtkX3DExporterFIWriterHelper::ReverseBytes(&v);
288 
289  p = reinterpret_cast<unsigned char*>(&f);
290  deltas.push_back(p[0]);
291  deltas.push_back(p[1]);
292  deltas.push_back(p[2]);
293  deltas.push_back(p[3]);
294  }
295  }
296 
297  size_t bufferSize = deltas.size() + static_cast<unsigned int>(ceil(deltas.size() * 0.001)) + 12;
298  unsigned char* buffer = new unsigned char[bufferSize];
299  size_t newSize = compressor->Compress(&deltas[0], static_cast<unsigned long>(deltas.size()),
300  buffer, static_cast<unsigned long>(bufferSize));
301 
302  std::string bytes;
303  int size32 = static_cast<int>(size);
304  int size32_reversed = vtkX3DExporterFIWriterHelper::ReverseBytes(&size32);
305  char* s = reinterpret_cast<char*>(&size32_reversed);
306  bytes.append(s, 4);
307  bytes.append(&span, 1);
308 
309  for (i = 0; i < newSize; i++)
310  {
311  unsigned char c = buffer[i];
312  bytes += c;
313  }
314  delete[] buffer;
315 
317  if (image)
318  {
319  compressor->SetCompressionLevel(5);
320  }
321  }
322 
323  static inline void EncodeQuantizedzlibFloatArray(vtkX3DExporterFIByteWriter* writer,
324  const double* value, size_t size, vtkZLibDataCompressor* compressor)
325  {
326  // We want to start at position 3
327  assert(writer->CurrentBytePos == 2);
328 
329  // ITU C.19.3.4: If the alternative encoding-algorithm is present,
330  // then the two bits '11' (discriminant) are appended
331  writer->PutBits("11");
332  // ITU 10.8.1: This encoding algorithm has a vocabulary table index of 33
333  writer->PutBits(34, 8);
334 
335  unsigned char* bytes = new unsigned char[size * 4];
336  unsigned char* bytepos = bytes;
337  std::string bytesCompressed;
338  size_t i;
339 
340  const double* vd = value;
341  for (i = 0; i < size; i++)
342  {
343  union float_to_unsigned_int_to_bytes {
344  float f;
345  unsigned int ui;
346  unsigned char ub[4]; // unsigned bytes
347  };
348  float_to_unsigned_int_to_bytes v;
349  v.f = (*vd) * 2.0;
350 
351  // Avoid -0
352  if (v.ui == 0x80000000)
353  {
354  v.f = 0.0f;
355  }
356  // vtkGenericWarningMacro(<< "value: " << v << " bytes: " << (int)s[0] << " " << (int)s[1] <<
357  // " " << (int)s[2] << " " << (int)s[3]);
358  *bytepos++ = v.ub[3];
359  *bytepos++ = v.ub[2];
360  *bytepos++ = v.ub[1];
361  *bytepos++ = v.ub[0];
362  vd++;
363  }
364 
365  // Compress the data
366  size_t bufferSize = (size * 4) + static_cast<size_t>(ceil((size * 4) * 0.001)) + 12;
367  unsigned char* buffer = new unsigned char[bufferSize];
368  size_t newSize = compressor->Compress(
369  bytes, static_cast<unsigned long>(size * 4), buffer, static_cast<unsigned long>(bufferSize));
370 
371  char* s;
372  // Put the number of bits for exponent
373  bytesCompressed += static_cast<char>(8);
374  // Put the number of bits for mantissa
375  bytesCompressed += static_cast<char>(23);
376  // Put the length
377  int length = static_cast<int>(size * 4);
378  int length_reversed = vtkX3DExporterFIWriterHelper::ReverseBytes(&length);
379  s = reinterpret_cast<char*>(&length_reversed);
380  bytesCompressed.append(s, 4);
381 
382  // Put the number of floats
383  int numFloats = static_cast<int>(size);
384  int numFloats_reversed = vtkX3DExporterFIWriterHelper::ReverseBytes(&numFloats);
385  s = reinterpret_cast<char*>(&numFloats_reversed);
386  bytesCompressed.append(s, 4);
387 
388  for (i = 0; i < newSize; i++)
389  {
390  unsigned char c = buffer[i];
391  bytesCompressed += c;
392  }
394  delete[] buffer;
395  delete[] bytes;
396  }
397 };
398 
399 #endif
400 // VTK-HeaderTest-Exclude: vtkX3DExporterFIWriterHelper.h
X3DEncoderFunctions
Definition: vtkX3DExporterFIWriterHelper.h:219
vtkX3DExporterFIWriterHelper::EncodeInteger3
static void EncodeInteger3(vtkX3DExporterFIByteWriter *writer, unsigned int value)
Definition: vtkX3DExporterFIWriterHelper.h:138
vtkX3DExporterFIWriterHelper::EncodeIntegerFI
static void EncodeIntegerFI(vtkX3DExporterFIByteWriter *writer, T *value, size_t size)
Definition: vtkX3DExporterFIWriterHelper.h:78
vtkX3D::value
Definition: vtkX3D.h:226
vtkX3DExporterFIWriterHelper::EncodeInteger2
static void EncodeInteger2(vtkX3DExporterFIByteWriter *writer, unsigned int value)
Definition: vtkX3DExporterFIWriterHelper.h:167
vtkX3D::image
Definition: vtkX3D.h:380
vtkX3DExporterFIWriterHelper::EncodeCharacterString3
static void EncodeCharacterString3(vtkX3DExporterFIByteWriter *writer, const std::string &value)
Definition: vtkX3DExporterFIWriterHelper.h:99
vtkX3D::length
Definition: vtkX3D.h:399
vtkX3DExporterFIWriterHelper::EncodeFloatFI
static void EncodeFloatFI(vtkX3DExporterFIByteWriter *writer, T *value, size_t size)
Definition: vtkX3DExporterFIWriterHelper.h:43
vtkX3DExporterFIWriterHelper::float_to_unsigned_int_to_bytes::ub
unsigned char ub[4]
Definition: vtkX3DExporterFIWriterHelper.h:39
vtkX3DExporterFIWriterHelper
Definition: vtkX3DExporterFIWriterHelper.h:33
vtkX3DExporterFIWriterHelper::float_to_unsigned_int_to_bytes::f
float f
Definition: vtkX3DExporterFIWriterHelper.h:37
vtkZLibDataCompressor::SetCompressionLevel
void SetCompressionLevel(int compressionLevel) override
Compression performance varies greatly with compression level Require level setting from any vtkDataC...
vtkX3DExporterFIWriterHelper::float_to_unsigned_int_to_bytes::ui
unsigned int ui
Definition: vtkX3DExporterFIWriterHelper.h:38
X3DEncoderFunctions::EncodeIntegerDeltaZ
static void EncodeIntegerDeltaZ(vtkX3DExporterFIByteWriter *writer, T *value, size_t size, vtkZLibDataCompressor *compressor, bool image=false)
Definition: vtkX3DExporterFIWriterHelper.h:224
vtkX3DExporterFIWriterHelper::EncodeLineFeed
static void EncodeLineFeed(vtkX3DExporterFIByteWriter *writer)
Definition: vtkX3DExporterFIWriterHelper.h:189
vtkX3DExporterFIWriterHelper::float_to_unsigned_int_to_bytes
Definition: vtkX3DExporterFIWriterHelper.h:36
vtkX3D::size
Definition: vtkX3D.h:259
vtkZLibDataCompressor
Data compression using zlib.
Definition: vtkZLibDataCompressor.h:29
vtkDataCompressor::Compress
size_t Compress(unsigned char const *uncompressedData, size_t uncompressedSize, unsigned char *compressedData, size_t compressionSpace)
Compress the given input data buffer into the given output buffer.
vtkX3D::string
Definition: vtkX3D.h:496
vtkX3DExporterFIWriterHelper::EncodeNonEmptyByteString5
static void EncodeNonEmptyByteString5(vtkX3DExporterFIByteWriter *writer, const std::string &value)
Definition: vtkX3DExporterFIWriterHelper.h:114
vtkZLibDataCompressor.h
X3DEncoderFunctions::EncodeQuantizedzlibFloatArray
static void EncodeQuantizedzlibFloatArray(vtkX3DExporterFIByteWriter *writer, const double *value, size_t size, vtkZLibDataCompressor *compressor)
Definition: vtkX3DExporterFIWriterHelper.h:323