Partially colour-manage TIFFs

This commit is contained in:
Přemysl Eric Janouch 2021-12-29 02:46:19 +01:00
parent 0110e0a5d2
commit 4832474c5f
Signed by: p
GPG Key ID: A0420B94F92B9493

View File

@ -2082,8 +2082,10 @@ load_libtiff_directory(TIFF *tiff, GError **error)
goto fail; goto fail;
} }
surface = cairo_image_surface_create( surface = cairo_image_surface_create(image.alpha != EXTRASAMPLE_UNSPECIFIED
CAIRO_FORMAT_ARGB32, image.width, image.height); ? CAIRO_FORMAT_ARGB32
: CAIRO_FORMAT_RGB24,
image.width, image.height);
image.req_orientation = ORIENTATION_LEFTTOP; image.req_orientation = ORIENTATION_LEFTTOP;
uint32_t *raster = (uint32_t *) cairo_image_surface_get_data(surface); uint32_t *raster = (uint32_t *) cairo_image_surface_get_data(surface);
@ -2092,15 +2094,15 @@ load_libtiff_directory(TIFF *tiff, GError **error)
goto fail; goto fail;
} }
// Needs to be converted from ABGR to alpha-premultiplied ARGB for Cairo. // Needs to be byte-swapped from ABGR to alpha-premultiplied ARGB for Cairo.
for (uint32_t i = image.width * image.height; i--;) { for (uint64_t i = image.width * image.height; i--; ) {
uint32_t pixel = raster[i], uint32_t pixel = raster[i];
a = TIFFGetA(pixel), raster[i] = TIFFGetA(pixel) << 24 | TIFFGetR(pixel) << 16 |
b = TIFFGetB(pixel) * a / 255, TIFFGetG(pixel) << 8 | TIFFGetB(pixel);
g = TIFFGetG(pixel) * a / 255,
r = TIFFGetR(pixel) * a / 255;
raster[i] = a << 24 | r << 16 | g << 8 | b;
} }
// It seems that neither GIMP nor Photoshop use unassociated alpha.
if (image.alpha == EXTRASAMPLE_UNASSALPHA)
fiv_io_premultiply_argb32(surface);
cairo_surface_mark_dirty(surface); cairo_surface_mark_dirty(surface);
// XXX: The whole file is essentially an Exif, any ideas? // XXX: The whole file is essentially an Exif, any ideas?
@ -2134,7 +2136,8 @@ fail:
} }
static cairo_surface_t * static cairo_surface_t *
open_libtiff(const gchar *data, gsize len, const gchar *path, GError **error) open_libtiff(const gchar *data, gsize len, const gchar *path,
FivIoProfile target, GError **error)
{ {
// Both kinds of handlers are called, redirect everything. // Both kinds of handlers are called, redirect everything.
TIFFErrorHandler eh = TIFFSetErrorHandler(NULL); TIFFErrorHandler eh = TIFFSetErrorHandler(NULL);
@ -2202,7 +2205,11 @@ fail:
TIFFSetWarningHandlerExt(whe); TIFFSetWarningHandlerExt(whe);
TIFFSetErrorHandler(eh); TIFFSetErrorHandler(eh);
TIFFSetWarningHandler(wh); TIFFSetWarningHandler(wh);
return result;
// TODO(p): Colour management even for un/associated alpha channels.
// Note that TIFF has a number of fields that an ICC profile can be
// constructed from--it's not a good idea to blindly assume sRGB.
return fiv_io_profile_finalize(result, target);
} }
#endif // HAVE_LIBTIFF -------------------------------------------------------- #endif // HAVE_LIBTIFF --------------------------------------------------------
@ -2415,7 +2422,7 @@ fiv_io_open_from_data(const char *data, size_t len, const gchar *path,
#endif // HAVE_LIBHEIF -------------------------------------------------------- #endif // HAVE_LIBHEIF --------------------------------------------------------
#ifdef HAVE_LIBTIFF //--------------------------------------------------------- #ifdef HAVE_LIBTIFF //---------------------------------------------------------
// This needs to be positioned after LibRaw. // This needs to be positioned after LibRaw.
if ((surface = open_libtiff(data, len, path, error))) if ((surface = open_libtiff(data, len, path, profile, error)))
break; break;
if (error) { if (error) {
g_debug("%s", (*error)->message); g_debug("%s", (*error)->message);