Java处理图片(图片缩放,图片裁剪,添加图文水印等)的两种方式

第一种:阿里云对象存储oss服务提供java的SDK方式。

首先开通阿里云的对象存储oss服务(本地调用存储不收费,通过公网调用会产生费用,但是很低);

进入服务管理页面后,创建Bucket,

根据需求是否开通相关服务:

创建好Bucket,进入控制台,可以在这里管理相关文件:

可通过首页打开帮助文档:

文档中提供对图片处理的Java SDK,也有其他语言。也提供上传下载的SDK。

如图片缩放的一些参数值:

提供的SDK参考代码:

// Endpoint以杭州为例,其它Region请按实际情况填写。
String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
// 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录RAM控制台创建RAM账号。
String accessKeyId = "<yourAccessKeyId>";
String accessKeySecret = "<yourAccessKeySecret>";
String bucketName = "<yourBucketName>";
String objectName = "<yourObjectName>";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 图片缩放。
String style = "image/resize,m_fixed,w_100,h_100";
GetObjectRequest request = new GetObjectRequest(bucketName, objectName);
request.setProcess(style);
ossClient.getObject(request, new File("example-resize.jpg"));
// 图片裁剪。
style = "image/crop,w_100,h_100,x_100,y_100,r_1";
request = new GetObjectRequest(bucketName, objectName);
request.setProcess(style);
ossClient.getObject(request, new File("example-crop.jpg"));
// 图片旋转。
style = "image/rotate,90";
request = new GetObjectRequest(bucketName, objectName);
request.setProcess(style);
ossClient.getObject(request, new File("example-rotate.jpg"));
// 图片锐化。
style = "image/sharpen,100"; 
request = new GetObjectRequest(bucketName, objectName);
request.setProcess(style);
ossClient.getObject(request, new File("example-sharpen.jpg"));
// 添加水印。
style = "image/watermark,text_SGVsbG8g5Zu-54mH5pyN5YqhIQ"; 
request = new GetObjectRequest(bucketName, objectName);
request.setProcess(style);
ossClient.getObject(request, new File("example-watermark.jpg"));
// 图片格式转换。
style = "image/format,png";
request = new GetObjectRequest(bucketName, objectName);
request.setProcess(style);
ossClient.getObject(request, new File("example-format.png"));
// 获取图片信息。
style = "image/info";
request = new GetObjectRequest(bucketName, objectName);
request.setProcess(style);
ossClient.getObject(request, new File("example-info.txt"));
// 关闭OSSClient。
ossClient.shutdown();

写的一个demo仅供参考:

package com.vevor.research.imageService.service;

import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.common.utils.IOUtils;
import com.aliyun.oss.internal.OSSHeaders;
import com.aliyun.oss.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Formatter;
import java.util.List;

/**
 * @author :lixinyu
 * @version :M1.0
 * @program :vevor-research
 * @date :Created in 2020/9/10 9:50
 * @description :oss存储,处理图片服务类
 */
@Slf4j
@Service
public class OssServiceImpl {

    /**
     *Endpoint以成都为例,其它Region请按实际情况填写。
     */
    @Value("${aliyun.oss.endpoint}")
    private String endpoint;

    /**
     * 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录RAM控制台创建RAM账号。
     */
    @Value("${aliyun.oss.accessKeyId}")
    private String accessKeyId;

    @Value("${aliyun.oss.accessKeySecret}")
    private String accessKeySecret;

    /**
     * 个人账户bucket,用户技术调研及测试
     */
    @Value("${aliyun.oss.bucketName}")
    private String bucketName;

    /**
     * 本地测试上传及下载路径
     */
    private final String filePath = "D:\\picture\\";

    /**
     * 本地图片上传至oss
     */
    public void uploadLocalToOss() {

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        try {
            // 创建PutObjectRequest对象。key为bucket里所要存储的文件名,可以指定文件夹
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, "vevor/black.png", new File(filePath+"black.png"));

            // 如果需要上传时设置存储类型与访问权限,请参考以下示例代码。
            ObjectMetadata metadata = new ObjectMetadata();
            // 设置http头
            metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
            // 设置文件读写权限权限,默认继承bucket权限
            metadata.setObjectAcl(CannedAccessControlList.PublicRead);
            putObjectRequest.setMetadata(metadata);

            /*// 您的回调服务器地址,如http://oss-demo.aliyuncs.com:23450,回调服务器必须是公网IP
            String callbackUrl = "http://61.185.225.102";
            // 上传回调参数。
            Callback callback = new Callback();
            callback.setCallbackUrl(callbackUrl);
            //(可选)设置回调请求消息头中Host的值,即您的服务器配置Host的值。
            callback.setCallbackHost("oss-cn-hangzhou.aliyuncs.com");
            // 设置发起回调时请求body的值。
            callback.setCallbackBody("{\\\"bucket\\\":${bucket},\\\"object\\\":${object},"
                    + "\\\"mimeType\\\":${mimeType},\\\"size\\\":${size},"
                    + "\\\"my_var1\\\":${x:var1},\\\"my_var2\\\":${x:var2}}");
            // 设置发起回调请求的Content-Type。
            callback.setCalbackBodyType(Callback.CalbackBodyType.JSON);
            // 设置发起回调请求的自定义参数,由Key和Value组成,Key必须以x:开始。
            callback.addCallbackVar("x:var1", "value1");
            callback.addCallbackVar("x:var2", "value2");
            putObjectRequest.setCallback(callback);*/

            // 上传文件
            ossClient.putObject(putObjectRequest);

            // 判断文件是否存在,也可用此方法判断上传是否成功
            boolean flag = ossClient.doesObjectExist(bucketName, "vevor/black.png");
            if (flag){
                log.info("upload success");
            }
        } catch (ClientException ce) {
            log.error("Error Message: " + ce.getMessage());
        } finally {
            // 关闭OSSClient。
            ossClient.shutdown();
        }
    }

    /**
     * 自定义处理图片并保存至bucket同时下载至本地
     */
    public JSONObject changeImageByFreeStyle() throws IOException {

        // 当前bucket下的要处理的文件名。
        String objectName = "black.png";
        int index = objectName.lastIndexOf(".");
        //获取图片去掉后缀(.jpg)的名字
        String realName = objectName.substring(0,index);
        //获取文件后缀
        String extension = objectName.substring(index);
        // 当前bucket下要存储的路径
        String bucketPath = "vevor/";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        // 先判断文件是否存在,不存在则抛异常
        boolean flag = ossClient.doesObjectExist(bucketName, objectName);
        if (!flag){
            throw new ClientException("文件不存在");
        }
        StringBuilder sbStyle = new StringBuilder();
        Formatter styleFormatter = new Formatter(sbStyle);
        // 自定义图片处理样式
        String styleType = "image/resize,m_fixed,w_500,h_100";
        String changeName = realName + "-change" + extension;
        // 存储在oss上的图片路径
        String targetImage = bucketPath + changeName;
        // base64编码
        styleFormatter.format("%s|sys/saveas,o_%s,b_%s", styleType,
                BinaryUtil.toBase64String(targetImage.getBytes()),
                BinaryUtil.toBase64String(bucketName.getBytes()));
        // 创建ProcessObjectRequest对象,处理图片
        ProcessObjectRequest request = new ProcessObjectRequest(bucketName, objectName, sbStyle.toString());

        // 图片持久化处理,存储在当前bucket下
        GenericResult processResult = ossClient.processObject(request);

        // 下载OSS文件到本地文件。如果指定的本地文件存在会覆盖,不存在则新建。
        GetObjectRequest objectRequest = new GetObjectRequest(bucketName, targetImage);
        String localPath = filePath + "vevor\\";
        ossClient.getObject(objectRequest,new File(checkFilePathAndName(localPath)+ changeName));
        // 获取状态
        String json = IOUtils.readStreamAsString(processResult.getResponse().getContent(), "UTF-8");
        processResult.getResponse().getContent().close();
        // 关闭OSSClient。
        ossClient.shutdown();
        JSONObject.parseObject(json);
        return JSONObject.parseObject(json);
    }

    /**
     * 下载bucket中的图片至本地
     */
    public void download(){

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        String objectName = "vevor/qq-change.jpg";

        // 下载OSS文件到本地文件。如果指定的本地文件存在会覆盖,不存在则新建。
        String localPath = filePath + "vevor\\";
        ossClient.getObject(new GetObjectRequest(bucketName, objectName), new File(checkFilePathAndName(localPath) + "qq-change.jpg"));
        log.info("图片已下载至:{}" + localPath);
        // 关闭OSSClient。
        ossClient.shutdown();
    }

    /**
     * 批量处理图片,通过列举文件实现批量操作并下载至本地
     */
    public void batchImage(){
        // 当前bucket下的文件夹名称
        String keyPrefix = "batch-test/";
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        // 列举文件。 如果不设置KeyPrefix,则列举存储空间下所有的文件。KeyPrefix,则列举包含指定前缀的文件。
        ObjectListing objectListing = ossClient.listObjects(bucketName,keyPrefix);
        List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
        // 如果设置KeyPrefix,第一个文件为与KeyPrefix同名的路径,而不是文件,所以删除它
        if (sums.get(0).getKey().equals(keyPrefix)){
            sums.remove(0);
        }

        // 添加自定义样式。
        String style = "image/resize,m_fixed,w_400,h_400";
        String localPath = filePath + "batch\\";
        for (OSSObjectSummary s : sums) {
            // key为bucket中带文件夹前缀的文件名
            GetObjectRequest request = new GetObjectRequest(bucketName, s.getKey());
            request.setProcess(style);
            String fileName = s.getKey().replace(keyPrefix,"");
            // 下载OSS文件到本地文件。如果指定的本地文件存在会覆盖,不存在则新建。
            ossClient.getObject(request, new File(checkFilePathAndName(localPath) + fileName));
        }
        // 关闭OSSClient。
        ossClient.shutdown();
        log.info("批量处理图片成功");
    }

    /**
     * 添加文字或文字水印
     */
    public void addWatermark(){
        String objectName = "vevor/qq-change.jpg";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        // 先判断文件是否存在,不存在则抛异常
        boolean flag = ossClient.doesObjectExist(bucketName, objectName);
        if (!flag){
            throw new ClientException("文件不存在");
        }
//        String watermark = "FORGED STEEL CONSTRUCTIO";
        String watermark = "black-change.png";
        String base64 = Base64.getEncoder().encodeToString(watermark.getBytes(StandardCharsets.UTF_8));
        // 文字水印样式
        // String style = "image/watermark,text_" + base64 + ",color_FFFFFF,size_30,g_center,x_0,y_0";
        // 图片水印样式
        String style = "image/watermark,image_" + base64 + ",g_south,x_0,y_0";
        GetObjectRequest request = new GetObjectRequest(bucketName,objectName);
        request.setProcess(style);
        String localPath = filePath + "watermark\\";
        // 处理完成后下载至本地
        ossClient.getObject(request,new File(checkFilePathAndName(localPath) + "black-change.png"));
        // 关闭OSSClient。
        ossClient.shutdown();
    }

    /**
     * 检查目录是否存在,不存在先创建,否则下载soo文件失败
     * @param path 文件路径
     * @return 文件路径
     */
    private String checkFilePathAndName(String path){
        File file = new File(path);
        if (!file.exists()){
            if (file.mkdir()){
                log.info("文件目录已创建");
            };
        }
        return path;
    }
}

其中endpoint,accessKeyId,accessKeySecret在application.yml中配置着(这些密钥信息需要自己申请)。like this ↓:

aliyun:
  oss:
    endpoint: oss-cn-chengdu.aliyuncs.com # oss对外服务的访问域名
    accessKeyId: LTAI4GG6tawYReHwYCxPtZmFz # 访问身份验证中用到用户标识
    accessKeySecret: spOQQe34bhiEtMnf6TrSS272AakNz9a # 用户用于加密签名字符串和oss用来验证签名字符串的密钥
    bucketName: lux-oss # oss的存储空间
    policy:
      expire: 300 # 签名有效期(S)
    maxSize: 10 # 上传文件大小(M)
    callback: http://XX(必须为公网ip):8080/aliyun/oss/callback # 文件上传成功后的回调地址
    dir:
      prefix: vevor/ # 上传文件夹路径前缀

其他操作可参考文档详情。

 

 

第二种方式:Java自带了图片处理类

具体实现参考自己写的一个Demo。

package com.vevor.research.imageService.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.CropImageFilter;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.io.File;
import java.io.IOException;

/**
 * @author :lixinyu
 * @version :M1.0
 * @program :vevor-research
 * @date :Created in 2020/9/11 9:59
 * @description :java图片处理类,包括java图片处理,java图片水印,java图片切割,java图片缩放,java图片格式转换,java图片等比例缩小
 *                Image是一个抽象类,BufferedImage是其实现类,是一个带缓冲区图像类,主要作用是将一幅图片加载到内存中
 *               (BufferedImage生成的图片在内存里有一个图像缓冲区,利用这个缓冲区我们可以很方便地操作这个图片),
 *                提供获得绘图对象、图像缩放、选择图像平滑度等功能,通常用来做图片大小变换、图片变灰、设置透明不透明等。
 */
@Slf4j
@Service
public class ImageServiceImpl {

    /**
     * 缩放图像(按指定比例缩放)
     * @param localImagePath 源图像文件地址
     * @param scaleImagePath 缩放后的图像地址
     * @param scaling        缩放比例
     * @param flag           缩放选择:true 放大; false 缩小;
     * @throws IOException   IOException
     */
    public void scaling(String localImagePath, String scaleImagePath, int scaling, boolean flag) throws IOException {
        // 读入文件
        BufferedImage localImage = ImageIO.read(new File(localImagePath));
        if (ObjectUtils.isEmpty(localImage)){
            throw new IllegalArgumentException("未找到图片");
        }
        // 得到源图宽
        int width = localImage.getWidth();
        // 得到源图长
        int height = localImage.getHeight();
        if (flag) {
            // 放大
            width = width * scaling;
            height = height * scaling;
        } else {
            // 缩小
            width = width / scaling;
            height = height / scaling;
        }
        // 创建图像的缩放版本
        Image image = localImage.getScaledInstance(width, height, Image.SCALE_DEFAULT);
        // 构造一个预定义图像类型的BufferedImage
        BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        // 获取图形2d
        Graphics graphics = tag.getGraphics();
        // 绘制缩小后的图
        graphics.drawImage(image, 0, 0, null);
        // 释放图形资源
        graphics.dispose();
        // 输出到文件流
        boolean success = ImageIO.write(tag, "JPEG", new File(scaleImagePath));
        if (!success){
            throw new IIOException("缩放图片失败");
        }
    }

    /**
     * 缩放图像(按指定宽高缩放)
     * @param localImagePath 源图像文件地址
     * @param scaleImagePath 缩放后的图像地址
     * @param width          缩放后的宽度
     * @param height         缩放后的高度
     * @throws IOException   IOException
     */
    public void scale1WithCustom(String localImagePath, String scaleImagePath, int width, int height) throws IOException {
        // 读入文件
        BufferedImage localImage = ImageIO.read(new File(localImagePath));
        if (ObjectUtils.isEmpty(localImage)){
            throw new IllegalArgumentException("未找到图片");
        }
        // 创建图像的缩放版本
        Image image = localImage.getScaledInstance(width, height, Image.SCALE_DEFAULT);
        // 构造一个预定义图像类型的BufferedImage
        BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        // 获取图形2d
        Graphics graphics = tag.getGraphics();
        // 绘制缩小后的图
        graphics.drawImage(image, 0, 0, null);
        // 释放图形资源
        graphics.dispose();
        // 输出到文件流
        boolean success = ImageIO.write(tag, "JPEG", new File(scaleImagePath));
        if (!success){
            throw new IIOException("缩放图片失败");
        }
    }

    /**
     * 缩放图像(按高度或者宽度比值缩放)
     * @param localImagePath 源图像文件地址
     * @param scaleImagePath 缩放后的图像地址
     * @param height         缩放后的高度
     * @param width          缩放后的宽度
     * @param repair         比例不对时是否需要补白:true为补白; false为不补白;
     * @throws IOException   IOException
     */
    public void scale1WithRatio(String localImagePath, String scaleImagePath, int width, int height, boolean repair) throws IOException {
        // 缩放比例
        double ratio;
        BufferedImage localImage = ImageIO.read(new File(localImagePath));
        if (ObjectUtils.isEmpty(localImage)){
            throw new IllegalArgumentException("未找到图片");
        }
        // Image.SCALE_SMOOTH 的缩略算法 生成缩略图片的平滑度的优先级比速度高 生成的图片质量比较好 但速度慢
        Image image = localImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
        // 计算比例
        if ((localImage.getHeight() > height) || (localImage.getWidth() > width)) {
            if (localImage.getHeight() > localImage.getWidth()) {
                // 源图高比宽长,缩放比例为:缩放高度/源图高度
                ratio = (new Integer(height)).doubleValue() / localImage.getHeight();
            } else {
                // 源图宽比高长,缩放比例为:缩放宽度/源图宽度
                ratio = (new Integer(width)).doubleValue() / localImage.getWidth();
            }
            // AffineTransform是J2SE中非常重要的专门处理2D图像仿射变换的类,表示缩放变换的变换。ratio为width,height倍数
            AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(ratio, ratio), null);

            // 转换源BufferedImage并将结果存储到目标BufferedImage。如果两个图像的颜色模型不匹配,则执行到目标颜色模型的颜色转换。
            // 如果目标图像为空,使用源代码创建缓冲区映像,返回过滤后的缓冲区图像
            image = op.filter(localImage, null);
        }
        if (repair) {
            // 补白
            // BufferedImage.TYPE_INT_RGB表示压缩为8位RGB颜色组件的图像
            BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            // 基于图片对象打开绘图
            Graphics2D graphics = bufferedImage.createGraphics();
            // 添加背景色
            graphics.setColor(Color.white);
            // 填充指定的图形
            graphics.fillRect(0, 0, width, height);

            // 根据宽度缩放规则绘图
            if (width == image.getWidth(null)) {
                graphics.drawImage(image, 0, (height - image.getHeight(null)) / 2,
                        image.getWidth(null), image.getHeight(null),
                        Color.white, null);
            } else {
                graphics.drawImage(image, (width - image.getWidth(null)) / 2, 0,
                        image.getWidth(null), image.getHeight(null),
                        Color.white, null);
            }

            // 释放图形资源
            graphics.dispose();
            image = bufferedImage;
        }
        boolean success = ImageIO.write((BufferedImage) image, "JPEG", new File(scaleImagePath));
        if (!success){
            throw new IIOException("缩放图片失败");
        }
    }

    /**
     * 图像切割(按指定起点坐标和宽高切割)
     * @param localImagePath 源图像地址
     * @param scaleImagePath 切片后的图像地址
     * @param x              目标切片起点坐标X
     * @param y              目标切片起点坐标Y
     * @param width          目标切片宽度
     * @param height         目标切片高度
     * @throws IOException   IOException
     */
    public void cutImage(String localImagePath, String scaleImagePath, int x, int y, int width, int height) throws IOException {
        // 读取源图像
        BufferedImage localImage = ImageIO.read(new File(localImagePath));
        if (ObjectUtils.isEmpty(localImage)){
            throw new IllegalArgumentException("未找到图片");
        }
        // 源图宽度和高度
        int localWidth = localImage.getHeight(null);
        int localHeight = localImage.getWidth(null);

        if (localWidth > 0 && localHeight > 0) {
            // 创建图像的缩放版本
            Image image = localImage.getScaledInstance(localWidth, localHeight, Image.SCALE_SMOOTH);

            // 四个参数分别为图像起点坐标和宽高
            // 即: CropImageFilter(int x,int y,int width,int height)
            // 提取绝对矩形
            ImageFilter filter = new CropImageFilter(x, y, width, height);

            // 使用指定的图像生成器创建图像
            Image img = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(image.getSource(), filter));
            BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics graphics = tag.getGraphics();
            // 绘制切割后的图
            graphics.drawImage(img, 0, 0, width, height, null);
            graphics.dispose();
            // 输出为文件
            boolean success = ImageIO.write(tag, "JPEG", new File(scaleImagePath));
            if (!success) {
                throw new IIOException("切割图片失败");
            }
        }
    }

    /**
     * 图像类型转换:如GIF->JPG、GIF->PNG、PNG->JPG、PNG->GIF(X)、BMP->PNG
     * @param localImagePath   源图像地址
     * @param convertImageFile 目标图像地址
     * @throws IOException     IOException
     */
    public void convert(String localImagePath, String convertImageFile) throws IOException {
        File file = new File(localImagePath);
        if (ObjectUtils.isEmpty(file)){
            throw new IllegalArgumentException("未找到图片");
        }
        // 判断文件是否有读取权限
        if (file.canRead() && file.canWrite()){
            BufferedImage image = ImageIO.read(file);
            // formatName:包含格式非正式名称的 String:如JPG、JPEG、GIF等
            boolean success = ImageIO.write(image, "jpg", new File(convertImageFile));
            if (!success) {
                throw new IIOException("切割图片失败");
            }
        } else {
            throw new SecurityException("无权访问文件");
        }
    }

    /**
     * 给图片添加文字水印
     * @param pressText      水印文字
     * @param localImageFile 源图像地址
     * @param markImageFile  目标图像地址
     * @param fontName       水印的字体名称
     * @param fontStyle      水印的字体样式(Font.BOLD / 36)
     * @param color          水印的字体颜色
     * @param fontSize       水印的字体大小
     * @param x              修正值
     * @param y              修正值
     * @param alpha          透明度,必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字,值越小透明度越高
     * @throws IOException   IOException
     */
    public void textWatermark(String pressText,
                              String localImageFile,
                              String markImageFile,
                              String fontName,
                              int fontStyle,
                              Color color,
                              int fontSize,
                              int x,
                              int y,
                              float alpha) throws IOException {
        File localFile = new File(localImageFile);
        if (ObjectUtils.isEmpty(localFile)){
            throw new IllegalArgumentException("未找到图片");
        }
        Image src = ImageIO.read(localFile);
        int width = src.getWidth(null);
        int height = src.getHeight(null);
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = image.createGraphics();
        graphics.drawImage(src, 0, 0, width, height, null);
        graphics.setColor(color);
        graphics.setFont(new Font(fontName, fontStyle, fontSize));
        graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
        // 在指定坐标绘制水印文字
        graphics.drawString(pressText, (width - (getLength(pressText) * fontSize))
                / 2 + x, (height - fontSize) / 2 + y);
        graphics.dispose();
        boolean success = ImageIO.write(image, "jpg", new File(markImageFile));
        if (!success) {
            throw new IIOException("添加文字水印失败");
        }
    }

    /**
     * 给图片添加图片水印
     * @param pressImg       水印图片
     * @param localImagePath 源图像地址
     * @param pressImageFile 目标图像地址
     * @param x              修正值。 默认在中间
     * @param y              修正值。 默认在中间
     * @param alpha          透明度,必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字,值越小透明度越高
     * @throws IOException   IOException
     */
    public void imageWatermark(String pressImg,
                                            String localImagePath,
                                            String pressImageFile,
                                            int x,
                                            int y,
                                            float alpha) throws IOException {
        File localFile = new File(localImagePath);
        if (ObjectUtils.isEmpty(localFile)){
            throw new IllegalArgumentException("未找到图片");
        }
        Image localImage = ImageIO.read(localFile);
        int width = localImage.getWidth(null);
        int height = localImage.getHeight(null);
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = image.createGraphics();
        graphics.drawImage(localImage, 0, 0, width, height, null);
        // 水印文件
        Image markImage = ImageIO.read(new File(pressImg));
        if (ObjectUtils.isEmpty(markImage)){
            throw new IllegalArgumentException("未找到水印图片");
        }
        int markImageWidth = markImage.getWidth(null);
        int markImageHeight = markImage.getHeight(null);
        // 将新像素与图形处理器上的现有像素组合
        graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
        // 矩形图像原点为左上角,x,y=0,图片水印在源图中间
        // x为原点在水平距离向右的修正值,x为原点在垂直距离向下的修正值
        graphics.drawImage(markImage, x, y, markImageWidth, markImageHeight, null);
        // 释放图形处理资源
        graphics.dispose();
        ImageIO.write(image,  "jpg", new File(pressImageFile));
    }

    /**
     * 计算text的长度(一个中文算两个字符)
     * @param text 字符
     * @return 字符长度
     */
    private int getLength(String text) {
        int length = 0;
        for (int i = 0; i < text.length(); i++) {
            if ((text.charAt(i) + "").getBytes().length > 1) {
                length += 2;
            } else {
                length += 1;
            }
        }
        return length / 2;
    }
}

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于Java中的MultipartFile图片上传而言,可以通过以下步骤实现图片水印的功能: 1. 首先,你需要在前端实现图片的上传功能,将图片以MultipartFile类型的对象传输到后端的controller层。 2. 在controller层接收到图片后,可以使用第三方库,如ImageIO或Thumbnails,来对图片进行处理。这些库提供了丰富的方法来处理图片。 3. 为了给图片添加水印信息,你可以创建一个水印图片,或者使用文字作为水印。要创建水印图片,你可以使用Java的Graphics2D类,在水印图片上绘制所需的文字或图形。 4. 一旦你有了水印图片,你可以使用Graphics2D的drawImage方法将水印图片绘制到原始图片上。可以通过指定位置和大小来调整水印的位置和大小。 5. 绘制水印后,你可以将带有水印图片保存到指定的目录或返回给前端。 总结一下,要实现Java MultipartFile图片上传加水印的功能,你需要在controller层接收到前端上传的图片,使用第三方库对图片进行处理,并在图片上绘制水印。最后,保存带有水印图片或返回给前端。<span class="em">1</span> #### 引用[.reference_title] - *1* [Java MultipartFile实现文件上传并为图片加上水印(二)](https://blog.csdn.net/weixin_42171478/article/details/113735313)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值