工作中需要将一张前端传过来的图片按照16:9的比例裁剪
1、通过ImageIO工具类读取网络、本地、或内存中的图片, 返回一个BufferedImage对象实例
BufferedImage类是Image抽象类的实现类,作用是将一个图片加载到内存中,它会在内存中有个图像缓冲区,利用缓冲区对图像做操作。
BufferedImage bufImage = ImageIO.read(InputStream input);
2、使用BufferedImage的相关API操作图片
int width = src.getWidth();//获得宽度
int height = src.getHeight();//获得高度
/**
* 裁剪图片, 参数说明:
* x: 裁剪起点横坐标
* y: 裁剪起点纵坐标
* w: 需要裁剪的宽度
* h: 需要裁剪的高度
*/
BufferedImage getSubimage (int x, int y, int w, int h);
3、操作后的图片保存
ByteArrayOutputStream os = new ByteArrayOutputStream();
//保存图片
/**
* 保存 bufImage, 参数说明:
* im: bufImage 本身, BufferedImage 实现了 RenderedImage 接口
* formatName: 保存的图片格式
* output: 结果输出位置
*/
ImageIO.write(src, name.substring(name.lastIndexOf(".") + 1), os);
os.close();
return new ByteArrayInputStream(os.toByteArray());
4、上传裁剪后的图片到oss
//裁剪人脸图片
public static InputStream cutPicture(InputStream inputStream, String name) {
ByteArrayOutputStream os = null;
BufferedImage src=null;
try {
int w, h = 0;
log.info("*****************************读取");
src = ImageIO.read(inputStream);
ImageIO.setUseCache(false);
int width = src.getWidth();
int height = src.getHeight();
log.info("***********width:{},height:{}",width,height);
float fw = (float) width;
float fh = (float) height;
float number = fw / fh;
if (number != (16.0 / 9.0)) {
if (number > (16.0 / 9)) {
w = height * 16 / 9;
h = height;
} else {
w = width;
h = width * 9 / 16;
}
src = src.getSubimage((width - w) / 2, (height - h) / 2, w, h);
}
os = new ByteArrayOutputStream();
//保存图片
boolean write = ImageIO.write(src, name.substring(name.lastIndexOf(".") + 1), os);
ImageIO.setUseCache(false);
//关闭图片对象资源
src.getGraphics().dispose();
if (write){
byte[] bytes = os.toByteArray();
return new ByteArrayInputStream(bytes);
} else {
throw new PlatformException("裁剪失败!");
}
} catch (IOException e) {
log.error("操作图片出错:" + e.getMessage());
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
if (os != null) {
os.close();
}
if(src!=null){
src.getGraphics().dispose();
}
} catch (IOException e) {
log.error("关闭流失败",e);
}
}
return null;
}
注意:使用BufferedImage操作图片需要将图片加载到内存中,如果图片过大或者多个线程来请求,很容易发生内存溢出的问题。可以使用ImageMaigck+Im4java来裁剪。可以参考博主另一篇:ImageMagick+Im4Java裁剪图片