高效的PDF格式SVG渲染(Java,Batik,Flying Saucer)

时间:2022-01-06 00:28:54

I'm rendering PDFs with XHTML and flying saucer. I've added SVG images (icons etc) as well. However, when I try to draw a lot of images (like 5000+) the rendering takes really long (obviously). There are only 10 or so different images to draw, but just repeating them a lot of times (same size).

我正在使用XHTML和飞碟渲染PDF。我也添加了SVG图像(图标等)。但是,当我尝试绘制大量图像(如5000+)时,渲染需要很长时间(显然)。只有10个左右的不同图像可以绘制,但只是重复它们很多次(相同的大小)。

Is there a way/library to do this efficiently?

有没有方法/库有效地做到这一点?

Currently using batik, flying saucer combo to draw images. The following code is used to parse the xhtml and find the img tags to place the SVG images:

目前使用蜡染,飞碟组合绘制图像。以下代码用于解析xhtml并找到img标记来放置SVG图像:

@Override
public ReplacedElement createReplacedElement(LayoutContext layoutContext, BlockBox blockBox, UserAgentCallback userAgentCallback, int cssWidth, int cssHeight) {
    Element element = blockBox.getElement();
    if (element == null) {
        return null;
    }
    String nodeName = element.getNodeName();
    if ("img".equals(nodeName)) {
        SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(XMLResourceDescriptor.getXMLParserClassName());
        SVGDocument svgImage = null;
        try {
            svgImage = factory.createSVGDocument(new File(element.getAttribute("src")).toURL().toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
        Element svgElement = svgImage.getDocumentElement();
        element.appendChild(element.getOwnerDocument().importNode(svgElement, true));
        return new SVGReplacedElement(svgImage, cssWidth, cssHeight);
    }
    return this.superFactory.createReplacedElement(layoutContext, blockBox, userAgentCallback, cssWidth, cssHeight);
}

And to draw the images i use:

并绘制我使用的图像:

    @Override
public void paint(RenderingContext renderingContext, ITextOutputDevice outputDevice, 
        BlockBox blockBox) {

    PdfContentByte cb = outputDevice.getWriter().getDirectContent();
    float width = cssWidth / outputDevice.getDotsPerPoint();
    float height = cssHeight / outputDevice.getDotsPerPoint();

    PdfTemplate template = cb.createTemplate(width, height);
    Graphics2D g2d = template.createGraphics(width, height);
    PrintTranscoder prm = new PrintTranscoder();
    TranscoderInput ti = new TranscoderInput(svg);
    prm.transcode(ti, null);
    PageFormat pg = new PageFormat();
    Paper pp = new Paper();
    pp.setSize(width, height);
    pp.setImageableArea(0, 0, width, height);
    pg.setPaper(pp);
    prm.print(g2d, pg, 0);
    g2d.dispose();

    PageBox page = renderingContext.getPage();
    float x = blockBox.getAbsX() + page.getMarginBorderPadding(renderingContext, CalculatedStyle.LEFT);
    float y = (page.getBottom() - (blockBox.getAbsY() + cssHeight)) + page.getMarginBorderPadding(
            renderingContext, CalculatedStyle.BOTTOM);
    x /= outputDevice.getDotsPerPoint(); 
    y /= outputDevice.getDotsPerPoint();

    cb.addTemplate(template, x, y);
}

An idea of the scaling. 100 images take 2 seconds, 5000 images take about 42 seconds on an i5 8gb RAM.

缩放的想法。在i5 8gb RAM上,100张图像需要2秒,5000张图像需要42秒。

So is there a way to store a drawn SVG in memory and paste it more quickly or something? Because right now it seems to take all images as separate images and eat all my memory and take forever.

那么有没有办法将绘制的SVG存储在内存中并更快地粘贴它或什么?因为现在它似乎把所有图像作为单独的图像,吃掉我所有的记忆,并永远。

1 个解决方案

#1


Managed to optimize the memory and speed by doing two things. I pre-generated the SVGDocuments in the createReplacedElement method which sped it up a bit. The main improvement was pre-generating all pdfTemplates for all the images. This greatly increased speed as the templates already contained the rendered images. The rendering of all regular text is still slow, so I might turn down the DPI.

通过做两件事来管理以优化内存和速度。我在createReplacedElement方法中预先生成了SVGDocuments,加快了它的速度。主要的改进是为所有图像预生成所有pdfTemplates。由于模板已包含渲染图像,因此速度大大提高。所有常规文本的呈现仍然很慢,因此我可能会拒绝DPI。

EDIT: further optimization see Is there any way improve the performance of FlyingSaucer?

编辑:进一步优化看是否有任何方法可以提高FlyingSaucer的性能?

#1


Managed to optimize the memory and speed by doing two things. I pre-generated the SVGDocuments in the createReplacedElement method which sped it up a bit. The main improvement was pre-generating all pdfTemplates for all the images. This greatly increased speed as the templates already contained the rendered images. The rendering of all regular text is still slow, so I might turn down the DPI.

通过做两件事来管理以优化内存和速度。我在createReplacedElement方法中预先生成了SVGDocuments,加快了它的速度。主要的改进是为所有图像预生成所有pdfTemplates。由于模板已包含渲染图像,因此速度大大提高。所有常规文本的呈现仍然很慢,因此我可能会拒绝DPI。

EDIT: further optimization see Is there any way improve the performance of FlyingSaucer?

编辑:进一步优化看是否有任何方法可以提高FlyingSaucer的性能?