VTK
dox/IO/Export/vtkX3DExporterFIWriterHelper.h
Go to the documentation of this file.
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