Skip to content

Commit 81d44f0

Browse files
committed
start to implement .hdr parser
1 parent 37699dc commit 81d44f0

File tree

8 files changed

+229
-1
lines changed

8 files changed

+229
-1
lines changed

.vscode/launch.json

+13
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,19 @@
3131
"externalConsole": false,
3232
"MIMode": "lldb"
3333
},
34+
{
35+
"name": "(Mac OS) Launch Test",
36+
"type": "cppdbg",
37+
"request": "launch",
38+
"program": "${workspaceFolder}/build/Test/HdrParserTest",
39+
"args": [
40+
],
41+
"stopAtEntry": false,
42+
"cwd": "${workspaceFolder}",
43+
"environment": [],
44+
"externalConsole": false,
45+
"MIMode": "lldb"
46+
},
3447
{
3548
"name": "(Windows) Launch Editor",
3649
"type": "cppvsdbg",

External/Darwin/bin/cmft_cli

-8 Bytes
Binary file not shown.

Framework/Common/SceneObjectTexture.hpp

+6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "BMP.hpp"
77
#include "TGA.hpp"
88
#include "DDS.hpp"
9+
#include "HDR.hpp"
910
#include "AssetLoader.hpp"
1011

1112
namespace My {
@@ -60,6 +61,11 @@ namespace My {
6061
DdsParser dds_parser;
6162
m_pImage = std::make_shared<Image>(dds_parser.Parse(buf));
6263
}
64+
else if (ext == ".hdr")
65+
{
66+
HdrParser hdr_parser;
67+
m_pImage = std::make_shared<Image>(hdr_parser.Parse(buf));
68+
}
6369
}
6470
}
6571

Framework/Parser/HDR.hpp

+156
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
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+
}

Framework/Parser/PNG.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ namespace My {
2323
IEND = "IEND"_u32
2424
};
2525

26+
#if DUMP_DETAILS
2627
static std::ostream& operator<<(std::ostream& out, PNG_CHUNK_TYPE type)
2728
{
2829
int32_t n = static_cast<int32_t>(type);
@@ -35,6 +36,7 @@ namespace My {
3536

3637
return out;
3738
}
39+
#endif
3840

3941
struct PNG_CHUNK_HEADER {
4042
uint32_t Length;

Test/CMakeLists.txt

+4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ add_executable(DdsParserTest DdsParserTest.cpp)
2626
target_link_libraries(DdsParserTest Common)
2727
add_test(NAME TEST_DdsParser COMMAND DdsParserTest)
2828

29+
add_executable(HdrParserTest HdrParserTest.cpp)
30+
target_link_libraries(HdrParserTest Common)
31+
add_test(NAME TEST_HdrParser COMMAND HdrParserTest)
32+
2933
IF(WIN32)
3034
add_custom_command(TARGET PngParserTest POST_BUILD
3135
COMMAND ${CMAKE_COMMAND} -E copy_if_different

Test/HdrParserTest.cpp

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#include <iostream>
2+
#include <string>
3+
#include "AssetLoader.hpp"
4+
#include "MemoryManager.hpp"
5+
#include "HDR.hpp"
6+
7+
using namespace std;
8+
using namespace My;
9+
10+
namespace My {
11+
IMemoryManager* g_pMemoryManager = new MemoryManager();
12+
AssetLoader* g_pAssetLoader = new AssetLoader();
13+
}
14+
15+
int main(int argc, const char** argv)
16+
{
17+
g_pMemoryManager->Initialize();
18+
g_pAssetLoader->Initialize();
19+
20+
#ifdef __ORBIS__
21+
g_pAssetLoader->AddSearchPath("/app0");
22+
#endif
23+
24+
{
25+
Buffer buf;
26+
if (argc >= 2) {
27+
buf = g_pAssetLoader->SyncOpenAndReadBinary(argv[1]);
28+
} else {
29+
buf = g_pAssetLoader->SyncOpenAndReadBinary("Textures/hdr/PaperMill_E_3k.hdr");
30+
}
31+
32+
HdrParser hdr_parser;
33+
34+
Image image = hdr_parser.Parse(buf);
35+
36+
cout << image;
37+
}
38+
39+
g_pAssetLoader->Finalize();
40+
g_pMemoryManager->Finalize();
41+
42+
delete g_pAssetLoader;
43+
delete g_pMemoryManager;
44+
45+
return 0;
46+
}
47+

0 commit comments

Comments
 (0)