是的,可以从(单个)InputStream读取多个图像.

我认为最明显的解决方案是使用一种文件格式,该文件格式已广泛支持多种图像,例如TIFF.即使ImageIO类没有任何便利的方法,如ImageIO.read(…)/ ImageIO.write(…),javax.imageio API也对读取和写入多图像文件提供了良好的支持. )读取/写入单个图像的方法.这意味着您需要编写更多代码(下面的代码示例).

但是,如果输入是由控件之外的第三方创建的,则不能选择使用其他格式.从注释中可以看出,您的输入实际上是串联的Exif JPEG流.好消息是,Java的JPEGImageReader / Writer确实允许在同一流中包含多个JPEG,即使这种格式不是很常见.

要从同一流中读取多个JPEG,可以使用以下示例(请注意,该代码是完全通用的,并且可以读取其他多图像文件,例如TIFF):

File file = ...; // May also use InputStream here

List images = new ArrayList<>();

try (ImageInputStream in = ImageIO.createImageInputStream(file)) {

Iterator readers = ImageIO.getImageReaders(in);

if (!readers.hasNext()) {

throw new AssertionError("No reader for file " + file);

}

ImageReader reader = readers.next();

reader.setInput(in);

// It's possible to use reader.getNumImages(true) and a for-loop here.

// However, for many formats, it is more efficient to just read until there's no more images in the stream.

try {

int i = 0;

while (true) {

images.add(reader.read(i++));

}

}

catch (IndexOutOfBoundsException expected) {

// We're done

}

reader.dispose();

}

此行以下的任何内容都只是额外的信息.

这是使用ImageIO API编写多图像文件的方法(代码示例使用TIFF,但是它非常通用,并且理论上也应适用于其他格式,但压缩类型参数除外).

File file = ...; // May also use OutputStream/InputStream here

List images = new ArrayList<>(); // Just add images...

Iterator writers = ImageIO.getImageWritersByFormatName("TIFF");

if (!writers.hasNext()) {

throw new AssertionError("Missing plugin");

}

ImageWriter writer = writers.next();

if (!writer.canWriteSequence()) {

throw new AssertionError("Plugin doesn't support multi page file");

}

ImageWriteParam param = writer.getDefaultWriteParam();

param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);

param.setCompressionType("JPEG"); // The allowed compression types may vary from plugin to plugin

// The most common values for TIFF, are NONE, LZW, Deflate or Zip, or JPEG

try (ImageOutputStream out = ImageIO.createImageOutputStream(file)) {

writer.setOutput(out);

writer.prepareWriteSequence(null); // No stream metadata needed for TIFF

for (BufferedImage image : images) {

writer.writeToSequence(new IIOImage(image, null, null), param);

}

writer.endWriteSequence();

}

writer.dispose();

请注意,在Java 9之前,您还需要第三方TIFF插件(例如JAI或我自己的TwelveMonkeys ImageIO)才能使用ImageIO读取/写入TIFF.

如果您真的不喜欢编写此冗长的代码,另一种选择是将图像包装成您自己的最小容器格式,该格式至少(包括)每个图像的长度.然后,您可以使用ImageIO.write(…)进行写入,也可以使用ImageIO.read(…)进行读取,但是您需要围绕它实现一些简单的流逻辑.当然,反对它的主要论据是它将是完全专有的.

但是,如果您要在类似客户端/服务器的设置中异步读取/写入(就像我怀疑的那样,从我的问题来看),这可能是很合理的,并且可能是可以接受的折衷方案.

就像是:

File file = new File(args[0]);

List images = new ArrayList<>();

try (DataOutputStream out = new DataOutputStream(new FileOutputStream(file))) {

ByteArrayOutputStream buffer = new ByteArrayOutputStream(1024 * 1024); // Use larger buffer for large images

for (BufferedImage image : images) {

buffer.reset();

ImageIO.write(image, "JPEG", buffer); // Or PNG or any other format you like, really

out.writeInt(buffer.size());

buffer.writeTo(out);

out.flush();

}

out.writeInt(-1); // EOF marker (alternatively, catch EOFException while reading)

}

// And, reading back:

try (DataInputStream in = new DataInputStream(new FileInputStream(file))) {

int size;

while ((size = in.readInt()) != -1) {

byte[] buffer = new byte[size];

in.readFully(buffer); // May be more efficient to create a FilterInputStream that counts bytes read, with local EOF after size

images.add(ImageIO.read(new ByteArrayInputStream(buffer)));

}

}

PS:如果您要做的只是将收到的图像写入磁盘,则不应使用ImageIO.而是使用普通的I / O(假定来自上一个示例的格式):

try (DataInputStream in = new DataInputStream(new FileInputStream(file))) {

int counter = 0;

int size;

while ((size = in.readInt()) != -1) {

byte[] buffer = new byte[size];

in.readFully(buffer);

try (FileOutputStream out = new FileOutputStream(new File("pics/out/" + (counter++) +".jpeg"))) {

out.write(buffer);

out.flush();

}

}

}

java import imageio_是否可以使用Java ImageIO从InputStream读取多个...相关推荐

  1. ImageIO.read(inputStream)读取.webp格式图片报错

    0.码仙励志 莫妒他长,妒长,则己终是短.莫护己短,护短,则己终不长. 1.问题描述 今天测试提了一个新bug,查找原因是因为测试上传了一张.webp格式的图片. 在代码运行到 javax.image ...

  2. java import 出错,Eclipse的java代码出错:The import XXXX cannot be resolved

    折腾Eclipse时,经常会遇到这种情况: 缺少某个库,找到之后,需要将该库,jar包,加入到当前项目,使得代码中的import xxx得以正常导入. [如何在Eclipse中导入/添加(外部的)库/ ...

  3. java打印计算机_在Java程序中实现高精度打印

    在Java环境中,可以使用 java.awt.Toolkit.getScreenResolution()可以得到屏幕每英寸的象素数,但是好像没有什么方法能知道某一台打印机的分辨率,更别提去控制打印粒度 ...

  4. Java Import

    在 Java 中使用import关键字来导入任意类型到同一个编译单元中 在代码中,导入代码应放在包声明代码之后,类型声明代码之前 Java 中有两种类型的导入声明: 单类型导入(Single-type ...

  5. Java import 和 import static

    我们可以使用 import 语句来导入特定包的类和接口.每当我们使用 import 语句时,不需要使用完全限定名称,我们可以直接使用短名称.我们可以使用静态导入 来从一个特定的类和包导入静态成员.每当 ...

  6. java import自定义类_自定义类加载器-从.class和.jar中读取

    一. 类加载器 JVM中的类加载器:在jvm中,存在两种类加载器, a) Boostrap ClassLoader:这个是由c++实现的,所以在方法区并没有Class对象的实例存在.用于加载JAVA_ ...

  7. java import自定义类_Java实现的自定义类加载器示例

    本文实例讲述了Java实现的自定义类加载器.分享给大家供大家参考,具体如下: 一 点睛 1 ClassLoader类有如下两个关键方法: loadClass(String name, boolean ...

  8. import java文件,java 文件夹操作,java文件夹,import java.

    java 文件夹操作,java文件夹,import java.import java.io.File; import java.io.FileInputStream; import java.io.F ...

  9. Java import javax.servlet 出错

    Java import javax.servlet 出错 Error: The import javax.servlet cannot be resolved The import javax.ser ...

最新文章

  1. 经典图书《重构:改善既有代码的设计》图灵再版出版倒计时
  2. 在深度学习中处理不均衡数据集
  3. 三星手机Android9和10的区别,三星开始在Galaxy Note 9上测试Android 10
  4. java string.join找不到_Java String join()用法及代码示例
  5. 《软件需求最佳实践》阅读笔记01
  6. css before 文字前面竖线_前端进阶: css必知的几个底层知识和技巧
  7. kali2.0安装mysql,Ubuntu/kali上安装MySQL,设置远程访问详细教程
  8. JavaScript的函数声明与函数表达式的区别
  9. [文摘20071224]七条不可不知的生存法则
  10. Spring-web-HandlerMethodReturnValueHandler
  11. linux系统下载了qq怎么安装,怎么在linux系统里面安装QQ
  12. python 闭包和装饰器
  13. leetcode 链表1
  14. spring4+struts2+hibernate5整合出现spring异常
  15. bzoj1783: [Usaco2010 Jan]Taking Turns
  16. 中国计算机学会(CCF)推荐国际学术会议和期刊目录(2019年版,官网转载)
  17. 博图在线升级 gsd_增值税发票开票软件(金税盘版)升级开票指南
  18. PM42L-048 步进电机
  19. 第一讲 OC简介及基本语法
  20. Uboot pmic调试

热门文章

  1. 高德地图坐标查询工具——JavaScript
  2. Debian系安装rabbitmq
  3. 聚合型代码审计工具QingScan使用实践
  4. android 反编译 jadx,jadx gui下载 jadx(Android反编译gui工具) v0.6.1 官方版 下载-脚本之家...
  5. 一步步教你如何在线申请国内商标
  6. vue中双击事件选中文本、通过输入框实现双击输入文字
  7. Android版本9华为,华为应用市场旧版本下载-华为应用市场老版v9.0.0.303 安卓版 - 极光下载站...
  8. 深度对比Soul、觅伊,两款社交软件区别在哪?
  9. java 简单文件加密
  10. COLD:中文冒犯性语言检测数据集