图片添加水印
来源:互联网 发布:mysql中nvl函数用法 编辑:程序博客网 时间:2024/06/05 11:00
最近学习了下Java实现图片添加水印,包括文字水印和图片水印,单图片添加水印和多图片批量添加水印等。下面简单总结下开发过程:
1.首先搭建框架,这里使用的是struts2框架,允许一次上传多个图片,可以将原图和添加过水印的图片对比展示。
web.xml中的配置文件:
<filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class></filter><filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern></filter-mapping>
struts.xml配置文件:
<struts> <!--设置开发模式,请求后缀的配置 --> <constant name="struts.action.extension" value="action" /> <!--设置编码形式为UTF-8 --> <constant name="struts.i18n.encoding" value="UTF-8" /> <!--省略其他配置信息 --> <constant name="struts.multipart.maxSize" value="1073741824" /> <!-- 设置上传文件的临时文件夹 --> <constant name="struts.multipart.saveDir" value="/tmpUpload" /> <package name="default" extends="struts-default"> <action name="watermark" class="com.watermark.WaterMarkAction" method="watermark"> <param name="uploadPath">/images</param> <result name="success">watermark.jsp</result> </action> </package></struts>
2.实现图片添加水印的实现思路是:
①创建缓存图片对象;
②创建Java绘图工具类;
③使用绘图工具对象将原图绘制到缓存图片对象;
④使用绘图工具将水印(文字/图片)绘制到缓存图片对象;
⑤创建图像编码工具类;
⑥使用图像编码工具类,输出缓存图像到目标图片文件。
3.给单个图片添加文字水印
public interface MarkService { public static final String MARK_TEXT = "Byron"; public static final String FONT_NAME = "微软雅黑"; public static final int FONT_STYLE = Font.BOLD; //黑体 public static final int FONT_SIZE = 20; //文字大小 public static final Color FONT_COLOR = Color.red;//文字颜色 public static final int X = 10; //文字坐标 public static final int Y = 10; public static float ALPHA = 0.3F; //文字水印透明度 public static final String LOGO = "logo.gif"; //图片形式的水印 public String watermark(File image,String imageFileName,String uploadPath,String realUploadPath);}
/* * 实现添加单个文字水印 */public class TextMarkService implements MarkService{ @Override public String watermark(File image, String imageFileName, String uploadPath, String realUploadPath) { String logoFileName = "logo_"+imageFileName; //定义目标文件输出的名称 OutputStream os = null; try { //1 创建图片缓存对象 Image image2 = ImageIO.read(image); //解码原图 int width = image2.getWidth(null); //获取原图的宽度 int height = image2.getHeight(null);//获取原图的高度 BufferedImage bufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); //图像颜色的设置 //2 创建Java绘图工具对象 Graphics2D g = bufferedImage.createGraphics(); //3 使用绘图工具对象将原图绘制到缓存图片对象 g.drawImage(image2, 0, 0, width, height, null); //4 使用绘图工具对象将水印(文字/图片)绘制到缓存图片 g.setFont(new Font(FONT_NAME,FONT_STYLE,FONT_SIZE)); g.setColor(FONT_COLOR); //获取文字水印的宽度和高度值 int width1 = FONT_SIZE*getTextLength(MARK_TEXT);//文字水印宽度 int height1= FONT_SIZE; //文字水印高度 //计算原图和文字水印的宽度和高度之差 int widthDiff = width - width1; //宽度之差 int heightDiff= height - height1; //高度之差 int x = X; //横坐标 int y = Y; //纵坐标 //保证文字水印在右下方显示 if(x > widthDiff){ x = widthDiff; } if(y > heightDiff){ y = heightDiff; } //水印透明度的设置 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,ALPHA)); //绘制文字 g.drawString(MARK_TEXT, x, y + FONT_SIZE); //释放工具 g.dispose(); //创建文件输出流,指向最终的目标文件 os = new FileOutputStream(realUploadPath+"/"+logoFileName); //5 创建图像文件编码工具类 JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os); //6 使用图像编码工具类,输出缓存图像到目标文件 en.encode(bufferedImage); } catch (Exception e) { e.printStackTrace(); }finally{ if(os!=null){ try { os.close(); //关闭流 } catch (Exception e2) { e2.printStackTrace(); } } } return uploadPath+"/"+logoFileName; } //文本长度的处理:文字水印的中英文字符的宽度转换 public int getTextLength(String text){ int length = text.length(); for(int i=0;i<text.length();i++){ String s = String.valueOf(text.charAt(i)); if(s.getBytes().length>1){ //中文字符 length++; } } length = length%2 == 0?length/2:length/2+1; //中文和英文字符的转换 return length; }}
4.新建一个index.jsp页面和水印添加成功后的watermark.jsp
index.jsp页面:
<body> <h4>上传图片</h4> <hr /> <form name="form1" action="${pageContext.request.contextPath}/watermark.action" method="post" enctype="multipart/form-data"> <input type="file" name="image" /><br /> <input type="file" name="image" /><br /> <input type="file" name="image" /><br /> <input type="file" name="image" /><br /> <input type="file" name="image" /><br /><br /> <input type="submit" value="上传图片" /> </form> <hr /></body>
效果如下:
watermark.jsp页面:
<body> <table width="99%" align="center"> <tr> <td width="50%" align="center"> <img src=${pageContext.request.contextPath }<s:property value="picInfo.imageURL"/> width="550" /> </td> <td width="50%" align="center"> <img src=${pageContext.request.contextPath }<s:property value="picInfo.logoImageURL"/> width="550" /> </td> </tr> </table></body>
5.WaterMarkAction处理类
package com.watermark;import java.io.File;import org.apache.struts2.ServletActionContext;import com.opensymphony.xwork2.ActionSupport;/** * * description:控制器 * @author Byron * */public class WaterMarkAction extends ActionSupport { private File image; // 单个图片上传 private String imageFileName; private PicInfo picInfo = new PicInfo(); // 创建数据模型 private String uploadPath; // 文件上传的相对路径,要在struts.xml文件中配置 /* * 请求处理方法:负责接收图片上传以及水印添加的请求 */ public String watermark() throws Exception { /* * 单个图片上传处理逻辑 */ // 文件上传的绝对路径是基于相对路径获取的 String realUploadPath = ServletActionContext.getServletContext() .getRealPath(uploadPath); UploadService uploadService = new UploadService(); // 调用uploadService来完成图片上传 picInfo.setImageURL(uploadService.uploadImage(image, imageFileName, uploadPath, realUploadPath)); MarkService markService = new TextMarkService(); // 创建上传单个图片添加文字水印服务 // 将上传好之后图片的路径保存到数据变量中,会将picInfo变量返回到watermark.jsp页面中 picInfo.setLogoImageURL(markService.watermark(image, imageFileName, uploadPath, realUploadPath)); return SUCCESS; } public File getImage() { return image; } public String getImageFileName() { return imageFileName; } public void setImageFileName(String imageFileName) { this.imageFileName = imageFileName; } public void setImage(File image) { this.image = image; } public String getUploadPath() { return uploadPath; } public void setUploadPath(String uploadPath) { this.uploadPath = uploadPath; } public PicInfo getPicInfo() { return picInfo; } public void setPicInfo(PicInfo picInfo) { this.picInfo = picInfo; }}
效果如下:
6.给图片添加多个文字水印,新建一个添加多文字水印的服务类
/* * 实现添加多个文字水印 */public class MoreTextMarkService implements MarkService{ @Override public String watermark(File image, String imageFileName, String uploadPath, String realUploadPath) { String logoFileName = "logo_"+imageFileName; //定义目标文件输出的名称 OutputStream os = null; try { //1 创建图片缓存对象 Image image2 = ImageIO.read(image); int width = image2.getWidth(null); int height = image2.getHeight(null); BufferedImage bufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); //2 创建Java绘图工具对象 Graphics2D g = bufferedImage.createGraphics(); //3 使用绘图工具对象将原图绘制到缓存图片对象 g.drawImage(image2, 0, 0, width, height, null); //4 使用绘图工具对象将水印(文字/图片)绘制到缓存图片 g.setFont(new Font(FONT_NAME,FONT_STYLE,FONT_SIZE)); g.setColor(FONT_COLOR); int width1 = FONT_SIZE*getTextLength(MARK_TEXT);//文字水印宽度 int height1= FONT_SIZE; //文字水印高度 //透明度的设置 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,ALPHA)); //旋转图片(30°) g.rotate(Math.toRadians(30),bufferedImage.getWidth()/2,bufferedImage.getHeight()/2); //设置水印的坐标 int x= -width/2; int y= -height/2; while(x < width*1.5){ y = -height/2; while(y < height*1.5){ g.drawString(MARK_TEXT,x,y); y += height1 + 50; } x += width1 + 50; //水印之间的间隔设为50 } //释放工具 g.dispose(); //最终目标文件 os = new FileOutputStream(realUploadPath+"/"+logoFileName); //5 创建图像文件编码工具类 JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os); //6 使用图像编码工具类,输出缓存图像到目标文件 en.encode(bufferedImage); } catch (Exception e) { e.printStackTrace(); }finally{ if(os!=null){ try { os.close(); } catch (Exception e2) { e2.printStackTrace(); } } } return uploadPath+"/"+logoFileName; } //处理文字水印的中英文字符的宽度转换 public int getTextLength(String text){ int length = text.length(); for(int i=0;i<text.length();i++){ String s = String.valueOf(text.charAt(i)); if(s.getBytes().length>1){ //中文字符 length++; } } length = length%2 == 0?length/2:length/2+1; //中文和英文字符的转换 return length; }
然后修改WaterMarkAction 中 markService为:
MarkService markService = new MoreTextMarkService(); //创建上传多个图片添加文字水印服务
效果如下:
7.批量上传图片添加多个文字水印,修改WaterMarkAction
package com.watermark;import java.io.File;import java.util.ArrayList;import java.util.List;import org.apache.struts2.ServletActionContext;import com.opensymphony.xwork2.ActionSupport;/** * * description:控制器 * @author Byron * */public class WaterMarkAction extends ActionSupport { private File[] image; // 多个图片上传 private String[] imageFileName; private List<PicInfo> picInfo = new ArrayList<PicInfo>(); private String uploadPath; // 文件上传的相对路径,struts.xml文件中配置 /* * 请求处理方法:负责接收图片上传以及水印添加的请求 */ public String watermark() throws Exception { /* * 批量添加文字水印 */ String realUploadPath = ServletActionContext.getServletContext() .getRealPath(uploadPath); UploadService uploadService = new UploadService(); // 创建水印服务类 MarkService markService = new MoreTextMarkService(); // 判断是否为多图片上传 if (image != null && image.length > 0) { for (int i = 0; i < image.length; i++) { PicInfo pi = new PicInfo(); pi.setImageURL(uploadService.uploadImage(image[i], imageFileName[i], uploadPath, realUploadPath)); // 水印添加操作 pi.setLogoImageURL(markService.watermark(image[i], imageFileName[i], uploadPath, realUploadPath)); // 将有水印的图片添加的picInfo数组中 picInfo.add(pi); } } return SUCCESS; } public File[] getImage() { return image; } public void setImage(File[] image) { this.image = image; } public String[] getImageFileName() { return imageFileName; } public void setImageFileName(String[] imageFileName) { this.imageFileName = imageFileName; } public String getUploadPath() { return uploadPath; } public void setUploadPath(String uploadPath) { this.uploadPath = uploadPath; } public List<PicInfo> getPicInfo() { return picInfo; } public void setPicInfo(List<PicInfo> picInfo) { this.picInfo = picInfo; }}
效果如下:
8.下面介绍如何给图片添加多个图片水印:
首先创建一个服务类:
/* * 实现添加多个图片水印 */public class MoreImageMarkService implements MarkService{ @Override public String watermark(File image, String imageFileName, String uploadPath, String realUploadPath) { String logoFileName = "logo_"+imageFileName; //定义目标文件输出的名称 OutputStream os = null; try { //1 创建图片缓存对象 Image image2 = ImageIO.read(image); int width = image2.getWidth(null); int height = image2.getHeight(null); BufferedImage bufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); //2 创建Java绘图工具对象 Graphics2D g = bufferedImage.createGraphics(); //3 使用绘图工具对象将原图绘制到缓存图片对象 g.drawImage(image2, 0, 0, width, height, null); //4 使用绘图工具对象将水印(文字/图片)绘制到缓存图片 String logoPath = realUploadPath + "/" + LOGO; File logo = new File(logoPath); Image logoImage = ImageIO.read(logo); int width1 = logoImage.getWidth(null); int height1= logoImage.getHeight(null); //透明度的设置 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,ALPHA)); //旋转图片(30°) g.rotate(Math.toRadians(30),bufferedImage.getWidth()/2,bufferedImage.getHeight()/2); int x= -width/2; int y= -height/2; while(x < width*1.5){ y = -height/2; while(y < height*1.5){ g.drawImage(logoImage,x,y,null); y+=height1+50; } x+= width1 + 50; } g.dispose(); //创建文件输出流,指向最终的目标文件 os = new FileOutputStream(realUploadPath+"/"+logoFileName); //5 创建图像文件编码工具类 JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os); //6 使用图像编码工具类,输出缓存图像到目标文件 en.encode(bufferedImage); } catch (Exception e) { e.printStackTrace(); }finally{ if(os!=null){ try { os.close(); } catch (Exception e2) { e2.printStackTrace(); } } } return uploadPath+"/"+logoFileName; }}
然后修改WaterMarkAction:
package com.watermark;import java.io.File;import java.util.ArrayList;import java.util.List;import org.apache.struts2.ServletActionContext;import com.opensymphony.xwork2.ActionSupport;/** * * description:控制器 * @author Byron * */public class WaterMarkAction extends ActionSupport { private File[] image; // 多个图片上传 private String[] imageFileName; private List<PicInfo> picInfo = new ArrayList<PicInfo>(); private String uploadPath; // 文件上传的相对路径,要在struts.xml文件中配置 /* * 请求处理方法:负责接收图片上传以及水印添加的请求 */ public String watermark() throws Exception { /* * 批量添加图片水印 */ String realUploadPath = ServletActionContext.getServletContext() .getRealPath(uploadPath); UploadService uploadService = new UploadService(); // 创建水印服务类 MarkService markService = new MoreImageMarkService(); // 判断是否为多图片上传 if (image != null && image.length > 0) { for (int i = 0; i < image.length; i++) { PicInfo pi = new PicInfo(); pi.setImageURL(uploadService.uploadImage(image[i], imageFileName[i], uploadPath, realUploadPath)); // 水印添加操作 pi.setLogoImageURL(markService.watermark(image[i], imageFileName[i], uploadPath, realUploadPath)); // 将有水印的图片添加的picInfo数组中 picInfo.add(pi); } } return SUCCESS; } public File[] getImage() { return image; } public void setImage(File[] image) { this.image = image; } public String[] getImageFileName() { return imageFileName; } public void setImageFileName(String[] imageFileName) { this.imageFileName = imageFileName; } public String getUploadPath() { return uploadPath; } public void setUploadPath(String uploadPath) { this.uploadPath = uploadPath; } public List<PicInfo> getPicInfo() { return picInfo; } public void setPicInfo(List<PicInfo> picInfo) { this.picInfo = picInfo; }}
效果如下:
参考项目源码可前往github下载:
0 0
- Java添加水印+图片水印+文字水印
- 给图片添加水印
- 为图片添加水印
- 为图片添加水印
- 图片添加水印功能
- 给图片添加水印
- C# 添加 图片 水印
- 给图片添加水印
- 上传图片添加水印
- 图片添加水印
- c# 添加图片水印
- 给图片添加水印
- 为图片添加水印
- Asp添加图片水印
- 图片添加水印
- .net图片添加水印
- C#图片添加水印
- 添加防伪图片水印
- 查找算法——javascript算法实现
- Quaternion.Slerp的使用
- [UVa 10943] How do you add? (计数+隔板法+重叠隔板)
- JavaScript中typeof
- 树莓派调整分区大小
- 图片添加水印
- GSON的使用(一)
- Python学习札记 2016-04-24
- linux下部署kodexplorer
- 排序算法——javascript算法实现
- 练习2 习题20
- 117. Populating Next Right Pointers in Each Node II
- 【spring】spring reference doc4.3.1 研读 <一>元数据配置以及Environment
- Java异常