40 #include <visp3/core/vpConfig.h>
42 #if defined(VISP_HAVE_STBIMAGE) && defined(VISP_HAVE_TINYEXR)
44 #include "vpImageIoBackend.h"
46 #define TINYEXR_USE_MINIZ 0
47 #define TINYEXR_USE_STB_ZLIB 1
48 #include <stb_image.h>
49 #include <stb_image_write.h>
51 #define TINYEXR_IMPLEMENTATION
56 EXRVersion exr_version;
58 int ret = ParseEXRVersionFromFile(&exr_version, filename.c_str());
63 if (exr_version.multipart) {
69 InitEXRHeader(&exr_header);
71 const char *err =
nullptr;
72 ret = ParseEXRHeaderFromFile(&exr_header, &exr_version, filename.c_str(), &err);
74 std::string err_msg(err);
75 FreeEXRErrorMessage(err);
80 for (
int i = 0; i < exr_header.num_channels; ++i) {
81 if (exr_header.pixel_types[i] == TINYEXR_PIXELTYPE_HALF) {
82 exr_header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
87 InitEXRImage(&exr_image);
89 ret = LoadEXRImageFromFile(&exr_image, &exr_header, filename.c_str(), &err);
92 std::string err_msg(err);
93 FreeEXRHeader(&exr_header);
94 FreeEXRErrorMessage(err);
100 if (exr_image.images) {
101 I.
resize(exr_image.height, exr_image.width);
102 memcpy(I.
bitmap, exr_image.images[0], exr_image.height*exr_image.width*
sizeof(
float));
104 else if (exr_image.tiles) {
105 I.
resize(exr_image.height, exr_image.width);
106 size_t data_width =
static_cast<size_t>(exr_header.data_window.max_x - exr_header.data_window.min_x + 1);
108 for (
int tile_idx = 0; tile_idx < exr_image.num_tiles; ++tile_idx) {
109 int sx = exr_image.tiles[tile_idx].offset_x * exr_header.tile_size_x;
110 int sy = exr_image.tiles[tile_idx].offset_y * exr_header.tile_size_y;
111 int ex = exr_image.tiles[tile_idx].offset_x * exr_header.tile_size_x + exr_image.tiles[tile_idx].width;
112 int ey = exr_image.tiles[tile_idx].offset_y * exr_header.tile_size_y + exr_image.tiles[tile_idx].height;
114 for (
unsigned int y = 0; y < static_cast<unsigned int>(ey - sy); ++y) {
115 for (
unsigned int x = 0; x < static_cast<unsigned int>(ex - sx); ++x) {
116 const float *src_image =
reinterpret_cast<const float *
>(exr_image.tiles[tile_idx].images[0]);
117 I.
bitmap[(y + sy) * data_width + (x + sx)] = src_image[y * exr_header.tile_size_x + x];
123 FreeEXRImage(&exr_image);
124 FreeEXRHeader(&exr_header);
129 EXRVersion exr_version;
131 int ret = ParseEXRVersionFromFile(&exr_version, filename.c_str());
136 if (exr_version.multipart) {
141 EXRHeader exr_header;
142 InitEXRHeader(&exr_header);
144 const char *err =
nullptr;
145 ret = ParseEXRHeaderFromFile(&exr_header, &exr_version, filename.c_str(), &err);
147 std::string err_msg(err);
148 FreeEXRErrorMessage(err);
153 for (
int i = 0; i < exr_header.num_channels; ++i) {
154 if (exr_header.pixel_types[i] == TINYEXR_PIXELTYPE_HALF) {
155 exr_header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
160 InitEXRImage(&exr_image);
162 ret = LoadEXRImageFromFile(&exr_image, &exr_header, filename.c_str(), &err);
165 std::string err_msg(err);
166 FreeEXRHeader(&exr_header);
167 FreeEXRErrorMessage(err);
173 if (exr_image.images) {
174 I.
resize(exr_image.height, exr_image.width);
175 for (
int i = 0; i < exr_image.height; ++i) {
176 for (
int j = 0; j < exr_image.width; ++j) {
177 I[i][j].R =
reinterpret_cast<float **
>(exr_image.images)[2][i * exr_image.width + j];
178 I[i][j].G =
reinterpret_cast<float **
>(exr_image.images)[1][i * exr_image.width + j];
179 I[i][j].B =
reinterpret_cast<float **
>(exr_image.images)[0][i * exr_image.width + j];
183 else if (exr_image.tiles) {
184 I.
resize(exr_image.height, exr_image.width);
185 size_t data_width =
static_cast<size_t>(exr_header.data_window.max_x - exr_header.data_window.min_x + 1);
187 for (
int tile_idx = 0; tile_idx < exr_image.num_tiles; ++tile_idx) {
188 int sx = exr_image.tiles[tile_idx].offset_x * exr_header.tile_size_x;
189 int sy = exr_image.tiles[tile_idx].offset_y * exr_header.tile_size_y;
190 int ex = exr_image.tiles[tile_idx].offset_x * exr_header.tile_size_x + exr_image.tiles[tile_idx].width;
191 int ey = exr_image.tiles[tile_idx].offset_y * exr_header.tile_size_y + exr_image.tiles[tile_idx].height;
202 for (
unsigned int y = 0; y < static_cast<unsigned int>(ey - sy); ++y) {
203 for (
unsigned int x = 0; x < static_cast<unsigned int>(ex - sx); ++x) {
204 for (
unsigned int c = 0; c < 3; ++c) {
205 const float *src_image =
reinterpret_cast<const float *
>(exr_image.tiles[tile_idx].images[c]);
206 reinterpret_cast<float *
>(I.
bitmap)[(y + sy) * data_width * 3 + (x + sx) * 3 + c] = src_image[y * exr_header.tile_size_x + x];
213 FreeEXRImage(&exr_image);
214 FreeEXRHeader(&exr_header);
217 void writeEXRTiny(
const vpImage<float> &I,
const std::string &filename)
220 InitEXRHeader(&header);
223 InitEXRImage(&image);
225 image.num_channels = 1;
227 image.images = (
unsigned char **)&I.
bitmap;
231 header.num_channels = 1;
232 header.channels = (EXRChannelInfo *)malloc(
sizeof(EXRChannelInfo) * header.num_channels);
234 strncpy(header.channels[0].name,
"Y", 255); header.channels[0].name[strlen(
"Y")] =
'\0';
236 header.pixel_types = (
int *)malloc(
sizeof(
int) * header.num_channels);
237 header.requested_pixel_types = (
int *)malloc(
sizeof(
int) * header.num_channels);
238 header.compression_type = TINYEXR_COMPRESSIONTYPE_ZIP;
239 for (
int i = 0; i < header.num_channels; ++i) {
240 header.pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
241 header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
244 const char *err =
nullptr;
245 int ret = SaveEXRImageToFile(&image, &header, filename.c_str(), &err);
246 if (ret != TINYEXR_SUCCESS) {
247 std::string err_msg(err);
248 FreeEXRErrorMessage(err);
249 free(header.channels);
250 free(header.requested_pixel_types);
251 free(header.pixel_types);
255 free(header.channels);
256 free(header.requested_pixel_types);
257 free(header.pixel_types);
260 void writeEXRTiny(
const vpImage<vpRGBf> &I,
const std::string &filename)
263 InitEXRHeader(&header);
266 InitEXRImage(&image);
268 image.num_channels = 3;
270 std::vector<float> images[3];
276 for (
unsigned int i = 0; i < I.
getSize(); ++i) {
277 images[0][i] = I.
bitmap[i].R;
278 images[1][i] = I.
bitmap[i].G;
279 images[2][i] = I.
bitmap[i].B;
283 image_ptr[0] = &(images[2].at(0));
284 image_ptr[1] = &(images[1].at(0));
285 image_ptr[2] = &(images[0].at(0));
287 image.images = (
unsigned char **)image_ptr;
291 header.num_channels = 3;
292 header.channels = (EXRChannelInfo *)malloc(
sizeof(EXRChannelInfo) * header.num_channels);
294 strncpy(header.channels[0].name,
"B", 255); header.channels[0].name[strlen(
"B")] =
'\0';
295 strncpy(header.channels[1].name,
"G", 255); header.channels[1].name[strlen(
"G")] =
'\0';
296 strncpy(header.channels[2].name,
"R", 255); header.channels[2].name[strlen(
"R")] =
'\0';
298 header.pixel_types = (
int *)malloc(
sizeof(
int) * header.num_channels);
299 header.requested_pixel_types = (
int *)malloc(
sizeof(
int) * header.num_channels);
300 header.compression_type = TINYEXR_COMPRESSIONTYPE_ZIP;
301 for (
int i = 0; i < header.num_channels; ++i) {
302 header.pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
303 header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
306 const char *err =
nullptr;
307 int ret = SaveEXRImageToFile(&image, &header, filename.c_str(), &err);
308 if (ret != TINYEXR_SUCCESS) {
309 std::string err_msg(err);
310 FreeEXRErrorMessage(err);
311 free(header.channels);
312 free(header.requested_pixel_types);
313 free(header.pixel_types);
317 free(header.channels);
318 free(header.requested_pixel_types);
319 free(header.pixel_types);
Error that can be emitted by the vpImage class and its derivatives.
unsigned int getWidth() const
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
unsigned int getSize() const
Type * bitmap
points toward the bitmap
unsigned int getHeight() const