2
// This unit is part of the GLScene Engine https://github.com/glscene
5
HDR File support for GLScene.
8
04/11/10 - DaStr - Added Delphi5 and Delphi6 compatibility
9
23/08/10 - Yar - Replaced OpenGL1x to OpenGLTokens
10
08/05/10 - Yar - Removed check for residency in AssignFromTexture
11
22/04/10 - Yar - Fixes after GLState revision
12
23/11/10 - DaStr - Added $I GLScene.inc
13
23/01/10 - Yar - Added to AssignFromTexture CurrentFormat parameter
14
20/01/10 - Yar - Creation
40
TGLHDRImage = class(TGLBaseImage)
42
function GetProgramType: Ansistring;
43
procedure SetProgramType(aval: Ansistring);
45
fGamma: Single; // image has already been gamma corrected with
46
// given gamma. defaults to 1.0 (no correction) */
47
fExposure: Single; // a value of 1.0 in an image corresponds to
48
// <exposure> watts/steradian/m^2.
50
fProgramType: string[16];
52
class function Capabilities: TGLDataFileCapabilities; override;
54
procedure LoadFromFile(const filename: string); override;
55
procedure LoadFromStream(stream: TStream); override;
57
procedure AssignFromTexture(textureContext: TGLContext;
58
const textureHandle: TGLuint;
59
textureTarget: TGLTextureTarget;
60
const CurrentFormat: Boolean;
61
const intFormat: TGLInternalFormat); reintroduce;
63
property Gamma: Single read fGamma;
64
property Exposure: Single read fExposure;
65
property ProgramType: Ansistring read GetProgramType write SetProgramType;
67
//---------------------------------------------------------------------
68
//---------------------------------------------------------------------
69
//---------------------------------------------------------------------
71
//---------------------------------------------------------------------
72
//---------------------------------------------------------------------
73
//---------------------------------------------------------------------
76
// ------------------ TGLHDRImage ------------------
82
procedure TGLHDRImage.LoadFromFile(const filename: string);
86
if FileStreamExists(fileName) then
88
fs := CreateFileStream(fileName, fmOpenRead);
93
ResourceName := filename;
97
raise EInvalidRasterFile.CreateFmt('File %s not found', [filename]);
100
procedure TGLHDRImage.LoadFromStream(stream: TStream);
102
cRgbeFormat32bit = 'FORMAT=32-bit_rle_rgbe';
104
cEXPOSURE = 'EXPOSURE=';
107
buf: array[0..1023] of AnsiChar;
111
tempBuf, top, bottom: PByte;
113
formatDefined: boolean;
115
function CmpWord(const word: string): boolean;
121
ts := header.Strings[i];
122
if Length(word) > Length(ts) then
124
for l := 1 to Length(word) do
125
if word[l] <> ts[l] then
136
stream.Read(buf, Length(buf) * sizeOf(AnsiChar));
137
header := TStringList.Create;
141
while i < Length(buf) do
153
s := s + string(buf[i]);
156
if i < Length(buf) then
159
raise EInvalidRasterFile.Create('Can''t find HDR header end.');
161
if (header.Strings[0][1] <> '#') or (header.Strings[0][2] <> '?') then
164
raise EInvalidRasterFile.Create('Bad HDR initial token.');
167
SetProgramtype(AnsiString(Copy(header.Strings[0], 3, Length(header.Strings[0])
170
formatDefined := false;
171
for i := 1 to header.Count - 1 do
173
if header.Strings[i] = cRgbeFormat32bit then
174
formatDefined := true
175
else if CmpWord(cGamma) then
178
s := Copy(header.Strings[i], j + 1, Length(header.Strings[i]) - j);
181
raise EInvalidRasterFile.Create('Bad HDR header.');
183
else if CmpWord(cEXPOSURE) then
185
j := Length(cEXPOSURE);
186
s := Copy(header.Strings[i], j + 1, Length(header.Strings[i]) - j);
187
val(s, fExposure, err);
189
raise EInvalidRasterFile.Create('Bad HDR header.');
191
else if CmpWord(cY) then
194
s := Copy(header.Strings[i], j + 1, Length(header.Strings[i]) - j);
196
sn := Copy(s, 1, j - 1);
197
val(sn, FLOD[0].Height, err);
198
Delete(s, 1, j + 3); // scip '+X '
199
val(s, FLOD[0].Width, err);
201
raise EInvalidRasterFile.Create('Bad HDR header.');
206
if not formatDefined then
207
raise EInvalidRasterFile.Create('no FORMAT specifier found.');
209
if (FLOD[0].Width = 0) or (FLOD[0].Height = 0) then
210
raise EInvalidRasterFile.Create('Bad image dimension.');
211
//set all the parameters
213
fColorFormat := GL_RGB;
214
fInternalFormat := tfRGBA_FLOAT32;
215
fDataType := GL_FLOAT;
217
fTextureArray := false;
218
fElementSize := GetTextureElementSize(tfFLOAT_RGB32);
219
ReallocMem(fData, DataSize);
220
LoadRLEpixels(stream, PSingle(fData), FLOD[0].Width, FLOD[0].Height);
222
//hdr images come in upside down then flip it
223
lineSize := fElementSize * FLOD[0].Width;
224
GetMem(tempBuf, lineSize);
227
Inc(bottom, lineSize * (FLOD[0].Height - 1));
228
for j := 0 to (FLOD[0].Height div 2) - 1 do
230
Move(top^, tempBuf^, lineSize);
231
Move(bottom^, top^, lineSize);
232
Move(tempBuf^, bottom^, lineSize);
234
Dec(bottom, lineSize);
239
function TGLHDRImage.GetProgramType: Ansistring;
241
Result := fProgramType;
244
procedure TGLHDRImage.SetProgramType(aval: Ansistring);
248
for i := 1 to Length(fProgramType) do
249
fProgramType[i] := aval[i];
255
procedure TGLHDRImage.AssignFromTexture(textureContext: TGLContext;
256
const textureHandle: TGLuint;
257
textureTarget: TGLTextureTarget;
258
const CurrentFormat: Boolean;
259
const intFormat: TGLInternalFormat);
261
oldContext: TGLContext;
262
contextActivate: Boolean;
264
residentFormat: TGLInternalFormat;
267
glTarget := DecodeGLTextureTarget(textureTarget);
268
if not ((glTarget = GL_TEXTURE_2D)
269
or (glTarget = GL_TEXTURE_RECTANGLE)) then
272
oldContext := CurrentGLContext;
273
contextActivate := (oldContext <> textureContext);
274
if contextActivate then
276
if Assigned(oldContext) then
277
oldContext.Deactivate;
278
textureContext.Activate;
282
textureContext.GLStates.TextureBinding[0, textureTarget] := textureHandle;
285
fTextureArray := false;
286
fColorFormat := GL_RGB;
287
fDataType := GL_FLOAT;
288
// Check level existence
289
GL.GetTexLevelParameteriv(glTarget, 0, GL_TEXTURE_INTERNAL_FORMAT, @texFormat);
290
if texFormat > 1 then
292
GL.GetTexLevelParameteriv(glTarget, 0, GL_TEXTURE_WIDTH, @FLOD[0].Width);
293
GL.GetTexLevelParameteriv(glTarget, 0, GL_TEXTURE_HEIGHT, @FLOD[0].Height);
295
residentFormat := OpenGLFormatToInternalFormat(texFormat);
296
if CurrentFormat then
297
fInternalFormat := residentFormat
299
fInternalFormat := intFormat;
303
if fLevelCount > 0 then
305
fElementSize := GetTextureElementSize(fColorFormat, fDataType);
306
ReallocMem(FData, DataSize);
307
GL.GetTexImage(glTarget, 0, fColorFormat, fDataType, fData);
313
if contextActivate then
315
textureContext.Deactivate;
316
if Assigned(oldContext) then
325
class function TGLHDRImage.Capabilities: TGLDataFileCapabilities;
327
Result := [dfcRead {, dfcWrite}];
331
{ Register this Fileformat-Handler with GLScene }
332
RegisterRasterFormat('hdr', 'High Dynamic Range Image', TGLHDRImage);