仅部分显示GIF图像

问题描述 投票:0回答:1

我在Java中使用GIF图片时遇到了一个奇怪的问题。该图像由XML API作为Base64编码的字符串提供。要解码Base64,我使用版本1.13中的commons-codec库。

[当我仅解码Base64字符串并将字节写出到文件时,该图像在浏览器和MS Paint中正确显示(在这里没有其他可测试的东西。

final String base64Gif = "[Base64 as provided by API]";
final byte[] sigImg = Base64.decodeBase64(base64Gif);
File sigGif = new File("C:/Temp/pod_1Z12345E5991872040.org.gif");
try (FileOutputStream fos = new FileOutputStream()) {
    fos.write(sigImg);
    fos.flush();
}

结果文件在MS Paint中打开:

The resulting file opened in MS Paint

但是当我现在开始使用Java使用此文件时(例如,使用openhtmltopdf库从HTML创建PDF文档),它已损坏,并且无法正确显示。

final String htmlLetterStr = "[HTML as provided by API]";
final Document doc = Jsoup.parse(htmlLetterStr);

try (FileOutputStream fos = new FileOutputStream(new File("C:/Temp/letter_1Z12345E5991872040.pdf"))) {
    PdfRendererBuilder builder = new PdfRendererBuilder();

    builder.useFastMode();
    builder.withW3cDocument(new W3CDom().fromJsoup(doc), "file:///C:/Temp/");
    builder.toStream(fos);
    builder.useDefaultPageSize(210, 297, BaseRendererBuilder.PageSizeUnits.MM);
    builder.run();

    fos.flush();
}

当我现在打开生成的PDF时,上面创建的图像如下所示。似乎只打印了第一个像素行,或者缺少某些图层,等等。

enter image description here

如果我再次使用ImageIO读取图像,然后尝试将其转换为PNG,也会发生同样的情况。生成的PNG外观与PDF文档中打印的图像完全相同。

如何使图像在PDF文档中正确显示?

编辑:链接到API提供的原始GIF Base64:https://pastebin.com/sYJv6j0h

java gif javax.imageio openhtmltopdf
1个回答
1
投票

正如@haraldK在评论中指出的那样,通过XML API提供的GIF文件不符合GIF标准,因此无法通过Java的ImageIO API进行解析。

由于似乎不存在用于修复文件的纯Java工具,所以我现在想出的解决方法是通过Java的Process API使用ImageMagick。使用convert选项调用-coalesce命令将解析损坏的GIF并创建一个符合GIF标准的新GIF。

// Decode broken GIF image and write to disk
final String base64Gif = "[Base64 as provided by API]";
final byte[] sigImg = Base64.decodeBase64(base64Gif);
Path gifPath = Paths.get("C:/Temp/pod_1Z12345E5991872040.tmp.gif");
if (!Files.exists(gifPath)) {
    Files.createFile(gifPath);
}
Files.write(gifPath, sigImg, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);

// Use the Java Process API to call ImageMagick (on Linux you would use the 'convert' binary)
ProcessBuilder procBuild = new ProcessBuilder();
procBuild.command("C:\\Program Files\\ImageMagick-7.0.9-Q16\\magick.exe", "C:\\Temp\\pod_1Z12345E5991872040.tmp.gif", "-coalesce", "C:\\Temp\\pod_1Z12345E5991872040.gif");
Process proc = procBuild.start();

// Wait for ImageMagick to complete its work
proc.waitFor();

新创建的文件可以由Java的ImageIO API读取并按预期使用。

© www.soinside.com 2019 - 2024. All rights reserved.