java给图片增加水印,根据图片大小自适应,右下角/斜角/平铺(代码片段)

HackShendi HackShendi     2022-12-15     770

关键词:

Hi,I’m Shendi
最近写自己的文件服务器,上传图片时需要自动增加水印,在这里记录一下



文章目录


水印就是在图片上绘画,文字水印是最常见的,比如CSDN文章里图片右下角就会有文字水印

在 Java 中,给图片添加水印一般可以分为以下几步

  1. 读取图片
  2. 获取/创建图片画板
  3. 将水印内容绘制到图片中
  4. 输出图片


效果展示

下面展示的是我所使用的水印效果

测试图片是百度拿的


原图


加上水印后

因我的要求不高,所以仅仅对角水印就可以了,可以根据自己需求绘制



读取图片

因为需要在图片上绘制,需要使用到 java.awt.image.BufferedImage 这个类

创建此类对象的方法有多种,这里只列出使用 ImageIO 将原图读取为 BufferedImage 的方式

// read 函数还可以传递输入流,例如直接使用FileInputStream -但需要自己关闭流
BufferedImage img = ImageIO.read(new File("文件地址"));


从 byte[] 读取图片

// 图片数据
byte[] imgData;
ByteArrayInputStream bInput = new ByteArrayInputStream(imgData);
BufferedImage img = ImageIO.read(bInput);


获取画板

Graphics g = img.getGraphics();

上面这种拿到的画板可以画线条圆圈文字等,但是不能旋转

需要旋转的话使用 Graphics2D

Graphics2D g = img.createGraphics();


绘制水印

绘制文字的函数

// 参数一为需要绘制的文字,参数2,3为绘制的位置
img.drawString("文字", x, y);

经过测试,在坐标 0,0 绘制的文字显示的位置是在左上角,但文字是往上显示的,如下图所示

所以如果想让文字在最左上角显示的话,y需要加上文字的大小

// 设置文字大小,参数一为字体名称,二为样式,三为大小
g.setFont(new Font("黑体", Font.PLAIN, 20));
img.drawString("Shendi", x, 20);

效果如下


根据图片大小自适应水印大小

首先需要知道如何获取图片大小,拿到BufferedImage,可以通过以下函数获取

// width宽, height高
int width = img.getWidth();
int height = img.getHeight();

拿到宽高后,实现自适应就很简单了,按比例设置文字大小即可
例如

// 这里根据自己需求操作
int fontSize = (width+height) / 40;
g.setFont(new Font("黑体", Font.PLAIN, fontSize));


右下角文字水印

上面已经实现左上角水印了,而且将图片位置拿到了,于是右下角水印就非常简单了

因为在右下角,文字是往右显示的,所以需要得到文字显示占用的宽度,经过测试

单个汉字占用宽度=文字大小
单个字母数字符号占用=文字大小 / 2

中文转bytes占3字节,字母数字只占一字节
于是封装了以下函数

/**
 * 获取字符串占用的宽度
 * <br>
 * @author Shendi <a href='tencent://AddContact/?fromId=45&fromSubId=1&subcmd=all&uin=1711680493'>QQ</a>
 * @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;

接下来将文字绘制到右下角就可以看到效果了

String str = "Shendi 砷碲";
g.setFont(new Font("黑体", Font.PLAIN, fontSize));
g.drawString(str, width - getStrWidth(str, fontSize), height);

可以给 x 往左移动一点,y往上移动一点,不要在最右下角
水印颜色一般都是透明的,设置透明度达到比较好的效果

String str = "Shendi 砷碲";
// 这里的 new Color四个参数为 rgba,值可以为 0-255, r红,g绿,b蓝,a透明度
g.setColor(new Color(0, 0, 0, 50));
g.setFont(new Font("黑体", Font.PLAIN, fontSize));
g.drawString(str, width - getStrWidth(str, fontSize) - 30, height - 30);

效果如下

换张图效果如下

完整代码如下

BufferedImage img = ImageIO.read(new File("图片位置"));
int width = img.getWidth();
int height = img.getHeight();
int fontSize = (width+height) / 40;

String str = "Shendi 砷碲";

Graphics2D g = img.createGraphics();
g.setColor(new Color(0, 0, 0, 50));
g.setFont(new Font("黑体", Font.PLAIN, fontSize));
g.drawString(str, width - getStrWidth(str, fontSize) - 30, height - 30);
g.dispose();

ImageIO.write(img, "png", new File("水印图片保存地址"));


斜角水印

右下角水印只有一个,而且所在位置很容易被p图去掉

于是我使用多个水印,简单的排列的话可以横着,竖着,但是斜着是比较好的,所以我使用了这种,也是最开始的展示效果

绘制一定数量的水印,将图片宽高按比例分成 n 份,然后循环绘制水印

BufferedImage img = ImageIO.read(new File("图片地址"));
int width = img.getWidth();
int height = img.getHeight();
// 绘制几个水印/分成几份
int num = 5;
// 每一份x,y的大小
int splitX = width / num, splitY = height / num;
// 每一份中间的位置
int centerX = splitX / 2, centerY = splitY / 2;
int fontSize = (width+height) / 40;

Graphics2D g = img.createGraphics();
g.setFont(new Font("黑体", Font.PLAIN, fontSize));
g.setColor(new Color(0, 0, 0, 30));
// 设置旋转角度,可以为0-1
g.rotate(0.2);

for (int i = 1; i <= num; i++) 
	int x = splitX * i - centerX - fontSize, y = splitY * i - centerY - fontSize;
	g.drawString("砷碲测试水印", x, y);

g.dispose();
ImageIO.write(img, "png", new File("输出位置"));

效果如下

绘制了五个水印,其中一个因为旋转而超出图片范围了,问题不大



平铺水印

暴力横竖二层循环绘制就可以了,最后加个旋转

首先需要计算横排能绘制多少个,竖排能绘制多少个

String str = "砷碲测试水印 Shendi";
// 文字占用宽度
int xWidth = getStrWidth(str, fontSize);

// x,y可以绘制的数量,多加一个补充空白
int xCanNum = width / xWidth + 1;
int yCanNum = height / fontSize + 1;

按顺序绘制,所以需要有文字间隔,这里使用文字大小作为间隔

// 间隔
int split = fontSize;

设置颜色,旋转,文字大小
接下来循环绘制即可

// i是y轴, 文字默认在y坐标上面,所以这里初始化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(str, x, y);
	

效果如下

这种效果不理想,加上旋转后,旋转点是左上角,于是要给 y 减去一定的数值将文字上拉
我这里就使用 y - (文字大小+间隔大小) * j

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(str, x, y-(fontSize+split)*j);
	

对于这种水印,文字显得太大了,将文字改小,间距拉大

int fontSize = (width+height) / 80;
int split = fontSize*2;

效果如下

完整代码如下

BufferedImage img = ImageIO.read(new File("图片文件"));
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);

String str = "砷碲测试水印 Shendi";
// 间隔
int split = fontSize*2;
// 文字占用的宽度
int xWidth = getStrWidth(str, fontSize);
// x,y可以绘制的数量,多加一个补充空白
intxCanNum = 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(str, x, y-(fontSize+split)*j);
	

g.dispose();
ImageIO.write(img, "png", new File("水印图片保存地址"));

图片水印

绘制文字水印使用 g.drawString,绘制图片水印使用 g.drawImage
例如

BufferedImage wmImg = ImageIO.read(new File("水印图"));
g.drawImage(wmImg, x, y, null);

效果如下

与文字水印绘制方法一致,但是需要计算坐标和水印图片大小等



输出图片

使用 ImageIO.write 输出

ImageIO.write(img, "png", new File("水印图片保存地址"));

其中第一个参数为图片,第二个参数为图片格式,第三个参数为保存地址

需要注意的是,第二个参数只能为 ImageIO.getReaderFormatNames() 中的项

如果是图片,最好传 png,使用jpg增加透明度可能 ImageIO.write 为 false(写入失败)



END

一键三连嘛?

java给图片增加水印,根据图片大小自适应,右下角/斜角/平铺(代码片段)

...读取图片获取画板绘制水印根据图片大小自适应水印大小右下角文字水印斜角水印平铺水印图片水印输出图片水印就是在图片上绘画,文字水印是最常见的,比如CSDN文章里图片右下角就会有文字水印在Java中,给图片... 查看详情

java图片水印打在图片上(代码片段)

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

unityugui图片自适应文字内容大小

1、(UI提示框与文字)UnityText组件需要与Image组件自适应新建如图的UI物体   如图为Image的RectTransform中设置Pivot(中心点),如果需要向上向左适应,则将中心点设置在Image的右下方,并添加ContentSizeFitter组件(放在父... 查看详情

ios--给图片添加水印(代码片段)

在iOS开发的过程中,有时需要给图片添加水印,但UIImage并没有提供直接的方法,下面我们给UIImage添加一个catgory,增加一个方法实现水印添加使用方法:通过UIImage直接调用,传入的参数分别是:要添加水印的图片,水印添加位... 查看详情

黄聪:利用imagemagick给图片加水印

...理假设把名为logo.gif的水印图标添加在原始图片(src.jpg)右下角,且水印的下边缘距原始图片10像素、右边缘距原始图片5像素。使用如下命令即可: convertsrc.jpglogo.gif-gravitysoutheast-geometry+5+10-compositedest.jpg-gravitysoutheast指叠加... 查看详情

js实现图片的大小自适应效果

需求是传过来一个图片,根据外层div的大小自动进行缩放效果。functionShowSecondImg(v){varrate,newX,newY,newW,newH=0;//表示图片相对窗口的缩放比例varimgW,imgH;varcenterW=$(window).width()-$("#alarmQueue").width()-$("#presInfo").width()-40;varcent 查看详情

dreamweaver背景图片怎么自适应浏览器大小

背景图片太大超出浏览器了,怎么让它自适应浏览器大小?background-image:url(%E6%9C%80%E7%BE%8E%E7%9A%84%E5%85%83%E7%B4%A0%E5%91%A8%E6%9C%9F%E8%A1%A8.jpg这窜代码应该加什么?图片自适应屏幕大小显示主要是利用百分比来控制,切忌给图片宽度一个固... 查看详情

css实现网页背景图片自适应全屏

一张清晰漂亮的背景图片能给网页加分不少,设计师也经常会给页面的背景使用大图,我们既不想图片因为不同分辨率图片变形,也不希望当在大屏的情况下,背景有一块露白,简而言之,就是实现能自适应屏幕大小又不会变形... 查看详情

cell添加选中时的背景图片显示图片和图片自适应框的大小

1.给cell添加选中时的背景图片UIView*myview=[[UIViewalloc]init];myview.frame=CGRectMake(0,0,320,47);myview.backgroundColor=[UIColorcolorWithPatternImage:[UIImageimageNamed:@"0006.png"]];cell.selectedBackgroundView 查看详情

css背景图片自适应元素大小

一、一种比较土的方法,<img>置于底层。 方法如下:   CSS代码:img{position:absolute;z-index:-10;width:50%;}     HTML:<imgsrc="背景图片路径"/><span>字在背景上</span>&nbs 查看详情

css实现自适应不同大小屏幕的背景大图的两种方法(转自简书)

...不同大小屏幕的背景大图的两种方法一张清晰漂亮的背景图片能给网页加分不少,设计师也经常会给页面的背景使用大图,我们既不想图片因为不同分辨率图片变形,也不希望当在大屏的情况下,背景有一块露白,简而言之,就... 查看详情

java实现给图片添加水印(文字水印或图片水印)(代码片段)

本文介绍java实现在图片上加文字水印的方法,水印可以是图片或者文字,操作方便。目录一、java实现给图片添加文字水印1.获取原图片对象信息1.1读取本地图片1.2读取网络图片2.添加水印3.获取目标图片4.完成代码二、java... 查看详情

如何快速消除图片上的文字或水印

...片放入文件夹内,方便后续操作。打开软件主界面,点击右下角“图片去水印”选项,进入操作界面。进入之后,点击中间的“添加文件”选项在文件夹内将要加水印的视频加入,也可以可以点击左下方的“添加文件夹”选项直... 查看详情

html网页背景图片自适应窗口大小

<!DOCTYPE><html><head><metahttp-equiv="Content-Type"content="text/html;charset=UTF-8"><title>helloworld</title></head><body><divid="Layer1"style="pos 查看详情

html中使背景图片自适应浏览器大小

  1、图片不够大,又background属性不能拉伸图片;2、只能用个div,把其z-index值设为负,并使这个div大小为整个body大小,在div里用<img>3、body的background属性去掉,要不然会被遮住 例子:<!DOCTYPEhtmlPUBLIC"-//W3C//DTDHTML... 查看详情

如何给word文档设置图片水印

...是OFFICE2003,首先我们打开WORD文档,如图所示请点击输入图片描述在WORD文档的菜单中找到“格式”,点击“格式”,在其下接菜单中找到“背景”选项,如下图所示请点击输入图片描述点击“背景”,在“背景”的下拉菜单中找... 查看详情

java给图片添加图片水印,设置样式平铺,拉伸

importjavax.imageio.ImageIO;importjava.awt.*;importjava.awt.image.BufferedImage;importjava.io.File;importjava.io.IOException;publicclassImageUtil{/***给图片添加水印*@paramoriginImgPath原始图片的路径*@paramtargetImg 查看详情

cell自适应网络图片大小

-(void)setModel:(SheBeiModel*)model{     //先从缓存中查找图片  UIImage*image=[[SDImageCachesharedImageCache]imageFromDiskCacheForKey:[NSStringstringWithFormat:@"%@%@",request 查看详情