aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2023-06-06 12:51:04 +0200
committerPřemysl Eric Janouch <p@janouch.name>2023-06-06 13:01:38 +0200
commitd6e79cf976befd0cc1d158c440106154554bb52b (patch)
tree6a13bff64e88a2a6daff6c9a47c1857e227c2232
parent6cc4ca1f44278c9821675dd5d1f34aa442c6ce7d (diff)
downloadfiv-d6e79cf976befd0cc1d158c440106154554bb52b.tar.gz
fiv-d6e79cf976befd0cc1d158c440106154554bb52b.tar.xz
fiv-d6e79cf976befd0cc1d158c440106154554bb52b.zip
With newer Little CMS, colour manage ARGB surfaces
-rw-r--r--fiv-io.c79
1 files changed, 52 insertions, 27 deletions
diff --git a/fiv-io.c b/fiv-io.c
index 27c8107..6722019 100644
--- a/fiv-io.c
+++ b/fiv-io.c
@@ -429,30 +429,6 @@ fiv_io_profile_page(cairo_surface_t *page, FivIoProfile target,
fiv_io_profile_free(source);
}
-#define fiv_io_profile_xrgb32_page(page, target) \
- fiv_io_profile_page((page), (target), fiv_io_profile_xrgb32)
-
-// TODO(p): Offer better integration, upgrade the bit depth if appropriate.
-static cairo_surface_t *
-fiv_io_profile_finalize(cairo_surface_t *image, FivIoProfile target)
-{
- if (!image || !target)
- return image;
-
- for (cairo_surface_t *page = image; page != NULL;
- page = cairo_surface_get_user_data(page, &fiv_io_key_page_next)) {
- // TODO(p): 1. un/premultiply ARGB, 2. do colour management
- // early enough, so that no avoidable increase of quantization error
- // occurs beforehands, and also for correct alpha compositing.
- // FIXME: This assumes that if the first frame is opaque, they all are.
- if (cairo_image_surface_get_format(page) == CAIRO_FORMAT_RGB24)
- fiv_io_profile_xrgb32_page(page, target);
- }
- return image;
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
static void
fiv_io_premultiply_argb32(cairo_surface_t *surface)
{
@@ -481,12 +457,26 @@ fiv_io_premultiply_argb32(cairo_surface_t *surface)
(G_BYTE_ORDER == G_LITTLE_ENDIAN ? TYPE_BGRA_8_PREMUL : TYPE_ARGB_8_PREMUL)
static void
-fiv_io_profile_argb32_premultiply(cairo_surface_t *surface,
+fiv_io_profile_argb32(cairo_surface_t *surface,
FivIoProfile source, FivIoProfile target)
{
+ g_return_if_fail(
+ cairo_image_surface_get_format(surface) == CAIRO_FORMAT_ARGB32);
+
+ unsigned char *data = cairo_image_surface_get_data(surface);
int w = cairo_image_surface_get_width(surface);
int h = cairo_image_surface_get_height(surface);
+ fiv_io_profile_rgb_direct(data, w, h, source, target,
+ FIV_IO_PROFILE_ARGB32_PREMUL, FIV_IO_PROFILE_ARGB32_PREMUL);
+}
+
+static void
+fiv_io_profile_argb32_premultiply(cairo_surface_t *surface,
+ FivIoProfile source, FivIoProfile target)
+{
unsigned char *data = cairo_image_surface_get_data(surface);
+ int w = cairo_image_surface_get_width(surface);
+ int h = cairo_image_surface_get_height(surface);
if (cairo_image_surface_get_format(surface) != CAIRO_FORMAT_ARGB32) {
fiv_io_profile_xrgb32_direct(data, w, h, source, target);
} else if (!fiv_io_profile_rgb_direct(data, w, h, source, target,
@@ -501,11 +491,14 @@ fiv_io_profile_argb32_premultiply(cairo_surface_t *surface,
#else // ! HAVE_LCMS2 || LCMS_VERSION < 2130
+// 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_page(
cairo_surface_t *page, FivIoProfile target)
{
- fiv_io_profile_xrgb32_page(page, target);
+ fiv_io_profile_page(page, target, fiv_io_profile_xrgb32);
for (cairo_surface_t *frame = page; frame != NULL;
frame = cairo_surface_get_user_data(frame, &fiv_io_key_frame_next))
@@ -514,6 +507,38 @@ fiv_io_profile_argb32_premultiply_page(
#endif // ! HAVE_LCMS2 || LCMS_VERSION < 2130
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+static void
+fiv_io_profile_any(cairo_surface_t *surface,
+ FivIoProfile source, FivIoProfile target)
+{
+ // TODO(p): Ensure we do colour management early enough, so that
+ // no avoidable increase of quantization error occurs beforehands,
+ // and also for correct alpha compositing.
+ switch (cairo_image_surface_get_format(surface)) {
+ break; case CAIRO_FORMAT_RGB24:
+ fiv_io_profile_xrgb32(surface, source, target);
+ break; case CAIRO_FORMAT_ARGB32:
+ fiv_io_profile_argb32(surface, source, target);
+ break; default:
+ g_debug("CM attempted on an unsupported surface format");
+ }
+}
+
+// TODO(p): Offer better integration, upgrade the bit depth if appropriate.
+static cairo_surface_t *
+fiv_io_profile_finalize(cairo_surface_t *image, FivIoProfile target)
+{
+ if (!target)
+ return image;
+
+ for (cairo_surface_t *page = image; page != NULL;
+ page = cairo_surface_get_user_data(page, &fiv_io_key_page_next))
+ fiv_io_profile_page(page, target, fiv_io_profile_any);
+ return image;
+}
+
// --- Wuffs -------------------------------------------------------------------
static bool
@@ -1420,7 +1445,7 @@ load_jpeg_finalize(cairo_surface_t *surface, bool cmyk,
if (cmyk)
fiv_io_profile_cmyk(surface, source, ctx->screen_profile);
else
- fiv_io_profile_xrgb32(surface, source, ctx->screen_profile);
+ fiv_io_profile_any(surface, source, ctx->screen_profile);
if (source)
fiv_io_profile_free(source);