Repository navigation
BUG: Decode low-bit DeviceRGB images as RGB instead of palette - #3929
Conversation
|
The failing jobs look like the usual network flakes on the download-fixture tests (there's a ConnectionResetError fetching the sample PDFs) — my added test is offline and passes. Happy to rebase or re-run whenever CI settles. @stefan6419846 let me know if you'd like me to run the fix against your original file. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3929 +/- ##
=======================================
Coverage 97.87% 97.87%
=======================================
Files 57 57
Lines 10779 10782 +3
Branches 2019 2019
=======================================
+ Hits 10550 10553 +3
Misses 127 127
Partials 102 102 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
stefan6419846
left a comment
There was a problem hiding this comment.
Thanks for the PR. I have left an inline comment.
Regarding my original case, this change does not solve it - most likely because the inline image section does not use a filter on the image data, while in your case, it seems like it is about the /FlateDecode filter.
|
Good catch on both counts. Took the int(mode[0]) suggestion — cleaner, and the only low-bit modes are On your case: you're right, and I can reproduce it. The expansion sits in Looks like the right place is _image_from_bytes itself, since every path Want me to do that in this PR, or keep this one to the flate fix for #3924 |
How would this affect the new parameters you introduced in the current PR? Would they still be relevant for a general fix, or would a general fix revert these? |
|
They'd stay as-is — a general fix doesn't revert them. The two params are doing the actual work: colors= makes bits2byte unpack What moves is only the dispatch — the I tried it locally: same 4-bit DeviceRGB image comes out as RGB So it's additive rather than a revert. Happy to fold it into this PR if |
stefan6419846
left a comment
There was a problem hiding this comment.
I guess we can make this two separate PRs if you are planning to work on preparing the second PR after this.
For this to get merged, please resolve the merge conflict.
4-bit and 2-bit /DeviceRGB images were forced to mode 'P', which left an unrecognized '4bits'/'2bits' Pillow mode and produced broken extraction. Treat multi-component DeviceRGB samples as interleaved color components: unpack them per row across all components and scale up to 8-bit, giving a proper RGB image. Single-component spaces still map to 'P'.
bab265e to
ac5072a
Compare
|
Rebased on main — the conflict was with the _handle_flate reorder in #3904. Happy to do the general _image_from_bytes fix as a separate PR once this |
## What's new ### Security (SEC) - Improve performance of read_until_whitespace (#3947) by @stefan6419846 - Limit CID width range and width count when loading fonts (#3946) by @stefan6419846 - Limit token length for ToUnicode entries (#3944) by @stefan6419846 ### Deprecations (DEP) - Deprecate previously missed inline_images setter as well (#3897) by @stefan6419846 ### New Features (ENH) - Add ActualText tag when we produce RTL appearance stream (#3901) by @PJBrs - Allow keeping original PDF header in non-incremental clone mode (#3918) by @pctablet505 - AppearanceStream: Add support for RTL appearance streams with Arabic characters (#3831) by @PJBrs - Add actions base class (#3552) by @j-t-1 ### Bug Fixes (BUG) - Expand low-bit samples for images without a filter (#3938) by @RavSinghChandan - Decode low-bit DeviceRGB images as RGB instead of palette (#3929) by @RavSinghChandan - Correctly handle IndirectObject in FlateDecode.decode DecodeParms (#3937) by @stefan6419846 ### Documentation (DOC) - Image and attachment filenames are unsanitized (#3942) by @stefan6419846 ### Maintenance (MAINT) - Update charset mappings (#3935) by @stefan6419846 [Full Changelog](6.14.2...6.15.0)
Fixes #3924.
A 4-bit (or 2-bit) per component /DeviceRGB image was being forced to
Pillow mode "P", which left the unrecognized "4bits"/"2bits" mode string
and broke extraction (either an error or a wrong-looking image).
The low-bit branch in
_handle_flateassumed a single component per pixel.For /DeviceRGB the samples are 3 interleaved color components, so this now:
width * colorssamples per row (not justwidth)Single-component color spaces (e.g. /DeviceGray) still map to "P", so the
existing 4-bit palette path is unchanged.
bits2bytekeeps its oldsignature via defaults (colors=1, scale=False).
Added an offline test covering a 2x2 4-bit DeviceRGB image and confirming a
single-component image still resolves to "P". @stefan6419846 — happy to have
you run this against your original file to confirm it resolves your case too.