Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
imageio.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*/
56#include "common/image.h"
57#ifdef HAVE_CONFIG_H
58#include "config.h"
59#endif
60#include "common/colorlabels.h"
61#include "common/colorspaces.h"
62#include "common/darktable.h"
63#include "common/debug.h"
64#include "common/exif.h"
65#include "common/image_cache.h"
66#include "common/history.h"
67#include "common/imageio.h"
69#ifdef HAVE_OPENEXR
70#include "common/imageio_exr.h"
71#endif
72#ifdef HAVE_OPENJPEG
73#include "common/imageio_j2k.h"
74#endif
75#include "common/imageio_gm.h"
76#include "common/imageio_im.h"
77#include "common/imageio_jpeg.h"
78#include "common/imageio_pfm.h"
79#include "common/imageio_png.h"
80#include "common/imageio_pnm.h"
83#include "common/imageio_rgbe.h"
84#include "common/imageio_tiff.h"
85#ifdef HAVE_LIBAVIF
86#include "common/imageio_avif.h"
87#endif
88#ifdef HAVE_LIBHEIF
89#include "common/imageio_heif.h"
90#endif
91#ifdef HAVE_WEBP
92#include "common/imageio_webp.h"
93#endif
95#include "common/mipmap_cache.h"
96#include "common/styles.h"
97#include "control/conf.h"
98#include "control/control.h"
99#include "develop/blend.h"
100#include "develop/develop.h"
101#include "develop/imageop.h"
102
103#if defined(HAVE_GRAPHICSMAGICK)
104#include <magick/api.h>
105#include <magick/blob.h>
106#elif defined(HAVE_IMAGEMAGICK)
107#include <MagickWand/MagickWand.h>
108#endif
109
110#include <assert.h>
111#include <glib/gstdio.h>
112#include <inttypes.h>
113#include <math.h>
114#include <stdio.h>
115#include <stdlib.h>
116#include <string.h>
117#include <strings.h>
118
119// These lists drive *type inference from the file extension only* (dt_imageio_get_type_from_extension).
120// They are deliberately conservative: the extension is only allowed to commit a dynamic-range flag
121// when the container's sample format is fixed. A raw extension always means sensor data; an
122// integer-only container is always LDR; a float-only container is always HDR.
123//
124// Containers that can hold EITHER integer or float / high-bit-depth data — TIFF, AVIF, HEIF/HEIC,
125// and `dng` — are NOT listed here on purpose: their dynamic range cannot be known before decoding,
126// so they stay UNKNOWN until dt_image_buffer_resolve_flags() classifies them from the decoded
127// buffer datatype (TYPE_FLOAT -> HDR, integer non-raw -> LDR). Decoder *routing* for those formats
128// lives in the separate raster_formats[] / hdr_formats[] lists below, which is a different concern.
129static const gchar *_supported_raw[]
130 = { "3fr", "ari", "arw", "bay", "cr2", "cr3", "crw", "dc2", "dcr", "erf", "fff",
131 "ia", "iiq", "k25", "kc2", "kdc", "mdc", "mef", "mos", "mrw", "nef", "nrw",
132 "orf", "pef", "raf", "raw", "rw2", "rwl", "sr2", "srf", "srw", "sti", "x3f", NULL };
133// integer-only raster containers — unambiguously low dynamic range:
134static const gchar *_supported_ldr[]
135 = { "bmp", "bmq", "cap", "cine", "cs1", "dcm", "gif", "gpr", "j2c", "j2k", "jng", "jp2", "jpc",
136 "jpeg", "jpg", "miff", "mng", "ori", "pbm", "pgm", "png", "pnm", "ppm", "pxn", "qtk", "rdc",
137 "webp", NULL };
138// float-only raster containers — unambiguously high dynamic range:
139static const gchar *_supported_hdr[] = { "exr", "hdr", "pfm", NULL };
140
156#if defined(HAVE_GRAPHICSMAGICK)
157static const char *_preview_format_from_mime_type(const char *mime_type)
158{
159 if(IS_NULL_PTR(mime_type) || mime_type[0] == '\0') return NULL;
160
161 if(!strcmp(mime_type, "image/jpeg")) return "JPEG";
162 if(!strcmp(mime_type, "image/png")) return "PNG";
163 if(!strcmp(mime_type, "image/tiff")) return "TIFF";
164 if(!strcmp(mime_type, "image/x-tiff")) return "TIFF";
165 if(!strcmp(mime_type, "image/gif")) return "GIF";
166 if(!strcmp(mime_type, "image/bmp")) return "BMP";
167 if(!strcmp(mime_type, "image/x-portable-pixmap")) return "PPM";
168 if(!strcmp(mime_type, "image/x-portable-graymap")) return "PGM";
169 if(!strcmp(mime_type, "image/x-portable-bitmap")) return "PBM";
170 if(!strcmp(mime_type, "image/x-portable-anymap")) return "PNM";
171 if(!strcmp(mime_type, "image/webp")) return "WEBP";
172 return NULL;
173}
174#endif
175
176// Best-effort image-type hint from the file extension. Returns DT_IMAGE_RAW / DT_IMAGE_LDR /
177// DT_IMAGE_HDR for the unambiguous extensions, or 0 ("unknown") for containers whose dynamic range
178// only the decoder can settle (TIFF, AVIF, HEIF/HEIC, DNG). Callers must treat 0 as "decode it";
179// dt_image_buffer_resolve_flags() sets the authoritative LDR/HDR/MOSAIC flags once decoded.
181{
182 const char *ext = g_str_has_prefix(extension, ".") ? extension + 1 : extension;
183 for(const char **i = _supported_raw; !IS_NULL_PTR(*i); i++)
184 {
185 if(!g_ascii_strncasecmp(ext, *i, strlen(*i)))
186 {
187 return DT_IMAGE_RAW;
188 }
189 }
190 for(const char **i = _supported_hdr; !IS_NULL_PTR(*i); i++)
191 {
192 if(!g_ascii_strncasecmp(ext, *i, strlen(*i)))
193 {
194 return DT_IMAGE_HDR;
195 }
196 }
197 for(const char **i = _supported_ldr; !IS_NULL_PTR(*i); i++)
198 {
199 if(!g_ascii_strncasecmp(ext, *i, strlen(*i)))
200 {
201 return DT_IMAGE_LDR;
202 }
203 }
204 // default to 0
205 return 0;
206}
207
208int dt_imageio_large_thumbnail(const char *filename, uint8_t **buffer, int32_t *th_width, int32_t *th_height,
210{
211 int res = 1;
212
213 uint8_t *buf = NULL;
214 char *mime_type = NULL;
215 size_t bufsize;
216
217 if(dt_exif_get_thumbnail(filename, &buf, &bufsize, &mime_type, th_width, th_height, MAX(width, height)))
218 goto error;
219
220 if(strcmp(mime_type, "image/jpeg") == 0)
221 {
222 // Decompress the JPG into our own memory format
224 if(dt_imageio_jpeg_decompress_header(buf, bufsize, &jpg)) goto error;
225 *buffer = (uint8_t *)dt_pixelpipe_cache_alloc_align_cache(
226 sizeof(uint8_t) * 4 * jpg.width * jpg.height,
227 0);
228 if(!*buffer) goto error;
229
230 *th_width = jpg.width;
231 *th_height = jpg.height;
232 // TODO: check if the embedded thumbs have a color space set! currently we assume that it's always sRGB
234 if(dt_imageio_jpeg_decompress(&jpg, *buffer))
235 {
237 *buffer = NULL;
238 goto error;
239 }
240
241 res = 0;
242 }
243 else
244 {
245#if defined(HAVE_GRAPHICSMAGICK)
246 const char *const preview_format = _preview_format_from_mime_type(mime_type);
247 ExceptionInfo exception;
248 Image *image = NULL;
249 ImageInfo *image_info = NULL;
250
251 GetExceptionInfo(&exception);
252 image_info = CloneImageInfo((ImageInfo *)NULL);
253 if(!IS_NULL_PTR(preview_format))
254 g_strlcpy(image_info->magick, preview_format, sizeof(image_info->magick));
255
256 image = BlobToImage(image_info, buf, bufsize, &exception);
257
258 if(exception.severity != UndefinedException) CatchException(&exception);
259
260 if(IS_NULL_PTR(image))
261 {
262 fprintf(stderr, "[dt_imageio_large_thumbnail GM] thumbnail not found?\n");
263 goto error_gm;
264 }
265
266 *th_width = image->columns;
267 *th_height = image->rows;
268 *color_space = DT_COLORSPACE_SRGB; // FIXME: this assumes that embedded thumbnails are always srgb
269
270 *buffer = (uint8_t *)dt_pixelpipe_cache_alloc_align_cache(
271 sizeof(uint8_t) * 4 * image->columns * image->rows,
272 0);
273 if(!*buffer) goto error_gm;
274
275 for(uint32_t row = 0; row < image->rows; row++)
276 {
277 uint8_t *bufprt = *buffer + (size_t)4 * row * image->columns;
278 int gm_ret = DispatchImage(image, 0, row, image->columns, 1, "RGBP", CharPixel, bufprt, &exception);
279
280 if(exception.severity != UndefinedException) CatchException(&exception);
281
282 if(gm_ret != MagickPass)
283 {
284 fprintf(stderr, "[dt_imageio_large_thumbnail GM] error_gm reading thumbnail\n");
286 *buffer = NULL;
287 goto error_gm;
288 }
289 }
290
291 // fprintf(stderr, "[dt_imageio_large_thumbnail GM] successfully decoded thumbnail\n");
292 res = 0;
293
294 error_gm:
295 if(image) DestroyImage(image);
296 if(image_info) DestroyImageInfo(image_info);
297 DestroyExceptionInfo(&exception);
298 if(res) goto error;
299#elif defined(HAVE_IMAGEMAGICK)
300 MagickWand *image = NULL;
301 MagickBooleanType mret;
302
303 image = NewMagickWand();
304 mret = MagickReadImageBlob(image, buf, bufsize);
305 if(mret != MagickTrue)
306 {
307 fprintf(stderr, "[dt_imageio_large_thumbnail IM] thumbnail not found?\n");
308 goto error_im;
309 }
310
311 *th_width = MagickGetImageWidth(image);
312 *th_height = MagickGetImageHeight(image);
313 switch (MagickGetImageColorspace(image)) {
314 case sRGBColorspace:
316 break;
317 default:
318 fprintf(stderr,
319 "[dt_imageio_large_thumbnail IM] could not map colorspace, using sRGB");
321 break;
322 }
323
324 *buffer = malloc(sizeof(uint8_t) * (*th_width) * (*th_height) * 4);
325 if(IS_NULL_PTR(*buffer)) goto error_im;
326
327 mret = MagickExportImagePixels(image, 0, 0, *th_width, *th_height, "RGBP", CharPixel, *buffer);
328 if(mret != MagickTrue) {
329 dt_free(*buffer);
330 fprintf(stderr,
331 "[dt_imageio_large_thumbnail IM] error while reading thumbnail\n");
332 goto error_im;
333 }
334
335 res = 0;
336
337error_im:
338 DestroyMagickWand(image);
339 if(res != 0) goto error;
340#else
341 fprintf(stderr,
342 "[dt_imageio_large_thumbnail] error: The thumbnail image is not in "
343 "JPEG format, and DT was built without neither GraphicsMagick or "
344 "ImageMagick. Please rebuild DT with GraphicsMagick or ImageMagick "
345 "support enabled.\n");
346#endif
347 }
348
349 if(res)
350 {
351 fprintf(
352 stderr,
353 "[dt_imageio_large_thumbnail] error: Not a supported thumbnail image format or broken thumbnail: %s\n",
354 mime_type);
355 goto error;
356 }
357
358error:
359 dt_free(mime_type);
360 dt_free(buf);
361 return res;
362}
363
364gboolean dt_imageio_has_mono_preview(const char *filename)
365{
367 uint8_t *tmp = NULL;
368 int32_t thumb_width = 0, thumb_height = 0;
369 gboolean mono = FALSE;
370
371 if(dt_imageio_large_thumbnail(filename, &tmp, &thumb_width, &thumb_height, &color_space, -1, -1))
372 goto cleanup;
373 if((thumb_width < 32) || (thumb_height < 32) || (IS_NULL_PTR(tmp)))
374 goto cleanup;
375
376 mono = TRUE;
377 for(int y = 0; y < thumb_height; y++)
378 {
379 uint8_t *in = (uint8_t *)tmp + (size_t)4 * y * thumb_width;
380 for(int x = 0; x < thumb_width; x++, in += 4)
381 {
382 if((in[0] != in[1]) || (in[0] != in[2]) || (in[1] != in[2]))
383 {
384 mono = FALSE;
385 goto cleanup;
386 }
387 }
388 }
389
390 cleanup:
391
392 dt_print(DT_DEBUG_IMAGEIO,"[dt_imageio_has_mono_preview] testing `%s', yes/no %i, %ix%i\n", filename, mono, thumb_width, thumb_height);
394 return mono;
395}
396
398void dt_imageio_flip_buffers(char *out, const char *in, const size_t bpp, const int wd, const int ht,
399 const int fwd, const int fht, const int stride,
400 const dt_image_orientation_t orientation)
401{
402 if(!orientation)
403 {
405 for(int j = 0; j < ht; j++) memcpy(out + (size_t)j * bpp * wd, in + (size_t)j * stride, bpp * wd);
406 return;
407 }
408 int ii = 0, jj = 0;
409 int si = bpp, sj = wd * bpp;
410 if(orientation & ORIENTATION_SWAP_XY)
411 {
412 sj = bpp;
413 si = ht * bpp;
414 }
415 if(orientation & ORIENTATION_FLIP_Y)
416 {
417 jj = (int)fht - jj - 1;
418 sj = -sj;
419 }
420 if(orientation & ORIENTATION_FLIP_X)
421 {
422 ii = (int)fwd - ii - 1;
423 si = -si;
424 }
426 for(int j = 0; j < ht; j++)
427 {
428 char *out2 = out + (size_t)labs(sj) * jj + (size_t)labs(si) * ii + (size_t)sj * j;
429 const char *in2 = in + (size_t)stride * j;
430 for(int i = 0; i < wd; i++)
431 {
432 memcpy(out2, in2, bpp);
433 in2 += bpp;
434 out2 += si;
435 }
436 }
437}
438
439void dt_imageio_flip_buffers_ui8_to_float(float *out, const uint8_t *in, const float black, const float white,
440 const int ch, const int wd, const int ht, const int fwd,
441 const int fht, const int stride,
442 const dt_image_orientation_t orientation)
443{
444 const float scale = 1.0f / (white - black);
445 if(!orientation)
446 {
448 for(int j = 0; j < ht; j++)
449 for(int i = 0; i < wd; i++)
450 for(int k = 0; k < ch; k++)
451 out[4 * ((size_t)j * wd + i) + k] = (in[(size_t)j * stride + (size_t)ch * i + k] - black) * scale;
452 return;
453 }
454 int ii = 0, jj = 0;
455 int si = 4, sj = wd * 4;
456 if(orientation & ORIENTATION_SWAP_XY)
457 {
458 sj = 4;
459 si = ht * 4;
460 }
461 if(orientation & ORIENTATION_FLIP_Y)
462 {
463 jj = (int)fht - jj - 1;
464 sj = -sj;
465 }
466 if(orientation & ORIENTATION_FLIP_X)
467 {
468 ii = (int)fwd - ii - 1;
469 si = -si;
470 }
472 for(int j = 0; j < ht; j++)
473 {
474 float *out2 = out + (size_t)labs(sj) * jj + (size_t)labs(si) * ii + sj * j;
475 const uint8_t *in2 = in + (size_t)stride * j;
476 for(int i = 0; i < wd; i++)
477 {
478 for(int k = 0; k < ch; k++) out2[k] = (in2[k] - black) * scale;
479 in2 += ch;
480 out2 += si;
481 }
482 }
483}
484
486{
487 // if buf is NULL, don't proceed
488 if(IS_NULL_PTR(buf))
489 return DT_IMAGEIO_OK;
490
492
493#ifdef HAVE_OPENEXR
494 ret = dt_imageio_open_exr(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_rgbe(img, filename, buf);
500 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
501 return ret;
502
503 ret = dt_imageio_open_pfm(img, filename, buf);
504 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
505 return ret;
506
507#ifdef HAVE_LIBAVIF
508 ret = dt_imageio_open_avif(img, filename, buf);
509 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
510 return ret;
511#endif
512
513#ifdef HAVE_LIBHEIF
514 ret = dt_imageio_open_heif(img, filename, buf);
515 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
516 return ret;
517#endif
518
519 ret = dt_imageio_open_exotic(img, filename, buf);
520 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
521 return ret;
522
524}
525
526static const char *raster_formats[] = {
527 ".jpg", ".jpeg", ".png", ".tiff", ".tif", ".pgm", ".pbm", ".ppm",
528
529#ifdef HAVE_OPENJPEG
530 ".jp2", ".j2k",
531#endif
532
533#ifdef HAVE_WEBP
534 ".webp",
535#endif
536
537 NULL,
538};
539
540gboolean dt_imageio_is_raster(const char *filename)
541{
542 const char *c = filename + strlen(filename);
543 while(c > filename && *c != '.') c--;
544 if(*c != '.') return FALSE;
545
546 int i = 0;
547 while(raster_formats[i])
548 {
549 if(!strcasecmp(c, raster_formats[i])) return TRUE;
550 i++;
551 }
552
553 return FALSE;
554}
555
556// We include DNG here since it's handled by raw libs
557static const char *raw_formats[] = {
558 ".3fr", ".ari", ".arw", ".bay", ".bmq", ".cap", ".cine", ".cr2", ".crw", ".cs1", ".dc2",
559 ".dcr", ".dng", ".gpr", ".erf", ".fff", ".ia", ".iiq", ".k25", ".kc2", ".kdc", ".mdc",
560 ".mef", ".mos", ".mrw", ".nef", ".nrw", ".orf", ".ori", ".pef", ".pxn", ".qtk", ".raf",
561 ".raw", ".rdc", ".rw2", ".rwl", ".sr2", ".srf", ".srw", ".x3f",
562
563#ifdef HAVE_LIBRAW
564 ".cr3",
565#endif
566
567 NULL
568};
569
570
571gboolean dt_imageio_is_raw(const char *filename)
572{
573 const char *c = filename + strlen(filename);
574 while(c > filename && *c != '.') c--;
575 if(*c != '.') return FALSE;
576
577 int i = 0;
578 while(raw_formats[i])
579 {
580 if(!strcasecmp(c, raw_formats[i])) return TRUE;
581 i++;
582 }
583
584 return FALSE;
585}
586
587static const char *hdr_formats[] = {
588 ".pfm", ".hdr",
589
590#ifdef HAVE_OPENEXR
591 ".exr",
592#endif
593
594#ifdef HAVE_LIBAVIF
595 ".avif",
596#endif
597
598#ifdef HAVE_LIBHEIF
599 ".heif", ".heic", ".hif",
600#endif
601
602 NULL
603};
604
605
606int dt_imageio_is_hdr(const char *filename)
607{
608 const char *c = filename + strlen(filename);
609 while(c > filename && *c != '.') c--;
610 if(*c != '.') return FALSE;
611
612 int i = 0;
613 while(hdr_formats[i])
614 {
615 if(!strcasecmp(c, hdr_formats[i])) return TRUE;
616 i++;
617 }
618
619 return FALSE;
620}
621
622static gboolean _is_in_list(char *elem, char *list)
623{
624 // Search if elem is contained in the coma-separated list string
625 gboolean success = FALSE;
626 if(elem && list)
627 {
628 while(!IS_NULL_PTR(list) && !success)
629 {
630 success = !g_ascii_strncasecmp(list, elem, strlen(elem));
631 list = strtok(NULL, ",");
632 }
633 }
634
635 return success;
636}
637
638gboolean dt_imageio_is_handled_by_libraw(dt_image_t *img, const char *filename)
639{
640 // Allow users to define some extensions, makers and models that should be handled by Libraw
641 gboolean is_handled = FALSE;
642
643 char *ext = g_strrstr(filename, ".") + 1; // move the pointer after the extension dot
644 char *extensions = dt_conf_get_string("libraw/extensions");
645 char *makers = dt_conf_get_string("libraw/makers");
646 char *models = dt_conf_get_string("libraw/models");
647
648 is_handled |= _is_in_list(ext, strtok(extensions, ","));
649 is_handled |= _is_in_list(img->exif_maker, strtok(makers, ","));
650 is_handled |= _is_in_list(img->exif_model, strtok(models, ","));
651
652 dt_free(extensions);
653 dt_free(makers);
654 dt_free(models);
655
656 const char *iolib = (is_handled) ? "Libraw" : "Rawspeed";
657 dt_print(DT_DEBUG_IMAGEIO, "[image I/O] image `%s` from camera `%s` of maker `%s` loaded with %s\n", filename,
658 img->exif_model, img->exif_maker, iolib);
659
660 return is_handled;
661}
662
663// transparent read method to load ldr image to dt_raw_image_t with exif and so on.
665{
666 // if buf is NULL, don't proceed
667 if(IS_NULL_PTR(buf))
668 return DT_IMAGEIO_OK;
669
671
672 ret = dt_imageio_open_jpeg(img, filename, buf);
673 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
674 return ret;
675
676 ret = dt_imageio_open_tiff(img, filename, buf);
677 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
678 return ret;
679
680#ifdef HAVE_WEBP
681 ret = dt_imageio_open_webp(img, filename, buf);
682 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
683 return ret;
684#endif
685
686 ret = dt_imageio_open_png(img, filename, buf);
687 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
688 return ret;
689
690#ifdef HAVE_OPENJPEG
691 ret = dt_imageio_open_j2k(img, filename, buf);
692 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
693 return ret;
694#endif
695
696 ret = dt_imageio_open_pnm(img, filename, buf);
697 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
698 return ret;
699
700 ret = dt_imageio_open_exotic(img, filename, buf);
701 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
702 return ret;
703
705}
706
708{
709 // if buf is NULL, don't proceed
710 if(IS_NULL_PTR(buf))
711 return DT_IMAGEIO_OK;
712
714
715 /* check if user wants to force processing through Libraw */
716 const gboolean force_libraw = dt_imageio_is_handled_by_libraw(img, filename);
717
718 /* use rawspeed to load the raw */
719 if(!force_libraw)
720 {
721 ret = dt_imageio_open_rawspeed(img, filename, buf);
722 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
723 return ret;
724 }
725
726#ifdef HAVE_LIBRAW
727 /* fallback that tries to open file via LibRAW to support Canon CR3 */
728 ret = dt_imageio_open_libraw(img, filename, buf);
729 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
730 return ret;
731#endif
732
733 /* try Rawspeed again in case Libraw was forced but failed */
734 if(force_libraw)
735 {
736 ret = dt_imageio_open_rawspeed(img, filename, buf);
737 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
738 return ret;
739 }
740
741 /* fallback that tries to open file via GraphicsMagick */
742 ret = dt_imageio_open_exotic(img, filename, buf);
743 if(ret == DT_IMAGEIO_OK || ret == DT_IMAGEIO_CACHE_FULL)
744 return ret;
745
747}
748
749void dt_imageio_to_fractional(float in, uint32_t *num, uint32_t *den)
750{
751 if(!(in >= 0))
752 {
753 *num = *den = 0;
754 return;
755 }
756 *den = 1;
757 *num = (int)(in * *den + .5f);
758 while(fabsf(*num / (float)*den - in) > 0.001f)
759 {
760 *den *= 10;
761 *num = (int)(in * *den + .5f);
762 }
763}
764
765int dt_imageio_export(const int32_t imgid, const char *filename, dt_imageio_module_format_t *format,
766 dt_imageio_module_data_t *format_params, const gboolean high_quality,
767 const gboolean copy_metadata, const gboolean export_masks,
768 dt_colorspaces_color_profile_type_t icc_type, const gchar *icc_filename,
770 dt_imageio_module_data_t *storage_params, int num, int total, dt_export_metadata_t *metadata)
771{
772 if(strcmp(format->mime(format_params), "x-copy") == 0)
773 /* This is a just a copy, skip process and just export */
774 return format->write_image(format_params, filename, NULL, icc_type, icc_filename, NULL, 0, imgid, num, total, NULL,
775 export_masks);
776 else
777 {
778 const gboolean is_scaling =
779 dt_conf_is_equal("plugins/lighttable/export/resizing", "scaling");
780
781 return dt_imageio_export_with_flags(imgid, filename, format, format_params, FALSE, FALSE, TRUE, is_scaling,
782 FALSE, NULL, copy_metadata, export_masks, icc_type, icc_filename, icc_intent,
783 storage, storage_params, num, total, metadata, NULL);
784 }
785}
786
787gboolean _apply_style_before_export(dt_develop_t *dev, dt_imageio_module_data_t *format_params, const int32_t imgid)
788{
789 GList *style_items = dt_styles_get_item_list(format_params->style, TRUE, -1);
790 if(IS_NULL_PTR(style_items))
791 {
792 dt_control_log(_("cannot find the style '%s' to apply during export."), format_params->style);
793 return TRUE;
794 }
795
796 dt_ioppr_check_iop_order(dev, imgid, "dt_imageio_export_with_flags");
798 dt_ioppr_update_for_style_items(dev, style_items, TRUE);
799
800 for(GList *st_items = style_items; st_items; st_items = g_list_next(st_items))
801 {
802 dt_style_item_t *st_item = (dt_style_item_t *)st_items->data;
803 dt_styles_apply_style_item(dev, st_item);
804 }
805
806 g_list_free_full(style_items, dt_style_item_free);
807 style_items = NULL;
808
809 return FALSE;
810}
811
812void _print_export_debug(dt_dev_pixelpipe_t *pipe, dt_imageio_module_data_t *format_params, const gboolean use_style)
813{
815 {
816 fprintf(stderr,"[dt_imageio_export_with_flags] ");
817 if(use_style)
818 {
819 fprintf(stderr,"appending style `%s'\n", format_params->style);
820 }
821 else fprintf(stderr,"\n");
822 int cnt = 0;
823 for(GList *nodes = pipe->nodes; nodes; nodes = g_list_next(nodes))
824 {
826 if(piece->enabled)
827 {
828 cnt++;
829 fprintf(stderr," %s", piece->module->op);
830 }
831 }
832 fprintf(stderr," (%i)\n", cnt);
833 }
834}
835
836
837void _filter_pipeline(const char *filter, dt_dev_pixelpipe_t *pipe)
838{
839 // Warning: can only filter prior to or past to a certain module, but not both !!!
840 if(filter)
841 {
842 if(!strncmp(filter, "pre:", 4)) dt_dev_pixelpipe_disable_after(pipe, filter + 4);
843 if(!strncmp(filter, "post:", 5)) dt_dev_pixelpipe_disable_before(pipe, filter + 5);
844 }
845}
846
847
849 const dt_imageio_module_data_t *format_params, const gboolean is_scaling, double *scale,
850 int width, int height, int *processed_width, int *processed_height)
851{
852 const double image_ratio = (double)pipe->processed_width / (double)pipe->processed_height;
853
854 if(is_scaling)
855 {
856 double _num, _denum;
858 const double scale_factor = _num / _denum;
859 *scale = fmin(scale_factor, 1.);
860 *processed_height = (int)roundf(pipe->processed_height * (*scale));
861 *processed_width = (int)roundf(pipe->processed_width * (*scale));
862 return 0;
863 }
864
865 // if width and height are both 0, we use the full resolution of the image
866 if(width == 0 && height == 0)
867 {
868 // original resolution
869 *processed_width = pipe->processed_width;
870 *processed_height = pipe->processed_height;
871 *scale = 1.;
872 return 0;
873 }
874
875 if(width > 0 && height > 0)
876 {
877 // fixed width and height : fit within a bounding box
878 *processed_width = MIN(pipe->processed_width, width);
879 *processed_height = MIN(pipe->processed_height, height);
880 double scale_x = (double)*processed_width / (double)pipe->processed_width;
881 double scale_y = (double)*processed_height / (double)pipe->processed_height;
882 *scale = fmin(scale_x, scale_y);
883
884 // Note : we handle each case separately to avoid rounding errors
885 if(image_ratio > 1.0)
886 {
887 // landscape image, width is the limiting factor
888 *processed_width = MIN((int)roundf(pipe->processed_width * (*scale)), pipe->processed_width);
889 *processed_height = MIN((int)roundf(*processed_width / image_ratio), pipe->processed_height);
890 }
891 else if(image_ratio < 1.0)
892 {
893 // portrait image, height is the limiting factor
894 *processed_height = MIN((int)roundf(pipe->processed_height * (*scale)), pipe->processed_height);
895 *processed_width = MIN((int)roundf(*processed_height * image_ratio), pipe->processed_width);
896 }
897 else
898 {
899 // square image, both width and height are the limiting factors
900 *processed_width = MIN((int)roundf(pipe->processed_width * (*scale)), pipe->processed_width);
901 *processed_height = MIN((int)roundf(pipe->processed_height * (*scale)), pipe->processed_height);
902 }
903 return 0;
904 }
905
906 if(width > 0)
907 {
908 // fluid height, fixed width
909 *processed_width = MIN(pipe->processed_width, width);
910 *processed_height = (int)roundf(*processed_width / image_ratio);
911 }
912 else if(height > 0)
913 {
914 // fluid width, fixed height
915 *processed_height = MIN(pipe->processed_height, height);
916 *processed_width = (int)roundf(*processed_height * image_ratio);
917 }
918
919 double scale_x = (double)*processed_width / (double)pipe->processed_width;
920 double scale_y = (double)*processed_height / (double)pipe->processed_height;
921 *scale = fmin(scale_x, scale_y);
922
923 return 0;
924}
925
926
927void _clamp_float_to_uint8(const float *const inbuf, uint8_t *const outbuf, const size_t processed_width,
928 const size_t processed_height)
929{
931 for(size_t k = 0; k < processed_width * processed_height; k++)
933 outbuf[4 * k + c] = (uint8_t)CLAMPF(roundf(inbuf[4 * k + c] * 255.f), 0.f, 255.f);
934}
935
936
937void _swap_byteorder_float_to_uint8(const float *const restrict inbuf, uint8_t *const outbuf,
938 const size_t processed_width, const size_t processed_height)
939{
941 for(size_t k = 0; k < processed_width * processed_height; k++)
942 {
943 outbuf[4 * k + 0] = (uint8_t)CLAMPF(roundf(inbuf[4 * k + 2] * 255.f), 0.f, 255.f);
944 outbuf[4 * k + 1] = (uint8_t)CLAMPF(roundf(inbuf[4 * k + 1] * 255.f), 0.f, 255.f);
945 outbuf[4 * k + 2] = (uint8_t)CLAMPF(roundf(inbuf[4 * k + 0] * 255.f), 0.f, 255.f);
946 outbuf[4 * k + 3] = (uint8_t)CLAMPF(roundf(inbuf[4 * k + 3] * 255.f), 0.f, 255.f);
947 }
948}
949
950
951void _export_final_buffer_to_uint16(const float *const restrict inbuf, uint16_t *const outbuf,
952 const size_t processed_width, const size_t processed_height)
953{
955 for(size_t k = 0; k < processed_width * processed_height; k++)
957 outbuf[4 * k + c] = (uint16_t)CLAMP(roundf(inbuf[4 * k + c] * 65535.f), 0.f, 65535.f);
958}
959
960// internal function: to avoid exif blob reading + 8-bit byteorder flag + high-quality override
961int dt_imageio_export_with_flags(const int32_t imgid, const char *filename,
963 const gboolean ignore_exif, const gboolean display_byteorder,
964 const gboolean high_quality, gboolean is_scaling, const gboolean thumbnail_export,
965 const char *filter, const gboolean copy_metadata, const gboolean export_masks,
966 dt_colorspaces_color_profile_type_t icc_type, const gchar *icc_filename,
968 dt_imageio_module_data_t *storage_params, int num, int total,
969 dt_export_metadata_t *metadata, dt_atomic_int *shutdown)
970{
971 dt_times_t start;
972 dt_get_times(&start);
973
976 void *outbuf = NULL;
977
978 // Get the history, aka sequence of editing changes
979 dt_develop_t dev;
980 dt_dev_init(&dev, 0);
981 dt_dev_load_image(&dev, imgid);
983
984 // Apply styles on top of current history
985 const gboolean use_style = !thumbnail_export && format_params->style[0] != '\0';
986 // If a style is to be applied during export, add the iop params into the history
987 if(use_style && _apply_style_before_export(&dev, format_params, imgid))
988 goto error;
989
990 int width = MAX(format_params->max_width, 0);
991 int height = MAX(format_params->max_height, 0);
992 double scale = 1.;
993
994 // Get a pipeline, aka sequence of nodes
995 int res = 0;
997 if(thumbnail_export)
998 res = dt_dev_pixelpipe_init_thumbnail(&pipe, &dev);
999 else
1000 res = dt_dev_pixelpipe_init_export(&pipe, &dev, format->levels(format_params), export_masks);
1001
1002 if(!res) goto error;
1003
1004 pipe.shutdown_ext = shutdown;
1005
1007
1008 // Sync history with pipeline nodes
1009 // Update the ICC type if DT_COLORSPACE_NONE is passed
1010 dt_colorspaces_get_output_profile(imgid, &icc_type, icc_filename);
1011 dt_dev_pixelpipe_set_icc(&pipe, icc_type, icc_filename, icc_intent);
1012
1013 // Find out what input size we want
1015
1016 // Take a local copy of the input buffer so we can release the mipmap cache lock immediately
1017 dt_mipmap_cache_get(cache, &buf, imgid, size, DT_MIPMAP_BLOCKING, 'r');
1018
1019 if(IS_NULL_PTR(buf.buf) || buf.width == 0 || buf.height == 0)
1020 {
1022 goto error;
1023 }
1024
1025 const size_t buf_width = buf.width;
1026 const size_t buf_height = buf.height;
1028
1029 // Update size with actual input and resync nodes
1030 dt_dev_pixelpipe_set_input(&pipe, imgid, buf_width, buf_height, buf.iscale, size);
1032
1033 // Write debug info to stdout
1034 _print_export_debug(&pipe, format_params, use_style);
1035
1036 // Remove modules past or prior a certain one.
1037 // Useful for partial exports, for technical purposes (HDR merge)
1038 _filter_pipeline(filter, &pipe);
1039
1040 // This export path drives the pipe directly instead of through dt_dev_pixelpipe_change(), so
1041 // establish the buffer-format contract (and disable incompatible nodes) explicitly, after the
1042 // optional filtering changed the node set and before ROI planning / global hashing.
1044
1045 // Get theoritical final size of image, taking distortions and croppings AND borders into account,
1046 // considering full-size original input. Meaning we can enlarge or reduce the original image,
1047 // even taking full-res input.
1048 // Needs to be done after optional filtering, in case we filter out distortion modules
1050 &pipe.processed_height);
1051
1052 dt_show_times(&start, "[export] creating pixelpipe");
1053
1054 // Compute the actual final sizes that fit within the bounding box width*height
1055 // while preserving original image ratio
1056 int processed_width = 0;
1057 int processed_height = 0;
1058 _get_export_size(&dev, &pipe, format_params, is_scaling, &scale, width, height,
1059 &processed_width, &processed_height);
1060
1062 "[dt_imageio_export] (direct) image input %ix%i, turned to output %ix%i, will be exported to fit %ix%i "
1063 "--> final size is %ix%i\n",
1064 pipe.iwidth, pipe.iheight, pipe.processed_width, pipe.processed_height, width, height, processed_width,
1065 processed_height);
1066
1067
1068 const int bpp = format->bpp(format_params);
1069
1070 dt_iop_roi_t roi = (dt_iop_roi_t){ 0, 0, processed_width, processed_height, scale };
1071
1072 dt_get_times(&start);
1073 int err = dt_dev_pixelpipe_process(&pipe, roi);
1074 dt_show_times(&start, thumbnail_export ? "[dev_process_thumbnail] pixel pipeline processing thread"
1075 : "[dev_process_export] pixel pipeline processing thread");
1076
1077 if(dt_dev_backbuf_get_hash(&pipe.backbuf) == -1 || err)
1078 {
1079 dt_print(DT_DEBUG_IMAGEIO, "[dt_imageio_export_with_flags] no valid output buffer\n");
1080 goto error;
1081 }
1082
1083 struct dt_pixel_cache_entry_t *cache_entry;
1084 void *data = NULL;
1086 &cache_entry, pipe.devid, NULL))
1087 goto error;
1088
1089 /* `peek()` only exposes the published cacheline, it does not transfer ownership.
1090 * Thumbnail/export conversion borrows the final pipeline output while the pipe backbuffer keeps
1091 * its own keepalive reference. Take and release our own explicit cache ref here so we don't
1092 * accidentally consume the backbuffer keepalive and free the final output too early. */
1095
1096 // Down-conversion to low-precision formats:
1097 const size_t pixels = pipe.backbuf.width * pipe.backbuf.height * 4;
1098 if(bpp == 8)
1099 {
1101 sizeof(uint8_t) * pixels,
1102 0);
1103 if(outbuf && display_byteorder)
1105 else if(outbuf)
1107
1108 /* Thumbnail export stores the in-memory RGBA buffer straight into the mipmap cache.
1109 * The thumbnail pipeline does not maintain a meaningful alpha contract across all
1110 * modules, so random zero/garbage alpha values would make valid RGB thumbnails render
1111 * black in consumers that composite the mipmap buffer. Keep thumbnail alpha opaque at
1112 * the export boundary and leave RGB untouched. */
1113 if(outbuf && thumbnail_export)
1114 {
1115 uint8_t *thumbnail_buf = (uint8_t *)outbuf;
1117 for(size_t k = 0; k < pixels / 4; k++) thumbnail_buf[4 * k + 3] = UINT8_MAX;
1118 }
1119 }
1120 else if(bpp == 16)
1121 {
1123 sizeof(uint16_t) * pixels,
1124 0);
1125 if(outbuf)
1127
1128 if(outbuf && thumbnail_export)
1129 {
1130 uint16_t *thumbnail_buf = (uint16_t *)outbuf;
1132 for(size_t k = 0; k < pixels / 4; k++) thumbnail_buf[4 * k + 3] = UINT16_MAX;
1133 }
1134 }
1135 else // output float, no further harm done to the pixels :)
1136 {
1138 sizeof(float_t) * pixels,
1139 0);
1140 if(outbuf)
1141 memcpy(outbuf, data, sizeof(float_t) * pixels);
1142
1143 if(outbuf && thumbnail_export)
1144 {
1145 float *thumbnail_buf = (float *)outbuf;
1147 for(size_t k = 0; k < pixels / 4; k++) thumbnail_buf[4 * k + 3] = 1.0f;
1148 }
1149 }
1150
1151 // Decrease ref count on the cache entry and release the read lock
1154
1155 if(IS_NULL_PTR(outbuf)) goto error;
1156
1157 format_params->width = pipe.backbuf.width;
1158 format_params->height = pipe.backbuf.height;
1159
1160 // Exif data should be 65536 bytes max, but if original size is close to that,
1161 // adding new tags could make it go over that... so let it be and see what
1162 // happens when we write the image
1163 int length = 0;
1164 uint8_t *exif_profile = NULL;
1165
1166 if(!ignore_exif)
1167 {
1168 gboolean from_cache = TRUE;
1169 char pathname[PATH_MAX] = { 0 };
1170 dt_image_full_path(imgid, pathname, sizeof(pathname), &from_cache, __FUNCTION__);
1171 // find output color profile for this image:
1172 int sRGB = (icc_type == DT_COLORSPACE_SRGB);
1173 // last param is dng mode, it's false here
1174 length = dt_exif_read_blob(&exif_profile, pathname, imgid, sRGB, pipe.backbuf.width, pipe.backbuf.height, 0);
1175 }
1176
1177 // Finally: write image buffer to target container
1178 res = format->write_image(format_params, filename, outbuf, icc_type, icc_filename, exif_profile, length, imgid,
1179 num, total, &pipe, export_masks);
1180
1181 dt_free(exif_profile);
1182 if(res) goto error;
1183
1185 dt_dev_cleanup(&dev);
1186
1187 /* now write xmp into that container, if possible */
1188 if(copy_metadata && (format->flags(format_params) & FORMAT_FLAGS_SUPPORT_XMP))
1189 dt_exif_xmp_attach_export(imgid, filename, metadata);
1190
1191 if(!thumbnail_export && strcmp(format->mime(format_params), "memory")
1192 && !(format->flags(format_params) & FORMAT_FLAGS_NO_TMPFILE))
1193 {
1195 format_params, storage, storage_params);
1196 }
1197
1199 return 0; // success
1200
1201error:
1204 dt_dev_cleanup(&dev);
1205 return 1;
1206}
1207
1208
1209// fallback read method in case file could not be opened yet.
1210// use GraphicsMagick (if supported) to read exotic LDRs
1212 dt_mipmap_buffer_t *buf)
1213{
1214 // if buf is NULL, don't proceed
1215 if(IS_NULL_PTR(buf))
1216 return DT_IMAGEIO_OK;
1217
1219
1220#if defined(HAVE_GRAPHICSMAGICK)
1221 ret = dt_imageio_open_gm(img, filename, buf);
1222#elif defined(HAVE_IMAGEMAGICK)
1223 ret = dt_imageio_open_im(img, filename, buf);
1224#else
1226#endif
1227
1228 return ret;
1229}
1230
1231// =================================================
1232// combined reading
1233// =================================================
1234
1235dt_imageio_retval_t dt_imageio_open(dt_image_t *img, // non-const * means you hold a write lock!
1236 const char *filename, // full path
1237 dt_mipmap_buffer_t *buf)
1238{
1239 /* first of all, check if file exists, don't bother to test loading if not exists */
1240 if(!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
1241 return !DT_IMAGEIO_OK;
1242
1244 img->loader = LOADER_UNKNOWN;
1245
1246 // Start with extensions that are supposed to work.
1247 // If they don't, they are corrupted.
1248
1249 if(dt_imageio_is_raster(filename))
1250 {
1251 ret = dt_imageio_open_raster(img, filename, buf);
1252 if(ret != DT_IMAGEIO_OK)
1253 {
1254 fprintf(stderr, "[imageio] The file %s is corrupted. Abort.\n", filename);
1255 dt_control_log(_("The file `%s` is corrupted."), filename);
1256 return ret;
1257 }
1258 }
1259
1260 if(dt_imageio_is_raw(filename))
1261 {
1262 ret = dt_imageio_open_raw(img, filename, buf);
1263 if(ret != DT_IMAGEIO_OK)
1264 {
1265 fprintf(stderr, "[imageio] The file %s is corrupted. Abort.\n", filename);
1266 dt_control_log(_("The file `%s` is corrupted."), filename);
1267 return ret;
1268 }
1269 }
1270
1271 if(dt_imageio_is_hdr(filename))
1272 {
1273 ret = dt_imageio_open_hdr(img, filename, buf);
1274 if(ret != DT_IMAGEIO_OK)
1275 {
1276 fprintf(stderr, "[imageio] The file %s is corrupted. Abort.\n", filename);
1277 dt_control_log(_("The file `%s` is corrupted."), filename);
1278 return ret;
1279 }
1280 }
1281
1282 // fallback: bruteforce everything hoping for a miracle
1283 // Most likely, it's a format we never heard of.
1284 if(ret != DT_IMAGEIO_OK && ret != DT_IMAGEIO_CACHE_FULL)
1285 ret = dt_imageio_open_raster(img, filename, buf);
1286
1287 if(ret != DT_IMAGEIO_OK && ret != DT_IMAGEIO_CACHE_FULL)
1288 ret = dt_imageio_open_raw(img, filename, buf);
1289
1290 if(ret != DT_IMAGEIO_OK && ret != DT_IMAGEIO_CACHE_FULL)
1291 ret = dt_imageio_open_hdr(img, filename, buf);
1292
1293 // Final check and abort
1294 if(ret != DT_IMAGEIO_OK)
1295 {
1296 fprintf(stderr, "[imageio] The file %s is supported by none of our decoders.\n", filename);
1297 dt_control_log(_("The file `%s` is supported by none of our decoders."), filename);
1298 return ret;
1299 }
1300
1301 img->p_width = img->width - img->crop_x - img->crop_width;
1302 img->p_height = img->height - img->crop_y - img->crop_height;
1303
1304 // The codec has now populated img->dsc: finalize the buffer-derived type flags
1305 // (DT_IMAGE_MOSAIC + DT_IMAGE_BUFFER_RESOLVED). This is the single point where the
1306 // decoded descriptor is mapped to the persisted classification.
1308
1309 return ret;
1310}
1311
1312gboolean dt_imageio_lookup_makermodel(const char *maker, const char *model,
1313 char *mk, int mk_len, char *md, int md_len,
1314 char *al, int al_len)
1315{
1316 // At this stage, we can't tell which loader is used to open the image.
1317 gboolean found = dt_rawspeed_lookup_makermodel(maker, model,
1318 mk, mk_len,
1319 md, md_len,
1320 al, al_len);
1321 if(found == FALSE)
1322 {
1323 // Special handling for CR3 raw files via libraw
1325 mk, mk_len,
1326 md, md_len,
1327 al, al_len);
1328 }
1329 return found;
1330}
1331
1332// clang-format off
1333// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
1334// vim: shiftwidth=2 expandtab tabstop=2 cindent
1335// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
1336// 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:66
const char * extension(dt_imageio_module_data_t *data)
Definition avif.c:645
void cleanup(dt_imageio_module_format_t *self)
Definition avif.c:164
int width
Definition bilateral.h:1
int height
Definition bilateral.h:1
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_iop_color_intent_t
Definition colorspaces.h:63
dt_colorspaces_color_profile_type_t
Definition colorspaces.h:81
@ DT_COLORSPACE_SRGB
Definition colorspaces.h:84
static dt_aligned_pixel_t sRGB
const dt_colormatrix_t dt_aligned_pixel_t out
static const int row
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.
gchar * dt_conf_get_string(const char *name)
gboolean dt_conf_is_equal(const char *name, const char *value)
void dt_control_log(const char *msg,...)
Definition control.c:761
void dt_show_times(const dt_times_t *start, const char *prefix)
Definition darktable.c:1580
darktable_t darktable
Definition darktable.c:181
void dt_print(dt_debug_thread_t thread, const char *msg,...)
Definition darktable.c:1542
@ DT_DEBUG_IMAGEIO
Definition darktable.h:733
#define dt_pixelpipe_cache_alloc_align_cache(size, id)
Definition darktable.h:433
#define dt_free(ptr)
Definition darktable.h:456
static void dt_get_times(dt_times_t *t)
Definition darktable.h:921
#define dt_pixelpipe_cache_free_align(mem)
Definition darktable.h:453
#define __DT_CLONE_TARGETS__
Definition darktable.h:367
#define for_four_channels(_var,...)
Definition darktable.h:664
#define __OMP_PARALLEL_FOR__(...)
Definition darktable.h:258
#define PATH_MAX
Definition darktable.h:1062
#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
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:188
dt_dev_image_storage_t dt_dev_load_image(dt_develop_t *dev, const int32_t imgid)
Definition develop.c:887
void dt_dev_init(dt_develop_t *dev, int32_t gui_attached)
Definition develop.c:128
int dt_exif_xmp_attach_export(const int32_t imgid, const char *filename, void *metadata)
Definition exif.cc:4241
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:1702
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)
Definition exif.cc:1890
dt_image_orientation_t
Definition image.h:203
@ ORIENTATION_SWAP_XY
Definition image.h:208
@ ORIENTATION_FLIP_Y
Definition image.h:206
@ ORIENTATION_FLIP_X
Definition image.h:207
dt_imageio_retval_t
Definition image.h:78
@ DT_IMAGEIO_OK
Definition image.h:79
@ DT_IMAGEIO_CACHE_FULL
Definition image.h:82
@ DT_IMAGEIO_FILE_CORRUPTED
Definition image.h:81
dt_image_flags_t
Definition image.h:91
@ DT_IMAGE_RAW
Definition image.h:111
@ DT_IMAGE_HDR
Definition image.h:113
@ DT_IMAGE_LDR
Definition image.h:109
@ LOADER_UNKNOWN
Definition image.h:222
int bpp
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, gboolean is_scaling, 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)
Definition imageio.c:961
void _clamp_float_to_uint8(const float *const inbuf, uint8_t *const outbuf, const size_t processed_width, const size_t processed_height)
Definition imageio.c:927
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)
Definition imageio.c:439
int dt_imageio_is_hdr(const char *filename)
Definition imageio.c:606
static const gchar * _supported_raw[]
Definition imageio.c:130
static const char * raster_formats[]
Definition imageio.c:526
static const char * raw_formats[]
Definition imageio.c:557
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)
Definition imageio.c:1312
dt_imageio_retval_t dt_imageio_open(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *buf)
Definition imageio.c:1235
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 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)
Definition imageio.c:765
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)
Definition imageio.c:937
dt_imageio_retval_t dt_imageio_open_raster(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *buf)
Definition imageio.c:664
void _filter_pipeline(const char *filter, dt_dev_pixelpipe_t *pipe)
Definition imageio.c:837
static const gchar * _supported_ldr[]
Definition imageio.c:135
static const char * hdr_formats[]
Definition imageio.c:587
gboolean dt_imageio_is_raster(const char *filename)
Definition imageio.c:540
gboolean dt_imageio_has_mono_preview(const char *filename)
Definition imageio.c:364
void dt_imageio_to_fractional(float in, uint32_t *num, uint32_t *den)
Definition imageio.c:749
gboolean dt_imageio_is_handled_by_libraw(dt_image_t *img, const char *filename)
Definition imageio.c:638
gboolean _get_export_size(dt_develop_t *dev, dt_dev_pixelpipe_t *pipe, const dt_imageio_module_data_t *format_params, const gboolean is_scaling, double *scale, int width, int height, int *processed_width, int *processed_height)
Definition imageio.c:848
gboolean _apply_style_before_export(dt_develop_t *dev, dt_imageio_module_data_t *format_params, const int32_t imgid)
Definition imageio.c:787
dt_imageio_retval_t dt_imageio_open_hdr(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *buf)
Definition imageio.c:485
dt_imageio_retval_t dt_imageio_open_raw(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *buf)
Definition imageio.c:707
static gboolean _is_in_list(char *elem, char *list)
Definition imageio.c:622
gboolean dt_imageio_is_raw(const char *filename)
Definition imageio.c:571
dt_imageio_retval_t dt_imageio_open_exotic(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *buf)
Definition imageio.c:1211
dt_image_flags_t dt_imageio_get_type_from_extension(const char *extension)
Map Exiv2 preview MIME types to decoder format identifiers.
Definition imageio.c:180
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,...
Definition imageio.c:208
static const gchar * _supported_hdr[]
Definition imageio.c:139
void _print_export_debug(dt_dev_pixelpipe_t *pipe, dt_imageio_module_data_t *format_params, const gboolean use_style)
Definition imageio.c:812
__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)
Definition imageio.c:398
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)
Definition imageio.c:951
dt_imageio_retval_t dt_imageio_open_avif(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
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_gm(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *buf)
Definition imageio_gm.h:33
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_im(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *buf)
Definition imageio_im.h:34
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)
gchar * dt_imageio_resizing_factor_get_and_parsing(double *num, double *denum)
@ 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:44
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)
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)
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:1271
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:1747
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:2377
static const float x
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
#define CLAMPF(a, mn, mx)
Definition math.h:89
size_t size
Definition mipmap_cache.c:3
dt_colorspaces_color_profile_type_t color_space
Definition mipmap_cache.c:5
#define dt_mipmap_cache_get(A, B, C, D, E, F)
@ DT_MIPMAP_BLOCKING
#define dt_mipmap_cache_release(A, B)
dt_mipmap_size_t
@ DT_MIPMAP_FULL
void dt_dev_pixelpipe_cache_ref_count_entry(dt_dev_pixelpipe_cache_t *cache, gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Increase/Decrease the reference count on the cache line as to prevent LRU item removal....
gboolean dt_dev_pixelpipe_cache_peek(dt_dev_pixelpipe_cache_t *cache, const uint64_t hash, void **data, dt_pixel_cache_entry_t **entry, const int preferred_devid, void **cl_mem_output)
Non-owning lookup of an existing cache line.
void dt_dev_pixelpipe_cache_rdlock_entry(dt_dev_pixelpipe_cache_t *cache, gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Lock or release the read lock on the entry.
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)
#define DT_DEBUG_CONTROL_SIGNAL_RAISE(ctlsig, signal,...)
Definition signal.h:347
@ 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:261
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)
struct dt_dev_pixelpipe_cache_t * pixelpipe_cache
Definition darktable.h:790
struct dt_mipmap_cache_t * mipmap_cache
Definition darktable.h:776
struct dt_control_signal_t * signals
Definition darktable.h:774
int32_t unmuted
Definition darktable.h:760
struct dt_iop_module_t *void * data
dt_backbuf_t backbuf
dt_atomic_int * shutdown_ext
int32_t height
Definition image.h:315
dt_image_loader_t loader
Definition image.h:335
int32_t crop_height
Definition image.h:316
int32_t width
Definition image.h:315
char exif_maker[64]
Definition image.h:292
int32_t crop_y
Definition image.h:316
int32_t crop_x
Definition image.h:316
int32_t p_height
Definition image.h:315
int32_t p_width
Definition image.h:315
char exif_model[64]
Definition image.h:293
int32_t crop_width
Definition image.h:316
Region of interest passed through the pixelpipe.
Definition imageop.h:72
void * data
dt_dev_pixelpipe_cache_t * cache
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