39#include "vpImageIoBackend.h"
41#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
43#define TINYEXR_USE_MINIZ 0
44#define TINYEXR_USE_STB_ZLIB 1
46#include <stb_image_write.h>
48#define TINYEXR_IMPLEMENTATION
53 EXRVersion exr_version;
55 int ret = ParseEXRVersionFromFile(&exr_version, filename.c_str());
60 if (exr_version.multipart) {
66 InitEXRHeader(&exr_header);
68 const char* err = NULL;
69 ret = ParseEXRHeaderFromFile(&exr_header, &exr_version, filename.c_str(), &err);
71 std::string err_msg(err);
72 FreeEXRErrorMessage(err);
77 for (
int i = 0; i < exr_header.num_channels; i++) {
78 if (exr_header.pixel_types[i] == TINYEXR_PIXELTYPE_HALF) {
79 exr_header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
84 InitEXRImage(&exr_image);
86 ret = LoadEXRImageFromFile(&exr_image, &exr_header, filename.c_str(), &err);
89 std::string err_msg(err);
90 FreeEXRHeader(&exr_header);
91 FreeEXRErrorMessage(err);
97 if (exr_image.images) {
98 I.
resize(exr_image.height, exr_image.width);
99 memcpy(I.
bitmap, exr_image.images[0], exr_image.height*exr_image.width*
sizeof(
float));
100 }
else if (exr_image.tiles) {
101 I.
resize(exr_image.height, exr_image.width);
102 size_t data_width =
static_cast<size_t>(exr_header.data_window.max_x - exr_header.data_window.min_x + 1);
104 for (
int tile_idx = 0; tile_idx < exr_image.num_tiles; tile_idx++) {
105 int sx = exr_image.tiles[tile_idx].offset_x * exr_header.tile_size_x;
106 int sy = exr_image.tiles[tile_idx].offset_y * exr_header.tile_size_y;
107 int ex = exr_image.tiles[tile_idx].offset_x * exr_header.tile_size_x + exr_image.tiles[tile_idx].width;
108 int ey = exr_image.tiles[tile_idx].offset_y * exr_header.tile_size_y + exr_image.tiles[tile_idx].height;
110 for (
unsigned int y = 0; y < static_cast<unsigned int>(ey - sy); y++) {
111 for (
unsigned int x = 0; x < static_cast<unsigned int>(ex - sx); x++) {
112 const float *src_image =
reinterpret_cast<const float *
>(exr_image.tiles[tile_idx].images[0]);
113 I.
bitmap[(y + sy) * data_width + (x + sx)] = src_image[y * exr_header.tile_size_x + x];
119 FreeEXRImage(&exr_image);
120 FreeEXRHeader(&exr_header);
125 EXRVersion exr_version;
127 int ret = ParseEXRVersionFromFile(&exr_version, filename.c_str());
132 if (exr_version.multipart) {
137 EXRHeader exr_header;
138 InitEXRHeader(&exr_header);
140 const char* err = NULL;
141 ret = ParseEXRHeaderFromFile(&exr_header, &exr_version, filename.c_str(), &err);
143 std::string err_msg(err);
144 FreeEXRErrorMessage(err);
149 for (
int i = 0; i < exr_header.num_channels; i++) {
150 if (exr_header.pixel_types[i] == TINYEXR_PIXELTYPE_HALF) {
151 exr_header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
156 InitEXRImage(&exr_image);
158 ret = LoadEXRImageFromFile(&exr_image, &exr_header, filename.c_str(), &err);
161 std::string err_msg(err);
162 FreeEXRHeader(&exr_header);
163 FreeEXRErrorMessage(err);
169 if (exr_image.images) {
170 I.
resize(exr_image.height, exr_image.width);
171 for (
int i = 0; i < exr_image.height; i++) {
172 for (
int j = 0; j < exr_image.width; j++) {
173 I[i][j].R =
reinterpret_cast<float **
>(exr_image.images)[2][i * exr_image.width + j];
174 I[i][j].G =
reinterpret_cast<float **
>(exr_image.images)[1][i * exr_image.width + j];
175 I[i][j].B =
reinterpret_cast<float **
>(exr_image.images)[0][i * exr_image.width + j];
178 }
else if (exr_image.tiles) {
179 I.
resize(exr_image.height, exr_image.width);
180 size_t data_width =
static_cast<size_t>(exr_header.data_window.max_x - exr_header.data_window.min_x + 1);
182 for (
int tile_idx = 0; tile_idx < exr_image.num_tiles; tile_idx++) {
183 int sx = exr_image.tiles[tile_idx].offset_x * exr_header.tile_size_x;
184 int sy = exr_image.tiles[tile_idx].offset_y * exr_header.tile_size_y;
185 int ex = exr_image.tiles[tile_idx].offset_x * exr_header.tile_size_x + exr_image.tiles[tile_idx].width;
186 int ey = exr_image.tiles[tile_idx].offset_y * exr_header.tile_size_y + exr_image.tiles[tile_idx].height;
197 for (
unsigned int y = 0; y < static_cast<unsigned int>(ey - sy); y++) {
198 for (
unsigned int x = 0; x < static_cast<unsigned int>(ex - sx); x++) {
199 for (
unsigned int c = 0; c < 3; c++) {
200 const float *src_image =
reinterpret_cast<const float *
>(exr_image.tiles[tile_idx].images[c]);
201 reinterpret_cast<float *
>(I.
bitmap)[(y + sy) * data_width * 3 + (x + sx) * 3 + c] = src_image[y * exr_header.tile_size_x + x];
208 FreeEXRImage(&exr_image);
209 FreeEXRHeader(&exr_header);
212void writeEXRTiny(
const vpImage<float> &I,
const std::string &filename)
215 InitEXRHeader(&header);
218 InitEXRImage(&image);
220 image.num_channels = 1;
222 image.images = (
unsigned char**)&I.
bitmap;
226 header.num_channels = 1;
227 header.channels = (EXRChannelInfo *)malloc(
sizeof(EXRChannelInfo) * header.num_channels);
229 strncpy(header.channels[0].name,
"Y", 255); header.channels[0].name[strlen(
"Y")] =
'\0';
231 header.pixel_types = (
int *)malloc(
sizeof(
int) * header.num_channels);
232 header.requested_pixel_types = (
int *)malloc(
sizeof(
int) * header.num_channels);
233 header.compression_type = TINYEXR_COMPRESSIONTYPE_ZIP;
234 for (
int i = 0; i < header.num_channels; i++) {
235 header.pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
236 header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
239 const char* err = NULL;
240 int ret = SaveEXRImageToFile(&image, &header, filename.c_str(), &err);
241 if (ret != TINYEXR_SUCCESS) {
242 std::string err_msg(err);
243 FreeEXRErrorMessage(err);
244 free(header.channels);
245 free(header.requested_pixel_types);
246 free(header.pixel_types);
250 free(header.channels);
251 free(header.requested_pixel_types);
252 free(header.pixel_types);
255void writeEXRTiny(
const vpImage<vpRGBf> &I,
const std::string &filename)
258 InitEXRHeader(&header);
261 InitEXRImage(&image);
263 image.num_channels = 3;
265 std::vector<float> images[3];
271 for (
unsigned int i = 0; i < I.
getSize(); i++) {
272 images[0][i] = I.
bitmap[i].R;
273 images[1][i] = I.
bitmap[i].G;
274 images[2][i] = I.
bitmap[i].B;
278 image_ptr[0] = &(images[2].at(0));
279 image_ptr[1] = &(images[1].at(0));
280 image_ptr[2] = &(images[0].at(0));
282 image.images = (
unsigned char**)image_ptr;
286 header.num_channels = 3;
287 header.channels = (EXRChannelInfo *)malloc(
sizeof(EXRChannelInfo) * header.num_channels);
289 strncpy(header.channels[0].name,
"B", 255); header.channels[0].name[strlen(
"B")] =
'\0';
290 strncpy(header.channels[1].name,
"G", 255); header.channels[1].name[strlen(
"G")] =
'\0';
291 strncpy(header.channels[2].name,
"R", 255); header.channels[2].name[strlen(
"R")] =
'\0';
293 header.pixel_types = (
int *)malloc(
sizeof(
int) * header.num_channels);
294 header.requested_pixel_types = (
int *)malloc(
sizeof(
int) * header.num_channels);
295 header.compression_type = TINYEXR_COMPRESSIONTYPE_ZIP;
296 for (
int i = 0; i < header.num_channels; i++) {
297 header.pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
298 header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
301 const char* err = NULL;
302 int ret = SaveEXRImageToFile(&image, &header, filename.c_str(), &err);
303 if (ret != TINYEXR_SUCCESS) {
304 std::string err_msg(err);
305 FreeEXRErrorMessage(err);
306 free(header.channels);
307 free(header.requested_pixel_types);
308 free(header.pixel_types);
312 free(header.channels);
313 free(header.requested_pixel_types);
314 free(header.pixel_types);
Error that can be emitted by the vpImage class and its derivatives.
Definition of the vpImage class member functions.
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