使用PDFBox和Apache Batik的PDF到SVG渲染问题

时间:2018-06-20 08:43:42

标签: java svg pdfbox batik

我将PDFBox与Apache Batik结合使用,以便将PDF页面呈现为SVG文档。它们中的大多数都能正常工作,但是在将特定图像渲染为SVG时遇到一些问题。

这是我使用的代码。它主要基于there上的帖子。

public void extractBookSvg(File pdfFile) throws Exception {
    // ... preliminary business actions

    SVGGeneratorContext ctx = createContext();
    SVGGraphics2D g = null;

    try (PDDocument document = PDDocument.load(pdfFile, MemoryUsageSetting.setupMixed(2147483648l))) {
        PDFRenderer renderer = new PDFRenderer(document);

        long startTime = System.currentTimeMillis();
        int pageNr = 0;
        for (PDPage page : document.getPages()) {
            long startTimeForPage = System.currentTimeMillis();

            g = createGraphics(ctx);
            renderer.renderPageToGraphics(pageNr, g, 3.47222f);

            pageNr++;
            try (OutputStream os = new ByteArrayOutputStream();
                    Writer out = new OutputStreamWriter(os)) {

                g.stream(out, true);

                //... do other business actions 
            }
        }
    }
    finally {
        pdfFile.delete();

        if (g != null) {
            g.finalize();
            g.dispose();
        }
    }
}

private SVGGraphics2D createGraphics(SVGGeneratorContext ctx) {
    SVGGraphics2D g2d = new CustomSVGGraphics2D(ctx, false);
    return g2d;
}

private SVGGeneratorContext createContext() {
    DOMImplementation impl = GenericDOMImplementation.getDOMImplementation();
    String svgNS = "http://www.w3.org/2000/svg";
    Document myFactory = impl.createDocument(svgNS, "svg", null);

    SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(myFactory);
    return ctx;
}

public static class CustomSVGGraphics2D extends SVGGraphics2D {

    public CustomSVGGraphics2D(SVGGeneratorContext generatorCtx, boolean textAsShapes) {
        super(generatorCtx, textAsShapes);
    }

    @Override
    public GraphicsConfiguration getDeviceConfiguration() {
        return new CustomGraphicsConfiguration();
    }
}

private static final class CustomGraphicsConfiguration extends GraphicsConfiguration {

    @Override
    public AffineTransform getNormalizingTransform() {
        return null;
    }

    @Override
    public GraphicsDevice getDevice() {
        return new CustomGraphicsDevice();
    }

    @Override
    public AffineTransform getDefaultTransform() {
        return null;
    }

    @Override
    public ColorModel getColorModel(int transparency) {
        return null;
    }

    @Override
    public ColorModel getColorModel() {
        return null;
    }

    @Override
    public java.awt.Rectangle getBounds() {
        return null;
    }
}

private static final class CustomGraphicsDevice extends GraphicsDevice {
    @Override
    public int getType() {
        return 0;
    }

    @Override
    public String getIDstring() {
        return null;
    }

    @Override
    public GraphicsConfiguration[] getConfigurations() {
        return null;
    }

    @Override
    public GraphicsConfiguration getDefaultConfiguration() {
        return null;
    }
}

如上所述,渲染图像时会出现问题:要么完全不渲染(显示为黑框),要么在某些不透明度低于1的图像上显示不透明度1。

以下是这两种情况的示例:

PDF render of transparent image

SVG render of transparent image

These images do not get rendered at all in SVG

How they actually show in the SVG

但是,如果我直接将这些页面呈现为图像(使用BufferedImage而不是Graphics2D),它们都可以很好地呈现(当然,质量要比svg低)。

此外,我尝试使用PDFDebugger实用工具调试PDF,这些图像没有出现在页面的资源XObject列表中,并且似乎在其他任何地方都找不到。

我的问题是:

  • 我如何找出问题是来自PDFBox渲染到Graphics2D对象中的方式,还是来自Batik生成SVG的方式?
  • 是否有办法确保在生成时正确显示这些图像?因为我在日志中看不到任何错误。
  • 如果是,那有什么解决方案?

谢谢!

0 个答案:

没有答案
相关问题