14

我们使用 iText 从 Java 生成 PDF(部分基于此站点上的建议)。但是,以 GIF 等图像格式嵌入我们的徽标副本会导致人们放大和缩小时看起来有点奇怪。

理想情况下,我们希望以矢量格式嵌入图像,例如 EPS、SVG 或只是 PDF 模板。该网站声称 EPS 支持已被删除,在 PDF 中嵌入 PDF 或 PS 可能会导致错误,甚至没有提及 SVG。

我们的代码使用 Graphics2D API 而不是直接使用 iText,但如果能达到结果,我们愿意跳出 AWT 模式并使用 iText 本身。如何才能做到这一点?

4

7 回答 7

8

根据文档, iText 支持以下图像格式:JPEG、GIF、PNG、TIFF、BMP、WMF 和 EPS。我不知道这是否有任何帮助,但我已成功使用iTextSharp在 pdf 文件中嵌入矢量WMF图像:

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();
        }
    }
}
于 2009-01-03T13:36:06.160 回答
7

我发现了 iText 作者的几个示例,它们使用 Graphics2D API 和 Apache Batik 库在 PDF 中绘制 SVG。

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

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

出于我的目的,我需要获取一串 SVG 并在 PDF 中以特定大小和位置绘制它,同时保持图像的矢量性质(无光栅化)。

我想绕过 SAXSVGDocumentFactory.createSVGDocument() 函数中流行的 SVG 文件。我发现以下帖子有助于使用 SVG 文本字符串而不是平面文件。

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

您必须从您的 String 创建一个 StringReader 并将其传递给 SAXSVGDocumentFactory#createDocument(String, Reader) 方法。作为字符串的第一个参数传递的 URI 将是 SVG 文档的基本文档 URI。仅当您的 SVG 引用任何外部文件时,这才重要。

最好的祝福,

丹尼尔

源自 iText 示例的 Java 源代码:

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

请注意,这会将 SVG 绘制到您正在处理的 PDF 中。SVG 显示为文本上方的浮动层。我仍在努力移动/缩放它并让它与文本内联,但希望这超出了问题的直接范围。

希望这能有所帮助。

干杯

编辑:我能够使用以下方法将我的 svg 实现为内联对象。注释行用于添加快速边框以检查定位。

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);
于 2012-09-19T21:10:54.433 回答
7

这是我从我在这里找到的帖子和官方示例中得出的:

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

Image 实例可以很容易地添加到 pdf 中(在我的情况下作为签名)。

于 2014-01-08T16:13:16.930 回答
5

我最近了解到,您可以将 Graphics2D 对象直接发送到 iText,生成的 PDF 文件与可缩放矢量图形一样好。从您的帖子中,听起来这可能会解决您的问题。

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();
于 2009-01-02T21:44:22.867 回答
3

这对我使用 itext 7.1.3 通过 SVGConverter 渲染 SVG 图像很有用。

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();
于 2018-12-05T10:53:32.700 回答
1

新版本的 iText 也支持 SVG 文件。请参阅页面。

于 2019-04-23T06:06:48.027 回答
0

我可以使它工作的唯一方法是将矢量 SVG 文件转换为矢量 PDF 文件,然后将其插入我的 itext/openpdf PDF。

你没看错:我在我的 PDF 中插入了一个矢量 PDF,效果很好。您可以放大,一切正常。

我在 Spring Boot 应用程序中使用此代码:

public void addVectorToPDF(PdfWriter writer) throws IOException {

    // My SVG image that I converted to PDF format, keeping the vectorial format.
    URL resource = this.getClass().getResource("/resources/my-vectorial-image-pdf-format.pdf");

    PdfReader reader = new PdfReader(resource);

    // Getting the page 01 of the PDF. The PDF has only the
    // SVG image inside, so the page 01 is everything.
    PdfImportedPage page = writer.getImportedPage(reader, 1);

    float posX = 50;
    float posY = 300;
    float scale = 0.75F;
    PdfContentByte canvas = writer.getDirectContent();

    // adding vectorial image pdf to my pdf
    canvas.addTemplate(page, scale, 0, 0, scale, posX, posY);

}

您可以使用 zamzar.com 将矢量 SVG 转换为 PDF。它对我来说效果很好。

在我的例子中,使用 Batik 和 Graphics2D 的解决方案没有保留矢量格式。

于 2020-02-25T00:22:46.357 回答