The former automatically adapts the prefix to binary and octal
output, and is what we already use in the majority of cases.
Patch generated by:
rg -l '0x\{' | xargs sed -i '' -e 's/0x{:/{:#/'
I ran it 4 times (until it stopped changing things) since each
invocation only converted one instance per line.
No behavior change.
Before, we used to reject profiles where the creation datetime was
invalid per spec. But invalid dates happen in practice (most commonly,
all fields set to 0). They don't affect profile conversion at all,
so be lenient about this, in exchange for slightly more wordy code
in the places that want to show the creation datetime.
Fixes a crash rendering page 2 of
https://fredrikbk.com/publications/copy-and-patch.pdf
With this, we convert a bunch of random colors to a
profile's profile connection space and back, and count
how many u8 colors make it through unchanged.
With this, you can do something like:
for f in ~/Downloads/Adobe\ ICC\ Profiles\ \(end-user\)/*/*.icc; do
echo $f
Build/lagom/bin/icc --debug-roundtrip $f
done
to test conversion through a bunch of profiles. These profiles are
available at:
https://www.adobe.com/support/downloads/iccprofiles/iccprofiles_win.html
...which ultimately leads to:
https://download.adobe.com/pub/adobe/iccprofiles/win/AdobeICCProfilesCS4Win_end-user.zip
(Or use `Build/lagom/bin/icc --debug-roundtrip -n sRGB` to test the
built-in sRGB 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.
...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.
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.
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.
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.)
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 :^)
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.
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.)
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.
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).
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.
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'.)
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.
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).
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.
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.
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.
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.