使用Pycairo创建带有(调整大小)PNG图像的PDF-重新缩放表面问题 [英] Create PDF with (resized) PNG images using Pycairo - rescaling Surface issue
问题描述
我有一些要下载的PNG图片链接,转换为缩略图"并使用Python和Cairo保存为PDF.
I have som PNG image links that I want to download, "convert to thumbnails" and save to PDF using Python and Cairo.
现在,我有一个有效的代码,但是我不知道如何控制纸张上的图像尺寸.有没有一种方法可以将PyCairo Surface调整为我想要的尺寸(恰好小于原始尺寸)?我希望将原始像素缩小"到更高的分辨率(在纸上).
Now, I have a working code, but I don't know how to control image size on paper. Is there a way to resize a PyCairo Surface to the dimensions I want (which happens to be smaller than the original)? I want the original pixels to be "shrinked" to a higher resolution (on paper).
此外,我尝试了PIL的Image.rescale()
函数,但它给了我20x20像素的输出(200x200像素的原始图像中的输出,这不是代码中的标语示例).我想要的是在纸上20x20毫米正方形内绘制的200x200像素图像(而不是我现在得到的200x200毫米正方形)
Also, I tried Image.rescale()
function from PIL, but it gives me back a 20x20 pixel output (out of a 200x200 pixel original image, which is not the banner example on the code). What I want is a 200x200 pixel image plotted inside a 20x20 mm square on paper (instead of a 200x200 mm square as I am getting now)
我当前的代码是:
#!/usr/bin/python
import cairo, urllib, StringIO, Image # could I do it without Image module?
paper_width = 210
paper_height = 297
margin = 20
point_to_milimeter = 72/25.4
pdfname = "out.pdf"
pdf = cairo.PDFSurface(pdfname , paper_width*point_to_milimeter, paper_height*point_to_milimeter)
cr = cairo.Context(pdf)
cr.scale(point_to_milimeter, point_to_milimeter)
f=urllib.urlopen("http://cairographics.org/cairo-banner.png")
i=StringIO.StringIO(f.read())
im=Image.open(i)
# are these StringIO operations really necessary?
imagebuffer = StringIO.StringIO()
im.save(imagebuffer, format="PNG")
imagebuffer.seek(0)
imagesurface = cairo.ImageSurface.create_from_png(imagebuffer)
### EDIT: best answer from Jeremy, and an alternate answer from mine:
best_answer = True # put false to use my own alternate answer
if best_answer:
cr.save()
cr.scale(0.5, 0.5)
cr.set_source_surface(imagesurface, margin, margin)
cr.paint()
cr.restore()
else:
cr.set_source_surface(imagesurface, margin, margin)
pattern = cr.get_source()
scalematrix = cairo.Matrix() # this can also be used to shear, rotate, etc.
scalematrix.scale(2,2) # matrix numbers seem to be the opposite - the greater the number, the smaller the source
scalematrix.translate(-margin,-margin) # this is necessary, don't ask me why - negative values!!
pattern.set_matrix(scalematrix)
cr.paint()
pdf.show_page()
请注意,漂亮的开罗横幅甚至不适合页面... 理想的结果是,我可以以用户空间单位(在这种情况下为毫米)控制此图像的宽度和高度,例如,创建漂亮的标题图像.
Note that the beautiful Cairo banner does not even fit the page... The ideal result would be that I could control the width and height of this image in user space units (milimeters, in this case), to create a nice header image, for example.
感谢您的阅读以及任何帮助或评论!
Thanks for reading and for any help or comment!!
推荐答案
在绘制图像时尝试缩放上下文.
Try scaling the context when you draw the image.
例如
cr.save() # push a new context onto the stack
cr.scale(0.5, 0.5) # scale the context by (x, y)
cr.set_source_surface(imagesurface, margin, margin)
cr.paint()
cr.restore() # pop the context
请参阅: http://cairographics.org/documentation/pycairo/2/reference/context.html 了解更多详情.
See: http://cairographics.org/documentation/pycairo/2/reference/context.html for more details.
这篇关于使用Pycairo创建带有(调整大小)PNG图像的PDF-重新缩放表面问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!