Commit graph

59 commits

Author SHA1 Message Date
Nico Weber
3a5d20d82b icc: Add a --measure flag that prints color difference in profile
If --measure is passed, icc prints the color pairs with the smallest
and largest perceptual difference between them.

Converting 254 * 254 * 254 * 4 = 65 Million colors from sRGB to LAB
and then computing 254 * 254 * 254 * 3 = 49 Million DeltaEs between
them takes a while. On my laptop, it takes 17s to run. So there's
a small progress display.
2023-04-30 05:57:20 +02:00
Nico Weber
6c7b3c56f2 icc: Print if a curve looks like the sRGB curve 2023-04-11 18:23:07 +02:00
Nico Weber
fe8c0292ad icc: Use {: >{}}, "", indent_amount for indenting
No behavior change.
2023-04-11 18:23:07 +02:00
Nico Weber
5d14a0081e icc: Make out_curve_tag() fallible 2023-04-11 18:23:07 +02:00
Nico Weber
5da9057a8f icc: Extract out_curve_tag() helper function 2023-04-11 18:23:07 +02:00
Lucas CHOLLET
496b7ffb2b LibGfx: Move all image loaders and writers to a subdirectory 2023-03-21 22:39:25 +01:00
Tim Schumacher
ecd1862859 AK: Rename Stream::write_entire_buffer to Stream::write_until_depleted
No functional changes.
2023-03-13 15:16:20 +00:00
Nico Weber
85507b34d7 icc: Introduce --name flag to load a built-in profile by name
...instead of from a file.

For now, `--name=sRGB` is the only valid value, but more will
probably follow in the future.

Just `icc --name=sRGB` prints the built-in sRGB profile.

`icc --name=sRGB --reencode-to=file.icc` writes it to file.icc.
2023-03-04 21:38:47 +00:00
Nico Weber
04d519f1f1 LibGfx: Use ICC::Profile::try_for_each_tag in icc main loop
I didn't use it in out_curve(), out_parametric_curve() since it
wouldn't be necessary if I printed the indent with a loop instead
of String::repeated() there.
2023-02-19 23:46:36 +01:00
Nico Weber
7880e11690 icc: Add flags for writing and dumping profiles
This adds three flags to icc:

* --reencode-to=<file> re-serializes a profile to a given file,
  using Gfx::ICC::encode(). This is mainly useful for testing that
  code.

* --dump-to=<file> dumps the raw ICC profile bytes read from the
  input to disk. This is useful for extracting ICC profiles from
  images, and for comparing the raw profile bytes to the profile
  bytes written by --reencode-to=.

If either of these flags is passed, icc by default no longer dumps
the icc data to stdout. To force priting of the data even if either
of these flags is present, this also adds:

* --print, which forces printing ICC contents, even if either or
  both of the icc-data writing flags are present.
2023-02-17 20:05:50 -07:00
Nico Weber
6f39c44160 icc: Dump embedded non-parametric curves in lutAToBType and lutAToBType 2023-02-13 00:15:02 +00:00
Nico Weber
7929f8fef9 icc: Dump embedded parametric curves in lutAToBType and lutAToBType 2023-02-13 00:15:02 +00:00
Nico Weber
ed8bd3a792 icc: Dump more information about curves in lutAToBType and lutAToBType 2023-02-13 00:15:02 +00:00
Nico Weber
b15a889ca4 icc: Dump some of lutAToBType and lutBToAType curve data 2023-02-12 20:07:45 +00:00
Nico Weber
9f0f3f434f LibGfx+icc: Stringify known signatureType values 2023-02-10 15:19:14 +00:00
Nico Weber
b232281d15 LibGfx+icc: Read chromaticityTag
This isn't terribly useful. But some profiles, for example the ones at
https://vpifg.com/help/icc-profiles/, do contain this tag and it seems
nice to be able to dump it, just for completeness.

I haven't seen any files that contain a phosphor or colorant type
different from "Unknown", even for the Rec2020 profile on that page.
(It has x,y coordinates that match the values required for Rec2020,
but it doesn't set the phosphor or colorant type to that.)
2023-02-10 14:23:37 +00:00
Nico Weber
c61cfdd5ed LibGfx+icc: Read viewingConditionsType
Not terribly useful in practice either and also mostly for
completionism. But with this, we can dump all types present
in Lightroom Classic-exported jpegs :^)
2023-02-10 14:16:52 +00:00
Nico Weber
664946c543 LibGfx+icc: Read measurementType
Also not terribly useful in practice and mostly for completionism.
Lightroom Classic-exported jpegs contain this type in their ICC data.
2023-02-10 14:02:19 +00:00
Nico Weber
e99a4ba7c8 icc: Call video_full_range_flag_to_string() 2023-02-09 16:35:08 +00:00
Nico Weber
2ff11bac3d LibGfx+icc: Implement half of lutAToBType and lutBToAType
These are among the permitted tag types of ATo0Tag and BToA0Tag,
which are among the required tags of most profiles. They are the
last permitted tag types for those profiles (the other are
lut8Type or lut16Type, which are already implemented).

They are pretty chonky types though, so this only implements
support for the E matrix and the CLUT. Support for the various
curves will be in a future PR.
2023-02-08 19:44:03 +00:00
Nico Weber
e8bbb3d915 LibGfx+icc: Read cicpType
This is a very new tag used for HDR content. The only files I know that
use it are the jpegs on https://ccameron-chromium.github.io/hdr-jpeg/
But they have an invalid ICC creation date, so `icc` can't process them.
(Commenting out the check for that does allow to print them.)

If the CIPC tag is present, it takes precedence about the actual data
in the profile and from what I understand, the ICC profile is
basically ignored. See https://www.color.org/events/HDR_experts.xalter
for background, in particular
https://www.color.org/hdr/02-Luke_Wallis.pdf (but the other talks
are very interesting too).

(PNG also has a cICP chunk that's supposed to take precedence over
iCCP.)
2023-02-08 16:41:58 +00:00
Nico Weber
8bd64f001c LibGfx+icc: Read signatureType
This isn't used by any mandatory tags, and it's not terribly useful.
But jpegs exported by Lightroom Classic write the 'tech' tag, and
it seems nice to be able to dump its contents.

signatureType stores a single u32 which for different tags with this
type means different things.

In each case, the value is one from a short table of valid values,
suggesting this should be a per-tag enum class instead of a
per-tag DistinctFourCC, per the comment at the top of DistincFourCC.h.
On the other hand, 3 of the 4 tables have an explicit "It is possible
that the ICC will define other signature values in the future" note,
which suggests the FourCC might actually be the way to go.

For now, just punt on that and manually dump the u32 in fourcc style
in icc.cpp and don't add any to_string() methods that return a readable
string based on the contents of these tables.
2023-02-08 16:35:57 +00:00
Nico Weber
cbcf8471a6 LibGfx+icc: Read namedColor2Type
This is the type of namedColor2Tag, which is a required tag in
NamedColor profiles.

The implementation is pretty basic for now and only exposes the
numbers stored in the file directly (after endian conversion).
2023-02-08 16:34:24 +00:00
Nico Weber
909c2a73c4 LibGfx+icc: Read and display lut16Type and lut8Type ICC tag types 2023-01-28 21:40:45 +00:00
Nico Weber
027c97d3b2 icc: Print profile size 2023-01-28 12:42:19 +01:00
Nico Weber
b5deccf859 LibGfx: Split ICC/Profile.{h,cpp} into several files
s15Fixed16Number and XYZNumber are somewhat awkwardly duplicated
in both Profile.cpp and TagTypes.cpp. Other than that, this is a
pure code move.

No behavior change.
2023-01-28 00:27:07 +00:00
Nico Weber
721b280849 LibGfx: Move ICCProfile.{h,cpp} to ICC/Profile.{h,cpp} 2023-01-28 00:27:07 +00:00
Nico Weber
2f3eefe03b icc: Accept path to images in addition to path to ICC profile 2023-01-27 17:26:48 +00:00
Nico Weber
87f1a0e957 LibGfx+icc: ICCProfile's primary_platform() should be optional
Found by running `icc` on a jpeg file produced by a Pixel phone
after #17195.
2023-01-27 12:01:58 +00:00
Nico Weber
4735397606 icc: Align "else" for Type3 with "if" 2023-01-26 17:38:17 +00:00
Nico Weber
0d94e23039 icc: Indent ParametricCurveTagData the same amount as the other types 2023-01-26 17:38:17 +00:00
Nico Weber
2095e2529f icc: Print each tag signature's spec name
The spec names are still a bit cryptic ("deviceMfgDescTag"
for "device manufacturer description"), but less cryptic than
just the fourcc.

There's a private tag area, so this will only print the spec name
of tags in the current spec. Private tags are in active use, e.g.:

    $ icc /Library/ColorSync/Profiles/WebSafeColors.icc
    ...
    Unknown tag ('dscm'): type 'mluc', offset 312, size 1490

(That's a v2 file. In v2, 'desc' has that strange textDescriptionType.
In v4, 'desc' has type 'mluc' -- but in v2, it didn't yet, so Apple
invented the private 'dscm' tag which has the description as an 'mluc'.)
2023-01-25 14:26:21 +01:00
Nico Weber
95992a255e icc: Print every TagData object only once
When several tags refer to the same TagData object, we now only print
it the first time, and print "(see 'foob' above)" the following times,
where `foob` is the tag identifier where we printed it the first time.
2023-01-24 14:45:27 +00:00
Nico Weber
fa00d94e82 LibGfx+icc: Add ICCProfile support for parametricCurveType and print it
With this, we can parse all types required in v4
"Three-component matrix-based Input profiles".
2023-01-23 23:37:33 +00:00
Nico Weber
67f718aa3f LibGfx+icc: Add ICCProfile support for curveType and print it 2023-01-23 18:20:55 +00:00
Nico Weber
9756842734 LibGfx+icc: Add ICCProfile support for s15Fixed16ArrayType and print it
This is the type of the chromaticAdaptationTag, which is a required tag
in v4 profiles for all non-DeviceLink profiles.
2023-01-23 18:09:23 +00:00
Nico Weber
6cfb057430 LibGfx+icc: Add ICCProfile support for XYZType and print it 2023-01-23 12:08:25 +00:00
Nico Weber
e7eccf4ac8 LibGfx+icc: Add ICCProfile support for textDescriptionType and print it
This is used in v2 profiles for the required 'desc' tag. In v2
profiles, it's also used by the 'dmnd', 'dmdd', 'scrd', 'vued' tags.

In v4 profiles, these all use 'mluc' instead (except for 'scrd', which
is no longer part of the spec in v4).
2023-01-23 10:09:01 +00:00
Nico Weber
19ce63babf icc: Print MultiLocalizedUnicodeTagData contents 2023-01-22 15:25:58 +00:00
Nico Weber
3bc70d7aa5 icc: Print TextTagData contents 2023-01-22 15:25:58 +00:00
Nico Weber
b56a145a67 LibGfx+icc: Make device manufacturer and device model clickable 2023-01-21 22:16:38 -05:00
Nico Weber
a0522aec90 icc: Remove needless use of DateTime::to_deprecated_string()
Turns out DateTime has a Formatter that prints the same thing that
to_deprecated_string() returns.

No behavior change.
2023-01-21 01:50:24 +00:00
Nico Weber
e47e5f5ce0 icc: Tweak output to look nicer
Align header on the `:`, and make bitmask output more structured.
2023-01-21 01:50:24 +00:00
Nico Weber
f28b052590 LibGfx: Add scaffolding for reading ICC tag table
The idea is that we'll have one type for each tag type.
For now, this treats all tag types as unknown, but it puts most
of the infrastructure for reading tags in place.
2023-01-20 21:44:36 +00:00
Nico Weber
7ae97c9fc4 LibGfx+icc: Look at profile_size field
This trims the input bytes to the profile size stored in the file.
Alternatively, we could reject files where the stored size doesn't
match the handed in size. But ICC profiles can be embedded in other
files, and those could conceivably pad the ICC profile data some.
2023-01-08 23:41:14 +01:00
Nico Weber
aee7c44064 LibGfx+icc: Print primary platform
There's a small, old-timey list of platforms in the spec, but as far
as I can tell nobody is using additional platforms on Linux or Android
or what. So let's try going with an enum class instead of the FourCC
machinery for now.
2023-01-08 09:56:07 +00:00
Nico Weber
fdbe501d3e LibGfx+icc: Print fields that are fourccs registered with the ICC
Namely:
- preferred CMM type
- device manufacturer
- device model
- profile creator

These all have in common that they can take arbitrary values, so I added
a FourCC class to deal with them, instead of using an enum class.
I made distinct types for each of them, so that they aren't accidentally
mixed up.
2023-01-07 13:41:41 +00:00
Nico Weber
516d800b01 icc: Extract out_optional() function 2023-01-07 13:41:41 +00:00
Nico Weber
d223477bc6 LibGfx+icc: Print device attribute flags
These flags are always 0 in practice in all profiles I've seen so far,
but hey, probably nice to dump them anyways.

And hey, it's just 86 lines to print 4 bits.
2023-01-06 21:33:46 +01:00
Nico Weber
c00ce2fba0 LibGfx+icc: Verify ICCProfile ID at parse time instead of in icc
Always computing computing the md5 takes some time, but most
icc profiles are small. So that's probably fine.

If this ends up being a perf problem in the future, or if it ends up
rejecting tons of embedded proiles from images, we can row it back.
But let's see if we can get away with this first.
2023-01-06 20:26:14 +01:00