PIL - Image

https://pillow.readthedocs.io/en/stable/reference/Image.html

https://pillow.readthedocs.io/en/latest/reference/open_files.html

https://en.wikipedia.org/wiki/Grace_Hopper

https://en.wikipedia.org/wiki/Lenna

INTRODUCTION

The 'Image' module provides a class with the same name which is used to represent a PIL image. The module also provides a number of factory functions, including functions to load images from files, and to create new images.

READING AND WRITING IMAGES


# PIL.Image.open(fp, mode='r', formats=None)
# fp : a filename (string), pathlib.Path object or a file object
#
# This is a lazy operation; this function identifies the file, but the file
# remains open and the actual image data is not read from the file until
# you try to process the data.

from PIL import Image

image1 = Image.open(file_name)
# processing ...
image1.close()

with Image.open(file_name) as image2:   # recommended
    print(image2.mode)
    print(image2.format)

image3.save(file_name, format)
image3.save("foto.jpg", "JPEG")
image3.save("foto.jpg") # the filename extension is used to discover the file format

CREATE THUMBNAILS


# The thumbnail size will preserve the aspect of the image and
# it will be no larger than the given size.
# Note that this function modifies the Image object in place.
# If you need to use the full resolution image as well,
# apply this method to a copy() of the original image.

with Image.open("hopper.jpg") as im:
    im.thumbnail((128, 128))   # miniatura
    im.save('hopper_thumbnail.jpg', "JPEG")

CONSTRUCTING IMAGES


# PIL.Image.new(mode, size, color=0)
# mode : the mode to use for the new image
# size : a 2-tuple, containing (width, height) in pixels
# color : default is black

im = Image.new("RGB", (512, 512), color='black') # color=(0, 0, 0)
im = Image.new("RGB", (512, 512), color='red') # color=(255, 0, 0)
im = Image.new("RGB", (512, 512), color='green') # color=(0, 255, 0)
im = Image.new("RGB", (512, 512), color='blue') # color=(0, 0, 255)
im = Image.new("RGB", (512, 512), color='gray') # color=(128, 128, 128)
im = Image.new("RGB", (512, 512), color='white') # color=(255, 255, 255)

im = Image.new("L", (512, 512), color='black') # color=0
im = Image.new("L", (512, 512), color='gray') # color=128
im = Image.new("L", (512, 512), color='white') # color=255

# PIL.Image.fromarray(obj, mode=None)

import numpy as np

a = np.zeros((128,128), dtype="uint8")   # black background
for i in range(64):
    for j in range(32,96):
        a[i,j] = 255   # white square

im = Image.fromarray(a, mode='L')
print ( im.getpixel((0,0)) ) # 0, (x,y)
print ( im.getpixel((32,64)) ) # 0, (x,y)
print ( im.getpixel((64,32)) ) # 255, (x,y)

im = Image.open("hopper.jpg")
print(im.mode)   # RGB
print(im.size)   # (517, 606)
print(im.format)   # JPEG
print(im.getpixel((0,0)))   # pixel (21, 26, 82)

a = np.asarray(im)
#a = np.array(im)   # the same result

print(a.dtype)   # uint8
print(a.shape)   # (606, 517, 3)

GEOMETRICAL TRANSFORMS


# Rotating images.

with Image.open("hopper.jpg") as im:
    im.rotate(45).show()
    # im.rotate() returns a new rotated image
    # new_im = im.rotate(45)
    # new_im.save("rotated.jpg")

# Resizing images.

with Image.open("hopper.jpg") as im:
    im.resize((130,150)).show()
    # im.resize() returns a new resized image
    # new_im = im.resize((130,150))
    # new_im.save("resized.jpg")

# This crops the input image with the provided coordinates.

with Image.open("hopper.jpg") as im:
    (left, upper, right, lower) = (20, 20, 100, 100)
    im.crop((left, upper, right, lower)).show()
    #
    # Here the image "im" is cropped and assigned to new variable im_crop
    # im_crop = im.crop((left, upper, right, lower))
    # im_crop.save("cropped.jpg")

COLOR TRANSFORMS


with Image.open("hopper.jpg") as im:
    im.convert("L").show()
    # im.convert() returns a converted copy of the image
    # new_im = im.convert("L")
    # new_im.save("bw.bmp")

PASTE


# Image.paste(im, box=None, mask=None)
#
# Pastes another image into this image.

# Add margins of any width vertically and horizontally.
# +--------------+
# |l   top      r|
# |e +--------+ i|
# |f |original| g|
# |t +--------+ h|
# |    bottom   t|
# +--------------+

def add_margin(image, top, right, bottom, left, color):
    width, height = image.size
    new_width = width + right + left
    new_height = height + top + bottom
    result = Image.new(image.mode, (new_width, new_height), color)
    result.paste(image, (left, top))
    return result

# Add margins to the rectangle to make it square.
# +-----------+  +---+---+---+
# |           |  |   |   |   |
# +-----------+  |   |ori|   |
# | original  |  |   |gin|   |
# +-----------+  |   |al |   |
# |           |  |   |   |   |
# +-----------+  +---+---+---+

def expand2square(image, background_color):
    width, height = image.size
    if width == height:
        return image
    elif width > height:
        result = Image.new(image.mode, (width, width), background_color)
        result.paste(image, (0, (width - height) // 2))
        return result
    else:
        result = Image.new(image.mode, (height, height), background_color)
        result.paste(image, ((height - width) // 2, 0))
        return result