图像#

如何从文档页面制作图像#

这个小脚本将获取一个文档文件名,并从它的每一页生成一个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.pngpage-1.png 等的 PNG 图像文件。图片的尺寸与其页面相同,宽度和高度四舍五入为整数,例如 A4 纵向页面的尺寸为 595 x 842 像素。它们在 x 和 y 方向上的分辨率为 96 dpi,并且没有透明度。您可以更改所有这些 - 有关如何执行此操作,请阅读接下来的部分。


如何提高 图像分辨率#

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

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

Page.get_pixmap() 默认将使用 Identity 矩阵,该矩阵什么也不做。

在以下内容中,我们对每个维度应用一个的缩放因子为2,这将为我们生成一幅四倍于原始分辨率的图像(大小也大约是原来的4倍):

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 值与图像 文件一起保存——当使用矩阵表示法时,系统不会自动进行此操作。


如何创建局部位图(剪辑)#

您并不总是需要或想要页面的完整图像。这种情况例如在您在GUI中显示图像并希望将相应的窗口填充为页面的放大部分时。

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

为了实现这一点,定义一个矩形,使其等于您希望在GUI中显示的区域,并将其称为“clip”。在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 的剪裁的左上点来计算正确的位图:

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)

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

通常,页面的位图还会显示页面的注释。有时候,这可能并不是所希望的。

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

您还可以单独渲染注释:它们有自己的 Annot.get_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. 使用 Page.get_text() 结合 “dict” 参数。这适用于所有文档类型。它将提取页面上显示的所有文本和图像,格式化为一个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. 创建一个Pixmap,其图像的指令为pix = pymupdf.Pixmap(doc, xref)。这个方法非常快(个位数微秒)。pixmap的属性(宽度,高度,…)将反映图像的属性。在这种情况下,没有办法判断嵌入的原始图像具有哪种格式。

  2. 提取 图像,使用 img = doc.extract_image(xref)。这是一个包含二进制图像数据的字典,作为 img[“image”]。还提供了多种元数据——大部分与您在图像的像素映像中找到的相同。主要区别在于字符串 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. “不需要知道:” 遍历文档的所有交叉引用列表,并对每一个执行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) 创建基本图像的位图。步骤 (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张图片,总大小为514MB(生成的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 秒,并且生成了 510 MB 的 PDF 文件大小。查看 这里 以获取更完整的源代码:它提供了目录选择对话框并跳过非文件条目。

方法 3:附加文件

实现此任务的第三种方法是通过页面注释附加文件,完整的源代码请参见这里

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

_images/img-attach-result.jpg

注意

这两种方法,embedattach 可以用于 任意文件 – 不仅仅是图像。

注意

我们强烈推荐使用这个非常棒的包 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的接口几乎是微不足道的。

输入格式

输出格式

描述

位图

.

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

一般方案仅如下两行:

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

备注

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

  2. 除了输出 文件 外,您还可以通过 pix.tobytes(“yyy”) 创建一个字节对象并传递它。

  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"))

注意

带有透明通道的PNG 转换为 Tkinter PhotoImage。这需要在进行 PPM 转换之前 去除透明通道字节

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"))

如何使用位图:粘贴图像#

这显示了如何将位图用于纯图形、非文档目的。该脚本读取一个图像文件并创建一个由原始图像的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示例,它创建了谢尔宾斯基地毯 - 一个将康托集推广到二维的分形。给定一个方形地毯,标记其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()。这两种方法有相似之处,但也存在差异。

None None None None None None None None None

标准

Page.insert_image()

Page.show_pdf_page()

可显示内容

图像文件,内存中的图像,像素图

PDF页面

显示分辨率

图像分辨率

矢量化(除了栅格页面内容)

旋转

0、90、180 或 270 度

任何角度

裁剪

否(仅全图)

保持纵横比

是(默认选项)

是(默认选项)

透明度(水印)

取决于图像

取决于页面

位置 / 放置

缩放以适应目标矩形

缩放以适应目标矩形

性能

自动防止重复;

自动防止重复;

多页图像支持

易用性

简单、直观;

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

基本代码模式为 Page.insert_image()。必须提供确切的一个参数 filename / stream / pixmap,如果不是重新插入已存在的图像:

None
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 对象(但可以从同一个文件中打开):

None
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
)

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

None

一段给定文本是否在页面上实际可见取决于多个因素:

None
  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以获取更多信息。