DirectBuffer для ускорения ImageIO

У меня есть много операций, связанных с созданием объекта BufferedImage с использованием сторонней библиотеки и сохранением его в файл jpg. Иногда одна обработка может иметь более 10 000 таких сохранений. В настоящее время я использую ImageIO.write(image, "jpg", file) напрямую, но производительность не очень удовлетворительная.

Мне интересно, могу ли я использовать прямой ByteBuffer для ускорения записи на диск? Я думаю о том, чтобы поместить BufferedImage в прямой ByteBuffer и, наконец, сохранить на диск с помощью FileChannel. Я не нашел способ сделать это. Интересно, как я могу поместить BufferedImage для прямого ByteBuffer? Некоторый пример кода очень поможет.

Вам нужно хранить изображения в формате JPEG? Если это так, вам, вероятно, лучше всего использовать собственные привязки для libJPEGTurbo. Можно использовать ImageOutputStreams с поддержкой nio, но я еще не видел существенной выгоды от этого. Однако, если вы просто хотите сбросить пиксели из памяти без формата файла, может сработать использование прямого буфера. Вот немного пример кода с использованием отображенной памяти BufferedImages.

Harald K 14.03.2019 13:28

Другие вещи, которые вы можете сделать для повышения производительности в отношении ImageIO, — это отключить кэширование диска (ImageIO.setUseCache(false)). Но я сомневаюсь, что это сильно поможет, если вы все равно будете писать в файл.

Harald K 14.03.2019 13:45

@haraldK Да, в конце мне нужно записать изображение в файл jpg. Как помогает кэширование диска?

J Freebird 14.03.2019 13:49

Кэширование диска не помогает (для производительности то есть делает помогает в экономии памяти). Но он включен по умолчанию. Я предлагаю вам отключить его.

Harald K 14.03.2019 13:53

JAI ImageIO поддерживает nio FileChannel-поддерживаемый ImageOuputStreams, вы можете попробовать посмотреть, поможет ли это. Но все же, я думаю, что libJPEGTurbo быстрее, как было сказано выше.

Harald K 14.03.2019 13:57

@haraldK Так есть ли способ закодировать байтовый буфер в jpg и сохранить его как изображение jpg? Сохранение может быть быстрее, поскольку оно напрямую отображается в память.

J Freebird 14.03.2019 13:58

Я думаю, вы смотрите на это неправильно. Файлы с отображением памяти не будут работать быстрее, чем память. А ваши BufferedImage уже в памяти. Если вы сделаете какое-нибудь профилирование, скорее всего, вы обнаружите, что время тратится на процесс кодирования JPEG, а не на запись результата на диск (при условии приличного SSD). Да, возможно, вы могли бы сделать запись на диск немного быстрее. Но реальный выигрыш заключается в переходе на более быстрый энкодер.

Harald K 14.03.2019 14:04
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
7
207
1

Ответы 1

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public byte[] toByteArray(BufferedImage image) throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();            
    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(baos);
    encoder.encode(image);            
    return baos.toByteArray();
}

Из ответа это попробуйте это. Должно быть быстрее.

Мне тоже удалось это сделать, но позже я обнаружил, что byte[] нельзя сохранить в формате jpg.

J Freebird 14.03.2019 13:50
Не гарантируется, что программа Java, которая напрямую вызывает пакеты sun.*, будет работать на всех платформах, совместимых с Java. На самом деле такая программа не гарантирует работу даже в будущих версиях на той же платформе. Подробнее читайте в Почему разработчикам не следует писать программы, вызывающие «солнечные» пакеты.
Harald K 14.03.2019 13:50

Другие вопросы по теме