需求,给指定目录下面以.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>* 满足这两个条件才能将水印打印到图片的指定位置,也就是可以进行动态位移。 </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