Java使用BufferedImage裁剪图片

巩俊远
2023-12-01

一、需求

工作中需要将一张前端传过来的图片按照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裁剪图片

 类似资料: