2 #include "../fileUtil.h"
6 /** Struct for computing (acts as a functor) and storing max.\ and min.\
7 * levels of leaf range blocks */
8 struct MQuadTree::NodeExtremes
{
12 : min( numeric_limits
<int>::max() ), max( numeric_limits
<int>::min() ) {}
13 void operator()(const MQuadTree::RangeNode
*node
) {
23 void MQuadTree::encode(const PlaneBlock
&toEncode
) {
24 ASSERT( !root
&& fringe
.empty() && toEncode
.ranges
==this && toEncode
.isReady() );
25 DEBUG_ONLY( planeBlock
= &toEncode
; )
27 // if allowed, prepare accelerators for heuristic dividing
28 if ( heuristicAllowed() )
29 toEncode
.summers_makeValid();
30 // create a new root, encode it via a recursive routine
31 root
= new Node( Block(0,0,toEncode
.width
,toEncode
.height
) );
32 root
->encode(toEncode
);
33 // generate the fringe, let the encoder process it
34 root
->getHilbertList(fringe
);
35 toEncode
.encoder
->finishEncoding();
38 void MQuadTree::writeData(ostream
&file
) {
39 ASSERT( !fringe
.empty() && root
);
40 // put in the stream the minimal and the maximal used level
41 NodeExtremes extremes
= for_each( fringe
, NodeExtremes() );
42 put
<Uchar
>(file
,extremes
.min
-zoom
);
43 put
<Uchar
>(file
,extremes
.max
-zoom
);
44 // put the tree structure in the stream
45 BitWriter
bitWriter(file
);
46 root
->toFile(bitWriter
,extremes
);
49 void MQuadTree::readData_buildRanges(istream
&file
,const PlaneBlock
&block
) {
50 ASSERT( fringe
.empty() && !root
);
51 DEBUG_ONLY( planeBlock
= &block
; )
52 zoom
= block
.settings
->zoom
;
53 // get from the stream the minimal and the maximal used level
54 NodeExtremes extremes
;
55 extremes
.min
= get
<Uchar
>(file
)+zoom
;
56 extremes
.max
= get
<Uchar
>(file
)+zoom
;
57 // build the range tree
58 BitReader
bitReader(file
);
59 root
= new Node( Block(0,0,block
.width
,block
.height
) );
60 root
->fromFile(bitReader
,extremes
);
61 // generate the fringe of the range tree
62 root
->getHilbertList(fringe
);
66 //// MQuadTree::Node class
68 void MQuadTree::Node::disconnect() {
69 // disconnects itself from its brothers in the circle
70 if ( father
->son
== this )
71 father
->son
= ( brother
==this ? 0 : brother
);
73 while (prev
->brother
!= this)
75 prev
->brother
= this->brother
;
78 void MQuadTree::Node::deleteSons() {
84 Node
*next
= now
->brother
;
91 void MQuadTree::Node::divide() {
92 // check against dividing already divided self
94 short size
= powers
[level
-1];
95 short xmid
= min
<short>( x0
+size
, xend
);
96 short ymid
= min
<short>( y0
+size
, yend
);
97 // top-left (don't know the brother yet, using 0)
98 son
= new Node( Block(x0
,y0
,xmid
,ymid
), this, 0 );
102 last
= new Node( Block(xmid
,y0
,xend
,ymid
), this, last
);
105 last
= new Node( Block(xmid
,ymid
,xend
,yend
), this, last
);
109 last
= new Node( Block(x0
,ymid
,xmid
,yend
), this, last
);
114 void MQuadTree::Node::getHilbertList(RangeList
&list
,char start
,char cw
) {
116 list
.push_back(this);
120 , *sons
[4]= {0,0,0,0};
121 // categorize sons by their position into sons[0-3] - clockwise from top-left
129 } while ( (now
=now
->brother
) != son
);
130 // recurse on the son that is the first on the Hilbert curve (if it's present)
131 int pos
= (start
%= 4);
133 sons
[pos
]->getHilbertList(list
,start
,-cw
);
134 // recurse on the second and the third son
135 for (int i
=0; i
<2; ++i
) {
138 sons
[pos
]->getHilbertList(list
,start
,cw
);
140 // recurse on the last son
143 sons
[pos
]->getHilbertList(list
,start
+2,-cw
);
146 int MQuadTree::Node::getSonCount() const {
149 Node
*now
= son
->brother
;
158 bool MQuadTree::Node::encode(const PlaneBlock
&toEncode
) {
159 if (*toEncode
.settings
->updateInfo
.terminate
)
162 MQuadTree
*mod
= debugCast
<MQuadTree
*>(toEncode
.ranges
);
163 ASSERT( mod
&& level
>=mod
->minLevel() );
164 const IColorTransformer::PlaneSettings
&plSet
= *toEncode
.settings
;
165 int pixCount
= size();
166 // check for minimal level -> cannot be divided, find the best domain
167 if ( level
== mod
->minLevel() ) {
168 // try to find the best mapping, not restricting the max.\ SE and exit
169 toEncode
.encoder
->findBestSE(*this,true);
170 plSet
.updateInfo
.incProgress(pixCount
);
174 /// \todo regular ranges optimization
175 float maxSE
= plSet
.moduleQ2SE
->rangeSE( plSet
.quality
, pixCount
);
176 bool tryEncode
= true;
178 if ( level
> mod
->maxLevel() )
181 // if heuirstic dividing is allowed and signals dividing, don't try to encode
182 if ( mod
->heuristicAllowed() ) {
184 toEncode
.getSums(*this).unpack(rSum
,r2Sum
);
185 if ( estimateSE(rSum
,r2Sum
,pixCount
,level
) > maxSE
)
188 // if we decided to try to encode, do it and return if the quality is sufficient
189 if ( tryEncode
&& toEncode
.encoder
->findBestSE(*this) <= maxSE
) {
190 plSet
.updateInfo
.incProgress(pixCount
);
194 else // tried to encode, but unsuccessfully and forced to be divided
195 ++debugCast
<MQuadTree
*>(toEncode
.ranges
)->badTries
;
198 // the range needs to be divided, try to encode the sons
200 bool aSonDivided
= false;
202 do {// if any of the sons is divided, set tryEncode to true
203 bool divided
= now
->encode(toEncode
);
204 aSonDivided
= aSonDivided
|| divided
;
205 } while ( (now
=now
->brother
) != son
);
206 // if (I unsuccessfully tried to encode or a son was divided) or (I have too big level), return
207 if ( aSonDivided
|| tryEncode
|| level
> mod
->maxLevel() )
209 // this range still has a chance, try to encode it
210 if ( toEncode
.encoder
->findBestSE(*this) <= maxSE
) {
212 ++debugCast
<MQuadTree
*>(toEncode
.ranges
)->badDivides
;
218 ++debugCast
<MQuadTree
*>(toEncode
.ranges
)->triedMerges
;
224 void MQuadTree::Node::toFile(BitWriter
&file
,NodeExtremes extremes
) {
227 if (level
<=extremes
.max
)
232 now
->toFile(file
,extremes
);
233 while ( (now
= now
->brother
) != son
);
235 // Node isn't divided
236 if (level
>extremes
.min
)
240 void MQuadTree::Node::fromFile(BitReader
&file
,NodeExtremes extremes
) {
241 // should I be divided ?
242 bool div
= level
>extremes
.max
|| ( level
>extremes
.min
&& file
.getBits(1) ) ;
247 now
->fromFile(file
,extremes
);
248 while ( (now
=now
->brother
) != son
);