1// tImageHDR.h 
2// 
3// This knows how to load and save a Radiance High Dynamic Range image (.hdr or .rgbe). It knows the details of the hdr 
4// file format and loads the data into a tPixel array. These tPixels may be 'stolen' by the tPicture's constructor if 
5// an HDR file is specified. After the array is stolen the tImageHDR is invalid. This is purely for performance. 
6// 
7// Copyright (c) 2020 Tristan Grimmer. 
8// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby 
9// granted, provided that the above copyright notice and this permission notice appear in all copies. 
10// 
11// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 
12// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 
13// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
14// AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 
15// PERFORMANCE OF THIS SOFTWARE. 
16// 
17// The conversion code for hdr data is a modified version of code from Radiance. Here is the licence. 
18// 
19// The Radiance Software License, Version 1.0 
20// Copyright (c) 1990 - 2015 The Regents of the University of California, through Lawrence Berkeley National Laboratory. All rights reserved. 
21// 
22// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 
23// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 
24// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the 
25// documentation and/or other materials provided with the distribution. 
26// 3. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: 
27// "This product includes Radiance software (http://radsite.lbl.gov/) developed by the Lawrence Berkeley National Laboratory (http://www.lbl.gov/)." 
28// Alternately, this acknowledgment may appear in the software itself, if and wherever such third-party acknowledgments normally appear. 
29// 4. The names "Radiance," "Lawrence Berkeley National Laboratory" and "The Regents of the University of California" must not be used to endorse 
30// or promote products derived from this software without prior written permission. For written permission, please contact radiance@radsite.lbl.gov. 
31// 5. Products derived from this software may not be called "Radiance", nor may "Radiance" appear in their name, without prior written permission of 
32// Lawrence Berkeley National Laboratory. 
33// 
34// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
35// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR ITS CONTRIBUTORS BE LIABLE FOR ANY 
36// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
37// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
38// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
39 
40#pragma once 
41#include <Foundation/tString.h> 
42#include <Math/tColour.h> 
43#include <Image/tPixelFormat.h> 
44namespace tImage 
45
46 
47 
48class tImageHDR 
49
50public
51 inline const static int DefaultExposure = 0
52 
53 // Creates an invalid tImageHDR. You must call Load manually. 
54 tImageHDR() { } 
55 tImageHDR(const tString& hdrFile, float gamma = tMath::DefaultGamma, int exp = DefaultExposure) { Load(hdrFile, gamma, exp); } 
56 
57 // hdrFileInMemory can be deleted after this runs. 
58 tImageHDR(uint8* hdrFileInMemory, int numBytes, float gamma = tMath::DefaultGamma, int exp = DefaultExposure) { Set(hdrFileInMemory, numBytes, gamma, exp); } 
59 
60 // This one sets from a supplied pixel array. It just reads the data (or steals the array if steal set). 
61 tImageHDR(tPixel* pixels, int width, int height, bool steal = false) { Set(pixels, width, height, steal); } 
62 
63 virtual ~tImageHDR() { Clear(); } 
64 
65 // Clears the current tImageHDR before loading. If false returned object is invalid. 
66 bool Load(const tString& hdrFile, float = tMath::DefaultGamma, int = DefaultExposure); 
67 bool Set(uint8* hdrFileInMemory, int numBytes, float = tMath::DefaultGamma, int = DefaultExposure); 
68 
69 // This one sets from a supplied pixel array. 
70 bool Set(tPixel* pixels, int width, int height, bool steal = false); 
71 
72 // Saves the tImageHDR to the hdr file specified. The extension of filename must be "hdr". Returns success. 
73 bool Save(const tString& hdrFile) const
74 
75 // After this call no memory will be consumed by the object and it will be invalid. 
76 void Clear(); 
77 bool IsValid() const { return Pixels ? true : false; } 
78 
79 int GetWidth() const { return Width; } 
80 int GetHeight() const { return Height; } 
81 
82 // After this call you are the owner of the pixels and must eventually delete[] them. This tImageHDR object is 
83 // invalid afterwards. 
84 tPixel* StealPixels(); 
85 tPixel* GetPixels() const { return Pixels; } 
86 tPixelFormat SrcPixelFormat = tPixelFormat::Invalid
87 
88private
89 bool LegacyReadRadianceColours(tPixel* scanline, int length); // Older hdr files use this scanline format. 
90 bool ReadRadianceColours(tPixel* scanline, int length); // Most hdr files use the new scanline format. This will call the old as necessary. 
91 bool ConvertRadianceToGammaCorrected(tPixel* scan, int len); 
92 static void AdjustExposure(tPixel* scan, int len, int adjust); 
93 
94 void PutB(int v) { *WriteP++ = uint8(v); } 
95 uint8 GetB() { return *ReadP++; } 
96 void UngetB(int v) { *(--ReadP) = v; } 
97 
98 int Width = 0
99 int Height = 0
100 tPixel* Pixels = nullptr
101 
102 // Read and write pointers used during processing. 
103 uint8* ReadP = nullptr
104 uint8* WriteP = nullptr
105 
106 // While it would be more efficient to share these tables between instances, we need thread safety. 
107 void SetupGammaTables(float gamma); 
108 void CleanupGammaTables(); 
109 
110 uint8* MantissaTable = nullptr
111 uint8* ExponentTable = nullptr
112 uint8 (*GammaTable)[256] = nullptr
113 
114 // Constants. 
115 const static int MaxGammaShift = 31
116 const static int MinScanLen = 8; // Minimum scanline length for encoding. 
117 const static int MaxScanLen = 0x7FFF; // Maximum scanline length for encoding. 
118 const static int MinRunLen = 4
119 const static int ExpXS = 128; // Excess used for exponent. 
120}; 
121 
122 
123// Implementation below this line. 
124 
125 
126inline void tImageHDR::Clear() 
127
128 Width = 0
129 Height = 0
130 delete[] Pixels
131 Pixels = nullptr
132 SrcPixelFormat = tPixelFormat::Invalid
133
134 
135 
136
137