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=========================================================================*/
20#ifndef vtkX3DExporterFIWriterHelper_h
21#define vtkX3DExporterFIWriterHelper_h
22
23//#include "vtkX3DExporterFIByteWriter.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{
35public:
37 {
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(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(vtkX3DExporterFIByteWriter* writer, const std::string& value)
115 {
116 int length = static_cast<int>(value.length());
117 if (length <= 8)
118 {
119 writer->PutBit(0);
120 writer->PutBits(length - 1, 3);
121 }
122 else if (length <= 264)
123 {
124 writer->PutBits("1000");
125 writer->PutBits(length - 9, 8);
126 }
127 else
128 {
129 writer->PutBits("1100");
130 writer->PutBits(length - 265, 32);
131 }
132 writer->PutBytes(value.c_str(), length);
133 }
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(0);
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
205private:
206
207 static int ReverseBytes(int* x) {
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
218};
219
221
222
223
224public:
225 template<typename T>
226 static inline void EncodeIntegerDeltaZ(vtkX3DExporterFIByteWriter* writer, T* value, size_t size, 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; 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) span = 4;
270
271 for(i = 0; i < static_cast<size_t>(span); i++)
272 {
273 int v = 1 + value[i];
274 int *vp = reinterpret_cast<int*>(&v);
275 f = vtkX3DExporterFIWriterHelper::ReverseBytes(vp);
276
277 p = reinterpret_cast <unsigned char*> (&f);
278 deltas.push_back(p[0]);
279 deltas.push_back(p[1]);
280 deltas.push_back(p[2]);
281 deltas.push_back(p[3]);
282 }
283 for(i = span; i < size; i++)
284 {
285 int v = 1 + (value[i] - value[i-span]);
286 f = vtkX3DExporterFIWriterHelper::ReverseBytes(&v);
287
288 p = reinterpret_cast <unsigned char*> (&f);
289 deltas.push_back(p[0]);
290 deltas.push_back(p[1]);
291 deltas.push_back(p[2]);
292 deltas.push_back(p[3]);
293 }
294 }
295
296 size_t bufferSize = deltas.size() + static_cast<unsigned int>(ceil(deltas.size()*0.001)) + 12;
297 unsigned char* buffer = new unsigned char[bufferSize];
298 size_t newSize = compressor->Compress(&deltas[0],static_cast<unsigned long>(deltas.size()), buffer, static_cast<unsigned long>(bufferSize));
299
300 std::string bytes;
301 int size32 = static_cast<int>(size);
302 int size32_reversed = vtkX3DExporterFIWriterHelper::ReverseBytes(&size32);
303 char *s = reinterpret_cast <char*> (&size32_reversed);
304 bytes.append(s, 4);
305 bytes.append(&span, 1);
306
307 for (i = 0; i < newSize; i++)
308 {
309 unsigned char c = buffer[i];
310 bytes += c;
311 }
312 delete [] buffer;
313
315 if (image)
316 {
317 compressor->SetCompressionLevel(5);
318 }
319 }
320
321 static inline void EncodeQuantizedzlibFloatArray(vtkX3DExporterFIByteWriter* writer, const double* value, size_t size, vtkZLibDataCompressor* compressor)
322 {
323 // We want to start at position 3
324 assert(writer->CurrentBytePos == 2);
325
326 // ITU C.19.3.4: If the alternative encoding-algorithm is present,
327 // then the two bits '11' (discriminant) are appended
328 writer->PutBits("11");
329 // ITU 10.8.1: This encoding algorithm has a vocabulary table index of 33
330 writer->PutBits(34, 8);
331
332 unsigned char* bytes = new unsigned char[size*4];
333 unsigned char* bytepos = bytes;
334 std::string bytesCompressed;
335 size_t i;
336
337 const double* vd = value;
338 for (i = 0; i < size; i++)
339 {
340 union float_to_unsigned_int_to_bytes
341 {
342 float f;
343 unsigned int ui;
344 unsigned char ub[4]; // unsigned bytes
345 };
346 float_to_unsigned_int_to_bytes v;
347 v.f = (*vd) * 2.0;
348
349 // Avoid -0
350 if (v.ui == 0x80000000)
351 {
352 v.f = 0.0f;
353 }
354 //vtkGenericWarningMacro(<< "value: " << v << " bytes: " << (int)s[0] << " " << (int)s[1] << " " << (int)s[2] << " " << (int)s[3]);
355 *bytepos++ = v.ub[3];
356 *bytepos++ = v.ub[2];
357 *bytepos++ = v.ub[1];
358 *bytepos++ = v.ub[0];
359 vd++;
360 }
361
362
363 // Compress the data
364 size_t bufferSize = (size * 4) + static_cast<size_t>(ceil((size * 4)*0.001)) + 12;
365 unsigned char* buffer = new unsigned char[bufferSize];
366 size_t newSize = compressor->Compress(bytes,
367 static_cast<unsigned long>(size * 4), buffer,
368 static_cast<unsigned long>(bufferSize));
369
370 char *s;
371 // Put the number of bits for exponent
372 bytesCompressed += static_cast<char>(8);
373 // Put the number of bits for mantissa
374 bytesCompressed += static_cast<char>(23);
375 // Put the length
376 int length = static_cast<int>(size*4);
377 int length_reversed = vtkX3DExporterFIWriterHelper::ReverseBytes(&length);
378 s = reinterpret_cast <char*> (&length_reversed);
379 bytesCompressed.append(s, 4);
380
381 // Put the number of floats
382 int numFloats = static_cast<int>(size);
383 int numFloats_reversed = vtkX3DExporterFIWriterHelper::ReverseBytes(&numFloats);;
384 s = reinterpret_cast <char*> (&numFloats_reversed);
385 bytesCompressed.append(s, 4);
386
387 for (i = 0; i < newSize; i++)
388 {
389 unsigned char c = buffer[i];
390 bytesCompressed += c;
391 }
393 delete [] buffer;
394 delete [] bytes;
395 }
396
397};
398
399#endif
400// 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.
virtual void SetCompressionLevel(int)
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