将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(例如某些地形图)时,我遇到了建议的 inkscape
、pdf2svg
、pdftocairo
以及不建议的 convert
和 mutool
的问题来自美国地质调查局。有时它们会崩溃,有时它们会产生大量膨胀的文件。对于我的用例,唯一能够正确处理所有这些 PDF 到 SVG 的转换工具是 dvisvgm。使用非常简单:
dvisvgm --pdf --output=file.svg file.pdf
它有各种额外的选项来处理元素的转换方式以及优化。如有必要,其生成的文件可以通过svgcleaner 进一步压缩,而不会造成感知质量损失。
【讨论】:
以上是关于将pdf转换为svg的主要内容,如果未能解决你的问题,请参考以下文章