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