1.获取坐标,拆分图片
/**
* 裁剪,图片保存
*
* @return
*/
public InputStream cut(int x, int y, int width, int height, MultipartFile srcpath) throws IOException {
InputStream is = null;
//InputStream nis= null;
ImageInputStream iis = null;
InputStream input;
try {
// 读取图片文件
is = new BufferedInputStream(srcpath.getInputStream());
// 获取文件名
String filename = srcpath.getOriginalFilename();
// 获取文件名后缀
String suffix = filename.substring(filename.lastIndexOf(".") + 1, filename.length());
//将png类型图片转换为jpg类型
if("png".equals(suffix) || "PNG".equals(suffix)){
is=ConvertImageFile(is);
}
/*
* 返回包含所有当前已注册 ImageReader 的 Iterator,这些 ImageReader 声称能够解码指定格式。
* 参数:formatName - 包含非正式格式名称 .(例如 "jpeg" 或 "tiff")等 。
*/
Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName("jpg");
ImageIO.getReaderFormatNames();
ImageReader reader = it.next();
// 获取图片流
iis = ImageIO.createImageInputStream(is);
/*
* <p>iis:读取源.true:只向前搜索 </p>.将它标记为 ‘只向前搜索’。
* 此设置意味着包含在输入源中的图像将只按顺序读取,可能允许 reader 避免缓存包含与以前已经读取的图像关联的数据的那些输入部分。
*/
reader.setInput(iis, true);
/*
* <p>描述如何对流进行解码的类<p>.用于指定如何在输入时从 Java Image I/O
* 框架的上下文中的流转换一幅图像或一组图像。用于特定图像格式的插件 将从其 ImageReader 实现的
* getDefaultReadParam 方法中返回 ImageReadParam 的实例。
*/
ImageReadParam param = reader.getDefaultReadParam();
/*
* 图片裁剪区域。Rectangle 指定了坐标空间中的一个区域,通过 Rectangle 对象
* 的左上顶点的坐标(x,y)、宽度和高度可以定义这个区域。
*/
Rectangle rect = new Rectangle(x, y, width, height);
// 提供一个 BufferedImage,将其用作解码像素数据的目标。
param.setSourceRegion(rect);
/*
* 使用所提供的 ImageReadParam 读取通过索引 imageIndex 指定的对象,并将 它作为一个完整的
* BufferedImage 返回。
*/
BufferedImage bi = reader.read(0, param);
// 保存新图片
// ImageIO.write(bi, "jpg", new File(subpath));
// 输出拆分图片文件流
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(bi, suffix, os);
input = new ByteArrayInputStream(os.toByteArray());
return input;
} finally {
if (is != null)
is.close();
if (iis != null)
iis.close();
}
}
2.图片类型转换(png转jpg)
private InputStream ConvertImageFile(InputStream file) throws IOException {
InputStream input = null;
BufferedImage bufferedImage;
try {
// read image file
bufferedImage = ImageIO.read(file);
// create a blank, RGB, same width and height, and a white
// background
BufferedImage newBufferedImage = new BufferedImage(bufferedImage.getWidth(), bufferedImage.getHeight(),
BufferedImage.TYPE_INT_RGB);
// TYPE_INT_RGB:创建一个RBG图像,24位深度,成功将32位图转化成24位
newBufferedImage.createGraphics().drawImage(bufferedImage, 0, 0, null);
// write to jpeg file
// ImageIO.write(newBufferedImage, "jpg", new File("c:\\java.jpg"));
//
// System.out.println("Done");
// 输出拆分图片文件流
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(newBufferedImage,"jpg",os);
input = new ByteArrayInputStream(os.toByteArray());
} catch (IOException e) {
e.printStackTrace();
}finally{
if (input != null)
input.close();
}
return input;
}
3.测试jpg类型图片剪切
public static void main(String[] args) {
//Test operateImage = new Test(7, 160, 1033, 708);
//Test operateImage = new Test(80, 339, 897, 535);
Test operateImage = new Test(41, 1269, 772, 1027);
//Test operateImage = new Test(46, 655, 946, 641);
//Test operateImage = new Test(41, 497, 1027, 772);
//Test operateImage = new Test(46, 634, 960, 661);
operateImage.srcpath = "D:/test/dc.jpg";
operateImage.subpath = "D:/test/dc1.jpg";
//operateImage.subpath = "D:/test/dc2.jpg";
try {
operateImage.cut();
System.out.println("拆分完成!");
} catch (IOException e) {
e.printStackTrace();
}
}
4.结果展示
原图片
拆分后图片1:
拆分后图片2:
5.注意点
亲身体验的一个坑,或许是自己理解没到位,就是在ImageIO.getImageReadersByFormatName(“jpg”) 获取图片读取器时错误的将类型设置为文件名后缀,导致测试中拆分png类型图片时报I/O error reading PNG header!异常,后面想了半天才发现自己先将png类型的图片转换为jpg类型,而文件又是png类型的,获取的ImageReader也是png类型,所以才导致这个错误的发生,望各位码友借鉴时注意!
参考代码:https://blog.csdn.net/nooneyanghuijava/article/details/8147350?locationNum=6&fps=1