web-dev-qa-db-ja.com

ファイルからBufferedImageに画像を読み書きする最も速い方法は?

  1. Java/GrailsでファイルからBufferedImageに画像を読み込む最も速い方法は何ですか?
  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()
8
user2722142

読み取るソリューションは、基本的にバイトを2回読み取ることです。1回はファイルから、もう1回はByteArrayInputStreamから読み取ります。それをしないでください

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を呼び出すと、(AFAIK)がバッファリングされていないChannelInputStreamが返されます。あなたはそれを包みたいでしょう

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

そのため、使用方法に応じて、ディスクへのIO呼び出しが少なくなります。

パーティーに遅れましたが、とにかく...

実際には、以下を使用します。

_ImageIO.read(new File(basePath + imageSource));
_

そして

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

...より速くなる可能性があります(プロファイラーを使用して試してみてください)。

これは、これらのバリアントがRandomAccessFile-backed ImageInputStream/ImageOutputStream実装を舞台裏で使用しているのに対し、InputStream/OutputStreamベースのバージョンはデフォルトでは、ディスクでバックアップされたシーク可能なストリームの実装を使用します。ディスクバッキングには、ストリームの内容全体を一時ファイルに書き込み、場合によってはそこから読み戻すことが含まれます(これは、イメージI/Oが非線形データアクセスの恩恵を受けることが多いためです)。

ストリームベースのバージョンで余分なI/Oを回避したい場合は、より多くのメモリを使用する代わりに、あいまいな名前の ImageIO.setUseCache(false) を呼び出して、無効にすることができますシーク可能な入力ストリームのディスクキャッシング。非常に大きな画像を扱っている場合、これは明らかに良い考えではありません。

5
haraldK

あなたはほとんど書くのが上手です。中間のByteArrayOutputStreamを使用しないでください。これは、コードの大きなボトルネックです。代わりに、FileOutputStreamをBufferedOutputStreamでラップし、同じことを行います。

あなたの読書にも同じことが言えます。 ItermediateByteArrayInputStreamを削除します。

0