Java 读写图像

转载自  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.html
2. 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 事件监听


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/328706.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

powerdesigner在工作时用到的方法

一、所有表中name同步comment的方法: 操作步骤:工具>execute commands>Edit/Run script Option Explicit ; 将下面脚本复制进去并执行 ValidationMode True InteractiveMode im_Batch Dim mdl the current modelget the current …

大数据项目实践:基于hadoop+spark+mongodb+mysql开发医院临床知识库系统

一、前言 从20世纪90年代数字化医院概念提出到至今的20多年时间,数字化医院(Digital Hospital)在国内各大医院飞速的普及推广发展,并取得骄人成绩。不但有数字化医院管理信息系统(HIS)、影像存档和通信系统(PACS)、电子…

两个对象集合根据对象的某个属性进行过滤,返回不同的部分

例如&#xff1a; plants 和houses 两个集合&#xff0c;进行对比过滤&#xff0c;取出plants里和houses不同的部分&#xff0c;并返回。 List<ImprovedSeedPlant> plants improvedSeedPlantMapper.selectList(spWrapper); List<StudsheepSheepHouse> houses h…

简历

技术岗&#xff01; 那么你应该写什么&#xff1f; 简单的介绍项目的规模&#xff0c;有多少技术人员&#xff0c;是互联网项目还是企业软件&#xff0c;这些就可以了。 接下来你需要写关于项目技术的那部分。 项目用了什么框架&#xff1f;spring 还是struts2 ,持久化是用的是…

java drawimage()方法

转载自 java drawimage()方法图像使用的支持分布于java.applet, java.awt, 和 java.awt.image包中。每一个图像都用一个 java.awt.Image 对象表示。除了Image 类外&#xff0c;java.awt 包提供了其它的基本的图像支持&#xff0c;例如Graphics 类的 drawImage方法&#xff0c;…

老师不能把你怎样,但外面的世界可以!

来源 | 菁优网 本文是一位老师讲述的三段小故事&#xff0c;告诉各位家长及孩子&#xff1a; 亲爱的孩子&#xff0c;老师是不能把你怎样&#xff0c;但外面的世界可以。 1. 我有一个学生&#xff0c;喜欢钻研奥数&#xff0c;却走路慢慢吞吞总爱迟到&#xff0c;同学给他起了…

TagHelper是怎么实现的

众所周知&#xff0c;在asp.net core中编写Razor视图的时候&#xff0c;用了一种新的写法--TagHelper 那这个TagHelper是怎么回事呢? 首先来看看TagHelper的项目位置&#xff0c;它是位于Microsoft.AspNetCore.Mvc.TagHelpers。 如果看到project.json&#xff0c;可以发现&…

java电商面试介绍

写博客 前两个项目采用的是ssh框架搭建的&#xff0c;最近的项目采用的是ssm框架搭建的。在实际开发中&#xff0c;我觉得这两个框架&#xff0c;他们最大的区别在于hibernate与mybatis的区别。 Hibernate与mybatis相比较&#xff0c;mybatis更为轻便、灵活&#xff0c;容易…

java 程序实现对图片的压缩生成缩略图并可设定长宽、尺寸压缩率、图片质量

转载自 java 程序实现对图片的压缩生成缩略图并可设定长宽、尺寸压缩率、图片质量 之前是在另一位高手的上传内容中学习到的&#xff0c;并将其代码根据我的需求进行了修改&#xff0c;参考位置&#xff1a;http://jiangpin1987.javaeye.com/blog/749690参考代码&#xff1a;…

List<Map<String,Object>>集合按照map中的某个值进行排序

List<Map<String,Object>>集合按照map中的某个值进行排序 举例&#xff1a; public void test5(){List<Map<String, Object>> list new ArrayList<Map<String, Object>>();Map<String, Object> map1 new HashMap<String, Obj…

面试

Java简历与面试 置顶2017年10月20日 10:04:29 阅读数&#xff1a;40142 Java就业指导 想要成为合格的Java程序员或工程师到底需要具备哪些专业技能&#xff0c;面试者在面试之前到底需要准备哪些东西呢&#xff1f;本文陈列的这些内容既可以作为个人简历中的内容&#xff0c…

全文搜索引擎 Elasticsearch 入门教程

转载自 全文搜索引擎 Elasticsearch 入门教程全文搜索属于最常见的需求&#xff0c;开源的 Elasticsearch &#xff08;以下简称 Elastic&#xff09;是目前全文搜索引擎的首选。 它可以快速地储存、搜索和分析海量数据。维基百科、Stack Overflow、Github 都采用它。Elastic…

写给实习生的第一天

实习生&#xff08;intern&#xff09;和新员工有所区别。实习生仿佛一个长达12周&#xff08;三个月&#xff09;的面试&#xff0c;一起工作&#xff0c;一起解决问题。在最后有答辩和debrief meeting讨论结果。可能通过了&#xff0c;最后公司给offer&#xff1b;也可能没有…

项目里远程调用POST/GET接口时使用的方法

一、远程调用post接口时的方法 方法一&#xff1a; 这个方式的querys传的是参数&#xff08;参数可是单个参数/对象&#xff09; host指的是远程调用的主机地址 headers指的是头信息&#xff08;可有可无&#xff09; body指的是字符集的编码格式 public static String doPo…

再讲IQueryablelt;Tgt;,揭开表达式树的神秘面纱

接上篇《先说IEnumerable&#xff0c;我们每天用的foreach你真的懂它吗&#xff1f;》 最近园子里定制自己的orm那是一个风生水起&#xff0c;感觉不整个自己的orm都不好意思继续混博客园了&#xff08;开个玩笑&#xff09;。那么在此之前我们有必要仔细了解下 IQueryable<…

Java进阶之路——从初级程序员到架构师,从小工到专家

转载自 Java进阶之路——从初级程序员到架构师&#xff0c;从小工到专家怎样学习才能从一名Java初级程序员成长为一名合格的架构师&#xff0c;或者说一名合格的架构师应该有怎样的技术知识体系&#xff0c;这是不仅一个刚刚踏入职场的初级程序员也是工作三五年之后开始迷茫…

堆排序原理及其实现(C++)

https://blog.csdn.net/lzuacm/article/details/52853194 堆排序原理及其实现(C) 1. 堆排序的引入 我们知道简单选择排序的时间复杂度为O(n^2)&#xff0c;熟悉各种排序算法的朋友都知道&#xff0c;这个时间复杂度是很大的&#xff0c;所以怎样减小简单选择排序的时间复杂度…

Redis集群~StackExchange.redis连接Twemproxy代理服务器

本文是Redis集群系列的一篇文章&#xff0c;主要介绍使用StackExchange.Redis进行Twemproxy&#xff08;文中简称TW&#xff09;代理服务的连接过程&#xff0c;事务上&#xff0c;对于&#xff34;&#xff37;来说&#xff0c;我们需要理解一下它的物理架构&#xff0c;它类似…

List集合转分页

当所要查询的数据不能通过框架自带的分页和自定义分页实现的时候&#xff0c;一般查询出来的数据大多数情况都是list的形式。这就牵扯到把list集合转成分页&#xff0c;实现分页操作。   以下就是list转page的工具 /*** list转page进行手动分页* param list 要转的list集合*…

内存转换Image到Icon

转载自 内存转换Image到Icon 时候我们需要在内存中转换Image格式到Icon 根据经验&#xff0c;通常我们应该可以这样做 Image image xxxx;///假设这里已经有一个Image对象 System.IO.MemoryStream mStream new System.IO.MemoryStream();///创建内存流 image.Save(mStream,…