TonicTones
Src/Operators/ReinhardLocalOperator/ReinhardLocalOperator.cpp
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 }
 All Classes Functions Variables