-
Notifications
You must be signed in to change notification settings - Fork 335
/
Reader.hx
94 lines (82 loc) · 2.54 KB
/
Reader.hx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package hxd.fmt.hdr;
class Reader {
public static function decode( bytes : haxe.io.Bytes, sRGB : Bool ) : { width : Int, height : Int, bytes : haxe.io.Bytes, gamma : Bool } {
var f = new haxe.io.BytesInput(bytes);
var width = 0, height = 0;
var keys = new Map();
while( true ) {
var line = f.readLine();
if( line == "" ) break;
if( line.charCodeAt(0) == "#".code ) continue;
var nameValue = line.split("=");
if( nameValue.length > 1 )
keys.set(nameValue.shift(), nameValue.join("="));
}
var parts = f.readLine().split(" ");
height = Std.parseInt(parts[1]);
width = Std.parseInt(parts[3]);
var gamma = keys.get("GAMMA") == "1";
var data = haxe.io.Bytes.alloc(width * height * 4 * 4);
var exposure = 1.0;
var exp = keys.get("EXPOSURE");
if( exp != null ) {
var exp = Std.parseFloat(exp);
if( exp < 1e-12 || exp < 1e12 ) exposure = exp;
}
var gammaCorrect = sRGB ? 1 : 1 / 2.2;
var gammaVals = [for( e in 0...256 ) Math.pow(e, gammaCorrect)];
var exps = [for( e in 0...256 ) Math.pow(Math.pow(2,e-128) / (256 * exposure), gammaCorrect)];
switch( keys.get("FORMAT") ) {
case "32-bit_rle_rgbe":
var dataPos = f.position;
var scanLen = width * 4;
var scanLine = haxe.io.Bytes.alloc(scanLen);
var widthBE = (width >> 8) | ((width & 0xFF) << 8);
#if hl
var data : hl.Bytes = data;
#end
for( y in 0...height ) {
var h = bytes.getInt32(dataPos);
if( (h&0xFFFF) != 0x0202 || (h>>>16) != widthBE ) {
// raw data
scanLine.blit(0, bytes, dataPos, width * 4);
dataPos += width * 4;
} else {
dataPos += 4;
var p = 0;
var end = width * 4;
while( p < end ) {
var len = bytes.get(dataPos++);
if( len > 128 ) {
len -= 128;
scanLine.fill(p, len, bytes.get(dataPos++));
} else {
scanLine.blit(p, bytes, dataPos, len);
dataPos += len;
}
p += len;
}
}
var pos = y * width * 16;
inline function output( v : Float ) {
#if hl
data.setF32(pos,v);
#else
data.setFloat(pos, v);
#end
pos += 4;
}
for( x in 0...width ) {
var e = exps[scanLine.get(x+width*3)];
output(gammaVals[scanLine.get(x)] * e);
output(gammaVals[scanLine.get(x+width)] * e);
output(gammaVals[scanLine.get(x+(width<<1))] * e);
output(1.0);
}
}
case fmt:
throw "Unsupported HDR format "+fmt;
}
return { width : width, height : height, bytes : data, gamma : gamma };
}
}