我们使用iText从Java生成PDF(部分基于本网站的推荐)。但是,以GIF等图像格式嵌入我们的徽标副本会导致人们放大和缩小时看起来有点奇怪。
理想情况下,我们希望将图像嵌入到矢量格式中,例如EPS,SVG或仅仅是PDF模板。该网站声称已经放弃了EPS支持,在PDF中嵌入PDF或PS可能会导致错误,甚至没有提到SVG。
我们的代码直接使用Graphics2D API而不是iText,但是如果达到了结果,我们愿意打破AWT模式并使用iText本身。如何才能做到这一点?
根据documentation 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();
}
}
}
这是我从这里发现的帖子和官方例子得出的:
/**
* 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(在我的情况下作为签名)。
我找到了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)方法。作为String传递的第一个参数的URI将是SVG文档的基本文档URI。只有在SVG引用任何外部文件时,这才应该很重要。
最好的祝福,
丹尼尔
Java Source源自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();
请注意,这将为您正在处理的PDF绘制SVG。 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);
我最近了解到,您可以将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();
这适用于我使用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();
新版iText也支持SVG文件。请参阅this页面。