SVG files are not rendered properly in iText Java. I should find a better way to insert vectorgraphs into my pdf files.
I'd like to generate PDF files with some vectorgraphs and texts programmatically. iText is one of the best library in processing PDF files in Java community. So I wrote a program with iText to fit my needs. My vectorgraphs were originally created by Adobe Illustrator, which is not supported directly in iText. After reading iText examples, I found that iText supports SVG files, so I convert my vectorgraphs to SVGs. However, these SVGs were still rendered incorrectly by iText. Some color was missing. Here is a very simple demo to reproduce the issue: First, add Maven dependencies (I'm using the latest version 9.0.0):
<dependencies>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-core</artifactId>
<version>9.0.0</version>
<type>pom</type>
</dependency>
</dependencies>
Second, write a simple Java class:
package net.opho.demo;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Image;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.properties.HorizontalAlignment;
import com.itextpdf.svg.converter.SvgConverter;
import java.io.FileInputStream;
public class main {
public static void main(String[] args) throws Exception {
String svgPath = "C:\\develop\\OPhOLogo.svg";
String outputPdfPathDemo = "C:\\develop\\demo.pdf";
try (FileInputStream svg = new FileInputStream(svgPath)) {
PdfDocument pdf = new PdfDocument(new PdfWriter(outputPdfPathDemo));
Image logo = SvgConverter.convertToImage(svg, pdf).setWidth(200).setHorizontalAlignment(HorizontalAlignment.CENTER);
Paragraph text = (new Paragraph("Some texts...")).setFontSize(20);
Document documentDemo = new Document(pdf);
documentDemo.add(logo);
documentDemo.add(text);
documentDemo.close();
}
}
}
In this example, the SVG file that I used can be previewed or downloaded from here.
The resultant PDF shows:
which is very different from the original SVG file in color!
As far as I am concerned, a good way to solve this problem is to avoid using SVG files. It is acknowledged that Adobe Illustrator files are very similar to PDF files. You can use a PDF viewer to open AI files directly. So why not directly embed the AI files in the PDF file (as a part)? I know that many document builder (such as latex compiler pdflatex
and xelatex
) support include PDFs as figures into a PDF, but how can I do the same thing with iText? I can merge AI files into a PDF file in iText, but such approaches induce a new page to the PDF, I just want the vectorgraph to be a part (like an image) in a PDF page. How can I do that?
If the above thinking is not a good way, or you know how to solve the SVG rendering bug, please tell me. Thank you!
An AI file is an Adobe proprietary hybrid. That like XFA forms is a PDF syntax wrapper around many sub parts. Thus in Illustrator the PDF output is not native. Here are some key lines, from a 19 KB SVG. Note as over 300 KB AI the XMP/XML metadata with thumbnail is roughly 50 KB alone ! Black as RGB in PDF would be [0 0 0] but in AI we see a different grey (35 31 32). The PDF body is compressed as a stream so needs decompression, and parts are PostScript Level3 headers (not used by a PDF reader) 65 KB is compressed specific to an AI stream. eventually about 26 KB uncompressed is the PDF equivalence of a 19 KB 1200x1025.142 SVG!
%PDF-1.6
%âãÏÓ
1 0 obj <</Metadata 2 0 R
2 0 obj <</Length 50644/Subtype/XML/Type/Metadata>>stream
<xmp:CreatorTool>Adobe Illustrator 27.5 (Windows)</xmp:CreatorTool>
<xmpGImg:width>256</xmpGImg:width><xmpGImg:height>236</xmpGImg:height>
<xmpGImg:format>JPEG</xmpGImg:format><xmpGImg:image>/9j/4AAQSkZJRgABAgEA...Cont...
<xmpTPg:HasVisibleTransparency>True</xmpTPg:HasVisibleTransparency>
<xmpTPg:PlateNames><rdf:Seq><rdf:li>Cyan</rdf:li>
<rdf:li>Magenta</rdf:li><rdf:li>Yellow</rdf:li><rdf:li>Black</rdf:li>
<xmpG:swatchName>Black</xmpG:swatchName>
<xmpG:mode>RGB</xmpG:mode><xmpG:type>PROCESS</xmpG:type>
<xmpG:red>35</xmpG:red><xmpG:green>31</xmpG:green><xmpG:blue>32</xmpG:blue>
3 0 obj<</Count 1/Kids[5 0 R]/Type/Pages>>
stream %!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 24.0
%%AI8_CreatorVersion: 27.5.0 %%For: (MISON) ()
13 0 obj <</Length 65536>>stream %AI24_ZStandard_Data(µ/ý XT¿....Cont...
28 0 obj <</Length 26758>> stream /OC /MC0 BDC /CS0 cs 0.494 0.827 0.969 scn /GS0 gs 0 68.74 1200 1025.142 re f ...........cont......
To explain how much SVG and PDF differ let us print your decompressed SVG in a Browser and decompress to see the similarities in vectors. The SVG you can compare by reading in any text reader is on the left and for each stroke I have added a line feed. However the PDF format is optimised into a zip stream so need to be decompressed and then the line feeds and other white spaces are automatically added.
Things you can see instantly are:
File size wise:
Uncompressed SVG=18.8 KB
PDF internal stream =6 0 obj <</Length 22412>> with overheads 24.0 KB (compressed 10.4 KB)
we are looking at just a very small part of this core section.
File handling is thus totally different as the AI file may externally look smaller , yet have lots of additional Overheads like metadata and thumbnails which are not generally used by a PDF reader.
The PDF writer needs to convert all of an SVG area into PDF values. Then compact them to reduce file size. Part of the reason a PDF could not be made any smaller or faster as the whole image needs to be decompressed into much more memory before rendering a given stream.
Each have their own way of working and have very few similarities internally or in handling.
A good WEB based HTML to PDF Printing conversion tool, should use the web colouring system efficiently to produce a "larger" well coloured PDF.