Repository navigation
Fix PSD layer tiles reading from the wrong file offset - #10089
Merged
radarhere merged 4 commits intoOct 2, 2026
Merged
Conversation
PsdImageFile.layers() parses each layer's channel data from a BytesIO copy of the layer info block, so the tile offsets it builds are positions within that copy, starting at 0. seek() then loads those tiles from the original file object, so the bytes actually decoded come from wherever that small offset lands in the real file, not from the layer's pixel data. Add self._layers_position, the real file offset the copy was read from, back onto each tile offset so seek() reads the correct bytes.
Member
|
I've created https://github.com/Arthur031221/Pillow/pull/1 with a suggestion to simplify this code. |
Applies radarhere's suggestion: read the layer info from the file directly so the tile offsets are already absolute, and use the test form from the same suggestion.
Contributor
Author
|
Thanks, applied your suggestion in d8511d1. I ran Tests/test_file_psd.py on that tree: 26 passed. |
Pass original file pointer to _layerinfo()
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes # .
Changes proposed in this pull request:
seek()to read anindividual layer gets back the wrong pixel data.
PsdImageFile.layersparses each layer's channel offsets from a
BytesIOcopy of the layerinfo block, so the offsets it records start at 0, relative to that copy.
seek()then loads tiles from the original file object using thosesame numbers as absolute file positions, so the decoder reads whatever
bytes happen to sit near the start of the real file (the header and
image resources) instead of the layer's actual pixel data.
self._layers_position, the real fileposition the copy was read from, so the bytes decoded for a layer are
the bytes that belong to it.
to the flattened image loaded at open time, and checks the two match.
Before this fix the loaded layer differs from the flattened image on
every pixel; on
main, this isTests/images/hopper.psd's "Background"layer, reached by seeking away and back to frame 1 so that
seek()actually re-reads the layer's tile instead of reusing the tile already
set up when the file was opened.
Verified locally:
python3 -m pytest Tests/test_file_psd.pypasses (26tests). Reverting only
src/PIL/PsdImagePlugin.pytomainand rerunningthe new test alone fails with "got different content"; restoring the fix
makes it pass again. Full suite on
mainbefore this change: 4951 passed,576 skipped, 3 xfailed. After this change: 4952 passed (the one new test),
576 skipped, 3 xfailed; no other test changed status.