PILPython中长用的图像处理库。但是它更新较慢,现在都是使用它的一个分支Pillow
Pillow继承了PIL接口并提供能更多功能。

安装

1
pip install Pillow

PillowPIL不能共存,在安装Pillow之前请先卸载PIL。最新版本 Pillow版本是5.0.0支持Python版本是2.7,3.4,3.5,3.6。

概念

Pillow用于处理栅格化的图像,也就是像素矩阵。

波段

图像可以由一个或多个波段数据组成。PIL能使你可以在单个图像中存储多个波段,前提是它们都具有相同的尺寸和深度。例如,一个 PNG图像拥有 R(红),G(蓝),B(绿),A(透明度)四个波段值。你可以对每个波段值进行操作,从而改变图片整体样子。通过getbands获取波段类型。

模式

图像的模式定义图像像素的类型和深度。当前版本支持一下标准的模式:

  • 1 (1-bit pixels, black and white, stored with one pixel per byte) 黑白二值模式
  • L (8-bit pixels, black and white) 黑白灰度模式
  • P (8-bit pixels, mapped to any other mode using a colour palette) 调色板(索引)模式
  • RGB (3x8-bit pixels, true colour) RGB真彩色
  • RGBA (4x8-bit pixels, true colour with transparency mask) RGBA真彩色
  • CMYK (4x8-bit pixels, colour separation) CMYK模式,一种套色模式
  • YCbCr (3x8-bit pixels, colour video format)
  • I (32-bit signed integer pixels) 有符号整数像素
  • F (32-bit floating point pixels) 浮点数像素

大小

通过image的size属性可以获取图片的大小(两个值得元组(width,height))。

坐标体系

PIL使用得是笛卡尔坐标系统。(0,0)在左边顶部,以(0,0)向右延伸是X轴正向而向下延伸是Y轴正向。
矩阵通常是个4-源矩阵,例如:800*600像素的图像矩阵元组是(0,0,800,600)。

API

Pillow拥有十几个模块通过这些模块可以对图片进行:剪辑,反转,合并,添加文字等变化。

Image模块

from PIL import Image,Image是Pillow最基础的模块,通过它可以读取或创建一个image实例,有了这image实例你才能对图像进行各种操作。

PIL.Image.new(mode, size, color=0)=>image

通过Image的new 方法你可以获取一个空白的image图像。你需要确定这个image的模式(mode)、大小(size),底色(color)

PIL.Image.open(fp, mode=’r’)=>image

打开并识别给定的图像。你可以获得图像的大小,模式,类型。它不会读取完整的图片信息只是读取文件头。load方法可以获得完整的图片信息。
fp可也为一个文件路径或一个文件对象。

1
2
3
4
from PIL import Image
im = Image.open('ex1.jpg')
print(im.size,im.mode,im.format)
# (600,800),RGB,JPEG

PIL.Image.alpha_composite(im1, im2)=>image

将im2覆盖在im1上。
im1图像必选是RGBA模式,并且im2图像大小和im1一样。

Image.copy()=>Image

拷贝一个Image副本,保留原图片。

Image.crop(box=None)=>image

传递一个矩阵区域,获取对应的Image。

ImageDraw模块

ImageDraw模块为Image图像提供了2D绘图,你可以使用这个模块创建图像、注释或者润饰已经存在的图像,快速生成用于Web的图形。

1
2
3
4
5
6
7
8
9
10
11
from PIL import Image, ImageDraw

im = Image.open("hopper.jpg")

draw = ImageDraw.Draw(im)
draw.line((0, 0) + im.size, fill=128)
draw.line((0, im.size[1], im.size[0], 0), fill=128)
del draw

# write to stdout
im.save(sys.stdout, "PNG")

PIL.ImageDraw.Draw(image, mode=None)=> Draw image

用给定的图像(image)创建一个绘图对象(Draw image)。
在这个绘图对象你可以添加文字或贴图。

PIL.ImageDraw.ImageDraw.text(xy, text, fill=None, font=None, anchor=None, spacing=0, align=”left”, direction=None, features=None)

在给定的位置上绘制字符串。

  • xy 字符串的坐标
  • text 字符串内容
  • fill 字符串的颜色
  • font 一个ImageFont对象,字符串使用的显示字体。
  • align 字符串对齐方式 ‘left’,’center’,’right’。
PIL.ImageDraw.ImageDraw.textsize(text, font=None, spacing=4, direction=None, features=None)

返回字符串所占空间的大小的(w,h)元组。

  • text 字符串内容
  • font 一个ImageFont对象,

ImageFont

ImageFont模块拥有一个同名的类。根据这个类的方法可以创建一个指定字符串大小和字体的imageFont实例。这个实例传递个PIL.ImageDraw.text()使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
from PIL import ImageFont, ImageDraw

draw = ImageDraw.Draw(image)

# use a bitmap font
font = ImageFont.load("arial.pil")

draw.text((10, 10), "hello", font=font)

# use a truetype font
font = ImageFont.truetype("arial.ttf", 15)

draw.text((10, 25), "world", font=font)

PIL.ImageFont.truetype(font=None, size=10, index=0, encoding=’’, layout_engine=None)=>font

  • font 载入一个TrueType和OpenType字体文件,创建一个字体对象
  • size 指定字体大小

例子

图片缩放

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import os, sys
from PIL import Image

print(sys.argv[1:])
for infile in sys.argv[1:]:
outfile = os.path.splitext(infile)[0] + '.thumbnail'+ os.path.splitext(infile)[1]
if infile != outfile:
im = Image.open(infile)
x, y = im.size
print(os.path.splitext(infile)[0],infile,outfile,x,y)
im.thumbnail((x/2, y/2))
im.save(outfile, im.format)

# python thumbnail.py e1.png e2.png e3.png

接受命令行传递进去的图片文字,取得图片名字和大小。按原来50%比例缩放。

添加中文水印

1
2
3
4
5
6
7
8
9
10
11
12
# -*- coding: UTF-8 -*-
from PIL import Image, ImageDraw, ImageFont

font = ImageFont.truetype('simsun.ttc',24) # 创建一个font对象并指定大小
base = Image.open('e3.jpg').convert('RGBA') # 打开一个图片,并将其转换为RGBA模式
txt = Image.new('RGBA', base.size, (255,255,255,0)) #创建文本image 白底透明
text = "你好!"
draw = ImageDraw.Draw(txt) # 创建一个可绘画得image对象
draw.text((20, 20),text, fill=(255,255,255),font=font)
out = Image.alpha_composite(base, txt)

out.show()

图片截取翻转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from PIL import Image

imageFName = 'e3.jpg'

def image_transpose(image):
xsize, ysize = image.size
xsizeLeft = xsize//2 #获得一个整数

boxLeft = (0, 0, xsizeLeft, ysize)
boxRight = (xsizeLeft, 0, xsize, ysize)
boxLeftNew = (0,0,xsizeLeft,ysize)
boxRightNew = (xsizeLeft, 0, xsize, ysize)

partLeft = image.crop(boxLeft).transpose(Image.FLIP_LEFT_RIGHT).transpose(Image.ROTATE_180)
partRight = image.crop(boxRight)

image.paste(partRight,boxLeftNew)
image.paste(partLeft, boxRightNew)

return image

avatar = Image.open(imageFName)
avatar = image_transpose(avatar)
avatar.show()

参考

https://pillow.readthedocs.io/en/5.0.0/index.html
https://www.gitbook.com/book/mr-zhao/pil/details
https://liam0205.me/2015/04/22/pil-tutorial-basic-usage/