/
pfstmo_fattal02.cpp
124 lines (109 loc) · 3.59 KB
/
pfstmo_fattal02.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/**
* @file pfstmo_fattal02.cpp
* @brief Tone map XYZ channels using Fattal02 model
*
* Gradient Domain High Dynamic Range Compression
* R. Fattal, D. Lischinski, and M. Werman
* In ACM Transactions on Graphics, 2002.
*
*
* This file is a part of LuminanceHDR package, based on pfstmo.
* ----------------------------------------------------------------------
* Copyright (C) 2003,2004 Grzegorz Krawczyk
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* ----------------------------------------------------------------------
*
* @author Grzegorz Krawczyk, <krawczyk@mpi-sb.mpg.de>
*
* $Id: pfstmo_fattal02.cpp,v 1.3 2008/09/04 12:46:49 julians37 Exp $
*/
#include "tmo_fattal02.h"
#include <cmath>
#include <iostream>
#include <sstream>
#include <algorithm>
#include "Libpfs/frame.h"
#include "Libpfs/colorspace/colorspace.h"
#include "Libpfs/exception.h"
#include "Libpfs/progress.h"
namespace
{
const float epsilon = 1e-4f;
}
void pfstmo_fattal02(pfs::Frame& frame,
float opt_alpha,
float opt_beta,
float opt_saturation,
float opt_noise,
bool newfattal,
bool fftsolver,
int detail_level,
pfs::Progress &ph)
{
if (fftsolver)
{
// opt_alpha = 1.f;
newfattal = true; // let's make sure, prudence is never enough!
}
if ( opt_noise <= 0.0f )
{
opt_noise = opt_alpha * 0.01f;
}
#ifndef NDEBUG
std::stringstream ss;
ss << "pfstmo_fattal02 (";
ss << "alpha: " << opt_alpha;
ss << ", beta: " << opt_beta;
ss << ". saturation: " << opt_saturation;
ss << ", noise: " << opt_noise;
ss << ", fftsolver: " << fftsolver << ")";
std::cout << ss.str() << std::endl;
#endif
//Store RGB data temporarily in XYZ channels
pfs::Channel *R, *G, *B;
frame.getXYZChannels( R, G, B );
//---
if ( !R || !G || !B )
{
throw pfs::Exception( "Missing X, Y, Z channels in the PFS stream" );
}
frame.getTags().setTag("LUMINANCE", "RELATIVE");
// tone mapping
const int w = frame.getWidth();
const int h = frame.getHeight();
pfs::Array2Df Yr(w,h);
pfs::Array2Df L(w,h);
pfs::transformRGB2Y(R, G, B, &Yr);
tmo_fattal02(w, h, Yr, L,
opt_alpha, opt_beta, opt_noise, newfattal,
fftsolver, detail_level,
ph);
if ( !ph.canceled() )
{
pfs::Array2Df& arrayRed = *R;
pfs::Array2Df& arrayGreen = *G;
pfs::Array2Df& arrayBlue = *B;
for (int i=0; i < w*h; i++)
{
float y = std::max( Yr(i), epsilon );
float l = std::max( L(i), epsilon );
arrayRed(i) = std::pow( std::max(arrayRed(i)/y, 0.f), opt_saturation ) * l;
arrayGreen(i) = std::pow( std::max(arrayGreen(i)/y, 0.f), opt_saturation ) * l;
arrayBlue(i) = std::pow( std::max(arrayBlue(i)/y, 0.f), opt_saturation ) * l;
}
ph.setValue( 100 );
}
}