PyMuPDF 1.24.4 中文文档(十二)(3)https://developer.aliyun.com/article/1559506
PDF 标准混合模式
有关说明,请参阅 Adobe PDF References,第 324 页:
PDF_BM_Color "Color" PDF_BM_ColorBurn "ColorBurn" PDF_BM_ColorDodge "ColorDodge" PDF_BM_Darken "Darken" PDF_BM_Difference "Difference" PDF_BM_Exclusion "Exclusion" PDF_BM_HardLight "HardLight" PDF_BM_Hue "Hue" PDF_BM_Lighten "Lighten" PDF_BM_Luminosity "Luminosity" PDF_BM_Multiply "Multiply" PDF_BM_Normal "Normal" PDF_BM_Overlay "Overlay" PDF_BM_Saturation "Saturation" PDF_BM_Screen "Screen" PDF_BM_SoftLight "Softlight"
图章注释图标
MuPDF 为橡皮图章注释定义了以下图标:
STAMP_Approved 0 STAMP_AsIs 1 STAMP_Confidential 2 STAMP_Departmental 3 STAMP_Experimental 4 STAMP_Expired 5 STAMP_Final 6 STAMP_ForComment 7 STAMP_ForPublicRelease 8 STAMP_NotApproved 9 STAMP_NotForPublicRelease 10 STAMP_Sold 11 STAMP_TopSecret 12 STAMP_Draft 13
对此页面有任何反馈吗?
此软件按原样提供,不附带任何明示或暗示的保证。此软件根据许可证分发,未经许可不得复制、修改或分发。有关详细信息,请参阅 artifex.com 的许可信息或联系美国加利福尼亚州旧金山 Mesa 街 39 号 108A 室的 Artifex Software Inc。
此文档涵盖了所有版本直到 1.24.4。
色彩数据库
自引入涉及颜色的方法(如Page.draw_circle()
)以来,可能需要访问预定义的颜色。
精美的 GUI 包wxPython具有超过 540 种预定义的 RGB 颜色数据库,这些颜色具有更多或更少可以记住的名称。其中不仅包括标准名称如“green”或“blue”,还有“turquoise”、“skyblue”以及 100(不仅仅是 50…)种“gray”等。
我们已经自由地复制了这个数据库(一个元组列表)修改为 PyMuPDF,并将其颜色作为 PDF 兼容的浮点三元组提供:对于 wxPython 的*(“WHITE”, 255, 255, 255),我们返回(1, 1, 1),可以直接用于color和fill*参数。我们还接受任何混合大小写的“wHiTe”以找到颜色。
函数getColor()
由于可能不经常需要颜色数据库,因此一个额外的导入语句似乎是可以接受的,以便访问它:
>>> # "getColor" is the only method you really need >>> from pymupdf.utils import getColor >>> getColor("aliceblue") (0.9411764705882353, 0.9725490196078431, 1.0) >>> # >>> # to get a list of all existing names >>> from pymupdf.utils import getColorList >>> cl = getColorList() >>> cl ['ALICEBLUE', 'ANTIQUEWHITE', 'ANTIQUEWHITE1', 'ANTIQUEWHITE2', 'ANTIQUEWHITE3', 'ANTIQUEWHITE4', 'AQUAMARINE', 'AQUAMARINE1'] ... >>> # >>> # to see the full integer color coding >>> from pymupdf.utils import getColorInfoList >>> il = getColorInfoList() >>> il [('ALICEBLUE', 240, 248, 255), ('ANTIQUEWHITE', 250, 235, 215), ('ANTIQUEWHITE1', 255, 239, 219), ('ANTIQUEWHITE2', 238, 223, 204), ('ANTIQUEWHITE3', 205, 192, 176), ('ANTIQUEWHITE4', 139, 131, 120), ('AQUAMARINE', 127, 255, 212), ('AQUAMARINE1', 127, 255, 212)] ...
打印颜色数据库
如果您真的想看看有多少可用的颜色,可以使用示例目录中的脚本print by RGB或print by HSV。它们在相同的目录中创建 PDF 文件(已经存在),其中包含所有这些颜色。它们唯一的区别是排序顺序:一个按 RGB 值排序,另一个按色相-饱和度值作为排序标准。这是这些文件的屏幕打印样式。
您对本页有什么反馈吗?
此软件按原样提供,不带任何明示或暗示的担保。此软件在许可下分发,除非根据该许可明确授权,否则不得复制、修改或分发。请参阅artifex.com的许可信息,或联系美国加利福尼亚州旧金山 Mesa Street 39 号 108A 套房的 Artifex Software Inc.获取更多信息。
本文档覆盖所有版本直到 1.24.4。
函数getColor()
由于可能不经常需要颜色数据库,因此一个额外的导入语句似乎是可以接受的,以便访问它:
>>> # "getColor" is the only method you really need >>> from pymupdf.utils import getColor >>> getColor("aliceblue") (0.9411764705882353, 0.9725490196078431, 1.0) >>> # >>> # to get a list of all existing names >>> from pymupdf.utils import getColorList >>> cl = getColorList() >>> cl ['ALICEBLUE', 'ANTIQUEWHITE', 'ANTIQUEWHITE1', 'ANTIQUEWHITE2', 'ANTIQUEWHITE3', 'ANTIQUEWHITE4', 'AQUAMARINE', 'AQUAMARINE1'] ... >>> # >>> # to see the full integer color coding >>> from pymupdf.utils import getColorInfoList >>> il = getColorInfoList() >>> il [('ALICEBLUE', 240, 248, 255), ('ANTIQUEWHITE', 250, 235, 215), ('ANTIQUEWHITE1', 255, 239, 219), ('ANTIQUEWHITE2', 238, 223, 204), ('ANTIQUEWHITE3', 205, 192, 176), ('ANTIQUEWHITE4', 139, 131, 120), ('AQUAMARINE', 127, 255, 212), ('AQUAMARINE1', 127, 255, 212)] ...
打印颜色数据库
如果您想实际看看许多可用颜色的外观,可以使用脚本 print by RGB 或者 print by HSV 在示例目录中。它们会创建 PDF 文件(已存在于同一目录中),展示所有这些颜色。它们唯一的区别在于排序顺序:一个按照 RGB 值排序,另一个按照色调-饱和度-亮度值排序。这是这些文件外观的屏幕截图。
您对本页面有任何反馈吗?
此软件按原样提供,没有明示或暗示的任何保证。此软件根据许可证分发,未经授权的情况下不得复制、修改或分发此软件。有关详细信息,请参阅 artifex.com 的许可信息或联系美国加利福尼亚州旧金山 Mesa Street 39 号 108A 套房的 Artifex Software Inc。
此文档涵盖了截至 1.24.4 版本的所有内容。
其他
附录 1:文本提取的详细信息
本章介绍了 PyMuPDF 的文本提取方法背景。
感兴趣的信息包括
- 它们提供了什么?
- 它们意味着什么(处理时间/数据大小)?
TextPage 的一般结构
TextPage 是(Py-)MuPDF 的类之一。通常在使用 Page 文本提取方法时在幕后创建(和销毁),但也可以直接使用并且可以作为持久对象使用。除了其名称所示,图像也可以选择性地作为文本页面的一部分:
<page> <text block> <line> <span> <char> <image block> <img>
一个文本页面由块(≈大致段落)组成。
一个块由行及其字符或图像组成。
一行由span组成。
一个span由具有相同字体属性的相邻字符组成:名称、大小、标志和颜色。
纯文本
函数TextPage.extractText()
(或者Page.get_text(“text”))提取页面的原始顺序中的纯文本。
一个示例输出:
>>> print(page.get_text("text")) Some text on first page.
注意
输出可能与习惯的“自然”阅读顺序不一致。但是,您可以执行page.get_text("text", sort=True)
请求按照“从左上到右下”的方案重新排序。
块
函数TextPage.extractBLOCKS()
(或者Page.get_text(“blocks”))提取页面的文本块作为像这样的项目列表:
(x0, y0, x1, y1, "lines in block", block_no, block_type)
前 4 个项目是块的浮点坐标。每个块内的行由换行符连接。
这是一种高速方法,默认情况下也会提取图像的元信息:每个图像显示为一个块,其中包含元信息的文本行。图像本身不会显示。
与上面的简单文本输出一样,也可以使用sort
参数来获取阅读顺序。
示例输出:
>>> print(page.get_text("blocks", sort=False)) [(50.0, 88.17500305175781, 166.1709747314453, 103.28900146484375, 'Some text on first page.', 0, 0)]
单词
函数TextPage.extractWORDS()
(或者Page.get_text(“words”))提取页面的文本单词作为像这样的项目列表:
(x0, y0, x1, y1, "word", block_no, line_no, word_no)
前 4 个项目是单词的浮点 bbox 坐标。最后三个整数提供有关单词位置的更多信息。
这是一种高速方法。与前面的方法一样,参数sort=True
将重新排序单词。
示例输出:
>>> for word in page.get_text("words", sort=False): print(word) (50.0, 88.17500305175781, 78.73200225830078, 103.28900146484375, 'Some', 0, 0, 0) (81.79000091552734, 88.17500305175781, 99.5219955444336, 103.28900146484375, 'text', 0, 0, 1) (102.57999420166016, 88.17500305175781, 114.8119888305664, 103.28900146484375, 'on', 0, 0, 2) (117.86998748779297, 88.17500305175781, 135.5909881591797, 103.28900146484375, 'first', 0, 0, 3) (138.64898681640625, 88.17500305175781, 166.1709747314453, 103.28900146484375, 'page.', 0, 0, 4)
HTML
TextPage.extractHTML()
(或者Page.get_text(“html”)输出完整反映了TextPage页面的结构 - 就像下面的 DICT / JSON 一样。其中包括图像、字体信息和文本位置。如果包含在 HTML 头和尾部代码中,它可以被互联网浏览器轻松显示。我们上面的例子:
>>> for line in page.get_text("html").splitlines(): print(line) <div id="page0" style="position:relative;width:300pt;height:350pt; background-color:white"> <p style="position:absolute;white-space:pre;margin:0;padding:0;top:88pt; left:50pt"><span style="font-family:Helvetica,sans-serif; font-size:11pt">Some text on first page.</span></p> </div>
控制 HTML 输出的质量
尽管 MuPDF v1.12.0 中的 HTML 输出已经有了很大改进,但还不是无 bug 的:我们在字体支持和图像定位方面发现了问题。
- HTML 文本包含对原始文档中使用的字体的引用。如果浏览器不认识这些字体(几乎不可能!),它将用其他字体替换它们;结果可能看起来很奇怪。这个问题因浏览器而异——在我的 Windows 机器上,MS Edge 表现得很好,而 Firefox 看起来很糟糕。
- 对于具有复杂结构的 PDF 文件,图像可能无法正确地定位和/或调整大小。这在旋转页面和页面 bbox 变体不重合的情况下可能发生(例如MediaBox != CropBox)。我们还不知道如何解决这个问题——我们在 MuPDF 的网站上提交了一个 bug 报告。
要解决字体问题,您可以使用一个简单的实用脚本扫描 HTML 文件并替换字体引用。这里有一个小例子,将所有字体替换为 PDF 基本 14 种字体之一:有衬线字体将变成“Times”,非衬线字体将变成“Helvetica”,等宽字体将变成“Courier”。希望您的浏览器能够正确处理它们的粗体、斜体等变体:
import sys filename = sys.argv[1] otext = open(filename).read() # original html text string pos1 = 0 # search start poition font_serif = "font-family:Times" # enter ... font_sans = "font-family:Helvetica" # ... your choices ... font_mono = "font-family:Courier" # ... here found_one = False # true if search successful while True: pos0 = otext.find("font-family:", pos1) # start of a font spec if pos0 < 0: # none found - we are done break pos1 = otext.find(";", pos0) # end of font spec test = otext[pos0 : pos1] # complete font spec string testn = "" # the new font spec string if test.endswith(",serif"): # font with serifs? testn = font_serif # use Times instead elif test.endswith(",sans-serif"): # sans serifs font? testn = font_sans # use Helvetica elif test.endswith(",monospace"): # monospaced font? testn = font_mono # becomes Courier if testn != "": # any of the above found? otext = otext.replace(test, testn) # change the source found_one = True pos1 = 0 # start over if found_one: ofile = open(filename + ".html", "w") ofile.write(otext) ofile.close() else: print("Warning: could not find any font specs!")
DICT(或 JSON)
TextPage.extractDICT()
(或 Page.get_text(“dict”, sort=False))输出完全反映了TextPage的结构,并为每个块、行和 span 提供了图像内容和位置详细信息(bbox——以像素为单位的边界框)。对于 DICT 输出,图像以bytes形式存储,而对于 JSON 输出,它们以 base64 编码字符串存储。
要查看字典输出结构的可视化,请查看字典输出的结构。
这是它的外观:
{ "width": 300.0, "height": 350.0, "blocks": [{ "type": 0, "bbox": (50.0, 88.17500305175781, 166.1709747314453, 103.28900146484375), "lines": ({ "wmode": 0, "dir": (1.0, 0.0), "bbox": (50.0, 88.17500305175781, 166.1709747314453, 103.28900146484375), "spans": ({ "size": 11.0, "flags": 0, "font": "Helvetica", "color": 0, "origin": (50.0, 100.0), "text": "Some text on first page.", "bbox": (50.0, 88.17500305175781, 166.1709747314453, 103.28900146484375) }) }] }] }
RAWDICT(或 RAWJSON)
TextPage.extractRAWDICT()
(或 Page.get_text(“rawdict”, sort=False))是DICT的信息超集,将详细级别提升一步。它看起来与上面的完全相同,只是其中的*“text”项目(string)在 spans 中被“chars”列表替换。每个“chars”条目都是一个字符dict*。例如,以下是上述*“text”: “Text in black color.”*条目的替代内容:
"chars": [{ "origin": (50.0, 100.0), "bbox": (50.0, 88.17500305175781, 57.336997985839844, 103.28900146484375), "c": "S" }, { "origin": (57.33700180053711, 100.0), "bbox": (57.33700180053711, 88.17500305175781, 63.4530029296875, 103.28900146484375), "c": "o" }, { "origin": (63.4530029296875, 100.0), "bbox": (63.4530029296875, 88.17500305175781, 72.61600494384766, 103.28900146484375), "c": "m" }, { "origin": (72.61600494384766, 100.0), "bbox": (72.61600494384766, 88.17500305175781, 78.73200225830078, 103.28900146484375), "c": "e" }, { "origin": (78.73200225830078, 100.0), "bbox": (78.73200225830078, 88.17500305175781, 81.79000091552734, 103.28900146484375), "c": " " < ... deleted ... > }, { "origin": (163.11297607421875, 100.0), "bbox": (163.11297607421875, 88.17500305175781, 166.1709747314453, 103.28900146484375), "c": "." }],
XML
TextPage.extractXML()
(或 Page.get_text(“xml”))版本提取了没有图像的文本,详细级别与 RAWDICT 相同:
>>> for line in page.get_text("xml").splitlines(): print(line) <page id="page0" width="300" height="350"> <block bbox="50 88.175 166.17098 103.289"> <line bbox="50 88.175 166.17098 103.289" wmode="0" dir="1 0"> <font name="Helvetica" size="11"> <char quad="50 88.175 57.336999 88.175 50 103.289 57.336999 103.289" x="50" y="100" color="#000000" c="S"/> <char quad="57.337 88.175 63.453004 88.175 57.337 103.289 63.453004 103.289" x="57.337" y="100" color="#000000" c="o"/> <char quad="63.453004 88.175 72.616008 88.175 63.453004 103.289 72.616008 103.289" x="63.453004" y="100" color="#000000" c="m"/> <char quad="72.616008 88.175 78.732 88.175 72.616008 103.289 78.732 103.289" x="72.616008" y="100" color="#000000" c="e"/> <char quad="78.732 88.175 81.79 88.175 78.732 103.289 81.79 103.289" x="78.732" y="100" color="#000000" c=" "/> ... deleted ... <char quad="163.11298 88.175 166.17098 88.175 163.11298 103.289 166.17098 103.289" x="163.11298" y="100" color="#000000" c="."/> </font> </line> </block> </page>
注意
我们已经成功测试了lxml来解释此输出。
PyMuPDF 1.24.4 中文文档(十二)(5)https://developer.aliyun.com/article/1559512