【问题标题】:Efficient SVG rendering for PDFs (Java, Batik, Flying Saucer)PDF 的高效 SVG 渲染(Java、Batik、Flying Saucer)
【发布时间】:2023-03-03 23:58:01
【问题描述】:

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

有没有办法/图书馆有效地做到这一点?

目前使用蜡染、飞碟组合来绘制图像。以下代码用于解析 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);
}

并绘制我使用的图像:

    @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);
}

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

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

【问题讨论】:

    标签: java performance memory svg pdf-generation


    【解决方案1】:

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

    编辑:进一步优化参见Is there any way improve the performance of FlyingSaucer?

    【讨论】:

      猜你喜欢
      • 2012-05-13
      • 1970-01-01
      • 1970-01-01
      • 2014-10-17
      • 1970-01-01
      • 2011-04-10
      • 1970-01-01
      • 2011-10-23
      • 2015-06-29
      相关资源
      最近更新 更多