120 void *exif,
int exif_len, int32_t imgid,
int num,
int total,
struct dt_dev_pixelpipe_t *pipe,
121 const gboolean export_masks)
133 header.insert(
"comment", Imf::StringAttribute(comment));
135 if(exif && exif_len > 0)
137 Imf::Blob exif_blob(exif_len, (uint8_t *)exif);
142 if(xmp_string && strlen(xmp_string) > 0)
144 header.insert(
"xmp", Imf::StringAttribute(xmp_string));
151 cmsToneCurve *red_curve = NULL,
154 cmsCIEXYZ *red_color = NULL,
158 float r[2],
g[2], b[2], w[2];
160 Imf::Chromaticities chromaticities;
162 if(!cmsIsMatrixShaper(out_profile))
goto icc_error;
164 red_curve = (cmsToneCurve *)cmsReadTag(out_profile, cmsSigRedTRCTag);
165 green_curve = (cmsToneCurve *)cmsReadTag(out_profile, cmsSigGreenTRCTag);
166 blue_curve = (cmsToneCurve *)cmsReadTag(out_profile, cmsSigBlueTRCTag);
168 red_color = (cmsCIEXYZ *)cmsReadTag(out_profile, cmsSigRedColorantTag);
169 green_color = (cmsCIEXYZ *)cmsReadTag(out_profile, cmsSigGreenColorantTag);
170 blue_color = (cmsCIEXYZ *)cmsReadTag(out_profile, cmsSigBlueColorantTag);
175 if(!cmsIsToneCurveLinear(red_curve) || !cmsIsToneCurveLinear(green_curve) || !cmsIsToneCurveLinear(blue_curve))
183 sum = red_color->X + red_color->Y + red_color->Z;
184 r[0] = red_color->X / sum;
185 r[1] = red_color->Y / sum;
186 sum = green_color->X + green_color->Y + green_color->Z;
187 g[0] = green_color->X / sum;
188 g[1] = green_color->Y / sum;
189 sum = blue_color->X + blue_color->Y + blue_color->Z;
190 b[0] = blue_color->X / sum;
191 b[1] = blue_color->Y / sum;
198 chromaticities.red = Imath::V2f(
r[0],
r[1]);
199 chromaticities.green = Imath::V2f(
g[0],
g[1]);
200 chromaticities.blue = Imath::V2f(b[0], b[1]);
201 chromaticities.white = Imath::V2f(w[0], w[1]);
203 Imf::addChromaticities(header, chromaticities);
204 Imf::addWhiteLuminance(header, 1.0);
209 dt_control_log(
"%s", _(
"the selected output profile doesn't work well with exr"));
210 fprintf(stderr,
"[exr export] warning: exporting with anything but linear matrix profiles might lead to wrong results when opening the image\n");
214 Imf::PixelType pixel_type = (Imf::PixelType)exr->
pixel_type;
216 header.channels().insert(
"R", Imf::Channel(pixel_type, 1, 1,
true));
217 header.channels().insert(
"G", Imf::Channel(pixel_type, 1, 1,
true));
218 header.channels().insert(
"B", Imf::Channel(pixel_type, 1, 1,
true));
220 Imf::OutputFile file(filename, header);
222 Imf::FrameBuffer data;
225 if(pixel_type == Imf::PixelType::FLOAT)
227 stride = 4 *
sizeof(float);
228 const float *in = (
const float *)in_tmp;
230 data.insert(
"R", Imf::Slice(pixel_type, (
char *)(in + 0), stride,
233 data.insert(
"G", Imf::Slice(pixel_type, (
char *)(in + 1), stride,
236 data.insert(
"B", Imf::Slice(pixel_type, (
char *)(in + 2), stride,
239 file.setFrameBuffer(data);
246 stride = 3 *
sizeof(
unsigned short);
247 unsigned short *
out = (
unsigned short *)malloc(stride *
width *
height);
252#pragma omp parallel for simd default(none) collapse(2) firstprivate(height, width, in_tmp, out)
254 for(
size_t y = 0; y <
height; y++)
258 const float *in_pixel = (
const float *)in_tmp + 4 * ((y *
width) +
x);
259 unsigned short *out_pixel =
out + 3 * ((y *
width) +
x);
261 out_pixel[0] = half(in_pixel[0]).bits();
262 out_pixel[1] = half(in_pixel[1]).bits();
263 out_pixel[2] = half(in_pixel[2]).bits();
267 data.insert(
"R", Imf::Slice(pixel_type, (
char *)(
out + 0), stride,
270 data.insert(
"G", Imf::Slice(pixel_type, (
char *)(
out + 1), stride,
273 data.insert(
"B", Imf::Slice(pixel_type, (
char *)(
out + 2), stride,
276 file.setFrameBuffer(data);
291 const size_t old_params_size,
const int old_version,
const int new_version,
294 if(old_version == 1 && new_version == 5)
296 struct dt_imageio_exr_v1_t
298 int max_width, max_height;
303 const dt_imageio_exr_v1_t *o = (dt_imageio_exr_v1_t *)old_params;
307 n->global.max_height = o->max_height;
308 n->global.width = o->width;
309 n->global.height = o->height;
310 g_strlcpy(
n->global.style, o->style,
sizeof(o->style));
313 *new_size = self->params_size(self);
316 if(old_version == 2 && new_version == 5)
318 struct dt_imageio_exr_v2_t
320 int max_width, max_height;
327 const dt_imageio_exr_v2_t *o = (dt_imageio_exr_v2_t *)old_params;
332 n->global.max_height = o->max_height;
333 n->global.width = o->width;
334 n->global.height = o->height;
335 g_strlcpy(
n->global.style, o->style,
sizeof(o->style));
336 n->compression = o->compression;
338 *new_size = self->params_size(self);
341 if(old_version == 3 && new_version == 5)
343 struct dt_imageio_exr_v3_t
345 int max_width, max_height;
351 const dt_imageio_exr_v3_t *o = (dt_imageio_exr_v3_t *)old_params;
355 n->global.max_height = o->max_height;
356 n->global.width = o->width;
357 n->global.height = o->height;
358 g_strlcpy(
n->global.style, o->style,
sizeof(o->style));
359 n->compression = o->compression;
361 *new_size = self->params_size(self);
364 if(old_version == 4 && new_version == 5)
366 struct dt_imageio_exr_v4_t
372 const dt_imageio_exr_v4_t *o = (dt_imageio_exr_v4_t *)old_params;
376 n->global.max_height = o->global.max_height;
377 n->global.width = o->global.width;
378 n->global.height = o->global.height;
379 g_strlcpy(
n->global.style, o->global.style,
sizeof(o->global.style));
380 n->compression = o->compression;
382 *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)