如何实现照片添加水印?

284 阅读3分钟

如何实现为一个照片添加水印??

工程中是讲究的前后端分离,前端可以上传的是一张或者多张照片,如图所示:

添加水印.png

JAVA代码具体实现

public class AddPhotoWaterMark {
    // 调用阿里云服务
    @Autowired
    public static AliyunOssService aliyunOssService;

    //日志
    private static final Logger logger = LoggerFactory.getLogger("pay");
// 传入参数是url 以及水印的信息
    public static BufferedImage mark(String srcImgPath, String address, String time, String name) throws IOException {
        try {
            // 读取原图片信息 这里是图片修改的工具方法
            Image srcImg = ImageIO.read(getImageStream(srcImgPath));
            int srcImgWidth = srcImg.getWidth(null);
            int srcImgHeight = srcImg.getHeight(null);

            // 加水印
            BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
            // Graphics2D 默认的渲染对象
            Graphics2D g = bufImg.createGraphics();
            g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);
            Font font = new Font("宋体", Font.PLAIN, (int) (srcImgWidth * 0.03));
            g.setColor(Color.WHITE); // 设置水印的颜色
            g.setFont(font);

            String str = address;
			// 水印地址的大小如果大于照片宽度则另起一行(有bug 只能起两行如果长度过大字体过小则超出照片长度的字体显示不出来)
            if (getWatermarkLength(str, g) > (srcImgWidth - (srcImgWidth * 0.1))) {
                Long v = (long) ((srcImgWidth - srcImgWidth * 0.1) / (int) (srcImgWidth * 0.03));

                g.drawString(name, (float) (srcImgWidth * 0.05), (float) ((srcImgHeight * 0.96 - srcImgWidth * 0.03 * 4)));
                g.drawString(time, (float) (srcImgWidth * 0.05), (float) (srcImgHeight * 0.97 - srcImgWidth * 0.03 * 3));
                g.drawString(str.substring(0, Math.toIntExact(v)), (float) (srcImgWidth * 0.05), (float) (srcImgHeight * 0.98 - srcImgWidth * 0.03 * 2));
                g.drawString(str.substring(Math.toIntExact(v)), (float) (srcImgWidth * 0.05), (float) (srcImgHeight * 0.98 - srcImgWidth * 0.03));
            } else {

                g.drawString(name, (float) (srcImgWidth * 0.05), (float) ((srcImgHeight * 0.96 - srcImgWidth * 0.03 * 3)));
                g.drawString(time, (float) (srcImgWidth * 0.05), (float) (srcImgHeight * 0.97 - srcImgWidth * 0.03 * 2));
                g.drawString(str, (float) (srcImgWidth * 0.05), (float) (srcImgHeight * 0.98 - srcImgWidth * 0.03));
            }
          	// 释放当前加水印操作资源
            g.dispose();
            return bufImg;
        } catch (IOException e) {
                    System.out.println("加水印异常,图片路径为:" + srcImgPath);
                    e.printStackTrace();
                }
        return null;
    }

    /**
     * 获取水印文字总长度
     *
     * @param waterMarkContent 水印的文字
     * @param g
     * @return 水印文字总长度
     */
    public static int getWatermarkLength(String waterMarkContent, Graphics2D g) {
        return g.getFontMetrics(g.getFont()).charsWidth(waterMarkContent.toCharArray(), 0, waterMarkContent.length());
    }

    /**
     * 获取网络图片流
     *
     * @param url
     * @return
     */
    private static InputStream getImageStream(String url) throws IOException {
        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setReadTimeout(5000);
            connection.setConnectTimeout(5000);
            connection.setRequestMethod("GET");
            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                InputStream inputStream = connection.getInputStream();
                return inputStream;
            }
        } catch (IOException e) {
            System.out.println("获取网络图片出现异常,图片路径为:" + url);
            e.printStackTrace();
        }
        return null;
    }
} 

第一个需求其中业务并不复杂,这个工具写的也不麻烦,主要是在于照片的逻辑校验。首先传来的照片是否需要加水印,可以查一下数据库是否存在图片信息来判断是否添加了水印。

单元测试

下面是本地数据的测试 可以自行更换:


import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

public class addMark {
    public static void main(String[] args) throws IOException {
        BufferedImage b = mark("sss","张飞","赵云","吕布");
        InputStream inputStream = bufferedImageToInputStream(b);

        // 设置数据缓冲
        byte[] bs = new byte[1024 * 2];
        // 读取到的数据长度
        int len;
        // 输出的文件流保存图片至本地
        OutputStream os = new FileOutputStream("D:\cc.jpg");
        while ((len = inputStream.read(bs)) != -1) {
            os.write(bs, 0, len);
        }
        os.close();
        inputStream.close();

    }
    /**
     * 将BufferedImage转换为InputStream
     *
     * @param image
     * @return
     */
    public static InputStream bufferedImageToInputStream(BufferedImage image) {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            ImageIO.write(image, "jpg", os);
            InputStream input = new ByteArrayInputStream(os.toByteArray());
            return input;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static BufferedImage mark(String srcImgPath, String address, String time, String name) throws IOException {
        try {
            // 读取原图片信息
            InputStream inputStream = new FileInputStream("D:\opt\aaa.jpg");
            Image srcImg = ImageIO.read(inputStream);

            int srcImgWidth = srcImg.getWidth(null);
            int srcImgHeight = srcImg.getHeight(null);

            // 加水印
            BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = bufImg.createGraphics();
            g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);
            Font font = new Font("宋体", Font.PLAIN, (int) (srcImgWidth * 0.03));
            g.setColor(Color.black); // 根据图片的背景设置水印颜色
            g.setFont(font);

            String str = address;

            if (getWatermarkLength(str, g) > (srcImgWidth - (srcImgWidth * 0.1))) {
                Long v = (long) ((srcImgWidth - srcImgWidth * 0.1) / (int) (srcImgWidth * 0.03));

                g.drawString(name, (float) (srcImgWidth * 0.05), (float) ((srcImgHeight * 0.96 - srcImgWidth * 0.03 * 4)));
                g.drawString(time, (float) (srcImgWidth * 0.05), (float) (srcImgHeight * 0.97 - srcImgWidth * 0.03 * 3));
                g.drawString(str.substring(0, Math.toIntExact(v)), (float) (srcImgWidth * 0.05), (float) (srcImgHeight * 0.98 - srcImgWidth * 0.03 * 2));
                g.drawString(str.substring(Math.toIntExact(v)), (float) (srcImgWidth * 0.05), (float) (srcImgHeight * 0.98 - srcImgWidth * 0.03));
            } else {

                g.drawString(name, (float) (srcImgWidth * 0.05), (float) ((srcImgHeight * 0.96 - srcImgWidth * 0.03 * 3)));
                g.drawString(time, (float) (srcImgWidth * 0.05), (float) (srcImgHeight * 0.97 - srcImgWidth * 0.03 * 2));
                g.drawString(str, (float) (srcImgWidth * 0.05), (float) (srcImgHeight * 0.98 - srcImgWidth * 0.03));
            }
            g.dispose();
            return bufImg;
        } catch (IOException e) {
            System.out.println("加水印异常,图片路径为:" + srcImgPath);
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取水印文字总长度
     *
     * @param waterMarkContent 水印的文字
     * @param g
     * @return 水印文字总长度
     */
    public static int getWatermarkLength(String waterMarkContent, Graphics2D g) {
        return g.getFontMetrics(g.getFont()).charsWidth(waterMarkContent.toCharArray(), 0, waterMarkContent.length());
    }

    /**
     * 获取网络图片流
     *
     * @param url
     * @return
     */
    private static InputStream getImageStream(String url) throws IOException {
        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setReadTimeout(5000);
            connection.setConnectTimeout(5000);
            connection.setRequestMethod("GET");
            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                InputStream inputStream = connection.getInputStream();
                return inputStream;
            }
        } catch (IOException e) {
            System.out.println("获取网络图片出现异常,图片路径为:" + url);
            e.printStackTrace();
        }
        return null;
    }
}