首先放上最初的Image工具类

package util;

import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.util.Iterator; import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream; public class ImageUtil { private ImageUtil() {
} /**
* 裁剪图像
*
* @param x,y 起始点
* @param width,height 宽高
* @param srcpath 被裁减图像路径
* @param subpath 裁剪后保存路径
* @param type 图像类型
* @throws Exception
*/
public static void cut(int x, int y, int width, int height, String srcpath,
String subpath, String type) throws Exception {
FileInputStream is = null;
ImageInputStream iis = null;
try {
// 读取图片文件
is = new FileInputStream(srcpath);
Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName(type);
ImageReader reader = it.next();
// 获取图片流
iis = ImageIO.createImageInputStream(is);
reader.setInput(iis, true);
ImageReadParam param = reader.getDefaultReadParam();
Rectangle rect = new Rectangle(x, y, width, height);
// 提供一个 BufferedImage,将其用作解码像素数据的目标。
param.setSourceRegion(rect);
BufferedImage bi = reader.read(0, param);
ImageIO.write(bi, type, new File(subpath));
} finally {
if (is != null)
is.close();
if (iis != null)
iis.close();
}
} /**
* 获取图像真实类型
*
* @param path 图像路径
* @return 图像类型
* @throws Exception
*/
public static String getTypeByStream(String path) throws Exception {
FileInputStream is = new FileInputStream(path);
String type = "";
byte[] b = new byte[4];
try {
is.read(b, 0, b.length);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != is) {
is.close();
}
}
type = bytesToHexString(b).toUpperCase();
if (type.contains("FFD8FF")) {
return "jpg";
} else if (type.contains("89504E47")) {
return "png";
} else if (type.contains("47494638")) {
return "gif";
} else if (type.contains("49492A00")) {
return "tif";
} else if (type.contains("424D")) {
return "bmp";
}
return type;
} /**
* byte数组转换成16进制字符串
*
* @param src
* @return
*/
private static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder();
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
} }

ImageUtil-origin

以前使用ImageReader对jpg图像进行裁剪没有任何异常,这几天接到新的需求,要能对tif图像进行裁剪。原以为只需将传入的type值改为tif即可,但报出了NoSuchElementException异常

java.util.NoSuchElementException
at javax.imageio.spi.FilterIterator.next(ServiceRegistry.java:825)
at javax.imageio.ImageIO$ImageReaderIterator.next(ImageIO.java:528)
at javax.imageio.ImageIO$ImageReaderIterator.next(ImageIO.java:513)

网上查了半天,各种说法都有,最终找到了问题所在:

在jdk下的src中可以看到jdk自带支持的imageio类型——bmp、gif、jpeg(jpg)、png等,就 是 没 有 tif !!!

所以就有了解决的方向——导入tif的imageio,需要的jar包有3个jai_codec、jai_core、jai_imageio

导入3个jar包后,对工具类进行测试,发现不报异常了,图像也正确切割了

原本到此应该就已经结束了,但是。。。

放到web项目中又报出了NoSuchElementException的异常

于是又是一顿搜索和实验,终于找到了正解——要在迭代器中注册tif的imageio类

IIORegistry registry = IIORegistry.getDefaultInstance();
registry.registerServiceProvider(new com.sun.media.imageioimpl.plugins.tiff.TIFFImageWriterSpi());
registry.registerServiceProvider(new com.sun.media.imageioimpl.plugins.tiff.TIFFImageReaderSpi());

加上这段代码后,在web中终于不会报异常了

所以最后的图片工具类就变成了这样

import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.util.Iterator; import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.spi.IIORegistry;
import javax.imageio.stream.ImageInputStream; public class ImageUtil { private ImageUtil() {
} static {
IIORegistry registry = IIORegistry.getDefaultInstance();
registry.registerServiceProvider(new com.sun.media.imageioimpl.plugins.tiff.TIFFImageWriterSpi());
registry.registerServiceProvider(new com.sun.media.imageioimpl.plugins.tiff.TIFFImageReaderSpi());
} /**
* 裁剪图像
*
* @param x,y 起始点
* @param width,height 宽高
* @param srcpath 被裁减图像路径
* @param subpath 裁剪后保存路径
* @param type 图像类型
* @throws Exception
*/
public static void cut(int x, int y, int width, int height, String srcpath,
String subpath, String type) throws Exception {
FileInputStream is = null;
ImageInputStream iis = null;
try {
// 读取图片文件
is = new FileInputStream(srcpath);
Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName(type);
ImageReader reader = it.next();
// 获取图片流
iis = ImageIO.createImageInputStream(is);
reader.setInput(iis, true);
ImageReadParam param = reader.getDefaultReadParam();
Rectangle rect = new Rectangle(x, y, width, height);
// 提供一个 BufferedImage,将其用作解码像素数据的目标。
param.setSourceRegion(rect);
BufferedImage bi = reader.read(0, param);
ImageIO.write(bi, type, new File(subpath));
} finally {
if (is != null)
is.close();
if (iis != null)
iis.close();
}
} /**
* 获取图像真实类型
*
* @param path 图像路径
* @return 图像类型
* @throws Exception
*/
public static String getTypeByStream(String path) throws Exception {
FileInputStream is = new FileInputStream(path);
String type = "";
byte[] b = new byte[4];
try {
is.read(b, 0, b.length);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != is) {
is.close();
}
}
type = bytesToHexString(b).toUpperCase();
if (type.contains("FFD8FF")) {
return "jpg";
} else if (type.contains("89504E47")) {
return "png";
} else if (type.contains("47494638")) {
return "gif";
} else if (type.contains("49492A00")) {
return "tif";
} else if (type.contains("424D")) {
return "bmp";
}
return type;
} /**
* byte数组转换成16进制字符串
*
* @param src
* @return
*/
private static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder();
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
} }

ImageUtil

和初始的工具类相比没什么太多的变动。。。

最后是3个包的下载地址 https://gitee.com/shizuru/ImageUtil/tree/master

通过ImageReader进行图像裁剪时出现NoSuchElementException异常的更多相关文章

  1. Java 使用Scanner时的NoSuchElementException异常

    做实验时设计了一个类,在类中的两个不同函数中分别创建了两个Scanner对象,并且在各个函数的结尾使用了close()方法,结果在运行时产生了NoSuchElementException异常. 实验的 ...

  2. 【开源】canvas图像裁剪、压缩、旋转

    前言 前段时间遇到了一个移动端对图像进行裁剪.压缩.旋转的需求. 考虑到已有各轮子的契合度都不高,于是自己重新造了一个轮子. 关于图像裁剪.压缩 在HTML5时代,canvas的功能已经非常强大了,可 ...

  3. canvas图像裁剪、压缩、旋转

    转载于:http://www.cnblogs.com/dailc/p/7843204.html 前言 前段时间遇到了一个移动端对图像进行裁剪.压缩.旋转的需求.考虑到已有各轮子的契合度都不高,于是自己 ...

  4. STM32内存受限情况下摄像头驱动方式与图像裁剪的选择

    1.STM32图像接收接口 使用stm32芯片,128kB RAM,512kB Rom,资源有限,接摄像头采集图像,这种情况下,内存利用制约程序设计. STM32使用DCMI接口读取摄像头,协议如下. ...

  5. PHP图像裁剪为任意大小的图像,图像不变形,不留下空白

    <?php /** * 说明:函数功能是把一个图像裁剪为任意大小的图像,图像不变形 * 参数说明:输入 需要处理图片的 文件名,生成新图片的保存文件名,生成新图片的宽,生成新图片的高 */ fu ...

  6. jQuery的图像裁剪插件Jcrop

    1.最基本使用方法     html代码部分: <img src="demo_files/flowers.gif" id="demoImage"/> ...

  7. HTML canvas图像裁剪

    canvas drawImage方法的图像裁剪理解可能会比较耗时,记录一下,以便供人翻阅! context.drawImage(img,sx,sy,swidth,sheight,x,y,width,h ...

  8. php 图像裁剪(自定义裁剪图片大小)

    <?php /** * 图像裁剪 * @param $title string 原图路径 * @param $content string 需要裁剪的宽 * @param $encode str ...

  9. jQuery Jcrop 图像裁剪

    jQuery Jcrop 图像裁剪 http://code.ciaoca.com/jquery/jcrop/ cropper.js 实现HTML5 裁剪图片并上传(裁剪上传头像.) https://b ...

随机推荐

  1. javascript--特权方法

    在Javascript--闭包一节中我们讲解了闭包的作用域和作用域链的特性.了解到在外部一般是不可能访问到内部作用域中的变量的,然而通过闭包我们可以定义特权方法访问私有变量.下面先介绍块级作用域再介绍 ...

  2. Redis 的几种常见使用方式

    常见使用方式 Redis 的几种常见使用方式包括: Redis 单副本 Redis 多副本(主从) Redis Sentinel(哨兵) Redis Cluster Redis 自研 各种使用方式的优 ...

  3. C#程序调用CMD执行命令,将参数传递给cmd.exe

    proc.StartInfo.Arguments = "/c ping 10.2.2.125"; C#程序调用CMD执行命令 将参数传递给cmd.exe的(Passing an a ...

  4. C++公有继承,私有继承和保护继承的区别

    昨天学习三种继承方式,有些比喻十分形象,特此分享. 首先说明几个术语: 1.基类 基类比起它的继承类是个更加抽象的概念,所描述的范围更大.所以可以看到有些抽象类,他们设计出来就是作为基类所存在的(有些 ...

  5. php mvc 模式的开发注意事项

    1.控制器中: 如果不涉及到数据库的就在控制器中. empty($res['code']) ? $this->error($res['msg']) : $this->success($re ...

  6. django 后台静态文件不显示

    原文链接 https://my.oschina.net/VASKS/blog/874270 django admin svg 不显示.后台显示 xx.svg 200 但浏览器就是不显示. 百度了一圈, ...

  7. MongoDB(mongodb-win32-x86_64-enterprise-windows-64-4.2.1-signed.msi)下载,启动和插入数据,查询

    下载链接:https://pan.baidu.com/s/19lM5Q-_BaDbjaO1Pj0SbYg&shfl=sharepset 安装一路Next就行,安装完毕后,进入目录C:\Prog ...

  8. Web Service 实例基于Socket创建Web服务

    ServerSocket服务器端代码如下: public static void main(String[] args) throws IOException { // 1:建立服务器端的tcp so ...

  9. 阶段5 3.微服务项目【学成在线】_day03 CMS页面管理开发_04-新增页面-服务端-接口开发

    api接口定义方法 api的微服务里面.CmsPageControllerApi内定义add方法,返回类型是CmsPageResult CmsPageResult继承了ResponseResult R ...

  10. 用VLC读取摄像头产生RTSP流,DSS主动取流转发(一)

    用VLC读取摄像头产生RTSP流,DSS主动取流转发(一) 摄像机地址是192.1.101.51,VLC运行在192.1.101.77上,DSS服务器架设在192.1.101.30上. Step1:V ...