PIL
PIL - Pillow
Install Pillow
-
PIL
-
Pillow
pip install pillow
Create First Image
- Image
- size
- color
from PIL import Image
img = Image.new('RGB', size=(100, 60), color='#eb8634')
img.save('first.png')
img.show() # Using ImageMagic on Linux
- Color can be one of the well-known names e.g. "red"
- Color can be RGB in decimal or hex. (RGB=Red Green Blue)
Write Text on Image
from PIL import Image, ImageDraw
img = Image.new('RGB', size=(100, 60), color='#eb8634')
draw = ImageDraw.Draw(img)
draw.text(
text="Some text",
xy=(10, 20),
)
img.save('first.png')
img.show()
Select font for Text on Image
from PIL import Image, ImageDraw, ImageFont
img = Image.new(mode='RGB', size=(300, 60), color='#eb8634')
font = ImageFont.truetype('Pillow/Tests/fonts/FreeMono.ttf', 20)
#font = ImageFont.truetype(f'c:\Windows\Fonts\Candara.ttf', 30)
#font = ImageFont.truetype(f'c:\Windows\Fonts\Candarab.ttf', 30)
#font = ImageFont.truetype(f'c:\Windows\Fonts\david.ttf', 30)
draw = ImageDraw.Draw(img)
draw.text(
text="Some text",
xy=(10, 20),
font=font,
)
img.save('first.png')
img.show()
Font directories
Linux: /usr/share/fonts/
Max OS: /Library/Fonts/
Windows: C:\Windows\fonts
Get size of an Image
from PIL import Image
import sys
if len(sys.argv) !=2:
exit(f"Usage: {sys.argv[0]} FILENAME")
in_file = sys.argv[1]
img = Image.open(in_file)
print(img.size) # a tuple
print(img.size[0]) # width
print(img.size[1]) # height
print(sys.getsizeof(img)) # The size of the variable
print(sys.getsizeof(img.tobytes())) # The payload
Get size of text
font = ImageFont.truetype(
'path/to/font.ttf', size
)
size = font.getsize(text)
Resize an existing Image
from PIL import Image
in_file = 'in.png'
out_file = 'new.png'
img = Image.open(in_file)
size = (img.size[0] / 2, img.size[1] / 2)
img.thumbnail(size)
img.save(out_file)
Crop an existing Image
from PIL import Image
in_file = 'in.png'
out_file = 'out.png'
img = Image.open(in_file)
width, height = img.size
width, height = img.size
# crop
# 10 pixels from the left
# 20 pixels from the top
# 30 pixels from the right
# 40 pixels from the bottom
cropped = img.crop((10, 20, width - 30, height - 40))
cropped.save(out_file)
cropped.show()
Combine two images
- Load one image from file
- Create a plain background
- Put the loaded image on the background
- Save the combined image
Rotated text
from PIL import Image, ImageDraw, ImageFont, ImageOps
img = Image.new(mode='RGB', size=(400, 200), color='#eb8634')
font = ImageFont.truetype('Pillow/Tests/fonts/FreeSansBold.ttf', 30)
text_layer = Image.new('L', (330, 50))
draw = ImageDraw.Draw(text_layer)
draw.text( (30, 0), "Text slightly rotated", font=font, fill=255)
rotated_text_layer = text_layer.rotate(10.0, expand=1)
img.paste( ImageOps.colorize(rotated_text_layer, (0,0,0), (10, 10,10)), (42,60), rotated_text_layer)
img.show()
Rotated text in top-right corner
TODO: fix this
from PIL import Image, ImageDraw, ImageFont, ImageOps
width = 400
height = 200
start = 100
end = 50
img = Image.new(mode='RGB', size=(width, height), color='#FAFAFA')
stripe_color = "#eb8634"
draw = ImageDraw.Draw(img)
draw.polygon([(width-start, 0), (width-end, 0), (width, end), (width, start) ], fill=stripe_color)
font = ImageFont.truetype('Pillow/Tests/fonts/FreeSansBold.ttf', 30)
text_layer = Image.new('RGB', size=(100, 100), color=stripe_color)
draw = ImageDraw.Draw(text_layer)
text = "Free"
size = draw.textsize(text=text, font=font)
# print(size)
draw.text( xy=(20, 0), text=text, font=font, fill=1)
#
rotated_text_layer = text_layer.rotate(-45.0, expand=0)
rotated_text_layer.show()
#img.paste( ImageOps.colorize(rotated_text_layer, (0,0,0), (10, 10,10)), (42,60), rotated_text_layer)
#img.paste(im = rotated_text_layer, box=(300, 0))
#img.paste(im = text_layer, box=(300, 0))
#img.show()
Embed image (put one image on another one)
from PIL import Image
in_file = 'python.png'
width = 600
height = 300
background = Image.new(mode='RGB', size=(width, height), color='#AAFAFA')
img = Image.open(in_file)
(emb_width, emb_height) = img.size
print(emb_width)
print(emb_height)
# slightly off the lower right corner of the background image
# using the image as the mask makes its background transparent
background.paste(im = img, box=(width-emb_width-10, height-emb_height-10), mask=img)
background.show()
Draw a triangle
from PIL import Image, ImageDraw
img = Image.new(mode='RGB', size=(800, 450), color='#eb8634')
draw = ImageDraw.Draw(img)
draw.polygon([(790, 275), (790, 430), (300, 430) ])
img.save('first.png')
img.show()
Draw a triangle and write text in it
from PIL import Image, ImageDraw, ImageFont
img = Image.new(mode='RGB', size=(800, 450), color='#eb8634')
draw = ImageDraw.Draw(img)
draw.polygon([(800, 275), (800, 450), (300, 450) ], fill = (255, 255, 255))
font = ImageFont.truetype('Pillow/Tests/fonts/FreeSansBold.ttf', 30)
draw.text((500, 400), 'Hello from Python', (0, 0, 0), font=font)
img.save('first.png')
img.show()
Draw a triangle and write rotated text in it
from PIL import Image, ImageDraw, ImageFont, ImageOps
img = Image.new(mode='RGB', size=(400, 200), color='#eb8634')
# #draw = ImageDraw.Draw(img)
# #draw.polygon([(800, 275), (800, 450), (300, 450) ], fill = (255, 255, 255))
#
#
#font = ImageFont.load_default()
font = ImageFont.truetype('Pillow/Tests/fonts/FreeSansBold.ttf', 30)
# txt = Image.new('L', (500, 500))
# d = ImageDraw.Draw(txt)
# d.text((300, 400), 'Hello from Python', font=font, color="white")
# w=txt.rotate(17.5, expand=1)
#
# #img.paste(txt)
# img.paste( ImageOps.colorize(w, (0,0,0), (255,255,84)), (242,60), w)
# # img.save('first.png')
# img.show()
#
text_layer = Image.new('L', (300, 50))
draw = ImageDraw.Draw(text_layer)
draw.text( (30, 0), "Text slightly rotated", font=font, fill=255)
rotated_text_layer = text_layer.rotate(10.0, expand=1)
img.paste( ImageOps.colorize(rotated_text_layer, (0,0,0), (10, 10,10)), (42,60), rotated_text_layer)
img.show()
Draw a rectangle
from PIL import Image, ImageDraw
img = Image.new('RGB', size=(100, 100))
draw = ImageDraw.Draw(img)
draw.rectangle((10, 10, 90, 90), fill="yellow", outline="red")
img.show()
Draw circle
from PIL import Image, ImageDraw
img = Image.new('RGB', (200, 200))
draw = ImageDraw.Draw(img)
draw.ellipse((50, 50, 150, 150), fill="#F00F4F")
img.show()
Draw heart
from PIL import Image, ImageDraw
def heart(size, fill):
width, height = size
img = Image.new('RGB', size, (0, 0, 0, 0))
draw = ImageDraw.Draw(img)
polygon = [
(width / 10, height / 3),
(width / 10, 81 * height / 120),
(width / 2, height),
(width - width / 10, 81 * height / 120),
(width - width / 10, height / 3),
]
draw.polygon(polygon, fill=fill)
#img.show()
draw.ellipse((0, 0, width / 2, 3 * height / 4), fill=fill)
draw.ellipse((width / 2, 0, width, 3 * height / 4), fill=fill)
return img
img = heart((50, 40), "red")
img.show()
Some samples, including this one, originally by Nadia Alramli
Rectangle with rounded corners
from PIL import Image, ImageDraw
def round_corner(radius, fill):
"""Draw a round corner"""
corner = Image.new('RGB', (radius, radius), (0, 0, 0, 0))
draw = ImageDraw.Draw(corner)
draw.pieslice((0, 0, radius * 2, radius * 2), 180, 270, fill=fill)
return corner
def round_rectangle(size, radius, fill):
"""Draw a rounded rectangle"""
width, height = size
rectangle = Image.new('RGB', size, fill)
corner = round_corner(radius, fill)
rectangle.paste(corner, (0, 0))
rectangle.paste(corner.rotate(90), (0, height - radius)) # Rotate the corner and paste it
rectangle.paste(corner.rotate(180), (width - radius, height - radius))
rectangle.paste(corner.rotate(270), (width - radius, 0))
return rectangle
img = round_rectangle((50, 50), 10, "yellow")
img.show()
Some samples, including this one, originally by Nadia Alramli
TODO
- http://web.archive.org/web/20130115175340/
- http://nadiana.com/pil-tutorial-basic-advanced-drawing
- Make the background color change from top to bottom
- Add straight lines to existing images
- Blur image
- Add rectangle to area on existing image
- Draw other simple images