Wildmeshing Toolkit
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>
6 #include <wmtk/utils/Logger.hpp>
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  }
106  wmtk::logger()
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