aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2024-01-27 21:42:24 +0100
committerPřemysl Eric Janouch <p@janouch.name>2024-01-27 21:42:24 +0100
commit39f6be3f64a6c5c0a1ec0ee8a1d905160381b71f (patch)
treeaa5c4fef4fcc44bbb742c7b5a356e80f43f1a548
parent9dcba6ee6e9f58bb21f64926b2e50492ba11fcf7 (diff)
downloadfiv-39f6be3f64a6c5c0a1ec0ee8a1d905160381b71f.tar.gz
fiv-39f6be3f64a6c5c0a1ec0ee8a1d905160381b71f.tar.xz
fiv-39f6be3f64a6c5c0a1ec0ee8a1d905160381b71f.zip
WIP: Thread-safe colour management
-rw-r--r--fiv-io-profile.c55
-rw-r--r--fiv-io.c32
-rw-r--r--fiv-io.h39
-rw-r--r--fiv.c2
-rw-r--r--tools/benchmark-raw.c2
5 files changed, 83 insertions, 47 deletions
diff --git a/fiv-io-profile.c b/fiv-io-profile.c
index 2c6f345..4e51848 100644
--- a/fiv-io-profile.c
+++ b/fiv-io-profile.c
@@ -34,7 +34,7 @@
static bool g_broken_cms_premul;
void
-fiv_io_profile_init(void)
+fiv_io_cmm_init(void)
{
// TODO(p): Use Little CMS with contexts instead.
#ifdef HAVE_LCMS2_FAST_FLOAT
@@ -43,6 +43,13 @@ fiv_io_profile_init(void)
#endif // HAVE_LCMS2_FAST_FLOAT
}
+FivIoCmm *
+fiv_io_cmm_get_default()
+{
+ // TODO: Maintain a singleton for the NULL cmsContext.
+ return NULL;
+}
+
FivIoProfile *
fiv_io_profile_new(const void *data, size_t len)
{
@@ -180,7 +187,7 @@ trivial_cmyk_to_host_byte_order_argb(unsigned char *p, int len)
}
void
-fiv_io_profile_cmyk(
+fiv_io_cmm_cmyk(FivIoCmm *self,
FivIoImage *image, FivIoProfile *source, FivIoProfile *target)
{
#ifndef HAVE_LCMS2
@@ -204,7 +211,7 @@ fiv_io_profile_cmyk(
}
static bool
-fiv_io_profile_rgb_direct(unsigned char *data, int w, int h,
+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)
{
@@ -239,26 +246,26 @@ fiv_io_profile_rgb_direct(unsigned char *data, int w, int h,
}
static void
-fiv_io_profile_xrgb32(
+fiv_io_cmm_xrgb32(FivIoCmm *self,
FivIoImage *image, FivIoProfile *source, FivIoProfile *target)
{
- fiv_io_profile_rgb_direct(image->data, image->width, image->height,
+ fiv_io_cmm_rgb_direct(self, image->data, image->width, image->height,
source, target, FIV_IO_PROFILE_ARGB32, FIV_IO_PROFILE_ARGB32);
}
void
-fiv_io_profile_4x16le_direct(unsigned char *data,
+fiv_io_cmm_4x16le_direct(FivIoCmm *self, unsigned char *data,
int w, int h, FivIoProfile *source, FivIoProfile *target)
{
- fiv_io_profile_rgb_direct(data, w, h, source, target,
+ fiv_io_cmm_rgb_direct(self, data, w, h, source, target,
FIV_IO_PROFILE_4X16LE, FIV_IO_PROFILE_4X16LE);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
-fiv_io_profile_page(FivIoImage *page, FivIoProfile *target,
- void (*frame_cb) (FivIoImage *, FivIoProfile *, FivIoProfile *))
+fiv_io_cmm_page(FivIoCmm *self, FivIoImage *page, FivIoProfile *target,
+ void (*frame_cb) (FivIoCmm *, FivIoImage *, FivIoProfile *, FivIoProfile *))
{
FivIoProfile *source = NULL;
if (page->icc)
@@ -266,7 +273,7 @@ fiv_io_profile_page(FivIoImage *page, FivIoProfile *target,
// TODO(p): All animations need to be composited in a linear colour space.
for (FivIoImage *frame = page; frame != NULL; frame = frame->frame_next)
- frame_cb(frame, source, target);
+ frame_cb(self, frame, source, target);
if (source)
fiv_io_profile_free(source);
@@ -299,28 +306,28 @@ fiv_io_premultiply_argb32(FivIoImage *image)
(G_BYTE_ORDER == G_LITTLE_ENDIAN ? TYPE_BGRA_8_PREMUL : TYPE_ARGB_8_PREMUL)
static void
-fiv_io_profile_argb32(FivIoImage *image,
+fiv_io_cmm_argb32(FivIoCmm *self, FivIoImage *image,
FivIoProfile *source, FivIoProfile *target)
{
g_return_if_fail(image->format == CAIRO_FORMAT_ARGB32);
// TODO: With g_no_cms_premultiplication,
// this probably also needs to be wrapped in un-premultiplication.
- fiv_io_profile_rgb_direct(image->data, image->width, image->height,
+ fiv_io_cmm_rgb_direct(self, image->data, image->width, image->height,
source, target,
FIV_IO_PROFILE_ARGB32_PREMUL, FIV_IO_PROFILE_ARGB32_PREMUL);
}
void
-fiv_io_profile_argb32_premultiply(
+fiv_io_cmm_argb32_premultiply(FivIoCmm *self,
FivIoImage *image, FivIoProfile *source, FivIoProfile *target)
{
if (image->format != CAIRO_FORMAT_ARGB32) {
- fiv_io_profile_xrgb32(image, source, target);
+ fiv_io_cmm_xrgb32(self, image, source, target);
} else if (g_broken_cms_premul) {
- fiv_io_profile_xrgb32(image, source, target);
+ fiv_io_cmm_xrgb32(self, image, source, target);
fiv_io_premultiply_argb32(image);
- } else if (!fiv_io_profile_rgb_direct(image->data,
+ } else if (!fiv_io_cmm_rgb_direct(self, image->data,
image->width, image->height, source, target,
FIV_IO_PROFILE_ARGB32, FIV_IO_PROFILE_ARGB32_PREMUL)) {
g_debug("failed to create a premultiplying transform");
@@ -333,11 +340,11 @@ fiv_io_profile_argb32_premultiply(
// TODO(p): Unpremultiply, transform, repremultiply. Or require lcms2>=2.13.
#define fiv_io_profile_argb32(surface, source, target)
-static void
-fiv_io_profile_argb32_premultiply(
+void
+fiv_io_cmm_argb32_premultiply(FivIoCmm *self,
FivIoImage *image, FivIoProfile *source, FivIoProfile *target)
{
- fiv_io_profile_xrgb32(image, source, target);
+ fiv_io_cmm_xrgb32(self, image, source, target);
fiv_io_premultiply_argb32(image);
}
@@ -346,7 +353,7 @@ fiv_io_profile_argb32_premultiply(
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void
-fiv_io_profile_any(
+fiv_io_cmm_any(FivIoCmm *self,
FivIoImage *image, FivIoProfile *source, FivIoProfile *target)
{
// TODO(p): Ensure we do colour management early enough, so that
@@ -354,9 +361,9 @@ fiv_io_profile_any(
// and also for correct alpha compositing.
switch (image->format) {
break; case CAIRO_FORMAT_RGB24:
- fiv_io_profile_xrgb32(image, source, target);
+ fiv_io_cmm_xrgb32(self, image, source, target);
break; case CAIRO_FORMAT_ARGB32:
- fiv_io_profile_argb32(image, source, target);
+ fiv_io_cmm_argb32(self, image, source, target);
break; default:
g_debug("CM attempted on an unsupported surface format");
}
@@ -364,12 +371,12 @@ fiv_io_profile_any(
// TODO(p): Offer better integration, upgrade the bit depth if appropriate.
FivIoImage *
-fiv_io_profile_finalize(FivIoImage *image, FivIoProfile *target)
+fiv_io_cmm_finalize(FivIoCmm *self, FivIoImage *image, FivIoProfile *target)
{
if (!target)
return image;
for (FivIoImage *page = image; page != NULL; page = page->page_next)
- fiv_io_profile_page(page, target, fiv_io_profile_any);
+ fiv_io_cmm_page(self, page, target, fiv_io_cmm_any);
return image;
}
diff --git a/fiv-io.c b/fiv-io.c
index 4fd3d29..f16a245 100644
--- a/fiv-io.c
+++ b/fiv-io.c
@@ -447,11 +447,12 @@ load_wuffs_frame(struct load_wuffs_frame_context *ctx, GError **error)
if (ctx->target) {
if (ctx->expand_16_float || ctx->pack_16_10) {
- fiv_io_profile_4x16le_direct(
+ fiv_io_cmm_4x16le_direct(fiv_io_cmm_get_default(),
targetbuf, ctx->width, ctx->height, ctx->source, ctx->target);
// The first one premultiplies below, the second doesn't need to.
} else {
- fiv_io_profile_argb32_premultiply(image, ctx->source, ctx->target);
+ fiv_io_cmm_argb32_premultiply(fiv_io_cmm_get_default(),
+ image, ctx->source, ctx->target);
}
}
@@ -1263,9 +1264,11 @@ load_jpeg_finalize(FivIoImage *image, bool cmyk,
g_bytes_get_data(image->exif, NULL), g_bytes_get_size(image->exif));
if (cmyk)
- fiv_io_profile_cmyk(image, source, ctx->screen_profile);
+ fiv_io_cmm_cmyk(fiv_io_cmm_get_default(),
+ image, source, ctx->screen_profile);
else
- fiv_io_profile_any(image, source, ctx->screen_profile);
+ fiv_io_cmm_any(fiv_io_cmm_get_default(),
+ image, source, ctx->screen_profile);
if (source)
fiv_io_profile_free(source);
@@ -1666,7 +1669,8 @@ open_libwebp(
WebPDemuxDelete(demux);
if (ctx->screen_profile)
- fiv_io_profile_argb32_premultiply_page(result, ctx->screen_profile);
+ fiv_io_cmm_argb32_premultiply_page(fiv_io_cmm_get_default(),
+ result, ctx->screen_profile);
fail:
WebPFreeDecBuffer(&config.output);
@@ -2049,7 +2053,8 @@ open_libraw(
out:
libraw_close(iprc);
- return fiv_io_profile_finalize(result, ctx->screen_profile);
+ return fiv_io_cmm_finalize(fiv_io_cmm_get_default(),
+ result, ctx->screen_profile);
}
#endif // HAVE_LIBRAW ---------------------------------------------------------
@@ -2226,7 +2231,8 @@ load_librsvg_render_internal(FivIoRenderClosureLibrsvg *self, double scale,
fiv_io_image_unref(image);
return NULL;
}
- return fiv_io_profile_finalize(image, target);
+ return fiv_io_cmm_finalize(fiv_io_cmm_get_default(),
+ image, target);
}
static FivIoImage *
@@ -2600,7 +2606,8 @@ open_libheif(
g_free(ids);
fail_read:
heif_context_free(ctx);
- return fiv_io_profile_finalize(result, ioctx->screen_profile);
+ return fiv_io_cmm_finalize(fiv_io_cmm_get_default(),
+ result, ioctx->screen_profile);
}
#endif // HAVE_LIBHEIF --------------------------------------------------------
@@ -2831,7 +2838,8 @@ fail:
TIFFSetWarningHandlerExt(whe);
TIFFSetErrorHandler(eh);
TIFFSetWarningHandler(wh);
- return fiv_io_profile_finalize(result, ctx->screen_profile);
+ return fiv_io_cmm_finalize(fiv_io_cmm_get_default(),
+ result, ctx->screen_profile);
}
#endif // HAVE_LIBTIFF --------------------------------------------------------
@@ -2926,9 +2934,11 @@ open_gdkpixbuf(
g_object_unref(pixbuf);
if (custom_argb32)
- fiv_io_profile_argb32_premultiply_page(image, ctx->screen_profile);
+ fiv_io_cmm_argb32_premultiply_page(fiv_io_cmm_get_default(),
+ image, ctx->screen_profile);
else
- image = fiv_io_profile_finalize(image, ctx->screen_profile);
+ image = fiv_io_cmm_finalize(fiv_io_cmm_get_default(),
+ image, ctx->screen_profile);
return image;
}
diff --git a/fiv-io.h b/fiv-io.h
index bb92033..26e1b93 100644
--- a/fiv-io.h
+++ b/fiv-io.h
@@ -28,7 +28,7 @@ typedef struct _FivIoImage FivIoImage;
// --- Colour management -------------------------------------------------------
-void fiv_io_profile_init(void);
+void fiv_io_cmm_init(void);
// TODO(p): Make it also possible to use Skia's skcms.
typedef void *FivIoProfile;
@@ -43,23 +43,42 @@ void fiv_io_profile_free(FivIoProfile *self);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+#define FIV_TYPE_IO_CMM (fiv_io_cmm_get_type())
+G_DECLARE_FINAL_TYPE(FivIoCmm, fiv_io_cmm, FIV, CMM, GObject)
+
+FivIoCmm *fiv_io_cmm_get_default();
+
+/*
+FivIoProfile *fiv_io_cmm_get_profile(
+ FivIoCmm *self, const void *data, size_t len);
+FivIoProfile *fiv_io_cmm_get_profile_from_bytes(FivIoCmm *self, GBytes *bytes);
+FivIoProfile *fiv_io_cmm_get_profile_sRGB(FivIoCmm *self);
+FivIoProfile *fiv_io_cmm_get_profile_sRGB_gamma(FivIoCmm *self, double gamma);
+FivIoProfile *fiv_io_cmm_get_profile_parametric(
+ FivIoCmm *self, double gamma, double whitepoint[2], double primaries[6]);
+*/
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
void fiv_io_premultiply_argb32(FivIoImage *image);
-void fiv_io_profile_cmyk(
+void fiv_io_cmm_cmyk(FivIoCmm *self,
FivIoImage *image, FivIoProfile *source, FivIoProfile *target);
-void fiv_io_profile_4x16le_direct(unsigned char *data,
+void fiv_io_cmm_4x16le_direct(FivIoCmm *self, unsigned char *data,
int w, int h, FivIoProfile *source, FivIoProfile *target);
-void fiv_io_profile_argb32_premultiply(
+void fiv_io_cmm_argb32_premultiply(FivIoCmm *self,
FivIoImage *image, FivIoProfile *source, FivIoProfile *target);
-void fiv_io_profile_page(FivIoImage *page, FivIoProfile *target,
- void (*frame_cb) (FivIoImage *, FivIoProfile *, FivIoProfile *));
-#define fiv_io_profile_argb32_premultiply_page(page, target) \
- fiv_io_profile_page((page), (target), fiv_io_profile_argb32_premultiply)
+void fiv_io_cmm_page(FivIoCmm *self, FivIoImage *page, FivIoProfile *target,
+ void (*frame_cb) (FivIoCmm *,
+ FivIoImage *, FivIoProfile *, FivIoProfile *));
+#define fiv_io_cmm_argb32_premultiply_page(cmm, page, target) \
+ fiv_io_cmm_page((cmm), (page), (target), fiv_io_cmm_argb32_premultiply)
-void fiv_io_profile_any(
+void fiv_io_cmm_any(FivIoCmm *self,
FivIoImage *image, FivIoProfile *source, FivIoProfile *target);
-FivIoImage *fiv_io_profile_finalize(FivIoImage *image, FivIoProfile *target);
+FivIoImage *fiv_io_cmm_finalize(
+ FivIoCmm *self, FivIoImage *image, FivIoProfile *target);
// --- Loading -----------------------------------------------------------------
diff --git a/fiv.c b/fiv.c
index f4f612e..1514d4a 100644
--- a/fiv.c
+++ b/fiv.c
@@ -2583,7 +2583,7 @@ on_app_handle_local_options(G_GNUC_UNUSED GApplication *app,
return 0;
}
- fiv_io_profile_init();
+ fiv_io_cmm_init();
// Normalize all arguments to URIs, and run thumbnailing modes first.
for (gsize i = 0; o.args && o.args[i]; i++) {
diff --git a/tools/benchmark-raw.c b/tools/benchmark-raw.c
index 9e1fe41..e1e6ea8 100644
--- a/tools/benchmark-raw.c
+++ b/tools/benchmark-raw.c
@@ -408,7 +408,7 @@ main(int argc, char *argv[])
// We don't need to call gdk_cairo_surface_create_from_pixbuf() here,
// so don't bother initializing GDK.
- fiv_io_profile_init();
+ fiv_io_cmm_init();
// A mode to just extract all thumbnails to files for closer inspection.
extract_mode = !!getenv("BENCHMARK_RAW_EXTRACT");