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
58 EXRVersion exr_version;
60 int ret = ParseEXRVersionFromFile(&exr_version, filename.c_str());
65 if (exr_version.multipart) {
71 InitEXRHeader(&exr_header);
73 const char *err =
nullptr;
74 ret = ParseEXRHeaderFromFile(&exr_header, &exr_version, filename.c_str(), &err);
76 std::string err_msg(err);
77 FreeEXRErrorMessage(err);
82 for (
int i = 0; i < exr_header.num_channels; ++i) {
83 if (exr_header.pixel_types[i] == TINYEXR_PIXELTYPE_HALF) {
84 exr_header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
89 InitEXRImage(&exr_image);
91 ret = LoadEXRImageFromFile(&exr_image, &exr_header, filename.c_str(), &err);
94 std::string err_msg(err);
95 FreeEXRHeader(&exr_header);
96 FreeEXRErrorMessage(err);
102 if (exr_image.images) {
103 I.
resize(exr_image.height, exr_image.width);
104 memcpy(I.
bitmap, exr_image.images[0], exr_image.height*exr_image.width*
sizeof(
float));
106 else if (exr_image.tiles) {
107 I.
resize(exr_image.height, exr_image.width);
108 size_t data_width =
static_cast<size_t>(exr_header.data_window.max_x - exr_header.data_window.min_x + 1);
110 for (
int tile_idx = 0; tile_idx < exr_image.num_tiles; ++tile_idx) {
111 int sx = exr_image.tiles[tile_idx].offset_x * exr_header.tile_size_x;
112 int sy = exr_image.tiles[tile_idx].offset_y * exr_header.tile_size_y;
113 int ex = exr_image.tiles[tile_idx].offset_x * exr_header.tile_size_x + exr_image.tiles[tile_idx].width;
114 int ey = exr_image.tiles[tile_idx].offset_y * exr_header.tile_size_y + exr_image.tiles[tile_idx].height;
116 for (
unsigned int y = 0; y < static_cast<unsigned int>(ey - sy); ++y) {
117 for (
unsigned int x = 0; x < static_cast<unsigned int>(ex - sx); ++x) {
118 const float *src_image =
reinterpret_cast<const float *
>(exr_image.tiles[tile_idx].images[0]);
119 I.
bitmap[(y + sy) * data_width + (x + sx)] = src_image[y * exr_header.tile_size_x + x];
125 FreeEXRImage(&exr_image);
126 FreeEXRHeader(&exr_header);
131 EXRVersion exr_version;
133 int ret = ParseEXRVersionFromFile(&exr_version, filename.c_str());
138 if (exr_version.multipart) {
143 EXRHeader exr_header;
144 InitEXRHeader(&exr_header);
146 const char *err =
nullptr;
147 ret = ParseEXRHeaderFromFile(&exr_header, &exr_version, filename.c_str(), &err);
149 std::string err_msg(err);
150 FreeEXRErrorMessage(err);
155 for (
int i = 0; i < exr_header.num_channels; ++i) {
156 if (exr_header.pixel_types[i] == TINYEXR_PIXELTYPE_HALF) {
157 exr_header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
162 InitEXRImage(&exr_image);
164 ret = LoadEXRImageFromFile(&exr_image, &exr_header, filename.c_str(), &err);
167 std::string err_msg(err);
168 FreeEXRHeader(&exr_header);
169 FreeEXRErrorMessage(err);
175 if (exr_image.images) {
176 I.
resize(exr_image.height, exr_image.width);
177 for (
int i = 0; i < exr_image.height; ++i) {
178 for (
int j = 0; j < exr_image.width; ++j) {
179 I[i][j].R =
reinterpret_cast<float **
>(exr_image.images)[2][i * exr_image.width + j];
180 I[i][j].G =
reinterpret_cast<float **
>(exr_image.images)[1][i * exr_image.width + j];
181 I[i][j].B =
reinterpret_cast<float **
>(exr_image.images)[0][i * exr_image.width + j];
185 else if (exr_image.tiles) {
186 I.
resize(exr_image.height, exr_image.width);
187 size_t data_width =
static_cast<size_t>(exr_header.data_window.max_x - exr_header.data_window.min_x + 1);
189 for (
int tile_idx = 0; tile_idx < exr_image.num_tiles; ++tile_idx) {
190 int sx = exr_image.tiles[tile_idx].offset_x * exr_header.tile_size_x;
191 int sy = exr_image.tiles[tile_idx].offset_y * exr_header.tile_size_y;
192 int ex = exr_image.tiles[tile_idx].offset_x * exr_header.tile_size_x + exr_image.tiles[tile_idx].width;
193 int ey = exr_image.tiles[tile_idx].offset_y * exr_header.tile_size_y + exr_image.tiles[tile_idx].height;
204 for (
unsigned int y = 0; y < static_cast<unsigned int>(ey - sy); ++y) {
205 for (
unsigned int x = 0; x < static_cast<unsigned int>(ex - sx); ++x) {
206 for (
unsigned int c = 0; c < 3; ++c) {
207 const float *src_image =
reinterpret_cast<const float *
>(exr_image.tiles[tile_idx].images[c]);
208 reinterpret_cast<float *
>(I.
bitmap)[(y + sy) * data_width * 3 + (x + sx) * 3 + c] = src_image[y * exr_header.tile_size_x + x];
215 FreeEXRImage(&exr_image);
216 FreeEXRHeader(&exr_header);
219 void writeEXRTiny(
const vpImage<float> &I,
const std::string &filename)
222 InitEXRHeader(&header);
225 InitEXRImage(&image);
227 image.num_channels = 1;
229 image.images = (
unsigned char **)&I.
bitmap;
233 header.num_channels = 1;
234 header.channels = (EXRChannelInfo *)malloc(
sizeof(EXRChannelInfo) * header.num_channels);
236 strncpy(header.channels[0].name,
"Y", 255); header.channels[0].name[strlen(
"Y")] =
'\0';
238 header.pixel_types = (
int *)malloc(
sizeof(
int) * header.num_channels);
239 header.requested_pixel_types = (
int *)malloc(
sizeof(
int) * header.num_channels);
240 header.compression_type = TINYEXR_COMPRESSIONTYPE_ZIP;
241 for (
int i = 0; i < header.num_channels; ++i) {
242 header.pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
243 header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
246 const char *err =
nullptr;
247 int ret = SaveEXRImageToFile(&image, &header, filename.c_str(), &err);
248 if (ret != TINYEXR_SUCCESS) {
249 std::string err_msg(err);
250 FreeEXRErrorMessage(err);
251 free(header.channels);
252 free(header.requested_pixel_types);
253 free(header.pixel_types);
257 free(header.channels);
258 free(header.requested_pixel_types);
259 free(header.pixel_types);
262 void writeEXRTiny(
const vpImage<vpRGBf> &I,
const std::string &filename)
265 InitEXRHeader(&header);
268 InitEXRImage(&image);
270 image.num_channels = 3;
272 std::vector<float> images[3];
278 for (
unsigned int i = 0; i < I.
getSize(); ++i) {
279 images[0][i] = I.
bitmap[i].R;
280 images[1][i] = I.
bitmap[i].G;
281 images[2][i] = I.
bitmap[i].B;
285 image_ptr[0] = &(images[2].at(0));
286 image_ptr[1] = &(images[1].at(0));
287 image_ptr[2] = &(images[0].at(0));
289 image.images = (
unsigned char **)image_ptr;
293 header.num_channels = 3;
294 header.channels = (EXRChannelInfo *)malloc(
sizeof(EXRChannelInfo) * header.num_channels);
296 strncpy(header.channels[0].name,
"B", 255); header.channels[0].name[strlen(
"B")] =
'\0';
297 strncpy(header.channels[1].name,
"G", 255); header.channels[1].name[strlen(
"G")] =
'\0';
298 strncpy(header.channels[2].name,
"R", 255); header.channels[2].name[strlen(
"R")] =
'\0';
300 header.pixel_types = (
int *)malloc(
sizeof(
int) * header.num_channels);
301 header.requested_pixel_types = (
int *)malloc(
sizeof(
int) * header.num_channels);
302 header.compression_type = TINYEXR_COMPRESSIONTYPE_ZIP;
303 for (
int i = 0; i < header.num_channels; ++i) {
304 header.pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
305 header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
308 const char *err =
nullptr;
309 int ret = SaveEXRImageToFile(&image, &header, filename.c_str(), &err);
310 if (ret != TINYEXR_SUCCESS) {
311 std::string err_msg(err);
312 FreeEXRErrorMessage(err);
313 free(header.channels);
314 free(header.requested_pixel_types);
315 free(header.pixel_types);
319 free(header.channels);
320 free(header.requested_pixel_types);
321 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