封装图片处理工具类,实现图片的裁剪、压缩、图片水印、文字水印、多行文字水印等功能

一、前言

最近用结合thumbnailator和Graphics2D封装了一个图片工具类,目前可以实现图片的裁剪、压缩、添加图片水印、文字水印、多行文字水印等功能,同时该工具类的实现使用了建造者模式、责任链模式、工厂模式、策略模式等多种设计模式,感觉图片处理的功能有一定的通用性,所以这次写一篇文章来分享一下这个工具类的使用方式和实现原理,代码不足之处还望大家指正,文末也会提供代码的github地址。

二、工具类的依赖和简单介绍

1、添加依赖

		<dependency>
            <groupId>net.coobird</groupId>
            <artifactId>thumbnailator</artifactId>
            <version>0.4.20</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.15</version>
        </dependency>
        <dependency>
            <groupId>commons-chain</groupId>
            <artifactId>commons-chain</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>
        <!-- 仅仅为了支持MultipartFile类型文件的加载,不加载MultipartFile这个依赖可以去掉-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.3.12</version>
            <scope>compile</scope>
        </dependency>

2、简单的使用

首先这个处理类提供了一个建造简化了工具栏使用,下面一个简单的使用示例,实现了图的裁剪裁剪,从这个示例代码可以看出这个图片处理工具类的建造者主要由load(加载需要处理的图片)、addRule(添加图片处理规则,可以多次添加)、toFile(输出处理后的图片)三部分组成。

ImageHandBuilder.load(imageResource)
                .addRule(ImageHandRuleFactory.regionRuleBuilder()
                        .regionType(RegionTypeEnum.SCALE_REGION)
                        .positions(Positions.TOP_CENTER)
                        .scale(0.5d).build())
                .toFile("D:\\test\\test-region-scale.jpg");

3、加载需要处理的图片

加载需要处理的图片的方法是load() 方法,建造者调用的第一个方法必须是这个load()方法。load()方法提供多个重载方法,支持以下传参。

	/**
     * 加载图片
     * @param absolutePath 图片绝对路径
     * @return Builder
     */
	Builder load(String absolutePath);

    /**
     * 加载图片
     * @param file 图片文件
     * @return Builder
     */
    Builder load(File file);

	/**
     * 加载图片
     * @param file 图片文件
     * @return Builder
     */
    Builder load(MultipartFile file);
    
    /**
     * 加载图片
     * @param url 图片url
     * @return Builder
     */
    Builder load(URL url);

 	/**
     * 加载图片
     * @param inputStream 图片输入流
     * @return Builder
     */
    Builder load(InputStream inputStream);

	/**
     * 加载图片
     * @param image 图片
     * @param fileType 图片类型
     * @return Builder
     */
    Builder load(BufferedImage image, String fileType);

4、添加图片处理规则

添加图片处理规则的方法是addRule(),支持RegionRule(裁剪规则)、CompressRule(压缩规则)、ImageWatermarkRule(图片水印规则)、TextWatermarkRule(文字水印规则)、MultipleTextWatermarkRule(多行文字水印规则)。规则的添加支持Builder方式和使用规则工厂的方法

4.1 Builder的方式

	@Test
    public void testBuilder() throws Exception {
        ClassLoader classLoader = ImageHandBuilderTest.class.getClassLoader();
        URL imageResource = classLoader.getResource("pic/example.jpg");
        ImageHandBuilder.load(imageResource)
                .addRule(RegionRule.builder()
                        .regionType(RegionTypeEnum.SCALE_REGION)
                        .positions(Positions.TOP_CENTER)
                        .scale(0.5d).build())
                .toFile("D:\\test\\test-region-scale.jpg");
    }

4.2 使用规则工厂的方式

	@Test
    public void testFactory() throws Exception {
        ClassLoader classLoader = ImageHandBuilderTest.class.getClassLoader();
        URL imageResource = classLoader.getResource("pic/example.jpg");
        ImageHandBuilder.load(imageResource)
                .addRule(ImageHandRuleFactory.regionRuleBuilder()
                        .regionType(RegionTypeEnum.SCALE_REGION)
                        .positions(Positions.TOP_CENTER)
                        .scale(0.5d).build())
                .toFile("D:\\test\\test-region-scale.jpg");
    }

5、输出处理后的图片

输出处理后的图片的方法是toFile()或toOutputStream()方法,是建造者最后需要调用的一个方法。输出处理后的图片的方法如下

		 /**
         * 将处理后的图片导出到文件
         * @param file 图片文件
         */
         void toFile(File file);

        /**
         * 将处理后的图片导出到文件
         * @param absolutePath 图片绝对路径
         */
         void toFile(String absolutePath);

        /**
         * 将处理后的图片导出到输出流
         * @param out 输出流
         */
         void toOutputStream(OutputStream out);

三、使用方式

下面我们使用同一张示例图片依次演示一下RegionRule(裁剪规则)、CompressRule(压缩规则)、ImageWatermarkRule(图片水印规则)、TextWatermarkRule(文字水印规则)、MultipleTextWatermarkRule(多行文字水印规则)这五种规则的设置和实现效果,下图处理前的示例原图,图片的原始比例为3840 X 2160:

1、图片裁剪

图片裁剪提供了按长宽裁剪和按比例裁剪两种裁剪方式

图片裁剪规则实体类

import com.fhey.common.file.imagehand.enums.RegionTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import net.coobird.thumbnailator.geometry.Positions;

/**
 * @author fhey
 * @date 2022-07-08 17:42:51
 * @description: 裁剪规则
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class RegionRule implements ImageHandRule {

    /**
     * 位置裁剪
     */
    private Positions positions;

    /**
     * 裁剪宽度
     */
    private Integer width;

    /**
     * 裁剪高度
     */
    private Integer height;

    /**
     * 裁剪比例
     */
    private Double scale;

    /**
     * 裁剪类型
     */
    private RegionTypeEnum regionType;
    
    @Override
    public boolean check() {
        if (null == regionType){
            throw new RuntimeException("裁剪类型(compressType)不能为空!");
        }
        if (RegionTypeEnum.SCALE_REGION.equals(regionType) && null == scale){
            throw new RuntimeException("按比列裁剪模式裁剪比例(scale)不能为空!");
        }
        if (RegionTypeEnum.WIDTH_HEIGHT_REGION.equals(regionType) && (null == width || null == height)){
            throw new RuntimeException("按宽高裁剪模式宽高不能为空!");
        }
        return true;
    }
}

1.1 按长宽裁剪

从图片中间裁剪300 X 300的区域

1.1.1 示例代码
 @Test
    public void testWidthHeightRegion() throws Exception {
        ClassLoader classLoader = ImageHandBuilderTest.class.getClassLoader();
        URL imageResource = classLoader.getResource("pic/example.jpg");
        ImageHandBuilder.load(imageResource)
                .addRule(ImageHandRuleFactory.regionRuleBuilder()
                        .regionType(RegionTypeEnum.WIDTH_HEIGHT_REGION)
                        .positions(Positions.CENTER)
                        .width(300)
                        .height(300).build())
                .toFile("D:\\test\\test-region-widthHeight.jpg");
    }
1.1.2 实现效果

由下图可以看出处理后的图片正好是300 X 300,但是只截取了中间一小块

1.2 按比例裁剪

从上中开始按图片0.5的比列裁剪

1.2.1 示例代码
 @Test
    public void testScaleRegion() throws Exception {
        ClassLoader classLoader = ImageHandBuilderTest.class.getClassLoader();
        URL imageResource = classLoader.getResource("pic/example.jpg");
        ImageHandBuilder.load(imageResource)
                .addRule(ImageHandRuleFactory.regionRuleBuilder()
                        .regionType(RegionTypeEnum.SCALE_REGION)
                        .positions(Positions.TOP_CENTER)
                        .scale(0.5d).build())
                .toFile("D:\\test\\test-region-scale.jpg");
    }
1.2.2 实现效果

有下图可以看出裁剪之后长宽都是原图的一半,因为从上中开始裁剪所以原图下方一些图片被裁剪掉了

2、图片压缩

图片压缩提供了按长宽压缩和按比例压缩两种压缩方式,其中按长宽压缩又提供了不保持比列、但宽度保持比列、自动保持比列。

图片压缩规则实体类

import com.fhey.common.file.imagehand.enums.CompressTypeEnum;
import com.fhey.common.file.imagehand.enums.KeepAspectRatioEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author fhey
 * @date 2022-07-08 17:28:28
 * @description: 压缩规则
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class CompressRule implements ImageHandRule {

    /**
     * 压缩宽度
     */
    private Integer width;

    /**
     * 压缩高度
     */
    private Integer height;

    /**
     * 压缩比例
     */
    private Double scale;

    /**
     * 压缩类型
     */
    private CompressTypeEnum compressType;

    /**
     * 是否保持宽高比
     */
    private KeepAspectRatioEnum keepAspectRatio;

    @Override
    public boolean check() {
        if (null == compressType){
            throw new RuntimeException("压缩类型(compressType)不能为空!");
        }
        if (CompressTypeEnum.SCALE_COMPRESS.equals(compressType) && null == scale){
            throw new RuntimeException("按比列压缩模式压缩比例(scale)不能为空!");
        }
        if (CompressTypeEnum.WIDTH_HEIGHT_COMPRESS.equals(compressType) && (null == width || null == height)){
            throw new RuntimeException("按宽高压缩模式宽高不能为空!");
        }
        return true;
    }
}

2.1 按长宽压缩 不保持比例

2.1.1 示例代码

将图片压缩成300 X 300

@Test
    public void testWidthHeightCompressNoKeepAspectRatio() throws Exception {
        ClassLoader classLoader = ImageHandBuilderTest.class.getClassLoader();
        URL imageResource = classLoader.getResource("pic/example.jpg");
        ImageHandBuilder.load(imageResource)
                .addRule(ImageHandRuleFactory.compressRuleBuilder()
                        .compressType(CompressTypeEnum.WIDTH_HEIGHT_COMPRESS)
                        .width(300)
                        .height(300).build())
                .toFile("D:\\test\\test-compress-widthHeight-noKeep.jpg");
    }
2.1.2 实现效果

由下图可以看出处理后的图片是300 X300,但是图片变形严重

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值