Some code cleanup and changes due to GCC upgrade to 4.3.*.
[fic.git] / debug.cpp
blobc1cf1e96ef76a50707fd1fcf0820db5274dcbdff
1 #include "interfaces.h"
2 #ifndef NDEBUG
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"
11 #include <QBoxLayout>
12 #include <QDialog>
13 #include <QLabel>
14 #include <QTabWidget>
15 #include <QTableWidget>
17 using namespace std;
19 int pos;
21 QWidget* MRoot::debugModule(QPixmap &pixmap,const QPoint &click) {
22 // create a new modeless dialog window
23 QDialog *dlg= new QDialog;
24 dlg->setModal(false);
25 // add a laid-out single widget created by IShapeTransformer
26 ( new QVBoxLayout(dlg) )->addWidget( moduleShape()->debugModule(pixmap,click) );
27 return dlg;
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 )
36 continue;
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) );
44 return tabs;
48 namespace NOSPACE {
49 struct RangeInfoAccumulator {
50 const ISquareDomains::PoolList *pools;
51 int rotCounts[9];
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)
57 rotCounts[i]= 0;
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() );
70 ++poolCounts[index];
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) {
80 const Block &b= **it;
81 if ( b.x0<=x && b.y0<=y && b.xend>x && b.yend>y )
82 return *it;
84 ASSERT(false); return 0;
88 namespace NOSPACE {
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 );
107 return image;
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 {
117 Real mul, add;
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);
140 if (info.qrDev2) {
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);
148 } else
149 msg+= "Only using solid color";
151 layout->addWidget( new QLabel(msg) );
153 if (info.qrDev2) {
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]);
184 msg= msg.arg(rots);
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);
190 msg= msg.arg(doms);
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] )
206 ) );
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) )
215 ) );
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) );
224 } // if-then-else
226 return widget;
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
243 QString msg;
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);
253 } // if-then-else
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
266 } // if-then-else
267 return 0;
270 QWidget* MSaupePredictor::debugModule(QPixmap &pixmap,const QPoint &click) {
271 if ( pixmap.rect().contains(click) )
272 return 0;
273 return new QLabel( QString("Predicted %1/%2 (%3%)")
274 .arg(predicted) .arg(maxpred) .arg(double(100)*predicted/(double)maxpred) );
277 #endif