如何将画布内容转换为图像?
Posted
技术标签:
【中文标题】如何将画布内容转换为图像?【英文标题】:How can I convert canvas content to an image? 【发布时间】:2012-03-27 08:59:02 【问题描述】:from Tkinter import *
root = Tk()
cv = Canvas(root)
cv.create_rectangle(10,10,50,50)
cv.pack()
root.mainloop()
我想将画布内容转换为位图或其他图像,然后进行其他操作,例如旋转或缩放图像,或更改其坐标。
如果我不再绘图,位图可以提高显示效率。
我该怎么办?
【问题讨论】:
在actionscript中有draw()函数实现,在python tkinter中如何工作? 【参考方案1】:我找到了一种非常有用的方法。为此,您需要 PIL 模块。代码如下:
from PIL import ImageGrab
def getter(widget):
x=root.winfo_rootx()+widget.winfo_x()
y=root.winfo_rooty()+widget.winfo_y()
x1=x+widget.winfo_width()
y1=y+widget.winfo_height()
ImageGrab.grab().crop((x,y,x1,y1)).save("file path here")
它的作用是将小部件名称传递给函数。命令root.winfo_rootx()
和root.winfo_rooty()
获取整个root
窗口左上角的像素位置。
然后,将widget.winfo_x()
和widget.winfo_y()
添加到其中,基本上只是获取要捕获的小部件左上角像素的像素坐标(在屏幕的像素(x,y)处)。
然后我找到了 (x1,y1),它是小部件的左下角像素。 ImageGrab.grab()
制作了一个打印屏幕,然后我裁剪它以仅获取包含小部件的位。虽然不完美,也不会制作出最好的图像,但它是一个很好的工具,可以获取任何小部件的图像并保存它。
如果您有任何问题,请发表评论!希望这有帮助!
【讨论】:
嗨,当我运行代码时,它会很快生成图片。您能否发布一个带有 tkinter 图形的示例脚本然后保存它?也许我在错误的时间放置或调用该函数。 @EerikMuuli 您必须仅在需要拍照时调用该函数。例如,您可以获得一个带有命令的按钮,在按钮命令的函数中,只需将getter(x)
放入其中 x 是小部件,甚至是整个根窗口。应该没问题。如果您还有其他问题,请在此处回复评论。
@EerikMuuli 首先,您使用的是 pyscreenshot 模块而不是 PIL,所以我不完全确定它是如何工作的。由于 PIL 可以做屏幕截图和许多其他功能,我会简单地获取 PIL 模块。此外,看起来你只是想制作画布,然后他们制作了一张矩形的图片。有更简单的方法可以做到这一点!按照自己的方式进行操作,然后使用 PIL 和我在回答中使用的保存功能,如果你真的想在截屏后退出,那么只需输入一个 exit() 或最好是 root.destroy() 命令在 getter 函数定义中。
绝妙的方法!比尝试在空白 PIL 图像上重复所有绘图命令或创建 Postscipt 输出并使用其他工具将其转换为图像要好得多。请注意,可以使用ImageGrab.grab((x,y,x1,y1)).save("file path here")
一步完成,而不是捕获整个屏幕然后裁剪它(请参阅ImageGrab.grab()
文档)。还应该指出,给定的文件扩展名决定了创建的图像文件的格式。
ImportError: ImageGrab is macOS and Windows only
【参考方案2】:
您可以生成 postscript 文档(用于输入其他工具:ImageMagick、Ghostscript 等):
from Tkinter import *
root = Tk()
cv = Canvas(root)
cv.create_rectangle(10,10,50,50)
cv.pack()
root.mainloop()
cv.update()
cv.postscript(file="file_name.ps", colormode='color')
root.mainloop()
或在 PIL 和 Tkinter 的画布上并行绘制相同的图像(请参阅:Saving a Tkinter Canvas Drawing (Python))。例如(受同一篇文章的启发):
from Tkinter import *
import Image, ImageDraw
width = 400
height = 300
center = height//2
white = (255, 255, 255)
green = (0,128,0)
root = Tk()
# Tkinter create a canvas to draw on
cv = Canvas(root, width=width, height=height, bg='white')
cv.pack()
# PIL create an empty image and draw object to draw on
# memory only, not visible
image1 = Image.new("RGB", (width, height), white)
draw = ImageDraw.Draw(image1)
# do the Tkinter canvas drawings (visible)
cv.create_line([0, center, width, center], fill='green')
# do the PIL image/draw (in memory) drawings
draw.line([0, center, width, center], green)
# PIL image can be saved as .png .jpg .gif or .bmp file (among others)
filename = "my_drawing.jpg"
image1.save(filename)
root.mainloop()
【讨论】:
当我尝试转换为 postscript 时,它会调整我的图像大小(保存的 postscript 相对于画布较小);为什么?? 既然postscript是矢量格式,我觉得这应该不是问题【参考方案3】:使用 Pillow 将 Postscript 转换为 PNG
from PIL import Image
def save_as_png(canvas,fileName):
# save postscipt image
canvas.postscript(file = fileName + '.eps')
# use PIL to convert to PNG
img = Image.open(fileName + '.eps')
img.save(fileName + '.png', 'png')
【讨论】:
不错。如果没有画布对象,我该怎么做?假设我有一个 .ps 文件,以及如何将其转换为 .png? 那么就用下面两行吧。 当我尝试这个时,我从 PIL (Pillow) 收到一个错误,即OSError: Unable to locate Ghostscript on paths
。
当我尝试这个时,我从 PIL (Pillow) 收到一个错误,即 OSError: Unable to locate Ghostscript on paths - 我也是【参考方案4】:
也许你可以尝试使用 widget_winfo_id 来获取画布的 HWND。
import win32gui
from PIL import ImageGrab
HWND = canvas.winfo_id() # get the handle of the canvas
rect = win32gui.GetWindowRect(HWND) # get the coordinate of the canvas
im = ImageGrab.grab(rect) # get image of the current location
【讨论】:
你不需要使用win32gui
来获取画布的坐标。有内置的tkinter
方法。以上是关于如何将画布内容转换为图像?的主要内容,如果未能解决你的问题,请参考以下文章