123 void *exif,
int exif_len, int32_t imgid,
int num,
int total,
struct dt_dev_pixelpipe_t *pipe,
124 const gboolean export_masks)
136 header.insert(
"comment", Imf::StringAttribute(comment));
138 if(exif && exif_len > 0)
140 Imf::Blob exif_blob(exif_len, (uint8_t *)exif);
145 if(xmp_string && strlen(xmp_string) > 0)
147 header.insert(
"xmp", Imf::StringAttribute(xmp_string));
154 cmsToneCurve *red_curve = NULL,
157 cmsCIEXYZ *red_color = NULL,
161 float r[2],
g[2], b[2], w[2];
163 Imf::Chromaticities chromaticities;
165 if(!cmsIsMatrixShaper(out_profile))
goto icc_error;
167 red_curve = (cmsToneCurve *)cmsReadTag(out_profile, cmsSigRedTRCTag);
168 green_curve = (cmsToneCurve *)cmsReadTag(out_profile, cmsSigGreenTRCTag);
169 blue_curve = (cmsToneCurve *)cmsReadTag(out_profile, cmsSigBlueTRCTag);
171 red_color = (cmsCIEXYZ *)cmsReadTag(out_profile, cmsSigRedColorantTag);
172 green_color = (cmsCIEXYZ *)cmsReadTag(out_profile, cmsSigGreenColorantTag);
173 blue_color = (cmsCIEXYZ *)cmsReadTag(out_profile, cmsSigBlueColorantTag);
178 if(!cmsIsToneCurveLinear(red_curve) || !cmsIsToneCurveLinear(green_curve) || !cmsIsToneCurveLinear(blue_curve))
186 sum = red_color->X + red_color->Y + red_color->Z;
187 r[0] = red_color->X / sum;
188 r[1] = red_color->Y / sum;
189 sum = green_color->X + green_color->Y + green_color->Z;
190 g[0] = green_color->X / sum;
191 g[1] = green_color->Y / sum;
192 sum = blue_color->X + blue_color->Y + blue_color->Z;
193 b[0] = blue_color->X / sum;
194 b[1] = blue_color->Y / sum;
201 chromaticities.red = Imath::V2f(
r[0],
r[1]);
202 chromaticities.green = Imath::V2f(
g[0],
g[1]);
203 chromaticities.blue = Imath::V2f(b[0], b[1]);
204 chromaticities.white = Imath::V2f(w[0], w[1]);
206 Imf::addChromaticities(header, chromaticities);
207 Imf::addWhiteLuminance(header, 1.0);
212 dt_control_log(
"%s", _(
"the selected output profile doesn't work well with exr"));
213 fprintf(stderr,
"[exr export] warning: exporting with anything but linear matrix profiles might lead to wrong results when opening the image\n");
217 Imf::PixelType pixel_type = (Imf::PixelType)exr->
pixel_type;
219 header.channels().insert(
"R", Imf::Channel(pixel_type, 1, 1,
true));
220 header.channels().insert(
"G", Imf::Channel(pixel_type, 1, 1,
true));
221 header.channels().insert(
"B", Imf::Channel(pixel_type, 1, 1,
true));
223 Imf::OutputFile file(filename, header);
225 Imf::FrameBuffer data;
228 if(pixel_type == Imf::PixelType::FLOAT)
230 stride = 4 *
sizeof(float);
231 const float *in = (
const float *)in_tmp;
233 data.insert(
"R", Imf::Slice(pixel_type, (
char *)(in + 0), stride,
236 data.insert(
"G", Imf::Slice(pixel_type, (
char *)(in + 1), stride,
239 data.insert(
"B", Imf::Slice(pixel_type, (
char *)(in + 2), stride,
242 file.setFrameBuffer(data);
249 stride = 3 *
sizeof(
unsigned short);
250 unsigned short *
out = (
unsigned short *)malloc(stride *
width *
height);
255#pragma omp parallel for simd default(none) collapse(2) firstprivate(height, width, in_tmp, out)
257 for(
size_t y = 0; y <
height; y++)
261 const float *in_pixel = (
const float *)in_tmp + 4 * ((y *
width) +
x);
262 unsigned short *out_pixel =
out + 3 * ((y *
width) +
x);
264 out_pixel[0] = half(in_pixel[0]).bits();
265 out_pixel[1] = half(in_pixel[1]).bits();
266 out_pixel[2] = half(in_pixel[2]).bits();
270 data.insert(
"R", Imf::Slice(pixel_type, (
char *)(
out + 0), stride,
273 data.insert(
"G", Imf::Slice(pixel_type, (
char *)(
out + 1), stride,
276 data.insert(
"B", Imf::Slice(pixel_type, (
char *)(
out + 2), stride,
279 file.setFrameBuffer(data);
294 const size_t old_params_size,
const int old_version,
const int new_version,
297 if(old_version == 1 && new_version == 5)
299 struct dt_imageio_exr_v1_t
301 int max_width, max_height;
306 const dt_imageio_exr_v1_t *o = (dt_imageio_exr_v1_t *)old_params;
310 n->global.max_height = o->max_height;
311 n->global.width = o->width;
312 n->global.height = o->height;
313 g_strlcpy(
n->global.style, o->style,
sizeof(o->style));
316 *new_size = self->params_size(self);
319 if(old_version == 2 && new_version == 5)
321 struct dt_imageio_exr_v2_t
323 int max_width, max_height;
330 const dt_imageio_exr_v2_t *o = (dt_imageio_exr_v2_t *)old_params;
335 n->global.max_height = o->max_height;
336 n->global.width = o->width;
337 n->global.height = o->height;
338 g_strlcpy(
n->global.style, o->style,
sizeof(o->style));
339 n->compression = o->compression;
341 *new_size = self->params_size(self);
344 if(old_version == 3 && new_version == 5)
346 struct dt_imageio_exr_v3_t
348 int max_width, max_height;
354 const dt_imageio_exr_v3_t *o = (dt_imageio_exr_v3_t *)old_params;
358 n->global.max_height = o->max_height;
359 n->global.width = o->width;
360 n->global.height = o->height;
361 g_strlcpy(
n->global.style, o->style,
sizeof(o->style));
362 n->compression = o->compression;
364 *new_size = self->params_size(self);
367 if(old_version == 4 && new_version == 5)
369 struct dt_imageio_exr_v4_t
375 const dt_imageio_exr_v4_t *o = (dt_imageio_exr_v4_t *)old_params;
379 n->global.max_height = o->global.max_height;
380 n->global.width = o->global.width;
381 n->global.height = o->global.height;
382 g_strlcpy(
n->global.style, o->global.style,
sizeof(o->global.style));
383 n->compression = o->compression;
385 *new_size = self->params_size(self);
int write_image(dt_imageio_module_data_t *tmp, const char *filename, const void *in_tmp, dt_colorspaces_color_profile_type_t over_type, const char *over_filename, void *exif, int exif_len, int32_t imgid, int num, int total, struct dt_dev_pixelpipe_t *pipe, const gboolean export_masks)