Java 将图像从文件读/写到 BufferedImage 的最快方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18522398/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 08:44:45  来源:igfitidea点击:

Fastest way to read/write Images from a File into a BufferedImage?

javagrailsgrails-2.0javax.imageio

提问by

  1. What is the fastest way to read Images from a File into a BufferedImage in Java/Grails?
  2. What is the fastest way to write Images from a BufferedImage into a File in Java/Grails?
  1. 在 Java/Grails 中将图像从文件读入 BufferedImage 的最快方法是什么?
  2. 在 Java/Grails 中将 BufferedImage 中的图像写入文件的最快方法是什么?

my variant (read):

我的变体(阅读):

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

my variant (write):

我的变体(写):

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()

采纳答案by Sotirios Delimanolis

Your solution to read is basically reading the bytes twice, once from the file and once from the ByteArrayInputStream. Don't do that

您的读取解决方案基本上是读取字节两次,一次是从文件中读取,一次是从ByteArrayInputStream. 不要那样做

With Java 7 to read

用Java 7阅读

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

With Java 7 to write

用Java 7编写

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

The call to Files.newInputStreamwill return a ChannelInputStreamwhich (AFAIK) is not buffered. You'll want to wrap it

调用Files.newInputStream将返回一个ChannelInputStream(AFAIK)未缓冲的。你会想要包装它

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

So that there are less IO calls to disk, depending on how you use it.

从而减少对磁盘的 IO 调用,具体取决于您的使用方式。

回答by Martijn Courteaux

You are almost good for writing. Just don't use the intermediate ByteArrayOutputStream. It is a giant bottleneck in your code. Instead wrap the FileOutputStream in a BufferedOutputStream and do the same.

你几乎擅长写作。只是不要使用中间的 ByteArrayOutputStream。这是您代码中的一个巨大瓶颈。而是将 FileOutputStream 包装在 BufferedOutputStream 中并执行相同的操作。

Same goes indeed for your reading. Remove the Itermediate ByteArrayInputStream.

你的阅读也是如此。删除中间 ByteArrayInputStream。

回答by haraldK

I'm late to the party, but anyway...

我参加聚会迟到了,但无论如何......

Actually, using:

实际上,使用:

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

and

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

...might prove faster (try it, using a profiler, to make sure).

...可能会更快(尝试一下,使用分析器,以确保)。

This is because these variants use RandomAccessFile-backed ImageInputStream/ImageOutputStreamimplementations behind the scenes, while the InputStream/OutputStream-based versions will by default use a disk-backed seekable stream implementation. The disk-backing involves writing the entire contents of the stream to a temporary file and possibly reading back from it (this is because image I/O often benefits from non-linear data access).

这是因为这些变体在幕后使用RandomAccessFile-backed ImageInputStream/ImageOutputStream实现,而InputStream/ -basedOutputStream版本将默认使用磁盘支持的可查找流实现。磁盘备份涉及将流的全部内容写入临时文件并可能从中读取(这是因为图像 I/O 通常受益于非线性数据访问)。

If you want to avoid extra I/O with the stream based versions, at the cost of using more memory, it is possible to call the ambiguously named ImageIO.setUseCache(false), to disable disk cachingof the seekable input streams. This is obviously not a good idea if you are dealing with very large images.

如果您想在基于流的版本中避免额外的 I/O,以使用更多内存为代价,则可以调用名称不明确的ImageIO.setUseCache(false),以禁用可查找输入流的磁盘缓存。如果您正在处理非常大的图像,这显然不是一个好主意。