1// ======================================================================== //
2// Copyright 2009-2019 Intel Corporation //
3// //
4// Licensed under the Apache License, Version 2.0 (the "License"); //
5// you may not use this file except in compliance with the License. //
6// You may obtain a copy of the License at //
7// //
8// http://www.apache.org/licenses/LICENSE-2.0 //
9// //
10// Unless required by applicable law or agreed to in writing, software //
11// distributed under the License is distributed on an "AS IS" BASIS, //
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
13// See the License for the specific language governing permissions and //
14// limitations under the License. //
15// ======================================================================== //
16
17#include "transfer_function.h"
18
19namespace oidn {
20
21 const float LogTransferFunction::xScale = 1.f / log(LogTransferFunction::yMax + 1.f);
22 const float PQXTransferFunction::xScale = 1.f / PQXTransferFunction::pqxForward(PQXTransferFunction::yMax * PQXTransferFunction::yScale);
23
24 float AutoexposureNode::autoexposure(const Image& color)
25 {
26 assert(color.format == Format::Float3);
27
28 constexpr float key = 0.18f;
29 constexpr float eps = 1e-8f;
30 constexpr int K = 16; // downsampling amount
31
32 // Downsample the image to minimize sensitivity to noise
33 const int H = color.height; // original height
34 const int W = color.width; // original width
35 const int HK = (H + K/2) / K; // downsampled height
36 const int WK = (W + K/2) / K; // downsampled width
37
38 // Compute the average log luminance of the downsampled image
39 using Sum = std::pair<float, int>;
40
41 // -- GODOT start --
42 // Sum sum =
43 // tbb::parallel_reduce(
44 // tbb::blocked_range2d<int>(0, HK, 0, WK),
45 // Sum(0.f, 0),
46 // [&](const tbb::blocked_range2d<int>& r, Sum sum) -> Sum
47 // {
48 // // Iterate over blocks
49 // for (int i = r.rows().begin(); i != r.rows().end(); ++i)
50 // {
51 // for (int j = r.cols().begin(); j != r.cols().end(); ++j)
52 // {
53
54 Sum sum = Sum(0.0f, 0);
55
56 for (int i = 0; i != HK; ++i)
57 {
58 for (int j = 0; j != WK; ++j)
59 {
60 // Compute the average luminance in the current block
61 const int beginH = int(ptrdiff_t(i) * H / HK);
62 const int beginW = int(ptrdiff_t(j) * W / WK);
63 const int endH = int(ptrdiff_t(i+1) * H / HK);
64 const int endW = int(ptrdiff_t(j+1) * W / WK);
65
66 float L = 0.f;
67
68 for (int h = beginH; h < endH; ++h)
69 {
70 for (int w = beginW; w < endW; ++w)
71 {
72 const float* rgb = (const float*)color.get(h, w);
73
74 const float r = maxSafe(rgb[0], 0.f);
75 const float g = maxSafe(rgb[1], 0.f);
76 const float b = maxSafe(rgb[2], 0.f);
77
78 L += luminance(r, g, b);
79 }
80 }
81
82 L /= (endH - beginH) * (endW - beginW);
83
84 // Accumulate the log luminance
85 if (L > eps)
86 {
87 sum.first += log2(L);
88 sum.second++;
89 }
90 }
91 }
92
93 // return sum;
94 // },
95 // [](Sum a, Sum b) -> Sum { return Sum(a.first+b.first, a.second+b.second); },
96 // tbb::static_partitioner()
97 // );
98 // -- GODOT end --
99
100 return (sum.second > 0) ? (key / exp2(sum.first / float(sum.second))) : 1.f;
101 }
102
103} // namespace oidn
104