java图片水印打在图片上

Posted 500年

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java图片水印打在图片上相关的知识,希望对你有一定的参考价值。

java图片水印打在图片上

说明

当前工具类支持:
1、根据图片大小和水印图片大小动态适配水印效果;
2、水印位置可自由选择:左上、正上、右上、正左、正中、正右、左下、正下、右下;
3、可根据实际业务调整水印透明度;

实现代码

WaterMarkUtil.java

import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;

import javax.imageio.ImageIO;

public class WaterMarkUtil {

	private static final int WATER_MARK_X_COORDINATE = 2;// 水印X坐标位置下标
	private static final int WATER_MARK_Y_COORDINATE = 3;// 水印Y坐标位置下标
	private static final int WATER_MARK_WIDTH = 0;// 水印宽下标
	private static final int WATER_MARK_HEIGHT = 1;// 水印高下标

	public static void main(String[] args) throws Exception {
		FileInputStream is = new FileInputStream("D:/tmp/cc2.jpg");
		FileInputStream mark = new FileInputStream("D:/tmp/背景2.jpg");
		OutputStream out = new FileOutputStream("D:/tmp/cc2-2.jpg");
		mark(is, mark, 50, 0.9f, WatermarkLocation.LOWER, out);

	}

	/**
	 * @param input             原图
	 * @param markImg           水印
	 * @param size              水印大小(0-100) 百分比分子
	 * @param clarity           透明度
	 * @param watermarkLocation 位置
	 * @param outImgStream      输出
	 * @return 结果
	 */
	public static boolean mark(FileInputStream input, FileInputStream markImg, int size, float clarity,
			WatermarkLocation watermarkLocation, OutputStream outImgStream) {
		clarity = clarity > 1 ? 1F : clarity;
		clarity = clarity < 0 ? 0.5F : clarity;
		BufferedImage img = null;
		BufferedImage mark = null;
		try {
			img = ImageIO.read(input);// 原图
			mark = ImageIO.read(markImg);// 水印
			BufferedImage bufImg = new BufferedImage(img.getWidth(null), img.getHeight(null),
					BufferedImage.TYPE_INT_RGB);
			int[] locationAndArea = new int[] { mark.getWidth(), mark.getHeight(), img.getWidth(), img.getHeight() };
			calculateLocationAndArea(size, watermarkLocation, locationAndArea);
			markImage(bufImg, img, mark, locationAndArea, clarity);
			ImageIO.write(bufImg, "jpg", outImgStream);
			outImgStream.flush();
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (outImgStream != null)
					outImgStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				if (markImg != null)
					markImg.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				if (input != null)
					input.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return false;
	}

	private static void markImage(BufferedImage bufImg, Image img, Image markImg, int[] locationAndArea,
			float clarity) {
		Graphics2D g = bufImg.createGraphics();
		g.drawImage(img, 0, 0, bufImg.getWidth(), bufImg.getHeight(), null);// 原图写入
		g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, clarity));
		g.drawImage(markImg, locationAndArea[WATER_MARK_X_COORDINATE], locationAndArea[WATER_MARK_Y_COORDINATE],
				locationAndArea[WATER_MARK_WIDTH], locationAndArea[WATER_MARK_HEIGHT], null);
		g.dispose();
	}

	private static void calculateLocationAndArea(int waterMarkRadio, WatermarkLocation watermarkLocation, int[] args) {
		int widthTemp = args[2] * waterMarkRadio / 100;
		int heightTemp = args[3] * waterMarkRadio / 100;
		boolean isExpand = calculateExpandingOrShrinking(widthTemp, heightTemp, args);
		calculate(args, isExpand, widthTemp, heightTemp, watermarkLocation);
	}

	private static void calculate(int[] args, boolean isExpand, int widthTemp, int heightTemp,
			WatermarkLocation watermarkLocation) {
		float maxTemp = Math.max(widthTemp, heightTemp);
		float maxWater = Math.max(args[0], args[1]);
		float minTemp = Math.min(widthTemp, heightTemp);
		float minWater = Math.min(args[0], args[1]);
		if (isExpand) {
			float avgRadio = (maxTemp / maxWater + minTemp / minWater) / 2;
			args[0] = new BigDecimal(args[0] * avgRadio).setScale(0, RoundingMode.HALF_UP).intValue();
			args[1] = new BigDecimal(args[1] * avgRadio).setScale(0, RoundingMode.HALF_UP).intValue();
		} else {
			float avgRadio = (maxWater / maxTemp + minWater / minTemp) / 2;
			args[0] = new BigDecimal(args[0] / avgRadio).setScale(0, RoundingMode.HALF_UP).intValue();
			args[1] = new BigDecimal(args[1] / avgRadio).setScale(0, RoundingMode.HALF_UP).intValue();
		}
		switch (watermarkLocation) {
		case UPPER_LEFT:
			args[2] = 0;
			args[3] = 0;
			break;
		case LEFT:
			args[2] = 0;
			args[3] = (args[3] - args[1]) / 2;
			break;
		case LOWER_LEFT:
			args[2] = 0;
			args[3] -= args[1];
			break;
		case UPPER:
			args[2] = (args[2] - args[0]) / 2;
			args[3] = 0;
			break;
		case MIDDLE:
			args[2] = (args[2] - args[0]) / 2;
			args[3] = (args[3] - args[1]) / 2;
			break;
		case LOWER:
			args[2] = (args[2] - args[0]) / 2;
			args[3] -= args[1];
			break;
		case UPPER_RIGHT:
			args[2] -= args[0];
			args[3] = 0;
			break;
		case RIGHT:
			args[2] -= args[0];
			args[3] = (args[3] - args[1]) / 2;
			break;
		case LOWER_RIGHT:
			args[2] -= args[0];
			args[3] -= args[1];
			break;
		default:
			break;
		}
	}

	/**
	 * 判断是扩大还是缩小
	 *
	 * @param widthTemp  widthTemp
	 * @param heightTemp heightTemp
	 * @param args       args
	 * @return true 扩大,false 缩小
	 */
	private static boolean calculateExpandingOrShrinking(int widthTemp, int heightTemp, int[] args) {
		int arg0 = Math.max(widthTemp, heightTemp) - Math.max(args[0], args[1]);
		int arg1 = Math.min(widthTemp, heightTemp) - Math.min(args[0], args[1]);
		if (arg0 > 0) {
			if (arg1 > 0) {
				return true;
			} else {
				return Math.abs(arg0) - Math.abs(arg1) > 0;
			}
		} else {
			if (arg1 > 0) {
				return Math.abs(arg1) - Math.abs(arg0) > 0;
			} else {
				return false;
			}
		}
	}
}

WatermarkLocation.java

public enum WatermarkLocation {

	UPPER_LEFT, // 左上
	UPPER, // 正上
	UPPER_RIGHT, // 右上
	LEFT, // 正左
	MIDDLE, // 正中
	RIGHT, // 正右
	LOWER_LEFT, // 左下
	LOWER, // 正下
	LOWER_RIGHT,// 右下
}

效果图

以上是关于java图片水印打在图片上的主要内容,如果未能解决你的问题,请参考以下文章

Python 给图片加文字或logo水印(附代码) | Python工具

php使用GD库实现图片水印和缩略图——封装成类

Java-如何使用Java将图片和文字拼接在一起(并非是给图片加水印)

图片加水印 图片验证码

水印,图片验证码

水印,图片验证码