Самый быстрый способ чтения / записи изображений из файла в BufferedImage?

  1. каков самый быстрый способ чтения изображений из файла в BufferedImage в Java / Grails?
  2. каков самый быстрый способ записи изображений из BufferedImage в файл в Java/Grails?

мой вариант (чтение):

byte [] imageByteArray = new File(basePath+imageSource).readBytes()
InputStream inStream = new ByteArrayInputStream(imageByteArray)
BufferedImage bufferedImage = ImageIO.read(inStream)

мой вариант (напишите):

BufferedImage bufferedImage = // some image
def fullPath = // image page + file name
byte [] currentImage

try{

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ImageIO.write( bufferedImage, "jpg", baos );
    baos.flush();
    currentImage = baos.toByteArray();
    baos.close();

    }catch(IOException e){
        System.out.println(e.getMessage());
    }       
   }    


def newFile = new FileOutputStream(fullPath)
newFile.write(currentImage)
newFile.close()

3 ответов


ваше решение для чтения в основном читает байты дважды, один раз из файла и один раз из ByteArrayInputStream. Не делай этого!--7-->

С Java 7 для чтения

BufferedImage bufferedImage = ImageIO.read(Files.newInputStream(Paths.get(basePath + imageSource)));

С Java 7 для записи

ImageIO.write(bufferedImage, "jpg", Files.newOutputStream(Paths.get(fullPath)));

вызов Files.newInputStream вернет ChannelInputStream который (AFAIK) не буферизован. Вы захотите завернуть его

new BufferedInputStream(Files.newInputStream(...));

чтобы было меньше вызовов ввода-вывода на диск, в зависимости от того, как вы его используете.


Я опаздываю на вечеринку, но в любом случае...

на самом деле, использовать:

ImageIO.read(new File(basePath + imageSource));

и

ImageIO.write(bufferedImage, "jpeg", new File(fullPath));

...может оказаться быстрее (попробуйте, используя профилировщик, чтобы убедиться).

это потому, что эти варианты используют RandomAccessFile - backed ImageInputStream/ImageOutputStream реализаций за кулисами, в то время как InputStream/OutputStream - версии по умолчанию будут использовать реализацию потока поиска с поддержкой диска. Резервное копирование диска включает запись всего содержимого поток во временный файл и, возможно, чтение из него (это связано с тем, что ввод-вывод изображений часто выигрывает от нелинейного доступа к данным).

если вы хотите избежать дополнительного ввода-вывода с потоковыми версиями, за счет использования большего объема памяти, можно вызвать двусмысленно названный ImageIO.setUseCache(false), чтобы отключить кэширование диска искомых входных потоков. Это, очевидно, не очень хорошая идея, если вы имеете дело с очень большими изображениями.


вы почти хороши для письма. Просто не используйте промежуточный ByteArrayOutputStream. Это гигантское узкое место в вашем коде. Вместо этого оберните FileOutputStream в BufferedOutputStream и сделайте то же самое.

то же самое касается вашего чтения. Удалите Itermediate ByteArrayInputStream.