首页 > 编程语言 >Java为图片加水印

Java为图片加水印

时间:2022-12-19 14:31:37浏览次数:51  
标签:Java String int 水印 private 加水 null public 图片


Java为图片加水印工具类

一、简介

  • 使用Java在图片上加上水印,可以添加文字、图片
  • 编写一个工具类的代码优化和整理
  • 使用建造者模式提高工具类的可配置性

二、效果图

Java为图片加水印_水印

三、基本参数

// +++++++++++++++ 配置参数 +++++++++++++++++++

/** 文字水印内容 */
private String fontText = null;
/** 图片水印内容 */
private String imgText = null;
/** 操作的图片文件 */
private String filePath = null;


// +++++++++++++ 初始化一些参数 +++++++++++++++++

/** 图片宽度 */
private int width;
/** 图片高度 */
private int height;
/** 画笔操作 */
private Graphics2D graphics2D = null;
/** 图片缓冲区 */
private BufferedImage bufferedImage = null;


// +++++++++++++ 自定义的水印参数 ++++++++++++++

/** 文字字体 */
private String fontName = null;
/** 文字样式 */
private int fontStyle;
/** 文字大小 */
private int fontSize;
/** 文字颜色 */
private Color fontColor;
/** 透明度 */
private float alpha;
/** 外框宽度 */
private int borderWidth;
/** 旋转高度 */
private double angdeg;
/** 间距 */
private int spacing;
/** 最后图片保存路径 */
private String savePath = null;

四、工具方法

水印位置
public static enum Position{
/** 上左 */
TOP_LEFT(1),
/** 上右 */
TOP_RIGHT(2),
/** 下左 */
BOTTOM_LEFT(3),
/** 下右 */
BOTTOM_RIGHT(4)
;
public int type;

Position(int type) {
this.type = type;
}

public int getType() {
return type;
}
}
设置文字或者图片水印位置
/**
* @function 设置文字或者图片水印位置
* @param position 添加水印的位置
* @param waterWidth 添加水印的宽度
* @param waterHeight 添加水印的高度
* @param type true:文字,false:图片
* @return int[] x, y
*/
private int[] setPosition (int position, int waterWidth, int waterHeight, boolean type) {
int x = width - waterWidth;
int y = height - waterHeight;
switch (position) {
case 1:
x = type ? borderWidth : 0;
y = type ? borderWidth : 0;
break;
case 2:
y = type ? borderWidth : 0;
break;
case 3:
x = type ? borderWidth : 0;
y = type ? y - borderWidth : y;
break;
case 4:
default:
x = type ? x - borderWidth : x;
y = type ? y - borderWidth : y;
break;
}
return new int[]{x, y};
}
初始化参数

初始化​​BufferImage​​​、​​Graphisc2D​​和目标图片的宽和高。

/**
* 初始化参数
*/
private void init () {
try {
// 获取图片示例,并获取图片的高度,宽度
Image img = ImageIO.read(new File(filePath));
width = img.getWidth(null);
height = img.getHeight(null);
// 创建图片缓冲区
bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 创建绘图工具
graphics2D = bufferedImage.createGraphics();
// 将原图放到缓冲区
graphics2D.drawImage(img, 0, 0, width, height, null);
} catch (IOException e) {
System.out.println("文件读写异常");
e.printStackTrace();
}
}
将操作之后的图片存在磁盘

如何没有填写保存路径,将会将原图片覆盖。

/**
* 将图片保存到磁盘
*/
private void save () {
String path = null;
if ((savePath == null) || (savePath.equals(""))) {
path = filePath;
} else {
path = savePath;
}
// 将缓冲区图片放到磁盘上
try (FileOutputStream os = new FileOutputStream(path)) {
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(os);
encoder.encode((bufferedImage));
} catch (IOException e) {
System.out.println("文件读写异常");
e.printStackTrace();
}
}
设置文字水印的宽和高

对于中英文字符宽度不一样,所以要对中英文进行不同的处理。

/**
* 获取文字位置
* @param text
* @return
*/
private int getTextLength (String text) {
int len = text.length();
for (int i = 0; i < text.length(); i++) {
String s = String.valueOf(text.charAt(i));
if (s.getBytes().length > 1) {
len ++;
}
}
return len % 2 == 0 ? len / 2 : len / 2 + 1;
}
添加单个文字水印
/**
* 添加单个文字水印
* @throws IOException
* @param place
*/
public void addFontWater(Position place) {
init();
// 创建文字水印的样式
graphics2D.setFont(new Font(fontName, fontStyle, fontSize));
// 文字颜色
graphics2D.setColor(fontColor);
// 获取文字位置x,y坐标
int type = place.getType();
int[] position = setPosition(type, fontSize * getTextLength(fontText), fontSize, true);
int x = position[0];
int y = position[1] + fontSize;
// 将文字写入指定位置,并关闭画笔资源
graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
graphics2D.drawString(fontText, x, y);
graphics2D.dispose();
save();
}
创建那个操作句柄
public static Builder create = new ImageWaterTool.Builder();
建造者模式设置属性

因为部分属性是默认,但是有些默认的属性是可以使用者自定义的,所以使用建造者进行对象属性构建是最好的。

public class ImageWaterTool {

// ++++++++ 配置参数 ++++++++++++++++
/** 文字水印内容 */
private String fontText = null;
/** 图片水印内容 */
private String imgText = null;
/** 操作的图片文件 */
private String filePath = null;
// .....

public ImageWaterTool(Builder builder) {
this.fontText = builder.fontText;
this.imgText = builder.imgText;
this.filePath = builder.filePath;
// ....
}

public static class Builder {

// +++++++++++ 配置参数 +++++++++++++++
/** 文字水印内容 */
private String fontText = null;
/** 图片水印内容 */
private String imgText = null;
/** 操作的图片文件 */
private String filePath = null;
// .....


public Builder setFontText(String fontText) {
this.fontText = fontText;
return this;
}

public Builder setImgText(String imgText) {
this.imgText = imgText;
return this;
}

public Builder setFilePath(String filePath) {
this.filePath = filePath;
return this;
}

// ....
}

public static enum Position{
// ....
}

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

/**
* @function 设置文字或者图片水印位置
* @param position 添加水印的位置
* @param waterWidth 添加水印的宽度
* @param waterHeight 添加水印的高度
* @param type true:文字 —— false:图片
* @return int[] x, y
*/
private int[] setPosition (int position, int waterWidth, int waterHeight, boolean type) {
// ....
}

/**
* 初始化参数
*/
private void init () {
// ....
}

/**
* 将图片保存到磁盘
*/
private void save () {
// ....
}

/**
* 获取文字位置
* @param text
* @return
*/
private int getTextLength (String text) {
// ....
}

/**
* 添加单个文字水印
* @throws IOException
* @param place
*/
public void addFontWater(Position place) {
// ....
}

/**
* 添加单个图片水印
* @throws IOException
*/
public void addPicWater (Position place) throws IOException {
// ....
}

/**
* 添加多个文字水印
* @throws IOException
*/
public void addManyFontWater () {
// ....
}

/**
* 添加多个图片水印
* @throws IOException
*/
public void addManyPicWater () throws IOException {
// ....
}

public static Builder create = new ImageWaterTool.Builder();

public static void main(String[] args) throws Exception {
ImageWaterTool.create
.setFilePath("C:\\Users\\long\\Desktop\\test-1.png")
.setFontText("https://blog.c.net/yhflyl")
.setFontSize(30)
.build()
.addFontWater(Position.BOTTOM_RIGHT);
}
}
使用
public static void main(String[] args) throws Exception {
ImageWaterTool.create
// 本地文件路径
.setFilePath("C:\\Users\\long\\Desktop\\test-1.png")
// 添加的文字水印
.setFontText("https://blog.c.net/yhflyl")
// 文字大小
.setFontSize(30)
.build()
.addFontWater(Position.BOTTOM_RIGHT);
}

五、完整代码

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
* @author 墨龙吟
* @version 1.0.0
* @ClassName ImageWaterUtil.java
* @Email [email protected]
* @Description TODO 文件添加水印
* @createTime 2019年09月09日 - 23:32
*/
public class ImageWaterTool {

// ++++++++++++++++++++++++++ 配置参数 +++++++++++++++++++++++++++++++++++++++++++++++++++
/** 文字水印内容 */
private String fontText = null;
/** 图片水印内容 */
private String imgText = null;
/** 操作的图片文件 */
private String filePath = null;

// ++++++++++++++++++++++++++ 初始化一些参数 ++++++++++++++++++++++++++++++++++++++++++++++
/** 图片宽度 */
private int width;
/** 图片高度 */
private int height;
/** 画笔操作 */
private Graphics2D graphics2D = null;
/** 图片缓冲区 */
private BufferedImage bufferedImage = null;

// +++++++++++++++++++++++++++++ 自定义的水印参数 ++++++++++++++++++++++++++++++++++++++++
/** 文字字体 */
private String fontName = null;
/** 文字样式 */
private int fontStyle;
/** 文字大小 */
private int fontSize;
/** 文字颜色 */
private Color fontColor;
/** 透明度 */
private float alpha;
/** 外框宽度 */
private int borderWidth;
/** 旋转高度 */
private double angdeg;
/** 间距 */
private int spacing;
/** 最后图片保存路径 */
private String savePath = null;

public ImageWaterTool(Builder builder) {
this.fontText = builder.fontText;
this.imgText = builder.imgText;
this.filePath = builder.filePath;
this.fontName = builder.fontName;
this.fontStyle = builder.fontStyle;
this.fontSize = builder.fontSize;
this.fontColor = builder.fontColor;
this.alpha = builder.alpha;
this.borderWidth = builder.borderWidth;
this.angdeg = builder.angdeg;
this.spacing = builder.spacing;
this.savePath = builder.savePath;
}

public static class Builder {

// ++++++++++++++++++++++++++ 配置参数 +++++++++++++++++++++++++++++++++++++++++++++++++++
/** 文字水印内容 */
private String fontText = null;
/** 图片水印内容 */
private String imgText = null;
/** 操作的图片文件 */
private String filePath = null;

// +++++++++++++++++++++++++++++ 自定义的水印参数 ++++++++++++++++++++++++++++++++++++++++
/** 文字字体 */
private String fontName = "微软雅黑";
/** 文字样式 */
private int fontStyle = Font.BOLD | Font.ITALIC;
/** 文字大小 */
private int fontSize = 30;
/** 文字颜色 */
private Color fontColor = Color.black;
/** 透明度 */
private float alpha = 0.3f;
/** 外框宽度 */
private int borderWidth = 20;
/** 旋转高度 */
private double angdeg = 30;
/** 间距 */
private int spacing = 200;
/** 最后图片保存路径 */
private String savePath = null;


public Builder setFontText(String fontText) {
this.fontText = fontText;
return this;
}

public Builder setImgText(String imgText) {
this.imgText = imgText;
return this;
}

public Builder setFilePath(String filePath) {
this.filePath = filePath;
return this;
}

public Builder setFontName(String fontName) {
this.fontName = fontName;
return this;
}

public Builder setFontStyle(int fontStyle) {
this.fontStyle = fontStyle;
return this;
}

public Builder setFontSize(int fontSize) {
this.fontSize = fontSize;
return this;
}

public Builder setFontColor(Color fontColor) {
this.fontColor = fontColor;
return this;
}

public Builder setAlpha(float alpha) {
this.alpha = alpha;
return this;
}

public Builder setBorderWidth(int borderWidth) {
this.borderWidth = borderWidth;
return this;
}

public Builder setAngdeg(double angdeg) {
this.angdeg = angdeg;
return this;
}

public Builder setSpacing(int spacing) {
this.spacing = spacing;
return this;
}

public Builder setSavePath(String savePath) {
this.savePath = savePath;
return this;
}

public ImageWaterTool build () throws Exception {
return new ImageWaterTool(this);
}
}

public static enum Position{
/** 上左 */
TOP_LEFT(1),
/** 上右 */
TOP_RIGHT(2),
/** 下左 */
BOTTOM_LEFT(3),
/** 下右 */
BOTTOM_RIGHT(4)
;
public int type;

Position(int type) {
this.type = type;
}

public int getType() {
return type;
}
}

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

/**
* @function 设置文字或者图片水印位置
* @param position 添加水印的位置
* @param waterWidth 添加水印的宽度
* @param waterHeight 添加水印的高度
* @param type true:文字 —— false:图片
* @return int[] x, y
*/
private int[] setPosition (int position, int waterWidth, int waterHeight, boolean type) {
int x = width - waterWidth;
int y = height - waterHeight;
switch (position) {
case 1:
x = type ? borderWidth : 0;
y = type ? borderWidth : 0;
break;
case 2:
y = type ? borderWidth : 0;
break;
case 3:
x = type ? borderWidth : 0;
y = type ? y - borderWidth : y;
break;
case 4:
default:
x = type ? x - borderWidth : x;
y = type ? y - borderWidth : y;
break;
}
return new int[]{x, y};
}

/**
* 初始化参数
*/
private void init () {
try {
// 获取图片示例,并获取图片的高度,宽度
Image img = ImageIO.read(new File(filePath));
width = img.getWidth(null);
height = img.getHeight(null);
// 创建图片缓冲区
bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 创建绘图工具
graphics2D = bufferedImage.createGraphics();
// 将原图放到缓冲区
graphics2D.drawImage(img, 0, 0, width, height, null);
} catch (IOException e) {
System.out.println("文件读写异常");
e.printStackTrace();
}
}

/**
* 将图片保存到磁盘
*/
private void save () {
String path = null;
if ((savePath == null) || (savePath.equals(""))) {
path = filePath;
} else {
path = savePath;
}
// 将缓冲区图片放到磁盘上
try (FileOutputStream os = new FileOutputStream(path)) {
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(os);
encoder.encode((bufferedImage));
} catch (IOException e) {
System.out.println("文件读写异常");
e.printStackTrace();
}
}

/**
* 获取文字位置
* @param text
* @return
*/
private int getTextLength (String text) {
int len = text.length();
for (int i = 0; i < text.length(); i++) {
String s = String.valueOf(text.charAt(i));
if (s.getBytes().length > 1) {
len ++;
}
}
return len % 2 == 0 ? len / 2 : len / 2 + 1;
}

/**
* 添加单个文字水印
* @throws IOException
* @param place
*/
public void addFontWater(Position place) {
init();
// 创建文字水印的样式
graphics2D.setFont(new Font(fontName, fontStyle, fontSize));
// 文字颜色
graphics2D.setColor(fontColor);
// 获取文字位置x,y坐标
int type = place.getType();
int[] position = setPosition(type, fontSize * getTextLength(fontText), fontSize, true);
int x = position[0];
int y = position[1] + fontSize;
// 将文字写入指定位置,并关闭画笔资源
graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
graphics2D.drawString(fontText, x, y);
graphics2D.dispose();
save();
}

/**
* 添加单个图片水印
* @throws IOException
*/
public void addPicWater (Position place) throws IOException {
init();
// 创建图片水印
Image imageWater = ImageIO.read(new File(imgText));
// 获取文字位置x,y坐标
int type = place.getType();
int[] position = setPosition(type, imageWater.getWidth(null), imageWater.getHeight(null), false);
int x = position[0];
int y = position[1];
// 将文字写入指定位置,并关闭画笔资源
graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
graphics2D.drawImage(imageWater, x, y, null);
graphics2D.dispose();
save();
}

/**
* 添加多个文字水印
* @throws IOException
*/
public void addManyFontWater () {
init();
// 创建文字水印的样式
graphics2D.setFont(new Font(fontName, fontStyle, fontSize));
graphics2D.setColor(fontColor);
// 获取文字宽高
int waterWidth = fontSize * getTextLength(fontText);
int waterHeight = fontSize;
// 将文字写入指定位置,并关闭画笔资源
graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
// 将文字旋转30度
graphics2D.rotate(Math.toRadians(angdeg), width / 2, height / 2);
// 添加多个
int x = -width / 2;
while (x < width * 1.5) {
int y = -height / 2;
while (y < height * 1.5) {
graphics2D.drawString(fontText, x, y);
y += waterHeight + spacing;
}
x += waterWidth + spacing;
}
graphics2D.dispose();
save();
}

/**
* 添加多个图片水印
* @throws IOException
*/
public void addManyPicWater () throws IOException {
// 初始化
init();
// 创建图片水印
Image imageWater = ImageIO.read(new File(imgText));
// 获取水印图片的宽高
int waterWidth = imageWater.getWidth(null);
int waterHeight = imageWater.getHeight(null);
// 将文字写入指定位置,并关闭画笔资源
graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
// 将文字旋转30度
graphics2D.rotate(Math.toRadians(angdeg), width / 2, height / 2);
// 添加多个
int x = -width / 2;
while (x < width * 1.5) {
int y = -height / 2;
while (y < height * 1.5) {
graphics2D.drawImage(imageWater, x, y, null);
y += waterHeight + spacing;
}
x += waterWidth + spacing;
}
graphics2D.dispose();
save();
}

public static Builder create = new ImageWaterTool.Builder();

public static void main(String[] args) throws Exception {
ImageWaterTool.create
.setFilePath("C:\\Users\\long\\Desktop\\test-1.png")
.setFontText("https://blog.c.net/yhflyl")
.setFontSize(30)
.build()
.addFontWater(Position.BOTTOM_RIGHT);

// 多个文字水印
// ImageWaterTool.create
// // 设置水印文字
// .setFontText("我的小笨蛋")
// .setFilePath("C:\\Users\\long\\Desktop\\笨蛋1.jpg")
// // 设置添加水印后的图片路径
.setSavePath("C:\\Users\\long\\Desktop\\pic-444.png")
// // 设置多个文字之间的距离
// .setSpacing(100)
// .setAngdeg(150)
// //设置水印的透明度
// .setAlpha(0.2f)
// .build()
// .addManyFontWater();
// 多个图片水印
// ImageWaterTool.create
// .setFilePath("C:\\Users\\long\\Desktop\\笨蛋.jpg")
// .setImgText("C:\\Users\\long\\Desktop\\logo.png")
// .build()
// .addManyPicWater();
}
}

五、关注一波,感谢

Java为图片加水印_水印_02


标签:Java,String,int,水印,private,加水,null,public,图片
From: https://blog.51cto.com/luckyqilin/5952640

相关文章

  • 项目采坑日志——Java浮点类型数据进行加减运算出现精度丢失问题
    Java浮点类型数据进行加减运算出现精度丢失问题​​现象​​​​解决效果​​​​问题分析​​​​出现问题的原因​​​​解决办法​​​​解决思路:​​​​具体实现代码:​......
  • 死磕Java多线程之线程池的基本使用与核心原理
    Java多线程之线程池一、线程池的自我介绍1.线程池的重要性(为什么使用线程池)线程池可以应对突然大爆发量的访问,通过有限个固定线程为大量的操作服务,减少创建和销毁线程所需......
  • php 滑动图片验证生成
    1.话不多说,直接干货,喜欢的希望大家一键三连<?phpnamespaceApp\Model;classVerifyImage{//浮层坐标数组protected$tailoringArray=[];//浮层......
  • java中常用的一些类型强制转换
    一.String->其他在​​Java​​项目的实际开发和应用中,常常需要用到将对象转为String这一基本功能。本文将对常用的转换方法进行一个总结。常用的方法有Object.toString()......
  • Java关键字(一)——instanceof
    目录​​1、obj必须为引用类型,不能是基本类型​​​​2、obj为null​​​​3、obj为class类的实例对象​​​​4、obj为class接口的实现类​​​​5、obj为class......
  • IDEA中编译报错【java: 程序包lombok不存在】
    一、lombok问题没有正确引入lombok检查是否在pom中引入lombok依赖<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId>......
  • Java锁升级
    锁升级整体对象头MarkWord结构如下:1.自旋锁与自适应自旋1.1自旋锁如果物理机器有一个以上的处理器或者处理器核心,能让两个或以上的线程同时并行执行,我们就可以让......
  • 连号区间数【第四届蓝桥杯省赛C++B组,第四届蓝桥杯省赛JAVAB组】
    连号区间数小明这些天一直在思考这样一个奇怪而有趣的问题:在\(1∼N\)的某个排列中有多少个连号区间呢?这里所说的连号区间的定义是:如果区间\([L,R]\)里的所有元素(即......
  • drawio批量重命名库图片名字
     s=[每个图标的名字];letn=0;for(letiofall.childNodes){ i.childNodes[2].click(); document.getElementsByClassName("geDialog")[1].getElementsByTagName("i......
  • java核心技术学习笔记——synchronized底层如何实现?什么是锁的升级、降级?
    在Java6之前,Monitor的实现完全是依靠操作系统内部的互斥锁,因为需要进行用户态到内核态的切换,所以同步操作是一个无差别的重量级操作。现代的(Oracle)JDK中,VM对此进......