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