-
Notifications
You must be signed in to change notification settings - Fork 3.3k
LibGfx/ICC+icc: Add built-in identity LAB profile using mft1 (Lut8TagData), implement conversion from PCS to it #26452
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This makes it clearer what they do. No behavior change.
Clarify two spec references, fix a copy-pasto.
No behavior change.
This will be used to implement conversion from PCS to LUT-based profiles (Lut16TagType, Lut8TagType, LutBToATagData with a CLUT). This is our third implementation of ND interpolation: * This file already as a ND->3D version * This new version, which does 3D->ND * SampledFunction::evaluate() in LibPDF's Function.cpp does ND->ND, at the expense of allocations (but since it's in an object, it can reuse a vector across calls) I think eventually we instead want a fast 4D->4D version that is always enough in practice, and a generinc ND->ND version, and use those two in both LibPDF and here. But let's get something working first.
...and make it slightly more general. No behavior change.
This profile idenity-maps PCSLAB to CIELAB.
This allows converting byte-encoded LAB values to PCS:
% echo '255, 0, 255' | \
icc -n LAB --stdin-u8-to-pcs
pcslab(100, -128, 127)
It can also be written to a file, for other tools to use it:
icc -n LAB --reencode-to serenity-LAB.icc
(...or you can then run `icc serenity-LAB.icc` instead of
`icc -n LAB` if you want to dump it from a file instead of from
memory, for some reason.)
Makes this work:
% echo 'pcslab(100, -128, 127)' | \
Build/lagom/bin/icc -n LAB --stdin-u8-from-pcs
255, 0, 255
Also makes it possible to write a roundtrip test for the
IdentityLAB() profile, so do so.
242e0a6 to
5d443c8
Compare
LucasChollet
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice!
|
|
||
| static void test_roundtrip(Gfx::ICC::Profile const& profile) | ||
| { | ||
| // Ideally this would be 1, but that makes tests take a few minutes on fast machine. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could use GEN to test a different subset on every run. Which means that we should have complete coverage over time.
I'm just thinking out-loud.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a big fan of deterministic behavior 😅
|
Thanks! |
This used to fail:
% Build/lagom/bin/image \
--assign-color-profile serenity-sRGB.icc \
--convert-to-color-profile \
./Build/lagom/Root/res/icc/Adobe/CMYK/USWebCoatedSWOP.icc \
-o buggie-cmyk.jpg \
Base/res/graphics/buggie.png
Runtime error: Can only convert to RGB at the moment,
but destination color space is not RGB
Now it works.
It only works for CMYK profiles that use an mft1 tag for the BToA tags,
because SerenityOS#26452 added support for converting from PCS to mft1.
Most CMYK profiles use mft1, but not all of them. Support for `mft2` and
`mBA ` tag types will be in a (straightforward) follow-up.
Implementation-wise, Profile grows two more methods for converting RGB
and CMYK bitmaps to CMYK. We now have 2x2 implementations for
{RGB,CMYK} -> {RGB,CMYK}. For N different channel types, we need O(N^2)
of these methods.
Instead, we could have conversion methods between RGB bitmap and PCS
bitmap and between CMYK and PCS bitmap. With this approach, we'd only
need O(N) (2*N) of these methods. Concretely, that'd be 2x2 methods too
though, and since there are two PCS types, depending on how it's
implemented it's actually 4*N (i.e. 8 for RGB and CMYK).
So the current 2x2 approach seems not terrible. It *is* a bit
repetitive.
We then call the right of these 4 methods in `image`.
See the PR that added this commit for rough quantitative quality
evaluation of the implementation.
This used to fail:
% Build/lagom/bin/image \
--assign-color-profile serenity-sRGB.icc \
--convert-to-color-profile \
./Build/lagom/Root/res/icc/Adobe/CMYK/USWebCoatedSWOP.icc \
-o buggie-cmyk.jpg \
Base/res/graphics/buggie.png
Runtime error: Can only convert to RGB at the moment,
but destination color space is not RGB
Now it works.
It only works for CMYK profiles that use an mft1 tag for the BToA tags,
because #26452 added support for converting from PCS to mft1.
Most CMYK profiles use mft1, but not all of them. Support for `mft2` and
`mBA ` tag types will be in a (straightforward) follow-up.
Implementation-wise, Profile grows two more methods for converting RGB
and CMYK bitmaps to CMYK. We now have 2x2 implementations for
{RGB,CMYK} -> {RGB,CMYK}. For N different channel types, we need O(N^2)
of these methods.
Instead, we could have conversion methods between RGB bitmap and PCS
bitmap and between CMYK and PCS bitmap. With this approach, we'd only
need O(N) (2*N) of these methods. Concretely, that'd be 2x2 methods too
though, and since there are two PCS types, depending on how it's
implemented it's actually 4*N (i.e. 8 for RGB and CMYK).
So the current 2x2 approach seems not terrible. It *is* a bit
repetitive.
We then call the right of these 4 methods in `image`.
See the PR that added this commit for rough quantitative quality
evaluation of the implementation.
Similar to what SerenityOS#26452 did for Lut8TagData and SerenityOS#26462 for Lut16TagData. With this, we can convert from PCS to all tag types :^) Which means our ICC implementation is now fairly complete! We don't support DeviceLink or Abstract profile types (both don't appear in images; both are arguably useful in some not-embedded-in-images scenarios), nor the optiona BToD / DToB tags, and are missing some other minor things (like grayscale profiles -- but not much is missing here). But overall, this is now a fairly complete basic ICC implementation :^)
Similar to what SerenityOS#26452 did for Lut8TagData and SerenityOS#26462 for Lut16TagData. With this, we can convert from PCS to all tag types :^) Which means our ICC implementation is now fairly complete! We don't support DeviceLink or Abstract profile types (both don't appear in images; both are arguably useful in some not-embedded-in-images scenarios), nor the optiona BToD / DToB tags, and are missing some other minor things (like grayscale profiles -- but not much is missing here). But overall, this is now a fairly complete (if slow) basic ICC implementation :^)
mft1 BToA0 tags are often present in CMYK profiles, so this is a step towards supporting converting images to CMYK.
Matrix profiles can only be used with PCSXYZ, but CMYK profiles use PCSLAB.
CMYK is 4D, which makes writing roundtrip tests for those profiles iffy. Adding a LAB profile that also uses PCSLAB as PCS space makes testing this easier.
Also add a roundtrip test for sRGB; for some reason I hadn't done that yet as far as I can tell.