diff options
author | Přemysl Eric Janouch <p@janouch.name> | 2024-01-27 23:43:06 +0100 |
---|---|---|
committer | Přemysl Eric Janouch <p@janouch.name> | 2024-01-28 00:09:15 +0100 |
commit | 04b0b0caf46f9b0f408b7c4d2774f96335c487a6 (patch) | |
tree | d9e5634954488cd983c3475c5531b6549993b169 | |
parent | 250f2f0f758a5f3ea0f3174843dbf55fc73b1370 (diff) | |
download | fiv-04b0b0caf46f9b0f408b7c4d2774f96335c487a6.tar.gz fiv-04b0b0caf46f9b0f408b7c4d2774f96335c487a6.tar.xz fiv-04b0b0caf46f9b0f408b7c4d2774f96335c487a6.zip |
WIP: Thread-safe colour management
-rw-r--r-- | fiv-io-cmm.c (renamed from fiv-io-profile.c) | 106 | ||||
-rw-r--r-- | fiv-io.h | 4 | ||||
-rw-r--r-- | meson.build | 2 |
3 files changed, 67 insertions, 45 deletions
diff --git a/fiv-io-profile.c b/fiv-io-cmm.c index 387b201..1336a22 100644 --- a/fiv-io-profile.c +++ b/fiv-io-cmm.c @@ -1,5 +1,5 @@ // -// fiv-profile.c: colour management +// fiv-io-cmm.c: colour management // // Copyright (c) 2024, Přemysl Eric Janouch <p@janouch.name> // @@ -23,6 +23,7 @@ #include "fiv-io.h" // Colour management must be handled before RGB conversions. +// TODO(p): Make it also possible to use Skia's skcms. #ifdef HAVE_LCMS2 #include <lcms2.h> #endif // HAVE_LCMS2 @@ -30,6 +31,56 @@ #include <lcms2_fast_float.h> #endif // HAVE_LCMS2_FAST_FLOAT +// --- Profiles ---------------------------------------------------------------- + +struct _FivIoProfile { + FivIoCmm *cmm; +#ifdef HAVE_LCMS2 + cmsHPROFILE profile; +#endif +}; + +GBytes * +fiv_io_profile_to_bytes(FivIoProfile *profile) +{ +#ifdef HAVE_LCMS2 + cmsUInt32Number len = 0; + (void) cmsSaveProfileToMem(profile, NULL, &len); + gchar *data = g_malloc0(len); + if (!cmsSaveProfileToMem(profile, data, &len)) { + g_free(data); + return NULL; + } + return g_bytes_new_take(data, len); +#else + (void) profile; + return NULL; +#endif +} + +#ifdef HAVE_LCMS2 + +static FivIoProfile * +fiv_io_profile_new(FivIoCmm *cmm, cmsHPROFILE profile) +{ + FivIoProfile *self = g_new0(FivIoProfile, 1); + self->cmm = g_object_ref(cmm); + self->profile = profile; + return self; +} + +#endif + +void +fiv_io_profile_free(FivIoProfile *self) +{ +#ifdef HAVE_LCMS2 + cmsCloseProfile(self->profile); +#endif + g_clear_object(&self->cmm); + g_free(self); +} + // --- Contexts ---------------------------------------------------------------- struct _FivIoCmm { @@ -47,8 +98,8 @@ G_DEFINE_TYPE(FivIoCmm, fiv_io_cmm, G_TYPE_OBJECT) static void fiv_io_cmm_finalize(GObject *gobject) { - FivIoCmm *self = FIV_IO_CMM(gobject); #ifdef HAVE_LCMS2 + FivIoCmm *self = FIV_IO_CMM(gobject); cmsDeleteContext(self->context); #endif @@ -98,7 +149,8 @@ fiv_io_cmm_get_profile(FivIoCmm *self, const void *data, size_t len) self = fiv_io_cmm_get_default(); #ifdef HAVE_LCMS2 - return cmsOpenProfileFromMemTHR(self->context, data, len); + return fiv_io_profile_new(self, + cmsOpenProfileFromMemTHR(self->context, data, len)); #else (void) data; (void) len; @@ -113,7 +165,8 @@ fiv_io_cmm_get_profile_sRGB(FivIoCmm *self) self = fiv_io_cmm_get_default(); #ifdef HAVE_LCMS2 - return cmsCreate_sRGBProfileTHR(self->context); + return fiv_io_profile_new(self, + cmsCreate_sRGBProfileTHR(self->context)); #else return NULL; #endif @@ -141,7 +194,7 @@ fiv_io_cmm_get_profile_parametric(FivIoCmm *self, cmsHPROFILE profile = cmsCreateRGBProfileTHR(self->context, &cmsWP, &cmsP, (cmsToneCurve *[3]){curve, curve, curve}); cmsFreeToneCurve(curve); - return profile; + return fiv_io_profile_new(self, profile); #else (void) gamma; (void) whitepoint; @@ -166,36 +219,6 @@ fiv_io_cmm_get_profile_from_bytes(FivIoCmm *self, GBytes *bytes) return fiv_io_cmm_get_profile(self, p, len); } -// --- Profiles ---------------------------------------------------------------- - -GBytes * -fiv_io_profile_to_bytes(FivIoProfile *profile) -{ -#ifdef HAVE_LCMS2 - cmsUInt32Number len = 0; - (void) cmsSaveProfileToMem(profile, NULL, &len); - gchar *data = g_malloc0(len); - if (!cmsSaveProfileToMem(profile, data, &len)) { - g_free(data); - return NULL; - } - return g_bytes_new_take(data, len); -#else - (void) profile; - return NULL; -#endif -} - -void -fiv_io_profile_free(FivIoProfile *self) -{ -#ifdef HAVE_LCMS2 - cmsCloseProfile(self); -#else - (void) self; -#endif -} - // --- Image loading ----------------------------------------------------------- // TODO(p): In general, try to use CAIRO_FORMAT_RGB30 or CAIRO_FORMAT_RGBA128F. @@ -250,8 +273,8 @@ fiv_io_cmm_cmyk(FivIoCmm *self, cmsHTRANSFORM transform = NULL; if (source && target) { transform = cmsCreateTransformTHR(self->context, - source, TYPE_CMYK_8_REV, target, - FIV_IO_PROFILE_ARGB32, INTENT_PERCEPTUAL, 0); + source->profile, TYPE_CMYK_8_REV, + target->profile, FIV_IO_PROFILE_ARGB32, INTENT_PERCEPTUAL, 0); } if (transform) { cmsDoTransform( @@ -284,21 +307,22 @@ fiv_io_cmm_rgb_direct(FivIoCmm *self, unsigned char *data, int w, int h, return false; #else // TODO(p): We should make this optional. - cmsHPROFILE src_fallback = NULL; + FivIoProfile *src_fallback = NULL; if (target && !source) - source = src_fallback = cmsCreate_sRGBProfileTHR(self->context); + source = src_fallback = fiv_io_cmm_get_profile_sRGB(self); cmsHTRANSFORM transform = NULL; if (source && target) { transform = cmsCreateTransformTHR(self->context, - source, source_format, target, target_format, INTENT_PERCEPTUAL, 0); + source->profile, source_format, + target->profile, target_format, INTENT_PERCEPTUAL, 0); } if (transform) { cmsDoTransform(transform, data, data, w * h); cmsDeleteTransform(transform); } if (src_fallback) - cmsCloseProfile(src_fallback); + fiv_io_profile_free(src_fallback); return transform != NULL; #endif } @@ -25,12 +25,10 @@ typedef enum _FivIoOrientation FivIoOrientation; typedef struct _FivIoRenderClosure FivIoRenderClosure; typedef struct _FivIoImage FivIoImage; +typedef struct _FivIoProfile FivIoProfile; // --- Colour management ------------------------------------------------------- -// TODO(p): Make it also possible to use Skia's skcms. -// TODO(p): Profiles might want to keep references to their CMM contexts. -typedef void *FivIoProfile; GBytes *fiv_io_profile_to_bytes(FivIoProfile *profile); void fiv_io_profile_free(FivIoProfile *self); diff --git a/meson.build b/meson.build index 155efeb..d56f402 100644 --- a/meson.build +++ b/meson.build @@ -165,7 +165,7 @@ tiff_tables = custom_target('tiff-tables.h', ) desktops = ['fiv.desktop', 'fiv-browse.desktop'] -iolib = static_library('fiv-io', 'fiv-io.c', 'fiv-io-profile.c', 'xdg.c', +iolib = static_library('fiv-io', 'fiv-io.c', 'fiv-io-cmm.c', 'xdg.c', tiff_tables, dependencies : dependencies).extract_all_objects(recursive : true) exe = executable('fiv', 'fiv.c', 'fiv-view.c', 'fiv-context-menu.c', |