diff options
Diffstat (limited to 'fiv-io-profile.c')
-rw-r--r-- | fiv-io-profile.c | 109 |
1 files changed, 85 insertions, 24 deletions
diff --git a/fiv-io-profile.c b/fiv-io-profile.c index 44eb0bf..387b201 100644 --- a/fiv-io-profile.c +++ b/fiv-io-profile.c @@ -30,31 +30,75 @@ #include <lcms2_fast_float.h> #endif // HAVE_LCMS2_FAST_FLOAT -// https://github.com/mm2/Little-CMS/issues/430 -static bool g_broken_cms_premul; +// --- Contexts ---------------------------------------------------------------- -void -fiv_io_cmm_init(void) +struct _FivIoCmm { + GObject parent_instance; +#ifdef HAVE_LCMS2 + cmsContext context; + + // https://github.com/mm2/Little-CMS/issues/430 + gboolean broken_premul; +#endif +}; + +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 + cmsDeleteContext(self->context); +#endif + + G_OBJECT_CLASS(fiv_io_cmm_parent_class)->finalize(gobject); +} + +static void +fiv_io_cmm_class_init(FivIoCmmClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS(klass); + object_class->finalize = fiv_io_cmm_finalize; +} + +static void +fiv_io_cmm_init(FivIoCmm *self) { - // TODO(p): Use Little CMS with contexts instead. + (void) self; + +#ifdef HAVE_LCMS2 + self->context = cmsCreateContext(NULL, self); +#endif #ifdef HAVE_LCMS2_FAST_FLOAT - if (cmsPluginTHR(NULL, cmsFastFloatExtensions())) - g_broken_cms_premul = LCMS_VERSION <= 2160; + if (cmsPluginTHR(self->context, cmsFastFloatExtensions())) + self->broken_premul = LCMS_VERSION <= 2160; #endif // HAVE_LCMS2_FAST_FLOAT } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + FivIoCmm * fiv_io_cmm_get_default() { - // TODO: Maintain a singleton for the NULL cmsContext. - return NULL; + static gsize initialization_value = 0; + static FivIoCmm *default_ = NULL; + if (g_once_init_enter(&initialization_value)) { + gsize setup_value = 1; + default_ = g_object_new(FIV_TYPE_IO_CMM, NULL); + g_once_init_leave(&initialization_value, setup_value); + } + return default_; } FivIoProfile * fiv_io_cmm_get_profile(FivIoCmm *self, const void *data, size_t len) { + if (!self) + self = fiv_io_cmm_get_default(); + #ifdef HAVE_LCMS2 - return cmsOpenProfileFromMemTHR(NULL, data, len); + return cmsOpenProfileFromMemTHR(self->context, data, len); #else (void) data; (void) len; @@ -65,8 +109,11 @@ fiv_io_cmm_get_profile(FivIoCmm *self, const void *data, size_t len) FivIoProfile * fiv_io_cmm_get_profile_sRGB(FivIoCmm *self) { + if (!self) + self = fiv_io_cmm_get_default(); + #ifdef HAVE_LCMS2 - return cmsCreate_sRGBProfileTHR(NULL); + return cmsCreate_sRGBProfileTHR(self->context); #else return NULL; #endif @@ -76,10 +123,10 @@ FivIoProfile * fiv_io_cmm_get_profile_parametric(FivIoCmm *self, double gamma, double whitepoint[2], double primaries[6]) { -#ifdef HAVE_LCMS2 - // TODO(p): Make sure to use the library in a thread-safe manner. - cmsContext context = NULL; + if (!self) + self = fiv_io_cmm_get_default(); +#ifdef HAVE_LCMS2 const cmsCIExyY cmsWP = {whitepoint[0], whitepoint[1], 1.0}; const cmsCIExyYTRIPLE cmsP = { {primaries[0], primaries[1], 1.0}, @@ -87,12 +134,12 @@ fiv_io_cmm_get_profile_parametric(FivIoCmm *self, {primaries[4], primaries[5], 1.0}, }; - cmsToneCurve *curve = cmsBuildGamma(context, gamma); + cmsToneCurve *curve = cmsBuildGamma(self->context, gamma); if (!curve) return NULL; - cmsHPROFILE profile = cmsCreateRGBProfileTHR( - context, &cmsWP, &cmsP, (cmsToneCurve *[3]){curve, curve, curve}); + cmsHPROFILE profile = cmsCreateRGBProfileTHR(self->context, + &cmsWP, &cmsP, (cmsToneCurve *[3]){curve, curve, curve}); cmsFreeToneCurve(curve); return profile; #else @@ -119,6 +166,8 @@ 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) { @@ -190,13 +239,18 @@ void fiv_io_cmm_cmyk(FivIoCmm *self, FivIoImage *image, FivIoProfile *source, FivIoProfile *target) { + if (!self) + self = fiv_io_cmm_get_default(); + #ifndef HAVE_LCMS2 + (void) self; (void) source; (void) target; #else cmsHTRANSFORM transform = NULL; if (source && target) { - transform = cmsCreateTransformTHR(NULL, source, TYPE_CMYK_8_REV, target, + transform = cmsCreateTransformTHR(self->context, + source, TYPE_CMYK_8_REV, target, FIV_IO_PROFILE_ARGB32, INTENT_PERCEPTUAL, 0); } if (transform) { @@ -215,7 +269,11 @@ fiv_io_cmm_rgb_direct(FivIoCmm *self, unsigned char *data, int w, int h, FivIoProfile *source, FivIoProfile *target, uint32_t source_format, uint32_t target_format) { + if (!self) + self = fiv_io_cmm_get_default(); + #ifndef HAVE_LCMS2 + (void) self; (void) data; (void) w; (void) h; @@ -228,11 +286,11 @@ fiv_io_cmm_rgb_direct(FivIoCmm *self, unsigned char *data, int w, int h, // TODO(p): We should make this optional. cmsHPROFILE src_fallback = NULL; if (target && !source) - source = src_fallback = cmsCreate_sRGBProfileTHR(NULL); + source = src_fallback = cmsCreate_sRGBProfileTHR(self->context); cmsHTRANSFORM transform = NULL; if (source && target) { - transform = cmsCreateTransformTHR(NULL, + transform = cmsCreateTransformTHR(self->context, source, source_format, target, target_format, INTENT_PERCEPTUAL, 0); } if (transform) { @@ -311,7 +369,7 @@ fiv_io_cmm_argb32(FivIoCmm *self, FivIoImage *image, { g_return_if_fail(image->format == CAIRO_FORMAT_ARGB32); - // TODO: With g_no_cms_premultiplication, + // TODO: With self->broken_premul, // this probably also needs to be wrapped in un-premultiplication. fiv_io_cmm_rgb_direct(self, image->data, image->width, image->height, source, target, @@ -322,9 +380,12 @@ void fiv_io_cmm_argb32_premultiply(FivIoCmm *self, FivIoImage *image, FivIoProfile *source, FivIoProfile *target) { + if (!self) + self = fiv_io_cmm_get_default(); + if (image->format != CAIRO_FORMAT_ARGB32) { fiv_io_cmm_xrgb32(self, image, source, target); - } else if (g_broken_cms_premul) { + } else if (self->broken_premul) { fiv_io_cmm_xrgb32(self, image, source, target); fiv_io_premultiply_argb32(image); } else if (!fiv_io_cmm_rgb_direct(self, image->data, @@ -338,7 +399,7 @@ fiv_io_cmm_argb32_premultiply(FivIoCmm *self, #else // ! HAVE_LCMS2 || LCMS_VERSION < 2130 // TODO(p): Unpremultiply, transform, repremultiply. Or require lcms2>=2.13. -#define fiv_io_profile_argb32(surface, source, target) +#define fiv_io_cmm_argb32(self, image, source, target) void fiv_io_cmm_argb32_premultiply(FivIoCmm *self, @@ -371,7 +432,7 @@ fiv_io_cmm_any(FivIoCmm *self, // TODO(p): Offer better integration, upgrade the bit depth if appropriate. FivIoImage * -fiv_io_cmm_finalize(FivIoCmm *self, FivIoImage *image, FivIoProfile *target) +fiv_io_cmm_finish(FivIoCmm *self, FivIoImage *image, FivIoProfile *target) { if (!target) return image; |