网站开发转包协议,最好的网站设计,阿里云搭建个人博客wordpress,石家庄网站制作长沙转载自 Java 读写图像Java中进行图像I/O#xff08;即读图片和写图片#xff0c;不涉及到复杂图像处理#xff09;有三个方法#xff1a;1. Java Image I/O API#xff0c;支持常见图片#xff0c;从Java 2 version 1.4.0开始就内置了。主页#xff1a;http://java.sun…转载自 Java 读写图像Java中进行图像I/O即读图片和写图片不涉及到复杂图像处理有三个方法1. Java Image I/O API支持常见图片从Java 2 version 1.4.0开始就内置了。主页http://java.sun.com/javase/6/docs/technotes/guides/imageio/index.html2. JAI 中的 Image I/O Tools支持更多图片类型例如JPEG-LS, JPEG2000, 和 TIFF。主页https://jai-imageio.dev.java.net/。JAI 是一个关于图像处理的框架很庞大其中仅仅jai-imageio是关于图像I/O的其他的可以不看。3. JAI的com.sun.media.jai.codec 也有一定的图像解码能力
当然还有众多的java开源工具包可以读写图像例如JIMI, JMagic等但JDK目前本身能够读写图片就用JDK的开发和部署方便不需要额外下载jar包。
由于JAI是Java新加入的很多组件不是正式规范JDK不自带因此开发和部署需要额外安装安装文件在官网https://jai.dev.java.net/下载得到。
如果你仅仅想读取常见格式的图片不需要用JAI这么高级这么庞大的东西用Java Image I/O API即可。
下面重点介绍 Java Image I/O API。
Java Image I/O API 主要在 javax.imageio 下面。JDK已经内置了常见图片格式的插件但它提供了插件体系结构第三方也可以开发插件支持其他图片格式。
下面这段代码可以展示JDK内置支持的图片格式。
import javax.imageio.*;
import java.util.Arrays;public class HelloWorld {public static void main(String args[]) {String readFormats[] ImageIO.getReaderFormatNames();String writeFormats[] ImageIO.getWriterFormatNames();System.out.println(“Readers: ” Arrays.asList(readFormats));System.out.println(“Writers: ” Arrays.asList(writeFormats));}
}
主页上有一个文档Java Image I/O API Guide很通俗易懂可以让你快速上手。以下内容主要来自这个文档的第3章。
第3章 编写图像I/O程序3.1 读写图片javax.imageio.ImageIO类提供了一组静态方法进行最简单的图像I/O操作。读取一个标准格式(GIF, PNG, or JPEG)的图片很简单
File f new File(“c:\images\myimage.gif”);
BufferedImage bi ImageIO.read(f);
Java Image I/O API 会自动探测图片的格式并调用对应的插件进行解码当安装了一个新插件新的格式会被自动理解程序代码不需要改变。
写图片同样简单
BufferedImage bi;
File f new File(“c:\images\myimage.png”);
ImageIO.write(im, “png”, f);
3.2 更进一步上一节谈到的方法对于简单程序已经足够了。不过Java Image I/O API 提供了为编写复杂程序的能力。为了利用API的高级特性应用程序应当直接使用类ImageReader 和ImageWriter。
3.3 ImageReader 类与其用ImageIO类来进行所有的解码操作不如用ImageIO类去得到一个ImageReader对象再用这个对象去进行读操作
Iterator readers ImageIO.getImageReadersByFormatName(“gif”);
ImageReader reader (ImageReader)readers.next();
ImageReader对象也可以基于文件内容、文件后缀或MIME类型获得。这个用于查找和初始化ImageReader对象的机制用到了javax.imageio.spi.ImageReaderSpi类它可以在不用初始化插件的情况下获得插件的信息。”service provider interfaces” (SPIs)将会在下一章详细讨论。一旦获得了一个ImageReader对象必须给它是指一个输入源。大部分ImageReader对象可以从ImageInputStream类输入源读取数据ImageInputStream是ImageI/O API定义的专用输入源。
获得一个ImageInputStream 是简单的。给定一个File或InputStream一个ImageInputStream对象可以通过调用如下函数产生
Object source; // File or InputStream
ImageInputStream iis ImageIO.createImageInputStream(source);
一旦有了输入源可以把它与一个ImageReader对象关联起来reader.setInput(iis, true);
如果输入源文件包含多张图片而程序不保证按顺序读取时第二个参数应该设置为false。对于那些只允许存储一张图片的文件格式永远传递true是合理的。当ImageReader对象有了输入源后我们就可以获取图片信息而不用把整张图片数据都读入内存。例如调用reader.getImageWidth(0)可以让我们获得文件中第一张图片的宽度。一个好的插件会试图解码文件的必要部分去获得图片的宽度而不用读取任何一个像素。为读取图片可以调用reader.read(imageIndex), imageIndex是文件当包含多张图片时中图片的索引。这与上一节调用ImageIO.read()产生的结果相同。
3.3.1 ImageReadParam如果需要更多的控制可以向read()方法传递一个ImageReadParam类型的参数。一个ImageReadParam对象可以让程序更好的利用内存。它不仅允许指定一个感兴趣的区域还可以指定一个抽样因子用于向下采样。
例如为了只解码图片的左上角的1/4程序可以先获取一个合适的ImageReadParam对象
ImageReadParam param reader.getDefaultReadParam();
接下来指定图片区域
import java.awt.Rectangle;
int imageIndex 0;
int half_width reader.getImageWidth(imageIndex)/2;
int half_height reader.getImageHeight(imageIndex)/2;
Rectangle rect new Rectangle(0, 0, half_width, half_height);
param.setSourceRegion(rect);
最后读取图片
BufferedImage bi reader.read(imageIndex, param);
结果是一张新图片宽和高都只有原图片的一半。
另一个例子为了读取每三个像素中的一个产生一个原图片1/9大小的图片可以用ImageReadParam指定抽样因子
param reader.getDefaultImageParam();
param.setSourceSubsampling(3, 3, 0, 0);
BufferedImage bi3 reader.read(0, param);
3.3.2 IIOParamController插件有时会提供一个IIOParamController类这是可选的。略。
3.3.3 读多图片文件ImageReader 中所有与图片打交道的方法都有一个imageIndex 参数这个参数用于读取多图片文件中的一张。
ImageReader.getNumImages()返回多图片文件中的图片个数。这个方法有一个boolean参数allowSearch。有的图片格式典型的GIF没有提供任何获取文件中的图片个数方法除非读取整个进行解析。这样代价很高因此设置allowSearch为false可以让方法直接返回-1而不是实际的图片个数。如果此参数是true则该方法总会返回文件中实际的图片个数。
即使在不知道文件中图片个数的情况下仍可以调用read(imageIndex); 如果索引值过大该方法会抛出IndexOutOfBoundsException异常。因此程序可以递增索引去获取图片直到异常。
3.3.4 读缩略图 有的图片格式允许一个或多个小的预览图与主图片一起存储在文件中。这些“缩略图”对于快速识别图片很有用不用解码整个图片。
程序可以调用如下代码探测一张图片有多少张缩略图
reader.getNumThumbnails(imageIndex);
如果存在缩略图可以调用如下代码获取
int thumbailIndex 0;
BufferedImage bi;
bi reader.readThumbnail(imageIndex, thumbnailIndex);3.4 ImageWriter 类 就像我们可以用ImageIO 的一个方法获取某种图片格式的ImageReader对象一样我们也可以获取ImageWriter对象
Iterator writers ImageIO.getImageWritersByFormatName(“png”);
ImageWriter writer (ImageWriter)writers.next();
一旦获取了一个ImageWriter对象必须给它设置一个输出源ImageOutputStream。
File f new File(“c:\images\myimage.png”);
ImageOutputStream ios ImageIO.createImageOutputStream(f);
writer.setOutput(ios);
最后可以把图片写入到输出源
BufferedImage bi;
writer.write(bi);3.4.1 写多图片文件IIOImage类用于存储图片缩略图或元信息的引用。下一节将讨论Metadata目前我们简单地给Metadata相关参数传递null。ImageWriter 类有一个方法write()用于从IIOImage创建一个新文件还有一个方法writeInsert()用于向一个已存在文件添加一个IIOImage对象。通过调用这两者可以创建一个多图片文件
BufferedImage first_bi, second_bi;
IIOImage first_IIOImage new IIOImage(first_bi, null, null);
IIOImage second_IIOImage new IIOImage(second_bi, null, null);
writer.write(null, first_IIOImage, null);
if (writer.canInsertImage(1)) {
writer.writeInsert(1, second_IIOImage, null);
} else {
System.err.println(“Writer can’t append a second image!”);
}3.5 处理 Metadata 所有与像素无关的信息都属于在Metadata。javax.imageio.metadata 包含了用于访问Metadata的类和接口。
Image I/O API 将stream metadata 和image metadata区别对待。stream metadata与一个文件中存储了多张图片有关image metadata只与单个图片有关。如果一个文件只包含一张图片那么就只存在image metadata。可以通过调用ImageReader.getStreamMetadata 和 getImageMetadata(int imageIndex)来获取metadata。这些方法会返回一个实现了IIOMetadata接口的对象该对象会被向上转化为ImageReader类型
3.6 编码转换略
3.7 事件监听略