1/* 2 * Copyright (c) 2004, Industrial Light & Magic, a division of Lucas 3 * Digital Ltd. LLC 4 * Distributed under the terms of the MIT License. 5 */ 6 7#include "EXRGamma.h" 8#include "ImathFun.h" 9#include "ImathMath.h" 10 11#include <algorithm> 12 13using namespace std; 14 15 16float 17knee(double x, double f) 18{ 19 return float (Imath::Math<double>::log (x * f + 1) / f); 20} 21 22 23float 24findKneeF(float x, float y) 25{ 26 float f0 = 0; 27 float f1 = 1; 28 29 while (knee (x, f1) > y) 30 { 31 f0 = f1; 32 f1 = f1 * 2; 33 } 34 35 for (int i = 0; i < 30; ++i) 36 { 37 float f2 = (f0 + f1) / 2; 38 float y2 = knee (x, f2); 39 40 if (y2 < y) 41 f1 = f2; 42 else 43 f0 = f2; 44 } 45 46 return (f0 + f1) / 2; 47} 48 49 50Gamma::Gamma(float gamma, 51 float exposure, 52 float defog, 53 float kneeLow, 54 float kneeHigh) 55: 56 g (gamma), 57 m (Imath::Math<float>::pow(2, exposure + 2.47393)), 58 d (defog), 59 kl (Imath::Math<float>::pow(2, kneeLow)), 60 f (findKneeF (Imath::Math<float>::pow(2, kneeHigh) - kl, 61 Imath::Math<float>::pow(2, 3.5) - kl)), 62 s (255.0 * Imath::Math<float>::pow(2, -3.5 * g)) 63{ 64} 65 66 67float 68Gamma::operator() (half h) 69{ 70 // 71 // Defog 72 // 73 74 float x = max (0.f, (h - d)); 75 76 // 77 // Exposure 78 // 79 80 x *= m; 81 82 // 83 // Knee 84 // 85 86 if (x > kl) 87 x = kl + knee (x - kl, f); 88 89 // 90 // Gamma 91 // 92 93 x = Imath::Math<float>::pow (x, g); 94 95 // 96 // Scale and clamp 97 // 98 99 return Imath::clamp (x * s, 0.f, 255.f); 100} 101