Java实现添加文字水印&图片水印的方法详解
作者:全村最野的狗 发布时间:2023-01-28 08:11:39
为什么要给图片添加水印
为图片添加水印的主要作用是保护图片版权,防止图片被未经授权的人使用或传播。
通常情况下,图片水印会包含图片作者的名字、版权信息或公司商标等信息,这些信息可以帮助识别图片的所有者,并对未经授权的使用进行追究。
此外,图片水印还可以用于提醒人们图片的使用限制,例如是否需要授权、是否可以用于商业用途等。
除此之外,图片水印还可以用于增加图片的视觉吸引力或宣传性,例如可以在图片中添加品牌 logo 或宣传标语等。
总的来说,图片水印的主要作用是保护图片版权和提醒人们图片的使用限制,但也可以用于提升图片的视觉效果和宣传性。
绘制文字水印
为图片添加水印是一种常用的图片处理技术。在 Java 中可以使用 Graphics2D 类来绘制水印。
以下是一个简单的例子,展示了如何在图片的右下角添加一个水印:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Watermark {
public static void main(String[] args) {
// 读取原图片
BufferedImage image = null;
try {
image = ImageIO.read(new File("original.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
// 获取图片的宽度和高度
int width = image.getWidth();
int height = image.getHeight();
// 创建一个图片缓存对象
BufferedImage newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 获取图片的画笔
Graphics2D g = newImage.createGraphics();
// 将原图片绘制到缓存图片上
g.drawImage(image, 0, 0, width, height, null);
// 设置水印的字体样式
g.setFont(new Font("微软雅黑", Font.BOLD, 20));
// 设置水印的颜色
g.setColor(Color.red);
// 设置水印的位置
g.drawString("Hello World!", width - 120, height - 10);
// 释放图形上下文使用的系统资源
g.dispose();
// 保存带水印的图片
try {
ImageIO.write(newImage, "jpg", new File("watermarked.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
动态计算字符串的宽度
如果你已经知道了字符串的大小(size)和内容(str),想要计算字符串的宽度,可以使用以下方法:
首先创建一个 Font 对象,使用该对象的 getStringBounds 方法计算字符串的宽度。
import java.awt.Font;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
public class StringWidth {
public static void main(String[] args) {
// 字符串内容
String str = "Hello World!";
// 字体大小
int size = 20;
// 创建字体对象
Font font = new Font("微软雅黑", Font.BOLD, size);
// 创建字体渲染上下文
FontRenderContext frc = new FontRenderContext(null, true, true);
// 计算字符串的宽度
Rectangle2D bounds = font.getStringBounds(str, frc);
// 输出字符串的宽度
System.out.println(bounds.getWidth());
}
}
在这段代码中,我们首先创建了一个 Font 对象,然后使用该对象的 getStringBounds 方法计算字符串的宽度。
注意,在调用 getStringBounds 方法时,需要传入一个 FontRenderContext 对象,该对象用于描述字体的渲染环境,可以影响字符串的显示效果。
最后,计算出的字符串宽度是一个 Rectangle2D 对象,你可以使用 getWidth 方法来获取实际的宽度值。
自适应文字水印位置
可以看到,我们添加的水印已经超出了图片的范围,导致显示不完全,出现这种结果的原因是因为我们默认字符的宽度为120px
.您可以通过上面介绍的动态计算字符宽度来让水印始终显示在图片上。
import java.awt.Color;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Watermark {
public static void main(String[] args) {
// 读取原图片
BufferedImage image = null;
try {
image = ImageIO.read(new File("original.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
// 获取图片的宽度和高度
int width = image.getWidth();
int height = image.getHeight();
// 创建一个图片缓存对象
BufferedImage newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 获取图片的画笔
Graphics2D g = newImage.createGraphics();
// 字符串内容
String str = "Hello World!";
// 字体大小
int size = 20;
// 创建字体对象
Font font = new Font("微软雅黑", Font.BOLD, size);
// 创建字体渲染上下文
FontRenderContext frc = new FontRenderContext(null, true, true);
// 计算字符串的宽度和高度
Rectangle2D bounds = font.getStringBounds(str, frc);
// 字符宽度
int strWidth = (int)bounds.getWidth();
// 字符高度
int strHeight = (int)bounds.getHeight();
// 将原图片绘制到缓存图片上
g.drawImage(image, 0, 0, width, height, null);
// 设置水印的字体样式
g.setFont(font);
// 设置水印的颜色
g.setColor(Color.red);
// 设置水印的位置
g.drawString("Hello World!", width - strWidth - 10, height - strHeight - 10);
// 释放图形上下文使用的系统资源
g.dispose();
// 保存带水印的图片
try {
ImageIO.write(newImage, "jpg", new File("watermarked.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
绘制图片水印
如果你想在 png 格式的图片上绘制透明的图片水印,可以使用以下方法:
首先读取原图片和水印图片,然后使用 Graphics2D 类的 drawImage 方法将水印图片绘制到原图片上,最后使用 setComposite 方法设置水印图片的 alpha 通道值来调整水印的透明度。
紫色部分为图片水印。
具体实现如下:
import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class TransparentWatermark {
public static void main(String[] args) {
// 读取原图片
BufferedImage image = null;
try {
image = ImageIO.read(new File("original.png"));
} catch (IOException e) {
e.printStackTrace();
}
// 获取图片的宽度和高度
int width = image.getWidth();
int height = image.getHeight();
// 创建一个图片缓存对象
BufferedImage newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 获取图片的画笔
Graphics2D g = newImage.createGraphics();
// 将原图片绘制到缓存图片上
g.drawImage(image, 0, 0, width, height, null);
// 读取水印图片
BufferedImage watermark = null;
try {
watermark = ImageIO.read(new File("watermark.png"));
} catch (IOException e) {
e.printStackTrace();
}
// 获取水印图片的宽度和高度
int wmWidth = watermark.getWidth();
int wmHeight = watermark.getHeight();
// 设置水印图片的透明度
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f));
// 绘制水印图片
g.drawImage(watermark, width - wmWidth - 10, height - wmHeight - 10, wmWidth, wmHeight, null);
// 释放图形上下文使用的系统资源
g.dispose();
// 保存带水印的图片
try {
ImageIO.write(newImage, "png", new File("watermarked.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
提升图片处理速度
目前我们添加文字水印和图片水印耗时都在 700ms - 2000ms
。
可以考虑以下几种方法来提升速度:
使用多线程:如果你需要批量添加文字水印,可以考虑使用多线程的方式来加速处理速度。例如,你可以将图片分成多份,每份使用一个线程处理,最后再将结果合并。
使用更快的图片处理库:如果你使用的是 Java 原生的图片处理工具(例如 java.awt 包),可以考虑使用更快的图片处理库,例如 OpenCV、Imaging、Thumbnails 等。这些库通常具有更快的处理速度,并且支持更多的图片格式和操作。
减少图片的质量:如果你的图片尺寸较大,可以考虑将图片的质量压缩到一个较低的水平,这样可以减少图片的体积,从而加快处理速度。
优化代码:如果你的代码有一些低效的地方,可以考虑优化代码,提升程序的执行效率。例如,可以避免使用过多的循环和分支语句,或者使用更快的算法等。
来源:https://juejin.cn/post/7196647843138404412


猜你喜欢
- 最近公司因为短信接口被盗刷的比较严重,需要做一个类似于淘宝的滑动验证,用于特定环境,以增加一层保障。拿到需求首先想到的是自定义ViewGro
- c#开发cad如何预览图块1.定义变量的方法代码如下2. 获取GetDwgImag图像的方法代码3.实现显示DWG文件的方法代码方
- 在游戏开发中,主角需要通过跑地图来通关升级,本章主要介绍主角的移动和摄像跟随的操作。主角移动角色位移通过主角的骨骼动画控制(后续文章会详细介
- Maven导入thymeleaf依赖飘红1、运行环境操作系统:win10jdk版本:1.8idea版本:2020.1maven版本:3.3.
- 1.准备工作首先实现识别数字等字符,我们要知道需要采用OCR (Optical Character Recognition,光学字符识别)来
- 本实例实现在jsp页面实现查询全国城市天气预报的功能,供大家参考,具体内容如下实例目录:实现效果:具体思路:从和风天气api那里取得具体城市
- 后台服务端import java.io.IOException;import java.io.InputStream;import java
- 1. RocketMQ Topic创建机制以下源码基于Rocket MQ 4.7.0RocketMQ Topic创建机制分为两种:一种自动创
- 在EditText输入数字的时候,通常我们需要限制小数点前后位数。比如金额输入一般我们需要限制小数点后面最多2位。我们可以通过 TextWa
- namespace PadWebServices.Model{ public static class DataTa
- 登录添加验证码是一个非常常见的需求,网上也有非常成熟的解决方案,其实,要是自己自定义登录实现这个并不难,但是如果需要在 Spring Sec
- 本文实例为大家分享了java通过PDF模板填写PDF表单的具体代码,包括图片,供大家参考,具体内容如下需要用到的java包: it
- 自定义封装StringUtils常用工具类,供大家参考,具体内容如下package com.demo.utils;import java.u
- Path接口1、Path表示的是一个目录名序列,其后还可以跟着一个文件名,路径中第一个部件是根部件时就是绝对路径,例如 / 或 C:\ ,而
- C#开发WinForm,如何实现TextBox获取输入焦点时自动全选?&nbs
- 题目:求1+2!+3!+...+20!的和程序分析:此程序只是把累加变成了累乘。程序设计:public class Ex21 {  
- 介绍Java命令模式(Command Pattern)是一种行为型设计模式,它将请求封装成一个对象,从而使不同的请求可以进行参数化,并支持请
- kaptcha是一个开源的验证码实现库1.添加依赖<dependency> <groupId>com.g
- 做这个功能是因为开发项目的时候,由于后台接口的一些参数的值的长度有要求,不能超过多少个字符,所以在编辑框中输入的字符是要有限制的
- 本文实例为大家分享了C#汉字转换为拼音缩写的实现代码,供大家参考,具体内容如下using System;using System.Confi