Line data Source code
1 :
2 : /*
3 : * Copyright (c) 2010, Eyescale Software GmbH <info@eyescale.ch>
4 : * 2013, Stefan.Eilemann@epfl.ch
5 : *
6 : * This library is free software; you can redistribute it and/or modify it under
7 : * the terms of the GNU Lesser General Public License version 2.1 as published
8 : * by the Free Software Foundation.
9 : *
10 : * This library is distributed in the hope that it will be useful, but WITHOUT
11 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13 : * details.
14 : *
15 : * You should have received a copy of the GNU Lesser General Public License
16 : * along with this library; if not, write to the Free Software Foundation, Inc.,
17 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 : */
19 :
20 : #include "compressorTurboJPEG.h"
21 :
22 : #include <iostream>
23 : #include <math.h>
24 :
25 : #define QUOTE( string ) STRINGIFY( string )
26 : #define STRINGIFY( foo ) #foo
27 :
28 : namespace lunchbox
29 : {
30 : namespace plugin
31 : {
32 : namespace
33 : {
34 : static int _version; // Eq plugin API version
35 : typedef const char* ( *GetKey_t ) ();
36 :
37 : #define REGISTER_ENGINE( token_, name_, quality_, ratio_, speed_, alpha ) \
38 : static void _getInfoTurbo ## token_ ## name_ ## alpha( EqCompressorInfo* const info ) \
39 : { \
40 : _version = info->version; \
41 : info->version = EQ_COMPRESSOR_VERSION; \
42 : info->capabilities = EQ_COMPRESSOR_DATA_2D; \
43 : if( alpha ) \
44 : info->capabilities |= EQ_COMPRESSOR_IGNORE_ALPHA; \
45 : info->quality = quality_ ## f; \
46 : info->ratio = ratio_ ## f; \
47 : info->speed = speed_ ## f; \
48 : info->name = EQ_COMPRESSOR_CH_EYESCALE_JPEG_## token_ ## name_; \
49 : info->tokenType = EQ_COMPRESSOR_DATATYPE_ ## token_; \
50 : if( alpha ) \
51 : { \
52 : if( _version > 2 ) \
53 : { \
54 : info->outputTokenType = EQ_COMPRESSOR_DATATYPE_ ## token_; \
55 : info->outputTokenSize = 3; \
56 : } \
57 : } \
58 : else if( _version < 3 ) \
59 : info->tokenType = EQ_COMPRESSOR_DATATYPE_INVALID; \
60 : } \
61 : \
62 : static bool _registerTurbo ## token_ ## name_ ## alpha() \
63 : { \
64 : Compressor::registerEngine( \
65 : Compressor::Functions( \
66 : EQ_COMPRESSOR_CH_EYESCALE_JPEG_ ## token_ ## name_, \
67 : _getInfoTurbo ## token_ ## name_ ## alpha, \
68 : CompressorTurboJPEG::getNewCompressor, \
69 : CompressorTurboJPEG::getNewCompressor, \
70 : CompressorTurboJPEG::decompress, 0 )); \
71 : return true; \
72 : } \
73 : \
74 : static bool _initialized ## token_ ## name_ ## alpha = \
75 : _registerTurbo ## token_ ## name_ ## alpha();
76 :
77 61 : REGISTER_ENGINE( RGBA, 100, 0.95, 0.33, 0.34, true );
78 61 : REGISTER_ENGINE( BGRA, 100, 0.95, 0.33, 0.34, true );
79 :
80 61 : REGISTER_ENGINE( RGBA, 90, 0.9, 0.09, 0.65, true );
81 61 : REGISTER_ENGINE( BGRA, 90, 0.9, 0.09, 0.65, true );
82 :
83 61 : REGISTER_ENGINE( RGBA, 80, 0.8, 0.07, 0.75, true );
84 61 : REGISTER_ENGINE( BGRA, 80, 0.8, 0.07, 0.75, true );
85 :
86 61 : REGISTER_ENGINE( RGB, 100, 0.95, 0.3, 1.2, false );
87 61 : REGISTER_ENGINE( RGB, 90, 0.9, 0.3, 1.2, false );
88 61 : REGISTER_ENGINE( RGB, 80, 0.8, 0.3, 1.2, false );
89 61 : REGISTER_ENGINE( BGR, 100, 0.95, 0.3, 1.2, false );
90 61 : REGISTER_ENGINE( BGR, 90, 0.9, 0.3, 1.2, false );
91 61 : REGISTER_ENGINE( BGR, 80, 0.8, 0.3, 1.2, false );
92 : }
93 :
94 0 : CompressorTurboJPEG::CompressorTurboJPEG( const unsigned name )
95 : : Compressor()
96 : , _quality( 100 )
97 : , _tokenSize( 4 )
98 : , _flags( 0 )
99 : , _encoder( 0 )
100 0 : , _decoder( 0 )
101 : {
102 0 : switch( name )
103 : {
104 : case EQ_COMPRESSOR_CH_EYESCALE_JPEG_BGRA80:
105 0 : _flags = TJ_BGR;
106 : case EQ_COMPRESSOR_CH_EYESCALE_JPEG_RGBA80:
107 0 : _quality = 80;
108 0 : break;
109 :
110 : case EQ_COMPRESSOR_CH_EYESCALE_JPEG_BGRA90:
111 0 : _flags = TJ_BGR;
112 : case EQ_COMPRESSOR_CH_EYESCALE_JPEG_RGBA90:
113 0 : _quality = 90;
114 0 : break;
115 :
116 : case EQ_COMPRESSOR_CH_EYESCALE_JPEG_BGRA100:
117 0 : _flags = TJ_BGR;
118 : case EQ_COMPRESSOR_CH_EYESCALE_JPEG_RGBA100:
119 0 : break;
120 :
121 : case EQ_COMPRESSOR_CH_EYESCALE_JPEG_BGR80:
122 0 : _flags = TJ_BGR;
123 : case EQ_COMPRESSOR_CH_EYESCALE_JPEG_RGB80:
124 0 : _quality = 80;
125 0 : _tokenSize = 3;
126 0 : break;
127 :
128 : case EQ_COMPRESSOR_CH_EYESCALE_JPEG_BGR90:
129 0 : _flags = TJ_BGR;
130 : case EQ_COMPRESSOR_CH_EYESCALE_JPEG_RGB90:
131 0 : _quality = 90;
132 0 : _tokenSize = 3;
133 0 : break;
134 :
135 : case EQ_COMPRESSOR_CH_EYESCALE_JPEG_BGR100:
136 0 : _flags = TJ_BGR;
137 : case EQ_COMPRESSOR_CH_EYESCALE_JPEG_RGB100:
138 0 : _tokenSize = 3;
139 0 : break;
140 :
141 : default:
142 0 : assert( false );
143 : }
144 :
145 0 : _flags = _flags | TJ_FASTUPSAMPLE;
146 0 : _results.push_back( new Result ); // RGB jpeg
147 0 : _results.push_back( new Result ); // Alpha uncompressed TODO RLE
148 0 : }
149 :
150 0 : CompressorTurboJPEG::~CompressorTurboJPEG()
151 : {
152 0 : if( _decoder )
153 0 : tjDestroy( _decoder );
154 0 : _decoder = 0;
155 :
156 0 : if( _encoder )
157 0 : tjDestroy( _encoder );
158 0 : _encoder = 0;
159 :
160 0 : }
161 :
162 0 : void CompressorTurboJPEG::compress( const void* const inData,
163 : const eq_uint64_t* inDims,
164 : const eq_uint64_t flags )
165 : {
166 0 : assert( !_decoder );
167 0 : assert( flags & EQ_COMPRESSOR_DATA_2D );
168 :
169 0 : if( !_encoder )
170 0 : _encoder = tjInitCompress();
171 :
172 0 : const bool useAlpha = !(flags & EQ_COMPRESSOR_IGNORE_ALPHA);
173 0 : if( useAlpha && _tokenSize == 4 )
174 : {
175 0 : const eq_uint64_t size = inDims[3] * inDims[1];
176 0 : _extractAlpha( reinterpret_cast< const unsigned char* >(inData), size );
177 0 : _nResults = 2;
178 : }
179 : else
180 0 : _nResults = 1;
181 :
182 0 : _results[0]->resize( TJBUFSIZE( inDims[1], inDims[3] ) );
183 0 : unsigned long size = 0;
184 :
185 0 : void* const data = const_cast< void* const >(inData);
186 0 : if( tjCompress( _encoder, reinterpret_cast< unsigned char*>( data ),
187 0 : inDims[1], inDims[1] * _tokenSize, inDims[3],
188 0 : _tokenSize, _results[0]->getData(), &size,
189 0 : TJ_444, _quality, _flags ))
190 : {
191 0 : assert( false );
192 : size = 0;
193 : }
194 0 : _results[0]->resize( size );
195 0 : }
196 :
197 0 : void CompressorTurboJPEG::decompress( const void* const* inData,
198 : const eq_uint64_t* const inSizes,
199 : const unsigned nInputs,
200 : void* const outData,
201 : eq_uint64_t* const outDims,
202 : const eq_uint64_t flags,
203 : void* const instance )
204 : {
205 0 : const bool useAlpha = !(flags & EQ_COMPRESSOR_IGNORE_ALPHA);
206 : static_cast< CompressorTurboJPEG* >( instance )->
207 0 : _decompress( inData, inSizes[0], nInputs, outData, outDims, useAlpha );
208 0 : }
209 :
210 0 : void CompressorTurboJPEG::_decompress( const void* const* inData,
211 : const eq_uint64_t inSize,
212 : const unsigned nInputs LB_UNUSED,
213 : void* const outData,
214 : eq_uint64_t* const outDims,
215 : const bool useAlpha )
216 : {
217 0 : assert( !_encoder );
218 0 : if( !_decoder )
219 0 : _decoder = tjInitDecompress();
220 0 : void* const data = const_cast< void* const >( inData[0] );
221 :
222 0 : if( tjDecompress( _decoder, reinterpret_cast< unsigned char* >(data),
223 : inSize, reinterpret_cast< unsigned char*>(outData),
224 0 : outDims[1], outDims[1] * _tokenSize, outDims[3],
225 0 : _tokenSize, _flags ))
226 : {
227 0 : assert( false );
228 : }
229 0 : else if( useAlpha && _tokenSize == 4 )
230 : {
231 0 : assert( nInputs == 2 );
232 0 : const eq_uint64_t size = outDims[3] * outDims[1];
233 0 : _addAlpha( inData[1], reinterpret_cast< unsigned* >( outData ), size);
234 : }
235 :
236 0 : }
237 :
238 0 : void CompressorTurboJPEG::_extractAlpha( const unsigned char* inData,
239 : const eq_uint64_t nPixels )
240 : {
241 0 : _results[1]->resize( nPixels );
242 :
243 0 : const unsigned char* end = inData + nPixels * 4;
244 0 : unsigned char* dst = _results[1]->getData();
245 0 : for( const unsigned char* src = ( inData + 3 ); src < end; src += 4 )
246 : {
247 0 : *dst = *src;
248 0 : ++dst;
249 : }
250 0 : }
251 :
252 0 : void CompressorTurboJPEG::_addAlpha( const void* const in, unsigned* out,
253 : const eq_uint64_t nPixels ) const
254 : {
255 0 : assert( _tokenSize == 4 );
256 :
257 0 : const unsigned char* alpha = reinterpret_cast<const unsigned char* >( in );
258 0 : const unsigned* end = out + nPixels;
259 0 : for(unsigned* i = out; i < end; ++i, ++alpha )
260 0 : *i = ((*i) & 0xffffffu) + ((*alpha)<<24);
261 0 : }
262 :
263 : }
264 90 : }
|