Pregunta

Usamos iText para generar archivos PDF desde Java (basado en parte en las recomendaciones de este sitio). Sin embargo, incrustar una copia de nuestro logotipo en un formato de imagen como GIF hace que se vea un poco extraño a medida que las personas se acercan y alejan.

Lo ideal sería que incrustáramos la imagen en un formato vectorial, como EPS, SVG o simplemente una plantilla de PDF. El sitio web afirma que se ha eliminado la compatibilidad con EPS, que incrustar un PDF o PS en un PDF puede generar errores, y ni siquiera menciona SVG.

Nuestro código usa la API Graphics2D en lugar de iText directamente, pero estaríamos dispuestos a salir del modo AWT y usar iText si logra el resultado. ¿Cómo se puede hacer esto?

¿Fue útil?

Solución

De acuerdo con 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 utilizado con éxito iTextSharp para insertar el vector 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();
        }
    }
}

Otros consejos

Esto es lo que obtuve 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).

Encontré un par de ejemplos del autor de iText que utilizan 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 cadena de SVG y dibujarla en un PDF con un tamaño y ubicación determinados, manteniendo 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 una cadena de texto SVG en lugar de un archivo plano.

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

  

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

     

Saludos cordiales,

     

Daniel

Fuente Java derivada de los ejemplos de iText:

// SVG as a text string.
String svg = "<svg>...</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 al PDF en el que está trabajando. El SVG aparece como una capa flotante sobre el texto. Todavía estoy trabajando para moverlo / escalarlo y tenerlo en línea con el texto, pero espero que eso quede fuera del alcance inmediato de la pregunta.

Espero que esto haya podido ayudar.

Saludos

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

Recientemente aprendí que puedes enviar tu objeto Graphics2D directamente a iText, y los archivos PDF resultantes son tan buenos como los gráficos vectoriales escalables. Desde su publicación, parece que esto podría resolver su problema.

Document document = new Document(PageSize.LETTER);
PdfWriter writer = null;
try {
    writer = PdfWriter.getInstance(document, new FileOutputStream(your file name));
} catch (Exception e) {
    // do something with exception
}

document.open();

PdfContentByte cb = writer.getDirectContent();
PdfTemplate tp = cb.createTemplate(width, height);
Graphics2D g2 = tp.createGraphics(width, height, new DefaultFontMapper());

// Create your graphics here - draw on the g2 Graphics object

g2.dispose();
cb.addTemplate(tp, 0, 100); // 0, 100 = x,y positioning of graphics in PDF page
document.close();

Esto me funcionó al utilizar itext 7.1.3 para renderizar la imagen SVG por SVGConverter.

PdfWriter writer = new PdfWriter(new FileOutputStream("/home/users/Documents/pdf/new.pdf"));

        PdfDocument pdfDoc = new PdfDocument(writer);

        Document doc = new Document(pdfDoc);

        URL svgUrl = new File(svg).toURI().toURL();

        doc.add(new Paragraph("new pikachu"));                      

        Image image = SvgConverter.convertToImage(svgUrl.openStream(), pdfDoc);                 
        doc.add(image);

        doc.close();

La nueva versión de iText también admite archivos SVG. Consulte esta página.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top