Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
imageio_core.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2009-2014 johannes hanika.
4 Copyright (C) 2010 Anton Blanchard.
5 Copyright (C) 2010-2012 Henrik Andersson.
6 Copyright (C) 2010 Kaminsky Andrey.
7 Copyright (C) 2010-2020 Tobias Ellinghaus.
8 Copyright (C) 2011 Bruce Guenter.
9 Copyright (C) 2011 Omari Stephens.
10 Copyright (C) 2011 Sergey Pavlov.
11 Copyright (C) 2011-2014, 2019 Ulrich Pegelow.
12 Copyright (C) 2012-2015 Jérémy Rosen.
13 Copyright (C) 2012-2014 Pascal de Bruijn.
14 Copyright (C) 2012-2015, 2018-2021 Pascal Obry.
15 Copyright (C) 2012 Richard Wonka.
16 Copyright (C) 2013 Simon Spannagel.
17 Copyright (C) 2014-2015 Pedro Côrte-Real.
18 Copyright (C) 2014-2018 Roman Lebedev.
19 Copyright (C) 2015 Edouard Gomez.
20 Copyright (C) 2016 Chris Hodapp.
21 Copyright (C) 2016, 2020 Matthieu Volat.
22 Copyright (C) 2017 Žilvinas Žaltiena.
23 Copyright (C) 2018-2019 Edgardo Hoszowski.
24 Copyright (C) 2018 Sören Witt.
25 Copyright (C) 2019, 2022 Aldric Renaudin.
26 Copyright (C) 2019 Andreas Schneider.
27 Copyright (C) 2019-2022 Hanno Schwalm.
28 Copyright (C) 2019-2021 Heiko Bauke.
29 Copyright (C) 2019 Philippe Weyland.
30 Copyright (C) 2020 a.
31 Copyright (C) 2020, 2022-2026 Aurélien PIERRE.
32 Copyright (C) 2020-2021 Hubert Kowalski.
33 Copyright (C) 2020 Miloš Komarčević.
34 Copyright (C) 2021 Daniel Vogelbacher.
35 Copyright (C) 2021 luzpaz.
36 Copyright (C) 2021 Ralf Brown.
37 Copyright (C) 2022 Martin Bařinka.
38 Copyright (C) 2022 parafin.
39 Copyright (C) 2022 Philipp Lutz.
40 Copyright (C) 2023-2024 Alynx Zhou.
41 Copyright (C) 2023 Ricky Moon.
42
43 darktable is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
45 the Free Software Foundation, either version 3 of the License, or
46 (at your option) any later version.
47
48 darktable is distributed in the hope that it will be useful,
49 but WITHOUT ANY WARRANTY; without even the implied warranty of
50 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51 GNU General Public License for more details.
52
53 You should have received a copy of the GNU General Public License
54 along with darktable. If not, see <http://www.gnu.org/licenses/>.
55*/
57#include "common/image.h"
58#ifdef HAVE_CONFIG_H
59#include "config.h"
60#endif
61#include "system/macros.h"
62#include "system/openmp.h"
64#include "system/mem_alloc.h"
65#include "system/simd.h"
66#include "common/logging.h"
67#include "common/times.h"
68#include "common/paths.h"
70#include "common/xmp_sidecar.h"
71#include "metadata/exif.h"
72#include "caches/image_cache.h"
73#include "history/history.h"
77#ifdef HAVE_OPENEXR
78#include "imageio/imageio_exr.h"
79#endif
80#ifdef HAVE_OPENJPEG
81#include "imageio/imageio_j2k.h"
82#endif
84#include "imageio/imageio_pfm.h"
85#include "imageio/imageio_png.h"
86#include "imageio/imageio_pnm.h"
91#ifdef HAVE_LIBAVIF
93#endif
94#ifdef HAVE_LIBHEIF
96#endif
97#ifdef HAVE_WEBP
99#endif
101#include "caches/mipmap_cache.h"
102#include "common/styles.h"
103#include "common/conf.h"
104#include "control/user_message.h"
105#include "develop/develop.h"
106#include "develop/imageop.h"
107
108
109#include <assert.h>
110#include <glib/gstdio.h>
111#include <inttypes.h>
112#include <math.h>
113#include <stdio.h>
114#include <stdlib.h>
115#include <string.h>
116#include <strings.h>
118#include "control/signal.h"
119
120
121// Best-effort image-type hint from the file extension. Returns DT_IMAGE_RAW / DT_IMAGE_LDR /
122// DT_IMAGE_HDR for the unambiguous extensions, or 0 ("unknown") for containers whose dynamic range
123// only the decoder can settle (TIFF, AVIF, HEIF/HEIC, DNG -- see dt_image_ext_is_ambiguous()).
124// Callers must treat 0 as "decode it"; dt_image_buffer_resolve_flags() sets the authoritative
125// LDR/HDR/MOSAIC flags once decoded.
126int dt_imageio_large_thumbnail(const char *filename, uint8_t **buffer, int32_t *th_width, int32_t *th_height,
128{
129 int res = 1;
130
131 uint8_t *buf = NULL;
132 char *mime_type = NULL;
133 size_t bufsize;
134
136 goto error;
137
138 // dt_exif_get_thumbnail() sets mime_type with strdup(), which returns NULL under memory
139 // pressure while still reporting success -- it checks its buffer allocation but not this
140 // one. Everything below reads it: two strcmp() calls and a "%s" in the error path.
141 if(IS_NULL_PTR(mime_type)) goto error;
142
143 if(strcmp(mime_type, "image/jpeg") == 0)
144 {
145 // Decompress the JPG into our own memory format
148 *buffer = (uint8_t *)dt_pixelpipe_cache_alloc_align_cache(
149 sizeof(uint8_t) * 4 * jpg.width * jpg.height,
150 0);
151 if(!*buffer) goto error;
152
153 *th_width = jpg.width;
154 *th_height = jpg.height;
155 // TODO: check if the embedded thumbs have a color space set! currently we assume that it's always sRGB
157 if(dt_imageio_jpeg_decompress(&jpg, *buffer))
158 {
160 *buffer = NULL;
161 goto error;
162 }
163
164 res = 0;
165 }
166 else if(!strcmp(mime_type, "image/tiff") || !strcmp(mime_type, "image/x-tiff"))
167 {
168 // The only other preview format raw files actually use. See
169 // dt_imageio_tiff_decode_blob() for why libtiff rather than a generic decoder.
171 {
172 // TODO: check if the embedded thumbs have a color space set! currently we assume that it's always sRGB
174 res = 0;
175 }
176 }
177
178 if(res)
179 {
180 fprintf(
181 stderr,
182 "[dt_imageio_large_thumbnail] error: Not a supported thumbnail image format or broken thumbnail: %s\n",
183 IS_NULL_PTR(mime_type) ? "(none)" : mime_type);
184 goto error;
185 }
186
187error:
189 dt_free(buf);
190 return res;
191}
192
193gboolean dt_imageio_crop_thumbnail(const dt_boundingbox_t box, uint8_t *const buffer,
194 int32_t *width, int32_t *height)
195{
196 if(IS_NULL_PTR(buffer) || IS_NULL_PTR(width) || IS_NULL_PTR(height)) return FALSE;
197
198 const int32_t in_width = *width;
199 const int32_t in_height = *height;
200 if(in_width < 1 || in_height < 1) return FALSE;
201
202 /* The box is normalized against the frame the camera renders its previews from, which is the
203 * same DefaultCropOrigin/DefaultCropSize rectangle the tag itself references -- so it maps
204 * onto the decoded preview directly, at whatever resolution that preview happens to be. */
205 const int32_t left = CLAMP((int32_t)roundf(box[1] * in_width), 0, in_width - 1);
206 const int32_t top = CLAMP((int32_t)roundf(box[0] * in_height), 0, in_height - 1);
207 const int32_t right = CLAMP((int32_t)roundf(box[3] * in_width), left + 1, in_width);
208 const int32_t bottom = CLAMP((int32_t)roundf(box[2] * in_height), top + 1, in_height);
209
210 const int32_t out_width = right - left;
211 const int32_t out_height = bottom - top;
212 if(out_width == in_width && out_height == in_height) return FALSE;
213
214 /* Compact in place, forward: destination row j starts at 4 * j * out_width, its source at
215 * 4 * ((j + top) * in_width + left). Since out_width <= in_width and top, left >= 0, the
216 * destination never runs ahead of the source, so no row is overwritten before it is read. */
217 for(int32_t j = 0; j < out_height; j++)
218 {
219 const uint8_t *const source = buffer + 4 * ((size_t)(j + top) * in_width + left);
220 uint8_t *const destination = buffer + 4 * (size_t)j * out_width;
221 memmove(destination, source, 4 * (size_t)out_width);
222 }
223
224 *width = out_width;
226 return TRUE;
227}
228
229gboolean dt_imageio_has_mono_preview(const char *filename)
230{
232 uint8_t *tmp = NULL;
233 int32_t thumb_width = 0, thumb_height = 0;
234 gboolean mono = FALSE;
235
236 if(dt_imageio_large_thumbnail(filename, &tmp, &thumb_width, &thumb_height, &color_space, -1, -1))
237 goto cleanup;
238 if((thumb_width < 32) || (thumb_height < 32) || (IS_NULL_PTR(tmp)))
239 goto cleanup;
240
241 mono = TRUE;
242 for(int y = 0; y < thumb_height; y++)
243 {
244 uint8_t *in = (uint8_t *)tmp + (size_t)4 * y * thumb_width;
245 for(int x = 0; x < thumb_width; x++, in += 4)
246 {
247 if((in[0] != in[1]) || (in[0] != in[2]) || (in[1] != in[2]))
248 {
249 mono = FALSE;
250 goto cleanup;
251 }
252 }
253 }
254
255 cleanup:
256
257 dt_print(DT_DEBUG_IMAGEIO,"[dt_imageio_has_mono_preview] testing `%s', yes/no %i, %ix%i\n", filename, mono, thumb_width, thumb_height);
259 return mono;
260}
261
263void dt_imageio_flip_buffers(char *out, const char *in, const size_t bpp, const int wd, const int ht,
264 const int fwd, const int fht, const int stride,
265 const dt_image_orientation_t orientation)
266{
267 if(!orientation)
268 {
270 for(int j = 0; j < ht; j++) memcpy(out + (size_t)j * bpp * wd, in + (size_t)j * stride, bpp * wd);
271 return;
272 }
273 int ii = 0, jj = 0;
274 int si = bpp, sj = wd * bpp;
275 if(orientation & ORIENTATION_SWAP_XY)
276 {
277 sj = bpp;
278 si = ht * bpp;
279 }
280 if(orientation & ORIENTATION_FLIP_Y)
281 {
282 jj = (int)fht - jj - 1;
283 sj = -sj;
284 }
285 if(orientation & ORIENTATION_FLIP_X)
286 {
287 ii = (int)fwd - ii - 1;
288 si = -si;
289 }
291 for(int j = 0; j < ht; j++)
292 {
293 char *out2 = out + (size_t)labs(sj) * jj + (size_t)labs(si) * ii + (size_t)sj * j;
294 const char *in2 = in + (size_t)stride * j;
295 for(int i = 0; i < wd; i++)
296 {
297 memcpy(out2, in2, bpp);
298 in2 += bpp;
299 out2 += si;
300 }
301 }
302}
303
304void dt_imageio_flip_buffers_ui8_to_float(float *out, const uint8_t *in, const float black, const float white,
305 const int ch, const int wd, const int ht, const int fwd,
306 const int fht, const int stride,
307 const dt_image_orientation_t orientation)
308{
309 const float scale = 1.0f / (white - black);
310 if(!orientation)
311 {
313 for(int j = 0; j < ht; j++)
314 for(int i = 0; i < wd; i++)
315 for(int k = 0; k < ch; k++)
316 out[4 * ((size_t)j * wd + i) + k] = (in[(size_t)j * stride + (size_t)ch * i + k] - black) * scale;
317 return;
318 }
319 int ii = 0, jj = 0;
320 int si = 4, sj = wd * 4;
321 if(orientation & ORIENTATION_SWAP_XY)
322 {
323 sj = 4;
324 si = ht * 4;
325 }
326 if(orientation & ORIENTATION_FLIP_Y)
327 {
328 jj = (int)fht - jj - 1;
329 sj = -sj;
330 }
331 if(orientation & ORIENTATION_FLIP_X)
332 {
333 ii = (int)fwd - ii - 1;
334 si = -si;
335 }
337 for(int j = 0; j < ht; j++)
338 {
339 float *out2 = out + (size_t)labs(sj) * jj + (size_t)labs(si) * ii + sj * j;
340 const uint8_t *in2 = in + (size_t)stride * j;
341 for(int i = 0; i < wd; i++)
342 {
343 for(int k = 0; k < ch; k++) out2[k] = (in2[k] - black) * scale;
344 in2 += ch;
345 out2 += si;
346 }
347 }
348}
349
351{
352 // if buf is NULL, don't proceed
353 if(IS_NULL_PTR(buf))
354 return DT_IMAGEIO_OK;
355
357
358#ifdef HAVE_OPENEXR
359 ret = dt_imageio_open_exr(img, filename, buf);
360 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
361 return ret;
362#endif
363
364 ret = dt_imageio_open_rgbe(img, filename, buf);
365 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
366 return ret;
367
368 ret = dt_imageio_open_pfm(img, filename, buf);
369 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
370 return ret;
371
372#ifdef HAVE_LIBAVIF
373 ret = dt_imageio_open_avif(img, filename, buf);
374 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
375 return ret;
376#endif
377
378#ifdef HAVE_LIBHEIF
379 ret = dt_imageio_open_heif(img, filename, buf);
380 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
381 return ret;
382#endif
383
385}
386
387// Decoder routing: dt_image_ext_is_ldr() drives dt_imageio_open_raster(), the generic/
388// exotic-capable chain -- kept distinct from is_hdr() (dt_imageio_open_hdr(), the dedicated
389// OpenEXR/Radiance/PFM/AVIF/HEIF chain). See the comment on dt_image_ext_is_raw/_ldr/_hdr in
390// common/image_extensions.h for why these must never be combined for routing purposes.
391gboolean dt_imageio_is_raster(const char *filename)
392{
393 const char *c = filename + strlen(filename);
394 while(c > filename && *c != '.') c--;
395 if(*c != '.') return FALSE;
396 return dt_image_ext_is_ldr(c + 1);
397}
398
399gboolean dt_imageio_is_raw(const char *filename)
400{
401 const char *c = filename + strlen(filename);
402 while(c > filename && *c != '.') c--;
403 if(*c != '.') return FALSE;
404 return dt_image_ext_is_raw(c + 1);
405}
406
407int dt_imageio_is_hdr(const char *filename)
408{
409 const char *c = filename + strlen(filename);
410 while(c > filename && *c != '.') c--;
411 if(*c != '.') return FALSE;
412 return dt_image_ext_is_hdr(c + 1);
413}
414
430static gboolean _is_in_list(const char *elem, char *list)
431{
432 if(IS_NULL_PTR(elem) || IS_NULL_PTR(list)) return FALSE;
433
434 char *saveptr = NULL;
435 for(char *entry = strtok_r(list, ",", &saveptr); !IS_NULL_PTR(entry);
436 entry = strtok_r(NULL, ",", &saveptr))
437 {
438 if(!g_ascii_strcasecmp(entry, elem)) return TRUE;
439 }
440
441 return FALSE;
442}
443
444gboolean dt_imageio_is_handled_by_libraw(dt_image_t *img, const char *filename)
445{
446 // Allow users to define some extensions, makers and models that should be handled by Libraw
447 gboolean is_handled = FALSE;
448
449 // g_strrstr() returns NULL when the name has no dot at all, and NULL + 1 is undefined
450 // behaviour before _is_in_list() ever gets to dereference it. An extensionless file in an
451 // imported folder is enough to reach this.
452 const char *dot = g_strrstr(filename, ".");
453 const char *ext = IS_NULL_PTR(dot) ? NULL : dot + 1;
454
455 char *extensions = dt_conf_get_string("libraw/extensions");
456 char *makers = dt_conf_get_string("libraw/makers");
457 char *models = dt_conf_get_string("libraw/models");
458
459 // _is_in_list() tokenises its list argument in place; these are private copies from
460 // dt_conf_get_string(), so that is safe.
463 is_handled |= _is_in_list(img->exif_model, models);
464
467 dt_free(models);
468
469 const char *iolib = (is_handled) ? "Libraw" : "Rawspeed";
470 dt_print(DT_DEBUG_IMAGEIO, "[image I/O] image `%s` from camera `%s` of maker `%s` loaded with %s\n", filename,
471 img->exif_model, img->exif_maker, iolib);
472
473 return is_handled;
474}
475
476// transparent read method to load ldr image to dt_raw_image_t with exif and so on.
478{
479 // if buf is NULL, don't proceed
480 if(IS_NULL_PTR(buf))
481 return DT_IMAGEIO_OK;
482
484
485 ret = dt_imageio_open_jpeg(img, filename, buf);
486 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
487 return ret;
488
489 ret = dt_imageio_open_tiff(img, filename, buf);
490 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
491 return ret;
492
493#ifdef HAVE_WEBP
494 ret = dt_imageio_open_webp(img, filename, buf);
495 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
496 return ret;
497#endif
498
499 ret = dt_imageio_open_png(img, filename, buf);
500 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
501 return ret;
502
503#ifdef HAVE_OPENJPEG
504 ret = dt_imageio_open_j2k(img, filename, buf);
505 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
506 return ret;
507#endif
508
509 ret = dt_imageio_open_pnm(img, filename, buf);
510 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
511 return ret;
512
514}
515
517{
518 // if buf is NULL, don't proceed
519 if(IS_NULL_PTR(buf))
520 return DT_IMAGEIO_OK;
521
523
524 /* check if user wants to force processing through Libraw */
525 const gboolean force_libraw = dt_imageio_is_handled_by_libraw(img, filename);
526
527 /* use rawspeed to load the raw */
528 if(!force_libraw)
529 {
530 ret = dt_imageio_open_rawspeed(img, filename, buf);
531 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
532 return ret;
533 }
534
535#ifdef HAVE_LIBRAW
536 /* fallback that tries to open file via LibRAW to support Canon CR3 */
537 ret = dt_imageio_open_libraw(img, filename, buf);
538 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
539 return ret;
540#endif
541
542 /* try Rawspeed again in case Libraw was forced but failed */
543 if(force_libraw)
544 {
545 ret = dt_imageio_open_rawspeed(img, filename, buf);
546 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
547 return ret;
548 }
549
551}
552
553void dt_imageio_to_fractional(float in, uint32_t *num, uint32_t *den)
554{
555 if(!(in >= 0))
556 {
557 *num = *den = 0;
558 return;
559 }
560 *den = 1;
561 *num = (int)(in * *den + .5f);
562 while(fabsf(*num / (float)*den - in) > 0.001f)
563 {
564 *den *= 10;
565 *num = (int)(in * *den + .5f);
566 }
567}
568
569int dt_imageio_export(const int32_t imgid, const char *filename, dt_imageio_module_format_t *format,
570 dt_imageio_module_data_t *format_params, const double scale_factor, const gboolean high_quality,
571 const gboolean copy_metadata, const gboolean export_masks,
572 dt_colorspaces_color_profile_type_t icc_type, const gchar *icc_filename,
574 dt_imageio_module_data_t *storage_params, int num, int total, dt_export_metadata_t *metadata)
575{
576 if(strcmp(format->mime(format_params), "x-copy") == 0)
577 /* This is a just a copy, skip process and just export */
578 return format->write_image(format_params, filename, NULL, icc_type, icc_filename, NULL, 0, imgid, num, total, NULL,
579 export_masks);
580 else
581 {
582 return dt_imageio_export_with_flags(imgid, filename, format, format_params, FALSE, FALSE, TRUE, scale_factor,
583 FALSE, NULL, copy_metadata, export_masks, icc_type, icc_filename, icc_intent,
584 storage, storage_params, num, total, metadata, NULL);
585 }
586}
587
589{
592 {
593 dt_control_log(_("cannot find the style '%s' to apply during export."), format_params->style);
594 return TRUE;
595 }
596
597 dt_ioppr_check_iop_order(dev, imgid, "dt_imageio_export_with_flags");
600
602 {
605 }
606
609
610 return FALSE;
611}
612
614{
616 {
617 fprintf(stderr,"[dt_imageio_export_with_flags] ");
618 if(use_style)
619 {
620 fprintf(stderr,"appending style `%s'\n", format_params->style);
621 }
622 else fprintf(stderr,"\n");
623 int cnt = 0;
624 for(GList *nodes = pipe->nodes; nodes; nodes = g_list_next(nodes))
625 {
627 if(piece->enabled)
628 {
629 cnt++;
630 fprintf(stderr," %s", piece->module->op);
631 }
632 }
633 fprintf(stderr," (%i)\n", cnt);
634 }
635}
636
637
638void _filter_pipeline(const char *filter, dt_dev_pixelpipe_t *pipe)
639{
640 // Warning: can only filter prior to or past to a certain module, but not both !!!
641 if(filter)
642 {
643 if(!strncmp(filter, "pre:", 4)) dt_dev_pixelpipe_disable_after(pipe, filter + 4);
644 if(!strncmp(filter, "post:", 5)) dt_dev_pixelpipe_disable_before(pipe, filter + 5);
645 }
646}
647
648
649static gboolean _get_export_size(const dt_dev_pixelpipe_t *pipe, const double scale_factor, double *scale,
650 int width, int height, int *processed_width, int *processed_height)
651{
652 const double image_ratio = (double)pipe->processed_width / (double)pipe->processed_height;
653
654 if(scale_factor > 0.0)
655 {
656 *scale = fmin(scale_factor, 1.);
657 *processed_height = (int)roundf(pipe->processed_height * (*scale));
658 *processed_width = (int)roundf(pipe->processed_width * (*scale));
659 return 0;
660 }
661
662 // if width and height are both 0, we use the full resolution of the image
663 if(width == 0 && height == 0)
664 {
665 // original resolution
666 *processed_width = pipe->processed_width;
667 *processed_height = pipe->processed_height;
668 *scale = 1.;
669 return 0;
670 }
671
672 if(width > 0 && height > 0)
673 {
674 // fixed width and height : fit within a bounding box
675 *processed_width = MIN(pipe->processed_width, width);
676 *processed_height = MIN(pipe->processed_height, height);
677 double scale_x = (double)*processed_width / (double)pipe->processed_width;
678 double scale_y = (double)*processed_height / (double)pipe->processed_height;
679 *scale = fmin(scale_x, scale_y);
680
681 // Note : we handle each case separately to avoid rounding errors
682 if(image_ratio > 1.0)
683 {
684 // landscape image, width is the limiting factor
685 *processed_width = MIN((int)roundf(pipe->processed_width * (*scale)), pipe->processed_width);
686 *processed_height = MIN((int)roundf(*processed_width / image_ratio), pipe->processed_height);
687 }
688 else if(image_ratio < 1.0)
689 {
690 // portrait image, height is the limiting factor
691 *processed_height = MIN((int)roundf(pipe->processed_height * (*scale)), pipe->processed_height);
692 *processed_width = MIN((int)roundf(*processed_height * image_ratio), pipe->processed_width);
693 }
694 else
695 {
696 // square image, both width and height are the limiting factors
697 *processed_width = MIN((int)roundf(pipe->processed_width * (*scale)), pipe->processed_width);
698 *processed_height = MIN((int)roundf(pipe->processed_height * (*scale)), pipe->processed_height);
699 }
700 return 0;
701 }
702
703 if(width > 0)
704 {
705 // fluid height, fixed width
706 *processed_width = MIN(pipe->processed_width, width);
707 *processed_height = (int)roundf(*processed_width / image_ratio);
708 }
709 else if(height > 0)
710 {
711 // fluid width, fixed height
712 *processed_height = MIN(pipe->processed_height, height);
713 *processed_width = (int)roundf(*processed_height * image_ratio);
714 }
715
716 double scale_x = (double)*processed_width / (double)pipe->processed_width;
717 double scale_y = (double)*processed_height / (double)pipe->processed_height;
718 *scale = fmin(scale_x, scale_y);
719
720 return 0;
721}
722
723
724void _clamp_float_to_uint8(const float *const inbuf, uint8_t *const outbuf, const size_t processed_width,
725 const size_t processed_height)
726{
728 for(size_t k = 0; k < processed_width * processed_height; k++)
730 outbuf[4 * k + c] = (uint8_t)CLAMPF(roundf(inbuf[4 * k + c] * 255.f), 0.f, 255.f);
731}
732
733
734void _swap_byteorder_float_to_uint8(const float *const restrict inbuf, uint8_t *const outbuf,
735 const size_t processed_width, const size_t processed_height)
736{
738 for(size_t k = 0; k < processed_width * processed_height; k++)
739 {
740 outbuf[4 * k + 0] = (uint8_t)CLAMPF(roundf(inbuf[4 * k + 2] * 255.f), 0.f, 255.f);
741 outbuf[4 * k + 1] = (uint8_t)CLAMPF(roundf(inbuf[4 * k + 1] * 255.f), 0.f, 255.f);
742 outbuf[4 * k + 2] = (uint8_t)CLAMPF(roundf(inbuf[4 * k + 0] * 255.f), 0.f, 255.f);
743 outbuf[4 * k + 3] = (uint8_t)CLAMPF(roundf(inbuf[4 * k + 3] * 255.f), 0.f, 255.f);
744 }
745}
746
747
748void _export_final_buffer_to_uint16(const float *const restrict inbuf, uint16_t *const outbuf,
749 const size_t processed_width, const size_t processed_height)
750{
752 for(size_t k = 0; k < processed_width * processed_height; k++)
754 outbuf[4 * k + c] = (uint16_t)CLAMP(roundf(inbuf[4 * k + c] * 65535.f), 0.f, 65535.f);
755}
756
757// internal function: to avoid exif blob reading + 8-bit byteorder flag + high-quality override
758int dt_imageio_export_with_flags(const int32_t imgid, const char *filename,
760 const gboolean ignore_exif, const gboolean display_byteorder,
761 const gboolean high_quality, const double scale_factor, const gboolean thumbnail_export,
762 const char *filter, const gboolean copy_metadata, const gboolean export_masks,
763 dt_colorspaces_color_profile_type_t icc_type, const gchar *icc_filename,
765 dt_imageio_module_data_t *storage_params, int num, int total,
766 dt_export_metadata_t *metadata, dt_atomic_int *shutdown)
767{
768 dt_times_t start;
769 dt_get_times(&start);
770
772 void *outbuf = NULL;
773
774 // Get the history, aka sequence of editing changes
775 dt_develop_t dev;
776 dt_dev_init(&dev, 0);
777 dt_dev_load_image(&dev, imgid);
779
780 // Apply styles on top of current history
781 const gboolean use_style = !thumbnail_export && format_params->style[0] != '\0';
782 // If a style is to be applied during export, add the iop params into the history
784 goto error;
785
786 int width = MAX(format_params->max_width, 0);
787 int height = MAX(format_params->max_height, 0);
788 double scale = 1.;
789
790 // Get a pipeline, aka sequence of nodes
791 int res = 0;
795 else
796 res = dt_dev_pixelpipe_init_export(&pipe, &dev, format->levels(format_params), export_masks);
797
798 if(!res) goto error;
799
800 pipe.shutdown_ext = shutdown;
801
803
804 // Sync history with pipeline nodes
805 // Update the ICC type if DT_COLORSPACE_NONE is passed
806 dt_colorspaces_get_output_profile(imgid, &icc_type, icc_filename);
807 dt_dev_pixelpipe_set_icc(&pipe, icc_type, icc_filename, icc_intent);
808
809 // Find out what input size we want
811
812 // Take a local copy of the input buffer so we can release the mipmap cache lock immediately
813 dt_mipmap_cache_get(&buf, imgid, size, DT_MIPMAP_BLOCKING, 'r');
814
815 if(IS_NULL_PTR(buf.buf) || buf.width == 0 || buf.height == 0)
816 {
818 goto error;
819 }
820
821 const size_t buf_width = buf.width;
822 const size_t buf_height = buf.height;
824
825 // Update size with actual input and resync nodes
826 dt_dev_pixelpipe_set_input(&pipe, imgid, buf_width, buf_height, buf.iscale, size);
828
829 // Write debug info to stdout
831
832 // Remove modules past or prior a certain one.
833 // Useful for partial exports, for technical purposes (HDR merge)
834 _filter_pipeline(filter, &pipe);
835
836 // This export path drives the pipe directly instead of through dt_dev_pixelpipe_change(), so
837 // establish the buffer-format contract (and disable incompatible nodes) explicitly, after the
838 // optional filtering changed the node set and before ROI planning / global hashing.
840
841 // Get theoritical final size of image, taking distortions and croppings AND borders into account,
842 // considering full-size original input. Meaning we can enlarge or reduce the original image,
843 // even taking full-res input.
844 // Needs to be done after optional filtering, in case we filter out distortion modules
847
848 dt_show_times(&start, "[export] creating pixelpipe");
849
850 // Compute the actual final sizes that fit within the bounding box width*height
851 // while preserving original image ratio
852 int processed_width = 0;
853 int processed_height = 0;
854 _get_export_size(&pipe, scale_factor, &scale, width, height, &processed_width, &processed_height);
855
857 "[dt_imageio_export] (direct) image input %ix%i, turned to output %ix%i, will be exported to fit %ix%i "
858 "--> final size is %ix%i\n",
860 processed_height);
861
862
863 const int bpp = format->bpp(format_params);
864
865 dt_iop_roi_t roi = (dt_iop_roi_t){ 0, 0, processed_width, processed_height, scale };
866
867 dt_get_times(&start);
868 int err = dt_dev_pixelpipe_process(&pipe, roi);
869 dt_show_times(&start, thumbnail_export ? "[dev_process_thumbnail] pixel pipeline processing thread"
870 : "[dev_process_export] pixel pipeline processing thread");
871
873 {
874 dt_print(DT_DEBUG_IMAGEIO, "[dt_imageio_export_with_flags] no valid output buffer\n");
875 goto error;
876 }
877
878 // Initialised because the failure path below tests it. It is currently reached only after
879 // dt_dev_pixelpipe_cache_ref_entry_by_hash() has written NULL into it on every early
880 // return -- a callee-side contract propping up a caller-side assumption, on a path whose
881 // failure mode is unreffing a garbage pointer.
882 struct dt_pixel_cache_entry_t *cache_entry = NULL;
883 void *data = NULL;
884 /* Atomically look up the final pipeline output and increment its refcount under the cache
885 * mutex. peek() + separate ref_count_entry() has a TOCTOU window: peek releases its
886 * tryrdlock immediately and returns with no ownership, so a concurrent eviction thread
887 * could see refcount==1 (backbuf keepalive only) and decrement it to 0 between peek()
888 * returning and our ref_count_entry() call — leaving us with a dangling data pointer that
889 * the OpenMP conversion threads then read → SIGSEGV. ref_entry_by_hash() closes that
890 * window by holding cache->lock across both the lookup and the increment. */
892 &data, &cache_entry)
893 || !data)
894 {
895 if(cache_entry)
897 goto error;
898 }
899
900 /* Hold a read lock for the duration of the conversion so no writer can replace the buffer
901 * while the OpenMP threads are reading it. */
903
904 // Down-conversion to low-precision formats:
905 const size_t pixels = pipe.backbuf.width * pipe.backbuf.height * 4;
906 if(bpp == 8)
907 {
909 sizeof(uint8_t) * pixels,
910 0);
913 else if(outbuf)
915
916 /* Thumbnail export stores the in-memory RGBA buffer straight into the mipmap cache.
917 * The thumbnail pipeline does not maintain a meaningful alpha contract across all
918 * modules, so random zero/garbage alpha values would make valid RGB thumbnails render
919 * black in consumers that composite the mipmap buffer. Keep thumbnail alpha opaque at
920 * the export boundary and leave RGB untouched. */
922 {
923 uint8_t *thumbnail_buf = (uint8_t *)outbuf;
925 for(size_t k = 0; k < pixels / 4; k++) thumbnail_buf[4 * k + 3] = UINT8_MAX;
926 }
927 }
928 else if(bpp == 16)
929 {
931 sizeof(uint16_t) * pixels,
932 0);
933 if(outbuf)
935
937 {
938 uint16_t *thumbnail_buf = (uint16_t *)outbuf;
940 for(size_t k = 0; k < pixels / 4; k++) thumbnail_buf[4 * k + 3] = UINT16_MAX;
941 }
942 }
943 else // output float, no further harm done to the pixels :)
944 {
946 sizeof(float_t) * pixels,
947 0);
948 if(outbuf)
949 memcpy(outbuf, data, sizeof(float_t) * pixels);
950
952 {
953 float *thumbnail_buf = (float *)outbuf;
955 for(size_t k = 0; k < pixels / 4; k++) thumbnail_buf[4 * k + 3] = 1.0f;
956 }
957 }
958
959 // Decrease ref count on the cache entry and release the read lock
962
963 if(IS_NULL_PTR(outbuf)) goto error;
964
967
968 // Exif data should be 65536 bytes max, but if original size is close to that,
969 // adding new tags could make it go over that... so let it be and see what
970 // happens when we write the image
971 int length = 0;
972 uint8_t *exif_profile = NULL;
973
974 if(!ignore_exif)
975 {
976 gboolean from_cache = TRUE;
977 char pathname[DT_PATH_MAX] = { 0 };
979 // find output color profile for this image:
980 int sRGB = (icc_type == DT_COLORSPACE_SRGB);
981 // last param is dng mode, it's false here
983 }
984
985 // Finally: write image buffer to target container
986 res = format->write_image(format_params, filename, outbuf, icc_type, icc_filename, exif_profile, length, imgid,
987 num, total, &pipe, export_masks);
988
990 if(res) goto error;
991
993 dt_dev_cleanup(&dev);
994
995 /* now write xmp into that container, if possible */
997 dt_exif_xmp_attach_export(imgid, filename, metadata);
998
999 if(!thumbnail_export && strcmp(format->mime(format_params), "memory")
1000 && !(format->flags(format_params) & FORMAT_FLAGS_NO_TMPFILE))
1001 {
1003 format_params, storage, storage_params);
1004 }
1005
1007 return 0; // success
1008
1009error:
1012 dt_dev_cleanup(&dev);
1013 return 1;
1014}
1015
1016
1017
1018// =================================================
1019// combined reading
1020// =================================================
1021
1022dt_imageio_retval_t dt_imageio_open(dt_image_t *img, // non-const * means you hold a write lock!
1023 const char *filename, // full path
1024 dt_mipmap_buffer_t *buf)
1025{
1026 /* first of all, check if file exists, don't bother to test loading if not exists */
1027 if(!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
1028 return !DT_IMAGEIO_OK;
1029
1031 img->loader = LOADER_UNKNOWN;
1032
1033 // Start with the decoder(s) the extension routes to (fast path). Unlike before, a failure here
1034 // no longer aborts: an extension can route to more than one category (see
1035 // dt_image_ext_is_ambiguous() -- e.g. a linear DNG that a raw decoder can't demosaic, or a
1036 // renamed/mislabeled file), so let it cascade into the bruteforce section below instead of
1037 // reporting "corrupted" on a file a later attempt would have opened fine.
1038 if(dt_imageio_is_raster(filename))
1039 ret = dt_imageio_open_raster(img, filename, buf);
1040
1041 if(ret != DT_IMAGEIO_OK && ret != DT_IMAGEIO_CACHE_FULL && dt_imageio_is_raw(filename))
1042 ret = dt_imageio_open_raw(img, filename, buf);
1043
1044 if(ret != DT_IMAGEIO_OK && ret != DT_IMAGEIO_CACHE_FULL && dt_imageio_is_hdr(filename))
1045 ret = dt_imageio_open_hdr(img, filename, buf);
1046
1047 // fallback: bruteforce everything hoping for a miracle
1048 // Most likely, it's a format we never heard of.
1049 if(ret != DT_IMAGEIO_OK && ret != DT_IMAGEIO_CACHE_FULL)
1050 ret = dt_imageio_open_raster(img, filename, buf);
1051
1052 if(ret != DT_IMAGEIO_OK && ret != DT_IMAGEIO_CACHE_FULL)
1053 ret = dt_imageio_open_raw(img, filename, buf);
1054
1055 if(ret != DT_IMAGEIO_OK && ret != DT_IMAGEIO_CACHE_FULL)
1056 ret = dt_imageio_open_hdr(img, filename, buf);
1057
1058 // Final check and abort
1059 if(ret != DT_IMAGEIO_OK)
1060 {
1061 fprintf(stderr, "[imageio] The file %s is supported by none of our decoders.\n", filename);
1062 dt_control_log(_("The file `%s` is supported by none of our decoders."), filename);
1063 return ret;
1064 }
1065
1066 img->p_width = img->width - img->crop_x - img->crop_width;
1067 img->p_height = img->height - img->crop_y - img->crop_height;
1068
1069 // The codec has now populated img->dsc: finalize the buffer-derived type flags
1070 // (DT_IMAGE_MOSAIC + DT_IMAGE_BUFFER_RESOLVED). This is the single point where the
1071 // decoded descriptor is mapped to the persisted classification.
1073
1074 return ret;
1075}
1076
1078 dt_mipmap_buffer_t *buf)
1079{
1080 if(IS_NULL_PTR(buf)) return DT_IMAGEIO_LOAD_FAILED;
1081
1082 memset(buf, 0, sizeof(*buf));
1083 buf->size = DT_MIPMAP_FULL;
1084
1085 /* The decoder allocates into the entry it is handed. Owning one here is what lets callers
1086 * decode a file without knowing that a cache entry exists -- see the header. */
1089
1090 const dt_imageio_retval_t ret = dt_imageio_open(img, filename, buf);
1092 return ret;
1093}
1094
1096{
1097 if(IS_NULL_PTR(buf) || IS_NULL_PTR(buf->cache_entry)) return;
1099 buf->cache_entry = NULL;
1100 buf->buf = NULL;
1101}
1102
1103gboolean dt_imageio_lookup_makermodel(const char *maker, const char *model,
1104 char *mk, int mk_len, char *md, int md_len,
1105 char *al, int al_len)
1106{
1107 // At this stage, we can't tell which loader is used to open the image.
1108 gboolean found = dt_rawspeed_lookup_makermodel(maker, model,
1109 mk, mk_len,
1110 md, md_len,
1111 al, al_len);
1112 if(found == FALSE)
1113 {
1114 // Special handling for CR3 raw files via libraw
1116 mk, mk_len,
1117 md, md_len,
1118 al, al_len);
1119 }
1120 return found;
1121}
1122
1123// clang-format off
1124// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
1125// vim: shiftwidth=2 expandtab tabstop=2 cindent
1126// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
1127// clang-format on
static void error(char *msg)
Definition ashift_lsd.c:202
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
atomic_int dt_atomic_int
Definition atomic.h:68
void cleanup(dt_imageio_module_format_t *self)
Definition avif.c:170
static const float x
The colour-profile module's API: which profiles exist, and how to apply one.
static dt_aligned_pixel_t sRGB
const dt_colormatrix_t dt_aligned_pixel_t out
const float top
gchar * dt_conf_get_string(const char *name)
Read the stored string for name as a private copy.
void dt_image_buffer_resolve_flags(dt_image_t *img)
void dt_image_full_path(const int32_t imgid, char *pathname, size_t pathname_len, gboolean *from_cache, const char *calling_func)
Get the full path of an image out of the database.
void dt_control_log(const char *msg,...)
Definition control.c:839
void dt_dev_pop_history_items(dt_develop_t *dev)
Thread-safe wrapper around dt_dev_pop_history_items_ext(), then update GUI.
void dt_dev_pixelpipe_propagate_formats(dt_dev_pixelpipe_t *pipe)
void dt_dev_pixelpipe_get_roi_out(dt_dev_pixelpipe_t *pipe, const int width_in, const int height_in, int *width, int *height)
void dt_dev_cleanup(dt_develop_t *dev)
Definition develop.c:237
dt_dev_image_storage_t dt_dev_load_image(dt_develop_t *dev, const int32_t imgid)
Definition develop.c:1020
void dt_dev_init(dt_develop_t *dev, int32_t gui_attached)
Definition develop.c:143
const int res
Definition dtpthread.h:351
int dt_exif_get_thumbnail(const char *path, uint8_t **buffer, size_t *size, char **mime_type, int *width, int *height, int min_width)
Definition exif.cc:1929
What a photograph says about itself: the EXIF, IPTC and XMP tags a camera and a cataloguer write,...
float dt_boundingbox_t[4]
Definition image.h:83
dt_image_orientation_t
Definition image.h:216
@ ORIENTATION_SWAP_XY
Definition image.h:221
@ ORIENTATION_FLIP_Y
Definition image.h:219
@ ORIENTATION_FLIP_X
Definition image.h:220
dt_imageio_retval_t
Definition image.h:91
@ DT_IMAGEIO_LOAD_FAILED
Definition image.h:99
@ DT_IMAGEIO_OK
Definition image.h:92
@ DT_IMAGEIO_CACHE_FULL
Definition image.h:95
@ DT_IMAGEIO_FILE_CORRUPTED
Definition image.h:94
@ LOADER_UNKNOWN
Definition image.h:283
gboolean dt_image_ext_is_ldr(const char *ext)
gboolean dt_image_ext_is_raw(const char *ext)
gboolean dt_image_ext_is_hdr(const char *ext)
int bpp
dt_imageio_retval_t dt_imageio_open_avif(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
void _clamp_float_to_uint8(const float *const inbuf, uint8_t *const outbuf, const size_t processed_width, const size_t processed_height)
void dt_imageio_flip_buffers_ui8_to_float(float *out, const uint8_t *in, const float black, const float white, const int ch, const int wd, const int ht, const int fwd, const int fht, const int stride, const dt_image_orientation_t orientation)
int dt_imageio_is_hdr(const char *filename)
gboolean dt_imageio_lookup_makermodel(const char *maker, const char *model, char *mk, int mk_len, char *md, int md_len, char *al, int al_len)
dt_imageio_retval_t dt_imageio_open(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *buf)
void dt_imageio_close_standalone(dt_mipmap_buffer_t *buf)
Release a buffer from dt_imageio_open_standalone(). NULL-safe, and safe to call on a buffer whose ope...
void _swap_byteorder_float_to_uint8(const float *const restrict inbuf, uint8_t *const outbuf, const size_t processed_width, const size_t processed_height)
dt_imageio_retval_t dt_imageio_open_raster(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *buf)
void _filter_pipeline(const char *filter, dt_dev_pixelpipe_t *pipe)
static gboolean _get_export_size(const dt_dev_pixelpipe_t *pipe, const double scale_factor, double *scale, int width, int height, int *processed_width, int *processed_height)
dt_imageio_retval_t dt_imageio_open_standalone(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *buf)
Decode a file into a buffer the CALLER owns, with no cache involvement.
gboolean dt_imageio_is_raster(const char *filename)
gboolean dt_imageio_has_mono_preview(const char *filename)
int dt_imageio_export(const int32_t imgid, const char *filename, dt_imageio_module_format_t *format, dt_imageio_module_data_t *format_params, const double scale_factor, const gboolean high_quality, const gboolean copy_metadata, const gboolean export_masks, dt_colorspaces_color_profile_type_t icc_type, const gchar *icc_filename, dt_iop_color_intent_t icc_intent, dt_imageio_module_storage_t *storage, dt_imageio_module_data_t *storage_params, int num, int total, dt_export_metadata_t *metadata)
void dt_imageio_to_fractional(float in, uint32_t *num, uint32_t *den)
gboolean dt_imageio_crop_thumbnail(const dt_boundingbox_t box, uint8_t *const buffer, int32_t *width, int32_t *height)
Crop an 8-bit RGBA preview buffer in place to a normalized bounding box.
gboolean dt_imageio_is_handled_by_libraw(dt_image_t *img, const char *filename)
gboolean _apply_style_before_export(dt_develop_t *dev, dt_imageio_module_data_t *format_params, const int32_t imgid)
dt_imageio_retval_t dt_imageio_open_hdr(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *buf)
dt_imageio_retval_t dt_imageio_open_raw(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *buf)
static gboolean _is_in_list(const char *elem, char *list)
Is elem one of the comma-separated entries of list?
int dt_imageio_export_with_flags(const int32_t imgid, const char *filename, dt_imageio_module_format_t *format, dt_imageio_module_data_t *format_params, const gboolean ignore_exif, const gboolean display_byteorder, const gboolean high_quality, const double scale_factor, const gboolean thumbnail_export, const char *filter, const gboolean copy_metadata, const gboolean export_masks, dt_colorspaces_color_profile_type_t icc_type, const gchar *icc_filename, dt_iop_color_intent_t icc_intent, dt_imageio_module_storage_t *storage, dt_imageio_module_data_t *storage_params, int num, int total, dt_export_metadata_t *metadata, dt_atomic_int *shutdown)
gboolean dt_imageio_is_raw(const char *filename)
int dt_imageio_large_thumbnail(const char *filename, uint8_t **buffer, int32_t *th_width, int32_t *th_height, dt_colorspaces_color_profile_type_t *color_space, const int width, const int height)
Load the thumbnail embedded into a RAW file having at least the size MAX(width, height) x MAX(width,...
void _print_export_debug(dt_dev_pixelpipe_t *pipe, dt_imageio_module_data_t *format_params, const gboolean use_style)
__DT_CLONE_TARGETS__ void dt_imageio_flip_buffers(char *out, const char *in, const size_t bpp, const int wd, const int ht, const int fwd, const int fht, const int stride, const dt_image_orientation_t orientation)
void _export_final_buffer_to_uint16(const float *const restrict inbuf, uint16_t *const outbuf, const size_t processed_width, const size_t processed_height)
dt_imageio_retval_t dt_imageio_open_exr(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
dt_imageio_retval_t dt_imageio_open_heif(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
dt_imageio_retval_t dt_imageio_open_j2k(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
int dt_imageio_jpeg_decompress_header(const void *in, size_t length, dt_imageio_jpeg_t *jpg)
dt_imageio_retval_t dt_imageio_open_jpeg(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
int dt_imageio_jpeg_decompress(dt_imageio_jpeg_t *jpg, uint8_t *out)
dt_imageio_retval_t dt_imageio_open_libraw(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *buf)
gboolean dt_libraw_lookup_makermodel(const char *maker, const char *model, char *mk, int mk_len, char *md, int md_len, char *al, int al_len)
@ FORMAT_FLAGS_SUPPORT_XMP
@ FORMAT_FLAGS_NO_TMPFILE
dt_imageio_retval_t dt_imageio_open_pfm(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
Definition imageio_pfm.c:42
dt_imageio_retval_t dt_imageio_open_png(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
dt_imageio_retval_t dt_imageio_open_pnm(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
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)
gboolean dt_rawspeed_lookup_makermodel(const char *maker, const char *model, char *mk, int mk_len, char *md, int md_len, char *al, int al_len)
dt_imageio_retval_t dt_imageio_open_rawspeed(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
dt_imageio_retval_t dt_imageio_open_rgbe(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
dt_imageio_retval_t dt_imageio_open_tiff(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
gboolean dt_imageio_tiff_decode_blob(const uint8_t *const blob, const size_t bufsize, uint8_t **out, int32_t *width, int32_t *height)
Decode a TIFF held in memory into 8-bit RGBx, for the previews raw files embed.
dt_imageio_retval_t dt_imageio_open_webp(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
const char * maker
const char * model
void dt_ioppr_resync_modules_order(dt_develop_t *dev)
Update dev->iop module order values from dev->iop_order_list.
Definition iop_order.c:1249
void dt_ioppr_update_for_style_items(dt_develop_t *dev, GList *st_items, gboolean append)
Update dev->iop_order_list with modules referenced by style items.
Definition iop_order.c:1721
int dt_ioppr_check_iop_order(dt_develop_t *dev, const int32_t imgid, const char *msg)
Debug helper to validate the current order for a develop context.
Definition iop_order.c:2351
static const dt_dev_pixelpipe_t * pipe
Definition layers.h:49
static const dt_dev_pixelpipe_t const dt_dev_pixelpipe_iop_t * piece
Definition layers.h:50
@ DT_DEBUG_IMAGEIO
Definition logging.h:68
int32_t dt_get_debug_flags(void)
Definition darktable.c:2085
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
#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 macros.h:96
#define CLAMPF(a, mn, mx)
Definition math.h:91
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
Definition mem_alloc.h:171
uint32_t width
Definition mipmap_cache.c:0
uint32_t height
Definition mipmap_cache.c:1
size_t size
Definition mipmap_cache.c:3
dt_colorspaces_color_profile_type_t color_space
Definition mipmap_cache.c:5
@ DT_MIPMAP_BLOCKING
dt_mipmap_size_t
@ DT_MIPMAP_FULL
#define dt_mipmap_cache_get(B, C, D, E, F)
#define dt_mipmap_cache_release(B)
#define __OMP_PARALLEL_FOR__(...)
Definition openmp.h:95
#define DT_PATH_MAX
Buffer size for a filesystem path anywhere in Ansel.
Definition paths.h:57
void dt_dev_pixelpipe_cache_ref_count_entry(gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Take or release one reference on a cache line. A referenced line is never evicted,...
void dt_dev_pixelpipe_cache_rdlock_entry(gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Lock or release the read lock on the entry.
gboolean dt_dev_pixelpipe_cache_ref_entry_by_hash(const uint64_t hash, void **data, dt_pixel_cache_entry_t **entry)
Resolve and retain an existing cache entry by hash.
#define dt_pixelpipe_cache_alloc_align_cache(size, id)
#define dt_pixelpipe_cache_free_align(mem)
void dt_dev_pixelpipe_set_input(dt_dev_pixelpipe_t *pipe, int32_t imgid, int width, int height, float iscale, dt_mipmap_size_t size)
void dt_dev_pixelpipe_disable_before(dt_dev_pixelpipe_t *pipe, const char *op)
void dt_dev_pixelpipe_disable_after(dt_dev_pixelpipe_t *pipe, const char *op)
void dt_dev_pixelpipe_set_icc(dt_dev_pixelpipe_t *pipe, dt_colorspaces_color_profile_type_t icc_type, const gchar *icc_filename, dt_iop_color_intent_t icc_intent)
void dt_dev_pixelpipe_create_nodes(dt_dev_pixelpipe_t *pipe)
int dt_dev_pixelpipe_init_thumbnail(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev)
int dt_dev_pixelpipe_init_export(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev, int levels, gboolean store_masks)
void dt_dev_pixelpipe_cleanup(dt_dev_pixelpipe_t *pipe)
int dt_dev_pixelpipe_process(dt_dev_pixelpipe_t *pipe, dt_iop_roi_t roi)
#define dt_dev_pixelpipe_synch_all(pipe)
static uint64_t dt_dev_backbuf_get_hash(const dt_backbuf_t *backbuf)
dt_iop_color_intent_t
ICC rendering intent, as stored in iop params and in conf.
dt_colorspaces_color_profile_type_t
@ DT_COLORSPACE_SRGB
sRGB – registered TWICE, and the two entries are not interchangeable.
#define DT_DEBUG_CONTROL_SIGNAL_RAISE(ctlsig, signal,...)
Definition signal.h:390
struct dt_control_signal_t * dt_control_signal_get_global(void)
Definition darktable.c:616
@ DT_SIGNAL_IMAGE_EXPORT_TMPFILE
This signal is raised after an image has been exported to a file, but before it is sent to facebook/p...
Definition signal.h:265
#define for_four_channels(_var,...)
Definition simd.h:89
void dt_cache_entry_free_detached(dt_cache_entry_t *entry)
Release an entry from dt_cache_entry_new_detached(), and its data. NULL-safe.
dt_cache_entry_t * dt_cache_entry_new_detached(void)
Allocate a cache entry that belongs to NO cache, for a one-shot decode.
GList * dt_styles_get_item_list(const char *name, gboolean params, int32_t imgid)
void dt_styles_apply_style_item(dt_develop_t *dev, dt_style_item_t *style_item)
void dt_style_item_free(gpointer data)
dt_backbuf_t backbuf
dt_atomic_int * shutdown_ext
int32_t height
Definition image.h:397
dt_image_loader_t loader
Definition image.h:417
int32_t crop_height
Definition image.h:398
int32_t width
Definition image.h:397
char exif_maker[64]
Definition image.h:374
int32_t crop_y
Definition image.h:398
int32_t crop_x
Definition image.h:398
int32_t p_height
Definition image.h:397
int32_t p_width
Definition image.h:397
char exif_model[64]
Definition image.h:375
int32_t crop_width
Definition image.h:398
Region of interest passed through the pixelpipe.
Definition format.h:49
dt_cache_entry_t * cache_entry
dt_mipmap_size_t size
void * data
#define __DT_CLONE_TARGETS__
typedef double((*spd)(unsigned long int wavelength, double TempK))
#define MIN(a, b)
Definition thinplate.c:32
#define MAX(a, b)
Definition thinplate.c:29
void dt_show_times(const dt_times_t *start, const char *prefix)
Definition darktable.c:2138
static void dt_get_times(dt_times_t *t)
Definition times.h:50
Telling the user something happened.
int dt_exif_xmp_attach_export(const int32_t imgid, const char *filename, void *metadata)
int dt_exif_read_blob(uint8_t **buf, const char *path, const int32_t imgid, const int sRGB, const int out_width, const int out_height, const int dng_mode)
The XMP document that carries an image's development: history stack, mask shapes, module order,...