00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <eq/base/omp.h>
00022
00023 namespace
00024 {
00025
00026 class UseAlpha
00027 {
00028 public:
00029 static inline bool use() { return true; }
00030 };
00031
00032 class NoAlpha
00033 {
00034 public:
00035 static inline bool use() { return false; }
00036 };
00037
00038 #define WRITE_OUTPUT( name ) \
00039 { \
00040 if( name ## Last == _rleMarker ) \
00041 { \
00042 name ## Out[0] = _rleMarker; \
00043 name ## Out[1] = _rleMarker; \
00044 name ## Out[2] = name ## Same; \
00045 name ## Out += 3; \
00046 } \
00047 else \
00048 switch( name ## Same ) \
00049 { \
00050 case 0: \
00051 break; \
00052 case 2: \
00053 name ## Out[0] = name ## Last; \
00054 name ## Out[1] = name ## Last; \
00055 name ## Out += 2; \
00056 break; \
00057 case 1: \
00058 name ## Out[0] = name ## Last; \
00059 ++(name ## Out); \
00060 break; \
00061 default: \
00062 name ## Out[0] = _rleMarker; \
00063 name ## Out[1] = name ## Last; \
00064 name ## Out[2] = name ## Same; \
00065 name ## Out += 3; \
00066 break; \
00067 } \
00068 }
00069
00070 #define WRITE( name ) \
00071 if( name == name ## Last && name ## Same != 255 ) \
00072 ++(name ## Same ); \
00073 else \
00074 { \
00075 WRITE_OUTPUT( name ); \
00076 name ## Last = name; \
00077 name ## Same = 1; \
00078 }
00079
00080
00081 template< typename PixelType, typename ComponentType,
00082 typename swizzleFunc, typename alphaFunc >
00083 static inline void _compress( const void* const input, const uint64_t nPixels,
00084 eq::plugin::Compressor::Result** results )
00085 {
00086 const PixelType* pixel = reinterpret_cast< const PixelType* >( input );
00087
00088 ComponentType* oneOut( reinterpret_cast< ComponentType* >(
00089 results[ 0 ]->getData( )));
00090 ComponentType* twoOut( reinterpret_cast< ComponentType* >(
00091 results[ 1 ]->getData( )));
00092 ComponentType* threeOut( reinterpret_cast< ComponentType* >(
00093 results[ 2 ]->getData( )));
00094 ComponentType* fourOut( reinterpret_cast< ComponentType* >(
00095 results[ 3 ]->getData( )));
00096
00097 ComponentType oneLast(0), twoLast(0), threeLast(0), fourLast(0);
00098 if( alphaFunc::use( ))
00099 swizzleFunc::swizzle( *pixel, oneLast, twoLast, threeLast, fourLast );
00100 else
00101 swizzleFunc::swizzle( *pixel, oneLast, twoLast, threeLast );
00102
00103 ComponentType oneSame( 1 ), twoSame( 1 ), threeSame( 1 ), fourSame( 1 );
00104 ComponentType one(0), two(0), three(0), four(0);
00105
00106 for( uint64_t i = 1; i < nPixels; ++i )
00107 {
00108 ++pixel;
00109
00110 if( alphaFunc::use( ))
00111 {
00112 swizzleFunc::swizzle( *pixel, one, two, three, four );
00113 WRITE( one );
00114 WRITE( two );
00115 WRITE( three );
00116 WRITE( four );
00117 }
00118 else
00119 {
00120 swizzleFunc::swizzle( *pixel, one, two, three );
00121 WRITE( one );
00122 WRITE( two );
00123 WRITE( three );
00124 }
00125 }
00126
00127 WRITE_OUTPUT( one );
00128 WRITE_OUTPUT( two );
00129 WRITE_OUTPUT( three )
00130 WRITE_OUTPUT( four );
00131
00132 results[0]->setSize( reinterpret_cast< uint8_t* > ( oneOut ) -
00133 results[0]->getData( ));
00134 results[1]->setSize( reinterpret_cast< uint8_t* >( twoOut ) -
00135 results[1]->getData( ));
00136 results[2]->setSize( reinterpret_cast< uint8_t* >( threeOut ) -
00137 results[2]->getData( ));
00138 results[3]->setSize( reinterpret_cast< uint8_t* >( fourOut ) -
00139 results[3]->getData( ));
00140 }
00141
00142 #define READ( name ) \
00143 if( name ## Left == 0 ) \
00144 { \
00145 name = *name ## In; \
00146 if( name == _rleMarker ) \
00147 { \
00148 name = name ## In[1]; \
00149 name ## Left = name ## In[2]; \
00150 name ## In += 3; \
00151 } \
00152 else \
00153 { \
00154 name ## Left = 1; \
00155 ++name ## In; \
00156 } \
00157 } \
00158 --name ## Left;
00159
00160 template< typename PixelType, typename ComponentType,
00161 typename swizzleFunc, typename alphaFunc >
00162 static inline void _decompress( const void* const* inData,
00163 const eq_uint64_t* const inSizes,
00164 const unsigned nInputs,
00165 void* const outData, const eq_uint64_t nPixels )
00166 {
00167 assert( (nInputs % 4) == 0 );
00168 assert( (inSizes[0] % sizeof( ComponentType )) == 0 );
00169 assert( (inSizes[1] % sizeof( ComponentType )) == 0 );
00170 assert( (inSizes[2] % sizeof( ComponentType )) == 0 );
00171
00172 const uint64_t nElems = nPixels * 4;
00173 const float width = static_cast< float >( nElems ) /
00174 static_cast< float >( nInputs );
00175
00176 const ComponentType* const* in =
00177 reinterpret_cast< const ComponentType* const* >( inData );
00178
00179 #ifdef EQ_USE_OPENMP
00180 #pragma omp parallel for
00181 #endif
00182 for( ssize_t i = 0; i < static_cast< ssize_t >( nInputs ) ; i+=4 )
00183 {
00184 const uint64_t startIndex = static_cast<uint64_t>( i/4 * width ) * 4;
00185 const uint64_t nextIndex =
00186 static_cast< uint64_t >(( i/4 + 1 ) * width ) * 4;
00187 const uint64_t chunkSize = ( nextIndex - startIndex ) / 4;
00188 PixelType* out = reinterpret_cast< PixelType* >( outData ) +
00189 startIndex / 4;
00190
00191 const ComponentType* oneIn = in[ i + 0 ];
00192 const ComponentType* twoIn = in[ i + 1 ];
00193 const ComponentType* threeIn = in[ i + 2 ];
00194 const ComponentType* fourIn = in[ i + 3 ];
00195
00196 ComponentType one(0), two(0), three(0), four(0);
00197 ComponentType oneLeft(0), twoLeft(0), threeLeft(0), fourLeft(0);
00198
00199 for( uint64_t j = 0; j < chunkSize ; ++j )
00200 {
00201 assert( static_cast< uint64_t >( oneIn-in[i+0]) <=
00202 inSizes[i+0] / sizeof( ComponentType ) );
00203 assert( static_cast< uint64_t >( twoIn-in[i+1]) <=
00204 inSizes[i+1] / sizeof( ComponentType ) );
00205 assert( static_cast< uint64_t >( threeIn-in[i+2]) <=
00206 inSizes[i+2] / sizeof( ComponentType ) );
00207
00208 if( alphaFunc::use( ))
00209 {
00210 READ( one );
00211 READ( two );
00212 READ( three );
00213 READ( four );
00214
00215 *out = swizzleFunc::deswizzle( one, two, three, four );
00216 }
00217 else
00218 {
00219 READ( one );
00220 READ( two );
00221 READ( three );
00222
00223 *out = swizzleFunc::deswizzle( one, two, three );
00224 }
00225 ++out;
00226 }
00227 assert( static_cast< uint64_t >( oneIn-in[i+0] ) ==
00228 inSizes[i+0] / sizeof( ComponentType ) );
00229 assert( static_cast< uint64_t >( twoIn-in[i+1] ) ==
00230 inSizes[i+1] / sizeof( ComponentType ) );
00231 assert( static_cast< uint64_t >( threeIn-in[i+2] ) ==
00232 inSizes[i+2] / sizeof( ComponentType ) );
00233 }
00234 }
00235
00236 static void _setupResults( const uint32_t nChannels, const eq_uint64_t inSize,
00237 eq::plugin::Compressor::ResultVector& results )
00238 {
00239
00240 #ifdef EQ_USE_OPENMP
00241 const size_t nChunks = nChannels * eq::base::OMP::getNThreads() * 4;
00242 #else
00243 const size_t nChunks = nChannels;
00244 #endif
00245
00246 while( results.size() < nChunks )
00247 results.push_back( new eq::plugin::Compressor::Result );
00248
00249
00250
00251 const eq_uint64_t maxChunkSize = (inSize/nChunks + 1) * 2;
00252 for( size_t i = 0; i < nChunks; ++i )
00253 results[i]->resize( maxChunkSize );
00254 }
00255
00256 template< typename PixelType, typename ComponentType,
00257 typename swizzleFunc, typename alphaFunc >
00258 static inline void _compress( const void* const inData,
00259 const eq_uint64_t nPixels, const bool useAlpha,
00260 const bool swizzle,
00261 eq::plugin::Compressor::ResultVector& results )
00262 {
00263 const uint64_t size = nPixels * sizeof( PixelType );
00264 _setupResults( 4, size, results );
00265
00266 const uint64_t nElems = nPixels * 4;
00267 const uint64_t nResults = results.size();
00268 const float width = static_cast< float >( nElems ) /
00269 static_cast< float >( nResults );
00270
00271 const ComponentType* const data =
00272 reinterpret_cast< const ComponentType* >( inData );
00273
00274 #ifdef EQ_USE_OPENMP
00275 #pragma omp parallel for
00276 #endif
00277 for( ssize_t i = 0; i < static_cast< ssize_t >( nResults ) ; i += 4 )
00278 {
00279 const uint64_t startIndex = static_cast< uint64_t >( i/4 * width ) * 4;
00280 const uint64_t nextIndex =
00281 static_cast< uint64_t >(( i/4 + 1 ) * width ) * 4;
00282 const uint64_t chunkSize = ( nextIndex - startIndex ) / 4;
00283
00284 _compress< PixelType, ComponentType, swizzleFunc, alphaFunc >(
00285 &data[ startIndex ], chunkSize, &results[i] );
00286 }
00287 }
00288
00289 }