diff options
author | Přemysl Eric Janouch <p@janouch.name> | 2021-12-26 03:10:50 +0100 |
---|---|---|
committer | Přemysl Eric Janouch <p@janouch.name> | 2021-12-26 03:25:38 +0100 |
commit | 2f993502fc6584a5877b300a1353cabf58c4e0e9 (patch) | |
tree | 8cc1400537e0ff544cdede782d7a523e2b06c293 | |
parent | e5b1a1861cb0e69411b4ebbfaadb235b9bd8a001 (diff) | |
download | fiv-2f993502fc6584a5877b300a1353cabf58c4e0e9.tar.gz fiv-2f993502fc6584a5877b300a1353cabf58c4e0e9.tar.xz fiv-2f993502fc6584a5877b300a1353cabf58c4e0e9.zip |
Make use of gAMA and sRGB PNG chunks
Neither EoG nor gThumb handle this correctly.
-rw-r--r-- | fiv-io.c | 49 |
1 files changed, 45 insertions, 4 deletions
@@ -198,6 +198,30 @@ fiv_io_profile_new_sRGB(void) #endif } +FivIoProfile +fiv_io_profile_new_sRGB_gamma(double gamma) +{ +#ifdef HAVE_LCMS2 + // TODO(p): Make sure to use the library in a thread-safe manner. + cmsContext context = NULL; + + static const cmsCIExyY D65 = {0.3127, 0.3290, 1.0}; + static const cmsCIExyYTRIPLE primaries = { + {0.6400, 0.3300, 1.0}, {0.3000, 0.6000, 1.0}, {0.1500, 0.0600, 1.0}}; + cmsToneCurve *curve = cmsBuildGamma(context, gamma); + if (!curve) + return NULL; + + cmsHPROFILE profile = cmsCreateRGBProfileTHR( + context, &D65, &primaries, (cmsToneCurve *[3]){curve, curve, curve}); + cmsFreeToneCurve(curve); + return profile; +#else + (void) gamma; + return NULL; +#endif +} + static FivIoProfile fiv_io_profile_new_from_bytes(GBytes *bytes) { @@ -740,13 +764,17 @@ open_wuffs(wuffs_base__image_decoder *dec, wuffs_base__io_buffer src, struct load_wuffs_frame_context ctx = { .dec = dec, .src = &src, .target = profile}; - // TODO(p): PNG also has sRGB and gAMA, as well as text chunks (Wuffs #58). - // The former two use WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA_PARSED. + // TODO(p): PNG text chunks (Wuffs #58). wuffs_base__image_decoder__set_report_metadata( ctx.dec, WUFFS_BASE__FOURCC__EXIF, true); wuffs_base__image_decoder__set_report_metadata( ctx.dec, WUFFS_BASE__FOURCC__ICCP, true); + wuffs_base__image_decoder__set_report_metadata( + ctx.dec, WUFFS_BASE__FOURCC__SRGB, true); + wuffs_base__image_decoder__set_report_metadata( + ctx.dec, WUFFS_BASE__FOURCC__GAMA, true); + double gamma = 0; while (true) { wuffs_base__status status = wuffs_base__image_decoder__decode_image_config( @@ -786,6 +814,14 @@ open_wuffs(wuffs_base__image_decoder *dec, wuffs_base__io_buffer src, } ctx.meta_xmp = bytes; continue; + + case WUFFS_BASE__FOURCC__SRGB: + gamma = 2.2; + break; + case WUFFS_BASE__FOURCC__GAMA: + gamma = 1e5 / + wuffs_base__more_information__metadata_parsed__gama(&minfo); + break; } g_bytes_unref(bytes); @@ -805,8 +841,13 @@ open_wuffs(wuffs_base__image_decoder *dec, wuffs_base__io_buffer src, goto fail; } - if (ctx.target && ctx.meta_iccp) - ctx.source = fiv_io_profile_new_from_bytes(ctx.meta_iccp); + // TODO(p): Improve our simplistic PNG handling of: gAMA, cHRM, sRGB. + if (ctx.target) { + if (ctx.meta_iccp) + ctx.source = fiv_io_profile_new_from_bytes(ctx.meta_iccp); + else if (isfinite(gamma) && gamma > 0) + ctx.source = fiv_io_profile_new_sRGB_gamma(gamma); + } // Wuffs maps tRNS to BGRA in `decoder.decode_trns?`, we should be fine. // wuffs_base__pixel_format__transparency() doesn't reflect the image file. |