图像#

如何从文档页面创建图像#

这个小脚本将接受一个文档文件名,并从其每个页面生成一个 PNG 文件。

文档可以是任何支持的类型

该脚本作为命令行工具运行,期望文件名作为参数提供。生成的图像文件(每页 1 个)存储在脚本所在的目录中。

import sys, pymupdf  # import the bindings
fname = sys.argv[1]  # get filename from command line
doc = pymupdf.open(fname)  # open document
for page in doc:  # iterate through the pages
    pix = page.get_pixmap()  # render page to an image
    pix.save("page-%i.png" % page.number)  # store image as a PNG

脚本目录现在将包含名为 page-0.png, page-1.png 等的 PNG 图像文件。图片具有其页面的尺寸,宽度和高度四舍五入为整数,例如 A4 竖版页面的 595 x 842 像素。它们在 x 和 y 维度上将具有 96 dpi 的分辨率,并且没有透明度。您可以更改所有这些 – 关于如何做到这一点,请阅读下一节。


如何提高图像分辨率#

文档页面的图像由 Pixmap 表示,创建 pixmap 的最简单方法是通过方法Page.get_pixmap()

此方法有许多选项可以影响结果。其中最重要的是 Matrix,它可以让你缩放、旋转、扭曲或镜像输出。

Page.get_pixmap() 默认将使用 Identity 矩阵,它不做任何事情。

接下来,我们对每个维度应用 2 倍的缩放因子,这将为我们生成一个分辨率提高四倍(尺寸也大约是四倍)的图像。

zoom_x = 2.0  # horizontal zoom
zoom_y = 2.0  # vertical zoom
mat = pymupdf.Matrix(zoom_x, zoom_y)  # zoom factor 2 in each dimension
pix = page.get_pixmap(matrix=mat)  # use 'mat' instead of the identity matrix

自版本 1.19.2 起,有一种更直接的方法来设置分辨率:可以使用参数 "dpi"(每英寸点数)代替 "matrix"。要创建页面的 300 dpi 图像,请指定 pix = page.get_pixmap(dpi=300)。除了符号简洁之外,这种方法还有一个额外的优点,即 dpi 值会随图像文件一起保存 – 这在使用 Matrix 符号时不会自动发生。


如何创建部分 Pixmap (剪辑)#

你并不总是需要或想要页面的完整图像。例如,当你在 GUI 中显示图像并希望用页面的缩放部分填充相应的窗口时,就是这种情况。

假设你的 GUI 窗口有足够的空间显示一个完整的文档页面,但你现在想用页面的右下四分之一来填充这个空间,从而使用四倍更好的分辨率。

为此,定义一个等于你希望在 GUI 中显示的区域的矩形,并将其称为“剪辑”。在 PyMuPDF 中构造矩形的一种方法是提供两个对角相对的角,这正是我们在这里所做的。

_images/img-clip.jpg
mat = pymupdf.Matrix(2, 2)  # zoom factor 2 in each direction
rect = page.rect  # the page rectangle
mp = (rect.tl + rect.br) / 2  # its middle point, becomes top-left of clip
clip = pymupdf.Rect(mp, rect.br)  # the area we want
pix = page.get_pixmap(matrix=mat, clip=clip)

在上面,我们通过指定两个对角相对的点来构造 clip:页面矩形的中心点 mp 和其右下角 rect.br


如何将剪辑缩放到 GUI 窗口#

另请阅读上一节。这次我们希望为剪辑计算缩放因子,使其图像最适合给定的 GUI 窗口。这意味着图像的宽度或高度(或两者)将等于窗口尺寸。对于以下代码片段,你需要提供接收页面剪辑矩形的 GUI 窗口的 WIDTH 和 HEIGHT。

# WIDTH: width of the GUI window
# HEIGHT: height of the GUI window
# clip: a subrectangle of the document page
# compare width/height ratios of image and window

if clip.width / clip.height < WIDTH / HEIGHT:
    # clip is narrower: zoom to window HEIGHT
    zoom = HEIGHT / clip.height
else:  # clip is broader: zoom to window WIDTH
    zoom = WIDTH / clip.width
mat = pymupdf.Matrix(zoom, zoom)
pix = page.get_pixmap(matrix=mat, clip=clip)

反过来,现在假设你知道缩放因子,并且需要计算合适的剪辑

在这种情况下,我们有 zoom = HEIGHT/clip.height = WIDTH/clip.width,所以我们必须设置 clip.height = HEIGHT/zoomclip.width = WIDTH/zoom。选择页面上剪辑的左上角点 tl 来计算正确的 pixmap。

width = WIDTH / zoom
height = HEIGHT / zoom
clip = pymupdf.Rect(tl, tl.x + width, tl.y + height)
# ensure we still are inside the page
clip &= page.rect
mat = pymupdf.Matrix(zoom, zoom)
pix = pymupdf.Pixmap(matrix=mat, clip=clip)

如何创建或抑制注解图像#

通常,页面的 pixmap 也显示页面的注解。有时,这可能不是期望的。

要在渲染的页面上抑制注解图像,只需在 Page.get_pixmap() 中指定 annots=False

你也可以单独渲染注解:它们有自己的 Annot.get_pixmap() 方法。生成的 pixmap 具有与注解矩形相同的尺寸。


如何提取图像:非 PDF 文档#

与前几节不同,本节讨论提取文档中包含的图像,以便它们可以作为一页或多页的一部分显示。

如果你想以文件形式或作为内存区域重新创建原始图像,你基本上有两种选择。

  1. 将你的文档转换为 PDF,然后使用仅适用于 PDF 的提取方法之一。这个代码片段将把文档转换为 PDF。

    >>> pdfbytes = doc.convert_to_pdf()  # this a bytes object
    >>> pdf = pymupdf.open("pdf", pdfbytes)  # open it as a PDF document
    >>> # now use 'pdf' like any PDF document
    
  2. 使用带有“dict”参数的Page.get_text()。这适用于所有文档类型。它将提取页面上显示的所有文本和图像,格式化为 Python 字典。每个图像将出现在一个图像块中,包含元信息和二进制图像数据。有关字典结构的详细信息,请参见 TextPage。该方法对 PDF 文件同样有效。这将创建一个页面上显示的所有图像的列表。

    >>> d = page.get_text("dict")
    >>> blocks = d["blocks"]  # the list of block dictionaries
    >>> imgblocks = [b for b in blocks if b["type"] == 1]
    >>> pprint(imgblocks[0])
    {'bbox': (100.0, 135.8769989013672, 300.0, 364.1230163574219),
     'bpc': 8,
     'colorspace': 3,
     'ext': 'jpeg',
     'height': 501,
     'image': b'\xff\xd8\xff\xe0\x00\x10JFIF\...',  # CAUTION: LARGE!
     'size': 80518,
     'transform': (200.0, 0.0, -0.0, 228.2460174560547, 100.0, 135.8769989013672),
     'type': 1,
     'width': 439,
     'xres': 96,
     'yres': 96}
    

如何提取图像:PDF 文档#

就像 PDF 中的任何其他“对象”一样,图像通过交叉引用号(xref,一个整数)来标识。如果你知道这个号码,你有两种方法访问图像数据。

  1. 使用指令 pix = pymupdf.Pixmap(doc, xref) 创建图像的 Pixmap。此方法非常快(单位是微秒)。pixmap 的属性(宽度、高度等)将反映图像的属性。在这种情况下,无法判断嵌入的原始图像是什么格式。

  2. 使用 img = doc.extract_image(xref) 提取图像。这是一个字典,包含二进制图像数据作为 img[“image”]。还提供了许多元数据 – 大部分与你在图像的 pixmap 中找到的相同。主要区别在于字符串 img[“ext”],它指定了图像格式:除了“png”之外,还可能出现“jpeg”、“bmp”、“tiff”等字符串。如果你想存储到磁盘,请使用此字符串作为文件扩展名。此方法的执行速度应与语句 pix = pymupdf.Pixmap(doc, xref);pix.tobytes() 的总速度进行比较。如果嵌入图像是 PNG 格式,Document.extract_image() 的速度大致相同(并且二进制图像数据相同)。否则,此方法快数千倍,并且图像数据小得多

问题仍然是:“我怎么知道那些图像的‘xref’号?”。对此有两个答案。

  1. “检查页面对象:” 遍历Page.get_images() 的项目。它是一个列表的列表,其项目看起来像 [xref, smask, …],包含图像的xref。然后可以将此xref 用于上述方法之一。将此方法用于有效(未损坏)的文档。但是请注意,同一个图像可能被多次引用(由不同的页面),因此你可能需要提供一种机制来避免多次提取。

  2. “无需知道:” 遍历文档中所有 xrefs 的列表,并为每个 xref 执行一次 Document.extract_image()。如果返回的字典为空,则继续 – 这个xref 不是图像。如果 PDF 损坏(页面不可用),请使用此方法。请注意,PDF 通常包含用于定义其他图像透明度的“伪图像”(“模板遮罩”)。你可能需要提供逻辑来排除这些图像的提取。另请查看下一节。

对于这两种提取方法,都有现成的通用脚本可用。

extract-from-pages.py 逐页提取图像

_images/img-extract-imga.jpg

以及 extract-from-xref.py 按 xref 表提取图像

_images/img-extract-imgb.jpg

如何处理图像遮罩#

PDF 中的某些图像附带图像遮罩。在其最简单的形式中,遮罩表示作为单独图像存储的 Alpha(透明度)字节。为了重建具有遮罩的原始图像,必须使用从其遮罩中提取的透明度字节来“丰富”它。

图像是否具有这种遮罩可以通过 PyMuPDF 中的两种方式之一识别出来。

  1. Document.get_page_images() 的一个项目具有通用格式 (xref, smask, ...),其中 xref 是图像的 xref,而 smask 如果为正,则是遮罩的 xref

  2. Document.extract_image() 的(字典)结果有一个键 “smask”,如果为正,它也包含任何遮罩的 xref

如果 smask == 0,则通过 xref 遇到的图像可以按原样处理。

要使用 PyMuPDF 恢复原始图像,必须执行如下所示的过程:

_images/img-stencil.jpg
>>> pix1 = pymupdf.Pixmap(doc.extract_image(xref)["image"])    # (1) pixmap of image w/o alpha
>>> mask = pymupdf.Pixmap(doc.extract_image(smask)["image"])   # (2) mask pixmap
>>> pix = pymupdf.Pixmap(pix1, mask)                           # (3) copy of pix1, image mask added

步骤 (1) 创建基本图像的 pixmap。步骤 (2) 对图像遮罩执行相同的操作。步骤 (3) 添加一个 alpha 通道并填充透明度信息。

上面的脚本 extract-from-pages.pyextract-from-xref.py 也包含此逻辑。


如何将所有图片(或文件)合并为一个 PDF#

我们在这里展示三个脚本,它们接受一个(图像和其他)文件列表,并将它们全部放入一个 PDF 中。

方法 1:将图像作为页面插入

第一个脚本将每张图像转换为尺寸相同的 PDF 页面。结果将是一个每张图像对应一页的 PDF。它仅适用于支持的图像文件格式。

import os, pymupdf
import PySimpleGUI as psg  # for showing a progress bar
doc = pymupdf.open()  # PDF with the pictures
imgdir = "D:/2012_10_05"  # where the pics are
imglist = os.listdir(imgdir)  # list of them
imgcount = len(imglist)  # pic count

for i, f in enumerate(imglist):
    img = pymupdf.open(os.path.join(imgdir, f))  # open pic as document
    rect = img[0].rect  # pic dimension
    pdfbytes = img.convert_to_pdf()  # make a PDF stream
    img.close()  # no longer needed
    imgPDF = pymupdf.open("pdf", pdfbytes)  # open stream as PDF
    page = doc.new_page(width = rect.width,  # new page with ...
                       height = rect.height)  # pic dimension
    page.show_pdf_page(rect, imgPDF, 0)  # image fills the page
    psg.EasyProgressMeter("Import Images",  # show our progress
        i+1, imgcount)

doc.save("all-my-pics.pdf")

这将生成一个 PDF,其大小仅比所有图片的总大小略大。以下是一些性能数据。

上述脚本在我的机器上处理 149 张总大小为 514 MB 的图片(生成的 PDF 大小也大致相同)大约需要 1 分钟。

_images/img-import-progress.jpg

点击此处查看更完整的源代码:它提供目录选择对话框,并跳过不支持的文件和非文件条目。

注意

我们可能已经使用 Page.insert_image() 而不是 Page.show_pdf_page(),结果将是一个看起来相似的文件。然而,根据图像类型,它可能会存储未压缩的图像。因此,必须使用保存选项 deflate = True 来实现合理的文件大小,这会显著增加处理大量图像时的运行时。因此,此处不建议使用此替代方法。

方法 2:嵌入文件

第二个脚本嵌入任意文件 – 不仅是图像。生成的 PDF 将只有一页(空白页),这是出于技术原因所需的。要稍后再次访问嵌入文件,你需要一个能够显示和/或提取嵌入文件的合适 PDF 查看器。

import os, pymupdf
import PySimpleGUI as psg  # for showing progress bar
doc = pymupdf.open()  # PDF with the pictures
imgdir = "D:/2012_10_05"  # where my files are

imglist = os.listdir(imgdir)  # list of pictures
imgcount = len(imglist)  # pic count
imglist.sort()  # nicely sort them

for i, f in enumerate(imglist):
    img = open(os.path.join(imgdir,f), "rb").read()  # make pic stream
    doc.embfile_add(img, f, filename=f,  # and embed it
                        ufilename=f, desc=f)
    psg.EasyProgressMeter("Embedding Files",  # show our progress
        i+1, imgcount)

page = doc.new_page()  # at least 1 page is needed

doc.save("all-my-pics-embedded.pdf")
_images/img-embed-progress.jpg

这是目前最快的方法,它也生成最小的输出文件大小。上述图片在我的机器上需要 20 秒,生成的 PDF 大小为 510 MB。请点击此处查看更完整的源代码:它提供目录选择对话框,并跳过非文件条目。

方法 3:附加文件

实现此任务的第三种方法是通过页面注解附加文件,请点击此处查看完整的源代码。

这与之前的脚本性能相似,并且生成的文件大小也相似。它将生成显示每个附加文件的“文件附件”图标的 PDF 页面。

_images/img-attach-result.jpg

注意

嵌入附加这两种方法都可用于任意文件 – 不仅是图像。

注意

我们强烈建议使用强大的 PySimpleGUI 包来显示可能长时间运行的任务的进度条。它是纯 Python 实现,使用 Tkinter(无需额外的 GUI 包),并且只需要多写一行代码!


如何创建矢量图像#

从文档页面创建图像的常用方法是 Page.get_pixmap()。Pixmap 表示光栅图像,因此你必须在创建时决定其质量(即分辨率)。之后无法更改。

PyMuPDF 还提供一种创建页面 SVG 格式(可伸缩矢量图形,用 XML 语法定义)的矢量图像的方法。SVG 图像在不同缩放级别下仍保持精确(当然,其中嵌入的任何光栅图形元素除外)。

指令 svg = page.get_svg_image(matrix=pymupdf.Identity) 返回一个 UTF-8 字符串 svg,可以将其保存为扩展名为“.svg”的文件。


如何转换图像#

作为众多功能之一,PyMuPDF 的图像转换非常简单。在许多情况下,它可以避免使用其他图形包,如 PIL/Pillow。

尽管如此,与 Pillow 的接口几乎微不足道。

输入格式

输出格式

描述

BMP

.

Windows 位图

JPEG

JPEG

联合图像专家组

JXR

.

JPEG 扩展范围

JPX/JP2

.

JPEG 2000

GIF

.

图形交换格式

TIFF

.

标签图像文件格式

PNG

PNG

便携式网络图形

PNM

PNM

便携式任意图

PGM

PGM

便携式灰度图

PBM

PBM

便携式位图

PPM

PPM

便携式像素图

PAM

PAM

便携式任意图

.

PSD

Adobe Photoshop 文档

.

PS

Adobe Postscript

一般方案只需以下两行

pix = pymupdf.Pixmap("input.xxx")  # any supported input format
pix.save("output.yyy")  # any supported output format

备注

  1. pymupdf.Pixmap(arg)输入参数可以是一个文件或一个包含图像的 bytes / io.BytesIO 对象。

  2. 除了输出到文件,你也可以通过 pix.tobytes(“yyy”) 创建一个 bytes 对象并传递它。

  3. 当然,输入和输出格式必须在色彩空间和透明度方面兼容。Pixmap 类在需要调整时已包含所需功能。

注意

将 JPEG 转换为 Photoshop:

pix = pymupdf.Pixmap("myfamily.jpg")
pix.save("myfamily.psd")

注意

JPEG 转换为 Tkinter PhotoImage。任何 RGB / 无 Alpha 图像都完全一样。转换为任何一种便携式任意图格式(PPM, PGM 等)都可以奏效,因为所有 Tkinter 版本都支持它们。

import tkinter as tk
pix = pymupdf.Pixmap("input.jpg")  # or any RGB / no-alpha image
tkimg = tk.PhotoImage(data=pix.tobytes("ppm"))

注意

带 Alpha 通道的 PNG 转换为 Tkinter PhotoImage。这需要在进行 PPM 转换之前移除 Alpha 字节

import tkinter as tk
pix = pymupdf.Pixmap("input.png")  # may have an alpha channel
if pix.alpha:  # we have an alpha channel!
    pix = pymupdf.Pixmap(pix, 0)  # remove it
tkimg = tk.PhotoImage(data=pix.tobytes("ppm"))

如何使用 Pixmap:拼接图像#

这展示了 pixmap 如何用于纯图形、非文档目的。脚本读取一个图像文件并创建一个新图像,该图像由原始图像的 3 * 4 个图块组成。

import pymupdf
src = pymupdf.Pixmap("img-7edges.png")      # create pixmap from a picture
col = 3                                  # tiles per row
lin = 4                                  # tiles per column
tar_w = src.width * col                  # width of target
tar_h = src.height * lin                 # height of target

# create target pixmap
tar_pix = pymupdf.Pixmap(src.colorspace, (0, 0, tar_w, tar_h), src.alpha)

# now fill target with the tiles
for i in range(col):
    for j in range(lin):
        src.set_origin(src.width * i, src.height * j)
        tar_pix.copy(src, src.irect) # copy input to new loc

tar_pix.save("tar.png")

这是输入图片

_images/img-7edges.png

这是输出

_images/img-target.png

如何使用 Pixmap:生成分形#

这是另一个 Pixmap 示例,创建了谢尔宾斯基地毯 – 一种将康托尔集推广到二维的分形。给定一个方形地毯,标记其 9 个子方形(3 乘 3),然后挖出中心的一个。以相同的方式处理剩余的八个子方形,并无限重复。最终结果是一个面积为零、分形维数约为 1.8928 的集合…

该脚本通过细化到单像素粒度,创建其近似的 PNG 图像。要提高图像精度,请更改 n(精度)的值。

import pymupdf, time
if not list(map(int, pymupdf.VersionBind.split("."))) >= [1, 14, 8]:
    raise SystemExit("need PyMuPDF v1.14.8 for this script")
n = 6                             # depth (precision)
d = 3**n                          # edge length

t0 = time.perf_counter()
ir = (0, 0, d, d)                 # the pixmap rectangle

pm = pymupdf.Pixmap(pymupdf.csRGB, ir, False)
pm.set_rect(pm.irect, (255,255,0)) # fill it with some background color

color = (0, 0, 255)               # color to fill the punch holes

# alternatively, define a 'fill' pixmap for the punch holes
# this could be anything, e.g. some photo image ...
fill = pymupdf.Pixmap(pymupdf.csRGB, ir, False) # same size as 'pm'
fill.set_rect(fill.irect, (0, 255, 255))   # put some color in

def punch(x, y, step):
    """Recursively "punch a hole" in the central square of a pixmap.

    Arguments are top-left coords and the step width.

    Some alternative punching methods are commented out.
    """
    s = step // 3                 # the new step
    # iterate through the 9 sub-squares
    # the central one will be filled with the color
    for i in range(3):
        for j in range(3):
            if i != j or i != 1:  # this is not the central cube
                if s >= 3:        # recursing needed?
                    punch(x+i*s, y+j*s, s)       # recurse
            else:                 # punching alternatives are:
                pm.set_rect((x+s, y+s, x+2*s, y+2*s), color)     # fill with a color
                #pm.copy(fill, (x+s, y+s, x+2*s, y+2*s))  # copy from fill
                #pm.invert_irect((x+s, y+s, x+2*s, y+2*s))       # invert colors

    return

#==============================================================================
# main program
#==============================================================================
# now start punching holes into the pixmap
punch(0, 0, d)
t1 = time.perf_counter()
pm.save("sierpinski-punch.png")
t2 = time.perf_counter()
print ("%g sec to create / fill the pixmap" % round(t1-t0,3))
print ("%g sec to save the image" % round(t2-t1,3))

结果应该看起来像这样

_images/img-sierpinski.png

如何与 NumPy 交互#

这展示了如何从 numpy 数组创建 PNG 文件(比大多数其他方法快数倍)。

import numpy as np
import pymupdf
#==============================================================================
# create a fun-colored width * height PNG with pymupdf and numpy
#==============================================================================
height = 150
width  = 100
bild = np.ndarray((height, width, 3), dtype=np.uint8)

for i in range(height):
    for j in range(width):
        # one pixel (some fun coloring)
        bild[i, j] = [(i+j)%256, i%256, j%256]

samples = bytearray(bild.tostring())    # get plain pixel data from numpy array
pix = pymupdf.Pixmap(pymupdf.csRGB, width, height, samples, alpha=False)
pix.save("test.png")

如何向 PDF 页面添加图像#

有两种方法可以向 PDF 页面添加图像:Page.insert_image()Page.show_pdf_page()。这两种方法有共同之处,但也有区别。

标准

Page.insert_image()

Page.show_pdf_page()

可显示内容

图像文件、内存中的图像、pixmap

PDF 页面

显示分辨率

图像分辨率

矢量化(光栅页面内容除外)

旋转

0, 90, 180 或 270 度

任意角度

剪辑

否(仅完整图像)

保持纵横比

是(默认选项)

是(默认选项)

透明度(水印)

取决于图像

取决于页面

位置 / 放置

缩放以适应目标矩形

缩放以适应目标矩形

性能

自动防止重复;

自动防止重复;

多页图像支持

易用性

简单,直观;

简单,直观;通过 Document.convert_to_pdf() 转换为 PDF 后,可用于所有文档类型(包括图像!)

Page.insert_image() 的基本代码模式。除非重新插入现有图像,否则必须提供参数 filename / stream / pixmap 中的恰好一个

page.insert_image(
    rect,                  # where to place the image (rect-like)
    filename=None,         # image in a file
    stream=None,           # image in memory (bytes)
    pixmap=None,           # image from pixmap
    mask=None,             # specify alpha channel separately
    rotate=0,              # rotate (int, multiple of 90)
    xref=0,                # re-use existing image
    oc=0,                  # control visibility via OCG / OCMD
    keep_proportion=True,  # keep aspect ratio
    overlay=True,          # put in foreground
)

Page.show_pdf_page() 的基本代码模式。源 PDF 和目标 PDF 必须是不同的 Document 对象(但可以从同一个文件打开)。

page.show_pdf_page(
    rect,                  # where to place the image (rect-like)
    src,                   # source PDF
    pno=0,                 # page number in source PDF
    clip=None,             # only display this area (rect-like)
    rotate=0,              # rotate (float, any value)
    oc=0,                  # control visibility via OCG / OCMD
    keep_proportion=True,  # keep aspect ratio
    overlay=True,          # put in foreground
)

如何使用 Pixmap:检查文本可见性#

页面上的给定文本片段是否实际可见取决于多种因素:

  1. 文本没有被其他对象覆盖,但颜色可能与背景相同,例如,白色背景上的白色文本等。

  2. 文本可能被图像或矢量图形覆盖。检测这一点是一项重要能力,例如,用于揭示匿名处理不当的法律文件。

  3. 文本被创建为隐藏状态。这种技术通常被 OCR 工具用来将识别的文本存储在页面上的一个不可见层中。

以下展示了如何检测上述情况 1 或情况 2(如果覆盖对象是单色的话)。

pix = page.get_pixmap(dpi=150)  # make page image with a decent resolution

# the following matrix transforms page to pixmap coordinates
mat = page.rect.torect(pix.irect)

# search for some string "needle"
rlist = page.search_for("needle")
# check the visibility for each hit rectangle
for rect in rlist:
    if pix.color_topusage(clip=rect * mat)[0] > 0.95:
        print("'needle' is invisible here:", rect)

方法 Pixmap.color_topusage() 返回一个元组 (ratio, pixel),其中 0 < ratio <= 1,而 pixel 是颜色的像素值。请注意,我们只创建一次 pixmap。如果存在多个命中矩形,这可以节省大量处理时间。

上述代码的逻辑是:如果针的矩形是(“几乎”:> 95%)单色,则文本不可见。可见文本的典型结果是返回背景颜色(多数是白色)和比例在 0.7 到 0.8 之间,例如 (0.685, b'xffxffxff')


本软件按“原样”提供,不附带任何明示或暗示的担保。本软件根据许可协议分发,除许可协议明确授权外,不得复制、修改或分发。有关许可信息,请参阅 artifex.com 或联系 Artifex Software Inc., 39 Mesa Street, Suite 108A, San Francisco CA 94129, United States 获取更多信息。