1
+ #pragma once
2
+ #include < cstdio>
3
+ #include < cstring>
4
+ #include " ImageParser.hpp"
5
+
6
+ namespace My {
7
+ static inline void
8
+ rgbe2float (float *red, float *green, float *blue, unsigned char rgbe[4 ])
9
+ {
10
+ float f;
11
+
12
+ if (rgbe[3 ]) { /* nonzero pixel*/
13
+ f = ldexp (1 .0f , rgbe[3 ]-(int )(128 +8 ));
14
+ *red = rgbe[0 ] * f;
15
+ *green = rgbe[1 ] * f;
16
+ *blue = rgbe[2 ] * f;
17
+ }
18
+ else
19
+ *red = *green = *blue = 0 .0f ;
20
+ }
21
+
22
+ class HdrParser : implements ImageParser
23
+ {
24
+ public:
25
+ virtual Image Parse (Buffer& buf)
26
+ {
27
+ Image img;
28
+ char * pData = reinterpret_cast <char *>(buf.GetData ());
29
+ auto remain_size = buf.GetDataSize ();
30
+
31
+ if (std::strncmp (pData, " #?RADIANCE\n " , sizeof (" #?RADIANCE\n " )))
32
+ {
33
+ std::cerr << " Image File is HDR format" << std::endl;
34
+ pData += sizeof (" #?RADIANCE" );
35
+
36
+ // process the header
37
+ while (*pData != ' \n ' )
38
+ {
39
+ char * p = pData;
40
+ // find the line end
41
+ while (*++p != ' \n ' && --remain_size > 0 ) {}
42
+ if (remain_size == 0 ) break ;
43
+ assert (*p == ' \n ' );
44
+ *p = ' \0 ' ;
45
+ if (*pData == ' #' )
46
+ {
47
+ // comment line, just ignore it
48
+ std::cerr << pData << std::endl;
49
+ }
50
+ else
51
+ {
52
+ // assignments
53
+ std::cerr << pData << std::endl;
54
+ }
55
+
56
+ if (remain_size)
57
+ {
58
+ pData = p + 1 ;
59
+ remain_size--;
60
+ }
61
+ else
62
+ {
63
+ break ;
64
+ }
65
+ }
66
+
67
+ // process dimension
68
+ assert (remain_size > 8 );
69
+
70
+ pData++;
71
+ remain_size--;
72
+
73
+ // find the line end
74
+ char * p = pData;
75
+ while (*++p != ' \n ' && --remain_size > 0 ) {}
76
+ if (remain_size == 0 ) assert (0 );
77
+ assert (*p == ' \n ' );
78
+ *p = ' \0 ' ;
79
+
80
+ char axis1[2 ];
81
+ char axis2[2 ];
82
+ size_t dimension1;
83
+ size_t dimension2;
84
+ std::sscanf (pData, " %2c %zu %2c %zu" , axis1, &dimension1, axis2, &dimension2);
85
+
86
+ if (axis1[1 ] == ' Y' )
87
+ {
88
+ img.Height = dimension1;
89
+ assert (axis2[1 ] == ' X' );
90
+ img.Width = dimension2;
91
+ }
92
+ else
93
+ {
94
+ assert (axis1[1 ] == ' X' );
95
+ img.Width = dimension1;
96
+ assert (axis2[1 ] == ' X' );
97
+ img.Height = dimension2;
98
+ }
99
+
100
+ assert (remain_size);
101
+ *p++ = ' \n ' ;
102
+ remain_size--;
103
+
104
+ pData = p;
105
+ assert (remain_size);
106
+ }
107
+
108
+ img.bitcount = 32 * 3 ; // float[3]
109
+ img.pitch = (img.bitcount >> 3 ) * img.Width ;
110
+ img.data_size = img.pitch * img.Height ;
111
+ img.data = new uint8_t [img.data_size ];
112
+
113
+ // now data section
114
+ assert (remain_size <= 4 * img.Height * img.Width );
115
+ float r, g, b;
116
+ unsigned char (*pRGBE)[4 ] = reinterpret_cast <unsigned char (*)[4 ]>(pData);
117
+ float (*pOutData)[3 ] = reinterpret_cast <float (*)[3 ]>(img.data );
118
+ if ((*pRGBE)[0 ] == 2 && (*pRGBE)[1 ] == 2 && (*pRGBE)[2 ] == img.Width >> 8 && (*pRGBE)[3 ] == (img.Width & 0xFF ))
119
+ {
120
+ // the file IS run lenght encoded
121
+ std::cerr << " The file *IS* run-length encoded" << std::endl;
122
+ }
123
+ else {
124
+ std::cerr << " The file is *NOT* run-length encoded" << std::endl;
125
+ // the file is NOT run lenght encoded
126
+ while (remain_size)
127
+ {
128
+ if ((*pRGBE)[0 ] == 255 && (*pRGBE)[1 ] == 255 && (*pRGBE)[2 ] == 255 )
129
+ {
130
+ uint8_t repeat_times = (*pRGBE)[3 ];
131
+ for (uint8_t i = 0 ; i < repeat_times; i++)
132
+ {
133
+ (*pOutData)[0 ] = r;
134
+ (*pOutData)[1 ] = g;
135
+ (*pOutData)[2 ] = b;
136
+ }
137
+
138
+ remain_size -= 4 ;
139
+ pRGBE++;
140
+ }
141
+
142
+ rgbe2float (&r, &g, &b, *pRGBE);
143
+ (*pOutData)[0 ] = r;
144
+ (*pOutData)[1 ] = g;
145
+ (*pOutData)[2 ] = b;
146
+
147
+ remain_size -= 4 ;
148
+ pRGBE++;
149
+ pOutData++;
150
+ }
151
+ }
152
+
153
+ return img;
154
+ }
155
+ };
156
+ }
0 commit comments