TonicTones
|
00001 // ReinhardLocalOperator.cpp 00002 // 00003 // Copyright 2010 Jérémy Laumon <jeremy.laumon@gmail.com> 00004 // 00005 // This program is free software; you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation; either version 2 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // This program is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with this program; if not, write to the Free Software 00017 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 00018 // MA 02110-1301, USA. 00019 00020 00021 #include <ReinhardLocalOperator.h> 00022 #include <Exceptions.h> 00023 #include <math.h> 00024 00025 #define OPERATOR_NAME "Reinhard Local Operator" 00026 00027 Q_EXPORT_PLUGIN2(TT_ReinhardLocalOperator, ReinhardLocalOperatorFactory) 00028 00029 00039 ReinhardLocalOperator::ReinhardLocalOperator() : 00040 inputImage(NULL), 00041 outputImage(NULL), 00042 width(0), 00043 height(0), 00044 keyValue(0.18), 00045 sharpening(8.0) 00046 { 00047 for(int k=0; k<9; ++k) 00048 { 00049 responses[k] = NULL; 00050 } 00051 } 00052 00053 ReinhardLocalOperator::~ReinhardLocalOperator() 00054 { 00055 for(int k=0; k<9; ++k) 00056 { 00057 delete[] responses[k]; 00058 } 00059 } 00060 00064 QString ReinhardLocalOperator::name() const 00065 { 00066 return tr(OPERATOR_NAME); 00067 } 00068 00069 void ReinhardLocalOperator::setupUi(QWidget* parent) 00070 { 00071 ui.setupUi(parent); 00072 00073 connect(ui.keyValueSlider, SIGNAL(sliderReleased()), this, SLOT(toneMap())); 00074 connect(ui.keyValueSlider, SIGNAL(valueChanged(int)), this, SLOT(updateKeyValue(int))); 00075 00076 connect(ui.sharpeningSlider, SIGNAL(sliderReleased()), this, SLOT(toneMap())); 00077 connect(ui.sharpeningSlider, SIGNAL(valueChanged(int)), this, SLOT(updateSharpening(int))); 00078 } 00079 00080 const HdrImage* ReinhardLocalOperator::getToneMappedImage() const 00081 { 00082 return outputImage; 00083 } 00084 00098 void ReinhardLocalOperator::setImage(const HdrImage* _inputImage) 00099 { 00100 if (!_inputImage->hasY()) 00101 throw Exception(tr("Image passed to %1 does not contains Y data. Cannot turn water into wine.").arg(name())); 00102 00103 QTime t; 00104 t.start(); 00105 00106 inputImage = _inputImage; 00107 QSize size = inputImage->size(); 00108 width = size.width(); 00109 height = size.height(); 00110 int Y = inputImage->YIndex(); 00111 int length = width*height; 00112 double delta = 0.0001; 00113 fftw_plan plan; 00114 fftw_complex* image = NULL; 00115 fftw_complex* filters[9] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; 00116 00117 delete outputImage; 00118 outputImage = new HdrImage(*inputImage); 00119 00120 // delete data from potential previous image 00121 for(int k=0; k<9; ++k) 00122 { 00123 delete[] responses[k]; 00124 } 00125 00126 00127 // calculate average luminance 00128 //TO COMPLETE 00129 00130 00131 // allocate memory for image fft and filters ffts 00132 image = new fftw_complex[length]; 00133 for(int k=0; k<9; ++k) 00134 { 00135 filters[k] = new fftw_complex[length]; 00136 for(int i=0; i<length; ++i) 00137 { 00138 filters[k][i][0] = 0.0; // re 00139 filters[k][i][1] = 0.0; // im 00140 } 00141 } 00142 00143 // generate filters data 00144 // TO COMPLETE 00145 00146 // compute filters ffts 00147 // TO COMPLETE, see fftw_plan_dft_2d() and fftw_execute() 00148 00149 // copy image data 00150 for(int i=0; i<height; ++i) 00151 { 00152 for(int j=0; j<width; ++j) 00153 { 00154 image[i*width + j][0] = (*inputImage)[i][j][Y]; 00155 image[i*width + j][1] = 0.0; 00156 } 00157 } 00158 00159 // compute image fft 00160 // TO COMPLETE, see fftw_plan_dft_2d() and fftw_execute() 00161 00162 // convolve image and filters 00163 // TO COMPLETE 00164 00165 // compute responses inverse ffts 00166 // TO COMPLETE, see fftw_plan_dft_2d() and fftw_execute() 00167 00168 fftw_destroy_plan(plan); 00169 delete[] image; 00170 for(int k=0; k<9; ++k) 00171 delete[] filters[k]; 00172 00173 ui.keyValueSlider->setValue(18); // = 0.18 00174 ui.sharpeningSlider->setValue(8); 00175 00176 msg = tr("Operator Init: %1 ms").arg(t.elapsed()); 00177 00178 toneMap(); 00179 } 00180 00185 fftw_complex* ReinhardLocalOperator::convolveFft(fftw_complex* f1, fftw_complex* f2) 00186 { 00187 int length = width*height; 00188 fftw_complex* res = reinterpret_cast<fftw_complex*>(fftw_malloc(sizeof(fftw_complex)*length)); 00189 00190 //TO COMPLETE 00191 00192 return res; 00193 } 00194 00200 void ReinhardLocalOperator::toneMap() 00201 { 00202 if(inputImage) 00203 { 00204 QTime t; 00205 t.start(); 00206 00207 int Y = inputImage->YIndex(); 00208 const float threshold = 0.05; 00209 00210 //for each pixel, find the appropriate filter to modulate the luminance 00211 //in the out image 00212 //TO COMPLETE 00213 00214 00215 emit message(msg + tr(" Tone Mapping: %1 ms").arg(t.elapsed())); 00216 00217 emit imageUpdated(); 00218 } 00219 } 00220 00226 void ReinhardLocalOperator::updateKeyValue(int value) 00227 { 00228 keyValue = double(value)/100.0; 00229 ui.keyValue->setText(QString("%1").arg(keyValue, 0, 'f', 2)); 00230 } 00231 00237 void ReinhardLocalOperator::updateSharpening(int value) 00238 { 00239 sharpening = double(value); 00240 ui.sharpening->setText(QString("%1").arg(sharpening)); 00241 } 00242 00243 00244 //---------------------------------------------------------------------- 00245 00256 ToneMappingOperatorPtr ReinhardLocalOperatorFactory::createOperator() const 00257 { 00258 return ToneMappingOperatorPtr(new ReinhardLocalOperator); 00259 } 00260 00264 QString ReinhardLocalOperatorFactory::operatorName() const 00265 { 00266 return tr(OPERATOR_NAME); 00267 }