2
* This file is a part of Qtpfsgui package.
3
* ----------------------------------------------------------------------
4
* Copyright (C) 2006,2007 Giuseppe Rota
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
* ----------------------------------------------------------------------
21
* @author Giuseppe Rota <grota@users.sourceforge.net>
24
#include "tonemapper_thread.h"
25
#include <QProgressBar>
26
pfs::Frame* resizeFrame(pfs::Frame* inpfsframe, int _xSize);
27
void applyGammaFrame( pfs::Frame*, const float);
28
pfs::Frame* pfstmo_ashikhmin02 (pfs::Frame*,bool,float,int);
29
pfs::Frame* pfstmo_drago03 (pfs::Frame *, float);
30
pfs::Frame* pfstmo_fattal02 (pfs::Frame*,float,float,float,float,bool);
31
pfs::Frame* pfstmo_durand02 (pfs::Frame*,float,float,float);
32
pfs::Frame* pfstmo_pattanaik00 (pfs::Frame*,bool,float,float,float,bool);
33
pfs::Frame* pfstmo_reinhard02 (pfs::Frame*,float,float,int,int,int,bool);
34
pfs::Frame* pfstmo_reinhard04 (pfs::Frame *,float,float,float);
35
pfs::Frame* pfstmo_mantiuk06(pfs::Frame*,float,float,bool);
37
// width of the pfs:frame written on disk during resize operation, cannot be the 100% size: originalxsize, because i don't resize to 100% and write to disk.
38
int xsize=-1; //-1 means nothing has been computed yet
39
// gamma of the pfs:frame written on disk after resize
40
float pregamma=-1; //-1 means NOT VALID (size has changed/is changing)
41
//pregamma!=-1 means that the pregamma frame has the xsize as width
45
TonemapperThread::TonemapperThread(int xorigsize, QString cachepath, QProgressBar* b) : QThread(0), bar(b), originalxsize(xorigsize), cachepath(cachepath){
46
colorspaceconversion=false;
49
TonemapperThread::~TonemapperThread() {
51
// qDebug("~TonemapperThread()");
54
void TonemapperThread::fetch(QString filename) {
56
workingframe=pfsio.readFrame(cachepath+filename);
59
void TonemapperThread::swap(pfs::Frame *frame, QString filename) {
62
pfsio.writeFrame(frame,cachepath+filename);
65
void TonemapperThread::run() {
67
// qDebug("::::::begin thread, size=%d, gamma=%f",xsize, pregamma);
69
if (opt.xsize==originalxsize && opt.pregamma==1.0f) {
70
//original goes into tone mapping
71
qDebug("::::::original goes into tone mapping");
72
fetch("/original.pfs");
74
colorspaceconversion=true;
75
emit setMaximumSteps(2);
76
} else if (opt.xsize==xsize && opt.pregamma==1.0f) {
77
//resized goes into tone mapping
78
qDebug("::::::resized goes into tone mapping");
79
fetch("/after_resize.pfs");
81
colorspaceconversion=true;
82
emit setMaximumSteps(2);
83
} else if ( (opt.xsize==xsize && opt.pregamma==pregamma) || (opt.xsize==originalxsize && xsize==-1 && opt.pregamma==pregamma) ) {
84
//after_pregamma goes into tone mapping
85
qDebug("::::::after_pregamma goes into tone mapping");
86
fetch("/after_pregamma.pfs");
88
emit setMaximumSteps(2);
89
} else if (opt.xsize==xsize) {
90
//resized goes into pregamma
91
qDebug("::::::resized goes into pregamma");
92
fetch("/after_resize.pfs");
94
emit setMaximumSteps(3);
95
} else if (opt.xsize==originalxsize) {
96
//original goes into pregamma
97
qDebug("::::::original goes into pregamma");
98
fetch("/original.pfs");
100
emit setMaximumSteps(3);
102
//original goes into resize
103
qDebug("::::::original goes into resize");
104
fetch("/original.pfs");
106
emit setMaximumSteps(4);
108
emit setCurrentProgress(1);
112
if (status==from_resize) {
113
assert(opt.xsize!=originalxsize);
114
qDebug("executing resize step");
115
pfs::Frame *resized=resizeFrame(workingframe, opt.xsize);
117
swap(resized,"/after_resize.pfs");
122
workingframe=resized;
123
status=from_pregamma;
124
if (bar) emit setCurrentProgress(bar->value()+1);
126
if (status==from_pregamma) {
127
qDebug("executing pregamma step");
128
applyGammaFrame( workingframe, opt.pregamma );
130
swap(workingframe,"/after_pregamma.pfs");
131
pregamma=opt.pregamma;
132
if (opt.xsize==originalxsize)
138
if (bar) emit setCurrentProgress(bar->value()+1);
140
if (status==from_tm) {
141
qDebug("executing tone mapping step");
142
if (colorspaceconversion)
143
workingframe->convertRGBChannelsToXYZ();
144
pfs::Frame *result=NULL;
145
switch (opt.tmoperator) {
147
result=pfstmo_mantiuk06(workingframe,
148
opt.operator_options.mantiukoptions.contrastfactor,
149
opt.operator_options.mantiukoptions.saturationfactor,
150
opt.operator_options.mantiukoptions.contrastequalization);
153
//fattal is NOT even reentrant! (problem in PDE solving)
154
//therefore I need to use a mutex here
156
result=pfstmo_fattal02(workingframe,
157
opt.operator_options.fattaloptions.alpha,
158
opt.operator_options.fattaloptions.beta,
159
opt.operator_options.fattaloptions.color,
160
opt.operator_options.fattaloptions.noiseredux,
161
opt.operator_options.fattaloptions.newfattal);
165
result=pfstmo_ashikhmin02(workingframe,
166
opt.operator_options.ashikhminoptions.simple,
167
opt.operator_options.ashikhminoptions.lct,
168
opt.operator_options.ashikhminoptions.eq2 ? 2 : 4);
171
//even durand seems to be not reentrant
173
result=pfstmo_durand02(workingframe,
174
opt.operator_options.durandoptions.spatial,
175
opt.operator_options.durandoptions.range,
176
opt.operator_options.durandoptions.base);
180
result=pfstmo_drago03(workingframe, opt.operator_options.dragooptions.bias);
183
result=pfstmo_pattanaik00(workingframe,
184
opt.operator_options.pattanaikoptions.local,
185
opt.operator_options.pattanaikoptions.multiplier,
186
opt.operator_options.pattanaikoptions.cone,
187
opt.operator_options.pattanaikoptions.rod,
188
opt.operator_options.pattanaikoptions.autolum);
191
result=pfstmo_reinhard02(workingframe,
192
opt.operator_options.reinhard02options.key,
193
opt.operator_options.reinhard02options.phi,
194
opt.operator_options.reinhard02options.range,
195
opt.operator_options.reinhard02options.lower,
196
opt.operator_options.reinhard02options.upper,
197
opt.operator_options.reinhard02options.scales);
200
result=pfstmo_reinhard04(workingframe,
201
opt.operator_options.reinhard04options.brightness,
202
opt.operator_options.reinhard04options.chromaticAdaptation,
203
opt.operator_options.reinhard04options.lightAdaptation);
206
if (bar) emit setCurrentProgress(bar->value()+1);
207
assert(result!=NULL);
209
const QImage& res=fromLDRPFStoQImage(result);
211
emit ImageComputed(res,&opt);
212
if (bar) emit removeProgressBar(bar);
217
void TonemapperThread::dumpOpts() {
218
qDebug("dump: opt.xsize=%d",opt.xsize);
219
qDebug("dump: opt.pregamma=%f",opt.pregamma);
220
switch (opt.tmoperator) {
222
qDebug("dump: fattal");
223
qDebug("dump: opt.alpha=%f",opt.operator_options.fattaloptions.alpha);
224
qDebug("dump: opt.beta=%f",opt.operator_options.fattaloptions.beta);
225
qDebug("dump: opt.color=%f",opt.operator_options.fattaloptions.color);
228
qDebug("dump: ashikhmin");
229
qDebug(opt.operator_options.ashikhminoptions.simple? "dump: opt.simple=true" : "dump: opt.simple=false");
230
qDebug("dump: opt.lct=%f",opt.operator_options.ashikhminoptions.lct);
231
qDebug("dump: opt.eq=%d",
232
opt.operator_options.ashikhminoptions.eq2 ? 2 : 4);
235
qDebug("dump: durand");
236
qDebug("dump: opt.spatial=%f",opt.operator_options.durandoptions.spatial);
237
qDebug("dump: opt.range=%f",opt.operator_options.durandoptions.range);
238
qDebug("dump: opt.base=%f",opt.operator_options.durandoptions.base);
241
qDebug("dump: drago");
242
qDebug("dump: opt.bias=%f",opt.operator_options.dragooptions.bias);
245
qDebug("dump: pattanaik");
246
qDebug(opt.operator_options.pattanaikoptions.local?"dump: opt.local=true":"dump: opt.local=false");
247
qDebug(opt.operator_options.pattanaikoptions.autolum?"dump: opt.autolum=true":"dump: opt.autolum=false");
248
qDebug("dump: opt.multiplier=%f",opt.operator_options.pattanaikoptions.multiplier);
249
qDebug("dump: opt.cone=%f",opt.operator_options.pattanaikoptions.cone);
250
qDebug("dump: opt.rod=%f",opt.operator_options.pattanaikoptions.rod);
253
qDebug("dump: reinhard02");
254
qDebug(opt.operator_options.reinhard02options.scales?"dump: opt.scales=true":"dump: opt.scales=false");
255
qDebug("dump: opt.key=%f",opt.operator_options.reinhard02options.key);
256
qDebug("dump: opt.phi=%f",opt.operator_options.reinhard02options.phi);
257
qDebug("dump: opt.range=%d",opt.operator_options.reinhard02options.range);
258
qDebug("dump: opt.lower=%d",opt.operator_options.reinhard02options.lower);
259
qDebug("dump: opt.upper=%d",opt.operator_options.reinhard02options.upper);
262
qDebug("dump: reinhard04");
263
qDebug("dump: opt.brightness=%f",opt.operator_options.reinhard04options.brightness);
264
qDebug("dump: opt.saturation=%f",opt.operator_options.reinhard04options.saturation);
270
void TonemapperThread::ComputeImage(const tonemapping_options opt) {
276
start(HighestPriority);