Java之Graphics2D图片生成水印
目录
一、介绍
二、效果图
三、代码
四、优化方向
五、参考链接
一、介绍
百度百科:Graphics2D ,Graphics 类,提供了对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制
不止通过JDK提供的工具类,还可以使用第三方的Thumbnailator工具,进行添加水印、制作缩略图等功能
二、效果图
1、生成水印前:
![Image 1][]
2、生成水印后:
![Image 1][]
三、代码
public class WaterMarkUtil {
private final static String[] IMAGE_TYPE = {"PNG","JPEG","JPG", "BMP", "GIF"};
private final static int HEADER_SIZE = 4;
public static byte[] getImageWithWaterMark(InputStream inputStream, String waterMarkContent) throws Exception {
if(null == inputStream){
throw new Exception("输入流不能为空");
}
if(null == waterMarkContent || waterMarkContent.isEmpty()){
throw new Exception("水印内容不能为空");
}
// 封装为BufferedInputStream,用于流文件类型读取后的重置
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
// 标记读取的文件类型长度
bufferedInputStream.mark(HEADER_SIZE);
// 获取文件类型
String fileType = getFileType(bufferedInputStream);
// 重置流到开始位置
bufferedInputStream.reset();
// 判断是否图片,否则结束处理
boolean isImage = matchImageType(fileType);
if(!isImage){
throw new Exception("文件类型非图片类型,支持:png、jpeg、jpg、bmp、gif,当前文件类型:" + fileType);
}
BufferedImage targetImg = ImageIO.read(bufferedInputStream);
int height = targetImg.getHeight();
int width = targetImg.getWidth();
//-------------------------文字水印 start----------------------------
BufferedImage waterMarkImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 创建画笔
Graphics2D graphics2D = waterMarkImage.createGraphics();
// 绘制原始图片
graphics2D.drawImage(targetImg, 0, 0, width, height, null);
// 设置水印颜色
graphics2D.setColor(new Color(255, 255, 255, 50));
double scale = 1.0;
if(width < height){
scale = (double) width / height;
}
int fontSize = (int) Math.ceil((double) (height / 25) * scale);
// 设置字体 画笔字体样式为微软雅黑,加粗,文字大小按比例给
graphics2D.setFont(new Font("微软雅黑", Font.BOLD, fontSize));
// 水印旋转度
graphics2D.rotate(Math.toRadians(-25), (double) width / 2, (double) height / 2);
int x = -width * 3;
int y;
// 计算水印文字的宽度
FontMetrics fontMetrics = graphics2D.getFontMetrics();
int watermarkWidth = fontMetrics.stringWidth(waterMarkContent);
// 水印横向间隔
int positionWidth = (int)(width * 0.15);
// 水印竖向间隔
int positionHeight = (int)(height * 0.15);
while (x < width * 3) {
y = -height * 3;
while (y < height * 3) {
graphics2D.drawString(waterMarkContent, x, y);
y += fontSize + positionWidth;
}
x += watermarkWidth + positionHeight;
}
graphics2D.dispose();
//-------------------------文字水印 end----------------------------
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write(waterMarkImage, fileType, byteArrayOutputStream);
return byteArrayOutputStream.toByteArray();
}
private static boolean matchImageType(String fileType){
if(null == fileType || fileType.isEmpty()){
return false;
}
for (String type : IMAGE_TYPE) {
if (fileType.equalsIgnoreCase(type)) {
return true;
}
}
return false;
}
private static String getFileType(InputStream is){
String fileType = null;
String fileHeader;
byte[] temp = new byte[HEADER_SIZE];
try {
is.read(temp, 0, HEADER_SIZE);
// 将读取到的字节数组转为十六进制字符串,,方法来自apache的commons-codec包
fileHeader = Hex.encodeHexString(temp).toUpperCase();
// 以下罗列几种类型,更多自行拓展
if (fileHeader.contains("504B0304")) {
fileType = "xlsx";
} else if (fileHeader.contains("FFD8FF")) {
fileType = "jpg";
} else if (fileHeader.contains("89504E47")) {
fileType = "png";
} else if (fileHeader.contains("47494638")) {
fileType = "gif";
} else if (fileHeader.contains("25504446")) {
fileType = "pdf";
} else if (fileHeader.contains("424D")) {
fileType = "bmp";
} else {
fileType = null;
}
} catch (Exception e) {
e.printStackTrace();
}
return fileType;
}
}
四、优化方向
目前这个版本的水印生成还是有局限性的,比如:图片太小、水印内容太长之类的问题,会导致生成的效果有问题,所有如果你遇到这种情况,可以通过以下的方面进行优化:
1、水印文字大小按照图片等比例进行控制
2、限制水印文字大小,水印宽度不得超过图片宽度的百分之多少,通过水印宽度反出水印文字字数过多
3、限制图文长度与宽度,过小就不生成,或者只生成一个水印之类的
五、参考链接
Java实现给图片加单个、多个文字水印_java添加多个水印_斯内克喜欢吃益达的博客-CSDN博客
java实现给图片添加水印(文字水印或图片水印)_12程序猿的博客-CSDN博客
[Image 1]:
还没有评论,来说两句吧...