java 批量为图片添加图标水印和文字水印

需求,给指定目录下面以.jpg结尾的文件,添加图标水印和文字水印

文章目录

          • 一、基础版本
          • 二、升级版本
          • 三、依赖

一、基础版本
package com.gblfy.util;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;/*** java为图片添加图标水印和文字水印** @author gblfy* @version 1.0* @explain 文字水印、图片水印* @creationTime 2020/07/01*/
public class WaterMarkUtil {//水印图片路径private static String WATER_MARKIMG_PATH = "D:" + File.separator + "1" + File.separator + "iconPath" + File.separator + "22.png";//当前登陆操作员 采用全局变量private static String operator;static {operator = "zhangsan";}/*** 将指定图标(png图片)印刷到指定图片上* <p>*  1.图标图片格式:*    png*  2.坐标轴:*    x轴决定左右位置*    y轴决定上下位置* 3.坐标位置*   x值越大距离右越近,反之,x值越小距离左越近;*   y值越大距离越往下,反之,y值越小距离越往上* </p>** @param pressImg  水印图片* @param targetImg 源图片路径的目标文件* @param x         x坐标* @param y         y坐标*/public final static void pressImage(String pressImg, String targetImg, int x, int y) {try {// 目标文件File imageFile = new File(targetImg);Image src = ImageIO.read(imageFile);int wideth = src.getWidth(null);int height = src.getHeight(null);BufferedImage image = new BufferedImage(wideth, height, BufferedImage.TYPE_INT_RGB);Graphics g = image.createGraphics();g.drawImage(src, 0, 0, wideth, height, null);// 水印文件File waterMarkImage = new File(pressImg);Image markImage = ImageIO.read(waterMarkImage);int weightMarkImage = markImage.getWidth(null);int heightMarkImage = markImage.getHeight(null);g.drawImage(markImage, x, y, weightMarkImage, heightMarkImage, null);// 水印结束g.dispose();FileOutputStream out = new FileOutputStream(targetImg);JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);encoder.encode(image);out.close();} catch (IOException e) {e.printStackTrace();}}/*** 打印文字水印图片* <p>* 1.图标图片格式:png* 2.坐标轴:*   x轴决定左右位置*   y轴决定上下位置* 3.坐标位置*   x值越大距离右越近,反之,x值越小距离左越近;*   y值越大距离越往下,反之,y值越小距离越往上* </p>** @param pressText 文字* @param targetImg 目标图片* @param fontName  字体名* @param fontStyle 字体样式* @param color     字体颜色* @param fontSize  字体大小* @param x         偏移量* @param y         偏移量*/public static void pressText(String pressText, String targetImg, String fontName, int fontStyle, Color color,int fontSize, int x, int y) {try {File imageFile = new File(targetImg);Image src = ImageIO.read(imageFile);int weidth = src.getWidth(null);int height = src.getHeight(null);BufferedImage image = new BufferedImage(weidth, height, BufferedImage.TYPE_INT_RGB);Graphics g = image.createGraphics();g.drawImage(src, 0, 0, weidth, height, null);g.setColor(color);g.setFont(new Font(fontName, fontStyle, fontSize));g.drawString(pressText, x, y);g.dispose();FileOutputStream out = new FileOutputStream(targetImg);JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);encoder.encode(image);out.close();} catch (IOException e) {e.printStackTrace();}}/*** 添加图标水印+文字水印** @param srcImgPath 需要处理的源图片路径*/public static void iconAndTextWatermark(String srcImgPath) {// 1.添加图标水印pressImage(WATER_MARKIMG_PATH, srcImgPath, 100, 500);System.out.println("--------------------添加图标水印 执行完成!--------------------");String date = TimeUtil.getCurrentDate().toString();String time = TimeUtil.getCurrentTime().toString();// 2.添加文字水印  参数根据真实保单图片进行调整pressText(operator, srcImgPath, "宋体", 0, Color.BLUE, 30, 540, 600);pressText(date, srcImgPath, "宋体", 0, Color.BLUE, 30, 540, 650);pressText(time, srcImgPath, "宋体", 0, Color.BLUE, 30, 540, 700);System.out.println("--------------------添加文字水印 执行完成!--------------------");}/*** 对.jpg图片文件进行筛选* <p>*   1.使用递归遍历目录下面的.jpg结尾图片文件*   2.对筛选通过的文件调用水印文件处理* </p>** @param path* @return*/public static void getFileListNotReturn(String path) {File dir = new File(path);// 该文件目录下文件全部放入数组File[] files = dir.listFiles();if (files != null) {for (int i = 0; i < files.length; i++) {String fileName = files[i].getName();// 判断是文件还是文件夹if (files[i].isDirectory()) {// 获取文件绝对路径getFileListNotReturn(files[i].getAbsolutePath());// 判断文件名是否以.jpg结尾} else if (fileName.endsWith(".jpg")) {String strFileName = files[i].getAbsolutePath();System.out.println("文件名:" + strFileName);//对符合条件的文件统一水印处理iconAndTextWatermark(strFileName);} else {continue;}}}}//--------------------------------------------单元测试--------------------------------------------public static void main(String[] args) {String srcImgPath = "D:\\1\\srcImgPath\\";System.out.println("图片路径:" + srcImgPath);getFileListNotReturn(srcImgPath);}/***  特别说明:*  如上面的效果展示的那样,要想将水印打印到图片指定位置,进行动态设置的话,需要:</p>*  第一,原图片大小;</p>*  第二,水印大小;</p>*  满足这两个条件才能将水印打印到图片的指定位置,也就是可以进行动态位移。&nbsp;</p>*  其中,图片水印可以进行动态设置,而文字水印则实现不了,因为我们无法获取文字水印的大小。</p>*  调试水印输出位置也是个细致活呀。</p>* 另外,水印的偏移量一般情况下均为正值,图片左上角为起点0,0,不同于数学上的Y轴,向下偏移用正值表示。*/
}
二、升级版本

根据图片的宽度(分辨率)和高度(分辨率),动态改变图标水印的宽度(分辨率)和高度(分辨率),适配所有的图片比例

实现原理:
1.图标水印
找到图片宽度(分辨率)和高度(分辨率)和图标水印的宽度(分辨率)和高度(分辨率)的比例关系即可
2.文字水印同理:
找到文字水印宽度(分辨率)和高度(分辨率)和图标水印的宽度(分辨率)和高度(分辨率)的比例关系即可

/*** 单证添加图标水印+文字水印* <p>* 1.使用递归遍历目录下面的单证图片文件* 2.对文件的不同元素,做不同处理* 1>如果是文件夹就地柜处理* 2>如果是文件就就进入处理范围* 3.获取单证图片的宽度和高度* 4.推算出新华水印图标的宽度和高度* 5.调用水印处理和新方法* </p>** @param srcImgPath*/public void getImageParamsAndDeal(String srcImgPath) {File dir = new File(srcImgPath);// 该文件目录下文件全部放入数组File[] files = dir.listFiles();if (files != null) {for (int i = 0; i < files.length; i++) {//文件的绝对路径String absolutePath = files[i].getAbsolutePath();// 判断是文件还是文件夹if (files[i].isDirectory()) {// 文件元素是文件夹递归调用自己getImageParamsAndDeal(absolutePath);} else {//对所有的单证图片进行统一处理String strFileName = absolutePath;System.out.println("文件名:" + strFileName);// 获取每张图片的高度 和 宽度File file = new File(strFileName);int[] imgWidth = getImgWidth(file);System.out.println("图片的宽度:" + imgWidth[0]);System.out.println("图片的高度:" + imgWidth[1]);//单证的宽度和高度int picWidth = imgWidth[0];int picHeight = imgWidth[1];//新华水印图标的宽度和高度初始化int picX = 0;int picY = 0;//新华水印图标的宽度和高度double width = (imgWidth[0] - (picWidth * 0.71)) / 2;double height = (imgWidth[1] - (picHeight * 0.18)) / 2;//新华水印图标的宽度和高度  取整特殊处理picX = (int) Math.floor(width);picY = (int) Math.floor(height);System.out.println("水印图标x:" + picX);System.out.println("水印图标y:" + picY);// 对符合条件的文件统一水印处理iconAndTextWatermark(strFileName, picX, picY, picWidth, picHeight);}}}}
 /*** 获取图片宽度和高度** @param file 图片文件* @return 宽度*/public static int[] getImgWidth(File file) {InputStream is = null;BufferedImage src = null;int result[] ={0, 0};try {is = new FileInputStream(file);src = javax.imageio.ImageIO.read(is);// 得到源图宽result[0] = src.getWidth(null);// 得到源图高result[1] = src.getHeight(null);is.close();} catch (Exception e) {e.printStackTrace();}return result;}
 /*** 添加图标水印+文字水印* <p>* 1.新华图标水印和单证图片的比例关系* 2.操作员文字水印和新华图标水印的比例关系* 3.日期文字水印和新华图标水印的比例关系* 4.时间文字水印和新华图标水印的比例关系* </p>** @param srcImgPath 需要处理的源图片路径*/public static void iconAndTextWatermark(String srcImgPath, int picX, int picY, int picWidth, int picHeight) {File fromFile = new File(nclWaterFilePath);File toFile = new File(nclWaterTempFilePath);//判断生成水印图标的绝对路径路是否存在不存在就创建if (!toFile.exists()) {toFile.mkdirs();}// ImageUtil.resizePng(fromFile, toFile, (int) (1244 * 0.71), (int)(1684 * 0.18), false);resizePng(fromFile, toFile, (int) (picWidth * 0.71), (int) (picHeight * 0.18), false);// 1.添加图标水印pressImage(nclWaterTempFilePath, srcImgPath, picX, picY);System.out.println("--------------------添加图标水印 执行完成!--------------------");// 2.添加文字水印 参数根据真实保单图片进行调整pressText(operator, srcImgPath, "宋体", 0, Color.BLUE, (int) (picHeight * 0.032), picX + (int) (picWidth * 0.57),picY + (int) (picHeight * 0.20));pressText(PubFun.getCurrentDate(), srcImgPath, "宋体", 0, Color.BLUE, (int) (picHeight * 0.032), picX+ (int) (picWidth * 0.57), picY + (int) (picHeight * 0.24));pressText(PubFun.getCurrentTime(), srcImgPath, "宋体", 0, Color.BLUE, (int) (picHeight * 0.032), picX+ (int) (picWidth * 0.57), picY + (int) (picHeight * 0.28));// System.out.println("--------------------添加文字水印 执行完成!--------------------");}
/*** 将指定图标(png图片)印刷到指定图片上* <p>* 1.图标图片格式:* png* 2.坐标轴:* x轴决定左右位置* y轴决定上下位置* 3.坐标位置* x值越大距离右越近,反之,x值越小距离左越近;* y值越大距离越往下,反之,y值越小距离越往上* </p>** @param pressImg  水印图片* @param targetImg 源图片路径的目标文件* @param x         x坐标* @param y         y坐标*/public final static void pressImage(String pressImg, String targetImg, int x, int y) {try {// 目标文件File imageFile = new File(targetImg);Image src = ImageIO.read(imageFile);int wideth = src.getWidth(null);int height = src.getHeight(null);BufferedImage image = new BufferedImage(wideth, height, BufferedImage.TYPE_INT_RGB);Graphics g = image.createGraphics();g.drawImage(src, 0, 0, wideth, height, null);// 水印文件File waterMarkImage = new File(pressImg);Image markImage = ImageIO.read(waterMarkImage);int weightMarkImage = markImage.getWidth(null);int heightMarkImage = markImage.getHeight(null);g.drawImage(markImage, x, y, weightMarkImage, heightMarkImage, null);// 水印结束g.dispose();FileOutputStream out = new FileOutputStream(targetImg);JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);encoder.encode(image);out.close();} catch (IOException e) {e.printStackTrace();}}/*** 打印文字水印图片* <p>* 1.图标图片格式:*   png* 2.坐标轴:*   x轴决定左右位置*   y轴决定上下位置* 3.坐标位置*   x值越大距离右越近,反之,x值越小距离左越近;*   y值越大距离越往下,反之,y值越小距离越往上* </p>** @param pressText 文字* @param targetImg 目标图片* @param fontName  字体名* @param fontStyle 字体样式* @param color     字体颜色* @param fontSize  字体大小* @param x         偏移量* @param y         偏移量*/public static void pressText(String pressText, String targetImg, String fontName, int fontStyle, Color color,int fontSize, int x, int y) {try {File imageFile = new File(targetImg);Image src = ImageIO.read(imageFile);int weidth = src.getWidth(null);int height = src.getHeight(null);BufferedImage image = new BufferedImage(weidth, height, BufferedImage.TYPE_INT_RGB);Graphics g = image.createGraphics();g.drawImage(src, 0, 0, weidth, height, null);g.setColor(color);g.setFont(new Font(fontName, fontStyle, fontSize));g.drawString(pressText, x, y);g.dispose();FileOutputStream out = new FileOutputStream(targetImg);JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);encoder.encode(image);out.close();} catch (IOException e) {e.printStackTrace();}}
    /*** 任意压缩PNG图片* <p>* 1.用于修改PNG水印图标的宽度(分辨率)和宽度(分辨率)* 2.动态适配单证图片宽度(分辨率)和宽度(分辨率)** @param fromFile     源文件* @param toFile       裁剪后的文件* @param outputWidth  裁剪宽度* @param outputHeight 裁剪高度* @param proportion   是否是等比缩放*/public static void resizePng(File fromFile, File toFile, int outputWidth, int outputHeight, boolean proportion) {try {BufferedImage bi2 = ImageIO.read(fromFile);int newWidth;int newHeight;// 判断是否是等比缩放if (proportion) {// 为等比缩放计算输出的图片宽度及高度double rate1 = ((double) bi2.getWidth(null)) / (double) outputWidth + 0.1;double rate2 = ((double) bi2.getHeight(null)) / (double) outputHeight + 0.1;// 根据缩放比率大的进行缩放控制double rate = rate1 < rate2 ? rate1 : rate2;newWidth = (int) (((double) bi2.getWidth(null)) / rate);newHeight = (int) (((double) bi2.getHeight(null)) / rate);} else {// 输出的图片宽度newWidth = outputWidth;// 输出的图片高度newHeight = outputHeight;}BufferedImage to = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);Graphics2D g2d = to.createGraphics();to = g2d.getDeviceConfiguration().createCompatibleImage(newWidth, newHeight, Transparency.TRANSLUCENT);g2d.dispose();g2d = to.createGraphics();@SuppressWarnings("static-access")Image from = bi2.getScaledInstance(newWidth, newHeight, bi2.SCALE_AREA_AVERAGING);g2d.drawImage(from, 0, 0, null);g2d.dispose();ImageIO.write(to, "png", toFile);} catch (Exception e) {e.printStackTrace();}}

测试
只需要传递需要添加水印的目录即可

  public static void main(String[] args) {Bl bl=new Bl()//1.批量添加水印bl.getImageParamsAndDeal(srcImgPath);}
三、依赖
jimi-1.0.jar
jai_imageio.jar
jai_core.jar
jai_codec-1.1.3.jar

下载链接:https://download.csdn.net/download/weixin_40816738/46766690

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/519872.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

“有趣”的投影:当PCA失效时怎么办?

目前&#xff0c;大多数的数据科学家都比较熟悉主成分分析 (Principal Components Analysis&#xff0c;PCA)&#xff0c;它是一个探索性的数据分析工具。可以这样简要的描述&#xff1a;研究人员经常使用PCA来降低维度&#xff0c;希望在他们的数据中找出有用的信息&#xff0…

线程最最基础的知识

戳蓝字“CSDN云计算”关注我们哦&#xff01;什么是线程试想一下没有线程的程序是怎么样的&#xff1f;百度网盘在上传文件时就无法下载文件了&#xff0c;得等文件上传完成后才能下载文件。这个我们现在看起来很反人性&#xff0c;因为我们习惯了一个程序同时可以进行运行多个…

特征工程自动化如何为机器学习带来重大变化

随着技术的快速发展&#xff0c;在数据科学领域中&#xff0c;包括库、工具和算法等总会不断地变化的。然而&#xff0c;一直都有这么一个趋势&#xff0c;那就是自动化水平不断地提高。 近些年来&#xff0c;在模型的自动化选择和超参数调整方面取得了一些进展&#xff0c;但…

工作组访问不到别人的计算机,众果搜的博客

常见问题&#xff1a;A 在网上邻居列表中找不到目标计算机。B 在网上邻居列表能找到&#xff0c;但却访问不了。C 以UNC路径能访问&#xff0c;但在网上邻居列表中却找不到。1、网上邻居列表的维护依赖于浏览服务(Computer Browers)&#xff0c;计算机通过广播方式登记到浏览器…

java 实现压缩zip的几种方案

需求&#xff0c;将指定目录下的文件及文件夹压缩成一个指定赔案号为名称&#xff0c;以".zip"结尾的压缩包提供客户下载。 package com.gblfy.util;import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.Fil…

序列模型简介——RNN, Bidirectional RNN, LSTM, GRU

既然我们已经有了前馈网络和CNN&#xff0c;为什么我们还需要序列模型呢&#xff1f;这些模型的问题在于&#xff0c;当给定一系列的数据时&#xff0c;它们表现的性能很差。序列数据的一个例子是音频的剪辑&#xff0c;其中包含一系列的人说过的话。另一个例子是英文句子&…

行!人工智能玩大了!程序员:太牛!你怎么看?

人工智能真的玩大了吗&#xff1f;人工智能行业的人才真的“爆发了&#xff1f;”AI程序员究竟怎么样&#xff1f;中国AI前景分析 程序员与远方最新参考&#xff0c;是12月2日出炉的《人工智能技术专利深度分析报告》。中国AI专利&#xff0c;已经位于世界前列&#xff0c;且正…

可应用于实际的14个NLP突破性研究成果(一)

语言理解对计算机来说是一个巨大的挑战。幼儿可以理解的微妙的细微差别仍然会使最强大的机器混淆。尽管深度学习等技术可以检测和复制复杂的语言模式&#xff0c;但机器学习模型仍然缺乏对我们的语言真正含义的基本概念性理解。 但在2018年确实产生了许多具有里程碑意义的研究…

String 常用API

public static void main(String[] args) {/*** String 常用API* 字符串* 1>截取* 2>替换**/String fileSuffix ".jpg";int i fileSuffix.indexOf(".");//截取.之后的内容&#xff0c;包含. indexs0String newStr fileSuffix.substring(i 0);…

小学五年级年级计算机教学计划,小学五年级信息技术教学计划范文

人类社会已进入信息时代,日新月异的信息技术在不断地改变着周围的世界。为了推广计算机信息技术,提高全民族的科学文化素质,发展小学信息技术教育。下面是学习啦小编整理的小学五年级信息技术教学计划范文&#xff0c;希望对大家有所帮助!小学五年级信息技术教学计划范文(一)一…

阿里资深技术专家:优秀的数据库存储引擎应具备哪些能力?

导读 本文作者是阿里巴巴OLTP数据库团队资深技术专家——曲山。作为自研高性能、低成本存储引擎X-Engine的负责人&#xff0c;曲山眼中的优秀关系型数据库存储引擎应该具备哪些能力呢&#xff1f; 正文 数据库内核按层次来分&#xff0c;就是两层&#xff1a;SQL & Stor…

开发函数计算的正确姿势——网页截图服务

前言 首先介绍下在本文出现的几个比较重要的概念&#xff1a; 函数计算&#xff08;Function Compute&#xff09;: 函数计算是一个事件驱动的服务&#xff0c;通过函数计算&#xff0c;用户无需管理服务器等运行情况&#xff0c;只需编写代码并上传。函数计算准备计算资源&am…

java实现删除指定指定目录下面指定某种类型的文件

/*** 删除指定目录下面指定文件类型的文件** param path*/public static void delSpecifyTheTypeFile(String path) {File dir new File(path);// 该文件目录下文件全部放入数组File[] files dir.listFiles();if (files ! null) {for (int i 0; i < files.length; i) {St…

如何关闭计算机的f12功能键,win10如何关闭快捷键?win10关闭F1~F12快捷键的方法

win10如何使用快捷键关闭?在win10系统中我们按下F1~F12原本可以正常使用系统中的功能。而然在笔记本中F1~F12竟然被笔记本中的功能所替代了&#xff0c;例如&#xff1a;打开/关闭 无线网卡&#xff0c;屏幕亮度加减、系统音量大小等&#xff0c;导致我们在使用F1~F12的时候只…

阿里巴巴宣布架构调整;英伟达放大招!重磅发布 ​TensorRT 7 ,支持超千种计算变换;苹果、谷歌和亚马逊罕见结盟……...

戳蓝字“CSDN云计算”关注我们哦&#xff01; 嗨&#xff0c;大家好&#xff0c;重磅君带来的【云重磅】特别栏目&#xff0c;如期而至&#xff0c;每周五第一时间为大家带来重磅新闻。把握技术风向标&#xff0c;了解行业应用与实践&#xff0c;就交给我重磅君吧&#xff01;重…

阿里开源分布式事务解决方案 Fescar 全解析

广为人知的阿里分布式事务解决方案&#xff1a;GTS&#xff08;Global Transaction Service&#xff09;&#xff0c;已正式推出开源版本&#xff0c;取名为“Fescar”&#xff0c;希望帮助业界解决微服务架构下的分布式事务问题&#xff0c;今天我们一起来深入了解。 FESCAR o…

鲜为人知的混沌工程,到底哪里好?

混沌工程属于一门新兴的技术学科&#xff0c;行业认知和实践积累比较少&#xff0c;大多数IT团队对它的理解还没有上升到一个领域概念。阿里电商域在2010年左右开始尝试故障注入测试的工作&#xff0c;希望解决微服务架构带来的强弱依赖问题。通过本文&#xff0c;你将了解到&a…

计算机软考中集成系统,软考中级系统集成项目管理工程师有哪些作用?

系统集成项目管理工程师属于计算机技术与软件专业技术资格(水平)考试(即软考)中级资格考试里面的一项考试。对于中级工程师而言&#xff0c;通过评定获得职称证书的人比通过考试获得职称证书的人更容易被社会认可与接受。因为评定职称的人有资格、有经验&#xff1b;在当今社会…

Nutanix在中国市场发布多云合作伙伴计划

近日&#xff0c;企业云操作系统厂商Nutanix宣布&#xff0c;在中国市场正式发布“精英技术联盟合作伙伴计划”。 “精英技术联盟合作伙伴计划”面向国内解决方案、应用和软硬件合作伙伴以及开发人员&#xff0c;帮助他们在全球领先的企业云平台上构建和部署差异化的解决方案&a…

将视觉深度学习模型应用于非视觉领域

介绍 近些年来&#xff0c;深度学习技术已经彻底改变了计算机视觉领域。由于迁移学习和各种各样的学习资源的出现&#xff0c;任何人都可以通过使用预训练的模型&#xff0c;将其应用到自己的工作当中&#xff0c;以此获得非常好的结果。随着深度学习越来越商业化&#xff0c;…