java 如何防止我的PDF到SVG转换代码生成臃肿的内容?

gev0vcfq  于 2023-05-21  发布在  Java
关注(0)|答案(7)|浏览(160)

我想把PDF转换成SVG。我使用ApachePDFBox和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,我已经找到了问题所在:它将原始文档中的每个字符都包含在自己的<text> </text>块中,即使字符的字体属性相同。
例如,单词“hello”将显示为6个不同的文本块。
有没有办法修复上面的代码?或者有没有其他更有效的解决方案?

voj3qocg

voj3qocg1#

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系统调用”将会产生更多关于如何正确完成这部分的信息。

14ifxucb

14ifxucb2#

看看pdf2svg(也在on github上):

使用

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/

e5nqia27

e5nqia273#

Pdftocairo可用于将PDF转换为SVG。Pdfcairo是Poppler-utils的一部分。
例如,要转换PDF的第二页,可以运行以下命令:

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

7lrncoxx4#

我遇到的问题,建议inkscape,pdf2svg,或pdftocairo工具,以及不建议转换和mutool工具,当试图转换大型和复杂的PDF文件,如一些地形图从美国地质调查局。有时它们会崩溃,有时它们会产生大量膨胀的文件。
对于我的用例,唯一能够正确处理所有这些问题的PDF到SVG转换工具是dvisvgm。使用它非常简单:

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

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

yh2wf1be

yh2wf1be5#

您可以在 *nix环境中使用bash。
拆分操作将PDF中的每个页面拆分为多个文件。to-svg.sh循环这些单页PDF以生成关联的SVG文件

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
whhtz7ly

whhtz7ly6#

Inkscape不再使用-l选项。它说“无法打开文件:/out.svg(不存在)"。该选项在手册页中的详细形式为--export-plain-svg,可以工作,但显示了一个弃用警告。我能够通过在Inkscape 1.1.2- 3ubuntu 4上使用-o选项来修复和更新命令:

inkscape in.pdf -o out.svg
798qvoo8

798qvoo87#

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

然而这有点麻烦,并且为了易于使用,获胜者必须去pdf 2svg(@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

它产生的svgs实际上看起来比上面的ghostscript-inkscape更好,字体似乎光栅更好。

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

但是,即使你没有sudo,安装也有点多。最重要的是,pdf 2svg不支持stdin/stdout,所以现成的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

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

相关问题