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;
223 image.width = I.getWidth();
224 image.height = I.getHeight();
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];
266 images[0].resize(I.getSize());
267 images[1].resize(I.getSize());
268 images[2].resize(I.getSize());
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;
283 image.width = I.getWidth();
284 image.height = I.getHeight();
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.