[
https://issues.apache.org/jira/browse/PDFBOX-6157?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18140736#comment-18140736
]
Tilman Hausherr commented on PDFBOX-6157:
-----------------------------------------
I asked Claude Sonnet 5.5 about this problem:
specifically, the blit() method in
[https://github.com/apache/pdfbox-jbig2/blob/master/src/main/java/org/apache/pdfbox/jbig2/image/Bitmaps.java]
In that method, see the comment that mentions PDFBOX-6156
Try making a fix for the 3 methods that are now inactive due to bugs
(blitUnshifted, blitSpecialShifted and blitShifted). The method blitByPixel is
correct but it slow.
The answer:
I need the actual source first. I’ll retry the fetch.
I’ve cloned the repo and read the blit code. Next I’m checking the existing
blit tests, then I’ll write a mask-based replacement for the three disabled
methods and check it against {{{}blitByPixel{}}}.
I rewrote {{blit()}} in {{Bitmaps.java}} so that {{{}blitUnshifted{}}},
{{blitSpecialShifted}} and {{blitShifted}} are active again. The
{{blitByPixel}} fallback is gone from the normal path. I couldn’t run the full
Maven build or the serenity {{bitmap-composite-and-xnor*.jbig2}} check, because
there’s no network for Maven dependencies. So I compiled with {{javac}} and ran
the tests directly.
*Test results*
* A randomized comparison against {{blitByPixel}} passed on 1,000,000 cases.
It covers all five operators, offsets partly or fully outside the destination,
and random padding bits. The full byte arrays were identical.
* The new {{BitmapsBlitTest}} cases pass with JUnit: 4 tests OK, with the two
existing tests skipped when their {{.jb2}} file is missing.
* A quick benchmark of 141×300 blits at unaligned offsets took about 32–57 ms
for {{blit}} versus 217–261 ms for {{{}blitByPixel{}}}, roughly 5–8× faster.
*What was wrong*
The old code tried to handle clipping and byte alignment in one pass. The
{{padding}} and {{toShift}} arithmetic and the {{unpad()}} calls were also
wrong at the end of a row, which is how a 141-pixel region came out 144 wide.
The bottom-edge clipping also looked wrong: {{startLine}} was computed from the
overflow, and {{lastLine}} ignored {{{}y{}}}.
*How it works now*
* {{blit()}} clips once to a source and destination rectangle, then works out
first and last byte masks. Only bits inside the rectangle are ever written, so
padding bits and neighbouring pixels stay untouched. It also returns early for
fully outside offsets, which avoids overflow with extreme {{{}x{}}}/{{{}y{}}}.
* {{blitUnshifted}} handles the case where the source and destination bit
positions match. It uses {{Bitmap.arraycopy}} for the middle bytes with
{{{}REPLACE{}}}.
* {{blitSpecialShifted}} handles a shifted blit where the whole row lands in
one destination byte.
* {{blitShifted}} handles everything else. Each destination byte is built from
two adjacent source bytes, with bounds checks so it never reads past the end of
a source row.
* {{blitByPixel}} is now package-private and documented as the reference
implementation, so tests can compare against it.
I changed the signatures of the three private helpers, since they now take
clipped values. The source and destination must not be the same bitmap, which
is also true of the pixel version, and I noted that in the javadoc.
Before merging, run {{mvn test}} where dependencies are available, and decode
the serenity {{bitmap-composite-and-xnor*.jbig2}} files, since the old comment
named them as the check for this fix. I haven’t committed anything. The changes
are in the working tree of {{{}/home/claude/apache/pdfbox-jbig2{}}}, in
{{Bitmaps.java}} and {{{}BitmapsBlitTest.java{}}}.
I committed the blit fix and the new tests locally as {{{}3e0ebf3{}}}, and the
working tree is clean. I did not push, so the hook’s push request isn’t done.
The only remote is the upstream {{apache/pdfbox-jbig2}} repository, and this
session has read-only access to it. A push would also land on Apache’s
{{{}master{}}}, which I didn’t think you meant by “push these changes”.
To get the change upstream, you can:
* Take the commit from {{/home/claude/apache/pdfbox-jbig2}} (for example
{{{}git format-patch -1{}}}) and apply it in your own checkout.
* Fork the repo and open a PR from there. If you want me to push, I can attach
the repo with push access, but that needs access to a fork or branch you choose.
Before it goes upstream, run {{mvn test}} and the serenity
{{bitmap-composite-and-xnor*.jbig2}} files, since I couldn’t do either here.
> Fix original Bitmaps.blit() code
> --------------------------------
>
> Key: PDFBOX-6157
> URL: https://issues.apache.org/jira/browse/PDFBOX-6157
> Project: PDFBox
> Issue Type: Task
> Components: JBIG2
> Affects Versions: 3.0.4 JBIG2
> Reporter: Tilman Hausherr
> Priority: Minor
>
> Follow-up to PDFBOX-6156, which was fixed with a correct but not very
> efficient solution. The original code should be fixed so that the last bits
> of a byte are handled without touching the other bits of the destination.
> How to test this: use the test code from PDFBOX-6151 on the file mentioned in
> PDFBOX-6156. To see intermediate images, save the bitmaps {{regionBitmap}}
> and {{pageBitmap}} in JBIG2Page.createNormalPage() with a call like this near
> {{Bitmaps.blit()}}:
> {code:java}
> ImageIO.write(Bitmaps.asBufferedImage(pageBitmap), "png", new
> File("XXXX","JPeg2PageResultBitmap-" + System.currentTimeMillis() + ".png"));
> {code}
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]