Java 图片加水印

自适应文字长度水印 

import cn.hutool.core.io.IoUtil;
import com.shinkeer.common.utils.DateUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Random;
import java.util.stream.IntStream;

/**
 * @program: 工具箱
 * @description 水印
 * @date 2023/6/6
 */
public class ImgWatermarkUtil {
    public static void main(String[] args) throws Exception {
        //imgWatermarkLocal(""D:\\公司文件\\图片.png","D:\\公司文件\\图片1.png","这是水印");
        InputStream inputStream = new FileInputStream("D:\\公司文件\\图片1.png");
        InputStream inputStreamFile = imgWatermarkInt(inputStream, "yph", "这是水印BXCVVBADSSF","png");
        saveFile(inputStreamFile,"D:\\公司文件\\图片" + DateUtils.dateTimeNow() + ".png");

    }

    public static void testFile(InputStream inputStream) throws Exception {
        InputStream inputStreamFile = imgWatermarkInt(inputStream, "这是水印", "png");
        saveFile(inputStreamFile,"D:\\公司文件\\图片" + DateUtils.dateTimeNow() + ".png");
    }

    /**
     * 保存本地
     * @param inputStream 输入流
     * @param filePath 保存地址
     * @throws IOException
     */
    public static void saveFile(InputStream inputStream, String filePath) throws IOException {
        try (OutputStream outputStream = new FileOutputStream(filePath)) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        }
    }


    /**
     * 给图片添加水印
     *
     * @param inputFile     原文件路径+名称
     * @param outputFile    添加水印后输出文件保存的路径+名称
     * @param waterMarkName 添加水印的内容
     */
    public static void imgWatermarkLocal(String inputFile, String outputFile, String waterMarkName) {
        try {
            BufferedImage img = ImageIO.read(new File(inputFile));
            int width = img.getWidth();
            int height = img.getHeight();

            int fontSize = (width + height) / 80;

            Graphics2D g = img.createGraphics();
            g.setFont(new Font("黑体", Font.PLAIN, fontSize));
            g.setColor(new Color(0, 0, 0, 30));
            g.rotate(0.2);

            // 间隔
            int split = fontSize * 2;
            // 文字占用的宽度
            int xWidth = getStrWidth(waterMarkName, fontSize);
            // x,y可以绘制的数量,多加一个补充空白
            int xCanNum = width / xWidth + 1;
            int yCanNum = height / fontSize + 1;
            for (int i = 1; i <= yCanNum; i++) {
                int y = fontSize * i + split * i;
                for (int j = 0; j < xCanNum; j++) {
                    int x = xWidth * j + split * j;
                    g.drawString(waterMarkName, x, y - (fontSize + split) * j);
                }
            }
            g.dispose();
            ImageIO.write(img, "png", new File(outputFile));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 图片加水印
     *
     * @param inputStream   输入流
     * @param waterMarkName 添加水印的内容
     * @return OutputStream 输出流
     */
    public static OutputStream imgWatermarkOut(InputStream inputStream, String waterMarkName) {
        try {
            BufferedImage img = ImageIO.read(inputStream);

            int width = img.getWidth();
            int height = img.getHeight();

            int fontSize = (width + height) / 80;

            Graphics2D g = img.createGraphics();
            g.setFont(new Font("黑体", Font.PLAIN, fontSize));
            g.setColor(new Color(0, 0, 0, 30));
            g.rotate(0.2);

            // 间隔
            int split = fontSize * 2;
            // 文字占用的宽度
            int xWidth = getStrWidth(waterMarkName, fontSize);
            // x,y可以绘制的数量,多加一个补充空白
            int xCanNum = width / xWidth + 1;
            int yCanNum = height / fontSize + 1;
            for (int i = 1; i <= yCanNum; i++) {
                int y = fontSize * i + split * i;
                for (int j = 0; j < xCanNum; j++) {
                    int x = xWidth * j + split * j;
                    g.drawString(waterMarkName, x, y - (fontSize + split) * j);
                }
            }
            g.dispose();
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ImageIO.write(img, "png", outputStream);
            return outputStream;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 图片加水印
     *
     * @param inputStream   输入流
     * @param waterMarkName 添加水印的内容
     * @param fileSuffix    扩展名
     * @return InputStream 新的输入流
     */
    public static InputStream imgWatermarkInt(InputStream inputStream, String waterMarkName, String fileSuffix) {
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            BufferedImage originalImage = ImageIO.read(inputStream);
            int width = originalImage.getWidth();
            int height = originalImage.getHeight();

            if (width <= 0 || height <= 0) {
                throw new IllegalArgumentException("Invalid image size.");
            }

            if (waterMarkName == null || waterMarkName.trim().isEmpty()) {
                throw new IllegalArgumentException("Watermark name cannot be empty.");
            }

            // 创建新的BufferedImage对象,并复制原始图像
            BufferedImage newImage = new BufferedImage(width, height, originalImage.getType());
            Graphics2D g = newImage.createGraphics();
            g.drawImage(originalImage, 0, 0, null);

            int fontSize = (width + height) / 80;
            g.setFont(new Font("黑体", Font.PLAIN, fontSize));
            g.setColor(new Color(0, 0, 0, 30));
            g.rotate(0.2);

            // 间隔
            int split = fontSize * 2;
            // 文字占用的宽度
            int xWidth = getStrWidth(waterMarkName, fontSize);
            // x,y可以绘制的数量,多加一个补充空白
            int xCanNum = width / xWidth + 1;
            int yCanNum = height / fontSize + 1;
            for (int i = 1; i <= yCanNum; i++) {
                int y = fontSize * i + split * i;
                for (int j = 0; j < xCanNum; j++) {
                    int x = xWidth * j + split * j;
                    g.drawString(waterMarkName, x, y - (fontSize + split) * j);
                }
            }
            g.dispose();

            // 将新的BufferedImage对象写入ByteArrayOutputStream中
            ImageIO.write(newImage, fileSuffix, outputStream);

            // 返回新的InputStream对象
            return new ByteArrayInputStream(outputStream.toByteArray());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 图片加水印
     *
     * @param inputStream      输入流
     * @param waterMarkNameOne 添加水印的内容
     * @param waterMarkNameTwo 添加水印的内容
     * @param fileSuffix       扩展名
     * @return InputStream 输入流
     */
    public static InputStream imgWatermarkInt(InputStream inputStream, String waterMarkNameOne, String waterMarkNameTwo, String fileSuffix) {
        try {

            BufferedImage img = ImageIO.read(inputStream);

            int width = img.getWidth();
            int height = img.getHeight();

            int fontSize = (width + height) / 80;


            // 间隔
            int split = fontSize * 2;
            // 文字占用的宽度
            int xWidth1 = getStrWidth(waterMarkNameOne, fontSize);
            int xWidth2 = getStrWidth(waterMarkNameTwo, fontSize);
            int xWidth = Math.max(xWidth1,xWidth2);
            // x,y可以绘制的数量,多加一个补充空白
            int xCanNum = width / xWidth + 1;
            int yCanNum = height / fontSize + 1;
            for (int i = 1; i <= yCanNum; i++) {
                int y = fontSize * i + split * i;
                String waterMarkName = "";
                for (int j = 0; j < xCanNum; j++) {
                    Graphics2D g = img.createGraphics();
                    g.setFont(new Font("黑体", Font.PLAIN, fontSize));
                    g.setColor(new Color(0, 0, 0, 30));
                    g.rotate(0.2);
                    int x = xWidth * j + split * j;
                    //随机水印
                    if (j % 2 == 0) {
                        waterMarkName = waterMarkNameOne;
                    } else {
                        waterMarkName = waterMarkNameTwo;
                    }
                    g.drawString(waterMarkName, x, y - (fontSize + split) * j);
                    g.dispose();
                }
            }


            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ImageIO.write(img, fileSuffix, outputStream);

            return new ByteArrayInputStream(outputStream.toByteArray());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 获取字符串占用的宽度
     * <br>
     *
     * @param str      字符串
     * @param fontSize 文字大小
     * @return 字符串占用的宽度
     */
    public static int getStrWidth(String str, int fontSize) {
        char[] chars = str.toCharArray();
        int fontSize2 = fontSize / 2;

        int width = 0;

        for (char c : chars) {
            int len = String.valueOf(c).getBytes().length;
            // 汉字为3,其余1
            // 可能还有一些特殊字符占用2等等,统统计为汉字
            if (len != 1) {
                width += fontSize;
            } else {
                width += fontSize2;
            }
        }
        return width == 0 ? 1 : width;
    }

    /**
     * 图片加水印
     *
     * @param inputStream   输入流
     * @param waterMarkName 添加水印的内容
     * @param fileSuffix    扩展名
     * @return InputStream 新的输入流
     */
    public static InputStream imgWatermarkInt2(InputStream inputStream, String waterMarkName, String fileSuffix) {
        try (InputStream in = inputStream; ByteArrayOutputStream out = new ByteArrayOutputStream()) {
            BufferedImage originalImage = ImageIO.read(in);
            int width = originalImage.getWidth();
            int height = originalImage.getHeight();

            if(width <= 0 || height <= 0){
                throw new IllegalArgumentException("Invalid image size.");
            }

            if(waterMarkName == null || waterMarkName.trim().isEmpty()){
                throw new IllegalArgumentException("Watermark name cannot be empty.");
            }

            // 创建新的BufferedImage对象,并复制原始图像
            BufferedImage newImage = new BufferedImage(width, height, originalImage.getType());
            Graphics2D g = newImage.createGraphics();
            g.drawImage(originalImage, 0, 0, null);

            int fontSize = (width + height) / 80;
            g.setFont(new Font("黑体", Font.PLAIN, fontSize));
            g.setColor(new Color(0, 0, 0, 30));
            g.rotate(0.2);

            // 间隔
            int split = fontSize * 2;
            // 文字占用的宽度
            int xWidth = getStrWidth(waterMarkName, fontSize);
            // x,y可以绘制的数量,多加一个补充空白
            int xCanNum = width / xWidth + 1;
            int yCanNum = height / fontSize + 1;

            // 使用流式API进行操作
            IntStream.range(1, yCanNum + 1)
                    .forEach(i -> {
                        int y = fontSize * i + split * i;
                        IntStream.range(0, xCanNum)
                                .forEach(j -> {
                                    int x = xWidth * j + split * j;
                                    g.drawString(waterMarkName, x, y - (fontSize + split) * j);
                                });
                    });

            g.dispose();

            // 将新的BufferedImage对象写入ByteArrayOutputStream中
            ImageIO.write(newImage, fileSuffix, out);

            // 返回新的InputStream对象
            return new ByteArrayInputStream(out.toByteArray());

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}

### Java 实现给图片添加水印Java中,可以利用`BufferedImage`类来处理图像并为其添加水印。下面是一个完整的例子展示如何通过代码实现这一功能。 #### 添加文字水印图片上 ```java import java.awt.*; import java.awt.image.BufferedImage; import javax.imageio.ImageIO; import java.io.File; public class WaterMarkUtil { public static void addTextWatermark(String srcImagePath, String destImagePath, String text) { try { File file = new File(srcImagePath); BufferedImage image = ImageIO.read(file); Graphics2D g2d = (Graphics2D) image.getGraphics(); AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f); // 设置透明度 g2d.setComposite(ac); Font font = new Font("Arial", Font.BOLD, 48); // 定义字体样式 g2d.setFont(font); g2d.setColor(Color.RED); // 文字颜色 int width = image.getWidth(null); int height = image.getHeight(null); // 计算位置使文本居中显示 FontMetrics fm = g2d.getFontMetrics(font); int strWidth = fm.stringWidth(text); int x = (width - strWidth) / 2; int y = height - 50; g2d.drawString(text, x, y); g2d.dispose(); ImageIO.write(image, "jpg", new File(destImagePath)); } catch (Exception e) { System.out.println(e.getMessage()); } } } ``` 此段程序读取源文件路径中的原始图片,在其底部中央绘制指定的文字作为水印,并保存至目标文件路径下[^1]。 #### 给图片添加另一个图片形式的水印 对于想要叠另一张较小尺寸的小图作为水印的情况,则可以通过调整坐标以及控制小图大小来进行操作: ```java public static void addImageWatermark(String srcImagePath, String watermarkPath, String destImagePath){ try{ BufferedImage sourceImg = ImageIO.read(new File(srcImagePath)); BufferedImage waterImg = ImageIO.read(new File(watermarkPath)); int w = sourceImg.getWidth(); int h = sourceImg.getHeight(); Graphics2D g = sourceImg.createGraphics(); float alpha = 0.7F; // 控制不透明度 Composite comp = AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,alpha); g.setComposite(comp); int wmW = waterImg.getWidth()/3; int wmH = waterImg.getHeight()/3; // 缩放后的宽度高度保持比例不变 AffineTransform at = new AffineTransform(); at.setToScale((double)wmW/waterImg.getWidth(), (double)wmH/waterImg.getHeight()); g.drawImage(sourceImg, null, 0, 0); g.drawImage(waterImg,at,w-wmW,h-wmH,null); g.dispose(); ImageIO.write(sourceImg,"JPEG",new File(destImagePath)); }catch(Exception ex){ ex.printStackTrace(); } } ``` 这段代码实现了载两张不同路径下的图片对象,其中一张被当作背景大图而另外一张则充当水印图案;之后按照一定算法计算出合适的放置区域并将它们合成在一起形成最终带有所需效果的新图片[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值