Type 2 <=> One-dimensional Group3, customized for TIFF
Type 3 <=> Two-dimensional Group3, uses the original 1D internally
Type 4 <=> Two-dimensional Group4
So let's clarify that this is not Group3 1D but the TIFF variant, which
is called `CCITTRLE` in libtiff. So let's stick with this name to avoid
confusion.
Images with a display mask ("stencil" as it's called in DPaint) add
an extra bitplane which acts as a mask. For now, at least skip it
properly. Later we should render masked pixels as transparent, but
this requires some refactoring.
SamplingFactors already has default initializers for its field,
so no need to have an explicit one for the first of the two fields.
No behavior change.
We now allow all subsampling factors where the subsampling factors
of follow-on components evenly decode the ones of the first component.
In practice, this allows YCCK 2111, CMYK 2112, and CMYK 2111.
Previously, we handled sampling factors as part of ycbcr_to_rgb().
That meant it worked ok for code paths that used YCbCr ("normal"
jpegs, and the YCC part of YCCK jpegs), but it didn't work for
example for the K channel in YCCK jpegs, nor for CMYK.
By making this a separate pass, it should now work for all cases.
It also makes it easier to support more subsampling arrangements
in the future, and to use something better than nearest neighbor
for upsampling subsampled blocks.
All the data is passed using the `Metadata` object, which has a
`main_tags` method. This method should be used when displaying only a
few main tags, for example to fill the property window of a file
manager. Another method returning the entire list of tags will be
implemented later on.
We refuse any image with a sample depth greater than 32, storing these
value as `u64` prevent any overflows. This is probably overkill as no
one in their right mind will use a 32 bits color table.
frame() still returns a regular RGB Bitmap (now lazily converted
from internal CMYK data), but JPEGImageDecoderPlugin now also
implements cmyk_frame().
Some apps seem to generate malformed images that are accepted
by most readers. We now only throw if malformed data would lead to
a write outside the chunky buffer.
ExifOrientedBitmap was implemented before the introduction of the TIFF
decoder. So we had to provide a definition of the Orientation enum. Now
that we have a TIFF implementation that comes with some enum
definitions, we should prefer this source.
When using the BMP encoding, ICO images are expected to contain a 1-bit
mask for transparency. Regardless an alpha channel is already included
in the image, the mask is always required. As stated here[1], the
mask is used to provide shadow around the image.
Unfortunately, it seems that some encoder do not include that second
transparency mask. So let's read that mask only if some data is still
remaining after decoding the image.
The test case has been generated by truncating the 64 last bytes
(originally dedicated to the mask) from the `serenity.ico` file and
changing the declared size of the image in the ICO header. The size
value is stored at the offset 0x0E in the file and I changed the value
from 0x0468 to 0x0428.
[1]: https://devblogs.microsoft.com/oldnewthing/20101021-00/?p=12483
This fixes an issue where GIF images without a global color table would
have the first segment incorrectly interpreted as color table data.
Makes many more screenshots appear on https://virtuallyfun.com/ :^)
TIFF files are made in a way that make them easily extendable and over
the years people have made sure to exploit that. In other words, it's
easy to find images with non-standard tags. Instead of returning an
error for that, let's skip them.
Note that we need to make sure to realign the reading head in the file.
The test case was originally a 10x10 checkerboard image with required
tags, and also the `DocumentName` tag. Then, I modified this tag in a
hexadecimal editor and replaced its id with 30 000 (0x3075 as a LE u16)
and the type with the same value as well. This is AFAIK, never used as
a custom TIFF tag, so this should remain an invalid tag id and type.