从 PDF 创建图像(PNG 或 JPEG)以及图像中文本的 HTML 图像映射?

Jas*_*n S 1 html pdf imagemap

我正在记录我维护的系统。本文档包含我在 TeX/TikZ 中创建的图表,该图表被渲染为 PDF 文件。然后,我将 PDF 文件转换为图像文件(通过 imagemagick 的 PNG),并将其包含在我的 HTML 文档中。效果很好。

现在我想为图像创建一个图像映射,以便我可以添加超链接/鼠标悬停/等。我希望根据系统中的更改定期更新此图像,因此如果可能的话,我希望自动化此过程。

当 PDF 文件渲染为 PNG 时,有没有办法使用软件库或工具自动创建 PDF 文件中各种文本内容的图像映射?

这是我创建的要点的一个示例:

在此输入图像描述

在这种情况下,我想通过在 PDF 中定位它们的边界框,将一些不同的文本字符串转换为超链接:

  • controller
  • actuator
  • sensor
  • A
  • B
  • C
  • D
  • u
  • y
  • F(s)
  • G(s)
  • H(s)

(它们都是PDF文件中的文本内容;我可以在Acrobat Reader中选择其中任何文本,然后复制+粘贴到我的文本编辑器中。)

有没有办法做到这一点?

cod*_*ody 5

我能够整理出以下可以作为起点的 Python 解决方案。它将 pdf 转换为 png 并输出相应的图像映射标记。

\n\n

它将输出 dpi 作为可选参数(默认 200),以便将边界框从默认 pdf dpi 72 正确缩放到 png 上:

\n\n
from pdf2image import convert_from_path\nfrom pdfminer.converter import PDFPageAggregator\nfrom pdfminer.layout import LAParams, LTTextBox\nfrom pdfminer.pdfinterp import PDFPageInterpreter\nfrom pdfminer.pdfinterp import PDFResourceManager\nfrom pdfminer.pdfpage import PDFPage\n\nfrom yattag import Doc, indent\n\nimport argparse\nimport os\n\n\ndef transform_coords(lobj, mb):\n\n    # Transform LTTextBox bounding box to image map area bounding box.\n    #\n    # The bounding box of each LTTextBox is specified as:\n    #\n    # x0: the distance from the left of the page to the left edge of the box\n    # y0: the distance from the bottom of the page to the lower edge of the box\n    # x1: the distance from the left of the page to the right edge of the box\n    # y1: the distance from the bottom of the page to the upper edge of the box\n    #\n    # So the y coordinates start from the bottom of the image. But with image map\n    # areas, y coordinates start from the top of the image, so here we subtract\n    # the bounding box\'s y-axis values from the total height.\n\n    return [lobj.x0, mb[3] - lobj.y1, lobj.x1, mb[3] - lobj.y0]\n\n\ndef get_imagemap(d):\n    doc, tag, text = Doc().tagtext()\n    with tag("map", name="map"):\n        for k, v in d.items():\n            doc.stag("area", shape="rect", coords=",".join(v), href="", alt=k)\n    return indent(doc.getvalue())\n\n\ndef get_bboxes(pdf, dpi):\n    fp = open(pdf, "rb")\n    rsrcmgr = PDFResourceManager()\n    device = PDFPageAggregator(rsrcmgr, laparams=LAParams())\n    interpreter = PDFPageInterpreter(rsrcmgr, device)\n    page = list(PDFPage.get_pages(fp))[0]\n\n    interpreter.process_page(page)\n    layout = device.get_result()\n\n    # PDFminer reports bounding boxes based on a dpi of 72. I could not find a way\n    # to change this, so instead I scale each coordinate by multiplying by dpi/72\n    scale = dpi / 72.0\n\n    return {\n        lobj.get_text().strip(): [\n            str(int(x * scale)) for x in transform_coords(lobj, page.mediabox)\n        ]\n        for lobj in layout\n        if isinstance(lobj, LTTextBox)\n    }\n\n\ndef main():\n    parser = argparse.ArgumentParser()\n    parser.add_argument("pdf")\n    parser.add_argument("--dpi", type=int, default=200)\n\n    args = parser.parse_args()\n\n    page = list(convert_from_path(args.pdf, args.dpi))[0]\n    page.save(f"{os.path.splitext(args.pdf)[0]}.png", "PNG")\n\n    print(get_imagemap(get_bboxes(args.pdf, args.dpi)))\n\n\nif __name__ == "__main__":\n    main()\n
Run Code Online (Sandbox Code Playgroud)\n\n

结果示例:

\n\n

\r\n
\r\n
<img src="https://i.stack.imgur.com/aXWMc.png" usemap="#map">\r\n<map name="map">\r\n  <area shape="rect" coords="361,8,380,43" href="#" alt="B" />\r\n  <area shape="rect" coords="434,31,500,64" href="#" alt="G(s)" />\r\n  <area shape="rect" coords="432,93,502,117" href="#" alt="actuator" />\r\n  <area shape="rect" coords="552,8,572,42" href="#" alt="C" />\r\n  <area shape="rect" coords="596,58,609,86" href="#" alt="y" />\r\n  <area shape="rect" coords="105,26,119,40" href="#" alt="+" />\r\n  <area shape="rect" coords="107,54,122,78" href="#" alt="\xe2\x88\x92" />\r\n  <area shape="rect" coords="35,58,51,86" href="#" alt="u" />\r\n  <area shape="rect" coords="164,8,182,43" href="#" alt="A" />\r\n  <area shape="rect" coords="163,152,183,187" href="#" alt="D" />\r\n  <area shape="rect" coords="241,31,311,64" href="#" alt="H(s)" />\r\n  <area shape="rect" coords="236,94,316,118" href="#" alt="controller" />\r\n  <area shape="rect" coords="243,175,309,208" href="#" alt="F (s)" />\r\n  <area shape="rect" coords="247,234,305,258" href="#" alt="sensor" />\r\n</map>
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n