Grafika wektorowa w iText PDF

Używamy iText do generowania plików PDF z Javy (częściowo w oparciu o zalecenia na tej stronie). Jednak osadzenie kopii naszego logo w formacie obrazu, takim jak GIF, powoduje, że wygląda nieco dziwnie, gdy ludzie przybliżają i oddalają.

Najlepiej byłoby osadzić obraz w formacie wektorowym, takim jak EPS, SVG lub po prostu szablon PDF. Witryna twierdzi, że obsługa EPS została wycofana, że osadzenie pliku PDF lub PS w pliku PDF może powodować błędy, a nawet nie wspomina o tym SVG.

Nasz kod używa API Graphics2D zamiast bezpośrednio iText, ale bylibyśmy skłonni wyjść z trybu AWT i użyć samego iText, jeśli osiągnie wynik. Jak można to zrobić?

Author: Marcus Downing, 2009-01-02

7 answers

Zgodnie z dokumentacją iText obsługuje następujące formaty obrazów: JPEG, GIF, PNG, TIFF, BMP, WMF i EPS. Nie wiem, czy to może pomóc, ale z powodzeniem użyłem iTextSharp do osadzenia obrazu wektor WMF w pliku 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();
        }
    }
}
 8
Author: Darin Dimitrov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-03 13:36:06

Znalazłem kilka przykładów autorstwa iText, które wykorzystują API Graphics2D i bibliotekę Apache Batik do rysowania SVG w pliku PDF.

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

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

Dla moich celów, musiałem wziąć ciąg SVG i narysować go w pliku PDF w określonym rozmiarze i miejscu, zachowując wektorowy Charakter obrazu (bez rasteryzacji).

Chciałem ominąć plik SVG wydaje się to powszechne w SAXSVGDocumentFactory.createSVGDocument () funkcje. Znalazłem następujący post pomocny przy użyciu ciągu tekstowego SVG zamiast płaskiego pliku.

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

Musisz utworzyć StringReader ze swojego łańcucha i przekazać go do metody SAXSVGDocumentFactory#createDocument (String, Reader). URI, który przekazujesz jako pierwszy parametr jako ciąg znaków, będzie dokumentem podstawowym URI dokumentu SVG. Powinno to być ważne tylko wtedy, gdy SVG odwołuje się do plików zewnętrznych.

Pozdrawiam,

Daniel

Źródło Javy pochodzące z przykładów 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();

Zwróć uwagę, że spowoduje to narysowanie SVG do pliku PDF, nad którym pracujesz. SVG jest wyświetlany jako pływająca warstwa nad tekstem. Nadal pracuję nad przeniesieniem / skalowaniem i utrzymaniem go w linii z tekstem, ale mam nadzieję, że jest to poza bezpośrednim zakresem pytanie.

Mam nadzieję, że to pomoże.

Cheers

EDIT: udało mi się zaimplementować mój svg jako obiekt inline, używając następujących elementów. Linie komentowane służą do szybkiego dodawania obramowania w celu sprawdzenia pozycjonowania.

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);
 7
Author: clayzermk1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-26 00:14:16

To wynika z postów, które tu znalazłem i oficjalnych przykładów:

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

Instancję obrazu można łatwo dodać do pliku pdf(w moim przypadku jako podpis).

 7
Author: Nick Russler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-08 16:13:16

Niedawno dowiedziałem się, że możesz wysłać swój obiekt Graphics2D bezpośrednio do iText, a wynikowe pliki PDF są tak samo dobre jak skalowalna grafika wektorowa. Z twojego postu wynika, że może to rozwiązać twój problem.

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();
 5
Author: David Koelle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-02 21:44:22

To działało u mnie przy użyciu itext 7.1.3 do renderowania obrazu SVG przez 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();
 3
Author: Yahini priya Raja,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-12-05 10:53:32

Nowa wersja iText obsługuje również pliki SVG. Proszę zapoznać się z Ta strona.

 1
Author: user3327560,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-04-23 06:08:28

Jedynym sposobem, aby to działało, jest Konwersja wektorowego pliku SVG na wektorowy plik PDF , przed wstawieniem go do mojego iText/OPENPDF PDF.

Dobrze zrozumiałeś: wstawiam wektorowy PDF do mojego PDF i działa jak urok. Możesz powiększyć i wszystko działa dobrze.

Używam tego kodu w aplikacji 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);

}

Możesz użyć zamzar.com aby przekonwertować wektorowy SVG na PDF. Dobrze mi to wyszło.

Rozwiązania z Batik i Graphics2D nie zachowały w moim przypadku formatu wektorowego.

 0
Author: Rafael S. Fijalkowski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-25 00:28:09