aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2024-01-27 23:43:06 +0100
committerPřemysl Eric Janouch <p@janouch.name>2024-01-28 00:09:15 +0100
commit04b0b0caf46f9b0f408b7c4d2774f96335c487a6 (patch)
treed9e5634954488cd983c3475c5531b6549993b169
parent250f2f0f758a5f3ea0f3174843dbf55fc73b1370 (diff)
downloadfiv-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.h4
-rw-r--r--meson.build2
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
}
diff --git a/fiv-io.h b/fiv-io.h
index 94a15e1..d86c80a 100644
--- a/fiv-io.h
+++ b/fiv-io.h
@@ -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',