3 #define TINYEXR_USE_STB_ZLIB 1
4 #define TINYEXR_USE_MINIZ 0
5 #define TINYEXR_IMPLEMENTATION
11 -> std::tuple<size_t, size_t, std::vector<float>>
14 wmtk::logger().debug(
"[load_image_exr_red_channel] start \"{}\"", path.string());
15 assert(std::filesystem::exists(path));
16 const std::string filename_ = path.string();
17 const char* filename = filename_.c_str();
19 const auto exr_version = [&filename, &path]() -> EXRVersion {
20 EXRVersion exr_version_;
22 const auto ret = ParseEXRVersionFromFile(&exr_version_, filename);
23 if (ret != TINYEXR_SUCCESS) {
24 wmtk::logger().error(
"failed LoadImageEXR \"{}\" \"version error\"", path.string());
25 throw std::runtime_error(
"LoadImageEXRError");
28 if (exr_version_.multipart || exr_version_.non_image) {
30 "failed LoadImageEXR \"{}\" \"multipart or non image\"",
32 throw std::runtime_error(
"LoadImageEXRError");
38 auto exr_header_data =
39 [&filename, &path, &exr_version]() -> std::tuple<EXRHeader, int> {
40 EXRHeader exr_header_;
41 InitEXRHeader(&exr_header_);
43 [[maybe_unused]]
const char* err =
nullptr;
44 const auto ret = ParseEXRHeaderFromFile(&exr_header_, &exr_version, filename, &err);
45 if (ret != TINYEXR_SUCCESS) {
46 wmtk::logger().error(
"failed LoadImageEXR \"{}\" \"header error\"", path.string());
47 FreeEXRHeader(&exr_header_);
48 throw std::runtime_error(
"LoadImageEXRError");
52 for (
int i = 0; i < exr_header_.num_channels; i++) {
53 if (exr_header_.pixel_types[i] != exr_header_.pixel_types[0] ||
54 exr_header_.requested_pixel_types[i] != exr_header_.pixel_types[i]) {
56 "failed LoadImageEXR \"{}\" \"inconsistent pixel_types\"",
58 FreeEXRHeader(&exr_header_);
59 throw std::runtime_error(
"LoadImageEXRError");
64 for (
int i = 0; i < exr_header_.num_channels; i++) {
65 if (exr_header_.pixel_types[i] == TINYEXR_PIXELTYPE_HALF) {
66 exr_header_.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
71 if (exr_header_.requested_pixel_types[0] != TINYEXR_PIXELTYPE_FLOAT) {
73 "failed LoadImageEXR \"{}\" \"only float exr are supported\"",
75 FreeEXRHeader(&exr_header_);
76 throw std::runtime_error(
"LoadImageEXRError");
80 if (exr_header_.tiled) {
82 "failed LoadImageEXR \"{}\" \"only non tiled exr are supported\"",
84 FreeEXRHeader(&exr_header_);
85 throw std::runtime_error(
"LoadImageEXRError");
90 for (
int i = 0; i < exr_header_.num_channels; i++) {
91 if (strcmp(exr_header_.channels[i].name,
"R") == 0) index_red_ = i;
94 wmtk::logger().warn(
"Could not find R channel. Looking for Y channel instead.");
95 for (
int i = 0; i < exr_header_.num_channels; i++) {
96 if (strcmp(exr_header_.channels[i].name,
"Y") == 0) index_red_ = i;
100 if (index_red_ < 0) {
101 std::vector<std::string> channels;
102 for (
int i = 0; i < exr_header_.num_channels; i++) {
103 channels.push_back(exr_header_.channels[i].name);
106 "failed LoadImageEXR \"{}\" can't find all expected channels: [{}]",
108 fmt::join(channels,
","));
109 FreeEXRHeader(&exr_header_);
110 throw std::runtime_error(
"LoadImageEXRError");
113 return {exr_header_, index_red_};
115 auto& exr_header = std::get<0>(exr_header_data);
116 const auto& index_data = std::get<1>(exr_header_data);
118 auto exr_image = [&filename, &path, &exr_header]() -> EXRImage {
120 InitEXRImage(&exr_image_);
122 [[maybe_unused]]
const char* err =
nullptr;
123 const auto ret = LoadEXRImageFromFile(&exr_image_, &exr_header, filename, &err);
124 if (ret != TINYEXR_SUCCESS) {
126 "failed LoadImageEXR \"{}\" \"failed to load image data\"",
128 FreeEXRHeader(&exr_header);
129 FreeEXRImage(&exr_image_);
130 throw std::runtime_error(
"LoadImageEXRError");
137 "[load_image_exr_red_channel] num_channels {} tiled {}",
138 exr_header.num_channels,
140 wmtk::logger().debug(
"[load_image_exr_red_channel] index_data {}", index_data);
141 assert(index_data >= 0);
142 assert(!exr_header.tiled);
144 std::vector<float> data_r;
145 data_r.reserve(
static_cast<size_t>(exr_image.width) *
static_cast<size_t>(exr_image.height));
147 const auto images =
reinterpret_cast<float**
>(exr_image.images);
148 for (
int i = 0; i < exr_image.width * exr_image.height; i++)
149 data_r.emplace_back(images[index_data][i]);
151 FreeEXRHeader(&exr_header);
152 FreeEXRImage(&exr_image);
154 wmtk::logger().debug(
"[load_image_exr_red_channel] done \"{}\"", path.string());
157 static_cast<size_t>(exr_image.width),
158 static_cast<size_t>(exr_image.height),
164 tuple<size_t, size_t, int, int, int, std::vector<float>, std::vector<float>, std::vector<float>>
166 using namespace wmtk;
167 wmtk::logger().debug(
"[load_image_exr_red_channel] start \"{}\"", path.string());
168 assert(std::filesystem::exists(path));
169 const std::string filename_ = path.string();
170 const char* filename = filename_.c_str();
172 const auto exr_version = [&filename, &path]() -> EXRVersion {
173 EXRVersion exr_version_;
175 const auto ret = ParseEXRVersionFromFile(&exr_version_, filename);
176 if (ret != TINYEXR_SUCCESS) {
177 wmtk::logger().error(
"failed LoadImageEXR \"{}\" \"version error\"", path.string());
178 throw std::runtime_error(
"LoadImageEXRError");
181 if (exr_version_.multipart || exr_version_.non_image) {
183 "failed LoadImageEXR \"{}\" \"multipart or non image\"",
185 throw std::runtime_error(
"LoadImageEXRError");
191 auto exr_header_data =
192 [&filename, &path, &exr_version]() -> std::tuple<EXRHeader, int, int, int> {
193 EXRHeader exr_header_;
194 InitEXRHeader(&exr_header_);
196 [[maybe_unused]]
const char* err =
nullptr;
197 const auto ret = ParseEXRHeaderFromFile(&exr_header_, &exr_version, filename, &err);
198 if (ret != TINYEXR_SUCCESS) {
199 wmtk::logger().error(
"failed LoadImageEXR \"{}\" \"header error\"", path.string());
200 FreeEXRHeader(&exr_header_);
201 throw std::runtime_error(
"LoadImageEXRError");
205 for (
int i = 0; i < exr_header_.num_channels; i++) {
206 if (exr_header_.pixel_types[i] != exr_header_.pixel_types[0] ||
207 exr_header_.requested_pixel_types[i] != exr_header_.pixel_types[i]) {
209 "failed LoadImageEXR \"{}\" \"inconsistent pixel_types\"",
211 FreeEXRHeader(&exr_header_);
212 throw std::runtime_error(
"LoadImageEXRError");
217 for (
int i = 0; i < exr_header_.num_channels; i++) {
218 if (exr_header_.pixel_types[i] == TINYEXR_PIXELTYPE_HALF) {
219 exr_header_.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
224 if (exr_header_.requested_pixel_types[0] != TINYEXR_PIXELTYPE_FLOAT) {
226 "failed LoadImageEXR \"{}\" \"only float exr are supported\"",
228 FreeEXRHeader(&exr_header_);
229 throw std::runtime_error(
"LoadImageEXRError");
233 if (exr_header_.tiled) {
235 "failed LoadImageEXR \"{}\" \"only non tiled exr are supported\"",
237 FreeEXRHeader(&exr_header_);
238 throw std::runtime_error(
"LoadImageEXRError");
243 int index_green_ = -1;
244 int index_blue_ = -1;
245 if (exr_header_.num_channels == 1) {
246 wmtk::logger().warn(
"Treat grayscale image as RGB: {}", path.string());
251 for (
int i = 0; i < exr_header_.num_channels; i++) {
252 if (strcmp(exr_header_.channels[i].name,
"R") == 0) index_red_ = i;
253 if (strcmp(exr_header_.channels[i].name,
"G") == 0) index_green_ = i;
254 if (strcmp(exr_header_.channels[i].name,
"B") == 0) index_blue_ = i;
258 if (index_red_ < 0) {
259 std::vector<std::string> channels;
260 for (
int i = 0; i < exr_header_.num_channels; i++) {
261 channels.push_back(exr_header_.channels[i].name);
264 "failed LoadImageEXR \"{}\" can't find all 3 expected channels: [{}]",
266 fmt::join(channels,
","));
267 FreeEXRHeader(&exr_header_);
268 throw std::runtime_error(
"LoadImageEXRError");
271 return {exr_header_, index_red_, index_green_, index_blue_};
273 auto& exr_header = std::get<0>(exr_header_data);
274 const auto& index_red = std::get<1>(exr_header_data);
275 const auto& index_green = std::get<2>(exr_header_data);
276 const auto& index_blue = std::get<3>(exr_header_data);
278 auto exr_image = [&filename, &path, &exr_header]() -> EXRImage {
280 InitEXRImage(&exr_image_);
282 [[maybe_unused]]
const char* err =
nullptr;
283 const auto ret = LoadEXRImageFromFile(&exr_image_, &exr_header, filename, &err);
284 if (ret != TINYEXR_SUCCESS) {
286 "failed LoadImageEXR \"{}\" \"failed to load image data\"",
288 FreeEXRHeader(&exr_header);
289 FreeEXRImage(&exr_image_);
290 throw std::runtime_error(
"LoadImageEXRError");
297 "[load_image_exr_3channels] num_channels {} tiled {}",
298 exr_header.num_channels,
300 wmtk::logger().debug(
"[load_image_exr_3channels] index_red {}", index_red);
301 wmtk::logger().debug(
"[load_image_exr_3channels] index_green {}", index_green);
302 wmtk::logger().debug(
"[load_image_exr_3channels] index_blue {}", index_blue);
303 assert(index_red >= 0);
304 assert(index_green >= 0);
305 assert(index_blue >= 0);
306 assert(!exr_header.tiled);
308 std::vector<float> data_r;
309 std::vector<float> data_g;
310 std::vector<float> data_b;
311 data_r.reserve(
static_cast<size_t>(exr_image.width) *
static_cast<size_t>(exr_image.height));
312 data_g.reserve(
static_cast<size_t>(exr_image.width) *
static_cast<size_t>(exr_image.height));
313 data_b.reserve(
static_cast<size_t>(exr_image.width) *
static_cast<size_t>(exr_image.height));
315 const auto images =
reinterpret_cast<float**
>(exr_image.images);
316 for (
int i = 0; i < exr_image.width * exr_image.height; i++) {
317 data_r.emplace_back(images[index_red][i]);
318 data_g.emplace_back(images[index_green][i]);
319 data_b.emplace_back(images[index_blue][i]);
321 FreeEXRHeader(&exr_header);
322 FreeEXRImage(&exr_image);
324 wmtk::logger().debug(
"[load_image_exr_3channels] done \"{}\"", path.string());
327 static_cast<size_t>(exr_image.width),
328 static_cast<size_t>(exr_image.height),
329 std::move(index_red),
330 std::move(index_green),
331 std::move(index_blue),
auto load_image_exr_split_3channels(const std::filesystem::path &path) -> std::tuple< size_t, size_t, int, int, int, std::vector< float >, std::vector< float >, std::vector< float >>
auto load_image_exr_red_channel(const std::filesystem::path &path) -> std::tuple< size_t, size_t, std::vector< float >>
spdlog::logger & logger()
Retrieves the current logger.