Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
imageio_profile.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2010 Alex Chateau.
4 Copyright (C) 2010-2011 Henrik Andersson.
5 Copyright (C) 2010-2013, 2016-2017 johannes hanika.
6 Copyright (C) 2010 José Carlos García Sogo.
7 Copyright (C) 2010, 2012-2014 Pascal de Bruijn.
8 Copyright (C) 2011 Antony Dovgal.
9 Copyright (C) 2011 Bruce Guenter.
10 Copyright (C) 2011 Robert Bieber.
11 Copyright (C) 2011-2018 Tobias Ellinghaus.
12 Copyright (C) 2011, 2013-2014 Ulrich Pegelow.
13 Copyright (C) 2012 Christian Tellefsen.
14 Copyright (C) 2012 Jérémy Rosen.
15 Copyright (C) 2012 Richard Wonka.
16 Copyright (C) 2014-2016 Pedro Côrte-Real.
17 Copyright (C) 2014-2016 Roman Lebedev.
18 Copyright (C) 2015 parafin.
19 Copyright (C) 2016 Peter Budai.
20 Copyright (C) 2018-2019 Edgardo Hoszowski.
21 Copyright (C) 2019 Andreas Schneider.
22 Copyright (C) 2019-2020 Heiko Bauke.
23 Copyright (C) 2019 jakubfi.
24 Copyright (C) 2019 luzpaz.
25 Copyright (C) 2019 Matthias Vogelgesang.
26 Copyright (C) 2019-2022 Pascal Obry.
27 Copyright (C) 2019 Philippe Weyland.
28 Copyright (C) 2020 a.
29 Copyright (C) 2020, 2022-2026 Aurélien PIERRE.
30 Copyright (C) 2020 Dan Torop.
31 Copyright (C) 2020 Hubert Kowalski.
32 Copyright (C) 2020-2021 Miloš Komarčević.
33 Copyright (C) 2020-2021 Ralf Brown.
34 Copyright (C) 2021 Sakari Kapanen.
35 Copyright (C) 2022 Martin Bařinka.
36 Copyright (C) 2023 Alynx Zhou.
37 Copyright (C) 2023 Luca Zulberti.
38
39 darktable is free software: you can redistribute it and/or modify
40 it under the terms of the GNU General Public License as published by
41 the Free Software Foundation, either version 3 of the License, or
42 (at your option) any later version.
43
44 darktable is distributed in the hope that it will be useful,
45 but WITHOUT ANY WARRANTY; without even the implied warranty of
46 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47 GNU General Public License for more details.
48
49 You should have received a copy of the GNU General Public License
50 along with darktable. If not, see <http://www.gnu.org/licenses/>.
51*/
52
53/* Choosing an ICC profile FOR AN IMAGE, and reading the one the file carries.
54 *
55 * This is codec work, not colour-management work, which is why it lives here rather than with
56 * the LittleCMS2 code in common/colorspaces.c. Deciding that a JPEG's embedded profile beats
57 * its EXIF colorspace tag, or that a RAW should use its camera matrix, means knowing what each
58 * format stores and where -- and it was the only reason colorspaces.c included six imageio
59 * codec headers.
60 */
61
63
65#include "common/image.h"
66#include "caches/image_cache.h"
67#include "common/logging.h"
68#include "system/macros.h"
69#include "system/mem_alloc.h"
70
71#include <lcms2.h>
72#include <string.h>
73
74#ifdef HAVE_OPENJPEG
75#include "imageio/imageio_j2k.h" // conditional-ok: only the HAVE_OPENJPEG branch below reads J2K
76#endif
78#include "imageio/imageio_png.h"
80#ifdef HAVE_LIBAVIF
81#include "imageio/imageio_avif.h" // conditional-ok: only the HAVE_LIBAVIF branch below reads AVIF
82#endif
83#ifdef HAVE_LIBHEIF
84#include "imageio/imageio_heif.h" // conditional-ok: only the HAVE_LIBHEIF branch below reads HEIF
85#endif
86
88{
89 // Note : when the image has already been opened from cache on the current session,
90 // the embedded color profile is already inited and stored in img->profile.
91
92 // Untagged images should be assumed to be sRGB.
95
96 /* The `goto finish` below (invalid imgid -> no cache entry) skips every assignment to
97 * *output, including the sRGB fallback at the end, so the caller was left returning an
98 * indeterminate pointer that reached cmsCreateTransform. Establish the contract here:
99 * *output is always written. */
100 if(!IS_NULL_PTR(output)) *output = NULL;
101
102 // Fetch filename for extension retrieval
103 char filename[PATH_MAX] = { 0 };
104 gboolean from_cache = TRUE;
106
107 const gchar *cc = filename + strlen(filename);
108 for(; *cc != '.' && cc > filename; cc--);
109 gchar *ext = g_ascii_strdown(cc + 1, -1);
110
111 // Fetch actual image
112 dt_image_t *img = dt_image_cache_get(imgid, 'w');
113 if(IS_NULL_PTR(img)) goto finish;
114
115 // Image codecs doing their own colorspace detection should set this to TRUE
116 gboolean already_set = FALSE;
117
118 dt_print(DT_DEBUG_COLORPROFILE, "Color profile type for %s: \n", filename);
119
120 /* Both of these CREATE a profile. Calling them once in the condition and again in the
121 * body -- which is what this cascade did -- leaked the first one every time the branch
122 * was taken. Create once, here, and hand the same object out below. The second is built
123 * only if the first failed, which is what the else-if short-circuit used to express. */
124 cmsHPROFILE embedded_icc = NULL;
125 if(img->profile && img->profile_size > 0)
127
128 cmsHPROFILE exif_matrix = NULL;
131
133 {
134 // Fast path : we already extracted ICC before. ICC profile is already inside.
136 if(!IS_NULL_PTR(output))
137 {
138 *output = embedded_icc;
139 embedded_icc = NULL; // handed over
140 *new_profile = TRUE;
141 }
142 dt_print(DT_DEBUG_COLORPROFILE, "Embedded ICC profile (inline)\n");
143 }
144 else if(!IS_NULL_PTR(exif_matrix))
145 {
146 // DNG and others : matrix inside EXIF
148 if(!IS_NULL_PTR(output))
149 {
150 *output = exif_matrix;
151 exif_matrix = NULL; // handed over
152 *new_profile = TRUE;
153 }
154 dt_print(DT_DEBUG_COLORPROFILE, "Embedded EXIF matrix\n");
155 }
156 else if(dt_image_is_monochrome(img))
157 {
158 // Monochrome RAW - colorspace doesn't matter
160 if(!IS_NULL_PTR(output))
162 dt_print(DT_DEBUG_COLORPROFILE, "Monochrome RAW\n");
163 }
165 {
166 // Color RAW
168 if(!IS_NULL_PTR(output))
169 {
171 *new_profile = TRUE;
172 }
173 dt_print(DT_DEBUG_COLORPROFILE, "Typical RAW\n");
174 }
175 else if(img->flags & DT_IMAGE_4BAYER)
176 {
177 // 4Bayer images have been pre-converted to rec2020
179 if(!IS_NULL_PTR(output))
181 dt_print(DT_DEBUG_COLORPROFILE, "4Bayer RAW\n");
182 }
183 else if(img->colorspace == DT_IMAGE_COLORSPACE_SRGB)
184 {
185 // Images tagged explicitely with sRGB flag
187 dt_print(DT_DEBUG_COLORPROFILE, "Raster image tagged with sRGB\n");
188 }
190 {
191 // Images tagged explicitely with Adobe RGB flag
193 if(!IS_NULL_PTR(output))
195 dt_print(DT_DEBUG_COLORPROFILE, "Raster image tagged with Adobe RGB\n");
196 }
197 else if(!strcmp(ext, "pfm"))
198 {
199 // PFM have no embedded color profile nor ICC tag, we can't know the color space
200 // but we can assume the are linear since it's a floating point format
202 if(!IS_NULL_PTR(output))
204 dt_print(DT_DEBUG_COLORPROFILE, "PFM untagged image\n");
205 }
206 else
207 {
208 // Images that need codecs.
209
210 // First, extract embedded profiles from headers.
211 // Done only once : if everything goes well, the next time we access this image from cache,
212 // we will read img->profile directly (first branch here).
213
214 if(!strcmp(ext, "jpg") || !strcmp(ext, "jpeg"))
215 {
219 }
220#ifdef HAVE_OPENJPEG
221 else if(!strcmp(ext, "jp2") || !strcmp(ext, "j2k") || !strcmp(ext, "j2c") || !strcmp(ext, "jpc"))
222 {
224 }
225#endif
226 else if((!strcmp(ext, "tif") || !strcmp(ext, "tiff")))
227 {
229 }
230 else if(!strcmp(ext, "png"))
231 {
233 }
234#ifdef HAVE_LIBAVIF
235 else if(!strcmp(ext, "avif"))
236 {
239
240 // try the nclx box before falling back to any ICC profile
242
243 // If we found a basic RGB colorspace from private AVIF metadata,
244 // bypass generic LCMS2 reading below
246 }
247#endif
248#ifdef HAVE_LIBHEIF
249 else if(!strcmp(ext, "heif") || !strcmp(ext, "heic") || !strcmp(ext, "hif"))
250 {
253
254 // try the nclx box before falling back to any ICC profile
256
257 // If we found a basic RGB colorspace from private AVIF metadata,
258 // bypass generic LCMS2 reading below
260 }
261#endif
262
263 // Finally, read the prepared embedded profile
264 /* Same double-create as above: build it once. */
265 cmsHPROFILE extracted_icc = NULL;
266 if(!already_set && img->profile && img->profile_size > 0)
268
270 {
272 if(!IS_NULL_PTR(output))
273 {
274 *output = extracted_icc;
275 extracted_icc = NULL; // handed over
276 *new_profile = TRUE;
277 }
278 dt_print(DT_DEBUG_COLORPROFILE, "Embedded ICC (extracted)\n");
279 }
280 else if(already_set && img->profile && img->profile_size > 0)
281 {
282 // This happens when AVIF/HEIF found a basic color profile into CICP fields
283 if(!IS_NULL_PTR(output))
285 dt_print(DT_DEBUG_COLORPROFILE, "Embedded ICC (extracted)\n");
286 }
287
289 }
290
291 // Handle the fallback to sRGB space
295
296 /* Anything built above but not handed to the caller is ours to close. This is the
297 * `output == NULL` case -- a caller that wants only the resolved type -- and the branches
298 * where a later one in the cascade won. Deliberately before the label: the `goto finish`
299 * path runs before either is created. */
302
303finish:
305 dt_free(ext);
306 return color_profile;
307}
309 int32_t imgid,
311 cmsHPROFILE *output,
312 gboolean *new_profile)
313{
314 if(output) *output = NULL;
316
318 return dt_image_find_best_color_profile(imgid, output, new_profile);
319
323 return DT_COLORSPACE_NONE;
324
325 const dt_image_t *img = dt_image_cache_get(imgid, 'r');
326 if(IS_NULL_PTR(img)) return DT_COLORSPACE_NONE;
327
329 {
331 return dt_image_find_best_color_profile(imgid, output, new_profile);
332 }
333
334 gboolean have_embedded_icc = (img->profile && img->profile_size > 0);
336
338 {
339 // Try to extract embedded ICC into cache if needed.
340 gboolean dummy_new_profile = FALSE;
342 }
343
344 img = dt_image_cache_get(imgid, 'r');
345 if(IS_NULL_PTR(img)) return DT_COLORSPACE_NONE;
346
347 cmsHPROFILE profile = NULL;
349
351 {
352 if(img->profile && img->profile_size > 0)
353 {
355 if(profile)
356 {
358 goto finish;
359 }
360 }
362 }
363
365 {
366 if(!isnan(img->d65_color_matrix[0]))
367 {
369 if(profile)
370 {
372 goto finish;
373 }
374 }
376 }
377
379 {
380 if(!isnan(img->adobe_XYZ_to_CAM[0][0]))
381 {
383 if(profile)
384 {
386 goto finish;
387 }
388 }
389 }
390
392
393finish:
395
396 if(profile)
397 {
398 if(output)
399 {
400 *output = profile;
402 }
403 else
404 {
406 }
407 }
408
409 return type;
410}
412{
413 cmsHPROFILE output = NULL;
415 return output;
416}
417/* Build (or reuse) the parsed profile for an image's embedded ICC, and give it to the image.
418 *
419 * It used to be appended to dt_colorspaces_t.profiles instead. That list is built once by
420 * dt_colorspaces_init() and then read from ~23 places without any lock, which is only safe
421 * while it is immutable -- and this function made it mutable, from export jobs that run in
422 * parallel. It also grew the list for the lifetime of the session (one entry per exported
423 * image), and leaked the container outright whenever the profile was not newly created,
424 * because only the new_profile branch ever registered it.
425 *
426 * An embedded profile is a property of one image, so the image owns it: stored under the image
427 * cache entry's own lock, freed when the image is evicted, and reused on the next export of the
428 * same image instead of built again.
429 */
432{
433 gboolean new_profile = FALSE;
435
436 // -1 in all indices ensures it is hidden from the GUI: this profile belongs to one image and
437 // has no place in any combo box.
438 /* new_profile carries ownership: several branches of dt_image_find_best_color_profile()
439 * return a profile borrowed from the application-wide list rather than a fresh one, and a
440 * container that closed such a profile would double-free it. */
443 {
445 return NULL;
446 }
447
448 if(profile && new_profile)
449 {
450 char *lang = getenv("LANG");
451 if(IS_NULL_PTR(lang)) lang = "en_US";
452 dt_colorspaces_get_profile_name(profile, lang, lang + 3, container->name, sizeof(container->name));
453 }
454
455 dt_image_t *img = dt_image_cache_get(imgid, 'w');
456 if(IS_NULL_PTR(img))
457 {
458 // No image to hand it to. Better to leak nothing and let the caller fall back than to put
459 // it back on the global list.
461 return NULL;
462 }
463
464 const dt_colorspaces_color_profile_t *result;
465 if(img->embedded_profile)
466 {
467 // Another thread got here first while we were parsing. Theirs is as good as ours, and it is
468 // the one every other borrower already holds.
470 result = img->embedded_profile;
471 }
472 else
473 {
475 result = container;
476 }
477 // Nothing persistent changed: this is a cached derivation of bytes already in the image.
479
480 return result;
481}
483 const int32_t imgid,
485 const char *camera_makermodel,
487{
488 if(resolved) *resolved = DT_COLORSPACE_NONE;
489
491 cmsHPROFILE profile = NULL;
492 gboolean owns = FALSE;
493
494 /* The three built-from-the-camera types. Each falls over to the embedded-ICC branch when
495 * this camera is not in the corresponding table -- which is what "matrix not found" means
496 * to a user, and why the fallthrough below is a chain rather than a switch. */
498 {
499 profile = camera_makermodel ? dt_colorspaces_create_darktable_profile(camera_makermodel) : NULL;
501 else owns = TRUE;
502 }
504 {
505 profile = camera_makermodel ? dt_colorspaces_create_vendor_profile(camera_makermodel) : NULL;
507 else owns = TRUE;
508 }
510 {
511 profile = camera_makermodel ? dt_colorspaces_create_alternate_profile(camera_makermodel) : NULL;
513 else owns = TRUE;
514 }
515
519 {
520 gboolean new_profile = FALSE;
523 }
524
525 if(IS_NULL_PTR(profile)) return NULL;
526
529 {
530 /* Do not leak the handle just because the container allocation failed: only WE know at
531 * this point whether it was created here or borrowed from the application list. */
533 return NULL;
534 }
535
536 if(resolved) *resolved = type;
537 return container;
538}
539
554
557 const char *over_filename)
558{
559
561
562 // Special case if output is undefined or uses private image color spaces : use the embedded profile if any.
563 // We need to read it from the original image and create it on-the-fly.
564 // Note: we don't allow export with deprecated vendor/enhanced/alternate matrices
569 {
571 }
572 else
573 {
574 // return a pointer to the profile specified in export.
575 // we have that in here to get rid of the if() check in all places calling this function.
577 }
578
579 // if all else fails -> fall back to sRGB
580 if(IS_NULL_PTR(p))
581 {
584 }
585
586 return p;
587}
589{
590 switch(cicp->color_primaries)
591 {
592 /* Give up immediately if unspecified */
594 if(cicp->transfer_characteristics == DT_CICP_TRANSFER_CHARACTERISTICS_UNSPECIFIED
595 && cicp->matrix_coefficients == DT_CICP_MATRIX_COEFFICIENTS_UNSPECIFIED)
596 return DT_COLORSPACE_NONE;
597 break; /* unspecified */
598
599 /* REC709 */
601
602 switch(cicp->transfer_characteristics)
603 {
604 /* SRGB */
606
607 switch(cicp->matrix_coefficients)
608 {
609 case DT_CICP_MATRIX_COEFFICIENTS_IDENTITY: /* support RGB (4:4:4 or lossless) */
612 case DT_CICP_MATRIX_COEFFICIENTS_REC601: /* support equivalents just in case of mistagging */
613 case DT_CICP_MATRIX_COEFFICIENTS_CHROMA_DERIVED_NCL: /* support incorrectly tagged files */
615 return DT_COLORSPACE_SRGB;
616 default:
617 break;
618 }
619
620 break; /* SRGB */
621
622 /* REC709 */
624 case DT_CICP_TRANSFER_CHARACTERISTICS_REC601: /* support equivalents just in case of mistagging */
625 case DT_CICP_TRANSFER_CHARACTERISTICS_REC2020_10B: /* support equivalents just in case of mistagging */
626 case DT_CICP_TRANSFER_CHARACTERISTICS_REC2020_12B: /* support equivalents just in case of mistagging */
627
628 switch(cicp->matrix_coefficients)
629 {
630 case DT_CICP_MATRIX_COEFFICIENTS_IDENTITY: /* support RGB (4:4:4 or lossless) */
635 default:
636 break;
637 }
638
639 break; /* REC709 */
640
641 /* LINEAR REC709 */
643
644 switch(cicp->matrix_coefficients)
645 {
646 case DT_CICP_MATRIX_COEFFICIENTS_IDENTITY: /* support RGB (4:4:4 or lossless) */
651 default:
652 break;
653 }
654
655 break; /* LINEAR REC709 */
656
657 default:
658 break;
659 }
660
661 break; /* REC709 */
662
663 /* REC2020 */
665
666 switch(cicp->transfer_characteristics)
667 {
668 /* LINEAR REC2020 */
670
671 switch(cicp->matrix_coefficients)
672 {
673 case DT_CICP_MATRIX_COEFFICIENTS_IDENTITY: /* support RGB (4:4:4 or lossless) */
678 default:
679 break;
680 }
681
682 break; /* LINEAR REC2020 */
683
684 /* PQ REC2020 */
686
687 switch(cicp->matrix_coefficients)
688 {
689 case DT_CICP_MATRIX_COEFFICIENTS_IDENTITY: /* support RGB (4:4:4 or lossless) */
694 default:
695 break;
696 }
697
698 break; /* PQ REC2020 */
699
700 /* HLG REC2020 */
702
703 switch(cicp->matrix_coefficients)
704 {
705 case DT_CICP_MATRIX_COEFFICIENTS_IDENTITY: /* support RGB (4:4:4 or lossless) */
710 default:
711 break;
712 }
713
714 break; /* HLG REC2020 */
715
716 default:
717 break;
718 }
719
720 break; /* REC2020 */
721
722 /* P3 */
724
725 switch(cicp->transfer_characteristics)
726 {
727 /* PQ P3 */
729
730 switch(cicp->matrix_coefficients)
731 {
732 case DT_CICP_MATRIX_COEFFICIENTS_IDENTITY: /* support RGB (4:4:4 or lossless) */
738 return DT_COLORSPACE_PQ_P3;
739 default:
740 break;
741 }
742
743 break; /* PQ P3 */
744
745 /* HLG P3 */
747
748 switch(cicp->matrix_coefficients)
749 {
750 case DT_CICP_MATRIX_COEFFICIENTS_IDENTITY: /* support RGB (4:4:4 or lossless) */
757 default:
758 break;
759 }
760
761 break; /* HLG P3 */
762
763 /* Display P3 */
765
766 switch(cicp->matrix_coefficients)
767 {
768 case DT_CICP_MATRIX_COEFFICIENTS_IDENTITY: /* support RGB (4:4:4 or lossless) */
775 default:
776 break;
777 }
778
779 break; /* Display P3 */
780
781 default:
782 break;
783 }
784
785 break; /* P3 */
786
787 /* XYZ */
789
790 switch(cicp->transfer_characteristics)
791 {
792 /* LINEAR XYZ */
794
795 switch(cicp->matrix_coefficients)
796 {
799 return DT_COLORSPACE_XYZ;
800 default:
801 break;
802 }
803
804 break; /* LINEAR XYZ */
805
806 default:
807 break;
808 }
809
810 break; /* XYZ */
811
812 default:
813 break;
814 }
815
817 dt_print(DT_DEBUG_IMAGEIO, "[colorin] unsupported CICP color profile for `%s': %d/%d/%d\n", filename,
818 cicp->color_primaries, cicp->transfer_characteristics, cicp->matrix_coefficients);
819
820 return DT_COLORSPACE_NONE;
821}
822
823// clang-format off
824// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
825// vim: shiftwidth=2 expandtab tabstop=2 cindent
826// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
827// clang-format on
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
uint32_t container(dt_lib_module_t *self)
cmsHPROFILE dt_colorspaces_create_xyzimatrix_profile(float mat[3][3])
Create a linear-gamma RGB profile from an XYZ->camera matrix.
void dt_colorspaces_free_image_profile(struct dt_colorspaces_color_profile_t *profile)
Release a profile container owned by an image, closing the LCMS2 handle inside it if and only if the ...
struct dt_colorspaces_color_profile_t * dt_colorspaces_new_image_profile(dt_colorspaces_color_profile_type_t type, cmsHPROFILE profile, gboolean owns_profile)
Build a container for a profile that belongs to ONE image rather than to the application.
const dt_colorspaces_color_profile_t * dt_colorspaces_get_profile(dt_colorspaces_color_profile_type_t type, const char *filename, dt_colorspaces_profile_role_t role)
Resolve a profile identity to its registered entry.
cmsHPROFILE dt_colorspaces_create_vendor_profile(const char *makermodel)
Create an ICC virtual profile from the shipped vendor matrices.
cmsHPROFILE dt_colorspaces_create_darktable_profile(const char *makermodel)
Create an ICC virtual profile from the shipped profiled colour matrices.
void dt_colorspaces_cleanup_profile(cmsHPROFILE p)
Close a profile created by any of the dt_colorspaces_create_* / dt_colorspaces_get_rgb_profile_from_m...
cmsHPROFILE dt_colorspaces_get_rgb_profile_from_mem(uint8_t *data, uint32_t size)
Open an lcms2 RGB profile from an in-memory ICC blob.
void dt_colorspaces_get_profile_name(cmsHPROFILE p, const char *language, const char *country, char *name, size_t len)
Read a profile's description tag into name, handling character encodings.
cmsHPROFILE dt_colorspaces_create_alternate_profile(const char *makermodel)
Create an ICC virtual profile from the shipped alternate matrices.
The colour-profile module's API: which profiles exist, and how to apply one.
gboolean dt_image_is_matrix_correction_supported(const dt_image_t *img)
gboolean dt_image_is_monochrome(const 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.
@ DT_IMAGE_COLORSPACE_ADOBE_RGB
Definition image.h:193
@ DT_IMAGE_COLORSPACE_SRGB
Definition image.h:192
@ DT_IMAGE_4BAYER
Definition image.h:139
void dt_image_cache_write_release(dt_image_t *img, dt_image_cache_write_mode_t mode)
dt_image_t * dt_image_cache_get(const int32_t imgid, char mode)
void dt_image_cache_read_release(const dt_image_t *img)
@ DT_IMAGE_CACHE_RELAXED
Definition image_cache.h:50
int dt_imageio_avif_read_profile(const char *filename, uint8_t **out, dt_colorspaces_cicp_t *cicp)
int dt_imageio_heif_read_profile(const char *filename, uint8_t **out, dt_colorspaces_cicp_t *cicp)
int dt_imageio_j2k_read_profile(const char *filename, uint8_t **out)
int dt_imageio_jpeg_read_profile(dt_imageio_jpeg_t *jpg, uint8_t **out)
int dt_imageio_jpeg_read_header(const char *filename, dt_imageio_jpeg_t *jpg)
int dt_imageio_png_read_profile(const char *filename, uint8_t **out)
static const dt_colorspaces_color_profile_t * _build_embedded_profile(const int32_t imgid, dt_colorspaces_color_profile_type_t *type)
dt_colorspaces_color_profile_type_t dt_colorspaces_get_input_profile_from_image(int32_t imgid, dt_colorspaces_color_profile_type_t requested, cmsHPROFILE *output, gboolean *new_profile)
Resolve an embedded/matrix input profile for a given image, honoring the requested type when possible...
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)
const cmsHPROFILE dt_colorspaces_get_embedded_profile(const int32_t imgid, dt_colorspaces_color_profile_type_t *type, gboolean *new_profile)
struct dt_colorspaces_color_profile_t * dt_image_get_input_profile(const int32_t imgid, const dt_colorspaces_color_profile_type_t requested, const char *camera_makermodel, dt_colorspaces_color_profile_type_t *resolved)
Resolve an image's own input profile into an opaque container, whatever kind it is.
struct dt_colorspaces_color_profile_t * dt_image_get_embedded_output_profile(const int32_t imgid, dt_colorspaces_color_profile_type_t *type)
Resolve the ICC profile embedded in an image's own file, into an opaque container.
dt_colorspaces_color_profile_type_t dt_image_find_best_color_profile(int32_t imgid, cmsHPROFILE *output, gboolean *new_profile)
Best effort to find a suitable (input) color profile for a given image, using embedded ICC or EXIF wh...
dt_colorspaces_color_profile_type_t dt_colorspaces_cicp_to_type(const dt_colorspaces_cicp_t *cicp, const char *filename)
int dt_imageio_tiff_read_profile(const char *filename, uint8_t **out)
_lib_location_type_t type
Definition location.c:1
@ DT_DEBUG_COLORPROFILE
Definition logging.h:65
@ DT_DEBUG_IMAGEIO
Definition logging.h:54
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
#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:65
#define dt_free(ptr)
Definition mem_alloc.h:97
#define PATH_MAX
Definition paths.h:45
dt_colorspaces_color_profile_type_t
@ DT_COLORSPACE_ADOBERGB
@ DT_COLORSPACE_EMBEDDED_MATRIX
@ DT_COLORSPACE_EMBEDDED_ICC
Image-derived profiles: enum 9..14, NOT registered in the list.
@ DT_COLORSPACE_SRGB
sRGB – registered TWICE, and the two entries are not interchangeable.
@ DT_COLORSPACE_REC709
@ DT_COLORSPACE_HLG_P3
@ DT_COLORSPACE_PQ_P3
@ DT_COLORSPACE_PQ_REC2020
@ DT_COLORSPACE_NONE
No profile / "take it from the image settings". Never matches a list entry.
@ DT_COLORSPACE_HLG_REC2020
@ DT_COLORSPACE_ENHANCED_MATRIX
@ DT_COLORSPACE_LIN_REC2020
@ DT_COLORSPACE_DISPLAY_P3
@ DT_COLORSPACE_STANDARD_MATRIX
@ DT_COLORSPACE_XYZ
@ DT_COLORSPACE_VENDOR_MATRIX
@ DT_COLORSPACE_LIN_REC709
@ DT_COLORSPACE_ALTERNATE_MATRIX
@ DT_PROFILE_ROLE_OUTPUT
Listed in the output/export-profile combo (colorout, export).
@ DT_PROFILE_ROLE_INPUT
Listed in the input-profile combo (colorin).
@ DT_PROFILE_ROLE_MONITOR
Eligible for the monitor-profile menu.
@ DT_CICP_TRANSFER_CHARACTERISTICS_UNSPECIFIED
@ DT_CICP_TRANSFER_CHARACTERISTICS_LINEAR
@ DT_CICP_TRANSFER_CHARACTERISTICS_HLG
@ DT_CICP_TRANSFER_CHARACTERISTICS_REC2020_12B
@ DT_CICP_TRANSFER_CHARACTERISTICS_REC709
@ DT_CICP_TRANSFER_CHARACTERISTICS_PQ
@ DT_CICP_TRANSFER_CHARACTERISTICS_REC2020_10B
@ DT_CICP_TRANSFER_CHARACTERISTICS_REC601
@ DT_CICP_TRANSFER_CHARACTERISTICS_SRGB
@ DT_CICP_COLOR_PRIMARIES_REC2020
@ DT_CICP_COLOR_PRIMARIES_UNSPECIFIED
@ DT_CICP_COLOR_PRIMARIES_P3
@ DT_CICP_COLOR_PRIMARIES_REC709
@ DT_CICP_COLOR_PRIMARIES_XYZ
@ DT_CICP_MATRIX_COEFFICIENTS_REC601
@ DT_CICP_MATRIX_COEFFICIENTS_REC2020_NCL
@ DT_CICP_MATRIX_COEFFICIENTS_UNSPECIFIED
@ DT_CICP_MATRIX_COEFFICIENTS_IDENTITY
@ DT_CICP_MATRIX_COEFFICIENTS_SYCC
@ DT_CICP_MATRIX_COEFFICIENTS_REC709
@ DT_CICP_MATRIX_COEFFICIENTS_CHROMA_DERIVED_NCL
The three ITU-T H.273 code points that describe a colour space without an ICC profile.
One registered profile: its identity, its LCMS handle, and where it sits in each combo box.
cmsHPROFILE profile
the actual profile; NULL for the three category entries
char filename[DT_IOP_COLOR_ICC_LEN]
icc file name (absolute; compare with dt_colorspaces_is_profile_equal())
int32_t flags
Definition image.h:377
uint32_t profile_size
Definition image.h:399
float d65_color_matrix[9]
Definition image.h:397
dt_image_colorspace_t colorspace
Definition image.h:405
float adobe_XYZ_to_CAM[4][3]
Definition image.h:425
struct dt_colorspaces_color_profile_t * embedded_profile
Definition image.h:404
uint8_t * profile
Definition image.h:398