Convierte SVG a PDF

¿Cómo se podría convertir un archivo SVG a PDF programáticamente? (Necesito modificar el SVG en ciertos aspectos antes de generar el PDF, así que simplemente pre-convertirlo usando una herramienta no será suficiente).

Idealmente, usar Java pero Perl o PHP también estarían bien.

Obviamente, básicamente estoy considerando Apache FOP y Batik con Java. Sin embargo, no importa cuánto tiempo busque, no puedo encontrar una introducción simple sobre cómo hacerlo. Cosas como SVGConverter tienen descripciones como “Define la interfaz para clases que pueden convertir parte o todo un GraphicContext”, pero realmente no sé lo que eso significa.

Tengo la sensación de que debe haber una API para hacer esto simplemente, provista por FOP o Batik, pero no puedo encontrarla en este momento (o tal vez realmente no exista).

En términos de las características SVG admitidas que necesito, el archivo tiene algunas rutas que están llenas de algunos degradados lineales.

Idealmente, si pudiera pasar el SVG como un documento DOM que sería ideal; luego cargaba mi plantilla de archivo SVG, la cambiaba según lo especificado por el usuario y luego generaba el PDF.

Gracias a Adrian por mostrar cómo se supone que se utilizará la API rasterizadora de Batik. Sin embargo, necesitaba una solución más liviana — No puedo escribir en archivos temporales, y quiero menos dependencias. Entonces, comenzando con los métodos que señaló, encontré una forma de acceder al código de nivel inferior para hacer la conversión y nada más.

import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import org.apache.batik.transcoder.Transcoder; import org.apache.batik.transcoder.TranscoderException; import org.apache.batik.transcoder.TranscoderInput; import org.apache.batik.transcoder.TranscoderOutput; import org.apache.fop.svg.PDFTranscoder; public class Test { public static void main(String[] argv) throws TranscoderException, FileNotFoundException { Transcoder transcoder = new PDFTranscoder(); TranscoderInput transcoderInput = new TranscoderInput(new FileInputStream(new File("/tmp/test.svg"))); TranscoderOutput transcoderOutput = new TranscoderOutput(new FileOutputStream(new File("/tmp/test.pdf"))); transcoder.transcode(transcoderInput, transcoderOutput); } } 

Los comandos de comstackción y ejecución son

 javac -cp batik-rasterizer.jar -d build Test.java java -cp build:batik-rasterizer.jar Test 

El punto importante es que TranscoderInput y TranscoderOutput pueden funcionar con cualquier InputStream y OutputStream , no solo flujos de archivos. Tenga en cuenta que uno de los constructores toma un org.w3c.dom.Document , lo que significa que ni siquiera necesita serializar un SVG DOM en una cadena SVG, guardando un paso adicional.

Esta versión tampoco escribe nada en stdout / stderr, a diferencia de la API de alto nivel.

Para salida JPEG, PNG o TIFF, reemplace org.apache.fop.svg.PDFTranscoder con org.apache.batik.transcoder.image.JPEGTranscoder , PNGTranscoder o TIFFTranscoder (tenga en cuenta que estos formatos de ráster están en un paquete diferente).

(No estoy muy seguro de cómo Java encuentra las clases org.apache.batk.transcoder.* Y org.apache.fop.svg.PDFTranscoder , ya que no las veo en batik-rasterizer.jar ).

Editar:

Aunque la simple comstackción de línea de comandos solo funciona con batik-rasterizer.jar , está haciendo una especie de magia de cargador de clases para encontrar todas las clases necesarias. En un caso más realista (construir un proyecto con Ant), debe encontrar las clases a mano. Se pueden encontrar en batik-1.7.zip del proyecto Batik y fop-1.1.zip del proyecto FOP . Desde Batik, necesitas comstackr con batik-transcoder.jar y ejecutar con

  • batik-transcoder.jar
  • batik-anim.jar
  • batik-awt-util.jar
  • batik-bridge.jar
  • batik-css.jar
  • batik-dom.jar
  • batik-ext.jar
  • batik-gvt.jar
  • batik-parser.jar
  • batik-script.jar
  • batik-svg-dom.jar
  • batik-util.jar
  • batik-xml.jar
  • xml-apis-ext.jar

Desde FOP, necesita comstackr con fop.jar y ejecutar con

  • fop.jar
  • avalon-framework-4.2.0.jar
  • xmlgraphics-commons-1.5.jar

Finalmente logré encontrar las líneas de código apropiadas para resolver esto usando el Batik .

Necesita tener el archivo SVG y el PDF resultante como archivos en el disco, es decir, no pude encontrar la manera de hacerlo en la memoria (estoy escribiendo un Servlet HTTP, así que no tengo ninguna necesidad intrínseca de escribir algo como un archivo , lo ideal sería transmitir el resultado al cliente HTTP). Usé File.createTemporaryFile para crear un archivo para volcar mi SVG en un archivo y para que se escribiera el PDF resultante.

Entonces las líneas que utilicé son las siguientes:

 import org.apache.batik.apps.rasterizer.DestinationType; import org.apache.batik.apps.rasterizer.SVGConverter; import ... // SVG available as a DOM object (created progtwigtically by my program) Document svgXmlDoc = ... // Save this SVG into a file (required by SVG -> PDF transformation process) File svgFile = File.createTempFile("graphic-", ".svg"); Transformer transformer = TransformerFactory.newInstance().newTransformer(); DOMSource source2 = new DOMSource(svgXmlDoc); FileOutputStream fOut = new FileOutputStream(svgFile); try { transformer.transform(source2, new StreamResult(fOut)); } finally { fOut.close(); } // Convert the SVG into PDF File outputFile = File.createTempFile("result-", ".pdf"); SVGConverter converter = new SVGConverter(); converter.setDestinationType(DestinationType.PDF); converter.setSources(new String[] { svgFile.toString() }); converter.setDst(outputFile); converter.execute(); 

Y tengo los siguientes JAR (búsqueda con Google para encontrar los proyectos y descargarlos):

  • avalon-framework-4.2.0.jar
  • batik-all-1.7.jar
  • commons-io-1.3.1.jar
  • commons-logging-1.0.4.jar
  • fop-0.95.jar
  • log4j-1.2.15.jar
  • xml-apis-ext.jar
  • xmlgraphics-commons-1.3.1.jar

necesitarás una biblioteca para renderizar svg’s y pdf’s. Recomiendo SVG Salamander para el primero, e iText para el segundo. Con svg salamander puedes leer el svg y crear un objeto de imagen, y con itext puedes escribir esa imagen en un pdf.

Yo uso Altsoft Xml2PDF. Si entendí correctamente todas sus necesidades y requisitos, será mejor que intente con la versión de Xml2PDF del Servidor.

Todo lo que necesitas es phantomjs. No necesitas el inmanejable Batik para esto; solo llegue a un punto donde puede ejecutar phantomjs, llamando a rasterize.js, usando la URL del pdf como fuente, y una ubicación como salida. Dependiendo de lo que quieras hacer con .pdf, ni siquiera necesitas Java.

http://phantomjs.org/screen-capture.html

Observe la parte que comienza con “Al lado del formato PNG, PhantomJS admite JPEG, GIF y PDF”.