43 InitEXRImage(&exrImage);
45 const char *err =
nullptr;
47 const std::filesystem::path abs_path = std::filesystem::absolute(filename);
48 const std::string file_str = abs_path.string();
49 const char *file_c_str = file_str.c_str();
51 PLOGI <<
"ExrLoader: input=" << filename <<
" absolute=" << abs_path
52 <<
" exists=" << std::filesystem::exists(abs_path);
56 InitEXRHeader(&header);
57 const EXRVersion version = {};
59 int parseResult = ParseEXRHeaderFromFile(&header, &version, file_c_str, &err);
60 if (parseResult != TINYEXR_SUCCESS) {
62 PLOGE <<
"Error parsing EXR header: " << err;
63 FreeEXRErrorMessage(err);
65 PLOGE <<
"Unknown error while parsing EXR file";
67 FreeEXRImage(&exrImage);
68 FreeEXRHeader(&header);
73 int result = LoadEXRImageFromFile(&exrImage, &header, file_c_str, &err);
74 if (result != TINYEXR_SUCCESS) {
76 PLOGE <<
"Error parsing EXR file: " << err;
77 FreeEXRErrorMessage(err);
79 PLOGE <<
"Unknown error while parsing EXR file";
81 FreeEXRImage(&exrImage);
82 FreeEXRHeader(&header);
86 PLOGI <<
"Loaded EXR: " << exrImage.width <<
"x" << exrImage.height
87 <<
" with " << exrImage.num_channels <<
" channels.";
89 tinygltf::Image image;
90 image.width = exrImage.width;
91 image.height = exrImage.height;
92 image.mimeType =
"image/x-exr";
93 image.uri = filename.string();
94 image.name = file_str;
99 image.pixel_type = TINYGLTF_COMPONENT_TYPE_FLOAT;
100 image.component = exrImage.num_channels;
103 if (image.component < 3) {
104 PLOGW <<
"EXR has less than 3 channels (" << image.component <<
"). glTF might expect RGB.";
111 const size_t bytes_per_component = image.bits / 8;
112 const size_t totalPixels =
static_cast<size_t>(image.width) * image.height;
113 const size_t totalBytes = totalPixels * image.component * bytes_per_component;
114 image.image.resize(totalBytes);
118 float *src_channels[4] = {
nullptr,
nullptr,
nullptr,
nullptr};
119 for (
int c = 0; c < std::min(exrImage.num_channels, 4); ++c) {
120 src_channels[c] =
reinterpret_cast<float *
>(exrImage.images[c]);
124 unsigned char *dest_ptr = image.image.data();
125 for (
int y = 0; y < image.height; ++y) {
126 for (
int x = 0; x < image.width; ++x) {
127 int pixel_idx = y * image.width + x;
128 for (
int c = 0; c < image.component; ++c) {
136 int actual_src_channel_idx = c;
137 if (image.component >= 3) {
141 actual_src_channel_idx = 2;
144 actual_src_channel_idx = 0;
151 if (actual_src_channel_idx < std::min(exrImage.num_channels, 4) && src_channels[
152 actual_src_channel_idx] !=
nullptr) {
153 value = src_channels[actual_src_channel_idx][pixel_idx];
157 memcpy(dest_ptr, &value, bytes_per_component);
158 dest_ptr += bytes_per_component;
164 FreeEXRImage(&exrImage);
165 FreeEXRHeader(&header);
179 InitEXRHeader(&header);
180 const EXRVersion version = {};
182 const char *err =
nullptr;
184 const std::string file_str = path.string();
185 const char *file_c_str = file_str.c_str();
188 int result = ParseEXRHeaderFromFile(&header, &version, file_c_str, &err);
189 if (result != TINYEXR_SUCCESS) {
191 PLOGE <<
"Error parsing EXR header: " << err;
192 FreeEXRErrorMessage(err);
194 PLOGE <<
"Unknown error while parsing EXR file";
196 FreeEXRHeader(&header);
200 FreeEXRHeader(&header);
201 return headerWrapper;