首页 > 解决方案 > 使用 PDFBox 和 Apache Batik 的 PDF 到 SVG 渲染问题

问题描述

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

这是我使用的代码。主要是根据那边的帖子。

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渲染

透明图像的 SVG 渲染

这些图像根本不会在 SVG 中呈现

它们在 SVG 中的实际显示方式

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

此外,我尝试使用 PDFDebugger 实用程序调试 PDF,这些图像没有出现在页面的资源 XObject 列表中,而且我似乎无法在其他地方找到它们。

我的问题是:

谢谢!

标签: javasvgpdfboxbatik

解决方案


推荐阅读