图片添加文字水印,或者图片水印,图片灰度操作,图片裁剪,按倍率放大图片,按倍率缩小图片

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.ClassUtils;
import org.apache.commons.lang.StringUtils;

import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;

import static sun.net.www.ParseUtil.toURI;

/**
 * @Date : 2020/11/16
 * @Time : 12:01
 * @Description : 图片添加文字水印,或者图片水印,图片灰度操作,图片裁剪,按倍率放大图片,按倍率缩小图片
 */

@Slf4j
public class ImageMarkUtil {
    //水印文字
    public static String MARK_TEXT = "水印";
    //水印字体
    public static String FONT_NAME = "微软雅黑";
    //水印文字粗细
    public static int FONT_STYLE = Font.BOLD;
    //水印文字大小
    public static int FONT_SIZE = 30;

    public static int MARGIN_ALL = 50;
    //水印颜色
    public static Color FONT_COLOR = Color.RED;
    //水印的角度
    public static int RADIANS = 30;
    //水印透明度
    public static float ALPHA = 0.5F;

    //指定水印位置
    public static int X = 0;
    public static int Y = 0;

    //默认的水印图片样式地址
    public static String LOGO_IMAGE_URL = "classpath:static/image/viewfile.gif";

    /**
     * @param srcPath 目标图片路径
     * @param toPath  图片输出路径
     * @Description 设置图片水印
     */
    public static void addWaterMark(String srcPath, String toPath) {
        File file = getFile(srcPath);
        //添加水印,返回处理后的图片对象
        BufferedImage bufferedImage = addWaterMark(getFile(srcPath), 1);
        //将处理后的图片输出到指定路径
        outPutImage(file.getName(), toPath, bufferedImage);
    }

    /**
     * @param srcPath 目标图片路径
     * @param toPath  图片输出路径
     * @Description 设置文字水印
     */
    public static void addTextMark(String srcPath, String toPath) {
        File file = getFile(srcPath);
        //添加水印,返回处理后的图片对象
        BufferedImage bufferedImage = addWaterMark(file, 0);
        //将处理后的图片输出到指定路径
        outPutImage(file.getName(), toPath, bufferedImage);
    }


    /**
     * 图片灰度操作
     *
     * @param srcPath 处理的图片对象
     * @param toPath  目标文件地址
     * @throws Exception
     */
    public static void imageGray(String srcPath, String toPath) {
        try {
            File file = getFile(srcPath);
            BufferedImage bufferedImage = ImageIO.read(file);
            ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
            ColorConvertOp op = new ColorConvertOp(cs, null);
            bufferedImage = op.filter(bufferedImage, null);
            //将处理后的图片输出到指定路径
            outPutImage(file.getName(), toPath, bufferedImage);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(StringUtils.isBlank(e.getMessage()) ? "图片灰白化异常" : e.getMessage());
        }
    }

    /**
     * 对图片裁剪,并把裁剪新图片保存
     *
     * @param srcPath 读取源图片路径
     * @param toPath  写入图片路径
     * @param x       剪切起始点x坐标
     * @param y       剪切起始点y坐标
     * @param width   剪切宽度
     * @param height  剪切高度
     * @throws IOException
     */
    public static void cropImage(String srcPath, String toPath,
                                 int x, int y, int width, int height) throws IOException {
        try {
            File file = getFile(srcPath);
            ImageInputStream iis = ImageIO.createImageInputStream(new FileInputStream(file));
            Iterator it = ImageIO.getImageReadersByFormatName(suffix(file));
            ImageReader reader = (ImageReader) it.next();
            //获取图片流
            reader.setInput(iis, true);
            ImageReadParam param = reader.getDefaultReadParam();
            //定义一个矩形
            Rectangle rect = new Rectangle(x, y, width, height);
            //提供一个 BufferedImage,将其用作解码像素数据的目标。
            param.setSourceRegion(rect);
            BufferedImage bufferedImage = reader.read(0, param);
            //将处理后的图片输出到指定路径
            outPutImage(file.getName(), toPath, bufferedImage);
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        }
    }


    /**
     * 按倍率缩小图片
     *
     * @param srcPath     读取图片路径
     * @param toPath      写入图片路径
     * @param widthRatio  宽度缩小比例
     * @param heightRatio 高度缩小比例
     * @throws RuntimeException
     */
    public static void reduceImageByRatio(String srcPath, String toPath, int widthRatio, int heightRatio) {
        try {
            File file = getFile(srcPath);
            // 构造Image对象
            BufferedImage srcBuffer = ImageIO.read(file);
            // 按比例缩减图像
            BufferedImage imageBuffer = imageShrinkRatio(srcBuffer, widthRatio, heightRatio, true);
            //将处理后的图片输出到指定路径
            outPutImage(file.getName(), toPath, imageBuffer);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(StringUtils.isBlank(e.getMessage()) ? "按倍率缩小图片异常" : e.getMessage());
        }
    }


    /**
     * 按倍率放大图片
     *
     * @param srcPath     读取图形路径
     * @param toPath      写入图片路径
     * @param widthRatio  宽度放大比例
     * @param heightRatio 高度放大比例
     * @throws IOException
     */
    public static void enlargementImageByRatio(String srcPath, String toPath, int widthRatio, int heightRatio) throws IOException {
        try {
            File file = getFile(srcPath);
            //读入文件
            String prefix = suffix(file);
            // 构造Image对象
            BufferedImage srcBuffer = ImageIO.read(file);
            // 按比例缩减图像
            BufferedImage imageBuffer = imageShrinkRatio(srcBuffer, widthRatio, heightRatio, false);
            //将处理后的图片输出到指定路径
            outPutImage(file.getName(), toPath, imageBuffer);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(StringUtils.isBlank(e.getMessage()) ? "按倍率放大图片异常" : e.getMessage());
        }
    }


    /**
     * 获取文件后缀名
     *
     * @param file
     * @return
     */
    private final static String suffix(File file) {
        String fileName = file.getName();
        return fileName.substring(fileName.indexOf(".") + 1);
    }

    /**
     * 按照给点的比例放大或者缩小图像
     * 当比例小于等于0时不发生任何变化
     *
     * @param originalImage 图像数据
     * @param withdRatio    宽度缩减比例
     * @param heightRatio   高度缩减比例
     * @param isShrink      是否缩小
     * @return 图像数据
     */
    private static BufferedImage imageShrinkRatio(BufferedImage originalImage, Integer withdRatio, Integer heightRatio, boolean isShrink) {
        if (withdRatio <= 0) {
            withdRatio = 1;
        }
        if (heightRatio <= 0) {
            heightRatio = 1;
        }
        int width = 0;
        int height = 0;
        if (isShrink) {
            width = originalImage.getWidth() / withdRatio;
            height = originalImage.getHeight() / heightRatio;
        } else {
            width = originalImage.getWidth() * withdRatio;
            height = originalImage.getHeight() * heightRatio;
        }
        BufferedImage newImage = new BufferedImage(width, height, originalImage.getType());
        Graphics g = newImage.getGraphics();
        g.drawImage(originalImage, 0, 0, width, height, null);
        g.dispose();
        return newImage;
    }


    /**
     * 添加图片水印操作,返回BufferedImage对象
     *
     * @param file     File实例
     * @param markType 0文字水印, 1图片水印
     * @return 处理后的图片对象
     * @throws Exception
     */
    private static BufferedImage addWaterMark(File file, int markType) {
        BufferedImage targetImage = null;
        try {
            // 加载待处理图片文件
            Image img = ImageIO.read(file);
            int width = img.getWidth(null);
            int height = img.getHeight(null);

            //创建目标图象文件
            targetImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics2D graphics2D = targetImage.createGraphics();
            //使用绘图工具对象,将原图绘制到缓存图片对象
            graphics2D.drawImage(img, 0, 0, img.getWidth(null), img.getHeight(null), null);

            graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA));
            graphics2D.rotate(Math.toRadians(RADIANS), targetImage.getHeight() / 2, targetImage.getHeight() / 2);//图层以中心为基点,转30度的弧度。

            //0文字水印, 1图片水印
            if (0 == markType) {
                graphics2D.setFont(new Font(FONT_NAME, FONT_STYLE, FONT_SIZE));
                graphics2D.setColor(FONT_COLOR);

                //如果没有指定水印位置,默认是平铺,
                if (X == 0 || Y == 0) {
                    //S1-获取文字水印的宽、高
                    int width1 = FONT_SIZE * getTextLength(MARK_TEXT);
                    int height1 = FONT_SIZE;
                    int x = -width / 2;
                    int y = -height / 2;

                    while (x < width * 1.6) {
                        y = -height / 2;
                        while (y < height * 1.6) {
                            graphics2D.drawString(MARK_TEXT, x, y);
                            y += height1 + MARGIN_ALL;
                        }
                        x += width1 + MARGIN_ALL;
                    }
                } else {
                    graphics2D.drawString(MARK_TEXT, X, Y);
                }
            } else if (1 == markType) {
                // 加载水印图片文件
                Image markImg = ImageIO.read(getFile(LOGO_IMAGE_URL));
                if (X == 0 || Y == 0) {
                    int x = -width / 2;
                    int y = -height / 2;
                    while (x < width * 1.6) {
                        y = -height / 2;
                        while (y < height * 1.6) {
                            graphics2D.drawImage(markImg, x, y, null);
                            y += markImg.getHeight(null) + MARGIN_ALL;
                        }
                        x += markImg.getWidth(null) + MARGIN_ALL;
                    }
                } else {
                    graphics2D.drawImage(markImg, X, Y, null);
                }
            }
            graphics2D.dispose();
        } catch (Exception e) {
            throw new RuntimeException(StringUtils.isBlank(e.getMessage()) ? "添加水印操作异常" : e.getMessage());
        }
        return targetImage;
    }


    /**
     * @param fileName       文件名称
     * @param realUploadPath 输出路径
     * @param bufferedImage  处理后的图片对象
     * @Description 将处理后的图片输出到指定路径
     */
    private static void outPutImage(String fileName, String realUploadPath, BufferedImage bufferedImage) {
        OutputStream os = null;
        try {
            os = new FileOutputStream(getFile(realUploadPath) + File.separator + fileName);
            // 创建图像编码工具类
            JPEGImageEncoder jpegImageEncoder = JPEGCodec.createJPEGEncoder(os);
            // 使用图片编码工具类,输出缓存图像到模板图片文件
            jpegImageEncoder.encode(bufferedImage);
        } catch (Exception e) {
            throw new RuntimeException(StringUtils.isBlank(e.getMessage()) ? "图片输出异常" : e.getMessage());
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    log.info(e.getMessage());
                }
            }
        }
    }

    /**
     * @param resourceLocation 路径
     * @return 新的 File实例
     * @Description 通过将给定的路径名的字符串转换成一个抽象路径名创建一个新的 File实例。
     */
    private static File getFile(String resourceLocation) {
        if (StringUtils.isBlank(resourceLocation)) {
            throw new RuntimeException("Resource location must not be null");
        }
        if (resourceLocation.startsWith("classpath:")) {
            String path = resourceLocation.substring("classpath:".length());
            String description = "class path resource [" + path + "]";
            ClassLoader cl = getDefaultClassLoader();
            URL url = cl != null ? cl.getResource(path) : ClassLoader.getSystemResource(path);
            if (url == null) {
                throw new RuntimeException(description + " cannot be resolved to absolute file path because it does not exist");
            } else {
                return getFile(url, description);
            }
        } else {
            try {
                return getFile(new URL(resourceLocation), "URL");
            } catch (MalformedURLException var5) {
                return new File(resourceLocation);
            }
        }
    }

    /**
     * @param resourceUrl 路径
     * @param description 操作描述
     * @return 新的 File实例
     * @Description 通过将给定的URL到一个抽象路径名创建一个新的 File实例。
     */
    private static File getFile(URL resourceUrl, String description) {
        if (resourceUrl == null) {
            throw new RuntimeException("Resource URL must not be null");
        }
        if (!"file".equals(resourceUrl.getProtocol())) {
            throw new RuntimeException(description + " cannot be resolved to absolute file path because it does not reside in the file system: " + resourceUrl);
        } else {
            return new File(toURI(resourceUrl).getSchemeSpecificPart());
        }
    }


    private static ClassLoader getDefaultClassLoader() {
        ClassLoader cl = null;

        try {
            cl = Thread.currentThread().getContextClassLoader();
        } catch (Throwable var3) {
        }

        if (cl == null) {
            cl = ClassUtils.class.getClassLoader();
            if (cl == null) {
                try {
                    cl = ClassLoader.getSystemClassLoader();
                } catch (Throwable var2) {
                }
            }
        }
        return cl;
    }

    private static int getTextLength(String text) {
        int length = text.length();
        for (int i = 0; i < text.length(); i++) {
            String s = String.valueOf(text.charAt(i));
            if (s.getBytes().length > 1) {
                length++;
            }
        }
        length = length % 2 == 0 ? length / 2 : length / 2 + 1;
        return length;
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值