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