Fix coordinate inversion when MediaBox origin is not (0, 0) - #1381
Open
apoorvdarshan wants to merge 1 commit into
Open
Fix coordinate inversion when MediaBox origin is not (0, 0)#1381apoorvdarshan wants to merge 1 commit into
apoorvdarshan wants to merge 1 commit into
Conversation
`_invert_box` flipped coordinates about the MediaBox *height* rather than its top edge, so the raw MediaBox y-origin (`mb_raw[1]`) was never subtracted. For pages whose MediaBox does not begin at `y == 0`, this shifted every object's `top`/`bottom` by that origin (often producing negative `top` values) and left `page.mediabox`/`page.bbox` starting at a non-zero `y`. Flip about the raw upper-`y` edge (`mb_raw[3]`) instead. This subtracts the origin correctly and is a no-op for the common case, where the MediaBox lower-left is `(0, 0)` and the top edge equals the height. Fixes jsvine#1332.
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 #1332.
Root cause
_invert_box(inpdfplumber/page.py) flips PDF coordinates vertically sothe origin ends up in the top-left. It did so about the MediaBox height:
with
mb_height = mb_raw[3] - mb_raw[1]. Because it subtracts from theheight rather than from the raw top edge (
mb_raw[3]), the MediaBox'sraw y-origin (
mb_raw[1]) is never subtracted. For a MediaBox whoselower-left is
(0, 0)this is fine (mb_height == mb_raw[3]), but whenthe MediaBox does not begin at
y == 0everytop/bottomis shifted bythat origin, and
page.mediabox/page.bboxstart at a non-zeroy.(pdfminer.six already normalizes object coordinates to a
(0, 0)-originpage, so the flip must not re-introduce the origin.)
Reproduction
A PDF with a centered-origin MediaBox
[-100 -200 100 200]containing asingle rectangle drawn at raw coordinates
10 20 30 40 re(raw spanx: 10..40,y: 20..60):Actual (before):
The page's top edge sits at
top == 200andmediabox[3] == 600eventhough the page is only
400units tall — the whole page is shifted downby the origin (
200).Corrected (after):
topnow ranges over[0, height], as expected.This also matches the report in #1332: raw MediaBox
(-100, -200, 100, 200)previously yielded
(-100, 200, 100, 600).The regression is also visible on the existing
tests/pdfs/issue-1181.pdffixture, whose first page has MediaBox
[0, 200, 420.9449, 585.2756]:page.mediabox == (0, -200.0, 420.9449, 185.2756), and objecttopvalues were shifted-200into negative territory(
min(top) == -41.3).page.mediabox == (0, 0.0, 420.9449, 385.2756), andmin(top)is
158.7(all non-negative).Fix
Flip about the raw upper-
yedge (mb_raw[3]) instead of the height.This subtracts the origin correctly and is a no-op for the common case
(where the MediaBox lower-left is
(0, 0), so the top edge equals theheight). The change is confined to the two MediaBox/CropBox call sites in
Page.__init__; the x-offset behavior introduced for #1181 is preserved(object x-coordinates and
page.mediabox[0]still keep the rawMediaBox
x0), and downstream consumers (process_object,point2coord) read the corrected origin fromself.mediaboxautomatically, so no other code needed to change.
Tests
Added
tests/test_issues.py::test_issue_1332, which uses the existingissue-1181.pdffixture (its first page has a non-zero MediaBoxy-origin) and asserts that the inverted MediaBox begins at
y == 0, thatno object has a negative
top, and that a sample character's coordinatesare corrected. The test fails on the current code
(
assert -200.0 == 0) and passes with the fix. The existing suitecontinues to pass (
python -m pytest, excluding thetest_repair.pycases that require a local Ghostscript install, which is unrelated to this
change).
black,isort, andflake8are clean on the changed files.Disclosure: prepared with AI assistance; reviewed and verified locally.