当前位置:网站首页>给图片左上角加logo标识、左下角加时间和地址、地址到达指定长度换行
给图片左上角加logo标识、左下角加时间和地址、地址到达指定长度换行
2022-07-29 21:13:00 【~忆缘】
效果
1.给照片添加logo水印
(1)添加pom依赖
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
/** * 给照片添加Logo水印 * @param projectPath 项目路径 * @param finalImageWater 加上水印后台图片存储地址 * @throws Exception */
private void addWaterLogoImage(String projectPath, String finalImageWater) throws Exception{
//读取原图,获取宽高
File file = new File(projectPath + "/WEB-INF/template/image.jpg");
BufferedImage image = ImageIO.read(file);
//读取水印图
BufferedImage waterImg = ImageIO.read(new File(projectPath + "/WEB-INF/template/雨虹logo.jpg"));
double bl = 0.18;//水印为原图宽占比
//根据比例计算新的水印图宽高
int waterWidth = (int) (image.getWidth() * bl);
int waterHeight = waterWidth * waterImg.getHeight() / waterImg.getWidth();
waterImg = Thumbnails.of(waterImg).size(waterWidth, waterHeight).keepAspectRatio(false).asBufferedImage();
//使用新水印执行添加水印操作 Positions.TOP_LEFT 将logo放到左上角
Thumbnails.of(file).watermark(Positions.TOP_LEFT, waterImg, 1f).scale(1).toFile(finalImageWater);
}
2.给照片添加时间、地址水印并实现地址过长换行效果
/** * 添加时间、地址水印 * @param finalImageWater */
private void addWaterFontImage(String finalImageWater, String address) {
try {
String waterFont = "时 间:"+ DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss");
address = "地 址:"+address;
// 读取原图片信息
File srcImgFile = new File(finalImageWater);
Image srcImg = ImageIO.read(srcImgFile);
int srcImgWidth = srcImg.getWidth(null);
int srcImgHeight = srcImg.getHeight(null);
// 初始化画布,图片多大,画布多大
BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g = bufImg.createGraphics();
//指定要绘制的图片
g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);
double fontLength = srcImgWidth * 0.3;//根据比例设置文字占的长度,即文字长度
int fontSize = (int) (fontLength / 5 * 0.6);//文字大小,0.9为差值
//设置字体样式,加粗,大小
Font font = new Font("黑体", Font.BOLD, fontSize);
//设置文字颜色
g.setColor(Color.white);
g.setFont(font);
//绘制文字的横纵坐标
/** * 控制换行 */
ArrayList<String> line_list = new ArrayList<>();
FontRenderContext frc = g.getFontRenderContext();
g.getFontRenderContext();
Rectangle2D stringBounds = font.getStringBounds(address, frc);
double fontWidth = stringBounds.getWidth();
if(fontWidth <= bufImg.getWidth()){
line_list.add(address);
}else {
int text_width = bufImg.getWidth()-60;// 输出文本宽度, 这里就以画布宽度作为文本宽度测试
double bs = fontWidth/text_width ;// 文本长度是文本框长度的倍数
int line_char_count = (int)Math.ceil(address.length() / bs) ;// 每行大概字数
int begin_index = 0 ;
while(begin_index <address.length()){
int end_index = begin_index + line_char_count ;
if(end_index>= address.length()){
end_index = address.length();
}
String line_str = address.substring(begin_index, end_index);
Rectangle2D tempStringBounds = font.getStringBounds(line_str, frc);
int tzcs = 0 ;// 调整次数
int tzzs = 1 ;// 调整字数, 临时文本的字符串长度大于要求的文本宽度时, 每次减少临时文本的字数, 然后重新测量文本宽度
while(tempStringBounds.getWidth()> text_width){
line_str = line_str.substring(0, line_str.length() - tzzs );// 每次向前 tzzs 个字符重新计算 (待优化)
tempStringBounds = font.getStringBounds(line_str, frc);
tzcs++;
}
System.out.println("调整"+(end_index - begin_index -line_str.length())+"个数字, 调整了"+tzcs+"次, 当前行宽度:"+tempStringBounds.getWidth());
line_list.add(line_str);
begin_index = begin_index + line_str.length() ;
}
}
int gao = 0;
if(srcImgHeight > srcImgWidth){
gao = 90;
}else{
gao = 100;
}
for(int i = 0;i<line_list.size();i++){
if(i == 0){
//绘制时间水印
g.drawString(waterFont, 20, (i+(srcImgHeight/gao))*80);
}
String line_str = line_list.get(i);
//绘制地址水印
g.drawString(line_str, 20, (i+1+(srcImgHeight/gao))*80);//35 为每行的高度
}
g.dispose();
// 输出图片
Thumbnails.of(srcImgFile).watermark(Positions.BOTTOM_LEFT, bufImg, 1f).scale(1).toFile(finalImageWater);
}catch (Exception e){
e.printStackTrace();
}
}
边栏推荐
- 7 行代码搞崩溃 B 站,原因令人唏嘘!
- MySQL Data Query - Union Query
- 亚马逊登录参数metadata1,encryptedPwd逆向分析
- 基于PaddleSpeech搭建个人语音听写服务
- APM电机输出逻辑(Motors类详解)
- 惠普服务器硬盘指示灯不亮或显示蓝色
- 网安学习-内网渗透2
- 1. Promise usage in JS, 2. The concept and usage of closures, 3. The difference between the four methods and areas of object creation, 4. How to declare a class
- 关于云计算的海量数据存储模型[通俗易懂]
- C语言操作符详解(1)
猜你喜欢
随机推荐
【AD】【持续更新ing】关于AD设计过程中一些小细节
【593. 有效的正方形】
解释器模式
WeChat Mini Program 31 Subcontracting Mechanism
VSCode配置终端为系统命令行
全系都更换带T四缸,安全、舒适一个不落
赶紧进来!!!带你认识C语言基本数据类型
第3章业务功能开发(线索关联市场活动,动态搜索)
什么是数据安全性?
Use the PostgreSQL GRANT command to modify permissions on various database objects
华为畅享50 Pro评测:HarmonyOS加持 更流畅更安全
【ORM框架:Sequelize的查询】
Jenkins 如何玩转接口自动化测试?
[Database] mysql date format conversion
240. Searching 2D Matrix II
378. The Kth Smallest Element in an Ordered Matrix
Oracle问题: ORA-01882: 未找到时区
网站ping端口的操作方法和命令介绍
错误解决:Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255]
【数据库】mysql日期格式转换
![[ACTF2020 Freshman Competition]Exec 1](/img/1e/a3c19d514207e6965d09c66b86e519.png)








