文档:https://pillow.readthedocs.io/en/stable/index.html
计算机图像基础
颜色和RGBA值
计算机程序通常将图像中的颜色表示为 RGBA 值。RGBA 值是一组数字,指定顔色中的红、绿、蓝和 alpha(透明度)的值。这些值是从 0(根本没有)到 255(最高)的整数。
这些 RGBA 值分配给单个像素,像素是计算机屏幕上能显示一种顔色的最小点(你可以想到,屏幕上有几百万像素)。像素的 RGB 设置准确地告诉它应该显示哪种颜色的色彩。
图像也有一个 alpha 值,用于生成 RGBA 值。如果图像显示在屏幕上,遮住了背景图像或桌面墙纸,alpha 值决定了“透过”这个图像的象素,你可以看到多少背景。
在 Pillow 中,RGBA 值表示为四个整数值的元组。例如,红色表示为(255,0,0,255)。这种颜色中红的值为最大,没有绿和蓝,并且 alpha 值最大,这意味着它完全不透明。绿色表示为(0,255,0,255),蓝色是(0,0,255,255)。白色是各种颜色的组合,即(255,255,255,255),而黑色没有任何颜色,是(0,0,0,255)。
如果颜色的 alpha 值为 0,不论 RGB 值是什么,该颜色是不可见的。毕竟,不可见的红色看起来就像不可见的黑色一样。
Pillow 使用了 HTML 使用的标准颜色名称。下面列出了一些标准颜色的名称和值。
Pillow 提供 ImageColor.getcolor()函数,所以你不必记住想用的顔色的 RGBA 值。该函数接受一个颜色名称字符串作为第一个参数,字符串'RGBA'作为第二个参数,返回一个 RGBA 元组。
坐标和 Box 元组
图像像素用 x 和 y 坐标指定,分别指定像素在图像中的水平和垂直位置。原点是位于图像左上角的像素,用符号(0,0)指定。第一个 0 表示 x 坐标,它以原点处为 0,从左至右增加。第二个 0 表示 y 坐标,它以原点处为 0,从上至下增加。
这值得重复一下:y 坐标向下走增加,你可能还记得数学课上使用的 y 坐标,与此相反。
许多 Pillow 函数和方法需要一个矩形元组参数。这意味着 Pillow 需要一个四个整坐标的元组,表示图像中的一个矩形区域。四个整数按顺序分别是:
- 左:该矩形的最左边的 x 坐标
- 顶:该矩形的顶边的 y 坐标
- 右:该矩形的最右边右面一个像素的 x 坐标。此整数必须比左边整数大
- 底:该矩形的底边下面一个像素的 y 坐标。此整数必须比顶边整数大
注意:该矩形包括左和顶坐标,直到但不包括右和底坐标
用 Pillow 操作图像
加载图像
要加载图像,就从 Pillow 导入 Image 模块,并调用 Image.open(),传入图像的文件名。
Pillow 的模块名称是PIL,这保持与老模块Python Imaging Library 向后兼容,这就是为什么必须 from PIL importImage,而不是 from Pillow import Image。由于Pillow 的创建者设计Pillow 模块的方式,你必须使用from PIL import Image 形式的 import 语句,而不是简单地 import PIL。
Image.open()函数的返回值是 Image 对象数据类型,它是 Pillow 将图像表示为Python 值的方法。可以调用 Image.open(),传入文件名字符串,从一个图像文件(任何格式)加载一个 Image 对象。通过 save()方法,对 Image 对象的所有更改都可以保存到图像文件中(也是任何格式)。所有的旋转、调整大小、裁剪、绘画和其他图像操作,都通过这个 Image 对象上的方法调用来完成。
from PIL import Image
catIm = Image.open('a.png')
将新图像进行保存:save()
Pillow 还提供了 Image.new()函数,它返回一个 Image 对象。这很像 Image.open(),不过 Image.new()返回的对象表示空白的图像。Image.new()的参数如下:
- 字符串'RGBA',将颜色模式设置为 RGBA(还有其他模式,但本书没有涉及)。
- 大小,是两个整数元组,作为新图像的宽度和高度。
- 图像开始采用的背景颜色,是一个表示 RGBA 值的四整数元组。你可以用ImageColor.getcolor()函数的返回值作为这个参数。另外,Image.new()也支持传入标准颜色名称的字符串。
处理 Image 数据类型
Image 对象有一些有用的属性,提供了加载的图像文件的基本信息:它的宽度和高度、文件名和图像格式(如 JPEG、GIF 或 PNG)。
读取进来的catIm的属性:
- size:返回一个元组,存放图片的宽高像素数
- filename:原始文件的名称
- format:原始图片的格式
- format_description:原始图片的格式(详细)
裁剪图片
裁剪图像是指在图像内选择一个矩形区域,并删除矩形之外的一切。
Image 对象的 crop()方法接受一个矩形元组,返回一个 Image 对象,表示裁剪后的图像。裁剪不是在原图上发生的,也就是说,原始的 Image 对象原封不动,crop()方法返回一个新的 Image 对象。
矩形元组(这里就是要裁剪的区域)包括左列和顶行的像素,直至但不包括右列和底行的像素。
复制和粘贴图像到其他图像
copy()方法返回一个新的 Image 对象,它和原来的 Image 对象具有一样的图像。如果需要修改图像,同时也希望保持原有的版本不变,这非常有用。
paste()方法在 Image 对象调用,将另一个图像粘贴在它上面。
尽管名称是 copy()和 paste(),但 Pillow 中的方法不使用计算机的剪贴板
注意:paste()方法在原图上修改它的 Image 对象,它不会返回粘贴后图像的Image 对象。如果想调用 paste(),但还要保持原始图像的未修改版本,就需要先复制图像,然后在副本上调用 paste()。
调整图像大小
resize()方法在 Image 对象上调用,返回指定宽度和高度的一个新 Image 对象。
它接受两个整数的元组作为参数,表示返回图像的新高度和宽度。
resize()方法不会在原图上修改Image 对象,而是返回一个新的Image 对象。
旋转和翻转图像
图像可以用 rotate()方法旋转,该方法返回旋转后的新 Image 对象,并保持原始Image 对象不变。rotate()的参数是一个整数或浮点数,表示图像逆时针旋转的度数。
当图像旋转 90 度或 270 度时,宽度和高度会变化。如果旋转其他角度,图像的原始尺寸会保持。在 Windows 上,使用黑色的背景来填补旋转造成的缝隙,如图 17-8 所示。在 OS X 上,使用透明的像素来填补缝隙。rotate()方法有一个可选的 expand 关键字参数,如果设置为 True,就会放大图像的尺寸,以适应整个旋转后的新图像。
利用 transpose()方法,还可以得到图像的“镜像翻转”。必须向 transpose()方法传入 Image.FLIP_LEFT_RIGHT 或 Image.FLIP_TOP_BOTTOM。
像 rotate()一样,transpose()会创建一个新 Image 对象。
更改单个像素
单个像素的颜色可以通过getpixel()和putpixel()方法取得和设置。它们都接受一个元组,表示像素的 x 和 y 坐标。putpixel()方法还接受一个元组,作为该像素的颜色。这个顔色参数是四整数RGBA 元组或三整数RGB 元组。
在图像上绘画
如果需要在图像上画线、矩形、圆形或其他简单形状,就用Pillow的ImageDraw模块。
from PIL import Image, ImageDraw
im = Image.new('RGBA', (200, 200), 'white')
draw = ImageDraw.Draw(im)
首先,我们导入 Image 和 ImageDraw。然后,创建一个新的图像,在这个例子中,是 200×200 的白色图像,将这个 Image 对象保存在 Im 中。我们将该 Image 对象传入 ImageDraw.Draw()函数,得到一个 ImageDraw 对象。这个对象有一些方法,可以在 Image 对象上绘制形状和文字。将 ImageDraw 对象保存在变量 draw 中,这样就能在接下来的例子中方便地使用它。
绘制形状
下面的 ImageDraw 方法在图像上绘制各种形状。这些方法的 fill 和 outline 参数是可选的,如果未指定,默认为白色。
点
point(xy, fill)
方法绘制单个像素。xy 参数表示要画的点的列表。该列表可以是 x和 y 坐标的元组的列表,例如[(x, y), (x, y), ...]
,或是没有元组的 x 和 y 坐标的列表,例如[x1, y1, x2, y2, ...]
。fill 参数是点的颜色,要么是一个 RGBA 元组,要么是颜色名称的字符串,如'red'。fill 参数是可选的。
线
line(xy, fill, width)
方法绘制一条线或一系列的线。xy 要么是一个元组的列表,例如[(x, y), (x, y), ...]
,要么是一个整数列表,例如[x1, y1, x2, y2, ...]
。每个点都是正在绘制的线上的一个连接点。可选的 fill 参数是线的颜色,是一个 RGBA 元组或颜色名称。可选的 width 参数是线的宽度,如果未指定,缺省值为1。
矩形
rectangle(xy, fill, outline)
方法绘制一个矩形。xy 参数是一个矩形元组,形式为(left,top, right, bottom)。left 和 top 值指定了矩形左上角的x 和 y 坐标,right 和bottom 指定了矩形的右下角。可选的 fill 参数是颜色,将填充该矩形的内部。可选的 outline 参数是矩形轮廓的颜色。
椭圆
ellipse(xy, fill, outline)
方法绘制一个椭圆。如果椭圆的宽度和高度一样,该方法将绘制一个圆。xy 参数是一个矩形元组(left, top, right, bottom)
,它表示正好包含该椭圆的矩形。可选的fill 参数是椭圆内的颜色,可选的outline 参数是椭圆轮廓的颜色。
多边形
polygon(xy, fill, outline)
方法绘制任意的多边形。xy 参数是一个元组列表,例如[(x, y), (x, y), ...]
,或者是一个整数列表,例如[x1, y1, x2, y2, ...]
,表示多边形边的连接点。最后一对坐标将自动连接到第一对坐标。可选的 fill 参数是多边形内部的颜色,可选的 outline 参数是多边形轮廓的颜色。
绘制文本
ImageDraw 对象还有 text()方法,用于在图像上绘制文本:
- xy 参数是两个整数的元组,指定文本区域的左上角。
- text 参数是想写入的文本字符串。
- 可选参数 fill 是文本的颜色。
- 可选参数 font 是一个 ImageFont 对象,用于设置文本的字体和大小。
因为通常很难预先知道一块文本在给定的字体下的大小,所以 ImageDraw 模块也提供了 textsize()
方法。它的第一个参数是要测量的文本字符串,第二个参数是可选的 ImageFont 对象。textsize()
方法返回一个两整数元组,表示如果以指定的字体写入图像,文本的宽度和高度。可以利用这个宽度和高度,帮助你精确计算文本放在图像上的位置。
text()的前三个参数非常简单。在用 text()向图像绘制文本之前,让我们来看看可选的第四个参数,即 ImageFont 对象。
text()和 textsize()都接受可选的 ImageFont 对象,作为最后一个参数。要使用的话:from PIL import ImageFont
导入Pillow 的 ImageFont 模块,就可以调用 ImageFont.truetype()函数,它有两个参数。第一个参数是字符串,表示字体的TrueType 文件,这是硬盘上实际的字体文件。TrueType 字体文件具有.TTF 文件扩展名,通常可以在以下文件夹中找到:
- 在 Windows 上:C:WindowsFonts。
- 在 OS X 上:/Library/Fonts and /System/Library/Fonts。
- 在 Linux 上:/usr/share/fonts/truetype。
ImageFont.truetype()的第二个参数是一个整数,表示字体大小的点数(而不是像素)。请记住,Pillow 创建的PNG 图像默认是每英寸 72 像素,一点是1/72 英寸。