2015-05-12 2 views
2

Я получаю PDF-файлы с XHTML и летающей тарелкой. Я добавил изображения SVG (значки и т. Д.). Однако, когда я пытаюсь рисовать много изображений (например, 5000+), рендеринг занимает очень много времени (очевидно). Есть только 10 или около того различных изображений, которые нужно рисовать, но просто повторяя их много раз (одинаковый размер).Эффективный SVG-рендеринг для PDF-файлов (Java, Batik, Flying Saucer)

Есть ли способ/библиотека, чтобы сделать это эффективно?

В настоящее время используется батик, летающая тарелка комбо для рисования изображений. Следующий код используется для разбора 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); 
} 

Идея масштабирования. 100 изображений занимают 2 секунды, 5000 изображений занимают около 42 секунд на i5 8gb RAM.

Итак, есть способ сохранить нарисованный SVG в памяти и вставить его быстрее или что-то еще? Потому что прямо сейчас кажется, что все изображения являются отдельными изображениями и съедают всю мою память и уходят навсегда.

ответ

1

Удаленное управление памятью и скоростью, делая две вещи. Я предварительно сгенерировал SVGDocuments в методе createReplacedElement, который немного ускорил его. Главным преимуществом было создание всех pdfTemplates для всех изображений. Это значительно увеличило скорость, поскольку шаблоны уже содержали визуализированные изображения. Отрисовка всего обычного текста все еще медленная, поэтому я могу отклонить DPI.

EDIT: дальнейшая оптимизация см. Is there any way improve the performance of FlyingSaucer?

Смежные вопросы