56

I want to convert PDF to SVG please suggest some libraries/executable that will be able to do this efficiently. I have written my own java program using the apache PDFBox and Batik libraries -

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);
    }

This solution works great but the size of the resulting svg files in huge.(many times greater than the pdf). I have figured out where the problem is by looking at the svg in a text editor. it encloses every character in the original document in its own block even if the font properties of the characters is the same. For example the word hello will appear as 6 different text blocks. Is there a way to fix the above code? or please suggest another solution that will work more efficiently.

user434541
  • 1,245
  • 2
  • 13
  • 21

6 Answers6

63

Inkscape can also be used to convert PDF to SVG. It's actually remarkably good at this, and although the code that it generates is a bit bloated, at the very least, it doesn't seem to have the particular issue that you are encountering in your program. I think it would be challenging to integrate it directly into Java, but inkscape provides a convenient command-line interface to this functionality, so probably the easiest way to access it would be via a system call.

To use Inkscape's command-line interface to convert a PDF to an SVG, use:

inkscape -l out.svg in.pdf

Which you can then probably call using:

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

I think exec() is synchronous and only returns after the process completes (although I'm not 100% sure on that), so you shoudl be able to just read "out.svg" after that. In any case, Googling "java system call" will yield more info on how to do that part correctly.

jbeard4
  • 11,927
  • 4
  • 52
  • 66
  • thanks that inkscape command seems to work however it only converts the first page, do u know of a command line option that will produce 1 svg for each page? – user434541 Nov 08 '10 at 18:20
  • 1
    I don't know of a way to do this, and the inkscape man page doesn't seem to indicate that this functionality is exposed in the command-line interface. I suppose your options would be to add this interface yourself by modifying the inkscape code. Or, you could do something very hacky and creative, and use a program like ghostscript to split the PDF into multiple single-page documents, and then feed each page individually to inkscape. – jbeard4 Nov 09 '10 at 02:06
  • 1
    Probably the best solution then is to split the pdf file in one file per page. Both pdfjam and pdftk can do this. – hlovdal Aug 28 '11 at 22:27
  • @Koen.'s answer points to pdf2svg, which can do multiple pages: `pdf2svg input.pdf output_page%d.svg all` – alxndr Feb 10 '13 at 05:53
  • I know this is old, but I've also noticed inkscape bloating (e.g. doubling up on groups) when dealing with .pdfs. Once you've got .svgs, there's a cleanup utility called [scour](http://www.codedread.com/scour/) which might help. – Chris H Aug 15 '13 at 11:54
  • 2
    I used the inkscape commandline approach but the fonts look really ugly in the svg. Is there a way to fix it? – remus Oct 08 '13 at 07:51
  • For people finding this solution in 2017: this option is horribly broken on Windows, where it pops up a PDF import settings dialog that needs to be confirmed, thus making this solution intractable for automated builds. – Mike 'Pomax' Kamermans Feb 26 '17 at 23:17
  • Agreed with you Mike. any solution to run that in command line using the latest Inkscape? – Mah Jin Khai May 29 '18 at 02:41
  • I haven't tested this with Windows, but `--pdf-poppler` works for me with inkscape 1.0 on Linux. In case anyone's curious, the full command I'm using is `inkscape --pdf-poppler in.pdf -T -l -o out.svg` which converts the fonts to paths. – MattHusz Jul 23 '20 at 02:12
40

Take a look at pdf2svg:

To use

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

When using all give a filename with %d in it (which will be replaced by the page number).

pdf2svg input.pdf output_page%d.svg all

And for some troubleshooting see: http://www.calcmaster.net/personal_projects/pdf2svg/

Community
  • 1
  • 1
Koen.
  • 21,087
  • 6
  • 75
  • 76
  • 5
    I had been using pdf2svg but I just discovered that it's much more of an approximation than inkscape. Specifically you loose detail when rendering small circles (I'm dealing with pdfs of 100,000s of paths). YMMV. – Aidan Kane Nov 27 '12 at 23:18
  • 6
    @AidanKane: On the other hand, pdf2svg does better than Inkscape for text; text from a LaTeX output file didn't show up in Inkscape's output for me. – Mechanical snail Feb 23 '14 at 21:15
  • 1
    @Mechanicalsnail: I have a lot more experience with this now. You're right, there are times where I've found things missing from inkscape conversions - and pdf2svg is fine. pdf2svg was updated to call a different function in cairo to do the rendering (which fixed the issue I described previously). Unfortunately that comes at the cost of having no text in svgs - all glyphs are converted to paths. I patched cairo and poppler to get text working again but I don't totally trust my hack :) – Aidan Kane Feb 23 '14 at 23:19
  • 1
    both inkscape and dvisvgm cannot create correct svg from latex. pdf2svg can. – ivo Welch Mar 01 '14 at 22:23
7

pdftocairo can be used to convert pdf to svg. pdfcairo is part of poppler-utils.

For example to convert 2nd page of a pdf, following command can be run.

pdftocairo -svg -f 1 -l 1 input.pdf
SuperNova
  • 15,051
  • 5
  • 67
  • 45
2
pdftk 82page.pdf burst
sh to-svg.sh 

contents of to-svg.sh

#!/bin/bash
FILES=burst/*
for f in $FILES
do
  inkscape -l "$f.svg" "$f"
done
Leblanc Meneses
  • 2,922
  • 1
  • 21
  • 25
0

inkscape (@jbeard4) for me produced svgs with no text in them at all, but I was able to make it work by going to postscript as an intermediary using ghostscript.

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

However this is a bit cumbersome, and the winner for ease of use has to go to pdf2svg (@Koen.) since it has that all flag so you don't need to loop.

However, pdf2svg isn't available on CentOS 8, and to install it you need to do the following:

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

It produces svgs that actually look nicer than the ghostscript-inkscape one above, the font seems to raster better.

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

But that installation is a bit much, too much even if you don't have sudo. On top of that, pdf2svg doesn't support stdin/stdout, so the readily available pdftocairo (@SuperNova) worked a treat in these regards, and here's an example of "advanced" use below:

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

Which produces files of the same quality and size (before compression) as pdf2svg, although not binary-identical (and even visually, jumping between output of the two some pixels of letters shift, but neither looks wrong/bad like inkscape did).

Hashbrown
  • 8,877
  • 7
  • 57
  • 71
0

I have encountered issues with the suggested inkscape, pdf2svg, pdftocairo, as well as the not suggested convert and mutool when trying to convert large and complex PDFs such as some of the topographical maps from the USGS. Sometimes they would crash, other times they would produce massively inflated files. The only PDF to SVG conversion tool that was able to handle all of them correctly for my use case was dvisvgm. Using it is very simple:

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

It has various extra options for handling how elements are converted, as well as for optimization. Its resulting files can further be compacted by svgcleaner if necessary without perceptual quality loss.

MrDrMcCoy
  • 269
  • 2
  • 18