3

我正在嘗試使用PIL的ImageDraw模塊進行單獨的像素操作。下面的代碼應該創建Tkinter畫布部件。然後打開圖像,將一個像素的顏色更改爲紅色,然後將圖像嵌入到畫布窗口小部件中。但是,它似乎並沒有工作。使用PIL的ImageDraw模塊

我的代碼:

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() 

我在運行我的代碼出現以下錯誤:

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 

回答

7

你的問題是你要重新分配im到許多東西。

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

當你調用ImageTk.PhotoImage(im),該函數需要PIL圖像對象,但你已經分配impoint()功能,這實際上返回None的結果。這是你的問題的原因。

我認爲你誤解了ImageDraw的工作原理。例如,看看here。基本上是:

  • 如果你想畫的東西複雜化你的PIL圖片
  • 您仍然需要直接在圖像你」上保持你的PIL圖像中一些變量
  • ImageDraw油漆你需​​要的ImageDraw實例在施工期間給它
  • 你可以在任何時候扔掉ImageDraw對象。它不包含任何重要信息,因爲所有內容都直接寫入圖像。

這裏的固定__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) 

你會發現我已經修復了一個幾件事情:

  • 設置畫布大小的圖像的大小。很明顯,你需要先加載圖像,然後才能找到圖像的大小,所以我已經移動了一些東西。
  • ImageDraw實例分配給一個單獨的變量
  • 繪製一個綠色的矩形而不是一個圓點,因爲這會更加突出。請注意,您不需要獲取draw.rectangle的返回值 - 它實際上會返回None,正如大多數其他繪圖函數一樣。
  • 刪除draw變量,我們就完成了調用create_image
+0

感謝的時候,真的茅塞頓開繪製

  • 中心在畫布後的圖像。 – rectangletangle 2011-01-31 20:42:59