With newer Little CMS, colour manage ARGB surfaces

This commit is contained in:
Přemysl Eric Janouch 2023-06-06 12:51:04 +02:00
parent 6cc4ca1f44
commit d6e79cf976
Signed by: p
GPG Key ID: A0420B94F92B9493
1 changed files with 52 additions and 27 deletions

View File

@ -429,30 +429,6 @@ fiv_io_profile_page(cairo_surface_t *page, FivIoProfile target,
fiv_io_profile_free(source); 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 static void
fiv_io_premultiply_argb32(cairo_surface_t *surface) fiv_io_premultiply_argb32(cairo_surface_t *surface)
{ {
@ -480,13 +456,27 @@ fiv_io_premultiply_argb32(cairo_surface_t *surface)
#define FIV_IO_PROFILE_ARGB32_PREMUL \ #define FIV_IO_PROFILE_ARGB32_PREMUL \
(G_BYTE_ORDER == G_LITTLE_ENDIAN ? TYPE_BGRA_8_PREMUL : TYPE_ARGB_8_PREMUL) (G_BYTE_ORDER == G_LITTLE_ENDIAN ? TYPE_BGRA_8_PREMUL : TYPE_ARGB_8_PREMUL)
static void
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 static void
fiv_io_profile_argb32_premultiply(cairo_surface_t *surface, fiv_io_profile_argb32_premultiply(cairo_surface_t *surface,
FivIoProfile source, FivIoProfile target) FivIoProfile source, FivIoProfile target)
{ {
unsigned char *data = cairo_image_surface_get_data(surface);
int w = cairo_image_surface_get_width(surface); int w = cairo_image_surface_get_width(surface);
int h = cairo_image_surface_get_height(surface); int h = cairo_image_surface_get_height(surface);
unsigned char *data = cairo_image_surface_get_data(surface);
if (cairo_image_surface_get_format(surface) != CAIRO_FORMAT_ARGB32) { if (cairo_image_surface_get_format(surface) != CAIRO_FORMAT_ARGB32) {
fiv_io_profile_xrgb32_direct(data, w, h, source, target); fiv_io_profile_xrgb32_direct(data, w, h, source, target);
} else if (!fiv_io_profile_rgb_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 #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 static void
fiv_io_profile_argb32_premultiply_page( fiv_io_profile_argb32_premultiply_page(
cairo_surface_t *page, FivIoProfile target) 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; for (cairo_surface_t *frame = page; frame != NULL;
frame = cairo_surface_get_user_data(frame, &fiv_io_key_frame_next)) 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 #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 ------------------------------------------------------------------- // --- Wuffs -------------------------------------------------------------------
static bool static bool
@ -1420,7 +1445,7 @@ load_jpeg_finalize(cairo_surface_t *surface, bool cmyk,
if (cmyk) if (cmyk)
fiv_io_profile_cmyk(surface, source, ctx->screen_profile); fiv_io_profile_cmyk(surface, source, ctx->screen_profile);
else else
fiv_io_profile_xrgb32(surface, source, ctx->screen_profile); fiv_io_profile_any(surface, source, ctx->screen_profile);
if (source) if (source)
fiv_io_profile_free(source); fiv_io_profile_free(source);