Pillow 编写图像插件
Pillow 使用插件模型,允许您将自己的解码器添加到库中,而无需对库本身进行任何更改。此类插件通常有这样的名称 XxxImagePlugin.py
,其中Xxx
是唯一的格式名称(通常是缩写)。
Pillow >=2.1.0不再以
ImagePlugin.py
名称自动导入python路径中。您需要手动导入图像插件。
Pillow分两个阶段解码文件:
- 它以加载的顺序遍历可用的图像插件,并
_accept
使用文件的前 16 个字节调用插件的函数。如果_accept
函数返回 true
,则调用插件的_open
方法来设置图像元数据和图像图块。该_open
方法不用于解码实际图像数据。 - 当请求图像数据时,该
ImageFile.load
方法被调用,该方法为每个图块设置一个解码器并将数据提供给它。
图像插件应包含从PIL.ImageFile.ImageFile
基类派生的格式处理程序 。这个类应该提供一个_open
方法,它读取文件头并至少设置mode
和 size
属性。为了能够加载文件,该方法还必须创建一个tile
描述符列表,其中包含解码器名称、图块的范围和任何特定于解码器的数据。格式处理程序类必须通过调用Image
模块显式注册。
出于性能原因, _open
方法必须快速拒绝没有适当内容的文件。
例子
下面的插件支持一个简单的格式,它有一个128字节的标题,由单词“SPAM”组成,后跟宽度、高度和像素大小(以位为单位)。标题字段用空格隔开。图像数据紧跟在标题之后,可以是二级、灰度或24位真彩色。
spamimageplugin.py:
from PIL import Image, ImageFile
def _accept(prefix):
return prefix[:4] == b"SPAM"
class SpamImageFile(ImageFile.ImageFile):
format = "SPAM"
format_description = "Spam raster image"
def _open(self):
header = self.fp.read(128).split()
# size in pixels (width, height)
self._size = int(header[1]), int(header[2])
# mode setting
bits = int(header[3])
if bits == 1:
self.mode = "1"
elif bits == 8:
self.mode = "L"
elif bits == 24:
self.mode = "RGB"
else:
raise SyntaxError("unknown number of bits")
# data descriptor
self.tile = [("raw", (0, 0) + self.size, 128, (self.mode, 0, 1))]
Image.register_open(SpamImageFile.format, SpamImageFile, _accept)
Image.register_extensions(SpamImageFile.format, [
".spam",
".spa", # DOS version
])
格式处理程序必须始终设置 size
和 mode
属性。如果未设置,则无法打开文件。为了简化插件,调用代码考虑异常,例如 SyntaxError
, KeyError
, IndexError
, EOFError
和
struct.error
无法识别文件。
请注意,必须使用 PIL.Image.register_open()
. 尽管不是必需的,但最好注册此格式使用的任何扩展名。
导入插件后,就可以使用了:
from PIL import Image
import SpamImagePlugin
with Image.open("hopper.spam") as im:
pass
这个tile
属性
为了能够读取该文件以及识别它, tile
还必须设置属性。这个属性包含一个平铺描述符列表,其中每个描述符指定如何将数据加载到图像中的给定区域。在大多数情况下,只使用一个描述符,覆盖整个图像。
tile描述符是一个包含以下内容的4元组:
(decoder, region, offset, parameters)
字段使用如下:
-
decoder
指定要使用的解码器。这个 raw
这里使用的解码器支持各种像素格式的未压缩数据。有关此解码器的详细信息,请参阅下面的说明。 -
region
一个4元组,指定在映像中存储数据的位置。 -
offset
从文件开头到图像数据的字节偏移量。 -
parameters
解码器的参数。此字段的内容取决于平铺描述符元组中第一个字段指定的解码器。如果解码器不需要任何参数,请用None
于此字段。
请注意 tile
属性包含一个平铺描述符列表,而不仅仅是一个描述符。
更多建议: