compressorRLE4BU.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "compressorRLE4BU.h"
00020
00021 namespace
00022 {
00023
00024 static const uint64_t _rleMarker = 0xE3A49A3D0254B9C1ull;
00025 }
00026
00027 #include "compressorRLE.ipp"
00028
00029 namespace eq
00030 {
00031 namespace plugin
00032 {
00033
00034 #define WRITE_SINGLE_OUTPUT \
00035 { \
00036 if( lastSymbol == _rleMarker ) \
00037 { \
00038 out[ outPos++ ] = _rleMarker; \
00039 out[ outPos++ ] = lastSymbol; \
00040 out[ outPos++ ] = nSame; \
00041 } \
00042 else \
00043 switch( nSame ) \
00044 { \
00045 case 0: \
00046 EQASSERTINFO( false, "Unreachable code"); \
00047 break; \
00048 case 3: \
00049 out[ outPos++ ] = lastSymbol; \
00050 case 2: \
00051 out[ outPos++ ] = lastSymbol; \
00052 case 1: \
00053 out[ outPos++ ] = lastSymbol; \
00054 break; \
00055 default: \
00056 out[ outPos++ ] = _rleMarker; \
00057 out[ outPos++ ] = lastSymbol; \
00058 out[ outPos++ ] = nSame; \
00059 break; \
00060 } \
00061 EQASSERTINFO( nWords<<1 >= outPos, \
00062 "Overwrite array bounds during image compress" ); \
00063 }
00064
00065
00066 static uint64_t _compress( const uint64_t* data, const uint64_t nWords,
00067 uint64_t* out )
00068 {
00069 out[ 0 ] = nWords;
00070
00071 uint64_t outPos = 1;
00072 uint64_t nSame = 1;
00073 uint64_t lastSymbol = data[0];
00074
00075 for( uint64_t i=1; i<nWords; ++i )
00076 {
00077 const uint64_t symbol = data[i];
00078
00079 if( symbol == lastSymbol )
00080 ++nSame;
00081 else
00082 {
00083 WRITE_SINGLE_OUTPUT;
00084 lastSymbol = symbol;
00085 nSame = 1;
00086 }
00087 }
00088
00089 WRITE_SINGLE_OUTPUT;
00090 return (outPos<<3);
00091 }
00092
00093 void CompressorRLE4BU::compress( const void* const inData,
00094 const eq_uint64_t nPixels,
00095 const bool useAlpha )
00096 {
00097 const uint64_t size = nPixels * sizeof( uint32_t );
00098 EQASSERT( size > 0 );
00099
00100 _setupResults( 1, size, _results );
00101
00102 const uint64_t nElems = (size%8) ? (size>>3)+1 : (size>>3);
00103 const ssize_t nResults = _results.size();
00104
00105
00106 const float width = static_cast< float >( nElems ) /
00107 static_cast< float >( nResults );
00108
00109 const uint64_t* const data =
00110 reinterpret_cast< const uint64_t* >( inData );
00111
00112 #ifdef EQ_USE_OPENMP
00113 #pragma omp parallel for
00114 #endif
00115 for( ssize_t i = 0; i < nResults; ++i )
00116 {
00117 const uint64_t startIndex = static_cast< uint64_t >( i * width );
00118 const uint64_t endIndex = static_cast< uint64_t >( (i+1) * width );
00119 uint64_t* out = reinterpret_cast< uint64_t* >(
00120 _results[i]->getData( ));
00121
00122 const uint64_t cSize = _compress( &data[ startIndex ],
00123 endIndex-startIndex, out );
00124 _results[i]->setSize( cSize );
00125 }
00126 }
00127
00128
00129 void CompressorRLE4BU::decompress( const void* const* inData,
00130 const eq_uint64_t* const inSizes,
00131 const unsigned nInputs, void* const outData,
00132 const eq_uint64_t nPixels,
00133 const bool useAlpha )
00134 {
00135
00136 if( nPixels == 0 )
00137 return;
00138
00139
00140
00141 uint64_t** outTable = static_cast< uint64_t** >(
00142 alloca( nInputs * sizeof( uint64_t* )));
00143
00144 {
00145 uint8_t* out = reinterpret_cast< uint8_t* >( outData );
00146 for( unsigned i = 0; i < nInputs; ++i )
00147 {
00148 outTable[i] = reinterpret_cast< uint64_t* >( out );
00149
00150 const uint64_t* in =
00151 reinterpret_cast< const uint64_t* >( inData[i] );
00152 const uint64_t nWords = in[0];
00153 out += nWords * sizeof( uint64_t );
00154 }
00155
00156 EQASSERTINFO(
00157 nPixels*4 >= (uint64_t)(out-reinterpret_cast<uint8_t*>(outData)-7),
00158 "Pixel data size does not match expected image size: "
00159 << nPixels*4 << " ? "
00160 << (uint64_t)(out-reinterpret_cast<uint8_t*>(outData)-7));
00161 }
00162
00163
00164
00165 #ifdef EQ_USE_OPENMP
00166 #pragma omp parallel for
00167 #endif
00168 for( ssize_t i = 0; i < static_cast< ssize_t >( nInputs ); ++i )
00169 {
00170 const uint64_t* in = reinterpret_cast< const uint64_t* >( inData[i] );
00171 uint64_t* out = outTable[i];
00172
00173 uint64_t outPos = 0;
00174 const uint64_t endPos = in[0];
00175 uint64_t inPos = 1;
00176
00177 while( outPos < endPos )
00178 {
00179 const uint64_t token = in[inPos++];
00180 if( token == _rleMarker )
00181 {
00182 const uint64_t symbol = in[inPos++];
00183 const uint64_t nSame = in[inPos++];
00184 EQASSERT( outPos + nSame <= endPos );
00185
00186 for( uint32_t j = 0; j<nSame; ++j )
00187 out[outPos++] = symbol;
00188 }
00189 else
00190 out[outPos++] = token;
00191
00192 EQASSERTINFO( ((outPos-1) << 3) <= nPixels*4,
00193 "Overwrite array bounds during decompress" );
00194 }
00195 EQASSERT( outPos == endPos );
00196 }
00197 }
00198
00199 }
00200 }