2009-01-02 25 views
10

Usamos iText para generar archivos PDF de Java (basado en parte en las recomendaciones de este sitio). Sin embargo, insertar una copia de nuestro logotipo en un formato de imagen como GIF hace que parezca un poco extraño a medida que las personas acercan y alejan la imagen.Gráficos vectoriales en iText PDF

Idealmente, nos gustaría incrustar la imagen en un formato vectorial, como EPS, SVG o simplemente una plantilla en PDF. El sitio web afirma que se ha eliminado la compatibilidad con EPS, que insertar un PDF o PS dentro de un PDF puede generar errores, y ni siquiera menciona SVG.

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

Respuesta

8

De acuerdo con la documentation iText soporta 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 imagen vectorial WMF para incrustar 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(); 
     } 
    } 
} 
+1

Obtuve una excepción cuando probé su código, esto no funciona, he leído recientemente que no es compatible con eps, debe convertirlo a WMF – Deumber

3

Recientemente me enteré de que puede enviar su 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(); 
+0

Eso es lo que ya estamos haciendo: usar Graphics2D para dibujar en la página. Lo que necesitamos es agregar una imagen en formato vectorial. –

4

me encontré con un par de ejemplos por el iText autor que usa 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, que tenía que tomar una serie de SVG y dibujar que en un PDF en un determinado tamaño y la ubicación mientras se mantiene la naturaleza del vector de la imagen (sin rasterización) .

Quería omitir el archivo SVG que parece ser frecuente en las funciones SAXSVGDocumentFactory.createSVGDocument(). La siguiente publicación me resultó ú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

usted tiene que crear un StringReader de su cadena y pasar a la que (, Cadena lector) método SAXSVGDocumentFactory # createDocument. 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 cualquier archivo externo.

Saludos,

Daniel

Java Fuente derivados de los ejemplos 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 va a dibujar un SVG para el PDF que se está trabajando. El SVG aparece como una capa flotante sobre el texto. Todavía estoy trabajando en moverlo/escalarlo y tenerlo en línea con el texto, pero espero que esté fuera del alcance inmediato de la pregunta.

Espero que haya sido capaz de ayudar.

Saludos

EDIT: yo era capaz de poner en práctica mi SVG como un objeto en línea usando la 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); 
+1

Hola, estoy tratando de encontrar una manera de hacer algo similar, renderizar archivos SVG en un documento PDF. ¿Qué versión de Itext estás usando? Me he dado cuenta de que los constructores son privados para la clase com.lowagie.text.pdf.PdfGraphics2D, al menos en iText 2.1.2, y no pude encontrar dicha clase en IText 5.5.4. ¡Gracias! - Jose Tepedino hace 6 minutos –

+0

@JoseTepedino Lo siento, pero no he tocado esto en años (desde que escribí la respuesta). Me imagino que estaba usando una versión que se lanzó en septiembre de 2012, por lo que probablemente sería iText 5.3.2 que se lanzó en agosto de 2012 de acuerdo con sus lanzamientos de GitHub - https://github.com/itext/itextpdf/releases /tag/5.3.2. Espero que ayude. – clayzermk1

+0

gracias por su mensaje! He progresado un poco, al encontrar una página API que indica que la clase PdfGraphics2D del paquete com.itextpdf.awt existe desde iText 5.0.2: http://developers.itextpdf.com/reference/com.itextpdf.awt.PdfGraphics2D . Todavía tengo un poco de terreno por recorrer, pero encontrar la versión correcta para usar es un buen comienzo. ¡Gracias! –

6

esto lo que deriva de los mensajes 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 pueden añadir fácilmente a la pdf (en mi caso como una firma).

+1

Las clases en el código de seguridad podrían ser importados utilizando próxima experto dependencia: ' org.apache.xmlgraphics batik-GVT 1,7 ' –

Cuestiones relacionadas