Saltar al contenido

Gráficos vectoriales en iText PDF

Tenemos el resultado a este atascamiento, o por lo menos eso deseamos. Si tienes alguna duda coméntalo, que sin tardar

Solución:

Según la documentación, iText admite los siguientes formatos de imagen: JPEG, GIF, PNG, TIFF, BMP, WMF y EPS. No sé si esto podría ser de alguna ayuda, pero he usado iTextSharp con éxito para incrustar una imagen vectorial WMF en un archivo pdf:

C#:

using System;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

public class Program 


    public static void Main() 
    
        Document document = new Document();
        using (Stream outputPdfStream = new FileStream("output.pdf", FileMode.Create, FileAccess.Write, FileShare.None))
        using (Stream imageStream = new FileStream("test.wmf", FileMode.Open, FileAccess.Read, FileShare.Read))
        
            PdfWriter.GetInstance(document, outputPdfStream);
            Image wmf = Image.GetInstance(imageStream);
            document.Open();
            document.Add(wmf);
            document.Close();
        
    

Encontré un par de ejemplos del autor de iText que usan la API Graphics2D y la biblioteca Apache Batik para dibujar el SVG en un PDF.

http://itextpdf.com/examples/iia.php?id=269

http://itextpdf.com/examples/iia.php?id=263

Para mis propósitos, necesitaba tomar una string de SVG y dibuje eso en un PDF en un cierto tamaño y ubicación mientras mantiene la naturaleza vectorial de la imagen (sin rasterización).

Quería omitir el archivo SVG que parece prevalecer en las funciones SAXSVGDocumentFactory.createSVGDocument(). Encontré la siguiente publicación útil para usar un texto SVG string en lugar de un archivo plano.

http://batik.2283329.n4.nabble.com/Parse-SVG-from-String-td3539080.html

Debe crear un StringReader a partir de su String y pasarlo al método SAXSVGDocumentFactory#createDocument(String, Reader). El URI que pase como primer parámetro como String será el URI del documento base del documento SVG. Esto solo debería ser importante si su SVG hace referencia a archivos externos.

Atentamente,

Daniel

Fuente Java derivada de los ejemplos de iText:

// SVG as a text string.
String svg = "...";

// Create the PDF document.
// rootPath is the present working directory path.
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(new File(rootPath + "svg.pdf")));
document.open();

// Add paragraphs to the document...
document.add(new Paragraph("Paragraph 1"));
document.add(new Paragraph(" "));

// Boilerplate for drawing the SVG to the PDF.
String parser = XMLResourceDescriptor.getXMLParserClassName();
SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(parser);
UserAgent userAgent = new UserAgentAdapter();
DocumentLoader loader = new DocumentLoader(userAgent);
BridgeContext ctx = new BridgeContext(userAgent, loader);
ctx.setDynamicState(BridgeContext.DYNAMIC);
GVTBuilder builder = new GVTBuilder();
PdfContentByte cb = writer.getDirectContent();

// Parse the SVG and draw it to the PDF.
Graphics2D g2d = new PdfGraphics2D(cb, 725, 400);
SVGDocument chart = factory.createSVGDocument(rootPath, new StringReader(svg));
GraphicsNode chartGfx = builder.build(ctx, chart);
chartGfx.paint(g2d);
g2d.dispose();

// Add paragraphs to the document...
document.add(new Paragraph("Paragraph 2"));
document.add(new Paragraph(" "));

document.close();

Tenga en cuenta que esto dibujará un SVG en el PDF en el que está trabajando. El SVG aparece como una capa flotante sobre el texto. Todavía estoy trabajando para moverlo/escalarlo y hacer que descanse en línea con el texto, pero espero que eso esté fuera del alcance inmediato de la pregunta.

Espero que esto haya podido ayudar.

Salud

EDITAR: Pude implementar mi svg como un objeto en línea usando lo siguiente. Las líneas comentadas son para agregar un borde rápido para verificar el posicionamiento.

SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(XMLResourceDescriptor.getXMLParserClassName());
UserAgent userAgent = new UserAgentAdapter();
DocumentLoader loader = new DocumentLoader(userAgent);
BridgeContext ctx = new BridgeContext(userAgent, loader);
ctx.setDynamicState(BridgeContext.DYNAMIC);
GVTBuilder builder = new GVTBuilder();
SVGDocument svgDoc = factory.createSVGDocument(rootPath, new StringReader(svg));
PdfTemplate svgTempl = PdfTemplate.createTemplate(writer, Float.parseFloat(svgDoc.getDocumentElement().getAttribute("width")), Float.parseFloat(svgDoc.getDocumentElement().getAttribute("height")));
Graphics2D g2d = new PdfGraphics2D(svgTempl, svgTempl.getWidth(), svgTempl.getHeight());
GraphicsNode chartGfx = builder.build(ctx, svgDoc);
chartGfx.paint(g2d);
g2d.dispose();
Image svgImg = new ImgTemplate(svgTempl);
svgImg.setAlignment(Image.ALIGN_CENTER);
//svgImg.setBorder(Image.BOX);
//svgImg.setBorderColor(new BaseColor(0xff, 0x00, 0x00));
//svgImg.setBorderWidth(1);
document.add(svgImg);

Esto es lo que derivé de las publicaciones que encontré aquí y los ejemplos oficiales:

/**
 * Reads an SVG Image file into an com.itextpdf.text.Image instance to embed it into a PDF
 * @param svgPath SVG filepath
 * @param writer PdfWriter instance 
 * @return Instance of com.itextpdf.text.Image holding the SVG file
 * @throws IOException
 * @throws BadElementException
 */
private static Image getSVGImage(String svgPath, PdfWriter writer) throws IOException, BadElementException 
    SVGDocument svgDoc = new SAXSVGDocumentFactory(null).createSVGDocument(null, new FileReader(svgPath));

    // Try to read embedded height and width
    float svgWidth = Float.parseFloat(svgDoc.getDocumentElement().getAttribute("width").replaceAll("[^0-9.,]",""));
    float svgHeight = Float.parseFloat(svgDoc.getDocumentElement().getAttribute("height").replaceAll("[^0-9.,]",""));

    PdfTemplate svgTempl = PdfTemplate.createTemplate(writer, svgWidth, svgHeight);
    Graphics2D g2d = new PdfGraphics2D(svgTempl, svgTempl.getWidth(), svgTempl.getHeight());
    GraphicsNode chartGfx = (new GVTBuilder()).build(new BridgeContext(new UserAgentAdapter()), svgDoc);
    chartGfx.paint(g2d);
    g2d.dispose();

    return new ImgTemplate(svgTempl);

La instancia de la imagen se puede agregar fácilmente al pdf (en mi caso, como una firma).

valoraciones y comentarios

Nos encantaría que puedieras mostrar esta reseña si te valió la pena.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *