compressorRLE.ipp

00001 
00002 /* Copyright (c) 2009, Cedric Stalder <cedric.stalder@gmail.com> 
00003  *               2009, Stefan Eilemann <eile@equalizergraphics.com>
00004  *
00005  * Template functions used by all compression routines
00006  * 
00007  * This library is free software; you can redistribute it and/or modify it under
00008  * the terms of the GNU Lesser General Public License version 2.1 as published
00009  * by the Free Software Foundation.
00010  *  
00011  * This library is distributed in the hope that it will be useful, but WITHOUT
00012  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00013  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00014  * details.
00015  * 
00016  * You should have received a copy of the GNU Lesser General Public License
00017  * along with this library; if not, write to the Free Software Foundation, Inc.,
00018  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
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     // determine number of chunks and set up output data structure
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     // The maximum possible size is twice the input size for each chunk, since
00250     // the worst case scenario is input made of tupels of 'rle marker, data'
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 }
Generated on Mon Aug 10 18:58:32 2009 for Equalizer 0.9 by  doxygen 1.5.8