Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
colorspaces.h File Reference

The colour-profile module's API: which profiles exist, and how to apply one. More...

#include "colorprofiles/profile_types.h"
#include "math/matrices.h"
#include "system/simd.h"
#include <glib.h>
#include <lcms2.h>
#include <pthread.h>
#include <stdint.h>
+ Include dependency graph for colorspaces.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  dt_colorspaces_t
 The module's private state. Declared here for the module's own .c files only. More...
 
struct  dt_colorspaces_color_profile_t
 One registered profile: its identity, its LCMS handle, and where it sits in each combo box. More...
 
struct  dt_colorspaces_cicp_t
 The three ITU-T H.273 code points that describe a colour space without an ICC profile. More...
 
struct  dt_colorprofile_desc_t
 A profile's public identity: what the GUI displays and stores, and nothing else. More...
 
struct  dt_colorprofiles_settings_t
 Consistent snapshot of the display and soft-proofing settings. More...
 

Macros

#define LUT_SAMPLES   0x10000
 Max samples in a tone-curve LUT built from a profile (65536).
 
#define TYPE_XYZA_FLT   (FLOAT_SH(1)|COLORSPACE_SH(PT_XYZ)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4))
 lcms2 pixel format for float XYZ + one extra channel.
 

Typedefs

typedef struct _GtkWidget GtkWidget
 GtkWidget, opaque, spelled exactly as GTK spells it.
 
typedef struct dt_colorspaces_t dt_colorspaces_t
 The module's private state. Declared here for the module's own .c files only.
 
typedef struct dt_colorspaces_color_profile_t dt_colorspaces_color_profile_t
 One registered profile: its identity, its LCMS handle, and where it sits in each combo box.
 
typedef struct dt_colorspaces_cicp_t dt_colorspaces_cicp_t
 The three ITU-T H.273 code points that describe a colour space without an ICC profile.
 
typedef struct dt_colorprofile_desc_t dt_colorprofile_desc_t
 A profile's public identity: what the GUI displays and stores, and nothing else.
 
typedef struct dt_colorprofiles_settings_t dt_colorprofiles_settings_t
 Consistent snapshot of the display and soft-proofing settings.
 
typedef void(* dt_colorspaces_profile_changed_handler_t) (void)
 Callback invoked after the monitor profile actually changed.
 

Functions

int mat3inv_float (float *const dst, const float *const src)
 Invert a 3x3 matrix stored row-major as 9 contiguous floats.
 
int mat3inv (float *const dst, const float *const src)
 Thin alias of mat3inv_float(), same contract.
 
void dt_colorprofiles_init (void)
 Build the module's single instance: register every built-in profile, load the color/in and color/out directories under both userconfig and datadir, restore the display/soft-proof settings from conf, and build the four prepared display transforms.
 
void dt_colorprofiles_cleanup (void)
 Persist the display/soft-proof settings to conf, flush the derived matrix/LUT memo, delete the prepared transforms, close every profile and free the instance.
 
void dt_colorspaces_lock_profile (const dt_colorspaces_color_profile_t *const profile)
 
void dt_colorspaces_unlock_profile (const dt_colorspaces_color_profile_t *const profile)
 
size_t dt_colorspaces_enumerate_profiles (const dt_colorspaces_profile_role_t role, dt_colorprofile_desc_t **out)
 Ordered snapshot of every profile registered for one role.
 
int dt_colorspaces_profile_index (const dt_colorspaces_profile_role_t role, const dt_colorspaces_color_profile_type_t type, const char *const filename)
 Combo position of (type, filename) within direction.
 
gboolean dt_colorspaces_profile_at (const dt_colorspaces_profile_role_t role, const int index, dt_colorprofile_desc_t *const out)
 Identity of the profile at index within direction.
 
gboolean dt_colorspaces_profile_exists (const dt_colorspaces_profile_role_t role, const dt_colorspaces_color_profile_type_t type, const char *const filename)
 Is this identity registered for this direction?
 
cmsHPROFILE dt_colorspaces_create_xyzimatrix_profile (float cam_xyz[3][3])
 Create a linear-gamma RGB profile from an XYZ->camera matrix.
 
cmsHPROFILE dt_colorspaces_create_darktable_profile (const char *makermodel)
 Create an ICC virtual profile from the shipped profiled colour matrices.
 
cmsHPROFILE dt_colorspaces_create_vendor_profile (const char *makermodel)
 Create an ICC virtual profile from the shipped vendor matrices.
 
cmsHPROFILE dt_colorspaces_create_alternate_profile (const char *makermodel)
 Create an ICC virtual profile from the shipped alternate matrices.
 
void dt_colorspaces_transform_rgba_float_row (const cmsHTRANSFORM transform, const float *in, float *out, const int width)
 Run a caller-owned LCMS transform over one row of RGBA float pixels.
 
void dt_colorspaces_transform_rgba_float_image (const cmsHTRANSFORM transform, const float *image_in, float *image_out, const int width, const int height)
 Run a caller-owned LCMS transform over a whole RGBA float image, one OpenMP task per row.
 
void dt_colorprofiles_xyz_to_display (const dt_aligned_pixel_t XYZ, dt_aligned_pixel_t RGB)
 Convert one D50 XYZ pixel to display RGB.
 
gboolean dt_colorprofiles_rgba8_to_display_bgra8 (const uint8_t *const in, uint8_t *const out, const int width, const int height, const dt_colorspaces_color_profile_type_t src_space)
 Convert a whole 8-bit plane from src_space to the display profile: packed RGBA8 in, BGRA8 out (cairo byte order).
 
gboolean dt_colorprofiles_bgra8_to_adobergb_rgba8 (const uint8_t *const in, uint8_t *const out, const int width, const int height, const dt_colorspaces_color_profile_type_t src_space)
 The storage leg: convert an 8-bit plane from src_space (BGRA8) to AdobeRGB (RGBA8), for thumbnails written to the mipmap cache.
 
gboolean dt_colorprofiles_srgb_to_display_strided (uint8_t *const pixels, const int width, const int height, const int rowstride, const int n_channels, const gboolean has_alpha)
 Convert a strided, packed-RGB(A) 8-bit buffer (GdkPixbuf shape) from sRGB to the display profile, in place.
 
void dt_colorprofiles_get_settings (dt_colorprofiles_settings_t *const out)
 Copy the current settings into caller-provided storage, under one lock.
 
gboolean dt_colorprofiles_set_display_profile_choice (const dt_colorspaces_color_profile_type_t type, const char *const filename)
 Set the monitor profile identity and rebuild the four prepared transforms.
 
gboolean dt_colorprofiles_set_display_intent (const dt_iop_color_intent_t intent)
 Set the rendering intent used towards the monitor, rebuilding the four prepared transforms.
 
gboolean dt_colorprofiles_set_softproof_profile_choice (const dt_colorspaces_color_profile_type_t type, const char *const filename)
 Set the soft-proofing target identity.
 
gboolean dt_colorprofiles_set_softproof_intent (const dt_iop_color_intent_t intent)
 Set the rendering intent used towards the soft-proofing target.
 
gboolean dt_colorprofiles_set_mode (const dt_colorspaces_color_mode_t mode)
 Set the proofing mode outright.
 
dt_colorspaces_color_mode_t dt_colorprofiles_toggle_mode (const dt_colorspaces_color_mode_t mode)
 Turn mode on, or back to DT_PROFILE_NORMAL if it is already the current mode, as one locked read-modify-write.
 
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_cleanup_profile (cmsHPROFILE p)
 Close a profile created by any of the dt_colorspaces_create_* / dt_colorspaces_get_rgb_profile_from_mem functions.
 
int dt_colorspaces_get_matrix_from_input_profile (cmsHPROFILE prof, dt_colormatrix_t matrix, float *lutr, float *lutg, float *lutb, const int lutsize)
 Extract the profile->XYZ matrix and the per-channel tone curves from an INPUT profile.
 
int dt_colorspaces_get_matrix_from_output_profile (cmsHPROFILE prof, dt_colormatrix_t matrix, float *lutr, float *lutg, float *lutb, const int lutsize)
 Extract the XYZ->profile matrix and the inverse tone curves from an OUTPUT profile.
 
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.
 
const char * dt_colorspaces_get_name (dt_colorspaces_color_profile_type_t type, const char *filename)
 Printable name for a profile identity, without touching the profile list.
 
void rgb2hsl (const dt_aligned_pixel_t rgb, float *h, float *s, float *l)
 Convert RGB to HSL. Common helper used by iop modules.
 
void hsl2rgb (dt_aligned_pixel_t rgb, float h, float s, float l)
 Convert HSL back to RGB. Common helper used by iop modules.
 
struct dt_colorspaces_color_profile_tdt_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.
 
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 container owns it.
 
void dt_colorspaces_set_profile_changed_handler (dt_colorspaces_profile_changed_handler_t handler)
 Register the one callback fired when the display profile changes.
 
void dt_colorspaces_set_display_profile (const dt_colorspaces_color_profile_type_t profile_type, GtkWidget *widget)
 Refresh the cached display profile from the monitor showing widget (X atom, colord, or the platform equivalent).
 
const dt_colorspaces_color_profile_tdt_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.
 
gboolean dt_colorspaces_is_profile_equal (const char *fullname, const char *filename)
 Do these two names refer to the same profile file?
 
void dt_colorspaces_update_display_transforms ()
 Delete and rebuild the four prepared display transforms from the current display profile and intent.
 
int dt_colorspaces_conversion_matrices_xyz (const float adobe_XYZ_to_CAM[4][3], float in_XYZ_to_CAM[9], double XYZ_to_CAM[4][3], double CAM_to_XYZ[3][4])
 Compute the XYZ->camera and camera->XYZ matrices for an image.
 
int dt_colorspaces_conversion_matrices_rgb (const float *adobe_XYZ_to_CAM, double(*RGB_to_CAM)[3], double(*CAM_to_RGB)[4], const float *embedded_matrix, double *mul)
 Compute the sRGB->camera and camera->sRGB matrices, and the default white balance multipliers.
 
void dt_colorspaces_cygm_apply_coeffs_to_rgb (float *out, const float *in, int num, double RGB_to_CAM[4][3], double CAM_to_RGB[3][4], dt_aligned_pixel_t coeffs)
 Apply CYGM white-balance coefficients to an image already converted to RGB by dt_colorspaces_cygm_to_rgb().
 
void dt_colorspaces_cygm_to_rgb (float *out, int num, double CAM_to_RGB[3][4])
 Convert a 4-channel CYGM buffer to RGB, in place.
 
void dt_colorspaces_rgb_to_cygm (float *out, int num, double RGB_to_CAM[4][3])
 Convert an RGB buffer to 4-channel CYGM, in place.
 

Detailed Description

The colour-profile module's API: which profiles exist, and how to apply one.

The module owns its state. A single dt_colorspaces_t lives file-static in colorspaces.c, built by dt_colorprofiles_init() and torn down by dt_colorprofiles_cleanup(). It used to hang off the application struct as darktable.color_profiles, which put every translation unit one dereference away from the profile list, its rwlock and its cached LCMS transforms.

The API is split in two halves, which is the whole design:

  • CRUDE (metadata). add/remove/fetch/enumerate answer questions ABOUT a profile – {type, filename, name} for a role – and answer them with VALUE copies. No lcms2 type crosses this boundary and no caller walks the list. No lock is taken: the list is built once at init and never appended to again.
  • Lock and Apply (data). dt_colorspaces_lock_profiles() / dt_colorspaces_unlock_profiles() pin the profile handles while a caller derives from one; the prepared-transform entry points below run the pixel loop themselves, so the cmsHTRANSFORM never leaves the module.
Note
Lifetime here is answered by a lock, not by a copy, and that is a measurement, not a taste: there is no cmsDupProfile in lcms2. The only true deep copy of a profile is serialise-and-reopen – about 0.005 ms for a built-in, but 1.02 ms for a real colord display profile – and copying a prepared cmsHTRANSFORM means rebuilding it from scratch, 2.2 to 38 ms, with nothing to amortise it against.
Including this header drags in <lcms2.h> and <pthread.h>. A translation unit that only needs the vocabulary (a profile type to store in its params, an intent to pass along) should include colorprofiles/profile_types.h instead, which is the reason that header exists.
Warning
Profiles derived from ONE IMAGE – DT_COLORSPACE_EMBEDDED_ICC through DT_COLORSPACE_ALTERNATE_MATRIX – are NOT registered in the list and cannot be resolved by identity through dt_colorspaces_get_profile(): their matrices come from the image's own camera data via iop/colorin.c. They live on the pipe that built them, never in the shared list.

Definition in file colorspaces.h.

Macro Definition Documentation

◆ LUT_SAMPLES

#define LUT_SAMPLES   0x10000

Max samples in a tone-curve LUT built from a profile (65536).

Note
iop/colorin.c and iop/colorout.c each re-define the identical value locally for their own lut[3][LUT_SAMPLES] members; the definitions must stay in step.

Definition at line 108 of file colorspaces.h.

◆ TYPE_XYZA_FLT

#define TYPE_XYZA_FLT   (FLOAT_SH(1)|COLORSPACE_SH(PT_XYZ)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4))

lcms2 pixel format for float XYZ + one extra channel.

This was removed from lcms2 in 2.4, so it is rebuilt from the same shift macros. Used for the prepared XYZ -> display transform, and by iop/colorout.c when the output profile is DT_COLORSPACE_XYZ.

Definition at line 115 of file colorspaces.h.

Typedef Documentation

◆ dt_colorprofile_desc_t

A profile's public identity: what the GUI displays and stores, and nothing else.

A plain value – copy it, put it in GTK object data, outlive anything with it. It carries no cmsHPROFILE, so it is unaffected by a monitor-profile change and needs no lock to keep.

◆ dt_colorprofiles_settings_t

Consistent snapshot of the display and soft-proofing settings.

The seven fields cross the module boundary only together. Reading them one at a time – which is what direct member access forced – lets a reader observe a new profile type paired with the previous filename, and a 512-byte filename read while it is being g_strlcpy'd is a TORN string, not merely a stale one. Both groups were read that way by iop/colorout.c (the display triple and the soft-proof pair, as separate unsynchronised loads spread over ~170 lines of commit_params) and by iop/filmicrgb.c on pipeline threads, while the GUI thread wrote them.

Warning
A module that snapshots this for its hash must then RENDER from the same snapshot. iop/filmicrgb.c snapshotted the soft-proof state for runtime_data_hash in commit_params, then read the live global again from process() / process_cl(), once per tile – rendering from state its cache key did not describe.

◆ dt_colorspaces_cicp_t

The three ITU-T H.273 code points that describe a colour space without an ICC profile.

Read out of AVIF/HEIF containers by imageio/imageio_avif.c and imageio/imageio_heif.c, and mapped onto a dt_colorspaces_color_profile_type_t by dt_colorspaces_cicp_to_type() (imageio/imageio_profile.c). Nothing in this module consumes it; it lives here because it is part of the colour vocabulary.

◆ dt_colorspaces_color_profile_t

One registered profile: its identity, its LCMS handle, and where it sits in each combo box.

Entries in the application-wide list are created once at init and freed by dt_colorprofiles_cleanup() (through _colorspaces_destroy(), which closes every profile it finds). The same struct is also used for a container belonging to ONE image – see dt_colorspaces_new_image_profile() – and those set every *_pos to -1 so they are invisible to enumeration by construction.

Warning
Three entries are registered with profile == NULL: the categories DT_COLORSPACE_WORK, DT_COLORSPACE_EXPORT and DT_COLORSPACE_SOFTPROOF, which name a user setting rather than a colour space. Nothing NULL-checks the handle at ~40 call sites that dereference ->profile; what actually keeps them safe is that lookup never gives the category entries a role (see roles), so a category entry can never be returned. Do not "fix" the lookup predicate to consult them a role of their own without auditing those sites first.

◆ dt_colorspaces_profile_changed_handler_t

typedef void(* dt_colorspaces_profile_changed_handler_t) (void)

Callback invoked after the monitor profile actually changed.

Definition at line 859 of file colorspaces.h.

◆ dt_colorspaces_t

The module's private state. Declared here for the module's own .c files only.

Nothing outside src/colorprofiles/ names this type, and the single instance is file-static in colorspaces.c – there is no accessor for it in this header. It is documented because the module's own translation units share it, not because it is an interface.

Almost all of it is immutable after dt_colorprofiles_init(). Exactly two things mutate afterwards, both guarded by the transforms lock: the DT_COLORSPACE_DISPLAY entry's cmsHPROFILE, and the four prepared transforms derived from it.

Warning
LOCK ORDER, where both are involved: _transforms_lock OUTER, the settings lock (private to colorspaces.c) INNER. The display setters need both, because changing the display profile identity also rebuilds the four transforms. Nothing takes them the other way round.

◆ GtkWidget

typedef struct _GtkWidget GtkWidget

GtkWidget, opaque, spelled exactly as GTK spells it.

dt_colorspaces_set_display_profile() only passes the window through to system/display_profile.h, so this header needs the name and nothing else. Declaring it here keeps <gtk/gtk.h> out of a header 40-odd files include, most of which have nothing to do with the GUI.

Definition at line 98 of file colorspaces.h.

Function Documentation

◆ dt_colorprofiles_bgra8_to_adobergb_rgba8()

gboolean dt_colorprofiles_bgra8_to_adobergb_rgba8 ( const uint8_t *const  in,
uint8_t *const  out,
const int  width,
const int  height,
const dt_colorspaces_color_profile_type_t  src_space 
)

The storage leg: convert an 8-bit plane from src_space (BGRA8) to AdobeRGB (RGBA8), for thumbnails written to the mipmap cache.

DT_COLORSPACE_DISPLAY uses the prepared display->AdobeRGB transform; anything else is resolved for DT_PROFILE_ROLE_MONITOR and a transform is built and destroyed inside the call.

Parameters
insource plane, width * height * 4 bytes.
outdestination plane, same size. Alpha is forced to 255.
widthplane width in pixels.
heightplane height in pixels.
src_spacecolour space the source is tagged with.
Returns
TRUE when a transform was applied, FALSE when only the R <-> B swap was.
Warning
Same aliasing caveat as dt_colorprofiles_rgba8_to_display_bgra8(): safe in place only while a transform exists. common/mipmap_cache.c calls this with buf, buf.

Definition at line 1587 of file colorspaces.c.

References _get_profile(), _transform_rgba8_to_bgra8(), _transforms_lock, DT_COLORSPACE_ADOBERGB, DT_COLORSPACE_DISPLAY, dt_colorspaces_get_global(), DT_PROFILE_ROLE_MONITOR, FALSE, height, IS_NULL_PTR, out, dt_colorspaces_color_profile_t::profile, transform(), dt_colorspaces_t::transform_display_to_adobe_rgb, TRUE, and width.

Referenced by dt_mipmap_cache_swap_at_size().

◆ dt_colorprofiles_cleanup()

void dt_colorprofiles_cleanup ( void  )

Persist the display/soft-proof settings to conf, flush the derived matrix/LUT memo, delete the prepared transforms, close every profile and free the instance.

The memo goes first, deliberately: its entries are derived from the profiles that are about to be closed.

Note
Idempotent, and safe to call when init never ran.
Warning
Called once, by the application, with no threads running. Any dt_iop_order_iccprofile_info_t * handed out by dt_colorspaces_add_profile() is dangling afterwards.

Definition at line 1259 of file colorspaces.c.

References _colorprofiles, _colorspaces_destroy(), dt_colorspaces_flush_profile_memo(), and IS_NULL_PTR.

Referenced by dt_cleanup().

◆ dt_colorprofiles_get_settings()

◆ dt_colorprofiles_init()

void dt_colorprofiles_init ( void  )

Build the module's single instance: register every built-in profile, load the color/in and color/out directories under both userconfig and datadir, restore the display/soft-proof settings from conf, and build the four prepared display transforms.

The instance is file-static in colorspaces.c; there is no way to name it from outside. It used to hang off darktable_t as struct dt_colorspaces_t *color_profiles, which put the whole application one dereference away from the profile list, its rwlock and its cached transforms.

Note
Idempotent: a second call with an instance already up returns immediately.
Warning
Called once, by the application, with no threads running. Everything that reads the profile list assumes it stops changing when this returns.
Note
Debug builds additionally run a selftest proving that the enumeration order this produces still matches the legacy per-entry *_pos integers – if it ever stops matching, every stored combo index in every preset points at the wrong profile.

Definition at line 1253 of file colorspaces.c.

References _colorprofiles, _colorspaces_build(), and IS_NULL_PTR.

Referenced by dt_init().

◆ dt_colorprofiles_rgba8_to_display_bgra8()

gboolean dt_colorprofiles_rgba8_to_display_bgra8 ( const uint8_t *const  in,
uint8_t *const  out,
const int  width,
const int  height,
const dt_colorspaces_color_profile_type_t  src_space 
)

Convert a whole 8-bit plane from src_space to the display profile: packed RGBA8 in, BGRA8 out (cairo byte order).

DT_COLORSPACE_SRGB and DT_COLORSPACE_ADOBERGB use the module's prepared transforms; DT_COLORSPACE_DISPLAY is already in display space and passes through with an R <-> B swap; anything else is resolved for DT_PROFILE_ROLE_MONITOR and a transform is built and destroyed inside the call.

Parameters
insource plane, width * height * 4 bytes.
outdestination plane, same size. Alpha is forced to 255.
widthplane width in pixels.
heightplane height in pixels.
src_spacecolour space the source is tagged with.
Returns
TRUE when the pixels were colour-managed (or were already in display space); FALSE when no transform could be built and only the byte swap was applied – a thumbnail cached with an exotic tag that has no DISPLAY-direction profile, for instance.
Warning
in and out may be the same buffer only on the colour-managed path, which relies on lcms2 converting in place between same-size formats. On the swap-only fallback the per-pixel swap reads in[0] after having written out[0], so an aliased call loses the red channel; both parameters are additionally restrict-qualified internally, which declares that they do not alias.

Definition at line 1534 of file colorspaces.c.

References _get_profile(), _transform_rgba8_to_bgra8(), _transforms_lock, DT_COLORSPACE_ADOBERGB, DT_COLORSPACE_DISPLAY, DT_COLORSPACE_SRGB, dt_colorspaces_get_global(), DT_PROFILE_ROLE_MONITOR, FALSE, height, IS_NULL_PTR, out, dt_colorspaces_color_profile_t::profile, transform(), dt_colorspaces_t::transform_adobe_rgb_to_display, dt_colorspaces_t::transform_srgb_to_display, TRUE, and width.

Referenced by _view_image_get_surface_internal().

◆ dt_colorprofiles_set_display_intent()

gboolean dt_colorprofiles_set_display_intent ( const dt_iop_color_intent_t  intent)

Set the rendering intent used towards the monitor, rebuilding the four prepared transforms.

Parameters
intentnew display intent.
Returns
TRUE when it changed.
Warning
Takes _transforms_lock for WRITING; see dt_colorprofiles_set_display_profile_choice().

Definition at line 1343 of file colorspaces.c.

References _settings_generation, _settings_lock, _transforms_lock, _update_display_transforms(), dt_colorspaces_t::display_intent, and dt_colorspaces_get_global().

Referenced by intent_callback().

◆ dt_colorprofiles_set_display_profile_choice()

gboolean dt_colorprofiles_set_display_profile_choice ( const dt_colorspaces_color_profile_type_t  type,
const char *const  filename 
)

Set the monitor profile identity and rebuild the four prepared transforms.

Identity and transforms are written under the same _transforms_lock hold, so a reader can never see one without the other.

Parameters
typenew display profile type.
filenameonly meaningful for DT_COLORSPACE_FILE; NULL is treated as "".
Returns
TRUE when something actually changed, FALSE when the choice was already in effect.
Note
Returning "did it change" is the point: callers used to decide that for themselves against a value read separately, and re-selecting the ALREADY ACTIVE display profile then reset the user to the system profile through an inherited "profile not found" fallback – firing on the one case where nothing should happen.
Warning
Takes _transforms_lock for WRITING. Never call it while holding dt_colorspaces_lock_profiles().

Definition at line 1319 of file colorspaces.c.

References _profile_choice_differs(), _settings_generation, _settings_lock, _transforms_lock, _update_display_transforms(), dt_colorspaces_t::display_filename, dt_colorspaces_t::display_type, dt_colorspaces_get_global(), dt_colorspaces_color_profile_t::filename, IS_NULL_PTR, and type.

Referenced by profile_callback().

◆ dt_colorprofiles_set_mode()

gboolean dt_colorprofiles_set_mode ( const dt_colorspaces_color_mode_t  mode)

Set the proofing mode outright.

Parameters
modeDT_PROFILE_NORMAL, DT_PROFILE_SOFTPROOF or DT_PROFILE_GAMUTCHECK.
Returns
TRUE when it changed.
See also
dt_colorprofiles_toggle_mode for the "press the button again to leave" behaviour.

Definition at line 1400 of file colorspaces.c.

References _settings_generation, _settings_lock, dt_colorspaces_get_global(), and dt_colorspaces_t::mode.

◆ dt_colorprofiles_set_softproof_intent()

gboolean dt_colorprofiles_set_softproof_intent ( const dt_iop_color_intent_t  intent)

Set the rendering intent used towards the soft-proofing target.

Parameters
intentnew soft-proof intent.
Returns
TRUE when it changed.

Definition at line 1384 of file colorspaces.c.

References _settings_generation, _settings_lock, dt_colorspaces_get_global(), and dt_colorspaces_t::softproof_intent.

◆ dt_colorprofiles_set_softproof_profile_choice()

gboolean dt_colorprofiles_set_softproof_profile_choice ( const dt_colorspaces_color_profile_type_t  type,
const char *const  filename 
)

Set the soft-proofing target identity.

Parameters
typenew soft-proof profile type.
filenameonly meaningful for DT_COLORSPACE_FILE; NULL is treated as "".
Returns
TRUE when it changed.
Note
No transform rebuild here: the soft-proof settings feed transforms that iop/colorout.c builds per commit_params, and nothing cached in this module derives from them. It therefore takes only the settings lock, not _transforms_lock.

Definition at line 1366 of file colorspaces.c.

References _profile_choice_differs(), _settings_generation, _settings_lock, dt_colorspaces_get_global(), dt_colorspaces_color_profile_t::filename, IS_NULL_PTR, dt_colorspaces_t::softproof_filename, dt_colorspaces_t::softproof_type, and type.

Referenced by _softproof_profile_callback().

◆ dt_colorprofiles_srgb_to_display_strided()

gboolean dt_colorprofiles_srgb_to_display_strided ( uint8_t *const  pixels,
const int  width,
const int  height,
const int  rowstride,
const int  n_channels,
const gboolean  has_alpha 
)

Convert a strided, packed-RGB(A) 8-bit buffer (GdkPixbuf shape) from sRGB to the display profile, in place.

Plain integers only: the module never sees a GdkPixbuf. Each row is widened to RGBA8 in per-thread scratch, converted, then written back narrowed and R <-> B swapped.

Parameters
pixelsfirst byte of the buffer; converted in place.
widthpixels per row.
heightrows.
rowstridebytes between the starts of two rows.
n_channelsbytes per pixel, 3 or 4.
has_alphawhether the 4th channel is alpha to be preserved.
Returns
TRUE on success. FALSE – leaving the pixels untouched – on a bad argument, when no display transform is available, or when the scratch allocation fails.
Note
The scratch for every thread is one allocation made BEFORE the parallel region on purpose: a per-thread allocation that could fail would put the worksharing loop behind a condition some threads take and others do not, which hangs.

Definition at line 1656 of file colorspaces.c.

References __OMP_FOR__, __OMP_PARALLEL__, _srgb_to_display_row(), _transforms_lock, dt_colorspaces_get_global(), dt_get_num_openmp_threads(), dt_get_thread_num(), FALSE, height, IS_NULL_PTR, MAX, transform(), dt_colorspaces_t::transform_srgb_to_display, TRUE, and width.

Referenced by _colorcorrect_pixbuf().

◆ dt_colorprofiles_toggle_mode()

dt_colorspaces_color_mode_t dt_colorprofiles_toggle_mode ( const dt_colorspaces_color_mode_t  mode)

Turn mode on, or back to DT_PROFILE_NORMAL if it is already the current mode, as one locked read-modify-write.

Parameters
modethe mode the caller's button stands for.
Returns
the mode now in effect – which is what the caller should reflect in its UI, rather than assuming its own button won.
Note
The two toggle buttons each open-coded "read mode, compare, write the opposite", which is not atomic: two accelerator presses in flight could both read DT_PROFILE_NORMAL and leave soft-proof and gamut-check disagreeing about which of them is on.

Definition at line 1416 of file colorspaces.c.

References _settings_generation, _settings_lock, dt_colorspaces_get_global(), DT_PROFILE_NORMAL, and dt_colorspaces_t::mode.

Referenced by _button_clicked().

◆ dt_colorprofiles_xyz_to_display()

void dt_colorprofiles_xyz_to_display ( const dt_aligned_pixel_t  XYZ,
dt_aligned_pixel_t  RGB 
)

Convert one D50 XYZ pixel to display RGB.

Parameters
XYZinput pixel, D50-referred XYZ, 4th channel ignored.
RGBoutput pixel, display RGB.
Note
Falls back to dt_XYZ_to_sRGB() when no display profile has been resolved yet (startup, headless, or a monitor whose profile could not be read). Two open-coded, byte-identical copies of this function used to dereference the cached handle without a lock and without that check, on a path that repaints on window move and resize – the very events that free it.
Warning
One pixel per call, lock included. This is for colour pickers and overlay swatches, not for a pixel loop.

Definition at line 1518 of file colorspaces.c.

References _transforms_lock, dt_colorspaces_get_global(), dt_XYZ_to_sRGB(), IS_NULL_PTR, RGB, transform(), dt_colorspaces_t::transform_xyz_to_display, and XYZ.

Referenced by _colormanage_ui_color(), and _colormanage_ui_color().

◆ dt_colorspaces_cleanup_profile()

void dt_colorspaces_cleanup_profile ( cmsHPROFILE  p)

Close a profile created by any of the dt_colorspaces_create_* / dt_colorspaces_get_rgb_profile_from_mem functions.

Parameters
pprofile handle; NULL is a no-op.
Warning
Only for profiles the caller OWNS. A handle obtained from dt_colorspaces_get_profile() belongs to the module's list and is closed by dt_colorprofiles_cleanup(); closing it here double-frees at shutdown.

Definition at line 1011 of file colorspaces.c.

References IS_NULL_PTR, and p.

Referenced by _build_embedded_profile(), _colorspaces_destroy(), _update_display_profile(), dt_colorspaces_free_conversion(), dt_colorspaces_free_image_profile(), dt_colorspaces_get_input_profile_from_image(), dt_image_find_best_color_profile(), dt_image_get_embedded_output_profile(), and dt_image_get_input_profile().

◆ dt_colorspaces_conversion_matrices_rgb()

int dt_colorspaces_conversion_matrices_rgb ( const float *  adobe_XYZ_to_CAM,
double(*)  RGB_to_CAM[3],
double(*)  CAM_to_RGB[4],
const float *  embedded_matrix,
double mul 
)

Compute the sRGB->camera and camera->sRGB matrices, and the default white balance multipliers.

Converted from dcraw's cam_xyz_coeff(). Rows of RGB->CAM are normalised so that RGB->CAM applied to (1,1,1) gives (1,1,1,1), and the multipliers fall out of that normalisation.

Parameters
adobe_XYZ_to_CAMthe camera's built-in Adobe matrix.
RGB_to_CAMreceives the forward matrix, or NULL if not wanted.
CAM_to_RGBreceives the pseudo-inverse, or NULL if not wanted.
embedded_matrix9 floats from the file; takes PRIORITY over the Adobe matrix when non-NULL and not NaN. Keep in sync with reload_defaults in iop/colorin.c.
mulreceives the 4 default WB multipliers, or NULL if not wanted.
Returns
TRUE on success, FALSE when no usable matrix was available.

Definition at line 2546 of file colorspaces.c.

References dt_colorspaces_pseudoinverse(), FALSE, i, IS_NULL_PTR, k, and TRUE.

Referenced by _custom_wb_from_coeffs(), calculate_bogus_daylight_wb(), commit_params(), gui_update(), and legacy_params().

◆ dt_colorspaces_conversion_matrices_xyz()

int dt_colorspaces_conversion_matrices_xyz ( const float  adobe_XYZ_to_CAM[4][3],
float  in_XYZ_to_CAM[9],
double  XYZ_to_CAM[4][3],
double  CAM_to_XYZ[3][4] 
)

Compute the XYZ->camera and camera->XYZ matrices for an image.

Parameters
adobe_XYZ_to_CAMthe camera's built-in Adobe matrix, used only as the fallback.
in_XYZ_to_CAM9 floats read from the file (a DNG ColorMatrix, say). When in_XYZ_to_CAM[0] is NaN the Adobe matrix is used instead; otherwise this one wins.
XYZ_to_CAMreceives the forward matrix; the 4th row is zeroed when it came from the 9-float form.
CAM_to_XYZreceives the pseudo-inverse.
Returns
TRUE on success, FALSE when neither source matrix is usable (both NaN).
Note
4 rows because the camera may be 4-colour (CYGM, RGBE).

Definition at line 2514 of file colorspaces.c.

References dt_colorspaces_pseudoinverse(), FALSE, i, and TRUE.

Referenced by prepare_matrices().

◆ dt_colorspaces_create_alternate_profile()

cmsHPROFILE dt_colorspaces_create_alternate_profile ( const char *  makermodel)

Create an ICC virtual profile from the shipped alternate matrices.

Parameters
makermodelcamera identifier, matched case-SENSITIVELY against dt_alternate_colormatrices.
Returns
a fresh cmsHPROFILE the CALLER owns, or NULL when absent.

Definition at line 573 of file colorspaces.c.

References dt_alternate_colormatrices, dt_alternate_colormatrix_cnt, IS_NULL_PTR, k, name, and preset.

Referenced by dt_image_get_input_profile().

◆ dt_colorspaces_create_darktable_profile()

cmsHPROFILE dt_colorspaces_create_darktable_profile ( const char *  makermodel)

Create an ICC virtual profile from the shipped profiled colour matrices.

Parameters
makermodelcamera identifier, matched case-INsensitively against dt_profiled_colormatrices.
Returns
a fresh cmsHPROFILE the CALLER owns, or NULL when this camera has no such matrix. Close it with dt_colorspaces_cleanup_profile().

Definition at line 673 of file colorspaces.c.

References dt_profiled_colormatrices, dt_profiled_colormatrix_cnt, IS_NULL_PTR, k, name, and preset.

Referenced by dt_image_get_input_profile().

◆ dt_colorspaces_create_vendor_profile()

cmsHPROFILE dt_colorspaces_create_vendor_profile ( const char *  makermodel)

Create an ICC virtual profile from the shipped vendor matrices.

Parameters
makermodelcamera identifier, matched case-SENSITIVELY against dt_vendor_colormatrices.
Returns
a fresh cmsHPROFILE the CALLER owns, or NULL when absent.

Definition at line 623 of file colorspaces.c.

References dt_vendor_colormatrices, dt_vendor_colormatrix_cnt, IS_NULL_PTR, k, name, and preset.

Referenced by dt_image_get_input_profile().

◆ dt_colorspaces_create_xyzimatrix_profile()

cmsHPROFILE dt_colorspaces_create_xyzimatrix_profile ( float  cam_xyz[3][3])

Create a linear-gamma RGB profile from an XYZ->camera matrix.

Parameters
cam_xyzthe XYZ->camera matrix; it is inverted internally, so the profile describes camera->XYZ.
Returns
a fresh cmsHPROFILE the CALLER owns and closes with dt_colorspaces_cleanup_profile(), or NULL when the matrix could not be inverted.

Definition at line 948 of file colorspaces.c.

References dt_colorspaces_create_xyzmatrix_profile(), and mat3inv().

Referenced by dt_colorspaces_get_input_profile_from_image(), and dt_image_find_best_color_profile().

◆ dt_colorspaces_cygm_apply_coeffs_to_rgb()

void dt_colorspaces_cygm_apply_coeffs_to_rgb ( float *  out,
const float *  in,
int  num,
double  RGB_to_CAM[4][3],
double  CAM_to_RGB[3][4],
dt_aligned_pixel_t  coeffs 
)

Apply CYGM white-balance coefficients to an image already converted to RGB by dt_colorspaces_cygm_to_rgb().

Parameters
outdestination, num pixels of 4 floats; only the first 3 channels are written.
insource, num pixels of 4 floats.
numpixel count.
RGB_to_CAMforward matrix from dt_colorspaces_conversion_matrices_rgb().
CAM_to_RGBits pseudo-inverse.
coeffsthe 4 per-camera-channel WB coefficients.
Warning
Dead code: verified to have no caller anywhere in the tree. Kept because the CYGM WB path is otherwise unimplemented, not because it is exercised.
Todo:
: CRITICAL: why is this function NOT used anywhere ???

Definition at line 2626 of file colorspaces.c.

References __OMP_PARALLEL_FOR__, i, and out.

◆ dt_colorspaces_cygm_to_rgb()

void dt_colorspaces_cygm_to_rgb ( float *  out,
int  num,
double  CAM_to_RGB[3][4] 
)

Convert a 4-channel CYGM buffer to RGB, in place.

Parameters
outbuffer of num pixels, stride 4 floats; channels 0..2 are overwritten with RGB and channel 3 is left as it was.
numpixel count.
CAM_to_RGBmatrix from dt_colorspaces_conversion_matrices_rgb().

Definition at line 2656 of file colorspaces.c.

References __OMP_PARALLEL_FOR__, i, k, and out.

Referenced by gui_update_from_coeffs(), and process().

◆ dt_colorspaces_enumerate_profiles()

size_t dt_colorspaces_enumerate_profiles ( const dt_colorspaces_profile_role_t  role,
dt_colorprofile_desc_t **  out 
)

Ordered snapshot of every profile registered for one role.

(*out)[k] is exactly the entry whose legacy X_pos was k for the single-bit role X, so a combo box built by walking this array keeps today's ordering and stays compatible with today's stored indices in presets and conf. A debug-build selftest at init asserts that equivalence against the real installed profile set.

Parameters
rolewhich combo box to enumerate. Must be a single bit (DT_PROFILE_ROLE_INPUT / _OUT / _WORK / _DISPLAY) for the index correspondence to mean anything; a multi-bit mask enumerates the union in list order instead.
outreceives a freshly allocated array of count descriptors, or NULL. The CALLER owns it and frees it with dt_free_align.
Returns
the number of descriptors written. 0 with *out == NULL is a legal answer – an empty role, or an allocation failure.
Note
Value copies: the array stays valid across a monitor-profile change and needs no lock.

Definition at line 2383 of file colorspaces.c.

References _entry_serves(), _fill_desc(), dt_alloc_align(), dt_colorspaces_get_global(), IS_NULL_PTR, k, out, p, and dt_colorspaces_t::profiles.

Referenced by _build_softproof_gamut_popover(), _get_profiles(), append_display(), gui_init(), and update_profile_list().

◆ dt_colorspaces_free_image_profile()

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 container owns it.

Parameters
profilecontainer to free; NULL is a no-op.
Note
Called by the image cache when the image is evicted; nothing else should need it. Declared here so common/image_cache.c does not need the struct layout.

Definition at line 877 of file colorspaces.c.

References dt_colorspaces_cleanup_profile(), dt_free, IS_NULL_PTR, and dt_colorspaces_color_profile_t::profile.

Referenced by _build_embedded_profile(), commit_params(), and dt_image_cache_deallocate().

◆ dt_colorspaces_get_matrix_from_input_profile()

int dt_colorspaces_get_matrix_from_input_profile ( cmsHPROFILE  prof,
dt_colormatrix_t  matrix,
float *  lutr,
float *  lutg,
float *  lutb,
const int  lutsize 
)

Extract the profile->XYZ matrix and the per-channel tone curves from an INPUT profile.

Parameters
profsource profile.
matrixreceives the colour matrix, or NULL to only probe whether extraction is possible.
lutr,lutg,lutbreceive lutsize samples each, or NULL to only probe. A channel whose TRC is linear is flagged by writing -1.0f into lut*[0] and nothing else – test for it before using the LUT.
lutsizesamples per curve, normally LUT_SAMPLES.
Returns
0 on success. Non-zero when the profile is not a matrix-shaper, carries a CLUT for any intent (in which case only LCMS may apply it), lacks a required tag, or has an all-zero colorant matrix.
Note
Curves and matrix are in the input sense; the output variant inverts them.

Definition at line 354 of file colorspaces.c.

References dt_colorspaces_get_matrix_from_profile(), lutsize, and matrix.

Referenced by _colorspaces_build(), _generate_profile_info(), and dt_colorspaces_prepare_conversion().

◆ dt_colorspaces_get_matrix_from_output_profile()

int dt_colorspaces_get_matrix_from_output_profile ( cmsHPROFILE  prof,
dt_colormatrix_t  matrix,
float *  lutr,
float *  lutg,
float *  lutb,
const int  lutsize 
)

Extract the XYZ->profile matrix and the inverse tone curves from an OUTPUT profile.

Parameters
profsource profile.
matrixreceives the inverted colour matrix, or NULL to only probe.
lutr,lutg,lutbreceive lutsize samples of the REVERSED curves, or NULL to only probe.
lutsizesamples per curve, normally LUT_SAMPLES.
Returns
0 on success, non-zero otherwise; same rejection reasons as the input variant.
Note
Calling it with every pointer NULL is how init decides whether a loaded .icc qualifies as a working/histogram profile.

Definition at line 360 of file colorspaces.c.

References dt_colorspaces_get_matrix_from_profile(), lutsize, and matrix.

Referenced by _colorspaces_build(), _generate_profile_info(), and dt_colorspaces_prepare_conversion().

◆ dt_colorspaces_get_name()

const char * dt_colorspaces_get_name ( dt_colorspaces_color_profile_type_t  type,
const char *  filename 
)

Printable name for a profile identity, without touching the profile list.

Parameters
typeprofile type.
filenamereturned verbatim for DT_COLORSPACE_FILE, ignored otherwise.
Returns
a translated static string for the built-ins, filename for DT_COLORSPACE_FILE, or NULL for DT_COLORSPACE_NONE and DT_COLORSPACE_LAST. Never free it.
Note
This is a pure switch on the enum, so it also names identities that are NOT registered in the list (the per-image DT_COLORSPACE_EMBEDDED_* / *_MATRIX entries) – which is exactly what error messages about an unresolvable profile need.

Definition at line 2035 of file colorspaces.c.

References DT_COLORSPACE_ADOBERGB, DT_COLORSPACE_ALTERNATE_MATRIX, DT_COLORSPACE_BRG, DT_COLORSPACE_DISPLAY, DT_COLORSPACE_DISPLAY2, DT_COLORSPACE_DISPLAY_P3, DT_COLORSPACE_EMBEDDED_ICC, DT_COLORSPACE_EMBEDDED_MATRIX, DT_COLORSPACE_ENHANCED_MATRIX, DT_COLORSPACE_EXPORT, DT_COLORSPACE_FILE, DT_COLORSPACE_HLG_P3, DT_COLORSPACE_HLG_REC2020, DT_COLORSPACE_INFRARED, DT_COLORSPACE_ITUR_BT1886, DT_COLORSPACE_LAB, DT_COLORSPACE_LAST, DT_COLORSPACE_LIN_REC2020, DT_COLORSPACE_LIN_REC709, DT_COLORSPACE_NONE, DT_COLORSPACE_PQ_P3, DT_COLORSPACE_PQ_REC2020, DT_COLORSPACE_PROPHOTO_RGB, DT_COLORSPACE_REC709, DT_COLORSPACE_SOFTPROOF, DT_COLORSPACE_SRGB, DT_COLORSPACE_STANDARD_MATRIX, DT_COLORSPACE_VENDOR_MATRIX, DT_COLORSPACE_WORK, DT_COLORSPACE_XYZ, dt_colorspaces_color_profile_t::filename, and type.

Referenced by _ioporder_runtime_band_text(), _resolve_work_profile(), _save_clut_callback(), commit_params(), gui_update(), profile_changed(), update_profile_list(), workicc_changed(), and write_image().

◆ dt_colorspaces_get_profile()

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.

Parameters
typeprofile type to find.
filenameonly consulted for DT_COLORSPACE_FILE, matched with dt_colorspaces_is_profile_equal().
roledirection mask; the first entry in registration order that serves any of its bits and matches the identity wins.
Returns
a pointer into the module's list, owned by the module and valid until dt_colorprofiles_cleanup() – do NOT close its profile. NULL when nothing matches.
Warning
This does not support image specifics: embedded profiles and camera matrices (DT_COLORSPACE_EMBEDDED_ICC .. DT_COLORSPACE_ALTERNATE_MATRIX) are not registered and always return NULL, as do the three category types.
When type can be DT_COLORSPACE_DISPLAY, wrap the resolve AND everything derived from ->profile in dt_colorspaces_lock_profiles() / dt_colorspaces_unlock_profiles(): that handle is closed and replaced on monitor changes.
A multi-bit direction returns the first match in registration order, which for DT_COLORSPACE_SRGB is the v4 INPUT-only entry – so DT_PROFILE_ROLE_ANY resolves the working profile to the wrong sRGB variant. Name the direction you mean.

Definition at line 2303 of file colorspaces.c.

References _get_profile(), dt_colorspaces_get_global(), dt_colorspaces_color_profile_t::filename, and type.

Referenced by _export_image(), _generate_profile_info(), _get_xyz_to_rgb_matrix(), _icc_blob_from_profile_key(), _read_chunky_16_Lab(), _read_chunky_8_Lab(), _resolve_endpoint(), _transform_from_to_rgb_lab_lcms2(), dt_colorspaces_get_output_profile(), dt_image_find_best_color_profile(), dt_imageio_tiff_read_profile(), and gui_init().

◆ dt_colorspaces_get_profile_name()

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.

Parameters
pprofile to describe.
languagetwo-letter ISO language code, e.g. "en".
countrytwo-letter ISO country code, e.g. "US".
namedestination buffer.
lenits size in bytes.
Note
On failure name is set to the empty string rather than left uninitialised, so the caller can test name[0].

Definition at line 1017 of file colorspaces.c.

References dt_free, error(), IS_NULL_PTR, name, p, and size.

Referenced by _build_embedded_profile(), _update_display_profile(), load_profile_from_dir(), and write_image().

◆ dt_colorspaces_get_rgb_profile_from_mem()

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.

If the blob is a GRAYSCALE profile, it is closed and a new RGB profile is synthesised from it with the same TRC, black point and white point, and Rec709 primaries – the pipeline has no grayscale path.

Parameters
datathe ICC blob.
sizeits length in bytes.
Returns
a fresh cmsHPROFILE the CALLER owns and closes with dt_colorspaces_cleanup_profile(), or NULL when the blob is not a readable profile.

Definition at line 1004 of file colorspaces.c.

References _ensure_rgb_profile(), dt_colorspaces_color_profile_t::profile, and size.

Referenced by dt_colorspaces_get_input_profile_from_image(), and dt_image_find_best_color_profile().

◆ dt_colorspaces_is_profile_equal()

gboolean dt_colorspaces_is_profile_equal ( const char *  fullname,
const char *  filename 
)

Do these two names refer to the same profile file?

Parameters
fullnamethe registered entry's name, always a full path.
filenamethe stored name, which may be a full path or just a base name.
Returns
TRUE when they match.
Note
The basename leniency exists for backward compatibility: older iop params recorded only the base name.

Definition at line 2273 of file colorspaces.c.

References _colorspaces_get_base_name(), _colorspaces_is_base_name(), and dt_colorspaces_color_profile_t::filename.

Referenced by _get_profile(), dt_colorspaces_profile_exists(), dt_colorspaces_profile_index(), and gui_update().

◆ dt_colorspaces_lock_profile()

void dt_colorspaces_lock_profile ( const dt_colorspaces_color_profile_t *const  profile)

◆ dt_colorspaces_new_image_profile()

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.

An embedded ICC profile is a property of its image, so the image owns it (dt_image_t.embedded_profile). It is deliberately NOT appended to the module's list: that list is built once at init and read from ~23 places with no lock, and appending to it from parallel export jobs was an unsynchronised write, unbounded growth, and a leak all at once.

Parameters
typeprofile type this container stands for.
profilethe LCMS2 handle to wrap.
owns_profilewhether the container must CLOSE that handle when freed. Pass FALSE when the profile is borrowed from the application-wide list, which owns and closes it.
Returns
a container the caller owns, freed with dt_colorspaces_free_image_profile().
Note
Every *_pos is -1, so it is hidden from every combo box by construction.
Warning
owns_profile is not cosmetic. Several branches of dt_image_find_best_color_profile() hand back a pointer INTO the application list and leave their new_profile out-parameter FALSE; passing TRUE for one of those double-frees at shutdown.

Definition at line 867 of file colorspaces.c.

References _create_profile(), container(), dt_colorspaces_color_profile_t::owns_profile, dt_colorspaces_color_profile_t::profile, and type.

Referenced by _build_embedded_profile(), dt_image_get_embedded_output_profile(), and dt_image_get_input_profile().

◆ dt_colorspaces_profile_at()

gboolean dt_colorspaces_profile_at ( const dt_colorspaces_profile_role_t  role,
const int  index,
dt_colorprofile_desc_t *const  out 
)

Identity of the profile at index within direction.

Parameters
roleMUST be a single bit.
index0-based position within that direction's enumeration.
outfilled on success, left completely untouched on failure.
Returns
TRUE on success. FALSE when the index is out of range, negative, or direction is not a single bit.
Note
FALSE is the "the stored choice is no longer installed, fall back" branch expressed as a return value rather than a diagnostic print – handle it, do not assert on it.

Definition at line 2437 of file colorspaces.c.

References _entry_serves(), _fill_desc(), _is_single_role(), dt_colorspaces_get_global(), FALSE, IS_NULL_PTR, k, out, p, dt_colorspaces_t::profiles, and TRUE.

Referenced by _profile_changed(), _softproof_profile_callback(), profile_changed(), and workicc_changed().

◆ dt_colorspaces_profile_exists()

gboolean dt_colorspaces_profile_exists ( const dt_colorspaces_profile_role_t  role,
const dt_colorspaces_color_profile_type_t  type,
const char *const  filename 
)

Is this identity registered for this direction?

The one query in this group that accepts a multi-bit mask, because a yes/no answer over a union is still meaningful where an index would not be.

Parameters
roleone or more direction bits.
typeprofile type to test.
filenameonly consulted for DT_COLORSPACE_FILE.
Returns
TRUE when some entry serving direction matches.

Definition at line 2462 of file colorspaces.c.

References _entry_serves(), DT_COLORSPACE_FILE, dt_colorspaces_get_global(), dt_colorspaces_is_profile_equal(), FALSE, dt_colorspaces_color_profile_t::filename, IS_NULL_PTR, p, dt_colorspaces_t::profiles, TRUE, and type.

Referenced by _resolve_work_profile(), and commit_params().

◆ dt_colorspaces_profile_index()

int dt_colorspaces_profile_index ( const dt_colorspaces_profile_role_t  role,
const dt_colorspaces_color_profile_type_t  type,
const char *const  filename 
)

Combo position of (type, filename) within direction.

Parameters
roleMUST be a single bit; anything else returns -1 rather than a meaningless number.
typeprofile type to find.
filenameonly consulted for DT_COLORSPACE_FILE, and matched with dt_colorspaces_is_profile_equal() so a bare basename stored by an old iop still resolves.
Returns
the 0-based position within that direction's enumeration, or -1 when absent or when direction has more than one bit set.
Note
Callers add their own offset for leading non-profile rows ("same as original", "image settings", ...); this function knows nothing about them.

Definition at line 2412 of file colorspaces.c.

References _entry_serves(), _is_single_role(), DT_COLORSPACE_FILE, dt_colorspaces_get_global(), dt_colorspaces_is_profile_equal(), dt_colorspaces_color_profile_t::filename, IS_NULL_PTR, p, dt_colorspaces_t::profiles, and type.

Referenced by _build_softproof_gamut_popover(), gui_init(), gui_reset(), gui_update(), and set_params().

◆ dt_colorspaces_rgb_to_cygm()

void dt_colorspaces_rgb_to_cygm ( float *  out,
int  num,
double  RGB_to_CAM[4][3] 
)

Convert an RGB buffer to 4-channel CYGM, in place.

Parameters
outbuffer of num pixels; it is READ with stride 3 and WRITTEN with 4 components per pixel, so it must have room for num * 4 floats and the two strides do not agree for num > 1. The only caller (iop/invert.c) passes num == 1, where the mismatch cannot bite.
numpixel count.
RGB_to_CAMmatrix from dt_colorspaces_conversion_matrices_rgb().

Definition at line 2671 of file colorspaces.c.

References __OMP_PARALLEL_FOR__, i, k, and out.

Referenced by colorpicker_callback(), and legacy_params().

◆ dt_colorspaces_set_display_profile()

void dt_colorspaces_set_display_profile ( const dt_colorspaces_color_profile_type_t  profile_type,
GtkWidget widget 
)

Refresh the cached display profile from the monitor showing widget (X atom, colord, or the platform equivalent).

trigger updating the display profile from the system settings (x atom, colord, ...)

On a real change it replaces the DT_COLORSPACE_DISPLAY entry's cmsHPROFILE, rebuilds the four prepared transforms, drops the derived matrix/LUT memo and fires the changed handler. Nothing happens when the bytes read match the ones already cached.

Parameters
profile_typethe display profile type in effect; passed through to the colord callback.
widgetany realized widget on the monitor to inspect; NULL returns immediately. The caller owns the window – this module never asks the GUI which one to look at.
Warning
It acquires _transforms_lock with trywrlock and RETURNS SILENTLY if that fails, because it is called from window move/resize handlers. A refresh is therefore best-effort, not guaranteed; never rely on the profile having been updated when this returns.
Todo:
: benchmark if the try is really needed when moving/resizing the window. Maybe we can just lock it

Definition at line 2168 of file colorspaces.c.

References _notify_profile_changed(), _transforms_lock, _update_display_profile(), dt_colorspaces_get_global(), dt_conf_get_string_const(), DT_DEBUG_CONTROL, dt_display_profile_read(), dt_free, dt_print(), FALSE, IS_NULL_PTR, name, profile_changed(), TRUE, window, dt_colorspaces_t::xprofile_data, and dt_colorspaces_t::xprofile_size.

Referenced by _update_display_profile().

◆ dt_colorspaces_set_profile_changed_handler()

void dt_colorspaces_set_profile_changed_handler ( dt_colorspaces_profile_changed_handler_t  handler)

Register the one callback fired when the display profile changes.

Parameters
handlerthe callback, or NULL to unregister.
Note
The application relays it on its signal bus; this module does not know there is one. Unregistered, the notification is dropped – correct for a headless run, where nothing is watching a monitor.
Warning
It fires from wherever the change was detected, including the colord async callback, and it fires AFTER _transforms_lock has been released – so a handler may take the lock, but must not assume it already holds it.

Definition at line 168 of file colorspaces.c.

References _profile_changed_handler.

Referenced by dt_gui_gtk_init().

◆ dt_colorspaces_transform_rgba_float_image()

void dt_colorspaces_transform_rgba_float_image ( const cmsHTRANSFORM  transform,
const float *  image_in,
float *  image_out,
const int  width,
const int  height 
)

Run a caller-owned LCMS transform over a whole RGBA float image, one OpenMP task per row.

Parameters
transforman lcms2 transform whose input and output formats are 4-channel float.
image_insource, width * height * 4 floats.
image_outdestination, same size.
widthimage width in pixels.
heightimage height in pixels.
Note
A NULL transform, a NULL buffer or a non-positive dimension is a no-op, not a crash.
See also
dt_colorspaces_transform_rgba_float_row for the aliasing rule that applies here too.

Definition at line 1443 of file colorspaces.c.

References __OMP_PARALLEL_FOR__, dt_colorspaces_transform_rgba_float_row(), height, IS_NULL_PTR, out, transform(), and width.

Referenced by _transform_from_to_rgb_lab_lcms2().

◆ dt_colorspaces_transform_rgba_float_row()

void dt_colorspaces_transform_rgba_float_row ( const cmsHTRANSFORM  transform,
const float *  in,
float *  out,
const int  width 
)

Run a caller-owned LCMS transform over one row of RGBA float pixels.

return the work profile as set in colorin

These two take a transform the CALLER built and owns (iop/colorin.c, iop/colorout.c, colorprofiles/iop_profile.c). For the module's own prepared display transforms use the entry points below instead – those handles are rebuilt on monitor-profile changes and must never be borrowed.

Parameters
transforman lcms2 transform whose input and output formats are 4-channel float.
insource row, width * 4 floats. May be the same buffer as out.
outdestination row, width * 4 floats.
widthpixels in the row.
Warning
LCMS transform handles are not safe to rediscover indirectly from mutable owner structs inside OpenMP regions. Alias the cmsHTRANSFORM to a local variable BEFORE entering a parallel region, declare that alias shared there, and pass only that stable handle in.

Definition at line 1436 of file colorspaces.c.

References out, transform(), and width.

Referenced by _apply_lcms2(), and dt_colorspaces_transform_rgba_float_image().

◆ dt_colorspaces_unlock_profile()

void dt_colorspaces_unlock_profile ( const dt_colorspaces_color_profile_t *const  profile)

◆ dt_colorspaces_update_display_transforms()

void dt_colorspaces_update_display_transforms ( )

Delete and rebuild the four prepared display transforms from the current display profile and intent.

Warning
The caller must already hold the module's profile lock FOR WRITING. There is no public way to do that – dt_colorspaces_lock_profiles() is a read lock, and the instance itself is private – so in practice this is only callable from inside the module, and the setters above (dt_colorprofiles_set_display_profile_choice(), dt_colorprofiles_set_display_intent()) are what external code should use. It has no remaining callers outside colorspaces.c.

Definition at line 1202 of file colorspaces.c.

References _update_display_transforms(), and dt_colorspaces_get_global().

Referenced by _update_display_profile().

◆ hsl2rgb()

void hsl2rgb ( dt_aligned_pixel_t  rgb,
float  h,
float  s,
float  l 
)

Convert HSL back to RGB. Common helper used by iop modules.

Parameters
rgbreceives the RGB pixel; the 4th channel is left alone.
h,s,lhue, saturation and lightness, each in [0, 1].

Definition at line 1104 of file colorspaces.c.

References rgb.

Referenced by commit_params(), hue_conversion(), process(), process_hsl_v1(), process_hsl_v2(), set_RGB_sliders(), update_balance_slider_colors(), update_colorpicker_color(), update_saturation_slider_color(), update_saturation_slider_end_color(), update_saturation_slider_end_color(), and update_saturation_slider_end_color().

◆ mat3inv()

int mat3inv ( float *const  dst,
const float *const  src 
)

Thin alias of mat3inv_float(), same contract.

See also
mat3inv_float

Definition at line 225 of file colorspaces.c.

References mat3inv_float().

Referenced by dt_colorspaces_create_xyzimatrix_profile(), dt_imageio_open_rgbe(), and homography().

◆ mat3inv_float()

int mat3inv_float ( float *const  dst,
const float *const  src 
)

Invert a 3x3 matrix stored row-major as 9 contiguous floats.

Parameters
dstdestination, 9 floats, written only on success.
srcsource, 9 floats.
Returns
0 on success, 1 when the matrix is singular (|det| < 1e-7), leaving dst untouched.
Note
Colour maths only by accident of history – iop/ashift.c uses it to invert a homography. A double variant is generated by the same macro in colorspaces.c but is deliberately not exported.

inverts the given 3x3 matrix

Definition at line 223 of file colorspaces.c.

Referenced by mat3inv().

◆ rgb2hsl()

void rgb2hsl ( const dt_aligned_pixel_t  rgb,
float *  h,
float *  s,
float *  l 
)

Convert RGB to HSL. Common helper used by iop modules.

Parameters
rgbinput pixel, components expected in [0, 1].
h,s,lreceive hue, saturation and lightness, each in [0, 1].

Definition at line 1060 of file colorspaces.c.

References delta, g, r, and rgb.

Referenced by color_picker_apply(), colorpick_callback(), process(), process_hsl_v1(), process_hsl_v2(), and set_HSL_sliders().