The halftone region decoding procedure can draw patterns completely
outside the page bitmap. I haven't seen this in practice yet (not
many files use pattern/halftone segments), but it seems like it's
possible in theory and seems like a good thing to check for.
Annex C describes how to read a grayscale bitmap with n bits per pixel:
It's encoded as n bilevel bitmaps, where each bilevel bitmap stores one
bit of the grayscale value (using a en.wikipedia.org/wiki/Gray_code,
which is named after Frank Gray and doesn't normally have much to do
with grayscale images).
A halftone region stores a grayscale bitmap and a linear coordinate
system the grayscale bitmap is in. The grayscale bitmap is overlaid
the halftone region using the coordinate system, and each sample in
the grayscale bitmap is used as an index into a pattern dictionary
and the bitmap at that index is drawn at the current location.
This allows for efficient compression of ordered dithering
(but not error-diffusion dithering).
This does not yet implement halftone region decoding for MMR bitmaps.
The halftone region decoding procedure is the only way to call the
generic region decoding procedure with a skip pattern. This does
include code to compute the skip pattern, but support for that
is not yet implemented in the generic region decoding procedure,
so it'll error out when encountered. (I haven't yet found a file
using this feature, not a way to create such a file yet.)
A pattern dictionary stores n bitmaps with the same dimensions w x h.
They're stored in a single bitmap of width `n * w` that's then cut
into n stripes.
The implementation is very similar to #23831.
I created the test exactly like in #23713, except that I replaced the
last four lines in the ini file with:
```
-txt -Param -rATX1 10
-txt -Param -rATY1 -1
-txt -Param -rATX2 4
-txt -Param -rATY2 15
```
...in the generic region decoding procedure (not yet in the generic
refinement region procedure). Not yet for EXTTEMPLATE though.
I haven't seen these being used in the wild, but:
* I want to optimize this code some, and it's probably good if it
is feature complete (and well-tested) before being optimized
* Other PDF engines implement support for this
* The Pattern/Halftone feature (which we don't yet implement either,
but which I'd like to implement because see previous two bullets)
calls the generic region decoding procedure with custom adaptive
template pixels
Only the coordinates get transposed -- the bitmaps apparently don't.
And all the prose amounts to "if the transposed bit is set, swap
instance s and t coordinates before painting", as far as I can tell.
Makes pages 3/4 and 7/8 in 0001346.pdf render. (But here the feature
isn't used to render transposed text -- it just has stripes that keep s
roughy constant, which would normally produce vertical runs but here
produces regular horizontal runs. It's not clear to me why this feature
is used for these pages!)
The T.800 spec says there should only be one 'colr' box, but the
extended jpx file format spec in T.801 annex M allows having multiple.
Method 2 is a basic ICC profile, while method 3 (jpx-only) allows full
ICC profiles. Support that.
For the test, I opened buggie.png in Photoshop, converted it to
grayscale, and saved it as a JPEG2000, with "JP2 Compatible" checked
and "Include Transparency" unchecked. I also unchecked "Include
Metadata", and "Lossless". I left "Fast Mode" checked and the quality
at the default 50.
I found this interesting, and it also explains e.g. why some
of the step numbers in 6.4 Text Region Decoding Procedure are off --
they added step 3) for COLEXTFLAG and forgot to update step references
to later steps.
.jpf (JPEG2000) files written by Photoshop contain a whole bunch of
these boxes.
fileformats.archiveteam.org/wiki/Boxes/atoms_format lists a few
UUID types. Of those 3, these are in Photoshop-written .jpf files:
* 0537cdab-9d0c-4431-a72a-fa561f2a113e Exif
* 2c4c0100-8504-40b9-a03e-562148d6dfeb Photoshop Image Resource
* be7acfcb-97a9-42e8-9c71-999491e3afac XMP
JPEG2000 is the last image format used in PDF filters that we
don't have a loader for. Let's change that.
This adds all the scaffolding, but no actual implementation yet.
This doesn't have to be a virtual method: it's called from
various create_from_stream() methods that have a static type
that's created. There's no point in the virtual call here,
and it makes it harder to add additional parameters to
read_from_stream() in some subclasses.