JAVA 通过 BufferedImage 进行图片的绘制,缩放,裁剪,水印等操作

本贴最后更新于 1726 天前,其中的信息可能已经事过境迁

最近开发当中,通过 JAVA 对图片进行了很多的操作,之前很少接触这方面的知识,特此记录下来

读取图片

//读取图片  通过JAVA自带的ImageIO里面的read方法
BufferedImage bufImage = ImageIO.read(File input);
BufferedImage bufImage = ImageIO.read(URL input);
BufferedImage bufImage = ImageIO.read(InputStream input);
BufferedImage bufImage = ImageIO.read(ImageInputStream input)

保存图片

/**
 *  image:RenderedImage 接口的实现类, BufferedImage 实现了 RenderedImage 接口
 *  formatName: 保存的图片格式的名称
 *  output: 结果输出位置
 */
ImageIO.write(RenderedImage image, String formatName, File output);
ImageIO.write(RenderedImage image, String formatName, OutputStream output);

绘制图片

/**
 * 创建一个指定宽高的图片内存对象
 * width : 宽度
 * height : 高度
 * imageType : 图片类型   参数为BufferedImage 自身定义的常量   
 *	TYPE_3BYTE_BGR :代表8位RGB分量图像
        TYPE_INT_ARGB :代表8位RGBA颜色组件包装成整数像素的图像
	......
 */
BufferedImage image = new BufferedImage(width, height, imageType);
//获取图片的画布
Graphics2D graphics = image.createGraphics();

//然后使用 Graphics 类在图片上绘制线段、矩形、图片、文本,设置背景颜色等等操作

// 设置画布颜色
void setColor(Color c)
// 设置字体颜色
void setFont(Font font)
// 设置线的宽度
setStroke(Stroke s)
// 设置背景颜色
void setBackground(Color c)
// 擦除某一区域(擦除后显示背景色)
void clearRect(int x, int y, int width, int height)
// 回收 Graphics 释放资源   操作完毕后一定要释放资源
void dispose()

// 绘制一条线段(如果两点为同一点,则绘制点)  
void  drawLine(int x1,  int y1,  int x2,  int y2)
// 绘制一个矩形(空心)  
void  drawRect(int x,  int y,  int width,  int height) 
// 绘制一个椭圆(空心) 
void  drawOval(int x,  int y,  int width,  int height)
// 绘制一个圆弧(弧线) 
void  drawArc(int x,  int y,  int width,  int height,  int startAngle,  int arcAngle)
// 绘制一张图片 ImageObserver:接收有关 Image 信息通知的异步更新接口,没用到直接传空
boolean  drawImage(Image image,  int x,  int y, ImageObserver observer)
// 绘制一段文本
void  drawString(String str,  int x,  int y)
...........................

缩放图片

/**
 *@param   width: 缩放后的宽度
 *@param   height: 缩放后的高度
 *@param   hints:  图像重采样算法的类型
 *
 *  hints 参数取值为以下之一(Image 类中的常量):
 *     SCALE_AREA_AVERAGING: 使用 Area Averaging 图像缩放算法;
 *     SCALE_DEFAULT: 使用默认的图像缩放算法;
 *     SCALE_SMOOTH: 选择图像平滑度比缩放速度具有更高优先级的图像缩放算法。
 *     ......
 */
Image getScaledInstance(int width, int height, int hints);

缩放的使用实例代码:

  /**
     * JAVA 图像等比缩放
     * @param srcImageFile  缩放的图片
     * @param destImageFile  缩放后的图片
     * @param scale  缩放比例
     * @return
     */
    public static boolean scale(File srcImageFile, File destImageFile,float scale){
        try {
            //使用ImageIO的read方法读取图片
            BufferedImage read = ImageIO.read(srcImageFile);
            //获取缩放后的宽高
            int width = (int) (read.getWidth()*scale);
            int height = (int) (read.getHeight()*scale);
            //调用缩放方法获取缩放后的图片
            Image img = read.getScaledInstance(width , height, Image.SCALE_DEFAULT);
            //创建一个新的缓存图片
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            //获取画笔
            Graphics2D graphics = image.createGraphics();
            //将Image对象画在画布上,最后一个参数,ImageObserver:接收有关 Image 信息通知的异步更新接口,没用到直接传空
            graphics.drawImage(img, 0, 0,null);
            //一定要释放资源
            graphics.dispose();
            //获取到文件的后缀名
            String fileName = srcImageFile.getName();
            String formatName = fileName.substring(fileName.lastIndexOf(".") + 1);
            //使用ImageIO的write方法进行输出
            ImageIO.write(image,formatName,destImageFile);
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

裁剪图片

/**
* 
* @param x     裁剪时x的坐标(左上角)
* @param y     裁剪时y的坐标(左上角)
* @param width  裁剪后的图片宽度
* @param height 裁剪后的图片高度
* 
* 裁剪后返回的是一个新的图片缓存对象
*/
 BufferedImage  getSubimage(int x,int y, int width  ,int height )

裁剪图片实例代码:

    /**
     * JAVA裁剪图片
     * @param srcImageFile  需要裁剪的图片
     * @param x     裁剪时x的坐标(左上角)
     * @param y     裁剪时y的坐标(左上角)
     * @param width  裁剪后的图片宽度
     * @param height 裁剪后的图片高度
     * @param destImageFile  裁剪后的图片
     * @return
     */
    public static boolean cut(File srcImageFile, int x,int y,int width,int height,File destImageFile){
        try {
            //使用ImageIO的read方法读取图片
            BufferedImage read = ImageIO.read(srcImageFile);
            //调用裁剪方法
            BufferedImage image = read.getSubimage(x, y, width, height);
            //获取到文件的后缀名
            String fileName = srcImageFile.getName();
            String formatName = fileName.substring(fileName.lastIndexOf(".") + 1);
            //使用ImageIO的write方法进行输出
            ImageIO.write(image,formatName,destImageFile);
        } catch (IOException e) {
            e.printStackTrace();
            return  false;
        }
        return true;
    }

添加水印

水印的添加主要是通过下面的方法进行的添加。
// 绘制一张图片 ImageObserver:接收有关 Image 信息通知的异步更新接口,没用到直接传空
boolean  drawImage(Image image,  int x,  int y, ImageObserver observer)
//设置水印透明度
void setComposite(Composite comp)
// 绘制一段文本
void  drawString(String str,  int x,  int y)

文本水印

    /**
     *  JAVA添加文字水印
     * @param srcImageFile  目标图片
     * @param destImageFile 结果图片
     * @param text         文字内容
     * @param x            水印x坐标
     * @param y            水印y坐标
     * @return
     */
    public static boolean watermarkText(File srcImageFile, File destImageFile, String text,int x,int y) {
        try {
            //使用ImageIO的read方法读取图片
            BufferedImage read = ImageIO.read(srcImageFile);
            Graphics2D graphics = read.createGraphics();
	    // 设置“抗锯齿”的属性
	    graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            // 设置字体类型和大小
            graphics.setFont(new Font("微软雅黑", Font.PLAIN, 20));
            // 设置颜色
            graphics.setColor(new Color(255,255,255));
            // 添加文字
            graphics.drawString(text,x,y);
            graphics.dispose();
            //获取到文件的后缀名
            String fileName = srcImageFile.getName();
            String formatName = fileName.substring(fileName.lastIndexOf(".") + 1);
            //使用ImageIO的write方法进行输出
            ImageIO.write(read,formatName,destImageFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

图片水印

    /**
     *  JAVA添加文字水印
     * @param srcImageFile  目标图片
     * @param destImageFile 结果图片
     * @param waterImage    水印图片
     * @param x            水印x坐标
     * @param y            水印y坐标
     * @return
     */
    public static boolean watermarkImage(File srcImageFile,File destImageFile, File waterImage,int x,int y) {
        try {
            //使用ImageIO的read方法读取图片
            BufferedImage read = ImageIO.read(srcImageFile);
            BufferedImage image = ImageIO.read(waterImage);
            //获取画布
            Graphics2D graphics = read.createGraphics();
            //设置透明度为0.5
            graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,0.5f));
            //添加水印
            graphics.drawImage(image,x,y,null);
            //关闭透明度
            //graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
            graphics.dispose();
            //获取到文件的后缀名
            String fileName = srcImageFile.getName();
            String formatName = fileName.substring(fileName.lastIndexOf(".") + 1);
            //使用ImageIO的write方法进行输出
            ImageIO.write(read,formatName,destImageFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

如何擦除水印?
第一种方法 :
// 擦除某一区域(擦除后显示背景色)
void clearRect(int x, int y, int width, int height)

第二种方法:色素替代法
找到水印的颜色编码,然后用背景色颜色编码替代。
代码实现:略 (这种清除水印的需求还是交给 PS 这种专业软件去做吧)

贝塞尔曲线

通常绘制线段直接使用一下的方法就可以了 drawLine 方法就可以了。但是在实现曲线的时候就很难看,所以需要用到贝塞尔曲线。
可以通过 Path 类来实现贝塞尔曲线的效果

BufferedImage image = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = image.createGraphics();
// 设置“抗锯齿”的属性
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//获取路径操作
Path2D path = new GeneralPath();
//通过移动到指定的浮点精度指定的指定的坐标,向路径添加一个点。
path.moveTo(192, 18);
//添加一个弯曲段,由两个新定义的点,通过绘制一条二次曲线相交的当前坐标和指定的坐标 (x2,y2)的路径,使用指定的点 (x1,y1)作为二次参考
path.quadTo(120, 12, 253, 67);
graphics.draw(path);
graphics.dispose();

总结

JAVA 操作图片的话算是一个非常冷门的功能了,最多就是图片的缩放,裁剪,水印这三种情况。如果需要进行一些额外的操作的话,就非常需要认真的查阅下 JDK 的 API,并且 JAVA 操作图片调试起来也非常的不方便。总的来说就是复杂的图片操作需求还是交给更专业的软件(PS)来进行操作吧!!!
JDK1.8 在线 API

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3187 引用 • 8213 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...