Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using PIL's ImageDraw Module

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.

My Code:

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

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
like image 545
rectangletangle Avatar asked Jan 31 '11 04:01

rectangletangle


People also ask

What module contains pillow's shape drawing code?

The 'ImageDraw' module provides simple 2D graphics support for Image Object. Generally, we use this module to create new images, annotate or retouch existing images and to generate graphics on the fly for web use. The graphics commands support the drawing of shapes and annotation of text.

How do you draw a line using PIL in Python?

line() Draws a line between the coordinates in the xy list. Parameters: xy – Sequence of either 2-tuples like [(x, y), (x, y), …] or numeric values like [x, y, x, y, …]. fill – Color to use for the line.

How do I use the imagedraw module?

You can use this module to create new images, annotate or retouch existing images, and to generate graphics on the fly for web use. ImageDraw.Draw.text () Draws the string at the given position.

How to draw a 2D image in PIL?

A simple 2D drawing interface for PIL images. :param im: The image to draw in. :param mode: Optional mode to use for color values. For RGB images, this argument can be RGB or RGBA (to blend the drawing into the image). For all other modes, this argument must be the same as the image mode. If omitted, the mode defaults to the mode of the image.

What is imagedraw in Python pillow?

Python’s Pillow which is a fork of the discontinued Python Imaging Library (PIL) is a powerful library that is capable of adding image processing capabilities to your python code. Pillow offers many modules that ease the process of working and modifying images. In this article, we will have a look at the ImageDraw module of this library.

What can I do with the PIL Module?

You can use this module to create new images, annotate or retouch existing images, and to generate graphics on the fly for web use. For a more advanced drawing library for PIL, see the aggdraw module. The graphics interface uses the same coordinate system as PIL itself, with (0, 0) in the upper left corner.


1 Answers

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

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.

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

  • 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.

Here's the fixed __init__ method:

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:

  • 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
like image 114
mpenkov Avatar answered Oct 02 '22 19:10

mpenkov