00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <QtGui>
00022 #include <TonicTones.h>
00023 #include <Exceptions.h>
00024 #include <iostream>
00025
00092 TonicTones::TonicTones(QWidget *parent) :
00093 QMainWindow(parent),
00094 inputImage(NULL),
00095 outputImage(NULL),
00096 gamma(1.0),
00097 gammaEnabled(true),
00098 operatorEnabled(true),
00099 loaderManager(*ImageLoaderManager::instance()),
00100 operatorManager(*ToneMappingOperatorManager::instance())
00101 {
00102 xyzToRgbMatrix[0][0]= 2.5651; xyzToRgbMatrix[0][1]=-1.1665; xyzToRgbMatrix[0][2]=-0.3986;
00103 xyzToRgbMatrix[1][0]=-1.0217; xyzToRgbMatrix[1][1]= 1.9777; xyzToRgbMatrix[1][2]= 0.0439;
00104 xyzToRgbMatrix[2][0]= 0.0753; xyzToRgbMatrix[2][1]=-0.2543; xyzToRgbMatrix[2][2]= 1.1892;
00105
00106 setupUi(this);
00107
00108 scrollArea = new ImageScrollArea;
00109 displayAreaLayout->addWidget(scrollArea);
00110
00111 zoomLabel = new QLabel;
00112 statusbar->addPermanentWidget(zoomLabel, 1);
00113
00114 operatorLabel = new QLabel;
00115 statusbar->addPermanentWidget(operatorLabel, 2);
00116
00117 conversionTimeLabel = new QLabel;
00118 statusbar->addPermanentWidget(conversionTimeLabel, 1);
00119
00120 displayTimeLabel = new QLabel;
00121 statusbar->addPermanentWidget(displayTimeLabel, 1);
00122
00123
00124 connect(operatorComboBox, SIGNAL(currentIndexChanged(const QString&)),
00125 this, SLOT(updateOperator(const QString&)));
00126 connect(scrollArea, SIGNAL(scaleChanged(double)), this, SLOT(updateZoom(double)));
00127 connect(actionOpen, SIGNAL(triggered()), this, SLOT(open()));
00128 connect(actionScreenColors, SIGNAL(triggered()), this, SLOT(openScreenColorsDialog()));
00129 connect(operatorGroupBox, SIGNAL(toggled(bool)), this, SLOT(enableOperator(bool)));
00130 connect(gammaGroupBox, SIGNAL(toggled(bool)), this, SLOT(enableGamma(bool)));
00131 connect(gammaSlider, SIGNAL(sliderReleased()), this, SLOT(displayImage()));
00132 connect(gammaSlider, SIGNAL(valueChanged(int)), this, SLOT(updateGamma(int)));
00133
00134 loaderManager.registerLoaders("Loaders");
00135
00136 QStringList operatorList = operatorManager.registerOperators("Operators");
00137 operatorComboBox->addItems(operatorList);
00138
00139
00140 if (loaderManager.empty())
00141 {
00142 qFatal("No image loader found! TonicTones will not be able to open images! Exiting now.");
00143 }
00144 if (operatorManager.empty())
00145 {
00146 qWarning("No tone mapping operator found. Satisfaction not guaranteed.");
00147 operatorGroupBox->hide();
00148 operatorOptionsGroupBox->hide();
00149 }
00150 }
00151
00155 void TonicTones::open()
00156 {
00157 QString fileName = QFileDialog::getOpenFileName(this);
00158
00159 try
00160 {
00161 if (!fileName.isEmpty())
00162 {
00163 HdrImage* newImage = new HdrImage(fileName);
00164 delete inputImage;
00165 inputImage = newImage;
00166
00167 if(operatorManager.getActiveOperator())
00168 {
00169 operatorManager.getActiveOperator()->setImage(inputImage);
00170 }
00171 else
00172 {
00173 operatorEnabled = false;
00174 updateImage();
00175 }
00176
00177 setWindowTitle(QString("TonicTones - %1").arg(QDir(fileName).dirName()));
00178
00179 scrollArea->scaleImage(1.0, false);
00180 }
00181 }
00182 catch(const Exception& e)
00183 {
00184 qWarning() << e.what();
00185 }
00186 }
00187
00193 void TonicTones::updateImage()
00194 {
00195 const HdrImage* image;
00196 if(operatorEnabled)
00197 image = operatorManager.getActiveOperator()->getToneMappedImage();
00198 else
00199 image = inputImage;
00200 if (image)
00201 {
00202 QTime t;
00203 t.start();
00204
00205 delete outputImage;
00206 try
00207 {
00208 outputImage = image->toRgb(xyzToRgbMatrix);
00209 }
00210 catch(const Exception& e)
00211 {
00212 qWarning() << e.what();
00213 }
00214 conversionTimeLabel->setText(tr("Transformation to RGB: %1 ms").arg(t.elapsed()));
00215 displayImage();
00216 }
00217 }
00218
00222 void TonicTones::displayImage() const
00223 {
00224 if (outputImage)
00225 {
00226 QTime t;
00227 t.start();
00228
00229 QSize size = outputImage->size();
00230 int width = size.width();
00231 int height = size.height();
00232 int pixels[width*height];
00233
00234 if(gammaEnabled and gamma!=1.0)
00235 {
00236 double gamma_corr = 1.0/gamma;
00237 for(int i=0; i<height; ++i)
00238 for(int j=0; j<width; ++j)
00239 {
00240 Color p = (*outputImage)[i][j].clamp();
00241 pixels[i*width+j] = qRgb(pow(p[0],gamma_corr)*255.0,pow(p[1],gamma_corr)*255.0,pow(p[2],gamma_corr)*255.0);
00242 }
00243 }
00244 else
00245 {
00246 for(int i=0; i<height; ++i)
00247 for(int j=0; j<width; ++j)
00248 {
00249 Color p = (*outputImage)[i][j].clamp();
00250 pixels[i*width+j] = qRgb(p[0]*255.0,p[1]*255.0,p[2]*255.0);
00251 }
00252 }
00253 QImage ldrImage((uchar*)pixels, width, height, QImage::Format_RGB32);
00254
00255 scrollArea->image()->setPixmap(QPixmap::fromImage(ldrImage));
00256 displayTimeLabel->setText(tr("Display: %1 ms").arg(t.elapsed()));
00257 }
00258 }
00259
00263 void TonicTones::updateZoom(double scaleFactor)
00264 {
00265 zoomLabel->setText(tr("Zoom: %1 %").arg(scaleFactor*100, 0, 'f', 0));
00266 }
00267
00271 void TonicTones::updateOperator(const QString& operatorName)
00272 {
00273 qDebug("%s selected.", operatorName.toStdString().c_str());
00274
00275
00276 operatorManager.setActiveOperator(operatorName);
00277
00278
00279 QLayoutItem* item = operatorOptionsGroupBox->layout()->itemAt(0);
00280 operatorOptionsGroupBox->layout()->removeItem(item);
00281 if(item)
00282 item->widget()->close();
00283
00284
00285 QWidget *wrapper = new QWidget;
00286 wrapper->setAttribute(Qt::WA_DeleteOnClose);
00287 operatorOptionsGroupBox->layout()->addWidget(wrapper);
00288 operatorManager.getActiveOperator()->setupUi(wrapper);
00289
00290 connect(operatorManager.getActiveOperator().data(),SIGNAL(imageUpdated()),
00291 this, SLOT(updateImage()));
00292 connect(operatorManager.getActiveOperator().data(),SIGNAL(message(const QString&)),
00293 operatorLabel, SLOT(setText(const QString&)));
00294
00295 if (inputImage)
00296 {
00297 operatorManager.getActiveOperator()->setImage(inputImage);
00298 }
00299 }
00300
00304 void TonicTones::updateGamma(int value)
00305 {
00306 gamma = float(value)/100.0;
00307 gammaValue->setText(QString("%1").arg(gamma, 0, 'f', 2));
00308 }
00309
00316 void TonicTones::enableOperator(bool enabled)
00317 {
00318 operatorEnabled = enabled;
00319 operatorOptionsGroupBox->setEnabled(enabled);
00320 updateImage();
00321 }
00322
00329 void TonicTones::enableGamma(bool enabled)
00330 {
00331 gammaEnabled = enabled;
00332 displayImage();
00333 }
00334
00335
00339 void TonicTones::openScreenColorsDialog()
00340 {
00341 QDialog dialog;
00342 uiScreenColors.setupUi(&dialog);
00343
00344
00345 QMatrix4x4 m;
00346 for (int i=0; i<3; ++i)
00347 for(int j=0; j<3; ++j)
00348 m(i,j) = xyzToRgbMatrix[i][j];
00349 m = m.inverted();
00350
00351 uiScreenColors.m00->setValue(m(0,0)); uiScreenColors.m01->setValue(m(0,1)); uiScreenColors.m02->setValue(m(0,2));
00352 uiScreenColors.m10->setValue(m(1,0)); uiScreenColors.m11->setValue(m(1,1)); uiScreenColors.m12->setValue(m(1,2));
00353 uiScreenColors.m20->setValue(m(2,0)); uiScreenColors.m21->setValue(m(2,1)); uiScreenColors.m22->setValue(m(2,2));
00354
00355 connect(&dialog, SIGNAL(accepted()), this, SLOT(updateScreenColors()));
00356 dialog.exec();
00357 }
00358
00364 void TonicTones::updateScreenColors()
00365 {
00366
00367
00368 QMatrix4x4 m = QMatrix4x4(uiScreenColors.m00->value(), uiScreenColors.m01->value(), uiScreenColors.m02->value(), 0.0,
00369 uiScreenColors.m10->value(), uiScreenColors.m11->value(), uiScreenColors.m12->value(), 0.0,
00370 uiScreenColors.m20->value(), uiScreenColors.m21->value(), uiScreenColors.m22->value(), 0.0,
00371 0.0, 0.0, 0.0 , 1.0).inverted();
00372 for (int i=0; i<3; ++i)
00373 for(int j=0; j<3; ++j)
00374 xyzToRgbMatrix[i][j] = m(i,j);
00375
00376 updateImage();
00377 }
00378