Wildmeshing Toolkit
Loading...
Searching...
No Matches
save_image_exr.cpp
Go to the documentation of this file.
1#include "save_image_exr.hpp"
2#define TINYEXR_USE_STB_ZLIB 1
3#define TINYEXR_USE_MINIZ 0
4#include <tinyexr.h>
5#include <cassert>
9 size_t width,
10 size_t height,
11 const std::vector<float>& data,
12 const std::filesystem::path& path)
13{
14 EXRHeader header;
15 InitEXRHeader(&header);
16
17 EXRImage image;
18 InitEXRImage(&image);
19
20 image.num_channels = 3;
21
22 std::vector<float> images[3];
23 images[0].resize(width * height);
24 images[1].resize(width * height);
25 images[2].resize(width * height);
26
27 // Split RGBRGBRGB... into R, G and B layer
28 for (int i = 0; i < width * height; i++) {
29 images[0][i] = data[i];
30 images[1][i] = -1.;
31 images[2][i] = -1.;
32 }
33
34 float* image_ptr[3];
35 image_ptr[0] = &(images[2].at(0)); // B
36 image_ptr[1] = &(images[1].at(0)); // G
37 image_ptr[2] = &(images[0].at(0)); // R
38
39 image.images = (unsigned char**)image_ptr;
40 image.width = width;
41 image.height = height;
42
43 header.num_channels = 3;
44 header.channels = (EXRChannelInfo*)malloc(sizeof(EXRChannelInfo) * header.num_channels);
45 // Must be (A)BGR order, since most of EXR viewers expect this channel order.
46 strncpy(header.channels[0].name, "B", 255);
47 header.channels[0].name[strlen("B")] = '\0';
48 strncpy(header.channels[1].name, "G", 255);
49 header.channels[1].name[strlen("G")] = '\0';
50 strncpy(header.channels[2].name, "R", 255);
51 header.channels[2].name[strlen("R")] = '\0';
52
53 header.pixel_types = (int*)malloc(sizeof(int) * header.num_channels);
54 header.requested_pixel_types = (int*)malloc(sizeof(int) * header.num_channels);
55 for (int i = 0; i < header.num_channels; i++) {
56 header.pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT; // pixel type of input image
57 header.requested_pixel_types[i] =
58 TINYEXR_PIXELTYPE_HALF; // pixel type of output image to be stored in .EXR
59 }
60
61 const char* err = NULL; // or nullptr in C++11 or later.
62 int ret = SaveEXRImageToFile(&image, &header, path.string().data(), &err);
63 if (ret != TINYEXR_SUCCESS) {
64 fprintf(stderr, "Save EXR err: %s\n", err);
65 FreeEXRErrorMessage(err); // free's buffer for an error message
66 return ret;
67 }
68 wmtk::logger().debug("Saved exr file. {} ", path);
69
70 free(header.channels);
71 free(header.pixel_types);
72 free(header.requested_pixel_types);
73 return 0;
74}
75
77 size_t width,
78 size_t height,
79 int r,
80 int g,
81 int b,
82 const std::vector<float>& data_r,
83 const std::vector<float>& data_g,
84 const std::vector<float>& data_b,
85 const std::filesystem::path& path)
86{
87 EXRHeader header;
88 InitEXRHeader(&header);
89
90 EXRImage image;
91 InitEXRImage(&image);
92
93 image.num_channels = 3;
94
95 std::vector<float> images[3];
96 images[0].resize(width * height);
97 images[1].resize(width * height);
98 images[2].resize(width * height);
99
100 // Split RGBRGBRGB... into R, G and B layer
101 for (int i = 0; i < width * height; i++) {
102 images[r][i] = data_r[i];
103 images[g][i] = data_g[i];
104 images[b][i] = data_b[i];
105 }
107 .info("[save r {} {}, g {} {} b {} {}]", r, images[r][0], g, images[g][0], b, images[b][0]);
108 float* image_ptr[3];
109 image_ptr[0] = &(images[2].at(0)); // B
110 image_ptr[1] = &(images[1].at(0)); // G
111 image_ptr[2] = &(images[0].at(0)); // R
112
113 image.images = (unsigned char**)image_ptr;
114 image.width = width;
115 image.height = height;
116
117 header.num_channels = 3;
118 header.channels = (EXRChannelInfo*)malloc(sizeof(EXRChannelInfo) * header.num_channels);
119 // Must be (A)BGR order, since most of EXR viewers expect this channel order.
120 strncpy(header.channels[0].name, "B", 255);
121 header.channels[0].name[strlen("B")] = '\0';
122 strncpy(header.channels[1].name, "G", 255);
123 header.channels[1].name[strlen("G")] = '\0';
124 strncpy(header.channels[2].name, "R", 255);
125 header.channels[2].name[strlen("R")] = '\0';
126
127 header.pixel_types = (int*)malloc(sizeof(int) * header.num_channels);
128 header.requested_pixel_types = (int*)malloc(sizeof(int) * header.num_channels);
129 for (int i = 0; i < header.num_channels; i++) {
130 header.pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT; // pixel type of input image
131 header.requested_pixel_types[i] =
132 TINYEXR_PIXELTYPE_HALF; // pixel type of output image to be stored in .EXR
133 }
134
135 const char* err = NULL; // or nullptr in C++11 or later.
136 int ret = SaveEXRImageToFile(&image, &header, path.string().data(), &err);
137 if (ret != TINYEXR_SUCCESS) {
138 fprintf(stderr, "Save EXR err: %s\n", err);
139 FreeEXRErrorMessage(err); // free's buffer for an error message
140 return ret;
141 }
142 printf("Saved exr file 3 channels. [ %s ] \n", path.c_str());
143
144 free(header.channels);
145 free(header.pixel_types);
146 free(header.requested_pixel_types);
147 return 0;
148}
149} // namespace wmtk::components::adaptive_tessellation::image
bool save_image_exr_3channels(size_t width, size_t height, int r, int g, int b, const std::vector< float > &data_r, const std::vector< float > &data_g, const std::vector< float > &data_b, const std::filesystem::path &path)
bool save_image_exr_red_channel(size_t width, size_t height, const std::vector< float > &data, const std::filesystem::path &path)
spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:58