Any plans to support arbitrary image rotation angles? #1658
-
I want to losslessly rotate and shear skewed scanned images (typically smartphone captures) by:
Looking at PDF 32000-1:2008 p.205, it seems applying transformation matrices to images is possible:
However, image-maintenance.md states that:
So:
Regards |
Beta Was this translation helpful? Give feedback.
Replies: 6 comments 5 replies
-
First of all, CTMs are already used of course - in image and all other insertions.
I am having no difficulties showing pages from other PDFs in any angle. So you might,
|
Beta Was this translation helpful? Give feedback.
-
For example, insert some Pillow image rotated left by 45°: from PIL import Image
import fitz
import io
img=Image.open("beauty-contest.jpg")
img.size
(607, 741)
src = fitz.open() # the 1-page PDF with the image
# give page width / height from image
spage = src.new_page(width=img.size[0], height=img.size[1])
fp = io.BytesIO()
img.save(fp, "JPEG") # make image memory
# and insert in PDF as fullpage image
spage.insert_image(spage.rect, stream=fp.getvalue())
5
doc = fitz.open() # your target PDF
page = doc.new_page()
rect = fitz.Rect(100,100,300,300) # image should land inside this
page.show_pdf_page(rect, src, 0, rotate=45)
7
doc.ez_save("test.pdf") |
Beta Was this translation helpful? Give feedback.
-
I'll need to test it out on pdf input since pillow and the like don't handle jpegs losslessly but this seems about right. Thanks! Btw, refactoring show_pdf_page() as a primitive that takes a CTM in (so calc_matrix is an external function) would be for the best. Putting aside how it reflects the PDF's own structure, even if you were to put down entry points variables for simple shifting and shearing, there's some fancy projections transformation matrices that can compensate for image capture angles that would still be best left as CTMs. On a side note, linear transformations math are covered in game engines tutorialst. Personally I can't remember any of it so it's more of a note-to-self really... ;) Still, thought I mention it in case someone passes by with similar interests and no clue what transformation matrices are. |
Beta Was this translation helpful? Give feedback.
-
Found some time to mess around with this again and managed a proof-of-concept prototype img2pdf output transformation:
I believe img2pdf always has just the 1 content stream so it should work on all img2pdf single-page outputs but masks might be an issue? Regardless, the general purpose version will cover those scenarios I guess. I actually did all of this first in pikepdf (the qpdf bindings) since the low-level APIs there were well documented:
But I don't want to deal with c++ for such a simple use case and I want to render with mupdf so I've converted it to pymupdf. The general purpose version does things differently. I got it working in pikepdf by duplicating the page to create a graphic stack and modifying that:
I believe pymupdf's existing n-up APIs should similarly create graphic stacks so it should work about the same but I haven't looked into it yet. Anyhow, that's about it for now. I'll try to find some time and wrap things up next couple of weeks. Thanks for the tips. p.s. In https://pymupdf.readthedocs.io/en/latest/faq.html#low-level-interfaces , the first example should read print(doc.xref_object(xref, compressed=False)) instead of print(doc.xref_object(i, compressed=False)). |
Beta Was this translation helpful? Give feedback.
-
the slightly more general purpose prototype with pymupdf:
Anyhow, I still don't know how to use the mupdf parser on the content stream (it should be there somewhere...) so I rolled a half baked junky lexer and hacked around that. Still, this should work on all single page pdfs, img2pdf or otherwise. So, that's good enough for me I guess. That's that I guess. |
Beta Was this translation helpful? Give feedback.
-
Thanks! And yeah, to clarify, the hacked-up mini-lexer above only happens to work on the specific, non-arbitrary graphic stacks coming off Thanks again :) p.s. References on how to roll your own lexer/parser:
Best of luck. |
Beta Was this translation helpful? Give feedback.
For example, insert some Pillow image rotated left by 45°:
Result looks like this: