Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
exr.cc
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2010-2012 johannes hanika.
4 Copyright (C) 2010, 2013 Pascal de Bruijn.
5 Copyright (C) 2011 Henrik Andersson.
6 Copyright (C) 2012-2014, 2020-2021 Pascal Obry.
7 Copyright (C) 2012 Richard Wonka.
8 Copyright (C) 2012-2020 Tobias Ellinghaus.
9 Copyright (C) 2013 Jean-Sébastien Pédron.
10 Copyright (C) 2013 Jérémy Rosen.
11 Copyright (C) 2013 Thomas Pryds.
12 Copyright (C) 2013 Ulrich Pegelow.
13 Copyright (C) 2014 Martijn van Beers.
14 Copyright (C) 2014-2015 parafin.
15 Copyright (C) 2014-2016 Roman Lebedev.
16 Copyright (C) 2016-2017 Peter Budai.
17 Copyright (C) 2018 Maks Naumov.
18 Copyright (C) 2019, 2022, 2025 Aurélien PIERRE.
19 Copyright (C) 2020 Diederik Ter Rahe.
20 Copyright (C) 2021 Hubert Kowalski.
21 Copyright (C) 2022 Martin Bařinka.
22 Copyright (C) 2022 Miloš Komarčević.
23 Copyright (C) 2025 Alynx Zhou.
24
25 darktable is free software: you can redistribute it and/or modify
26 it under the terms of the GNU General Public License as published by
27 the Free Software Foundation, either version 3 of the License, or
28 (at your option) any later version.
29
30 darktable is distributed in the hope that it will be useful,
31 but WITHOUT ANY WARRANTY; without even the implied warranty of
32 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 GNU General Public License for more details.
34
35 You should have received a copy of the GNU General Public License
36 along with darktable. If not, see <http://www.gnu.org/licenses/>.
37 */
38
39// needs to be defined before any system header includes for control/conf.h to work in C++ code
40#define __STDC_FORMAT_MACROS
41
42#include "glib.h"
43
44#include "bauhaus/bauhaus.h"
45#include "common/colorspaces.h"
46#include "common/darktable.h"
47#include "common/exif.h"
48#include "common/imageio.h"
49#include "common/imageio_exr.h"
51#include "control/conf.h"
52#include "control/control.h"
54
55#include "common/imageio_exr.hh"
56
57#include <OpenEXR/ImfChannelList.h>
58#include <OpenEXR/ImfFrameBuffer.h>
59#include <OpenEXR/ImfStandardAttributes.h>
60#include <OpenEXR/ImfThreading.h>
61#include <OpenEXR/ImfOutputFile.h>
62
63#ifdef __cplusplus
64extern "C" {
65#endif
66
67DT_MODULE(5)
68
70{
71 NO_COMPRESSION = 0, // no compression
72 RLE_COMPRESSION = 1, // run length encoding
73 ZIPS_COMPRESSION = 2, // zlib compression, one scan line at a time
74 ZIP_COMPRESSION = 3, // zlib compression, in blocks of 16 scan lines
75 PIZ_COMPRESSION = 4, // piz-based wavelet compression
76 PXR24_COMPRESSION = 5, // lossy 24-bit float compression
77 B44_COMPRESSION = 6, // lossy 4-by-4 pixel block compression,
78 // fixed compression rate
79 B44A_COMPRESSION = 7, // lossy 4-by-4 pixel block compression,
80 // flat fields are compressed more
81 DWAA_COMPRESSION = 8, // lossy DCT based compression, in blocks
82 // of 32 scanlines
83 DWAB_COMPRESSION = 9, // lossy DCT based compression, in blocks
84 // of 256 scanlines
85 NUM_COMPRESSION_METHODS // number of different compression methods
86}; // copy of Imf::Compression
87
89{
90 EXR_PT_UINT = 0, // unsigned int (32 bit)
91 EXR_PT_HALF = 1, // half (16 bit floating point)
92 EXR_PT_FLOAT = 2, // float (32 bit floating point)
93 NUM_PIXELTYPES // number of different pixel types
94}; // copy of Imf::PixelType
95
102
108
110{
111 Imf::BlobAttribute::registerAttributeType();
112}
113
117
118int write_image(dt_imageio_module_data_t *tmp, const char *filename, const void *in_tmp,
119 dt_colorspaces_color_profile_type_t over_type, const char *over_filename,
120 void *exif, int exif_len, int32_t imgid, int num, int total, struct dt_dev_pixelpipe_t *pipe,
121 const gboolean export_masks)
122{
123 const dt_imageio_exr_t *exr = (dt_imageio_exr_t *)tmp;
124
125 Imf::setGlobalThreadCount(darktable.num_openmp_threads);
126
127 Imf::Header header(exr->global.width, exr->global.height, 1, Imath::V2f(0, 0), 1, Imf::INCREASING_Y,
128 (Imf::Compression)exr->compression);
129
130 char comment[1024];
131 snprintf(comment, sizeof(comment), "Developed using %s", darktable_package_string);
132
133 header.insert("comment", Imf::StringAttribute(comment));
134
135 if(exif && exif_len > 0)
136 {
137 Imf::Blob exif_blob(exif_len, (uint8_t *)exif);
138 header.insert("exif", Imf::BlobAttribute(exif_blob));
139 }
140
141 char *xmp_string = dt_exif_xmp_read_string(imgid);
142 if(xmp_string && strlen(xmp_string) > 0)
143 {
144 header.insert("xmp", Imf::StringAttribute(xmp_string));
145 dt_free(xmp_string);
146 }
147
148 // try to add the chromaticities
149 if(imgid > 0)
150 {
151 cmsToneCurve *red_curve = NULL,
152 *green_curve = NULL,
153 *blue_curve = NULL;
154 cmsCIEXYZ *red_color = NULL,
155 *green_color = NULL,
156 *blue_color = NULL;
157 cmsHPROFILE out_profile = dt_colorspaces_get_output_profile(imgid, &over_type, over_filename)->profile;
158 float r[2], g[2], b[2], w[2];
159 float sum;
160 Imf::Chromaticities chromaticities;
161
162 if(!cmsIsMatrixShaper(out_profile)) goto icc_error;
163
164 red_curve = (cmsToneCurve *)cmsReadTag(out_profile, cmsSigRedTRCTag);
165 green_curve = (cmsToneCurve *)cmsReadTag(out_profile, cmsSigGreenTRCTag);
166 blue_curve = (cmsToneCurve *)cmsReadTag(out_profile, cmsSigBlueTRCTag);
167
168 red_color = (cmsCIEXYZ *)cmsReadTag(out_profile, cmsSigRedColorantTag);
169 green_color = (cmsCIEXYZ *)cmsReadTag(out_profile, cmsSigGreenColorantTag);
170 blue_color = (cmsCIEXYZ *)cmsReadTag(out_profile, cmsSigBlueColorantTag);
171
172 if(IS_NULL_PTR(red_curve) || IS_NULL_PTR(green_curve) || IS_NULL_PTR(blue_curve) || IS_NULL_PTR(red_color) || IS_NULL_PTR(green_color) || IS_NULL_PTR(blue_color))
173 goto icc_error;
174
175 if(!cmsIsToneCurveLinear(red_curve) || !cmsIsToneCurveLinear(green_curve) || !cmsIsToneCurveLinear(blue_curve))
176 goto icc_error;
177
178// printf("r: %f %f %f\n", red_color->X, red_color->Y, red_color->Z);
179// printf("g: %f %f %f\n", green_color->X, green_color->Y, green_color->Z);
180// printf("b: %f %f %f\n", blue_color->X, blue_color->Y, blue_color->Z);
181// printf("w: %f %f %f\n", white_point->X, white_point->Y, white_point->Z);
182
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;
192
193 // hard code the white point to D50 as the primaries from the ICC should be adapted to that
194 // calculated from D50 illuminant XYZ values in ICC specs
195 w[0] = 0.345702915;
196 w[1] = 0.358538597;
197
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]);
202
203 Imf::addChromaticities(header, chromaticities);
204 Imf::addWhiteLuminance(header, 1.0); // just assume 1 here
205
206 goto icc_end;
207
208icc_error:
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");
211 }
212icc_end:
213
214 Imf::PixelType pixel_type = (Imf::PixelType)exr->pixel_type;
215
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));
219
220 Imf::OutputFile file(filename, header);
221
222 Imf::FrameBuffer data;
223 size_t stride;
224
225 if(pixel_type == Imf::PixelType::FLOAT)
226 {
227 stride = 4 * sizeof(float);
228 const float *in = (const float *)in_tmp;
229
230 data.insert("R", Imf::Slice(pixel_type, (char *)(in + 0), stride,
231 stride * exr->global.width));
232
233 data.insert("G", Imf::Slice(pixel_type, (char *)(in + 1), stride,
234 stride * exr->global.width));
235
236 data.insert("B", Imf::Slice(pixel_type, (char *)(in + 2), stride,
237 stride * exr->global.width));
238
239 file.setFrameBuffer(data);
240 file.writePixels(exr->global.height);
241 }
242 else
243 {
244 const size_t width = exr->global.width;
245 const size_t height = exr->global.height;
246 stride = 3 * sizeof(unsigned short);
247 unsigned short *out = (unsigned short *)malloc(stride * width * height);
248 if(IS_NULL_PTR(out))
249 return 1;
250
251#ifdef _OPENMP
252#pragma omp parallel for simd default(none) collapse(2) firstprivate(height, width, in_tmp, out)
253#endif
254 for(size_t y = 0; y < height; y++)
255 {
256 for(size_t x = 0; x < width; x++)
257 {
258 const float *in_pixel = (const float *)in_tmp + 4 * ((y * width) + x);
259 unsigned short *out_pixel = out + 3 * ((y * width) + x);
260
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();
264 }
265 }
266
267 data.insert("R", Imf::Slice(pixel_type, (char *)(out + 0), stride,
268 stride * exr->global.width));
269
270 data.insert("G", Imf::Slice(pixel_type, (char *)(out + 1), stride,
271 stride * exr->global.width));
272
273 data.insert("B", Imf::Slice(pixel_type, (char *)(out + 2), stride,
274 stride * exr->global.width));
275
276 file.setFrameBuffer(data);
277 file.writePixels(exr->global.height);
278
279 dt_free(out);
280 }
281
282 return 0;
283}
284
286{
287 return sizeof(dt_imageio_exr_t);
288}
289
290void *legacy_params(dt_imageio_module_format_t *self, const void *const old_params,
291 const size_t old_params_size, const int old_version, const int new_version,
292 size_t *new_size)
293{
294 if(old_version == 1 && new_version == 5)
295 {
296 struct dt_imageio_exr_v1_t
297 {
298 int max_width, max_height;
299 int width, height;
300 char style[128];
301 };
302
303 const dt_imageio_exr_v1_t *o = (dt_imageio_exr_v1_t *)old_params;
305
306 n->global.max_width = o->max_width;
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));
311 n->compression = PIZ_COMPRESSION;
312 n->pixel_type = EXR_PT_FLOAT;
313 *new_size = self->params_size(self);
314 return n;
315 }
316 if(old_version == 2 && new_version == 5)
317 {
318 struct dt_imageio_exr_v2_t
319 {
320 int max_width, max_height;
321 int width, height;
322 char style[128];
325 };
326
327 const dt_imageio_exr_v2_t *o = (dt_imageio_exr_v2_t *)old_params;
329
330 // last param was dropped (pixel type)
331 n->global.max_width = o->max_width;
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;
337 n->pixel_type = o->pixel_type >= EXR_PT_HALF ? o->pixel_type : EXR_PT_FLOAT;
338 *new_size = self->params_size(self);
339 return n;
340 }
341 if(old_version == 3 && new_version == 5)
342 {
343 struct dt_imageio_exr_v3_t
344 {
345 int max_width, max_height;
346 int width, height;
347 char style[128];
349 };
350
351 const dt_imageio_exr_v3_t *o = (dt_imageio_exr_v3_t *)old_params;
353
354 n->global.max_width = o->max_width;
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;
360 n->pixel_type = EXR_PT_FLOAT;
361 *new_size = self->params_size(self);
362 return n;
363 }
364 if(old_version == 4 && new_version == 5)
365 {
366 struct dt_imageio_exr_v4_t
367 {
370 };
371
372 const dt_imageio_exr_v4_t *o = (dt_imageio_exr_v4_t *)old_params;
374
375 n->global.max_width = o->global.max_width;
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;
381 n->pixel_type = EXR_PT_FLOAT;
382 *new_size = self->params_size(self);
383 return n;
384 }
385 return NULL;
386}
387
389{
390 dt_imageio_exr_t *d = (dt_imageio_exr_t *)calloc(1, sizeof(dt_imageio_exr_t));
391 d->compression = (dt_imageio_exr_compression_t)dt_conf_get_int("plugins/imageio/format/exr/compression");
392 const int bpp = dt_conf_get_int("plugins/imageio/format/exr/bpp");
393 d->pixel_type = (dt_imageio_exr_pixeltype_t)(bpp >> 4);
394 return d;
395}
396
398{
399 dt_free(params);
400}
401
402int set_params(dt_imageio_module_format_t *self, const void *params, const int size)
403{
404 if(size != (int)self->params_size(self)) return 1;
407 dt_bauhaus_combobox_set(g->bpp, d->pixel_type - EXR_PT_HALF);
408 dt_bauhaus_combobox_set(g->compression, d->compression);
409 return 0;
410}
411
413{
414 return 32; // always request float, any conversion is done internally
415}
416
421
423{
424 return "image/x-exr";
425}
426
428{
429 return "exr";
430}
431
432const char *name()
433{
434 return _("OpenEXR (16/32-bit float)");
435}
436
437static void bpp_combobox_changed(GtkWidget *widget, gpointer user_data)
438{
439 const int pixel_type = dt_bauhaus_combobox_get(widget) + EXR_PT_HALF;
440 dt_conf_set_int("plugins/imageio/format/exr/bpp", pixel_type << 4);
441}
442
443static void compression_combobox_changed(GtkWidget *widget, gpointer user_data)
444{
445 const int compression = dt_bauhaus_combobox_get(widget);
446 dt_conf_set_int("plugins/imageio/format/exr/compression", compression);
447}
448
450{
451 self->gui_data = malloc(sizeof(dt_imageio_exr_gui_t));
453
454 self->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING);
455
456 // Bit depth combo box
457 const int bpp_last = dt_conf_get_int("plugins/imageio/format/exr/bpp");
458
460 dt_bauhaus_widget_set_label(gui->bpp, N_("bit depth"));
461
462 dt_bauhaus_combobox_add(gui->bpp, _("16 bit"));
463 dt_bauhaus_combobox_add(gui->bpp, _("32 bit"));
464 dt_bauhaus_combobox_set(gui->bpp, (bpp_last >> 4) - EXR_PT_HALF);
465 gtk_box_pack_start(GTK_BOX(self->widget), gui->bpp, TRUE, TRUE, 0);
466 g_signal_connect(G_OBJECT(gui->bpp), "value-changed", G_CALLBACK(bpp_combobox_changed), NULL);
467
468 // Compression combo box
469 const int compression_last = dt_conf_get_int("plugins/imageio/format/exr/compression");
470
472 dt_bauhaus_widget_set_label(gui->compression, N_("compression"));
473
474 dt_bauhaus_combobox_add(gui->compression, _("uncompressed"));
475 dt_bauhaus_combobox_add(gui->compression, _("RLE"));
476 dt_bauhaus_combobox_add(gui->compression, _("ZIPS"));
477 dt_bauhaus_combobox_add(gui->compression, _("ZIP"));
478 dt_bauhaus_combobox_add(gui->compression, _("PIZ"));
479 dt_bauhaus_combobox_add(gui->compression, _("PXR24"));
480 dt_bauhaus_combobox_add(gui->compression, _("B44"));
481 dt_bauhaus_combobox_add(gui->compression, _("B44A"));
482 dt_bauhaus_combobox_add(gui->compression, _("DWAA"));
483 dt_bauhaus_combobox_add(gui->compression, _("DWAB"));
484 dt_bauhaus_combobox_set(gui->compression, compression_last);
485 gtk_box_pack_start(GTK_BOX(self->widget), gui->compression, TRUE, TRUE, 0);
486 g_signal_connect(G_OBJECT(gui->compression), "value-changed", G_CALLBACK(compression_combobox_changed), NULL);
487}
488
490{
491 dt_free(self->gui_data);
492}
493
495{
497 const int bpp = dt_confgen_get_int("plugins/imageio/format/exr/bpp", DT_DEFAULT);
499 dt_bauhaus_combobox_set(gui->compression, dt_confgen_get_int("plugins/imageio/format/exr/compression", DT_DEFAULT));
500}
501
502
503
504#ifdef __cplusplus
505}
506#endif
507// clang-format off
508// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
509// vim: shiftwidth=2 expandtab tabstop=2 cindent
510// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
511// clang-format on
#define TRUE
Definition ashift_lsd.c:162
int dt_bauhaus_combobox_get(GtkWidget *widget)
Definition bauhaus.c:2347
void dt_bauhaus_combobox_set(GtkWidget *widget, const int pos)
Definition bauhaus.c:2301
void dt_bauhaus_widget_set_label(GtkWidget *widget, const char *label)
Definition bauhaus.c:1653
GtkWidget * dt_bauhaus_combobox_new(dt_bauhaus_t *bh, dt_gui_module_t *self)
Definition bauhaus.c:1842
void dt_bauhaus_combobox_add(GtkWidget *widget, const char *text)
Definition bauhaus.c:2016
int width
Definition bilateral.h:1
int height
Definition bilateral.h:1
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
const dt_colorspaces_color_profile_t * dt_colorspaces_get_output_profile(const int32_t imgid, dt_colorspaces_color_profile_type_t *over_type, const char *over_filename)
dt_colorspaces_color_profile_type_t
Definition colorspaces.h:81
const dt_colormatrix_t dt_aligned_pixel_t out
@ DT_DEFAULT
Definition conf.h:96
const char darktable_package_string[]
void dt_conf_set_int(const char *name, int val)
int dt_conf_get_int(const char *name)
int dt_confgen_get_int(const char *name, dt_confgen_value_kind_t kind)
void dt_control_log(const char *msg,...)
Definition control.c:761
darktable_t darktable
Definition darktable.c:181
#define DT_MODULE(MODVER)
Definition darktable.h:140
#define dt_free(ptr)
Definition darktable.h:456
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition darktable.h:281
char * dt_exif_xmp_read_string(const int32_t imgid)
Definition exif.cc:4116
const char * mime(dt_imageio_module_data_t *data)
Definition exr.cc:422
size_t params_size(dt_imageio_module_format_t *self)
Definition exr.cc:285
void gui_reset(dt_imageio_module_format_t *self)
Definition exr.cc:494
void gui_init(dt_imageio_module_format_t *self)
Definition exr.cc:449
const char * extension(dt_imageio_module_data_t *data)
Definition exr.cc:427
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)
Definition exr.cc:118
dt_imageio_exr_compression_t
Definition exr.cc:70
@ DWAB_COMPRESSION
Definition exr.cc:83
@ PXR24_COMPRESSION
Definition exr.cc:76
@ DWAA_COMPRESSION
Definition exr.cc:81
@ RLE_COMPRESSION
Definition exr.cc:72
@ NUM_COMPRESSION_METHODS
Definition exr.cc:85
@ B44A_COMPRESSION
Definition exr.cc:79
@ NO_COMPRESSION
Definition exr.cc:71
@ B44_COMPRESSION
Definition exr.cc:77
@ ZIP_COMPRESSION
Definition exr.cc:74
@ PIZ_COMPRESSION
Definition exr.cc:75
@ ZIPS_COMPRESSION
Definition exr.cc:73
int set_params(dt_imageio_module_format_t *self, const void *params, const int size)
Definition exr.cc:402
const char * name()
Definition exr.cc:432
void cleanup(dt_imageio_module_format_t *self)
Definition exr.cc:114
int levels(dt_imageio_module_data_t *p)
Definition exr.cc:417
void * legacy_params(dt_imageio_module_format_t *self, const void *const old_params, const size_t old_params_size, const int old_version, const int new_version, size_t *new_size)
Definition exr.cc:290
dt_imageio_exr_pixeltype_t
Definition exr.cc:89
@ EXR_PT_UINT
Definition exr.cc:90
@ EXR_PT_FLOAT
Definition exr.cc:92
@ EXR_PT_HALF
Definition exr.cc:91
@ NUM_PIXELTYPES
Definition exr.cc:93
void free_params(dt_imageio_module_format_t *self, dt_imageio_module_data_t *params)
Definition exr.cc:397
static void compression_combobox_changed(GtkWidget *widget, gpointer user_data)
Definition exr.cc:443
void init(dt_imageio_module_format_t *self)
Definition exr.cc:109
void * get_params(dt_imageio_module_format_t *self)
Definition exr.cc:388
void gui_cleanup(dt_imageio_module_format_t *self)
Definition exr.cc:489
static void bpp_combobox_changed(GtkWidget *widget, gpointer user_data)
Definition exr.cc:437
#define DT_GUI_BOX_SPACING
Definition gtk.h:109
#define DT_GUI_MODULE(x)
int bpp
@ IMAGEIO_RGB
Definition imageio.h:70
@ IMAGEIO_FLOAT
Definition imageio.h:66
static const float x
size_t size
Definition mipmap_cache.c:3
Imf ::TypedAttribute< Imf ::Blob > BlobAttribute
struct _GtkWidget GtkWidget
Definition splash.h:29
const float r
int32_t num_openmp_threads
Definition darktable.h:758
struct dt_bauhaus_t * bauhaus
Definition darktable.h:778
GtkWidget * compression
Definition exr.cc:106
GtkWidget * bpp
Definition exr.cc:105
dt_imageio_exr_compression_t compression
Definition exr.cc:99
dt_imageio_module_data_t global
Definition exr.cc:98
dt_imageio_exr_pixeltype_t pixel_type
Definition exr.cc:100
GModule *GtkWidget * widget