使用PIL的ImageDraw模块 [英] Using PIL's ImageDraw Module

查看:154
本文介绍了使用PIL的ImageDraw模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用PIL的ImageDraw模块进行单独的像素操作。下面的代码应该创建Tkinter canvas小部件。然后打开图像,将一个像素的颜色更改为红色,然后将图像嵌入到画布小部件中。但是,它似乎没有用。

I'm trying to do individual pixel manipulation using PIL's ImageDraw Module. The code bellow is supposed to create Tkinter canvas widget. Then open an image, change one pixel's color to red, then embed the image in the canvas widget. However, it doesn't seem to be working.

我的代码:

import Tkinter
from PIL import ImageTk, Image, ImageDraw


class image_manip(Tkinter.Tk):

    def __init__(self):
        Tkinter.Tk.__init__(self)

        self.configure(bg='red')

        self.ImbImage = Tkinter.Canvas(self, highlightthickness=0, bd=0, bg='blue')
        self.ImbImage.pack()

        im = Image.open(r'C:\Python26\Suite\test.png')

        print im.format, im.size, im.mode

        im = ImageDraw.Draw(im)

        im = im.point((0, 0), fill="red")

        self.i = ImageTk.PhotoImage(im)
        self.ImbImage.create_image(139, 59, image=self.i)




def run():
    image_manip().mainloop()
if __name__ == "__main__":
    run()

我在runni时遇到以下错误我的代码:

I get the following error upon running my code:

Exception AttributeError: "PhotoImage instance has no attribute '_PhotoImage__photo'" in <bound method PhotoImage.__del__ of <PIL.ImageTk.PhotoImage instance at 0x05DF7698>> ignored
Traceback (most recent call last):
  File "<string>", line 245, in run_nodebug
  File "C:\Python26\Suite\test_image.py", line 30, in <module>
    run()
  File "C:\Python26\Suite\test_image.py", line 28, in run
    image_manip().mainloop()
  File "C:\Python26\Suite\test_image.py", line 20, in __init__
    self.i = ImageTk.PhotoImage(im)
  File "C:\Python26\lib\site-packages\PIL\ImageTk.py", line 109, in __init__
    mode = Image.getmodebase(mode)
  File "C:\Python26\lib\site-packages\PIL\Image.py", line 245, in getmodebase
    return ImageMode.getmode(mode).basemode
  File "C:\Python26\lib\site-packages\PIL\ImageMode.py", line 50, in getmode
    return _modes[mode]
KeyError: None


推荐答案

你的问题是你将 im 重新分配给多件事。

Your problem is you're reassigning im to multiple things.

im = Image.open(r'C:\Python26\Suite\test.png')
im = ImageDraw.Draw(im)
im = im.point((0, 0), fill="red")

当你打电话给 ImageTk.PhotoImage(im) ,该函数需要一个PIL图像对象,但您已经将 im 分配给 point()的结果函数,实际返回。这是导致问题的原因。

When you call ImageTk.PhotoImage(im), the function expects a PIL image object, but you've already assigned im to the result of the point() function, which actually returns None. This is the cause of your problem.

我认为你误解了ImageDraw的工作原理。有关示例,请查看此处。基本上:

I think you're misunderstanding how ImageDraw works. Have a look here for an example. Basically:


  • 如果你想画一些复杂的东西,你需要一个 ImageDraw 的实例在您的PIL图片上

  • 您仍然需要将PIL图像保存在某个变量中

  • ImageDraw 直接在施工期间给出的图像上绘画

  • 您可以随时丢弃 ImageDraw 对象。它不包含任何重要信息,因为所有内容都直接写入图像。

  • You need an instance of ImageDraw if you want to draw something complicated on your PIL Image
  • You still need to keep your PIL image in some variable
  • ImageDraw paints directly on the image you've given it during construction time
  • You can throw away the ImageDraw object at any point. It doesn't contain any important information because everything is written directly to the image.

这是固定的 __ init__ 方法:

def __init__(self):
    Tkinter.Tk.__init__(self)
    self.configure(bg='red')
    im = Image.open(r'C:\Python26\Suite\test.png')
    width, height = im.size
    self.ImbImage = Tkinter.Canvas(self, highlightthickness=0, bd=0, bg='red', width=width, height=height)
    self.ImbImage.pack()
    print im.format, im.size, im.mode

    draw = ImageDraw.Draw(im)
    draw.rectangle([0, 0, 40, 40 ],  fill="green")
    del draw

    self.i = ImageTk.PhotoImage(im)
    self.ImbImage.create_image(width/2, height/2, image=self.i)

你会注意到我修了几件事:

You'll notice I've fixed a couple of things:


  • 将画布大小设置为图像的大小。显然,你需要在找到图像大小之前加载图像,所以我已经移动了一些东西。

  • 分配 ImageDraw 实例到单独的变量

  • 绘制一个绿色矩形而不是一个点,因为这会更突出。请注意,您不需要获取 draw.rectangle 的返回值 - 它实际上返回,因为大多数其他绘图功能可以。

  • 完成绘图后删除 draw 变量

  • 调用 create_image

  • Set the canvas size to the size of the image. Obviously, you need to load the image before you can find the image size, so I've moved things around a bit.
  • Assign the ImageDraw instance to a separate variable
  • Draw a green rectangle instead of a dot, cause this will stand out more. Note you don't need to grab the return value of draw.rectangle -- it actually returns None, as most other drawing functions do.
  • Delete the draw variable after we're done drawing
  • Center the image in the canvas when calling create_image

这篇关于使用PIL的ImageDraw模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆