3

PILのImageDrawモジュールを使用して個々のピクセル操作を実行しようとしています。コードはTkinterのキャンバスウィジェットを作成することになっています。その後、画像を開き、1つのピクセルの色を赤に変更して、その画像をキャンバスウィジェットに埋め込みます。しかし、それは動作していないようです。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イメージオブジェクトを期待していますが、まだ実際にNoneを返すpoint()関数の結果にimを割り当てました。これがあなたの問題の原因です。

ImageDrawの仕組みを誤解していると思います。たとえば、hereを見てください。基本的には:

  • あなたは静止画に直接いくつかの変数
  • ImageDraw塗料であなたをあなたのPILのイメージを維持する必要があり、あなたのPILイメージ
  • に複雑なものを描きたい場合は、ImageDrawのインスタンスを必要とします」工事中に与えられたもの
  • ImageDrawオブジェクトはいつでも捨てることができます。すべてが画像に直接書き込まれるため、重要な情報は含まれません。

    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) 
    

    あなたは、私は物事のカップルを修正しました気付くでしょう:

はここで固定__init__方法だ

  • 画像のサイズにキャンバスサイズを設定します。明らかに、イメージサイズを見つける前にイメージをロードする必要があるので、少し動いてきました。
  • 別の変数にのインスタンスを割り当てます。
  • ドットの代わりに緑色の四角形を描くので、これがより顕著になります。返り値draw.rectangleを取得する必要はありません。ほとんどの他の描画関数と同様に、実際にはNoneを返します。私たちは本当に物事をクリアすること、create_image
+0

感謝を呼び出すときに

  • センターキャンバスで画像を描画し終わった後
  • draw変数を削除します。 – rectangletangle

  • +1

    ImageTk.PhotoImage(im)を*永続*(ガベージコレクションされていない)変数に割り当てる必要があることに注意してください。 Tkinterにはバグがあります。バグはローカル変数に割り当ててcreate_imageで使用するだけでガベージコレクションされます。 http://infohost.nmt.edu/tcc/help/pubs/pil/image-tk.htmlを参照してください。 – mckoss

    関連する問題