it-roy-ru.com

Java BufferedImage в формат PNG Base64 String

Я пытаюсь получить вывод на скриншот в виде строки в кодировке base64, но не очень далеко. Код, который у меня есть, использует библиотеку Base64 ( http://iharder.sourceforge.net/current/Java/base64/ ):

    Robot robot = new Robot();
    Rectangle r = new Rectangle( Toolkit.getDefaultToolkit().getScreenSize() );
    BufferedImage bi = robot.createScreenCapture(r);
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    OutputStream b64 = new Base64.OutputStream(os);
    ImageIO.write(bi, "png", os);
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    out.writeTo(b64);
    String result = out.toString("UTF-8");

Каждый раз, когда я запускаю это, «результат» всегда пустая строка, но я не понимаю, почему. Есть идеи?

Примечание: я не хочу записывать png в файл на диске.

12
user72003

Я следовал за xehpuk's answer, но у меня были проблемы с определенными изображениями, в которых отсутствовали последние несколько строк пикселей при визуализации в определенных браузерах через URL-адрес данных (Chrome и Firefox, Safari, казалось, прекрасно их отображали). Я подозреваю, что это потому, что браузер делает все возможное, чтобы интерпретировать данные, но последние несколько байтов данных отсутствовали, поэтому он показывает, что он может.

Кажется, причиной этой проблемы является обтекание выходного потока. Документация для Base64.wrap(OutputStream os) объясняет: 

Рекомендуется незамедлительно закрыть возвращенный выходной поток после использования, во время которого он сбросит все возможные оставшиеся байты в основной выходной поток.

Таким образом, в зависимости от длины данных, возможно, что последние несколько байтов не очищаются от потока, потому что close() не вызывается для него. Мое решение этого состояло в том, чтобы не беспокоить обтекание потока и просто закодировать поток непосредственно:

public static String imgToBase64String(final RenderedImage img, final String formatName)
{
  final ByteArrayOutputStream os = new ByteArrayOutputStream();

  try
  {
    ImageIO.write(img, formatName, os);
    return Base64.getEncoder().encodeToString(os.toByteArray());
  }
  catch (final IOException ioe)
  {
    throw new UncheckedIOException(ioe);
  }
}

Это решило проблемы с отсутствующими рядами пикселей при визуализации в браузере.

8
Robert Hunt

Следующее утверждение работает в неправильном направлении:

out.writeTo(b64);

Он перезаписывает данные Base 64 пустым байтовым массивом out.

Какова цель out в любом случае? Я не думаю, что вам это нужно.

Обновление:

И вы записываете изображение непосредственно в os вместо записи через кодировщик Base 64.

Следующий код должен работать:

...
ByteArrayOutputStream os = new ByteArrayOutputStream();
OutputStream b64 = new Base64.OutputStream(os);
ImageIO.write(bi, "png", b64);
String result = os.toString("UTF-8");
15
Codo

Кодирование Base64 и декодирование изображений с использованием Java 8:

public static String imgToBase64String(final RenderedImage img, final String formatName) {
    final ByteArrayOutputStream os = new ByteArrayOutputStream();
    try {
        ImageIO.write(img, formatName, Base64.getEncoder().wrap(os));
        return os.toString(StandardCharsets.ISO_8859_1.name());
    } catch (final IOException ioe) {
        throw new UncheckedIOException(ioe);
    }
}

public static BufferedImage base64StringToImg(final String base64String) {
    try {
        return ImageIO.read(new ByteArrayInputStream(Base64.getDecoder().decode(base64String)));
    } catch (final IOException ioe) {
        throw new UncheckedIOException(ioe);
    }
}

Используйте это так для сценария скриншота:

final Robot robot = new Robot();
final Rectangle r = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
final BufferedImage bi = robot.createScreenCapture(r);
final String base64String = imgToBase64String(bi, "png");
11
xehpuk

Это работает для меня:

Кодировать изображение в строку Base64

public static String encodeToString(BufferedImage image, String type) {
    String imageString = null;
    ByteArrayOutputStream bos = new ByteArrayOutputStream();

    try {
        ImageIO.write(image, type, bos);
        byte[] imageBytes = bos.toByteArray();

        Base64.Encoder encoder = Base64.getEncoder();
        imageString = encoder.encodeToString(imageBytes);

        bos.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return imageString;
}

Декодировать Base64 String в изображение

public static BufferedImage decodeToImage(String imageString) {
    BufferedImage image = null;
    byte[] imageByte;
    try {
        Base64.Decoder decoder = Base64.getDecoder();
        imageByte = decoder.decode(imageString);
        ByteArrayInputStream bis = new ByteArrayInputStream(imageByte);
        image = ImageIO.read(bis);
        bis.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return image;
}
0
Manuel Schmitzberger