1
///////////////////////////////////////////////////////////////////////////
3
// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
6
// All rights reserved.
8
// Redistribution and use in source and binary forms, with or without
9
// modification, are permitted provided that the following conditions are
11
// * Redistributions of source code must retain the above copyright
12
// notice, this list of conditions and the following disclaimer.
13
// * Redistributions in binary form must reproduce the above
14
// copyright notice, this list of conditions and the following disclaimer
15
// in the documentation and/or other materials provided with the
17
// * Neither the name of Industrial Light & Magic nor the names of
18
// its contributors may be used to endorse or promote products derived
19
// from this software without specific prior written permission.
21
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
///////////////////////////////////////////////////////////////////////////
37
//----------------------------------------------------------------------------
41
//----------------------------------------------------------------------------
43
#include <ImageView.h>
44
#include <ImathMath.h>
46
#include <halfFunction.h>
49
#if defined PLATFORM_WINDOWS
51
#ifndef WIN32_LEAN_AND_MEAN
52
#define WIN32_LEAN_AND_MEAN
57
#elif defined PLATFORM_DARWIN_PPC
58
#include <OpenGL/gl.h>
68
ImageView::ImageView (int x, int y,
71
const Imf::Rgba pixels[],
79
Fl_Gl_Window (x, y, w, h, label),
92
_screenPixels (dw * dh * 3)
100
ImageView::setExposure (float exposure)
102
_exposure = exposure;
103
updateScreenPixels();
109
ImageView::setDefog (float defog)
112
updateScreenPixels();
118
ImageView::setKneeLow (float kneeLow)
121
updateScreenPixels();
127
ImageView::setKneeHigh (float kneeHigh)
129
_kneeHigh = kneeHigh;
130
updateScreenPixels();
141
glViewport (0, 0, w(), h());
142
glOrtho(0, w(), h(), 0, -1, 1);
145
glClearColor (0.3, 0.3, 0.3, 1.0);
146
glClear (GL_COLOR_BUFFER_BIT);
148
if (_dx + _dw <= 0 || _dx >= w())
151
for (int y = 0; y < _dh; ++y)
153
if (y + _dy < 0 || y + _dy >= h())
156
glRasterPos2i (max (0, _dx), y + _dy + 1);
158
glDrawPixels (_dw + min (0, _dx), // width
161
GL_UNSIGNED_BYTE, // type
162
_screenPixels + // pixels
163
static_cast <ptrdiff_t> ((y * _dw - min (0, _dx)) * 3));
169
ImageView::computeFogColor ()
175
for (int j = 0; j < _dw * _dh; ++j)
177
const Imf::Rgba &rp = _rawPixels[j];
198
// Conversion from raw pixel data to data for the OpenGL frame buffer:
200
// 1) Compensate for fogging by subtracting defog
201
// from the raw pixel values.
203
// 2) Multiply the defogged pixel values by
204
// 2^(exposure + 2.47393).
206
// 3) Values, which are now 1.0, are called "middle gray".
207
// If defog and exposure are both set to 0.0, then
208
// middle gray corresponds to a raw pixel value of 0.18.
209
// In step 6, middle gray values will be mapped to an
210
// intensity 3.5 f-stops below the display's maximum
213
// 4) Apply a knee function. The knee function has two
214
// parameters, kneeLow and kneeHigh. Pixel values
215
// below 2^kneeLow are not changed by the knee
216
// function. Pixel values above kneeLow are lowered
217
// according to a logarithmic curve, such that the
218
// value 2^kneeHigh is mapped to 2^3.5 (in step 6,
219
// this value will be mapped to the the display's
220
// maximum intensity).
222
// 5) Gamma-correct the pixel values, assuming that the
223
// screen's gamma is 2.2 (or 1 / 0.4545).
225
// 6) Scale the values such that pixels middle gray
226
// pixels are mapped to 84.66 (or 3.5 f-stops below
227
// the display's maximum intensity).
229
// 7) Clamp the values to [0, 255].
234
knee (double x, double f)
236
return float (Imath::Math<double>::log (x * f + 1) / f);
241
findKneeF (float x, float y)
246
while (knee (x, f1) > y)
252
for (int i = 0; i < 30; ++i)
254
float f2 = (f0 + f1) / 2;
255
float y2 = knee (x, f2);
263
return (f0 + f1) / 2;
271
Gamma (float exposure, float defog, float kneeLow, float kneeHigh);
272
float operator () (half h);
276
Gamma::Gamma (float exposure, float defog, float kneeLow, float kneeHigh):
277
m (Imath::Math<float>::pow (2, exposure + 2.47393)),
279
kl (Imath::Math<float>::pow (2, kneeLow)),
280
f (findKneeF (Imath::Math<float>::pow (2, kneeHigh) - kl,
281
Imath::Math<float>::pow (2, 3.5) - kl))
286
Gamma::operator () (half h)
292
float x = max (0.f, (h - d));
305
x = kl + knee (x - kl, f);
311
x = Imath::Math<float>::pow (x, 0.4545f);
317
return clamp (x * 84.66f, 0.f, 255.f);
322
// Dithering: Reducing the raw 16-bit pixel data to 8 bits for the
323
// OpenGL frame buffer can sometimes lead to contouring in smooth
324
// color ramps. Dithering with a simple Bayer pattern eliminates
325
// visible contouring.
329
dither (float v, int x, int y)
331
static const float d[4][4] =
333
0.f / 16, 8.f / 16, 2.f / 16, 10.f / 16,
334
12.f / 16, 4.f / 16, 14.f / 16, 6.f / 16,
335
3.f / 16, 11.f / 16, 1.f / 16, 9.f / 16,
336
15.f / 16, 7.f / 16, 13.f / 16, 5.f / 16,
339
return (unsigned char) (v + d[y & 3][x & 3]);
346
ImageView::updateScreenPixels ()
349
rGamma (Gamma (_exposure,
353
-HALF_MAX, HALF_MAX);
356
gGamma (Gamma (_exposure,
360
-HALF_MAX, HALF_MAX);
363
bGamma (Gamma (_exposure,
367
-HALF_MAX, HALF_MAX);
369
for (int y = 0; y < _dh; ++y)
373
for (int x = 0; x < _dw; ++x)
376
const Imf::Rgba &rp = _rawPixels[j];
377
unsigned char *sp = _screenPixels + j * 3;
379
sp[0] = dither (rGamma (rp.r), x, y);
380
sp[1] = dither (gGamma (rp.g), x, y);
381
sp[2] = dither (bGamma (rp.b), x, y);