00001 #include "quadTree.h"
00002 #include "../fileUtil.h"
00003
00004 using namespace std;
00005
00008 struct MQuadTree::NodeExtremes {
00009 int min, max;
00010
00011 NodeExtremes()
00012 : min( numeric_limits<int>::infinity() ), max( -numeric_limits<int>::infinity() ) {}
00013 void operator()(const MQuadTree::RangeNode *node) {
00014 int now= node->level;
00015 if (now<min)
00016 min= now;
00017 if (now>max)
00018 max= now;
00019 }
00020 };
00021
00022
00023 void MQuadTree::encode(const PlaneBlock &toEncode) {
00024 ASSERT( !root && fringe.empty() && toEncode.ranges==this && toEncode.isReady() );
00025 DEBUG_ONLY( planeBlock= &toEncode; )
00026 zoom= 0;
00027
00028 if ( heuristicAllowed() )
00029 toEncode.summers_makeValid();
00030
00031 root= new Node( Block(0,0,toEncode.width,toEncode.height) );
00032 root->encode(toEncode);
00033
00034 root->getHilbertList(fringe);
00035 toEncode.encoder->finishEncoding();
00036 }
00037
00038 void MQuadTree::writeData(ostream &file) {
00039 ASSERT( !fringe.empty() && root );
00040
00041 NodeExtremes extremes= for_each( fringe, NodeExtremes() );
00042 put<Uchar>(file,extremes.min-zoom);
00043 put<Uchar>(file,extremes.max-zoom);
00044
00045 BitWriter bitWriter(file);
00046 root->toFile(bitWriter,extremes);
00047 }
00048
00049 void MQuadTree::readData_buildRanges(istream &file,const PlaneBlock &block) {
00050 ASSERT( fringe.empty() && !root );
00051 DEBUG_ONLY( planeBlock= █ )
00052 zoom= block.settings->zoom;
00053
00054 NodeExtremes extremes;
00055 extremes.min= get<Uchar>(file)+zoom;
00056 extremes.max= get<Uchar>(file)+zoom;
00057
00058 BitReader bitReader(file);
00059 root= new Node( Block(0,0,block.width,block.height) );
00060 root->fromFile(bitReader,extremes);
00061
00062 root->getHilbertList(fringe);
00063 }
00064
00065
00067
00068 void MQuadTree::Node::disconnect() {
00069
00070 if ( father->son == this )
00071 father->son= ( brother==this ? 0 : brother );
00072 Node *prev= this;
00073 while (prev->brother != this)
00074 prev= prev->brother;
00075 prev->brother= this->brother;
00076 }
00077
00078 void MQuadTree::Node::deleteSons() {
00079
00080 if (!son)
00081 return;
00082 Node *now= son;
00083 do {
00084 Node *next= now->brother;
00085 delete now;
00086 now= next;
00087 } while (now!=son);
00088 son= 0;
00089 }
00090
00091 void MQuadTree::Node::divide() {
00092
00093 ASSERT(!son);
00094 short size= powers[level-1];
00095 short xmid= min<short>( x0+size, xend );
00096 short ymid= min<short>( y0+size, yend );
00097
00098 son= new Node( Block(x0,y0,xmid,ymid), this, 0 );
00099 Node *last= son;
00100
00101 if (xmid < xend) {
00102 last= new Node( Block(xmid,y0,xend,ymid), this, last );
00103
00104 if (ymid < yend)
00105 last= new Node( Block(xmid,ymid,xend,yend), this, last );
00106 }
00107
00108 if (ymid < yend)
00109 last= new Node( Block(x0,ymid,xmid,yend), this, last );
00110
00111 son->brother= last;
00112 }
00113
00114 void MQuadTree::Node::getHilbertList(RangeList &list,char start,char cw) {
00115 if (!son) {
00116 list.push_back(this);
00117 return;
00118 }
00119 Node *now= son
00120 , *sons[4]= {0,0,0,0};
00121
00122 do {
00123 int pos= 0;
00124 if ( now->x0 > x0 )
00125 ++pos;
00126 if ( now->y0 > y0 )
00127 pos= 3-pos;
00128 sons[pos]= now;
00129 } while ( (now=now->brother) != son );
00130
00131 int pos= (start%= 4);
00132 if (sons[pos])
00133 sons[pos]->getHilbertList(list,start,-cw);
00134
00135 for (int i=0; i<2; ++i) {
00136 pos= (pos+4+cw)%4;
00137 if (sons[pos])
00138 sons[pos]->getHilbertList(list,start,cw);
00139 }
00140
00141 pos= (pos+4+cw)%4;
00142 if (sons[pos])
00143 sons[pos]->getHilbertList(list,start+2,-cw);
00144 }
00145
00146 int MQuadTree::Node::getSonCount() const {
00147 if (!son)
00148 return 0;
00149 Node *now= son->brother;
00150 int count= 1;
00151 while (now!=son) {
00152 now= now->brother;
00153 ++count;
00154 }
00155 return count;
00156 }
00157
00158 bool MQuadTree::Node::encode(const PlaneBlock &toEncode) {
00159 if (*toEncode.settings->updateInfo.terminate)
00160 throw exception();
00161
00162 MQuadTree *mod= debugCast<MQuadTree*>(toEncode.ranges);
00163 ASSERT( mod && level>=mod->minLevel() );
00164 const IColorTransformer::PlaneSettings &plSet= *toEncode.settings;
00165 int pixCount= size();
00166
00167 if ( level == mod->minLevel() ) {
00168
00169 toEncode.encoder->findBestSE(*this,true);
00170 plSet.updateInfo.incProgress(pixCount);
00171 return false;
00172 }
00173
00174
00175 float maxSE= plSet.moduleQ2SE->rangeSE( plSet.quality, pixCount );
00176 bool tryEncode= true;
00177
00178 if ( level > mod->maxLevel() )
00179 tryEncode= false;
00180 else {
00181
00182 if ( mod->heuristicAllowed() ) {
00183 Real rSum, r2Sum;
00184 toEncode.getSums(*this).unpack(rSum,r2Sum);
00185 if ( estimateSE(rSum,r2Sum,pixCount,level) > maxSE )
00186 tryEncode= false;
00187 }
00188
00189 if ( tryEncode && toEncode.encoder->findBestSE(*this) <= maxSE ) {
00190 plSet.updateInfo.incProgress(pixCount);
00191 return false;
00192 }
00193 #ifndef NDEBUG
00194 else
00195 ++debugCast<MQuadTree*>(toEncode.ranges)->badTries;
00196 #endif
00197 }
00198
00199 divide();
00200 bool aSonDivided= false;
00201 Node *now= son;
00202 do {
00203 bool divided= now->encode(toEncode);
00204 aSonDivided= aSonDivided || divided;
00205 } while ( (now=now->brother) != son );
00206
00207 if ( aSonDivided || tryEncode || level > mod->maxLevel() )
00208 return true;
00209
00210 if ( toEncode.encoder->findBestSE(*this) <= maxSE ) {
00211 #ifndef NDEBUG
00212 ++debugCast<MQuadTree*>(toEncode.ranges)->badDivides;
00213 #endif
00214 deleteSons();
00215 return false;
00216 } else {
00217 #ifndef NDEBUG
00218 ++debugCast<MQuadTree*>(toEncode.ranges)->triedMerges;
00219 #endif
00220 return true;
00221 }
00222 }
00223
00224 void MQuadTree::Node::toFile(BitWriter &file,NodeExtremes extremes) {
00225 if (son) {
00226
00227 if (level<=extremes.max)
00228 file.putBits(1,1);
00229
00230 Node *now= son;
00231 do
00232 now->toFile(file,extremes);
00233 while ( (now= now->brother) != son );
00234 } else
00235
00236 if (level>extremes.min)
00237 file.putBits(0,1);
00238 }
00239
00240 void MQuadTree::Node::fromFile(BitReader &file,NodeExtremes extremes) {
00241
00242 bool div= level>extremes.max || ( level>extremes.min && file.getBits(1) ) ;
00243 if (div) {
00244 divide();
00245 Node *now= son;
00246 do
00247 now->fromFile(file,extremes);
00248 while ( (now=now->brother) != son );
00249 }
00250 }