Line data Source code
1 :
2 : /* Copyright (c) 2010, Cedric Stalder <cedric.stalder@gmail.com>
3 : * 2010-2013, Stefan Eilemann <eile@eyescale.ch>
4 : *
5 : * This library is free software; you can redistribute it and/or modify it under
6 : * the terms of the GNU Lesser General Public License version 2.1 as published
7 : * by the Free Software Foundation.
8 : *
9 : * This library is distributed in the hope that it will be useful, but WITHOUT
10 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 : * details.
13 : *
14 : * You should have received a copy of the GNU Lesser General Public License
15 : * along with this library; if not, write to the Free Software Foundation, Inc.,
16 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 : */
18 :
19 : #include "compressorRLEB.h"
20 : #include <limits>
21 :
22 : namespace
23 : {
24 : static const uint8_t _rleMarker = 0x42; // just a random number
25 : }
26 :
27 : #include "compressorRLE.ipp"
28 :
29 : namespace lunchbox
30 : {
31 : namespace plugin
32 : {
33 : namespace
34 : {
35 61 : REGISTER_ENGINE( CompressorRLEB, BYTE, BYTE, 1., 0.93, 1., false );
36 : }
37 :
38 : template< typename T >
39 513 : inline void _compressChunk( const T* const in, const eq_uint64_t nPixels,
40 : Compressor::Result* result )
41 : {
42 513 : if( nPixels == 0 )
43 : {
44 0 : result->setSize( 0 );
45 902 : return;
46 : }
47 :
48 513 : T* tokenOut = reinterpret_cast< T* >( result->getData( ));
49 5668654 : T tokenLast( in[0] );
50 5668654 : T tokenSame( 1 );
51 5668654 : T token(0);
52 :
53 39446936 : for( eq_uint64_t i = 1; i < nPixels; ++i )
54 : {
55 39446037 : token = in[i];
56 39446037 : COMPRESS( token );
57 : }
58 :
59 899 : WRITE_OUTPUT( token );
60 898 : result->setSize( (tokenOut - reinterpret_cast< T* >( result->getData( ))) *
61 : sizeof( T ));
62 : #ifndef LUNCHBOX_AGGRESSIVE_CACHING
63 899 : result->pack();
64 : #endif
65 : }
66 :
67 : template< typename T >
68 76 : ssize_t _compress( const void* const inData, const eq_uint64_t nPixels,
69 : Compressor::ResultVector& results )
70 : {
71 76 : const eq_uint64_t size = nPixels * sizeof( T );
72 76 : const ssize_t nChunks = _setupResults( 1, size, results );
73 : const float width = static_cast< float >( nPixels ) /
74 76 : static_cast< float >( nChunks );
75 :
76 76 : const T* const data = reinterpret_cast< const T* >( inData );
77 :
78 658 : #pragma omp parallel for
79 582 : for( ssize_t i = 0; i < static_cast< ssize_t >( nChunks ) ; ++i )
80 : {
81 609 : const eq_uint64_t startIndex = static_cast< eq_uint64_t >( i * width );
82 :
83 : eq_uint64_t nextIndex;
84 609 : if ( i == nChunks - 1 )
85 76 : nextIndex = nPixels;
86 : else
87 533 : nextIndex = static_cast< eq_uint64_t >(( i + 1 ) * width );
88 609 : const eq_uint64_t chunkSize = ( nextIndex - startIndex );
89 :
90 609 : _compressChunk< T >( &data[ startIndex ], chunkSize, results[i] );
91 : }
92 76 : return nChunks;
93 : }
94 :
95 :
96 76 : void CompressorRLEB::compress( const void* const inData,
97 : const eq_uint64_t nPixels, const bool /*alpha*/ )
98 : {
99 76 : if( (nPixels & 0x7) == 0 )
100 14 : _nResults = _compress< eq_uint64_t >( inData, nPixels>>3, _results );
101 62 : else if( (nPixels & 0x3) == 0 )
102 14 : _nResults = _compress< uint32_t >( inData, nPixels>>2, _results );
103 48 : else if( (nPixels & 0x1) == 0 )
104 18 : _nResults = _compress< uint16_t >( inData, nPixels>>1, _results );
105 : else
106 30 : _nResults = _compress< uint8_t >( inData, nPixels, _results );
107 76 : }
108 :
109 : //----------------------------------------------------------------------
110 : template< typename T >
111 900 : inline void _decompressChunk( const T* in, T* out, const eq_uint64_t nPixels )
112 : {
113 900 : T token(0);
114 900 : T tokenLeft(0);
115 :
116 40315444 : for( eq_uint64_t i = 0; i < nPixels ; ++i )
117 : {
118 40314544 : if( tokenLeft == 0 )
119 : {
120 41590014 : token = *in; ++in;
121 41590014 : if( token == _rleMarker )
122 : {
123 0 : token = *in; ++in;
124 0 : tokenLeft = *in; ++in;
125 : }
126 : else // single symbol
127 42737998 : tokenLeft = 1;
128 : }
129 :
130 40314544 : --tokenLeft;
131 40314544 : out[i] = token;
132 : }
133 900 : }
134 :
135 :
136 : template< typename T >
137 76 : void _decompress( const void* const* inData, const unsigned nInputs,
138 : void* const outData, const eq_uint64_t nPixels )
139 : {
140 : const float width = static_cast< float >( nPixels ) /
141 76 : static_cast< float >( nInputs );
142 :
143 76 : const T* const* in = reinterpret_cast< const T* const* >( inData );
144 :
145 611 : #pragma omp parallel for
146 535 : for( ssize_t i = 0; i < static_cast< ssize_t >( nInputs ) ; ++i )
147 : {
148 658 : const eq_uint64_t startIndex = static_cast<uint64_t>( i * width );
149 :
150 : eq_uint64_t nextIndex;
151 658 : if ( i == static_cast<ssize_t>( nInputs -1 ) )
152 76 : nextIndex = nPixels;
153 : else
154 582 : nextIndex = static_cast< eq_uint64_t >(( i + 1 ) * width );
155 :
156 658 : const eq_uint64_t chunkSize = ( nextIndex - startIndex );
157 658 : T* out = reinterpret_cast< T* >( outData ) + startIndex;
158 :
159 658 : _decompressChunk< T >( in[i], out, chunkSize );
160 : }
161 76 : }
162 :
163 76 : void CompressorRLEB::decompress( const void* const* inData,
164 : const eq_uint64_t* const /*inSizes*/,
165 : const unsigned nInputs, void* const outData,
166 : eq_uint64_t* const outDims,
167 : const eq_uint64_t flags, void* const )
168 : {
169 76 : const eq_uint64_t nPixels = ( flags & EQ_COMPRESSOR_DATA_1D) ?
170 76 : outDims[1] : outDims[1] * outDims[3];
171 76 : if( (nPixels & 0x7) == 0 )
172 14 : _decompress< uint64_t >( inData, nInputs, outData, nPixels>>3 );
173 62 : else if( (nPixels & 0x3) == 0 )
174 14 : _decompress< uint32_t >( inData, nInputs, outData, nPixels>>2 );
175 48 : else if( (nPixels & 0x1) == 0 )
176 18 : _decompress< uint16_t >( inData, nInputs, outData, nPixels>>1 );
177 : else
178 30 : _decompress< uint8_t >( inData, nInputs, outData, nPixels );
179 76 : }
180 :
181 : }
182 90 : }
|