将pdf转换为svg

Posted

技术标签:

【中文标题】将pdf转换为svg【英文标题】:convert pdf to svg 【发布时间】:2011-05-06 10:55:00 【问题描述】:

我想将 PDF 转换为 SVG,请建议一些能够有效地执行此操作的库/可执行文件。我已经使用 apache PDFBox 和 Batik 库编写了自己的 java 程序 -

PDDocument document = PDDocument.load( pdfFile );
DOMImplementation domImpl =
    GenericDOMImplementation.getDOMImplementation();

// Create an instance of org.w3c.dom.Document.
String svgNS = "http://www.w3.org/2000/svg";
Document svgDocument = domImpl.createDocument(svgNS, "svg", null);
SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(svgDocument);
ctx.setEmbeddedFontsOn(true);

// Ask the test to render into the SVG Graphics2D implementation.

    for(int i = 0 ; i < document.getNumberOfPages() ; i++)
        String svgFName = svgDir+"page"+i+".svg";
        (new File(svgFName)).createNewFile();
        // Create an instance of the SVG Generator.
        SVGGraphics2D svgGenerator = new SVGGraphics2D(ctx,false);
        Printable page  = document.getPrintable(i);
        page.print(svgGenerator, document.getPageFormat(i), i);
        svgGenerator.stream(svgFName);
    

此解决方案效果很好,但生成的 svg 文件的大小很大。(比 pdf 大很多倍)。我通过在文本编辑器中查看 svg 找出了问题所在。即使字符的字体属性相同,它将原始文档中的每个字符都包含在自己的块中。例如,单词 hello 将显示为 6 个不同的文本块。有没有办法修复上面的代码?或者请提出其他更有效的解决方案。

【问题讨论】:

【参考方案1】:

Inkscape 也可用于将 PDF 转换为 SVG。它实际上非常擅长这一点,虽然它生成的代码有点臃肿,但至少它似乎没有您在程序中遇到的特定问题。我认为将它直接集成到 Java 中会很有挑战性,但是inkscape 为这个功能提供了一个方便的命令行界面,所以访问它的最简单方法可能是通过系统调用。

要使用 Inkscape 的命令行界面将 PDF 转换为 SVG,请使用:

inkscape -l out.svg in.pdf

然后您可以使用以下方式调用:

Runtime.getRuntime().exec("inkscape -l out.svg in.pdf")

http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Runtime.html#exec%28java.lang.String%29

我认为 exec() 是同步的,并且仅在进程完成后返回(尽管我对此不是 100% 确定),因此您应该能够在此之后读取“out.svg”。在任何情况下,谷歌搜索“java 系统调用”都会产生更多关于如何正确执行该部分的信息。

【讨论】:

感谢 inkscape 命令似乎可以工作,但是它只转换第一页,你知道一个命令行选项会为每页生成 1 个 svg 吗? 我不知道有什么方法可以做到这一点,并且 inkscape 手册页似乎并未表明此功能已在命令行界面中公开。我想你的选择是通过修改inkscape代码自己添加这个接口。或者,您可以做一些非常 hacky 和创造性的事情,并使用 ghostscript 之类的程序将 PDF 拆分为多个单页文档,然后将每个页面单独提供给 inkscape。 可能最好的解决方案是将 pdf 文件拆分为每页一个文件。 pdfjam 和 pdftk 都可以做到这一点。 @Koen.的回答指向pdf2svg,可以做多页:pdf2svg input.pdf output_page%d.svg all 我使用了 inkscape 命令行方法,但字体在 svg 中看起来真的很难看。有办法解决吗?【参考方案2】:

看看pdf2svg:

使用

pdf2svg <input.pdf> <output.svg> [<pdf page no. or "all" >]

使用all 时,请提供一个包含%d 的文件名(将被页码替换)。

pdf2svg input.pdf output_page%d.svg all

有关一些故障排除,请参阅: http://www.calcmaster.net/personal_projects/pdf2svg/

【讨论】:

我一直在使用 pdf2svg,但我发现它比inkscape 更像一个近似值。具体来说,您在渲染小圆圈时会丢失细节(我正在处理 100,000 条路径的 pdf)。 YMMV。 @AidanKane:另一方面,pdf2svg 在文本方面比 Inkscape 做得更好; LaTeX 输出文件中的文本没有显示在 Inkscape 的输出中。 @Mechanicalsnail:我现在在这方面有了更多的经验。你是对的,有时我发现inkscape转换中缺少一些东西 - pdf2svg很好。 pdf2svg 已更新为在 cairo 中调用不同的函数来进行渲染(这解决了我之前描述的问题)。不幸的是,这是以 svgs 中没有文本为代价的——所有字形都转换为路径。我修补了 cairo 和 poppler 以使文本再次工作,但我并不完全相信我的 hack :) inkscape 和 dvisvgm 都无法从乳胶创建正确的 svg。 pdf2svg 可以。【参考方案3】:
pdftk 82page.pdf burst
sh to-svg.sh 

to-svg.sh的内容

#!/bin/bash
FILES=burst/*
for f in $FILES
do
  inkscape -l "$f.svg" "$f"
done

【讨论】:

【参考方案4】:

pdftocairo 可用于将 pdf 转换为 svg。 pdfcairo 是 poppler-utils 的一部分。

例如转换 pdf 的第二页,可以运行以下命令。

pdftocairo -svg -f 1 -l 1 input.pdf

【讨论】:

我认为最好的答案,最简单的解决方案。 您的命令将转换“第一”页而不是“第二”页【参考方案5】:

inkscape (@jbeard4) 为我制作了完全没有文本的 svg,但我能够通过使用 ghostscript 将 postscript 作为中介来使其工作。

for page in $(seq 1 `pdfinfo $1.pdf | awk '/^Pages:/ print $2'`)
do
    pdf2ps -dFirstPage=$page -dLastPage=$page -dNoOutputFonts $1.pdf $1_$page.ps
    inkscape -z -l $1_$page.svg $1_$page.ps
    rm $1_$page.ps
done

但是这有点麻烦,并且易于使用的获胜者必须去pdf2svg(@Koen.),因为它有all标志,所以你不需要循环.

但是pdf2svg 在 CentOS 8 上不可用,要安装它,您需要执行以下操作:

git clone https://github.com/dawbarton/pdf2svg.git && cd pdf2svg
#if you dont have development stuff specific to this project
sudo dnf config-manager --set-enabled powertools
sudo dnf install cairo-devel poppler-glib-devel
#git repo isn't quite ready to ./configure
touch README
autoreconf -f -i
./configure && make && sudo make install

它生成的 svg 实际上看起来比上面的 ghostscript-inkscape 更好,字体似乎更好。

pdf2svg $1.pdf $1_%d.svg all

但是即使你没有 sudo,安装也有点过分。最重要的是,pdf2svg 不支持标准输入/标准输出,所以现成的pdftocairo (@SuperNova) 在这些方面发挥了作用,下面是一个“高级”使用示例:

for page in $(seq 1 `pdfinfo $1.pdf | awk '/^Pages:/ print $2'`)
do
    pdftocairo -svg -f $page -l $page $1.pdf - | gzip -9 >$1_$page.svg.gz
done

它产生与 pdf2svg 相同质量和大小(压缩前)的文件,虽然不是二进制相同的(甚至在视觉上,在两个字母的输出之间跳跃一些像素移位,但看起来都不像 inkscape 那样错误/坏)。

【讨论】:

【参考方案6】:

在尝试转换大型复杂 PDF(例如某些地形图)时,我遇到了建议的 inkscapepdf2svgpdftocairo 以及不建议的 convertmutool 的问题来自美国地质调查局。有时它们会崩溃,有时它们会产生大量膨胀的文件。对于我的用例,唯一能够正确处理所有这些 PDF 到 SVG 的转换工具是 dvisvgm。使用非常简单:

dvisvgm --pdf --output=file.svg file.pdf

它有各种额外的选项来处理元素的转换方式以及优化。如有必要,其生成的文件可以通过svgcleaner 进一步压缩,而不会造成感知质量损失。

【讨论】:

以上是关于将pdf转换为svg的主要内容,如果未能解决你的问题,请参考以下文章

怎么用ABBYY将PDF转换为JPEG图像

怎么用ABBYY将PDF转换为JPEG图像

问:如何将PDF文档(表格式的)转换为Excel格式?

如何将多张图纸共同进行转换为PDF格式?

如何将PDF文档转换为CHM格式文档?

如何将图像转换为PDF?