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工具