GIF изображение отображается только частично - PullRequest
0 голосов
/ 17 февраля 2020

У меня странная проблема с GIF-изображением в Java. Изображение предоставляется API XML в виде строки в кодировке Base64. Для декодирования Base64 я использую библиотеку commons-code c в версии 1.13.

Когда я просто декодирую строку 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 (например, создавая документ PDF из HTML с использованием библиотеки openhtmltopdf), он поврежден и не отображается должным образом.

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?

Редактировать: ссылка на оригинальный GIF Base64 as предоставляемые API: https://pastebin.com/sYJv6j0h

1 Ответ

1 голос
/ 24 февраля 2020

Как отметил @haraldK в комментариях, файл GIF, предоставляемый через API XML, не соответствует стандарту GIF и, следовательно, не может быть проанализирован с помощью API-интерфейса ImageIO Java.

Поскольку Кажется, не существует чистого Java инструмента для восстановления файла, обходной путь, который я нашел сейчас, - это использование ImageMagick через Java Process API. Вызов команды convert с параметром -coalesce проанализирует сломанный 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 API ImageIO и будет использоваться, как ожидается.

...