VTK
|
00001 /*========================================================================= 00002 00003 Program: Visualization Toolkit 00004 Module: vtkX3DExporterFIWriterHelper.h 00005 00006 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 00007 All rights reserved. 00008 See Copyright.txt or http://www.kitware.com/Copyright.htm for details. 00009 00010 This software is distributed WITHOUT ANY WARRANTY; without even 00011 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 00012 PURPOSE. See the above copyright notice for more information. 00013 00014 =========================================================================*/ 00019 #ifndef __vtkX3DExporterFIWriterHelper_h 00020 #define __vtkX3DExporterFIWriterHelper_h 00021 00022 //#include "vtkX3DExporterFIByteWriter.h" 00023 #include "vtkZLibDataCompressor.h" 00024 #include <cassert> 00025 00026 #define EXPONENT_MASK_32 0x7f800000 00027 #define MANTISSA_MASK_32 0x007fffff 00028 00029 #ifndef max 00030 #define max(a,b) (((a) > (b)) ? (a) : (b)) 00031 #endif 00032 class vtkX3DExporterFIWriterHelper 00033 { 00034 public: 00035 union float_to_unsigned_int_to_bytes 00036 { 00037 float f; 00038 unsigned int ui; 00039 unsigned char ub[4]; // unsigned bytes 00040 }; 00041 00042 template<typename T> 00043 static inline void EncodeFloatFI(vtkX3DExporterFIByteWriter* writer, T* value, size_t size) 00044 { 00045 // We want to start at position 3 00046 assert(writer->CurrentBytePos == 2); 00047 00048 // ITU C.19.3.4: If the alternative encoding-algorithm is present, 00049 // then the two bits '11' (discriminant) are appended 00050 writer->PutBits("11"); 00051 // ITU 10.8.1: This encoding algorithm has a vocabulary table index of 7, 00052 writer->PutBits(7-1, 8); 00053 00054 std::string bytes; 00055 char byte[4]; 00056 for (size_t i = 0; i < size; i++) 00057 { 00058 float_to_unsigned_int_to_bytes v; 00059 v.f = value[i]; 00060 00061 // Avoid -0 00062 if (v.ui == 0x80000000) 00063 { 00064 v.f = 0; 00065 } 00066 00067 byte[0] = v.ub[3]; 00068 byte[1] = v.ub[2]; 00069 byte[2] = v.ub[1]; 00070 byte[3] = v.ub[0]; 00071 00072 bytes.append(byte, 4); 00073 } 00074 EncodeNonEmptyByteString5(writer, bytes); 00075 } 00076 00077 template<typename T> 00078 static inline void EncodeIntegerFI(vtkX3DExporterFIByteWriter* writer, T* value, size_t size) 00079 { 00080 // We want to start at position 3 00081 assert(writer->CurrentBytePos == 2); 00082 00083 // ITU C.19.3.4: If the alternative encoding-algorithm is present, 00084 // then the two bits '11' (discriminant) are appended 00085 writer->PutBits("11"); 00086 // ITU 10.8.1: This encoding algorithm has a vocabulary table index of 4, 00087 writer->PutBits(4-1, 8); 00088 std::string bytes; 00089 for(size_t i = 0; i < size; i++) 00090 { 00091 int v = value[i]; 00092 int f = ReverseBytes(&v); 00093 char *p = reinterpret_cast <char*> (&f); 00094 bytes.append(p, 4); 00095 } 00096 EncodeNonEmptyByteString5(writer, bytes); 00097 } 00098 00099 static inline void EncodeCharacterString3(vtkX3DExporterFIByteWriter* writer, std::string value) 00100 { 00101 // We want to start at position 3 00102 assert(writer->CurrentBytePos == 2); 00103 00104 // ITU C.19.3.1 If the alternative utf-8 is present, then the two bits '00' 00105 // are appended to the bit stream. 00106 writer->PutBits("00"); 00107 // ITU C.19.4: The component bytes is encoded as described in C.23. 00108 EncodeNonEmptyByteString5(writer, value); 00109 } 00110 00111 // ITU C.23: Encoding of the NonEmptyByteString starting 00112 // on the fifth bit of an byte 00113 static inline void EncodeNonEmptyByteString5(vtkX3DExporterFIByteWriter* writer, std::string value) 00114 { 00115 int length = static_cast<int>(value.length()); 00116 if (length <= 8) 00117 { 00118 writer->PutBit(0); 00119 writer->PutBits(length - 1, 3); 00120 } 00121 else if (length <= 264) 00122 { 00123 writer->PutBits("1000"); 00124 writer->PutBits(length - 9, 8); 00125 } 00126 else 00127 { 00128 writer->PutBits("1100"); 00129 writer->PutBits(length - 265, 32); 00130 } 00131 writer->PutBytes(value.c_str(), length); 00132 } 00133 00134 00135 // ITU C.27: Encoding of integers in the range 1 to 2^20 00136 // starting on the third bit of an byte 00137 static inline void EncodeInteger3(vtkX3DExporterFIByteWriter* writer, unsigned int value) 00138 { 00139 // We want to start at position 3 00140 assert(writer->CurrentBytePos == 2); 00141 00142 if (value <= 32) // ITU C.27.2 00143 { 00144 writer->PutBit(0); 00145 writer->PutBits(value - 1, 5); 00146 } 00147 else if (value <= 2080) // ITU C.27.3 00148 { 00149 writer->PutBits("100"); 00150 writer->PutBits(value - 33, 11); 00151 } 00152 else if (value < 526368) // ITU C.27.4 00153 { 00154 writer->PutBits("101"); 00155 writer->PutBits(value - 2081, 19); 00156 } 00157 else // ITU C.27.5 00158 { 00159 writer->PutBits("1100000000"); 00160 writer->PutBits(value - 526369, 20); 00161 } 00162 } 00163 00164 // ITU C.25: Encoding of integers in the range 1 to 2^20 00165 // starting on the second bit of an byte 00166 static inline void EncodeInteger2(vtkX3DExporterFIByteWriter* writer, unsigned int value) 00167 { 00168 // We want to start at position 2 00169 assert(writer->CurrentBytePos == 1); 00170 00171 if (value <= 64) // ITU C.25.2 00172 { 00173 writer->PutBits("0"); 00174 writer->PutBits(value - 1, 6); 00175 } 00176 else if (value <= 8256) // ITU C.25.3 00177 { 00178 writer->PutBits("10"); 00179 writer->PutBits(value - 65, 13); 00180 } 00181 else // ITU C.25.4 00182 { 00183 writer->PutBits("110"); 00184 writer->PutBits(value - 8257, 20); 00185 } 00186 } 00187 00188 static inline void EncodeLineFeed(vtkX3DExporterFIByteWriter* writer) 00189 { 00190 static bool firstTime = true; 00191 writer->FillByte(); 00192 if (firstTime) 00193 { 00194 writer->PutBits("1001000000001010"); 00195 firstTime = false; 00196 } 00197 else 00198 { 00199 //cout << "Encode NOT the first time" << endl; 00200 writer->PutBits("10100000"); 00201 } 00202 } 00203 00204 private: 00205 00206 static int ReverseBytes(int* x) { 00207 /* break x apart, then put it back together backwards */ 00208 int part1 = (*x) & 0xFF; 00209 int part2 = ((*x) >> 8) & 0xFF; 00210 int part3 = ((*x) >> 16) & 0xFF; 00211 int part4 = ((*x) >> 24) & 0xFF; 00212 return (part1 << 24) | ( part2 << 16) | (part3 << 8) | part4; 00213 } 00214 00215 00216 friend class X3DEncoderFunctions; 00217 }; 00218 00219 class X3DEncoderFunctions { 00220 00221 00222 00223 public: 00224 template<typename T> 00225 static inline void EncodeIntegerDeltaZ(vtkX3DExporterFIByteWriter* writer, T* value, size_t size, vtkZLibDataCompressor* compressor, bool image = false) 00226 { 00227 // We want to start at position 3 00228 assert(writer->CurrentBytePos == 2); 00229 00230 // ITU C.19.3.4: If the alternative encoding-algorithm is present, 00231 // then the two bits '11' (discriminant) are appended 00232 writer->PutBits("11"); 00233 // ITU 10.8.1: This encoding algorithm has a vocabulary table index of 33 00234 writer->PutBits(34-1, 8); 00235 00236 // compute delta 00237 char span = 0; 00238 size_t i = 0; 00239 int f; unsigned char *p; 00240 std::vector<unsigned char> deltas; 00241 00242 if (image) 00243 { 00244 span = 0; 00245 for(i = 0; i < size; i++) 00246 { 00247 int v = 1 + (value[i]); 00248 int *vp = reinterpret_cast<int*>(&v); 00249 f = vtkX3DExporterFIWriterHelper::ReverseBytes(vp); 00250 p = reinterpret_cast <unsigned char*> (&f); 00251 deltas.push_back(p[0]); 00252 deltas.push_back(p[1]); 00253 deltas.push_back(p[2]); 00254 deltas.push_back(p[3]); 00255 } 00256 compressor->SetCompressionLevel(9); 00257 } 00258 else 00259 { 00260 for (i = 0; i < 20; i++) 00261 { 00262 if (value[i] == -1) 00263 { 00264 span = static_cast<char>(i) + 1; 00265 break; 00266 } 00267 } 00268 if (!span) span = 4; 00269 00270 for(i = 0; i < static_cast<size_t>(span); i++) 00271 { 00272 int v = 1 + value[i]; 00273 int *vp = reinterpret_cast<int*>(&v); 00274 f = vtkX3DExporterFIWriterHelper::ReverseBytes(vp); 00275 00276 p = reinterpret_cast <unsigned char*> (&f); 00277 deltas.push_back(p[0]); 00278 deltas.push_back(p[1]); 00279 deltas.push_back(p[2]); 00280 deltas.push_back(p[3]); 00281 } 00282 for(i = span; i < size; i++) 00283 { 00284 int v = 1 + (value[i] - value[i-span]); 00285 f = vtkX3DExporterFIWriterHelper::ReverseBytes(&v); 00286 00287 p = reinterpret_cast <unsigned char*> (&f); 00288 deltas.push_back(p[0]); 00289 deltas.push_back(p[1]); 00290 deltas.push_back(p[2]); 00291 deltas.push_back(p[3]); 00292 } 00293 } 00294 00295 size_t bufferSize = deltas.size() + static_cast<unsigned int>(ceil(deltas.size()*0.001)) + 12; 00296 unsigned char* buffer = new unsigned char[bufferSize]; 00297 size_t newSize = compressor->Compress(&deltas[0],static_cast<unsigned long>(deltas.size()), buffer, static_cast<unsigned long>(bufferSize)); 00298 00299 std::string bytes; 00300 int size32 = static_cast<int>(size); 00301 int size32_reversed = vtkX3DExporterFIWriterHelper::ReverseBytes(&size32); 00302 char *s = reinterpret_cast <char*> (&size32_reversed); 00303 bytes.append(s, 4); 00304 bytes.append(&span, 1); 00305 00306 for (i = 0; i < newSize; i++) 00307 { 00308 unsigned char c = buffer[i]; 00309 bytes += c; 00310 } 00311 delete [] buffer; 00312 00313 vtkX3DExporterFIWriterHelper::EncodeNonEmptyByteString5(writer, bytes); 00314 if (image) 00315 { 00316 compressor->SetCompressionLevel(5); 00317 } 00318 } 00319 00320 static inline void EncodeQuantizedzlibFloatArray(vtkX3DExporterFIByteWriter* writer, const double* value, size_t size, vtkZLibDataCompressor* compressor) 00321 { 00322 // We want to start at position 3 00323 assert(writer->CurrentBytePos == 2); 00324 00325 // ITU C.19.3.4: If the alternative encoding-algorithm is present, 00326 // then the two bits '11' (discriminant) are appended 00327 writer->PutBits("11"); 00328 // ITU 10.8.1: This encoding algorithm has a vocabulary table index of 33 00329 writer->PutBits(34, 8); 00330 00331 unsigned char* bytes = new unsigned char[size*4]; 00332 unsigned char* bytepos = bytes; 00333 std::string bytesCompressed; 00334 size_t i; 00335 00336 const double* vd = value; 00337 for (i = 0; i < size; i++) 00338 { 00339 union float_to_unsigned_int_to_bytes 00340 { 00341 float f; 00342 unsigned int ui; 00343 unsigned char ub[4]; // unsigned bytes 00344 }; 00345 float_to_unsigned_int_to_bytes v; 00346 v.f = (*vd) * 2.0; 00347 00348 // Avoid -0 00349 if (v.ui == 0x80000000) 00350 { 00351 v.f = 0.0f; 00352 } 00353 //vtkGenericWarningMacro(<< "value: " << v << " bytes: " << (int)s[0] << " " << (int)s[1] << " " << (int)s[2] << " " << (int)s[3]); 00354 *bytepos++ = v.ub[3]; 00355 *bytepos++ = v.ub[2]; 00356 *bytepos++ = v.ub[1]; 00357 *bytepos++ = v.ub[0]; 00358 vd++; 00359 } 00360 00361 00362 // Compress the data 00363 size_t bufferSize = (size * 4) + static_cast<size_t>(ceil((size * 4)*0.001)) + 12; 00364 unsigned char* buffer = new unsigned char[bufferSize]; 00365 size_t newSize = compressor->Compress(bytes, 00366 static_cast<unsigned long>(size * 4), buffer, 00367 static_cast<unsigned long>(bufferSize)); 00368 00369 char *s; 00370 // Put the number of bits for exponent 00371 bytesCompressed += static_cast<char>(8); 00372 // Put the number of bits for mantissa 00373 bytesCompressed += static_cast<char>(23); 00374 // Put the length 00375 int length = static_cast<int>(size*4); 00376 int length_reversed = vtkX3DExporterFIWriterHelper::ReverseBytes(&length); 00377 s = reinterpret_cast <char*> (&length_reversed); 00378 bytesCompressed.append(s, 4); 00379 00380 // Put the number of floats 00381 int numFloats = static_cast<int>(size); 00382 int numFloats_reversed = vtkX3DExporterFIWriterHelper::ReverseBytes(&numFloats);; 00383 s = reinterpret_cast <char*> (&numFloats_reversed); 00384 bytesCompressed.append(s, 4); 00385 00386 for (i = 0; i < newSize; i++) 00387 { 00388 unsigned char c = buffer[i]; 00389 bytesCompressed += c; 00390 } 00391 vtkX3DExporterFIWriterHelper::EncodeNonEmptyByteString5(writer, bytesCompressed); 00392 delete [] buffer; 00393 delete [] bytes; 00394 } 00395 00396 }; 00397 00398 #endif 00399 // VTK-HeaderTest-Exclude: vtkX3DExporterFIWriterHelper.h