20

使用谷歌(和这个网站)我看到了一些类似的问题,但我的问题仍然在这里:

“我想绘制图像(不读取文件),能够操纵该图像中每个像素的颜色。”

我看到了另一个问题,建议在哪里做这样的事情:

from tkinter import *
A=Tk()
B=Canvas(A)
B.place(x=0,y=0,height=256,width=256)
for a in range(256):
    for b in range(256):
        B.create_line(a,b,a+1,b+1,fill=pyList[a][b])#where pyList is a matrix of hexadecimal strings
A.geometry("256x256")
mainloop()

事实上,这回答了我的问题,但是......它非常慢。我应该如何处理 1920x1080 图像?等我死?

所以我要求执行与上述代码相同但以更快的方式执行的操作

我找到了一种改进 jsbueno 建议的方法的方法,在链接的页面中有说明:

为什么 Photoimage 放慢?

4

2 回答 2

37

这确实很棘手——我认为您必须使用 Canvas 小部件,但它也无法访问 Pixels。不过,嵌入在画布中的图像项目确实有。Tkinter.PhotoImage 类确实有一个“put”方法,它接受十六进制格式的颜色和像素坐标:

from tkinter import Tk, Canvas, PhotoImage, mainloop
from math import sin

WIDTH, HEIGHT = 640, 480

window = Tk()
canvas = Canvas(window, width=WIDTH, height=HEIGHT, bg="#000000")
canvas.pack()
img = PhotoImage(width=WIDTH, height=HEIGHT)
canvas.create_image((WIDTH/2, HEIGHT/2), image=img, state="normal")

for x in range(4 * WIDTH):
    y = int(HEIGHT/2 + HEIGHT/4 * sin(x/80.0))
    img.put("#ffffff", (x//4,y))

mainloop()

好消息是,即使以这种方式完成,更新也是“实时”的:您在图像上设置像素,然后看到它们出现在屏幕上。


这应该比在屏幕上绘制更高级别线的方式快得多 - 但对于大量像素,它仍然会很慢,因为每个像素都需要一个 Python 函数调用。任何其他直接操作像素的纯 Python 方式都会受到影响——唯一的出路是从 Python 代码中调用在本机代码中一次操作多个像素的原语。

Cairo 是一个不错的用于获取 2d 绘图的跨平台库,但文档记录也很差 - 它应该比 Tkinter 的 Canvas 或 PhotoImage 具有更好的图元。

于 2012-09-05T17:54:41.167 回答
5

不要忘记在 canvas.create_image 之后保存参考。在某些情况下,尤其是在使用 PIL 模块时,python 会垃圾收集图像,即使它正在显示!语法类似于 canvas.create_image((WIDTH/2, HEIGHT/2), image=img) canvas.image = img

于 2016-12-25T10:01:12.160 回答