iText PDF 中的矢量图形

2022-09-03 18:05:28

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

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

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


答案 1

根据文档,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();
        }
    }
}

答案 2

我找到了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

您必须从字符串创建一个 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);

推荐