1 #include "stdEncoder.h"
2 #include "../fileUtil.h"
4 /// \file stdEncoder.cpp
9 /** Quantizes f that belongs to 0..possib/2^scale into 0..possib-1 */
10 inline int quantizeByPower(Real f
,int scale
,int possib
) {
11 ASSERT( f
>=0 && f
<=possib
/(Real
)powers
[scale
] );
12 int result
= (int)trunc(ldexp(f
,scale
));
13 ASSERT( result
>=0 && result
<=possib
);
14 return result
<possib
? result
: --result
;
16 /** Performs the opposite to ::quantizeByPower */
17 inline Real
dequantizeByPower(int i
,int scale
,int DEBUG_ONLY(possib
)) {
18 ASSERT( i
>=0 && i
<possib
);
19 Real result
= ldexp(i
+Real(0.5),-scale
);
20 ASSERT( result
>=0 && result
<= possib
/(Real
)powers
[scale
] );
24 /** (De)Quantizer for range-block averages */
28 Average(int possibLog2
) {
30 // the average is from [0,1]
32 possib
= powers
[possibLog2
];
35 { return quantizeByPower(avg
,scale
,possib
); }
37 { return dequantizeByPower(i
,scale
,possib
); }
39 { return dequant(quant(avg
)); }
42 /** (De)Quantizer for range-block deviations */
46 Deviation(int possibLog2
) {
48 // the deviation is from [0,0.5] -> we have to scale twice more (log2+=1)
50 possib
= powers
[possibLog2
];
53 { return quantizeByPower(dev
,scale
,possib
); }
55 { return dequantizeByPower(i
,scale
,possib
); }
57 { return dequant(quant(dev
)); }
62 struct LevelPoolInfo_indexComparator
{
63 typedef ISquareEncoder::LevelPoolInfo LevelPoolInfo
;
64 bool operator()( const LevelPoolInfo
&a
, const LevelPoolInfo
&b
)
65 { return a
.indexBegin
< b
.indexBegin
; }
68 MStandardEncoder::PoolInfos::const_iterator MStandardEncoder
69 ::getPoolFromDomID( int domID
, const PoolInfos
&poolInfos
) {
70 ASSERT( domID
>=0 && domID
<poolInfos
.back().indexBegin
);
72 PoolInfos::value_type toFind
;
73 toFind
.indexBegin
= domID
;
74 return upper_bound( poolInfos
.begin(), poolInfos
.end(), toFind
75 , LevelPoolInfo_indexComparator() ) -1;
78 const ISquareDomains::Pool
& MStandardEncoder::getDomainData
79 ( const RangeNode
&rangeBlock
, const ISquareDomains::PoolList
&pools
80 , const PoolInfos
&poolInfos
, int domIndex
, int zoom
, Block
&block
) {
83 PoolInfos::const_iterator it
= getPoolFromDomID( domIndex
, poolInfos
);
84 const Pool
&pool
= pools
[ it
- poolInfos
.begin() ];
85 // get the coordinates
86 int indexInPool
= domIndex
- it
->indexBegin
;
87 ASSERT( indexInPool
>=0 && indexInPool
<(it
+1)->indexBegin
);
88 int sizeNZ
= powers
[rangeBlock
.level
-zoom
];
89 int zoomFactor
= powers
[zoom
];
90 // changed: the domains are mapped along columns and not rows
91 int domsInCol
= getCountForDensity( pool
.height
/zoomFactor
, it
->density
, sizeNZ
);
92 block
.x0
= (indexInPool
/domsInCol
)*it
->density
*zoomFactor
;
93 block
.y0
= (indexInPool
%domsInCol
)*it
->density
*zoomFactor
;
94 block
.xend
= block
.x0
+powers
[rangeBlock
.level
];
95 block
.yend
= block
.y0
+powers
[rangeBlock
.level
];
100 /** Adjust block of a domain to be mapped equally on an incomplete range (depends on rotation) */
101 inline static Block
adjustDomainForIncompleteRange( Block range
, int rotation
, Block domain
) {
104 // 2, 2T: bottom right
105 // 3, 3T: bottom left
107 ASSERT( 0<=rotation
&& rotation
<8 );
108 int rotID
= rotation
/2;
110 int xSize
= range
.width();
111 int ySize
= range
.height();
113 int magic
= rotID
+rotation
%2;
114 if ( magic
==1 || magic
==3 ) // for rotations 0T, 1, 2T, 3 -> swapped x and y
117 if ( rotID
>1 ) // domain rotations 2, 3, 2T, 3T -> aligned to the bottom
118 domain
.y0
= domain
.yend
-ySize
;
119 else // other rotations are aligned to the top
120 domain
.yend
= domain
.y0
+ySize
;
122 if ( rotID
==1 || rotID
==2 ) // rotations 1, 2, 1T, 2T -> aligned to the right
123 domain
.x0
= domain
.xend
-xSize
;
124 else // other rotations are aligned to the left
125 domain
.xend
= domain
.x0
+xSize
;
132 void MStandardEncoder::initialize( IRoot::Mode mode
, PlaneBlock
&planeBlock_
) {
133 planeBlock
= &planeBlock_
;
134 // prepare the domains-module
135 planeBlock
->domains
->initPools(*planeBlock
);
137 int maxLevel
= 1 +log2ceil(max( planeBlock
->width
, planeBlock
->height
));
138 // prepare levelPoolInfos
139 levelPoolInfos
.resize(maxLevel
);
141 if (mode
==IRoot::Encode
) {
142 typedef ISquareDomains::PoolList PoolList
;
143 // prepare the domains
144 planeBlock
->domains
->fillPixelsInPools(*planeBlock
);
145 // initialize the range summers
146 planeBlock
->summers_makeValid();
148 // prepare maximum SquareErrors allowed for regular range blocks
149 stdRangeSEs
.resize(maxLevel
+1);
150 planeBlock
->settings
->moduleQ2SE
->regularRangeErrors
151 ( planeBlock
->settings
->quality
, maxLevel
+1, &stdRangeSEs
.front() );
156 typedef IStdEncPredictor::NewPredictorData StableInfo
;
158 /** Information about the best (found so far) domain block for a range block */
159 struct BestInfo
: public IStdEncPredictor::Prediction
{
160 float error
; ///< The square error of the mapping
161 bool inverted
; ///< Whether the colours are mapped with a negative linear coefficient
164 , dSum
/// Sum of all pixels in best domain
165 , d2Sum
; ///< Sum of squares of all pixesl in the best domain
169 : Prediction(), error( numeric_limits
<float>::max() ) {}
170 IStdEncPredictor::Prediction
& prediction()
173 } // namespace NOSPACE
176 struct MStandardEncoder::EncodingInfo
{
177 typedef bool (EncodingInfo::*ExactCompareProc
)( Prediction prediction
);
180 /** Possible comparing methods */
181 static const ExactCompareProc exactCompareArray
[];
183 ExactCompareProc selectedProc
; ///< Selected comparing method
185 StableInfo stable
; ///< Information only depending on the range (and not domain) block
186 BestInfo best
; ///< Information about the best (at the moment) mapping found
187 float targetSE
/// The maximal accepted SE (square error) for the range
188 , maxSE2Predict
; ///< The maximal SE that the predictor should try to predict
194 /** Initializes a RangeInfo object from #this */
195 RangeInfo
* initRangeInfo(RangeInfo
*ri
) const {
196 ri
->bestSE
= best
.error
;
197 ri
->prediction()= best
;
198 ri
->qrAvg
= stable
.qrAvg
;
199 ri
->qrDev2
= stable
.qrDev2
;
200 ri
->inverted
= best
.inverted
;
202 ri
->exact
.avg
= stable
.rSum
/stable
.pixCount
;
203 ri
->exact
.dev2
= stable
.r2Sum
/stable
.pixCount
- sqr(ri
->exact
.avg
);
204 ri
->exact
.linCoeff
= ( stable
.pixCount
*best
.rdSum
- stable
.rSum
*best
.dSum
)
205 / ( stable
.pixCount
*best
.d2Sum
- sqr(best
.dSum
) );
206 ri
->exact
.constCoeff
= ri
->exact
.avg
- ri
->exact
.linCoeff
*best
.dSum
/stable
.pixCount
;
211 /** Selects the right comparing method according to #stable */
212 void selectExactCompareProc() {
213 selectedProc
= exactCompareArray
214 [((( stable
.quantError
*2
215 + stable
.allowInversion
) *2
216 + stable
.isRegular
) *2
217 + (stable
.maxLinCoeff2
>= 0) ) *2
218 + (stable
.bigScaleCoeff
!= 0)
222 /** Uses the selected comparing method */
223 bool exactCompare(Prediction prediction
)
224 { return (this->* selectedProc
)(prediction
); }
227 /** Template for all the comparing methods */
228 template < bool quantErrors
, bool allowInversion
, bool isRegular
229 , bool restrictMaxLinCoeff
, bool bigScalePenalty
>
230 bool exactCompareProc( Prediction prediction
);
231 }; // EncodingInfo class
233 #define ALTERNATE_0(name,params...) name<params>
234 #define ALTERNATE_1(name,params...) ALTERNATE_0(name,##params,false), ALTERNATE_0(name,##params,true)
235 #define ALTERNATE_2(name,params...) ALTERNATE_1(name,##params,false), ALTERNATE_1(name,##params,true)
236 #define ALTERNATE_3(name,params...) ALTERNATE_2(name,##params,false), ALTERNATE_2(name,##params,true)
237 #define ALTERNATE_4(name,params...) ALTERNATE_3(name,##params,false), ALTERNATE_3(name,##params,true)
238 #define ALTERNATE_5(name,params...) ALTERNATE_4(name,##params,false), ALTERNATE_4(name,##params,true)
239 const MStandardEncoder::EncodingInfo::ExactCompareProc
240 MStandardEncoder::EncodingInfo::exactCompareArray
[]
241 = {ALTERNATE_5(&MStandardEncoder::EncodingInfo::exactCompareProc
)};
249 template< bool quantErrors
, bool allowInversion
, bool isRegular
250 , bool restrictMaxLinCoeff
, bool bigScalePenalty
>
251 bool MStandardEncoder::EncodingInfo::exactCompareProc( Prediction prediction
) {
252 using namespace MatrixWalkers
;
253 // find out which domain was predicted (pixel matrix and position within it)
255 const Pool
&pool
= getDomainData( *stable
.rangeBlock
, *stable
.pools
, *stable
.poolInfos
256 , prediction
.domainID
, 0/*zoom*/, domBlock
);
257 // compute domain sums
259 domBlock
= adjustDomainForIncompleteRange
260 ( *stable
.rangeBlock
, prediction
.rotation
, domBlock
);
262 pool
.getSums(domBlock
).unpack(dSum
,d2Sum
);
263 // compute the denominator common to most formulas
264 Real test
= stable
.pixCount
*d2Sum
- sqr(dSum
);
265 if (test
<=0) // skip too flat domains
269 // compute the sum of products of pixels
270 Real rdSum
= walkOperateCheckRotate
271 ( Checked
<const SReal
>(stable
.rangePixels
, *stable
.rangeBlock
), RDSummer
<Real
,SReal
>()
272 , pool
.pixels
, domBlock
, prediction
.rotation
) .result();
274 Real nRDs_RsDs
= stable
.pixCount
*rdSum
- stable
.rSum
*dSum
;
275 // check for negative linear coefficients (if needed)
279 // compute the square of linear coefficient if needed (for restricting or penalty)
280 Real linCoeff2
DEBUG_ONLY(= numeric_limits
<Real
>::quiet_NaN() );
281 if ( restrictMaxLinCoeff
|| bigScalePenalty
)
282 linCoeff2
= stable
.rnDev2
* denom
;
283 if (restrictMaxLinCoeff
)
284 if ( linCoeff2
> stable
.maxLinCoeff2
)
287 float optSE
DEBUG_ONLY(= numeric_limits
<Real
>::quiet_NaN() );
290 optSE
= stable
.qrAvg
* ( stable
.pixCount
*stable
.qrAvg
- ldexp(stable
.rSum
,1) )
291 + stable
.r2Sum
+ stable
.qrDev
292 * ( stable
.pixCount
*stable
.qrDev
- ldexp( abs(nRDs_RsDs
)*sqrt(denom
), 1 ) );
293 } else { // !quantErrors
294 // assuming different linear coeffitient
295 Real inner
= stable
.rnDev2
- stable
.rnDev
*abs(nRDs_RsDs
)*sqrt(denom
);
296 optSE
= ldexp( inner
, 1 ) / stable
.pixCount
;
299 // add big-scaling penalty if needed
301 optSE
+= linCoeff2
* targetSE
* sqr(pool
.contrFactor
) * stable
.bigScaleCoeff
;
303 // test if the error is the best so far
304 if ( optSE
< best
.error
) {
305 best
.prediction()= prediction
;
306 best
.error
= maxSE2Predict
= optSE
;
307 best
.inverted
= nRDs_RsDs
<0;
318 } // EncodingInfo::exactCompareProc method
321 float MStandardEncoder::findBestSE(const RangeNode
&range
,bool allowHigherSE
) {
322 ASSERT( planeBlock
&& !stdRangeSEs
.empty() && !range
.encoderData
);
323 const IColorTransformer::PlaneSettings
*plSet
= planeBlock
->settings
;
325 // initialize an encoding-info object
328 info
.stable
.rangeBlock
= &range
;
329 info
.stable
.rangePixels
= planeBlock
->pixels
;
330 info
.stable
.pools
= &planeBlock
->domains
->getPools();
332 ASSERT( range
.level
< (int)levelPoolInfos
.size() );
333 info
.stable
.poolInfos
= &levelPoolInfos
[range
.level
];
334 // check the level has been initialized
335 if ( info
.stable
.poolInfos
->empty() ) {
336 buildPoolInfos4aLevel(range
.level
,plSet
->zoom
);
337 ASSERT( !info
.stable
.poolInfos
->empty() );
340 info
.stable
.allowRotations
= settingsInt(AllowedRotations
);
341 info
.stable
.quantError
= settingsInt(AllowedQuantError
);
342 info
.stable
.allowInversion
= settingsInt(AllowedInversion
);
343 info
.stable
.isRegular
= range
.isRegular();
345 Real coeff
= settingsFloat(MaxLinCoeff
);
346 info
.stable
.maxLinCoeff2
= coeff
==MaxLinCoeff_none
? -1 : sqr(coeff
);
348 info
.stable
.bigScaleCoeff
= settingsFloat(BigScaleCoeff
);
350 planeBlock
->getSums(range
).unpack( info
.stable
.rSum
, info
.stable
.r2Sum
);
351 info
.stable
.pixCount
= range
.size();
352 info
.stable
.rnDev2
= info
.stable
.pixCount
*info
.stable
.r2Sum
- sqr(info
.stable
.rSum
);
353 if (info
.stable
.rnDev2
<0)
354 info
.stable
.rnDev2
= 0;
355 info
.stable
.rnDev
= sqrt(info
.stable
.rnDev2
);
359 Quantizer::Average
quantAvg( settingsInt(QuantStepLog_avg
) );
360 Quantizer::Deviation
quantDev( settingsInt(QuantStepLog_dev
) );
361 Real average
= info
.stable
.rSum
/ info
.stable
.pixCount
;
362 info
.stable
.qrAvg
= quantAvg
.qRound(average
);
364 variance
= info
.stable
.r2Sum
/info
.stable
.pixCount
- sqr(average
);
365 Real deviance
= variance
>0 ? sqrt(variance
) : 0;
366 int qrDev
= quantDev
.quant(deviance
);
367 // if we have too little deviance or no domain pool for that big level or no domain in the pool
368 if ( !qrDev
|| range
.level
>= (int)levelPoolInfos
.size()
369 || info
.stable
.poolInfos
->back().indexBegin
<= 0 ) // -> no domain block, only average
370 goto returning
; // skips to the end, assigning a constant block
371 else { // the regular case, with nonzero quantized deviance
372 info
.stable
.qrDev
= quantDev
.dequant(qrDev
);
373 info
.stable
.qrDev2
= sqr(info
.stable
.qrDev
);
377 info
.targetSE
= info
.maxSE2Predict
= info
.stable
.isRegular
? stdRangeSEs
[range
.level
]
378 : plSet
->moduleQ2SE
->rangeSE( plSet
->quality
, range
.size() );
379 ASSERT(info
.targetSE
>=0);
381 info
.maxSE2Predict
= numeric_limits
<float>::max();
382 info
.selectExactCompareProc();
384 { // a goto-skippable block
385 // create and initialize a new predictor
386 auto_ptr
<IStdEncPredictor::IOneRangePredictor
> predictor
387 ( modulePredictor()->newPredictor(info
.stable
) );
388 typedef IStdEncPredictor::Predictions Predictions
;
389 Predictions predicts
;
391 float sufficientSE
= info
.targetSE
*settingsFloat(SufficientSEq
);
392 // get and process prediction chunks until an empty one is returned
393 while ( !predictor
->getChunk(info
.maxSE2Predict
,predicts
).empty() )
394 for (Predictions::iterator it
=predicts
.begin(); it
!=predicts
.end(); ++it
) {
395 bool betterSE
= info
.exactCompare(*it
);
396 if ( betterSE
&& info
.best
.error
<=sufficientSE
)
402 // check the case that the predictor didn't return any domains
403 if ( info
.best
.error
== numeric_limits
<float>::max() ) { // a constant block
404 info
.stable
.qrDev
= info
.stable
.qrDev2
= 0;
405 info
.best
.error
= info
.stable
.quantError
406 ? info
.stable
.r2Sum
+ info
.stable
.qrAvg
407 *( info
.stable
.pixCount
*info
.stable
.qrAvg
- ldexp(info
.stable
.rSum
,1) )
408 : variance
*info
.stable
.pixCount
;
410 // store the important info and return the error
411 range
.encoderData
= info
.initRangeInfo( rangeInfoAlloc
.make() );
412 return info
.best
.error
;
415 void MStandardEncoder::buildPoolInfos4aLevel(int level
,int zoom
) {
416 // get the real maximum domain count (divide by the number of rotations)
417 int domainCountLog2
= planeBlock
->settings
->domainCountLog2
;
418 if ( settingsInt(AllowedRotations
) )
420 // get the per-domain-pool densities
421 vector
<short> densities
= planeBlock
->domains
->getLevelDensities(level
,domainCountLog2
);
422 // store it in the this-level infos with beginIndex values for all pools
423 vector
<LevelPoolInfo
> &poolInfos
= levelPoolInfos
[level
];
424 ASSERT( poolInfos
.empty() );
425 const ISquareDomains::PoolList
&pools
= planeBlock
->domains
->getPools();
427 int domainSizeNZ
= powers
[level
-zoom
];
428 int poolCount
= pools
.size();
429 poolInfos
.resize(poolCount
+1);
431 int domCount
= poolInfos
[0].indexBegin
= 0; // accumulated count
432 for (int i
=0; i
<poolCount
; ++i
) {
433 int dens
= poolInfos
[i
].density
= densities
[i
];
435 if (dens
) // if dens==0, there are no domains -> no increase
436 domCount
+= getCountForDensity2D( pools
[i
].width
/powers
[zoom
]
437 , pools
[i
].height
/powers
[zoom
], dens
, domainSizeNZ
);
438 poolInfos
[i
+1].indexBegin
= domCount
;
440 poolInfos
[poolCount
].density
= -1;
443 void MStandardEncoder::writeSettings(ostream
&file
) {
444 ASSERT( /*modulePredictor() &&*/ moduleCodec(true) && moduleCodec(false) );
445 // put settings needed for decoding
446 put
<Uchar
>( file
, settingsInt(AllowedRotations
) );
447 put
<Uchar
>( file
, settingsInt(AllowedInversion
) );
448 put
<Uchar
>( file
, settingsInt(QuantStepLog_avg
) );
449 put
<Uchar
>( file
, settingsInt(QuantStepLog_dev
) );
450 // put ID's of connected modules
451 //the predictor module doesn't need to be known
452 file_saveModuleType( file
, ModuleCodecAvg
);
453 file_saveModuleType( file
, ModuleCodecDev
);
454 // put the settings of connected modules
455 moduleCodec(true)->writeSettings(file
);
456 moduleCodec(false)->writeSettings(file
);
458 void MStandardEncoder::readSettings(istream
&file
) {
459 ASSERT( !modulePredictor() && !moduleCodec(true) && !moduleCodec(false) );
460 // get settings needed for decoding
461 settingsInt(AllowedRotations
)= get
<Uchar
>(file
);
462 settingsInt(AllowedInversion
)= get
<Uchar
>(file
);
463 settingsInt(QuantStepLog_avg
)= get
<Uchar
>(file
);
464 settingsInt(QuantStepLog_dev
)= get
<Uchar
>(file
);
465 // create connected modules
466 //the predictor module doesn't need to be known
467 file_loadModuleType( file
, ModuleCodecAvg
);
468 file_loadModuleType( file
, ModuleCodecDev
);
469 // get the settings of connected modules
470 moduleCodec(true)->readSettings(file
);
471 moduleCodec(false)->readSettings(file
);
474 void MStandardEncoder::writeData(ostream
&file
,int phase
) {
475 typedef RangeList::const_iterator RLcIterator
;
476 ASSERT( moduleCodec(true) && moduleCodec(false) );
477 ASSERT( planeBlock
&& planeBlock
->ranges
&& planeBlock
->encoder
==this );
478 const RangeList
&ranges
= planeBlock
->ranges
->getRangeList();
479 ASSERT( !ranges
.empty() );
482 case 0: { // save the averages
484 vector
<int> averages
;
485 averages
.reserve(ranges
.size());
486 Quantizer::Average
quant( settingsInt(QuantStepLog_avg
) );
487 for (RLcIterator it
=ranges
.begin(); it
!=ranges
.end(); ++it
) {
488 ASSERT( *it
&& (*it
)->encoderData
);
490 const RangeInfo
*info
= static_cast<RangeInfo
*>( (*it
)->encoderData
);
491 averages
.push_back( quant
.quant(info
->qrAvg
) );
493 // pass it to the codec
494 moduleCodec(true)->setPossibilities( powers
[settingsInt(QuantStepLog_avg
)] );
495 moduleCodec(true)->encode( averages
, file
);
499 case 1: { // save the deviations
502 devs
.reserve(ranges
.size());
503 Quantizer::Deviation
quant( settingsInt(QuantStepLog_dev
) );
504 for (RLcIterator it
=ranges
.begin(); it
!=ranges
.end(); ++it
) {
505 ASSERT( *it
&& (*it
)->encoderData
);
507 const RangeInfo
*info
= static_cast<RangeInfo
*>( (*it
)->encoderData
);
508 int dev
= ( info
->domainID
>=0 ? quant
.quant(sqrt(info
->qrDev2
)) : 0 );
511 // pass it to the codec
512 moduleCodec(false)->setPossibilities( powers
[settingsInt(QuantStepLog_dev
)] );
513 moduleCodec(false)->encode( devs
, file
);
517 case 2: { // save the rest
518 BitWriter
stream(file
);
519 // put the inversion bits if inversion is allowed
520 if ( settingsInt(AllowedInversion
) )
521 for (RLcIterator it
=ranges
.begin(); it
!=ranges
.end(); ++it
) {
522 ASSERT( *it
&& (*it
)->encoderData
);
524 const RangeInfo
*info
= static_cast<RangeInfo
*>( (*it
)->encoderData
);
525 if ( info
->domainID
>= 0 )
526 stream
.putBits(info
->inverted
,1);
528 // put the rotation bits if rotations are allowed
529 if ( settingsInt(AllowedRotations
) )
530 for (RLcIterator it
=ranges
.begin(); it
!=ranges
.end(); ++it
) {
531 ASSERT( *it
&& (*it
)->encoderData
);
533 const RangeInfo
*info
= static_cast<RangeInfo
*>( (*it
)->encoderData
);
534 if ( info
->domainID
>= 0 ) {
535 ASSERT( 0<=info
->rotation
&& info
->rotation
<8 );
536 stream
.putBits( info
->rotation
, 3 );
539 // find out bits needed to store IDs of domains for every level
541 domBits
.resize( levelPoolInfos
.size() );
542 for (int i
=0; i
<(int)levelPoolInfos
.size(); ++i
) {
543 int count
= levelPoolInfos
[i
].empty() ? 0 : levelPoolInfos
[i
].back().indexBegin
;
546 domBits
[i
]= count
? log2ceil(count
) : 0;
548 // put the domain bits
549 for (RLcIterator it
=ranges
.begin(); it
!=ranges
.end(); ++it
) {
550 ASSERT( *it
&& (*it
)->encoderData
);
552 const RangeInfo
*info
= static_cast<RangeInfo
*>( (*it
)->encoderData
);
553 int domID
= info
->domainID
;
555 int bits
= domBits
[ (*it
)->level
];
556 ASSERT( 0<=domID
&& domID
<powers
[bits
] );
558 stream
.putBits( domID
, bits
);
567 void MStandardEncoder::readData(istream
&file
,int phase
) {
568 typedef RangeList::const_iterator RLcIterator
;
569 ASSERT( moduleCodec(true) && moduleCodec(false) );
570 ASSERT( planeBlock
&& planeBlock
->ranges
&& planeBlock
->encoder
==this );
571 const RangeList
&ranges
= planeBlock
->ranges
->getRangeList();
572 ASSERT( !ranges
.empty() );
575 case 0: { // create the infos and load the averages
576 // get the list of averages from the codec
577 vector
<int> averages
;
578 moduleCodec(true)->setPossibilities( powers
[settingsInt(QuantStepLog_avg
)] );
579 moduleCodec(true)->decode( file
, ranges
.size(), averages
);
580 // iterate the list, create infos and fill them with dequantized averages
581 Quantizer::Average
quant( settingsInt(QuantStepLog_avg
) );
582 for (RLcIterator it
=ranges
.begin(); it
!=ranges
.end(); ++it
) {
583 ASSERT( *it
&& !(*it
)->encoderData
);
585 RangeInfo
*info
= rangeInfoAlloc
.make();
586 (*it
)->encoderData
= info
;
587 info
->qrAvg
= quant
.dequant(averages
[it
-ranges
.begin()]);
588 DEBUG_ONLY( info
->bestSE
= -1; ) // SE not needed for decoding,saving,...
589 if ( !settingsInt(AllowedInversion
) )
590 info
->inverted
= false;
595 case 1: { // load the deviations
596 // get the list of deviations from the codec
598 moduleCodec(false)->setPossibilities( powers
[settingsInt(QuantStepLog_dev
)] );
599 moduleCodec(false)->decode( file
, ranges
.size(), devs
);
600 // iterate the list, create infos and fill the with dequantized deviations
601 Quantizer::Deviation
quant( settingsInt(QuantStepLog_dev
) );
602 for (RLcIterator it
=ranges
.begin(); it
!=ranges
.end(); ++it
) {
603 ASSERT( *it
&& (*it
)->encoderData
);
605 RangeInfo
*info
= static_cast<RangeInfo
*>( (*it
)->encoderData
);
606 int quantDev
= devs
[it
-ranges
.begin()];
608 info
->qrDev2
= sqr(quant
.dequant(quantDev
));
609 else { // it's a flat block
612 DEBUG_ONLY( info
->inverted
= false; )
613 ASSERT( info
->rotation
==-1 && info
->domainID
==-1 );
619 case 2: { // load the rest
620 BitReader
stream(file
);
621 // get the inversion bits if inversion is allowed
622 if ( settingsInt(AllowedInversion
) )
623 for (RLcIterator it
=ranges
.begin(); it
!=ranges
.end(); ++it
) {
624 ASSERT( *it
&& (*it
)->encoderData
);
626 RangeInfo
*info
= static_cast<RangeInfo
*>( (*it
)->encoderData
);
628 info
->inverted
= stream
.getBits(1);
630 // get the rotation bits if rotations are allowed
631 for (RLcIterator it
=ranges
.begin(); it
!=ranges
.end(); ++it
) {
632 ASSERT( *it
&& (*it
)->encoderData
);
634 RangeInfo
*info
= static_cast<RangeInfo
*>( (*it
)->encoderData
);
636 info
->rotation
= settingsInt(AllowedRotations
) ? stream
.getBits(3) : 0;
638 // find out bits needed to store IDs of domains for every level
639 vector
<int> domBits( levelPoolInfos
.size(), -1 );
640 // get the domain bits
641 for (RLcIterator it
=ranges
.begin(); it
!=ranges
.end(); ++it
) {
642 ASSERT( *it
&& (*it
)->encoderData
);
644 RangeInfo
*info
= static_cast<RangeInfo
*>( (*it
)->encoderData
);
647 int level
= (*it
)->level
;
648 int bits
= domBits
[level
];
650 // yet unused level -> initialize it and get the right bits
651 buildPoolInfos4aLevel(level
,planeBlock
->settings
->zoom
);
653 = log2ceil( levelPoolInfos
[level
].back().indexBegin
);
656 // get the domain ID, check it's OK and store it in the range's info
657 int domID
= stream
.getBits(bits
);
658 checkThrow( domID
< levelPoolInfos
[level
].back().indexBegin
);
659 info
->domainID
= domID
;
661 // initialize decoding accelerators for domain-to-range mappings
662 initRangeInfoAccelerators();
670 void MStandardEncoder::decodeAct( DecodeAct action
, int count
) {
672 ASSERT( planeBlock
&& planeBlock
->ranges
&& planeBlock
->encoder
==this );
673 const RangeList
&ranges
= planeBlock
->ranges
->getRangeList();
674 ASSERT( !ranges
.empty() );
681 planeBlock
->pixels
.fillSubMatrix
682 ( Block(0,0,planeBlock
->width
,planeBlock
->height
), 0.5f
);
683 planeBlock
->summers_invalidate();
688 // prepare the domains, iterate each range block
689 planeBlock
->domains
->fillPixelsInPools(*planeBlock
);
690 for (RangeList::const_iterator it
=ranges
.begin(); it
!=ranges
.end(); ++it
) {
691 const RangeInfo
&info
= *(const RangeInfo
*) (*it
)->encoderData
;
692 if ( info
.domainID
< 0 ) { // no domain - constant color
693 planeBlock
->pixels
.fillSubMatrix( **it
, info
.qrAvg
);
696 // get domain sums and the pixel count
698 info
.decAccel
.pool
->getSums(info
.decAccel
.domBlock
).unpack(dSum
,d2Sum
);
699 Real pixCount
= (*it
)->size();
701 Real linCoeff
= (info
.inverted
? -pixCount
: pixCount
)
702 * sqrt( info
.qrDev2
/ ( pixCount
*d2Sum
- sqr(dSum
) ) );
704 if ( !isnormal(linCoeff
) || !linCoeff
) {
705 planeBlock
->pixels
.fillSubMatrix( **it
, info
.qrAvg
);
708 Real constCoeff
= info
.qrAvg
- linCoeff
*dSum
/pixCount
;
710 using namespace MatrixWalkers
;
711 MulAddCopyChecked
<Real
> oper( linCoeff
, constCoeff
, 0, 1 );
712 walkOperateCheckRotate( Checked
<SReal
>(planeBlock
->pixels
, **it
), oper
713 , info
.decAccel
.pool
->pixels
, info
.decAccel
.domBlock
, info
.rotation
);
720 void MStandardEncoder::initRangeInfoAccelerators() {
721 // get references that are the same for all range blocks
722 const RangeList
&ranges
= planeBlock
->ranges
->getRangeList();
723 const ISquareDomains::PoolList
&pools
= planeBlock
->domains
->getPools();
724 int zoom
= planeBlock
->settings
->zoom
;
725 // iterate over the ranges (and their accelerators)
726 for ( RangeList::const_iterator it
=ranges
.begin(); it
!=ranges
.end(); ++it
) {
727 // get range level, reference to the range's info and to the level's pool infos
728 int level
= (*it
)->level
;
729 RangeInfo
&info
= *static_cast<RangeInfo
*>( (*it
)->encoderData
);
730 if ( info
.domainID
< 0 )
732 const PoolInfos
&poolInfos
= levelPoolInfos
[level
];
733 // build pool infos for the level (if neccesary), fill info's accelerators
734 if ( poolInfos
.empty() )
735 buildPoolInfos4aLevel(level
,zoom
), ASSERT( !poolInfos
.empty() );
736 info
.decAccel
.pool
= &getDomainData
737 ( **it
, pools
, poolInfos
, info
.domainID
, zoom
, info
.decAccel
.domBlock
);
738 // adjust domain's block if the range isn't regular
739 if ( !(*it
)->isRegular() )
740 info
.decAccel
.domBlock
= adjustDomainForIncompleteRange
741 ( **it
, info
.rotation
, info
.decAccel
.domBlock
);