Opening images: the Image object

Pillow · Essentials · 8 min

Every Pillow task starts from an Image object, and knowing what open actually does avoids file-handle and lazy-loading surprises.

Pillow is installed as pillow but imported as PIL: from PIL import Image. The central class is `Image.Image`.

Image.open(path_or_file) identifies the format from the file's contents, not its extension, and returns an Image. Useful attributes:

  • im.format: the detected file format, such as "JPEG" or "PNG" (None for images you create)
  • im.size: a (width, height) tuple, also im.width and im.height
  • im.mode: how pixels are stored, such as "RGB", "RGBA" or "L" (grayscale)

Image.open is lazy: it reads only the header. Pixel data is decoded when you first need it, or when you call im.load(). The file stays open until then, so use a with block, which closes the file when you are done. If you need the pixels after the block, call im.load() or make a copy inside it.

Image.new(mode, size, color) creates a blank image; colours can be tuples, ints or names like "skyblue" and "#ff8800".

Most methods return a new image rather than changing the original: im.resize(...), im.convert(...), im.rotate(...). A few operate in place and return None, notably im.thumbnail(...) and im.paste(...).

im.getpixel((x, y)) and im.putpixel read and write single pixels; they are fine for a few values, but far too slow for loops over a whole image.

Example

from PIL import Image

im = Image.new("RGB", (320, 200), "skyblue")    # mode, (width, height), colour
print(im.size, im.mode, im.format)              # (320, 200) RGB None
im.save("sky.png")

with Image.open("sky.png") as img:              # lazy: header only so far
    print(img.format, img.size, img.mode)       # PNG (320, 200) RGB
    print(img.width, img.height)                # 320 200
    print(img.getpixel((10, 10)))               # (135, 206, 235)
    img.load()                                  # decode pixels now

bigger = im.resize((640, 400))                  # returns a NEW image
print(im.size, bigger.size)                     # (320, 200) (640, 400)

Remember

  • Install pillow, import from PIL import Image
  • size is (width, height); mode says how pixels are stored
  • Image.open is lazy and detects the format from content
  • Most methods return new images; thumbnail and paste work in place

Watch out for

  • Writing im.resize((w, h)) and expecting im itself to change: assign the returned image.

Check yourself

  1. What does `Image.open('photo.jpg').size` return for a photo 4000 pixels wide and 3000 tall?
  2. A file named `logo.png` actually contains JPEG data. What is `Image.open('logo.png').format`?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: pillow.readthedocs.io/en/stable/reference/Image.html