阅读(1849) (0)

Pillow 编写图像插件

2021-07-12 14:56:51 更新

Pillow 使用插件模型,允许您将自己的解码器添加到库中,而无需对库本身进行任何更改。此类插件通常有这样的名称​ XxxImagePlugin.py​,其中​Xxx​是唯一的格式名称(通常是缩写)。

Pillow >=2.1.0不再以​ ImagePlugin.py​名称自动导入python路径中。您需要手动导入图像插件。

Pillow分两个阶段解码文件:

  1. 它以加载的顺序遍历可用的图像插件,并​_accept​使用文件的前 16 个字节调用插件的函数。如果​_accept​函数返回 ​true​,则调用插件的​_open​ 方法来设置图像元数据和图像图块。该​_open​方法不用于解码实际图像数据。
  2. 当请求图像数据时,该​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 ​属性包含一个平铺描述符列表,而不仅仅是一个描述符。