У меня есть много операций, связанных с созданием объекта BufferedImage с использованием сторонней библиотеки и сохранением его в файл jpg. Иногда одна обработка может иметь более 10 000 таких сохранений. В настоящее время я использую ImageIO.write(image, "jpg", file) напрямую, но производительность не очень удовлетворительная.
Мне интересно, могу ли я использовать прямой ByteBuffer для ускорения записи на диск? Я думаю о том, чтобы поместить BufferedImage в прямой ByteBuffer и, наконец, сохранить на диск с помощью FileChannel. Я не нашел способ сделать это. Интересно, как я могу поместить BufferedImage для прямого ByteBuffer? Некоторый пример кода очень поможет.
Другие вещи, которые вы можете сделать для повышения производительности в отношении ImageIO, — это отключить кэширование диска (ImageIO.setUseCache(false)). Но я сомневаюсь, что это сильно поможет, если вы все равно будете писать в файл.
@haraldK Да, в конце мне нужно записать изображение в файл jpg. Как помогает кэширование диска?
Кэширование диска не помогает (для производительности то есть делает помогает в экономии памяти). Но он включен по умолчанию. Я предлагаю вам отключить его.
JAI ImageIO поддерживает nio FileChannel-поддерживаемый ImageOuputStreams, вы можете попробовать посмотреть, поможет ли это. Но все же, я думаю, что libJPEGTurbo быстрее, как было сказано выше.
@haraldK Так есть ли способ закодировать байтовый буфер в jpg и сохранить его как изображение jpg? Сохранение может быть быстрее, поскольку оно напрямую отображается в память.
Я думаю, вы смотрите на это неправильно. Файлы с отображением памяти не будут работать быстрее, чем память. А ваши BufferedImage уже в памяти. Если вы сделаете какое-нибудь профилирование, скорее всего, вы обнаружите, что время тратится на процесс кодирования JPEG, а не на запись результата на диск (при условии приличного SSD). Да, возможно, вы могли бы сделать запись на диск немного быстрее. Но реальный выигрыш заключается в переходе на более быстрый энкодер.




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