Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Things on this page are fragmentary and immature notes/thoughts of the author. Please read with your own judgement!

import numpy as np
from PIL import Image, ImageChops

Image.open

Opens and identifies the given image file. Even though the method Image.open takes a mode argument, it must take the value "r".

Notice that the method Image.open is lazy which means that the image file remains open and the actual image data is not read from the file until needed. This behavior might cause issue sometimes. For example, let’s say that you load many images using the following code and try to combine them into one picke file for easy access.

images = [Image.open(path) for path in Path(".").glob("*.png")]

You will likely encouter an error saying “too many files opened” because all image files are opened and not closed. One simple way to fix this problem is to call the method Image.copy to use the underlying image data, which makes the underlying image file closed automatically.

images = [Image.open(path).copy() for path in Path(".").glob("*.png")]

Of course, you can also manually call the method Image.load to load the image data and close the image file.

def read_image(path: Path) -> Image:
    img = Image.open(path)
    img.load()
    return img      
      
    
images = [read_image(path) for path in Path(".").glob("*.png")
img = Image.open("../../home/media/poker/4h.png")
img
<PIL.PngImagePlugin.PngImageFile image mode=RGB size=37x54 at 0x7F44D628B978>

Load Corruppted Image

You will encounter “IOError: image file truncated” if an image you try to load is corrupted. However, you can still load the image (and fill the truncated part as black pixles) with the following settings. For more details, please refer to Python PIL “IOError: image file truncated” with big images .

from PIL import ImageFile

ImageFile.LOAD_TRUNCATED_IMAGES = True

Image.fromarray

  1. When loading a boolean numpy array (representing a black/white image), you can either use mode=None (default, auto detect the mode) or mode="L" (gray scale). Notice that using mode="1" (black/white) doesn’t load the numpy array correct (which sounds like a bug to me). It is worth noting that when using mode=None the underlying numpy array for the image is still boolean while when using mode="L" the underlying numpy array is float and the boolean values are converted to 0 or 255.

  2. If you every encounter the error “TypeError: Cannot handle this data type” when loading an image using Image.fromarray, it means that the type of elements in the array is not support and you need to manually cast the type of elments in the numpy array (to numpy.uint8) before calling Image.fromarray on it. It is suggested that you always ensure the data type of a numpy array is the desired one before loading it as an image. If the data type of an numpy array is correct, you do not have to specify a mode (the default works well). Otherwise, if the data type is not correct it might not help even if you try to specify different modes. The most commonly used data types when dealing with images are numpy.uint8 and bool (for black/white images).

     :::python
     import numpy as np
     Imagee.fromarray(arr.astype(np.uint8))
  3. NOTE: Even if Image.fromarray accepts a mode parameter, it seems that the mode BGR;24 doesn’t work with Image.fromarray. As an alternative way, you can manually flip a numpy array which is the BGR representation of an image.

     Image.fromarray(np.flip(arr, 2))
arr = np.array(img)
Image.fromarray(arr)
<PIL.Image.Image image mode=RGB size=37x54 at 0x7F44D621C978>
img_bw = img.convert("1", dither=False)
img_bw
<PIL.Image.Image image mode=1 size=37x54 at 0x7F44D627B1D0>
arr_bw = np.array(img_bw)
arr_bw
array([[False, True, True, ..., True, True, True], [ True, True, True, ..., True, True, True], [ True, True, True, ..., True, True, True], ..., [False, True, True, ..., True, True, True], [False, False, False, ..., False, False, False], [False, False, False, ..., False, False, False]])
Image.fromarray(arr_bw)
<PIL.Image.Image image mode=1 size=37x54 at 0x7F44D61C4630>
np.array(Image.fromarray(arr_bw))
array([[False, True, True, ..., True, True, True], [ True, True, True, ..., True, True, True], [ True, True, True, ..., True, True, True], ..., [False, True, True, ..., True, True, True], [False, False, False, ..., False, False, False], [False, False, False, ..., False, False, False]])
Image.fromarray(arr_bw, mode="L")
<PIL.Image.Image image mode=L size=37x54 at 0x7F44D61C49B0>
np.array(Image.fromarray(arr_bw, mode="L"))
array([[ 0, 255, 255, ..., 255, 255, 255], [255, 255, 255, ..., 255, 255, 255], [255, 255, 255, ..., 255, 255, 255], ..., [ 0, 255, 255, ..., 255, 255, 255], [ 0, 0, 0, ..., 0, 0, 0], [ 0, 0, 0, ..., 0, 0, 0]], dtype=uint8)
Image.fromarray(arr_bw, mode="1")
<PIL.Image.Image image mode=1 size=37x54 at 0x7F44D61C4C88>