1 #include "interfaces.h"
4 #include "modules/root.h"
5 #include "modules/squarePixels.h"
6 #include "modules/stdEncoder.h"
7 #include "modules/quadTree.h"
8 #include "modules/stdDomains.h"
9 #include "modules/saupePredictor.h"
15 #include <QTableWidget>
21 QWidget
* MRoot::debugModule(QPixmap
&pixmap
,const QPoint
&click
) {
22 // create a new modeless dialog window
23 QDialog
*dlg
= new QDialog
;
25 // add a laid-out single widget created by IShapeTransformer
26 ( new QVBoxLayout(dlg
) )->addWidget( moduleShape()->debugModule(pixmap
,click
) );
30 QWidget
* MSquarePixels::debugModule(QPixmap
&pixmap
,const QPoint
&click
) {
31 // create a tab widget
32 QTabWidget
*tabs
= new QTabWidget
;
33 // fill one tab for every job by three sub-tabs with the three modules
34 for (int i
=0; i
<(int)jobs
.size(); ++i
) {
35 if ( jobs
[i
].ranges
->getRangeList().size() == 1 )
37 QTabWidget
*tabs2
= new QTabWidget
;
38 tabs2
->addTab( jobs
[i
].encoder
->debugModule(pixmap
,click
) , "Encoder" );
39 tabs2
->addTab( jobs
[i
].ranges
->debugModule(pixmap
,click
), "Ranges" );
40 tabs2
->addTab( jobs
[i
].domains
->debugModule(pixmap
,click
), "Domains" );
42 tabs
->addTab( tabs2
, QString("Job %1").arg(i
+1) );
49 struct RangeInfoAccumulator
{
50 const ISquareDomains::PoolList
*pools
;
52 vector
<int> poolCounts
, levelCounts
;
54 RangeInfoAccumulator(const ISquareDomains::PoolList
&poolList
)
55 : pools( &poolList
), poolCounts( pools
->size(), 0 ), levelCounts( 10, 0 ) {
56 for (int i
=0; i
<9; ++i
)
60 void operator()(const ISquareRanges::RangeNode
*range
) {
61 const MStandardEncoder::RangeInfo
&info
62 = static_cast<MStandardEncoder::RangeInfo
&>( *range
->encoderData
);
63 // increment the counts of ranges on this rotation and level
64 ++rotCounts
[info
.rotation
+1];
65 ++levelCounts
.at(range
->level
);
66 // find and increment the pool of the range's domain (if exists)
67 if ( info
.rotation
>=0 ) {
68 int index
= info
.decAccel
.pool
- &*pools
->begin() ;
69 ASSERT( index
>=0 && index
<(int)pools
->size() );
73 }; // RangeAccumulator struct
75 const ISquareRanges::RangeNode
* findRangeOnPoint
76 ( const ISquareRanges::RangeList
&ranges
, const QPoint
&click
) {
77 int x
= click
.x(), y
= click
.y();
78 ISquareRanges::RangeList::const_iterator it
;
79 for (it
=ranges
.begin(); it
!=ranges
.end(); ++it
) {
81 if ( b
.x0
<=x
&& b
.y0
<=y
&& b
.xend
>x
&& b
.yend
>y
)
84 ASSERT(false); return 0;
89 static void addFramedImage(QLayout
*layout
,const QImage
&image
) {
90 QLabel
*label
= new QLabel
;
91 label
->setPixmap( QPixmap::fromImage(image
) );
92 label
->setFrameStyle( QFrame::Plain
| QFrame::Box
); // to have a thin frame
93 label
->setSizePolicy( QSizePolicy() ); // to have the frame exatly around the image
94 layout
->addWidget(label
);
96 template<class Assigner
>
97 QImage
imageFromMatrix(CSMatrix matrix
,Block block
,int rotation
,Assigner assigner
) {
98 QImage
image(block
.width(),block
.height(),QImage::Format_RGB32
);
100 using namespace MatrixWalkers
;
101 // changing rotation because of transposed CheckedImage
102 rotation
= Rotation::compose(1,rotation
);
104 walkOperateCheckRotate( CheckedImage
<QImage
,QRgb
>(image
), assigner
105 , matrix
, block
, rotation
);
109 struct GrayImageAssigner
{
110 void operator()(QRgb
&rgb
,const SReal
&pixel
) {
111 int gray
= Float2int
<8,Real
>::convertCheck(pixel
);
112 rgb
= qRgb(gray
,gray
,255); // not gray colour (intentionally)
114 void innerEnd() const {}
116 struct GrayImageMulAddAssigner
: public GrayImageAssigner
{
119 GrayImageMulAddAssigner(Real toMul
,Real toAdd
)
120 : mul(toMul
), add(toAdd
) {}
121 void operator()(QRgb
&rgb
,const SReal
&pixel
)
122 { GrayImageAssigner::operator()( rgb
, pixel
*mul
+add
); }
125 QWidget
* MStandardEncoder::debugModule(QPixmap
&pixmap
,const QPoint
&click
) {
126 const ISquareRanges::RangeList
&ranges
= planeBlock
->ranges
->getRangeList();
128 QWidget
*widget
= new QWidget
;
129 QBoxLayout
*layout
= new QVBoxLayout(widget
);
131 if ( pixmap
.rect().contains(click
) ) { // info about range clicked on
132 const RangeNode
&range
= *findRangeOnPoint( ranges
, click
);
133 const RangeInfo
&info
= static_cast<RangeInfo
&>(*range
.encoderData
);
135 QString msg
= QString("Quantized average: %1\nQuantized deviation: %2\n\n")
136 .arg(info
.qrAvg
) .arg(sqrt(info
.qrDev2
));
138 msg
+= QString("Encoding SE: %1\n") .arg(info
.bestSE
);
141 int poolIndex
= info
.decAccel
.pool
- &*planeBlock
->domains
->getPools().begin();
142 const Block
&domBlock
= info
.decAccel
.domBlock
;
143 msg
+= QString("Domain pool: %1\nDomain block top-left corner coordinates:\n"
144 "\t %2 %3\n") .arg(poolIndex
) .arg(domBlock
.x0
) .arg(domBlock
.y0
);
146 msg
+= QString("Rotation: %1\nInversion: %2")
147 .arg((int)info
.rotation
) .arg(info
.inverted
);
149 msg
+= "Only using solid color";
151 layout
->addWidget( new QLabel(msg
) );
154 layout
->addWidget( new QLabel("Domain block:") );
155 addFramedImage( layout
156 , imageFromMatrix( info
.decAccel
.pool
->pixels
, info
.decAccel
.domBlock
157 , 0, GrayImageAssigner() )
160 layout
->addWidget( new QLabel("Domain block, transformed (encode-mode-only):") );
161 addFramedImage( layout
162 , imageFromMatrix( info
.decAccel
.pool
->pixels
, info
.decAccel
.domBlock
163 , info
.rotation
, GrayImageMulAddAssigner(info
.exact
.linCoeff
,info
.exact
.constCoeff
) )
167 layout
->addWidget( new QLabel("Range block:") );
168 addFramedImage( layout
169 , imageFromMatrix( planeBlock
->pixels
, range
, 0, GrayImageAssigner() )
172 } else { // provide general info
173 RangeInfoAccumulator
info( planeBlock
->domains
->getPools() );
174 info
= for_each( ranges
.begin(), ranges
.end(), info
);
176 {// create a label with various counts info
177 QString msg
= "Range count: %1\nRotation counts: %2\nDomain pool counts: %3";
178 // fill in the total range count
179 msg
= msg
.arg( ranges
.size() );
180 // fill in the rotation counts
181 QString rots
= QString::number(info
.rotCounts
[0]);
182 for (int i
=1; i
<9; ++i
)
183 (rots
+= ", ")+= QString::number(info
.rotCounts
[i
]);
185 // fill in the domain counts
186 QString doms
= QString::number(info
.rotCounts
[0]);
187 vector
<int>::const_iterator it
;
188 for (it
= info
.poolCounts
.begin(); it
!=info
.poolCounts
.end(); ++it
)
189 (doms
+= ", ")+= QString::number(*it
);
191 // create the label and add it to the layout
192 layout
->addWidget( new QLabel(msg
) );
195 int maxLevel
= 1 +log2ceil(max( planeBlock
->width(), planeBlock
->height() ));
197 QTableWidget
*table
= new QTableWidget( maxLevel
-2, 3 );
198 table
->setHorizontalHeaderLabels
199 ( QStringList() << "Level" << "Ranges" << "Domain count" );
200 for (int level
=2; level
<maxLevel
; ++level
) {
201 // the number of the level
202 table
->setItem( level
-2, 0, new QTableWidgetItem(QString::number(level
)) );
203 // the count of the ranges on the level
204 table
->setItem( level
-2, 1, new QTableWidgetItem(
205 QString::number( info
.levelCounts
[level
] )
207 // the maximum allowed SE for the level
208 //float maxSE= planeBlock->moduleQ2SE->rangeSE( planeBlock->quality, powers[2*level] );
209 //table->setItem( level-2, 1.5, new QTableWidgetItem(QString::number(maxSE)) );
210 // the domain count for the level
211 int domCount
= levelPoolInfos
[level
].empty() ? -1
212 : levelPoolInfos
[level
].back().indexBegin
;
213 table
->setItem( level
-2, 2, new QTableWidgetItem(
214 QString("2 ^ %1").arg( log2(domCount
) )
217 // resize the label and add it to the layout
218 table
->resizeColumnsToContents();
219 table
->resizeRowsToContents();
220 layout
->addWidget(table
);
222 if ( modulePredictor() )
223 layout
->addWidget( modulePredictor()->debugModule(pixmap
,click
) );
227 } // MStandardEncoder::debugModule method
230 QWidget
* MQuadTree::debugModule(QPixmap
&pixmap
,const QPoint
&click
) {
232 if ( pixmap
.rect().contains(click
) ) { // info about range clicked on
233 const ISquareRanges::RangeNode
&range
= *findRangeOnPoint( fringe
, click
);
235 QString msg
= QString("Level: %1\nRegular: %2\n"
236 "Top-left corner: %3 %4\nWidth: %5\nHeight: %6")
237 .arg(range
.level
) .arg(range
.isRegular())
238 .arg(range
.x0
) .arg(range
.y0
)
239 .arg(range
.width()) .arg(range
.height());
240 return new QLabel(msg
);
242 } else { // provide general info
244 // add info about heuristic dividing (if it's allowed)
245 if ( settingsInt(HeuristicAllowed
) ) {
246 msg
+= "Heuristic dividing info:\n"
247 "\tBad tries (forced to divide): %1\n"
248 "\tBad divides (successful merges): %2\n"
249 "\tUnsuccessful merges: %3\n";
250 msg
= msg
.arg(badTries
).arg(badDivides
).arg(triedMerges
);
252 return new QLabel(msg
);
255 } // MQuadTree::debugModule method
258 QWidget
* MStdDomains::debugModule(QPixmap
&pixmap
,const QPoint
&click
) {
260 if ( pixmap
.rect().contains(click
) ) { // info about range clicked on
263 } else { // provide general info
270 QWidget
* MSaupePredictor::debugModule(QPixmap
&pixmap
,const QPoint
&click
) {
271 if ( pixmap
.rect().contains(click
) )
273 return new QLabel( QString("Predicted %1/%2 (%3%)")
274 .arg(predicted
) .arg(maxpred
) .arg(double(100)*predicted
/(double)maxpred
) );