java 截取img_Atitit 图像截取裁剪与java img api 艾提拉总结 目录 1.1. 3.3 ImageReader 类1 1.2. 3.3.1 ImageReadParam2 1...

Atitit图像截取裁剪与java img api 艾提拉总结

目录

与其用ImageIO类来进行所有的解码操作,不如用ImageIO类去得到一个ImageReader对象, 再用这个对象去进行读操作:

[if !supportLists]00001. [endif]

Iterator readers = ImageIO.getImageReadersByFormatName(“gif”);

[if !supportLists]00002. [endif]

[if !supportLists]00003. [endif]

ImageReader reader = (ImageReader)readers.next();

[if !supportLists]00004. [endif]

ImageReader对象也可以基于文件内容、文件后缀或MIME类型获得。这个用于查找和初始 化ImageReader对象的机制用到了javax.imageio.spi.ImageReaderSpi类,它可以在不用初 始化插件的情况下获得插件的信息。”service provider interfaces” (SPIs)将会在下一 章详细讨论。一旦获得了一个ImageReader对象,必须给它是指一个输入源。大部分 ImageReader对象可以从ImageInputStream类输入源读取数据,ImageInputStream是Image I/O API定义的专用输入源。获得一个ImageInputStream 是简单的。给定一个File或InputStream,一个 ImageInputStream对象可以通过调用如下函数产生:

[if !supportLists]00001. [endif]

Object source; // File or InputStream

[if !supportLists]00002. [endif]

[if !supportLists]00003. [endif]

ImageInputStream iis = ImageIO.createImageInputStream(source);

[if !supportLists]00004. [endif]

一旦有了输入源,可以把它与一个ImageReader对象关联起来:

reader.setInput(iis, true);

如果输入源文件包含多张图片,而程序不保证按顺序读取时,第二个参数应该设置为false。对于那些只允许存储一张图片的文件格式,永远传递true是合理的。 当ImageReader对象有了输入源后,我们就可以获取图片信息而不用把整张图片数据都读入 内存。例如,调用reader.getImageWidth(0)可以让我们获得文件中第一张图片的宽度。一 个好的插件会试图解码文件的必要部分,去获得图片的宽度,而不用读取任何一个像素。为读取图片,可以调用reader.read(imageIndex), imageIndex是文件(当包含多张图片时) 中图片的索引。这与上一节调用ImageIO.read()产生的结果相同。

BufferedImage bi = reader.read(imageIndex, param);

如果需要更多的控制,可以向read()方法传递一个ImageReadParam类型的参数。一个 ImageReadParam对象可以让程序更好的利用内存。它不仅允许指定一个感兴趣的区域,还 可以指定一个抽样因子,用于向下采样。例如,为了只解码图片的左上角的1/4,程序可以先获取一个合适的ImageReadParam对象:

另一个例子,为了读取每三个像素中的一个,产生一个原图片1/9大小的图片,可以用 ImageReadParam指定抽样因子:

[if !supportLists]00001. [endif]

param = reader.getDefaultImageParam();

[if !supportLists]00002. [endif]

[if !supportLists]00003. [endif]

param.setSourceSubsampling(3, 3, 0, 0);

[if !supportLists]00004. [endif]

[if !supportLists]00005. [endif]

BufferedImage bi3 = reader.read(0, param);

[if !supportLists]00006. [endif]

ImageReader 中所有与图片打交道的方法都有一个imageIndex 参数,这个参数用于读取多 图片文件中的一张。ImageReader.getNumImages()返回多图片文件中的图片个数。这个方法有一个boolean参数, allowSearch。有的图片格式,典型的GIF,没有提供任何获取文件中的图片个数方法,除 非读取整个进行解析。这样代价很高,因此设置allowSearch为false可以让方法直接返回 -1,而不是实际的图片个数。如果此参数是true,则该方法总会返回文件中实际的图片个 数。即使在不知道文件中图片个数的情况下,仍可以调用read(imageIndex); 如果索引值过大, 该方法会抛出IndexOutOfBoundsException异常。因此,程序可以递增索引去获取图片, 直到异常。

有的图片格式允许一个(或多个)小的预览图,与主图片一起存储在文件中。这些“缩略图”对于快速识别图片很有用,不用解码整个图片。程序可以调用如下代码,探测一张图片有多少张缩略图:reader.getNumThumbnails(imageIndex);如果存在缩略图,可以调用如下代码获取:

[if !supportLists]00001. [endif]

int thumbailIndex = 0;

[if !supportLists]00002. [endif]

[if !supportLists]00003. [endif]

BufferedImage bi;

[if !supportLists]00004. [endif]

[if !supportLists]00005. [endif]

bi = reader.readThumbnail(imageIndex, thumbnailIndex);

[if !supportLists]00006. [endif]

[if !supportLists]00007. [endif]

[if !supportLists]00008. [endif]

就像我们可以用ImageIO 的一个方法获取某种图片格式的ImageReader对象一样,我们也可 以获取ImageWriter对象:

[if !supportLists]00001. [endif]

Iterator writers = ImageIO.getImageWritersByFormatName(“png”);

[if !supportLists]00002. [endif]

[if !supportLists]00003. [endif]

ImageWriter writer = (ImageWriter)writers.next();

[if !supportLists]00004. [endif]

一旦获取了一个ImageWriter对象,必须给它设置一个输出源ImageOutputStream。

[if !supportLists]00001. [endif]

File f = new File(“c:imagesmyimage.png”);

[if !supportLists]00002. [endif]

[if !supportLists]00003. [endif]

ImageOutputStream ios = ImageIO.createImageOutputStream(f);

[if !supportLists]00004. [endif]

[if !supportLists]00005. [endif]

writer.setOutput(ios);

[if !supportLists]00006. [endif]

最后,可以把图片写入到输出源:

[if !supportLists]00001. [endif]

BufferedImage bi;

[if !supportLists]00002. [endif]

[if !supportLists]00003. [endif]

writer.write(bi)

[if !supportLists]00004. [endif]

IIOImage类用于存储图片,缩略图或元信息的引用。下一节将讨论Metadata,目前,我们 简单地给Metadata相关参数传递null。 ImageWriter 类有一个方法write(),用于从IIOImage创建一个新文件,还有一个方法 writeInsert(),用于向一个已存在文件添加一个IIOImage对象。通过调用这两者,可以创 建一个多图片文件:

[if !supportLists]00001. [endif]

BufferedImage first_bi, second_bi;

[if !supportLists]00002. [endif]

[if !supportLists]00003. [endif]

IIOImage first_IIOImage = new IIOImage(first_bi, null, null);

[if !supportLists]00004. [endif]

[if !supportLists]00005. [endif]

IIOImage second_IIOImage = new IIOImage(second_bi, null, null);

[if !supportLists]00006. [endif]

[if !supportLists]00007. [endif]

writer.write(null, first_IIOImage, null);

[if !supportLists]00008. [endif]

[if !supportLists]00009. [endif]

if (writer.canInsertImage(1)) {

[if !supportLists]00010. [endif]

[if !supportLists]00011. [endif]

writer.writeInsert(1, second_IIOImage, null);

[if !supportLists]00012. [endif]

[if !supportLists]00013. [endif]

} else {

[if !supportLists]00014. [endif]

[if !supportLists]00015. [endif]

System.err.println(“Writer can’t append a second image!”);

[if !supportLists]00016. [endif]

[if !supportLists]00017. [endif]

}

[if !supportLists]00018. [endif]

所有与像素无关的信息,都属于在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类型,

[if !supportLists]4. [endif]Code

D:\workspace\wechatTelbookOcrVcf

public class imgUtil {

public static void main(String[] args) throws FileNotFoundException, IOException {

String srcimg = "D:\\bawei\\Screenshot_2019-05-09-18-57-58-500_com.tencent.mm.png";

//385 287,93 27

Rectangle rect = new Rectangle(282, 258, 430, 36);

//rect = new Rectangle(100, 100, 100, 36);

String dest = "D:\\0img\\Screenshot_2019-05-09-18-57-58-500_com.tencent.mm.cut.png";

BufferedImage bi =imgUtil.cutImg( srcimg, rect,"png");

ImageIO.write(bi, "png", new FileOutputStream(dest));

System.out.println("--");

}

public static BufferedImage cutImg(String srcimg, Rectangle rect, String imgFmt)

throws FileNotFoundException, IOException {

return cutImg(ImageIO.read(new FileInputStream(srcimg)), rect, imgFmt);

}

static org.apache.log4j.Logger logger = Logger.getLogger(imgUtil.class);

public static BufferedImage cutImg(BufferedImage img, Rectangle rect, String suffix) throws IOException {

logger.info(img.getWidth()+":"+img.getHeight());

//for debug ,show witdh height.. IllegalArgumentException: Empty region!

// 根据图片类型获取该种类型的ImageReader

/**

* reader.setInput(iis, true); 如果输入源文件包含多张图片,而程序不保证按顺序读取时,第二个参数应该设置为

* false。对于那些只允许存储一张图片的文件格式,永远传递true是合理的。

* 当ImageReader对象有了输入源后,我们就可以获取图片信息而不用把整张图片数据都读入

* 内存。例如,调用reader.getImageWidth(0)可以让我们获得文件中第一张图片的宽度。一

* 个好的插件会试图解码文件的必要部分,去获得图片的宽度,而不用读取任何一个像素。

*/

ImageReader ImageReader1 = ImageIO.getImageReadersBySuffix(suffix).next();

ImageReader1.setInput(

ImageIO.createImageInputStream(new ByteArrayInputStream(bufferedImageToByteArray(img, suffix))), true);

ImageReadParam imageReadParam = new Supplier() {

@Override

public ImageReadParam get() {

ImageReadParam ImageReadParam1 = ImageReader1.getDefaultReadParam();

ImageReadParam1.setSourceRegion(rect);

return ImageReadParam1;

}

}.get();

//为读取图片,可以调用reader.read(imageIndex), imageIndex是文件(当包含多张图片时) 中图片的索引

BufferedImage bi = ImageReader1.read(0, imageReadParam);

return bi;

// return cutImg(rect, ImageReader1, ImageReadParam1);

}

private static byte[] bufferedImageToByteArray(BufferedImage img, String suffix) throws IOException {

ByteArrayOutputStream out = new ByteArrayOutputStream();

boolean flag = ImageIO.write(img, suffix, out);

byte[] b = out.toByteArray();

return b;

}

private static BufferedImage rectx(String srcimg, Rectangle rect) throws Exception {

// 图片输入流

ImageInputStream iis = ImageIO.createImageInputStream(srcimg);

// 图片读取器

Iterator it = ImageIO.getImageReaders(iis);

if (it.hasNext()) {

ImageReader r = it.next();

// 设置输入流

r.setInput(iis, true);

System.out.println("格式=" + r.getFormatName());

System.out.println("宽=" + r.getWidth(0));

System.out.println("高=" + r.getHeight(0));

// 读取参数

ImageReadParam param = r.getDefaultReadParam();

// 创建要截取的矩形范围

// Rectangle rect = new Rectangle(100, 100, 400, 200);

// 设置截取范围参数

param.setSourceRegion(rect);

// 读取截图数据

BufferedImage bi = r.read(0, param);

// 保存图片

// ImageIO.write(bi, "jpg", t);

return bi;

}

return null;

}

}

(2条消息)Java使用imageio 读写图像 - Code-Create-World - CSDN博客.html

>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值