00001 #include <memory>
00002
00003 #include "stdEncoder.h"
00004 #include "../fileUtil.h"
00005
00006 using namespace std;
00007
00009
00011 namespace Quantizer {
00013 inline int quantizeByPower(Real f,int scale,int possib) {
00014 ASSERT( f>=0 && f<=possib/(Real)powers[scale] );
00015 int result= (int)trunc(ldexp(f,scale));
00016 ASSERT( result>=0 && result<=possib );
00017 return result<possib ? result : --result;
00018 }
00020 inline Real dequantizeByPower(int i,int scale,int DEBUG_ONLY(possib)) {
00021 ASSERT( i>=0 && i<possib );
00022 Real result= ldexp(i+Real(0.5),-scale);
00023 ASSERT( result>=0 && result<= possib/(Real)powers[scale] );
00024 return result;
00025 }
00026
00027 class QuantBase {
00028 protected:
00029 int scale
00030 , possib;
00031 public:
00033 int quant(Real val) const
00034 { return quantizeByPower(val,scale,possib); }
00036 Real dequant(int i) const
00037 { return dequantizeByPower(i,scale,possib); }
00039 Real qRound(Real val) const
00040 { return dequant(quant(val)); }
00041 };
00042
00044 class Average: public QuantBase {
00045 public:
00046 Average(int possibLog2) {
00047 ASSERT(possibLog2>0);
00048
00049 scale= possibLog2;
00050 possib= powers[possibLog2];
00051 }
00052 };
00053
00055 class Deviation: public QuantBase {
00056 public:
00057 Deviation(int possibLog2) {
00058 ASSERT(possibLog2>0);
00059
00060 scale= possibLog2+1;
00061 possib= powers[possibLog2];
00062 }
00063 };
00064 }
00065
00066
00068 inline static Block adjustDomainForIncompleteRange( Block range, int rotation, Block domain ) {
00069
00070
00071
00072
00073
00074 ASSERT( 0<=rotation && rotation<8 );
00075 int rotID= rotation/2;
00076
00077 int xSize= range.width();
00078 int ySize= range.height();
00079
00080 int magic= rotID+rotation%2;
00081 if ( magic==1 || magic==3 )
00082 swap(xSize,ySize);
00083
00084 if ( rotID>1 )
00085 domain.y0= domain.yend-ySize;
00086 else
00087 domain.yend= domain.y0+ySize;
00088
00089 if ( rotID==1 || rotID==2 )
00090 domain.x0= domain.xend-xSize;
00091 else
00092 domain.xend= domain.x0+xSize;
00093
00094 return domain;
00095 }
00096
00098
00099 void MStdEncoder::initialize( IRoot::Mode mode, PlaneBlock &planeBlock_ ) {
00100 planeBlock= &planeBlock_;
00101
00102 planeBlock->domains->initPools(*planeBlock);
00103
00104 int maxLevel= 1 +log2ceil(max( planeBlock->width, planeBlock->height ));
00105
00106 levelPoolInfos.resize(maxLevel);
00107
00108 if (mode==IRoot::Encode) {
00109 typedef ISquareDomains::PoolList PoolList;
00110
00111 planeBlock->domains->fillPixelsInPools(*planeBlock);
00112 for_each( planeBlock->domains->getPools(), mem_fun_ref(&Pool::summers_makeValid) );
00113
00114 planeBlock->summers_makeValid();
00115
00116
00117 stdRangeSEs.resize(maxLevel+1);
00118 planeBlock->settings->moduleQ2SE->regularRangeErrors
00119 ( planeBlock->settings->quality, maxLevel+1, &stdRangeSEs.front() );
00120 }
00121 }
00122
00123
00124 namespace NOSPACE {
00125 struct LevelPoolInfo_indexComparator {
00126 typedef ISquareEncoder::LevelPoolInfo LevelPoolInfo;
00127 bool operator()( const LevelPoolInfo &a, const LevelPoolInfo &b )
00128 { return a.indexBegin < b.indexBegin; }
00129 };
00130 }
00131 MStdEncoder::PoolInfos::const_iterator MStdEncoder
00132 ::getPoolFromDomID( int domID, const PoolInfos &poolInfos ) {
00133 ASSERT( domID>=0 && domID<poolInfos.back().indexBegin );
00134
00135 PoolInfos::value_type toFind;
00136 toFind.indexBegin= domID;
00137 return upper_bound( poolInfos.begin(), poolInfos.end(), toFind
00138 , LevelPoolInfo_indexComparator() ) -1;
00139 }
00140
00141 const ISquareDomains::Pool& MStdEncoder::getDomainData
00142 ( const RangeNode &rangeBlock, const ISquareDomains::PoolList &pools
00143 , const PoolInfos &poolInfos, int domIndex, int zoom, Block &block ) {
00144
00145
00146 PoolInfos::const_iterator it= getPoolFromDomID( domIndex, poolInfos );
00147 const Pool &pool= pools[ it - poolInfos.begin() ];
00148
00149 int indexInPool= domIndex - it->indexBegin;
00150 ASSERT( indexInPool>=0 && indexInPool<(it+1)->indexBegin );
00151 int sizeNZ= powers[rangeBlock.level-zoom];
00152 int zoomFactor= powers[zoom];
00153
00154 int domsInCol= getCountForDensity( pool.height/zoomFactor, it->density, sizeNZ );
00155 block.x0= (indexInPool/domsInCol)*it->density*zoomFactor;
00156 block.y0= (indexInPool%domsInCol)*it->density*zoomFactor;
00157 block.xend= block.x0+powers[rangeBlock.level];
00158 block.yend= block.y0+powers[rangeBlock.level];
00159
00160 return pool;
00161 }
00162
00163
00164 namespace NOSPACE {
00165 typedef IStdEncPredictor::NewPredictorData StableInfo;
00166
00168 struct BestInfo: public IStdEncPredictor::Prediction {
00169 float error;
00170 bool inverted;
00171 #ifndef NDEBUG
00172 Real rdSum
00173 , dSum
00174 , d2Sum;
00175 #endif
00176
00178 BestInfo()
00179 : Prediction(), error( numeric_limits<float>::infinity() ) {}
00181 IStdEncPredictor::Prediction& prediction()
00182 { return *this; }
00183 };
00184 }
00185
00187 struct MStdEncoder::EncodingInfo {
00189 typedef bool (EncodingInfo::*ExactCompareProc)( Prediction prediction );
00190
00191 private:
00192 static const ExactCompareProc exactCompareArray[];
00193
00194 ExactCompareProc selectedProc;
00195 public:
00196 StableInfo stable;
00197 BestInfo best;
00198 float targetSE;
00199
00200 public:
00202 EncodingInfo()
00203 : selectedProc(0) {}
00204
00206 RangeInfo* initRangeInfo(RangeInfo *ri) const {
00207 ri->bestSE= best.error;
00208 ri->domainID= best.domainID;
00209 ri->rotation= best.rotation;
00210 ri->qrAvg= stable.qrAvg;
00211 ri->qrDev2= stable.qrDev2;
00212 ri->inverted= best.inverted;
00213 #ifndef NDEBUG
00214 ri->exact.avg= stable.rSum/stable.pixCount;
00215 ri->exact.dev2= stable.r2Sum/stable.pixCount - sqr(ri->exact.avg);
00216 ri->exact.linCoeff= ( stable.pixCount*best.rdSum - stable.rSum*best.dSum )
00217 / ( stable.pixCount*best.d2Sum - sqr(best.dSum) );
00218 ri->exact.constCoeff= ri->exact.avg - ri->exact.linCoeff*best.dSum/stable.pixCount;
00219 #endif
00220 return ri;
00221 }
00222
00224 void selectExactCompareProc() {
00225 selectedProc= exactCompareArray
00226 [((( stable.quantError *2
00227 + stable.allowInversion ) *2
00228 + stable.isRegular ) *2
00229 + (stable.maxLinCoeff2 >= 0) ) *2
00230 + (stable.bigScaleCoeff != 0)
00231 ];
00232 }
00233
00235 bool exactCompare(Prediction prediction)
00236 { return (this->* selectedProc)(prediction); }
00237
00238 private:
00240 template < bool quantErrors, bool allowInversion, bool isRegular
00241 , bool restrictMaxLinCoeff, bool bigScalePenalty >
00242 bool exactCompareProc( Prediction prediction );
00243 };
00244
00245 #define ALTERNATE_0(name,params...) name<params>
00246 #define ALTERNATE_1(name,params...) ALTERNATE_0(name,##params,false), ALTERNATE_0(name,##params,true)
00247 #define ALTERNATE_2(name,params...) ALTERNATE_1(name,##params,false), ALTERNATE_1(name,##params,true)
00248 #define ALTERNATE_3(name,params...) ALTERNATE_2(name,##params,false), ALTERNATE_2(name,##params,true)
00249 #define ALTERNATE_4(name,params...) ALTERNATE_3(name,##params,false), ALTERNATE_3(name,##params,true)
00250 #define ALTERNATE_5(name,params...) ALTERNATE_4(name,##params,false), ALTERNATE_4(name,##params,true)
00251 const MStdEncoder::EncodingInfo::ExactCompareProc MStdEncoder::EncodingInfo::exactCompareArray[]
00252 = {ALTERNATE_5(&MStdEncoder::EncodingInfo::exactCompareProc)};
00253 #undef ALTERNATE_0
00254 #undef ALTERNATE_1
00255 #undef ALTERNATE_2
00256 #undef ALTERNATE_3
00257 #undef ALTERNATE_4
00258 #undef ALTERNATE_5
00259
00260 template< bool quantErrors, bool allowInversion, bool isRegular
00261 , bool restrictMaxLinCoeff, bool bigScalePenalty >
00262 bool MStdEncoder::EncodingInfo::exactCompareProc( Prediction prediction ) {
00263 using namespace MatrixWalkers;
00264
00265 Block domBlock;
00266 const Pool &pool= getDomainData( *stable.rangeBlock, *stable.pools, *stable.poolInfos
00267 , prediction.domainID, 0, domBlock );
00268
00269 if (!isRegular)
00270 domBlock= adjustDomainForIncompleteRange
00271 ( *stable.rangeBlock, prediction.rotation, domBlock );
00272 Real dSum, d2Sum;
00273 pool.getSums(domBlock).unpack(dSum,d2Sum);
00274
00275 Real test= stable.pixCount*d2Sum - sqr(dSum);
00276 if (test<=0)
00277 return false;
00278 Real denom= 1/test;
00279
00280
00281 Real rdSum= walkOperateCheckRotate
00282 ( Checked<const SReal>(stable.rangePixels->pixels, *stable.rangeBlock), RDSummer<Real,SReal>()
00283 , pool.pixels, domBlock, prediction.rotation ) .result();
00284
00285 Real nRDs_RsDs= stable.pixCount*rdSum - stable.rSum*dSum;
00286
00287 if (!allowInversion)
00288 if (nRDs_RsDs<0)
00289 return false;
00290
00291 Real linCoeff2 DEBUG_ONLY(= numeric_limits<Real>::quiet_NaN() );
00292 if ( restrictMaxLinCoeff || bigScalePenalty )
00293 linCoeff2= stable.rnDev2 * denom;
00294 if (restrictMaxLinCoeff)
00295 if ( linCoeff2 > stable.maxLinCoeff2 )
00296 return false;
00297
00298 float optSE DEBUG_ONLY(= numeric_limits<Real>::quiet_NaN() );
00299
00300 if (quantErrors) {
00301 optSE= stable.qrAvg * ( stable.pixCount*stable.qrAvg - ldexp(stable.rSum,1) )
00302 + stable.r2Sum + stable.qrDev
00303 * ( stable.pixCount*stable.qrDev - ldexp( abs(nRDs_RsDs)*sqrt(denom), 1 ) );
00304 } else {
00305
00306 Real inner= stable.rnDev2 - stable.rnDev*abs(nRDs_RsDs)*sqrt(denom);
00307 optSE= ldexp( inner, 1 ) / stable.pixCount;
00308 }
00309
00310
00311 if (bigScalePenalty)
00312 optSE+= linCoeff2 * targetSE * pool.contrFactor * stable.bigScaleCoeff;
00313
00314
00315 if ( optSE < best.error ) {
00316 best.prediction()= prediction;
00317 best.error= optSE;
00318 best.inverted= nRDs_RsDs<0;
00319
00320 #ifndef NDEBUG
00321 best.rdSum= rdSum;
00322 best.dSum= dSum;
00323 best.d2Sum= d2Sum;
00324 #endif
00325
00326 return true;
00327 } else
00328 return false;
00329 }
00330
00331
00332 float MStdEncoder::findBestSE(const RangeNode &range,bool allowHigherSE) {
00333 ASSERT( planeBlock && !stdRangeSEs.empty() && !range.encoderData );
00334 const IColorTransformer::PlaneSettings *plSet= planeBlock->settings;
00335
00336
00337 EncodingInfo info;
00338
00339 info.stable.rangeBlock= ⦥
00340 info.stable.rangePixels= planeBlock;
00341 info.stable.pools= &planeBlock->domains->getPools();
00342
00343 ASSERT( range.level < (int)levelPoolInfos.size() );
00344 info.stable.poolInfos= &levelPoolInfos[range.level];
00345
00346 if ( info.stable.poolInfos->empty() ) {
00347 buildPoolInfos4aLevel(range.level);
00348 ASSERT( !info.stable.poolInfos->empty() );
00349 }
00350
00351 info.stable.allowRotations= settingsInt(AllowedRotations);
00352 info.stable.quantError= settingsInt(AllowedQuantError);
00353 info.stable.allowInversion= settingsInt(AllowedInversion);
00354 info.stable.isRegular= range.isRegular();
00355 {
00356 Real coeff= settingsFloat(MaxLinCoeff);
00357 info.stable.maxLinCoeff2= coeff==MaxLinCoeff_none ? -1 : sqr(coeff);
00358 }
00359 info.stable.bigScaleCoeff= settingsFloat(BigScaleCoeff);
00360
00361 planeBlock->getSums(range).unpack( info.stable.rSum, info.stable.r2Sum );
00362 info.stable.pixCount= range.size();
00363 info.stable.rnDev2= info.stable.pixCount*info.stable.r2Sum - sqr(info.stable.rSum);
00364 if (info.stable.rnDev2<0)
00365 info.stable.rnDev2= 0;
00366 info.stable.rnDev= sqrt(info.stable.rnDev2);
00367
00368 Real variance;
00369 {
00370 Quantizer::Average quantAvg( settingsInt(QuantStepLog_avg) );
00371 Quantizer::Deviation quantDev( settingsInt(QuantStepLog_dev) );
00372 Real average= info.stable.rSum / info.stable.pixCount;
00373 info.stable.qrAvg= quantAvg.qRound(average);
00374
00375 variance= info.stable.r2Sum/info.stable.pixCount - sqr(average);
00376 Real deviance= variance>0 ? sqrt(variance) : 0;
00377 int qrDev= quantDev.quant(deviance);
00378
00379 if ( !qrDev || range.level >= (int)levelPoolInfos.size()
00380 || info.stable.poolInfos->back().indexBegin <= 0 )
00381 goto returning;
00382 else {
00383 info.stable.qrDev= quantDev.dequant(qrDev);
00384 info.stable.qrDev2= sqr(info.stable.qrDev);
00385 }
00386 }
00387
00388 info.targetSE= info.best.error= info.stable.isRegular ? stdRangeSEs[range.level]
00389 : plSet->moduleQ2SE->rangeSE( plSet->quality, range.size() );
00390 ASSERT(info.targetSE>=0);
00391 if (allowHigherSE)
00392 info.best.error= numeric_limits<float>::infinity();
00393 info.selectExactCompareProc();
00394
00395 {
00396
00397 auto_ptr<IStdEncPredictor::IOneRangePredictor> predictor
00398 ( modulePredictor()->newPredictor(info.stable) );
00399 typedef IStdEncPredictor::Predictions Predictions;
00400 Predictions predicts;
00401
00402 float sufficientSE= info.targetSE*settingsFloat(SufficientSEq);
00403
00404 while ( !predictor->getChunk(info.best.error,predicts).empty() )
00405 for (Predictions::iterator it=predicts.begin(); it!=predicts.end(); ++it) {
00406 bool betterSE= info.exactCompare(*it);
00407 if ( betterSE && info.best.error<=sufficientSE )
00408 goto returning;
00409 }
00410 }
00411
00412 returning:
00413
00414 if ( info.best.domainID < 0 ) {
00415 info.stable.qrDev= info.stable.qrDev2= 0;
00416 info.best.error= info.stable.quantError
00417 ? info.stable.r2Sum + info.stable.qrAvg
00418 *( info.stable.pixCount*info.stable.qrAvg - ldexp(info.stable.rSum,1) )
00419 : variance*info.stable.pixCount;
00420 }
00421
00422 range.encoderData= info.initRangeInfo( new RangeInfo );
00423 return info.best.error;
00424 }
00425
00426 void MStdEncoder::buildPoolInfos4aLevel(int level) {
00427
00428 int domainCountLog2= planeBlock->settings->domainCountLog2;
00429 if ( settingsInt(AllowedRotations) )
00430 domainCountLog2-= 3;
00431
00432 vector<short> densities= planeBlock->domains->getLevelDensities(level,domainCountLog2);
00433
00434 vector<LevelPoolInfo> &poolInfos= levelPoolInfos[level];
00435 ASSERT( poolInfos.empty() );
00436 const ISquareDomains::PoolList &pools= planeBlock->domains->getPools();
00437 int zoom= planeBlock->settings->zoom;
00438
00439 int domainSizeNZ= powers[level-zoom];
00440 int poolCount= pools.size();
00441 poolInfos.resize(poolCount+1);
00442
00443 int domCount= poolInfos[0].indexBegin= 0;
00444 for (int i=0; i<poolCount; ++i) {
00445 int dens= poolInfos[i].density= densities[i];
00446 ASSERT(dens>=0);
00447 if (dens)
00448 domCount+= getCountForDensity2D( rShift(pools[i].width,zoom)
00449 , rShift(pools[i].height,zoom), dens, domainSizeNZ );
00450 poolInfos[i+1].indexBegin= domCount;
00451 }
00452 poolInfos[poolCount].density= -1;
00453 }
00454
00455 void MStdEncoder::writeSettings(ostream &file) {
00456 ASSERT( moduleCodec(true) && moduleCodec(false) );
00457
00458 put<Uchar>( file, settingsInt(AllowedRotations) );
00459 put<Uchar>( file, settingsInt(AllowedInversion) );
00460 put<Uchar>( file, settingsInt(QuantStepLog_avg) );
00461 put<Uchar>( file, settingsInt(QuantStepLog_dev) );
00462
00463 file_saveModuleType( file, ModuleCodecAvg );
00464 file_saveModuleType( file, ModuleCodecDev );
00465
00466 moduleCodec(true)->writeSettings(file);
00467 moduleCodec(false)->writeSettings(file);
00468 }
00469 void MStdEncoder::readSettings(istream &file) {
00470 ASSERT( !modulePredictor() && !moduleCodec(true) && !moduleCodec(false) );
00471
00472 settingsInt(AllowedRotations)= get<Uchar>(file);
00473 settingsInt(AllowedInversion)= get<Uchar>(file);
00474 settingsInt(QuantStepLog_avg)= get<Uchar>(file);
00475 settingsInt(QuantStepLog_dev)= get<Uchar>(file);
00476
00477 file_loadModuleType( file, ModuleCodecAvg );
00478 file_loadModuleType( file, ModuleCodecDev );
00479
00480 moduleCodec(true)->readSettings(file);
00481 moduleCodec(false)->readSettings(file);
00482 }
00483
00484 void MStdEncoder::writeData(ostream &file,int phase) {
00485 typedef RangeList::const_iterator RLcIterator;
00486 ASSERT( moduleCodec(true) && moduleCodec(false) );
00487 ASSERT( planeBlock && planeBlock->ranges && planeBlock->encoder==this );
00488 const RangeList &ranges= planeBlock->ranges->getRangeList();
00489 ASSERT( !ranges.empty() );
00490
00491 switch(phase) {
00492 case 0: {
00493
00494 vector<int> averages;
00495 averages.reserve(ranges.size());
00496 Quantizer::Average quant( settingsInt(QuantStepLog_avg) );
00497 for (RLcIterator it=ranges.begin(); it!=ranges.end(); ++it) {
00498 ASSERT( *it && (*it)->encoderData );
00499 STREAM_POS(file);
00500 const RangeInfo *info= RangeInfo::get(*it);
00501 averages.push_back( quant.quant(info->qrAvg) );
00502 }
00503
00504 moduleCodec(true)->setPossibilities( powers[settingsInt(QuantStepLog_avg)] );
00505 moduleCodec(true)->encode( averages, file );
00506 break;
00507 }
00508
00509 case 1: {
00510
00511 vector<int> devs;
00512 devs.reserve(ranges.size());
00513 Quantizer::Deviation quant( settingsInt(QuantStepLog_dev) );
00514 for (RLcIterator it=ranges.begin(); it!=ranges.end(); ++it) {
00515 ASSERT( *it && (*it)->encoderData );
00516 STREAM_POS(file);
00517 const RangeInfo *info= RangeInfo::get(*it);
00518 int dev= ( info->domainID>=0 ? quant.quant(sqrt(info->qrDev2)) : 0 );
00519 devs.push_back(dev);
00520 }
00521
00522 moduleCodec(false)->setPossibilities( powers[settingsInt(QuantStepLog_dev)] );
00523 moduleCodec(false)->encode( devs, file );
00524 break;
00525 }
00526
00527 case 2: {
00528 BitWriter stream(file);
00529
00530 if ( settingsInt(AllowedInversion) )
00531 for (RLcIterator it=ranges.begin(); it!=ranges.end(); ++it) {
00532 ASSERT( *it && (*it)->encoderData );
00533 STREAM_POS(file);
00534 const RangeInfo *info= RangeInfo::get(*it);
00535 if ( info->domainID >= 0 )
00536 stream.putBits(info->inverted,1);
00537 }
00538
00539 if ( settingsInt(AllowedRotations) )
00540 for (RLcIterator it=ranges.begin(); it!=ranges.end(); ++it) {
00541 ASSERT( *it && (*it)->encoderData );
00542 STREAM_POS(file);
00543 const RangeInfo *info= RangeInfo::get(*it);
00544 if ( info->domainID >= 0 ) {
00545 ASSERT( 0<=info->rotation && info->rotation<8 );
00546 stream.putBits( info->rotation, 3 );
00547 }
00548 }
00549
00550 vector<int> domBits;
00551 domBits.resize( levelPoolInfos.size() );
00552 for (int i=0; i<(int)levelPoolInfos.size(); ++i) {
00553 int count= levelPoolInfos[i].empty() ? 0 : levelPoolInfos[i].back().indexBegin;
00554 ASSERT(count>=0);
00555 STREAM_POS(file);
00556 domBits[i]= count ? log2ceil(count) : 0;
00557 }
00558
00559 for (RLcIterator it=ranges.begin(); it!=ranges.end(); ++it) {
00560 ASSERT( *it && (*it)->encoderData );
00561 STREAM_POS(file);
00562 const RangeInfo *info= RangeInfo::get(*it);
00563 int domID= info->domainID;
00564 if ( domID >= 0 ) {
00565 int bits= domBits[ (*it)->level ];
00566 ASSERT( 0<=domID && domID<powers[bits] );
00567 if (bits>0)
00568 stream.putBits( domID, bits );
00569 }
00570 }
00571 break;
00572 }
00573 default:
00574 ASSERT(false);
00575 }
00576 }
00577 void MStdEncoder::readData(istream &file,int phase) {
00578 typedef RangeList::const_iterator RLcIterator;
00579 ASSERT( moduleCodec(true) && moduleCodec(false) );
00580 ASSERT( planeBlock && planeBlock->ranges && planeBlock->encoder==this );
00581 const RangeList &ranges= planeBlock->ranges->getRangeList();
00582 ASSERT( !ranges.empty() );
00583
00584 switch(phase) {
00585 case 0: {
00586
00587 vector<int> averages;
00588 moduleCodec(true)->setPossibilities( powers[settingsInt(QuantStepLog_avg)] );
00589 moduleCodec(true)->decode( file, ranges.size(), averages );
00590
00591 Quantizer::Average quant( settingsInt(QuantStepLog_avg) );
00592 for (RLcIterator it=ranges.begin(); it!=ranges.end(); ++it) {
00593 ASSERT( *it && !(*it)->encoderData );
00594 STREAM_POS(file);
00595 RangeInfo *info= new RangeInfo;
00596 (*it)->encoderData= info;
00597 info->qrAvg= quant.dequant(averages[it-ranges.begin()]);
00598 DEBUG_ONLY( info->bestSE= -1; )
00599 if ( !settingsInt(AllowedInversion) )
00600 info->inverted= false;
00601 }
00602 break;
00603 }
00604
00605 case 1: {
00606
00607 vector<int> devs;
00608 moduleCodec(false)->setPossibilities( powers[settingsInt(QuantStepLog_dev)] );
00609 moduleCodec(false)->decode( file, ranges.size(), devs );
00610
00611 Quantizer::Deviation quant( settingsInt(QuantStepLog_dev) );
00612 for (RLcIterator it=ranges.begin(); it!=ranges.end(); ++it) {
00613 ASSERT( *it && (*it)->encoderData );
00614 STREAM_POS(file);
00615 RangeInfo *info= RangeInfo::get(*it);
00616 int quantDev= devs[it-ranges.begin()];
00617 if (quantDev)
00618 info->qrDev2= sqr(quant.dequant(quantDev));
00619 else {
00620 info->qrDev2= 0;
00621
00622 DEBUG_ONLY( info->inverted= false; )
00623 ASSERT( info->rotation==-1 && info->domainID==-1 );
00624 }
00625 }
00626 break;
00627 }
00628
00629 case 2: {
00630 BitReader stream(file);
00631
00632 if ( settingsInt(AllowedInversion) )
00633 for (RLcIterator it=ranges.begin(); it!=ranges.end(); ++it) {
00634 ASSERT( *it && (*it)->encoderData );
00635 STREAM_POS(file);
00636 RangeInfo *info= RangeInfo::get(*it);
00637 if (info->qrDev2)
00638 info->inverted= stream.getBits(1);
00639 }
00640
00641 for (RLcIterator it=ranges.begin(); it!=ranges.end(); ++it) {
00642 ASSERT( *it && (*it)->encoderData );
00643 STREAM_POS(file);
00644 RangeInfo *info= RangeInfo::get(*it);
00645 if (info->qrDev2)
00646 info->rotation= settingsInt(AllowedRotations) ? stream.getBits(3) : 0;
00647 }
00648
00649 vector<int> domBits( levelPoolInfos.size(), -1 );
00650
00651 for (RLcIterator it=ranges.begin(); it!=ranges.end(); ++it) {
00652 ASSERT( *it && (*it)->encoderData );
00653 STREAM_POS(file);
00654 RangeInfo *info= RangeInfo::get(*it);
00655 if (!info->qrDev2)
00656 continue;
00657 int level= (*it)->level;
00658 int bits= domBits[level];
00659 if (bits<0) {
00660
00661 buildPoolInfos4aLevel(level);
00662 bits= domBits[level]
00663 = log2ceil( levelPoolInfos[level].back().indexBegin );
00664 ASSERT( bits>0 );
00665 }
00666
00667 int domID= stream.getBits(bits);
00668 checkThrow( domID < levelPoolInfos[level].back().indexBegin );
00669 info->domainID= domID;
00670 }
00671
00672 initRangeInfoAccelerators();
00673 break;
00674 }
00675 default:
00676 ASSERT(false);
00677 }
00678 }
00679
00680 void MStdEncoder::decodeAct( DecodeAct action, int count ) {
00681
00682 ASSERT( planeBlock && planeBlock->ranges && planeBlock->encoder==this );
00683 const RangeList &ranges= planeBlock->ranges->getRangeList();
00684 ASSERT( !ranges.empty() );
00685
00686 switch (action) {
00687 default:
00688 ASSERT(false);
00689 case Clear:
00690 ASSERT(count==1);
00691 planeBlock->pixels.fillSubMatrix
00692 ( Block(0,0,planeBlock->width,planeBlock->height), 0.5f );
00693 planeBlock->summers_invalidate();
00694 break;
00695 case Iterate:
00696 ASSERT(count>0);
00697 do {
00698
00699 planeBlock->domains->fillPixelsInPools(*planeBlock);
00700 for (RangeList::const_iterator it=ranges.begin(); it!=ranges.end(); ++it) {
00701 const RangeInfo &info= *RangeInfo::get(*it);
00702 if ( info.domainID < 0 ) {
00703 planeBlock->pixels.fillSubMatrix( **it, info.qrAvg );
00704 continue;
00705 }
00706
00707 Real dSum, d2Sum;
00708 info.decAccel.pool->summers_makeValid();
00709 info.decAccel.pool->getSums(info.decAccel.domBlock).unpack(dSum,d2Sum);
00710 Real pixCount= (*it)->size();
00711
00712 Real linCoeff= (info.inverted ? -pixCount : pixCount)
00713 * sqrt( info.qrDev2 / ( pixCount*d2Sum - sqr(dSum) ) );
00714 if ( !isnormal(linCoeff) || !linCoeff ) {
00715 planeBlock->pixels.fillSubMatrix( **it, info.qrAvg );
00716 continue;
00717 }
00718 Real constCoeff= info.qrAvg - linCoeff*dSum/pixCount;
00719
00720 using namespace MatrixWalkers;
00721 MulAddCopyChecked<Real> oper( linCoeff, constCoeff, 0, 1 );
00722 walkOperateCheckRotate( Checked<SReal>(planeBlock->pixels, **it), oper
00723 , info.decAccel.pool->pixels, info.decAccel.domBlock, info.rotation );
00724 }
00725 } while (--count);
00726 break;
00727 }
00728 }
00729
00730 void MStdEncoder::initRangeInfoAccelerators() {
00731
00732 const RangeList &ranges= planeBlock->ranges->getRangeList();
00733 const ISquareDomains::PoolList &pools= planeBlock->domains->getPools();
00734 int zoom= planeBlock->settings->zoom;
00735
00736 for ( RangeList::const_iterator it=ranges.begin(); it!=ranges.end(); ++it ) {
00737
00738 int level= (*it)->level;
00739 RangeInfo &info= *RangeInfo::get(*it);
00740 if ( info.domainID < 0 )
00741 continue;
00742 const PoolInfos &poolInfos= levelPoolInfos[level];
00743
00744 if ( poolInfos.empty() )
00745 buildPoolInfos4aLevel(level), ASSERT( !poolInfos.empty() );
00746 info.decAccel.pool= &getDomainData
00747 ( **it, pools, poolInfos, info.domainID, zoom, info.decAccel.domBlock );
00748
00749 if ( !(*it)->isRegular() )
00750 info.decAccel.domBlock= adjustDomainForIncompleteRange
00751 ( **it, info.rotation, info.decAccel.domBlock );
00752 }
00753 }