Мы используем iText для создания PDF-файлов из Java (частично на основе рекомендаций на этом сайте). Однако встраивание копии нашего логотипа в формат изображения, такой как GIF, приводит к тому, что он выглядит немного странно, когда люди увеличивают и уменьшают масштаб.
В идеале мы хотели бы встроить изображение в векторный формат, такой как EPS, SVG или просто шаблон PDF. На веб-сайте утверждается, что поддержка EPS прекращена, что встраивание PDF или PS в PDF может привести к ошибкам, и даже не упоминается SVG.
Наш код использует Graphics2D API, а не iText напрямую, но мы были бы готовы выйти из режима AWT и использовать сам iText, если бы он достиг результата. Как это может быть сделано?




Недавно я узнал, что вы можете отправить свой объект 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 поддерживает следующие форматы изображений: JPEG, GIF, PNG, TIFF, BMP, WMF и EPS. Я не знаю, может ли это помочь, но я успешно использовал iTextSharp для встраивания векторного изображения WMF в файл 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();
}
}
}
Я получаю исключение, когда пробовал ваш код, это не работает для меня, я недавно прочитал, что eps не поддерживается, вы должны преобразовать его в WMF
Я нашел пару примеров от автора iText, которые используют Graphics2D API и библиотеку Apache Batik для рисования SVG в PDF.
http://itextpdf.com/examples/iia.php?id=269
http://itextpdf.com/examples/iia.php?id=263
Для моих целей мне нужно было взять строку SVG и нарисовать ее в PDF-файле определенного размера и в определенном месте, сохраняя при этом векторный характер изображения (без растеризации).
Я хотел обойти SVG-файл, который, кажется, преобладает в функциях SAXSVGDocumentFactory.createSVGDocument (). Я нашел следующий пост полезным для использования текстовой строки SVG вместо плоского файла.
http://batik.2283329.n4.nabble.com/Parse-SVG-from-String-td3539080.html
You have to create a StringReader from your String and pass that to the SAXSVGDocumentFactory#createDocument(String, Reader) method. The URI that you pass as the first parameter as a String will be the base document URI of the SVG document. This should only be important if your SVG references any external files.
Best regards,
Daniel
Исходный код Java, полученный из примеров 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();
Обратите внимание, что это приведет к отображению 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);
Здравствуйте, я пытаюсь найти способ сделать что-то подобное, чтобы преобразовать файлы SVG в документ PDF. Какую версию Itext вы используете? Я заметил, что конструкторы являются частными для класса com.lowagie.text.pdf.PdfGraphics2D, по крайней мере, в iText 2.1.2, и я не смог найти такой класс в IText 5.5.4. Спасибо! - Хосе Тепедино 6 минут назад
@JoseTepedino Мне очень жаль, но я не касался этого годами (с тех пор, как написал ответ). Я могу представить, что использую версию, выпущенную примерно в сентябре 2012 года, так что это, вероятно, будет iText 5.3.2, выпущенная в августе 2012 года в соответствии с их выпусками GitHub - github.com/itext/itextpdf/releases/tag/5.3.2. Надеюсь, это поможет.
Спасибо за твое сообщение! Я добился небольшого прогресса, найдя страницу API, на которой указано, что класс PdfGraphics2D из пакета com.itextpdf.awt существует с iText 5.0.2: developers.itextpdf.com/reference/…. Мне еще предстоит кое-что обсудить, но поиск правильной версии для использования - хорошее начало. Спасибо!
Это то, что я извлек из сообщений, которые я нашел здесь, и официальных примеров:
/**
* 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);
}
Экземпляр изображения можно легко добавить в pdf (в моем случае в качестве подписи).
Классы в приведенном выше коде могут быть импортированы с использованием следующей зависимости maven: <dependency> <groupId>org.apache.xmlgraphics</groupId> <artifactId>batik-gvt</artifactId> <version>1.7</version> </dependency>
Это сработало для меня, используя itext 7.1.3 для рендеринга изображения SVG с помощью 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();
Новая версия iText также поддерживает файлы SVG. См. Страницу это.
Согласовано. Добавьте в этот ответ полезные подробности, и я с радостью проголосую за него.
Единственный способ заставить его работать - это преобразование векторного файла SVG в векторный файл PDF, прежде чем вставлять его в мой PDF-файл itext / openpdf.
Вы правильно поняли: я вставляю векторный 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 в моем случае не сохранили векторный формат.
Это то, что мы уже делаем - используем Graphics2D для рисования на странице. Нам нужно добавить изображение в векторном формате.