工具版本:
- Eclipse:eclipse-jee-mars-R-win32-x86_64
- JDK:jdk1.8.0_60
实现思路:
1.首先,我们需要创建一个缓存图片对象,存储我们的水印处理的中间结果,这个对象我们会在内存中进行存储,这样应用处理效率高,程序性能较好;
BufferedImage:实现缓存图片对象,存储在内存中,提高程序运行效率
2.接着,我们需要创建一个Java绘图工具对象,对我们刚刚创建好的缓存图片对象进行图片的图像处理操作。
具体操作:(1)我们使用绘图工具对象将需要打水印的原图先绘制到缓存图片对象中,相当于先把我们的原图铺好;
(2)接着,就可以进行水印处理,使用绘图工具将水印(文字/图片)绘制到缓存图片对象中,相当于使用绘图工具将水印(文字/图片)写在原图上面去;
(3)这样就实现了水印的处理。
Graphics2D:实现绘图工具对象,通过名字可以看出,这个工具类可以对平面图像做一个图像操作
3.但是打好水印的图片仍在我们的内存中,我们无法使用,我们如何将内存中的图片最终保存在我们的磁盘中呢?
4.这个时候就需要一个图像编码工具类:
(1)首先我们创建一个图像编码工具类对象,该对象使用指定的编码格式对我们的图片对象进行编码处理;
(2)同时,在缓存图片对象和磁盘目标文件之间搭起了一个桥梁;使用图片编码工具类,输出缓存图像到目标图片文件。
JPEGImageEncoder:图片编码工具类,对我们的图像文件做一个编码处理,并且将BuferedImage内存缓冲图片对象输出到磁盘中
具体实现:
- Jar包准备:这里我们使用Struts2框架进行开发;
- web.xml配置文件配置
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <display-name>WaterMark</display-name> <!-- struts2核心过滤器 --> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
- struts.xml配置文件配置
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <!-- 开启开发模式 --> <constant name="struts.devMode" value="false" /> <!-- 开启动态方法调用 --> <constant name="struts.enable.DynamicMethodInvocation" value="true"/> <!-- 请求后缀的配置,会处理后缀为action的web请求 --> <constant name="struts.action.extension" value="action"/> <!-- 编码配置 --> <constant name="struts.i18n.encoding" value="UTF-8"/> <!-- 上传文件大小配置,单位:字节 --> <constant name="struts.multipart.maxSize" value="1073741824"/> <constant name="struts.multipart.saveDir" value="/tmpUpload"/> <!-- 用户模块的Action配置 --> <package name="default" extends="struts-default"> <!-- 单个文字水印 --> <action name="textWaterMark" class="com.watermark.action.WaterMarkAction" method="textWaterMark"> <param name="uploadPath">/images</param> <result name="success">showtextmark.jsp</result> </action> <!-- 单个图片水印 --> <action name="imageWaterMark" class="com.watermark.action.WaterMarkAction" method="imageWaterMark"> <param name="uploadPath">/images</param> <result name="success">showimagemark.jsp</result> </action> <!-- 多个文字水印 --> <action name="multiTextWaterMark" class="com.watermark.action.WaterMarkAction" method="multiTextWaterMark"> <param name="uploadPath">/images</param> <result name="success">showmultitextmark.jsp</result> </action> <!-- 多个图片水印 --> <action name="multiImageWaterMark" class="com.watermark.action.WaterMarkAction" method="multiImageWaterMark"> <param name="uploadPath">/images</param> <result name="success">showmultiimagemark.jsp</result> </action> <!-- 批量处理单个文字水印 --> <action name="batchTextWaterMark" class="com.watermark.action.BatchWaterMarkAction" method="textWaterMark"> <param name="uploadPath">/images</param> <result name="success">batchshowtextmark.jsp</result> </action> <!-- 批量处理单个图片水印 --> <action name="batchImageWaterMark" class="com.watermark.action.BatchWaterMarkAction" method="imageWaterMark"> <param name="uploadPath">/images</param> <result name="success">batchshowimagemark.jsp</result> </action> <!-- 批量处理多个文字水印 --> <action name="batchMultiTextWaterMark" class="com.watermark.action.BatchWaterMarkAction" method="multiTextWaterMark"> <param name="uploadPath">/images</param> <result name="success">batchshowmultitextmark.jsp</result> </action> <!-- 批量处理多个图片水印 --> <action name="batchMultiImageWaterMark" class="com.watermark.action.BatchWaterMarkAction" method="multiImageWaterMark"> <param name="uploadPath">/images</param> <result name="success">batchshowmultiimagemark.jsp</result> </action> </package> </struts>
- 实体类PicInfo,用来封装上传图片的URL和添加水印后的图片URL
package com.watermark.entity; /** * 图片信息类 * @author aibinxiao * @date 2017年6月6日 上午11:13:59 */ public class PicInfo { private String imageURL; // 上传图片的返回路径 private String logoImageURL; // 添加水印的返回路径 public String getImageURL() { return imageURL; } public void setImageURL(String imageURL) { this.imageURL = imageURL; } public String getLogoImageURL() { return logoImageURL; } public void setLogoImageURL(String logoImageURL) { this.logoImageURL = logoImageURL; } @Override public String toString() { return "PicInfo [imageURL=" + imageURL + ", logoImageURL=" + logoImageURL + "]"; } }
- 分析文字水印中文本长度的工具类TextUtil
package com.watermark.util; /** * 文本工具类 * @author aibinxiao * @date 2017年6月6日 下午4:21:37 */ public class TextUtil { /** * 分析文本水印中文字所占的宽度 * @param text * @return */ public static int getTextLength(String text){ int length = text.length(); // 循环分析文本中的每一个字符 for(int i=0;i<length;i++){ String s = String.valueOf(text.charAt(i)); if(s.getBytes().length>1){// 如果字节长度大于1,则为中文 length++; }// 如果是因为字符则不进行处理 } // 最后做折半处理 length = length%2==0?length/2:length/2+1; return length; } }
- 上传要添加水印的图片的业务逻辑处理类,即图片上传类UploadService
package com.watermark.service; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; /** * 图片上传逻辑 * @author aibinxiao * @date 2017年6月6日 上午10:52:49 */ public class UploadService { /** * 上传图片的方法 * @param Image 上传的图片 * @param imageFileName 上传图片的名称 * @param uploadPath 上传图片的相对路径 * @param realUploadPath 上传的绝对路径 * @return 上传图片后相对的返回路径 */ public String uploadImage(File image,String imageFileName,String uploadPath,String realUploadPath){ // 思路: // 1.通过输入流使用循环不断去读取图片数据,如果读到了数据,说明没有读完, // 2.然后将图片数据通过输出流写入我们的目标文件里 InputStream is = null; OutputStream os = null; try { is = new FileInputStream(image); // 输入流读取图片 os = new FileOutputStream(realUploadPath+File.separator+imageFileName); // 输出流,指向我们最终要保存的路径,即绝对路径+文件名 byte[] buffer = new byte[1024]; // 创建一个字节数组,用来保存每次读取到的图片数据 int len = 0; // 用来表示我们每次读取到的数组长度 while((len=is.read(buffer))>0){ os.write(buffer); // 如果读取数组长度大于0,说明读取到了图片数据,然后我们通过输出流,写入到目标文件中 } } catch (Exception e) { e.printStackTrace(); }finally { if(is!=null){ try { is.close(); } catch (Exception e2) { e2.printStackTrace(); } } if(os!=null){ try { os.close(); } catch (Exception e2) { e2.printStackTrace(); } } } return uploadPath + File.separator + imageFileName; } }
- 添加单个文字水印的业务逻辑处理类TextMarkService
package com.watermark.service; import java.awt.AlphaComposite; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import javax.imageio.ImageIO; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGImageEncoder; import com.watermark.util.TextUtil; /** * 为图片添加单个文字水印 * @author aibinxiao * @date 2017年6月6日 上午11:54:47 */ 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 { Image image2 = ImageIO.read(image); // ImageIO工具类,通过read方法去解码对应的图片文件,解码成一个相应的图片对象,在这个对象中就存储这图片的高度、宽度等信息 int width = image2.getWidth(null); int height = image2.getHeight(null); BufferedImage bufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);// 三个参数,图片的高度、宽度、颜色信息 // BufferedImage.TYPE_INT_RGB 图像颜色设置,用我们这个对象具有整数像素的8位RGB颜色 // 创建绘图工具,专门用于二维图像和文本的处理 Graphics2D g = bufferedImage.createGraphics(); // 将原图通过绘图工具绘制到缓存图片对象 g.drawImage(image2, 0, 0, width, height, null); // 参数:1.原图; 23.绘制坐标:因为原图和缓存图片对象高度宽度一致,所以绘制过程中坐标为0; 45.绘制图片的高度宽度:设置为原图的高度宽度即可 // 为图片添加一个文字水印 g.setFont(new Font(FONT_NAME,FONT_STYLE,FONT_SIZE));// 设置文字水印的字体信息 g.setColor(FONT_COLOR);// 设置文字水印的颜色 // 获取文字水印的高度、宽度值 int width1 = FONT_SIZE * TextUtil.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坐标大于宽度差,则表示文字水印无法在横向无法完整显示,所以设置为最大值,即宽度差 x = widthDiff; } if(y>heightDiff){// 同x y = heightDiff; } // 设置文字水印的透明度 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,ALPHA)); g.drawString(MARK_TEXT, x, y + FONT_SIZE);// 注意y坐标需要坐小的调整,需要加上文字大小的参数,因为y坐标值指向的位置是文字水印文本内容的下方,如果不加会导致文字水印靠上显示,导致文字水印显示不全 g.dispose();// 释放图片绘制工具,此时添加了水印的图片已经生成,但仍然在内存中 // 创建文件输出流,指向最终目标文件 os = new FileOutputStream(realUploadPath + File.separator + logoFileName); // 创建图像编码工具类 JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os); // 使用图片编码工具类对象将内存中的图片对象输出到目标文件中去 en.encode(bufferedImage); } catch (Exception e) { e.printStackTrace(); }finally { if(os!=null){ try { os.close(); } catch (Exception e2) { e2.printStackTrace(); } } } return uploadPath + File.separator + logoFileName;// 返回添加水印后的图像路径 } }
- 添加多个文字水印的业务逻辑处理类MultiTextMarkService
package com.watermark.service; import java.awt.AlphaComposite; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import javax.imageio.ImageIO; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGImageEncoder; import com.watermark.util.TextUtil; /** * 多个文字水印 * @author aibinxiao * @date 2017年6月6日 下午4:08:56 */ public class MultiTextMarkService implements MarkService { @Override public String watermark(File image, String imageFileName, String uploadPath, String realUploadPath) { String logoFileName = "logo_" + imageFileName; OutputStream os = null; try { Image image2 = ImageIO.read(image); // ImageIO工具类,通过read方法去解码对应的图片文件,解码成一个相应的图片对象,在这个对象中就存储这图片的高度、宽度等信息 int width = image2.getWidth(null); int height = image2.getHeight(null); // 创建缓存图片对象 BufferedImage bufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);// 三个参数,图片的高度、宽度、颜色信息 // BufferedImage.TYPE_INT_RGB 图像颜色设置,用我们这个对象具有整数像素的8位RGB颜色 // 创建绘图工具,专门用于二维图像和文本的处理 Graphics2D g = bufferedImage.createGraphics(); // 将原图通过绘图工具绘制到缓存图片对象 g.drawImage(image2, 0, 0, width, height, null); // 参数:1.原图; 23.绘制坐标:因为原图和缓存图片对象高度宽度一致,所以绘制过程中坐标为0; 45.绘制图片的高度宽度:设置为原图的高度宽度即可 // 为图片添加一个文字水印 g.setFont(new Font(FONT_NAME,FONT_STYLE,FONT_SIZE));// 设置文字水印的字体信息 g.setColor(FONT_COLOR);// 设置文字水印的颜色 // 获取文字水印的高度、宽度值 int width1 = FONT_SIZE * TextUtil.getTextLength(MARK_TEXT); int height1 = FONT_SIZE; // 设置文字水印的透明度 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,ALPHA)); // 倾斜图片,参数1:倾斜角度(单位:幅度),所需需要通过Math将角度转换位幅度,参数23: 为旋转圆心坐标,设置为图片的中心,即高度和宽度的1/2 g.rotate(Math.toRadians(30), bufferedImage.getWidth()/2, bufferedImage.getHeight()/2); // X,Y坐标的设置,由于倾斜之后,X,Y坐标都在一定程度增大了,但是为了避免不必要的计算,我们直接扩大一倍,所以X和Y的向左向上做一个移动 int x = -width/2; int y = -height/2; // 将宽度扩展1/2 while(x < width * 1.5){ y = -height/2;// 每次移动之后,y值做一个重新的设定,保证文字水印是从上到下的添加 while(y < height * 1.5){ // 将高度扩展1/2,再通过循环最终完成多个水印的添加 g.drawString(MARK_TEXT, x, y); y += height1 + 240; // 每次y坐标向下移动,并且在添加新的水印时,加上一定的高度间隔,设置为240px } x += width1 + 240; // 每次x坐标向右移动,并且在添加新的水印时,加上一定的宽度间隔,设置为240px } g.dispose();// 释放图片绘制工具,此时添加了水印的图片已经生成,但仍然在内存中 // 创建文件输出流,指向最终目标文件 os = new FileOutputStream(realUploadPath + File.separator + logoFileName); // 创建图像编码工具类 JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os); // 使用图片编码工具类对象将内存中的图片对象输出到目标文件中去 en.encode(bufferedImage); } catch (Exception e) { e.printStackTrace(); }finally { if(os!=null){ try { os.close(); } catch (Exception e2) { e2.printStackTrace(); } } } return uploadPath + File.separator + logoFileName;// 返回添加水印后的图像路径 } }
- 添加单个图片水印的业务逻辑处理类ImageMarkService
package com.watermark.service; import java.awt.AlphaComposite; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import javax.imageio.ImageIO; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGImageEncoder; /** * 为图片添加单个图片水印 * @author aibinxiao * @date 2017年6月6日 下午3:32:51 */ public class ImageMarkService implements MarkService { @Override public String watermark(File image, String imageFileName, String uploadPath, String realUploadPath) { String logoFileName = "logo_" + imageFileName; OutputStream os = null; // logo水印所在路径 String logoPath = realUploadPath + File.separator + LOGO; try { Image image2 = ImageIO.read(image); // ImageIO工具类,通过read方法去解码对应的图片文件,解码成一个相应的图片对象,在这个对象中就存储这图片的高度、宽度等信息 int width = image2.getWidth(null); int height = image2.getHeight(null); BufferedImage bufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);// 三个参数,图片的高度、宽度、颜色信息 // BufferedImage.TYPE_INT_RGB 图像颜色设置,用我们这个对象具有整数像素的8位RGB颜色 // 创建绘图工具,专门用于二维图像和文本的处理 Graphics2D g = bufferedImage.createGraphics(); // 将原图通过绘图工具绘制到缓存图片对象 g.drawImage(image2, 0, 0, width, height, null); // 参数:1.原图; 23.绘制坐标:因为原图和缓存图片对象高度宽度一致,所以绘制过程中坐标为0; 45.绘制图片的高度宽度:设置为原图的高度宽度即可 // 为图片添加一个图片水印 File logo = new File(logoPath); Image imageLogo = ImageIO.read(logo);// 通过ImageIo工具类去分析logo图片的高度宽度等信息 int width1 = imageLogo.getWidth(null); int height1 = imageLogo.getHeight(null); // 计算原图与图片水印的高度、宽度差,防止水印过大,不能全部在图片上 int widthDiff = width - width1; int heightDiff = height - height1; int x = X; int y = Y; if(x>widthDiff){//如果x坐标大于宽度差,则表示图片水印无法在横向无法完整显示,所以设置为最大值,即宽度差 x = widthDiff; } if(y>heightDiff){// 同x y = heightDiff; } // 设置文字水印的透明度 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,ALPHA)); g.drawImage(imageLogo, x, y, null); g.dispose();// 释放图片绘制工具,此时添加了水印的图片已经生成,但仍然在内存中 // 创建文件输出流,指向最终目标文件 os = new FileOutputStream(realUploadPath + File.separator + logoFileName); // 创建图像编码工具类 JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os); // 使用图片编码工具类对象将内存中的图片对象输出到目标文件中去 en.encode(bufferedImage); } catch (Exception e) { e.printStackTrace(); }finally { if(os!=null){ try { os.close(); } catch (Exception e2) { e2.printStackTrace(); } } } return uploadPath + File.separator + logoFileName;// 返回添加水印后的图像路径 } }
- 添加多个图片水印的业务逻辑处理类MultiImageMarkService
package com.watermark.service; import java.awt.AlphaComposite; import java.awt.Graphics2D; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import javax.imageio.ImageIO; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGImageEncoder; /** * 多个图片水印 * @author aibinxiao * @date 2017年6月6日 下午4:58:59 */ public class MultiImageMarkServie implements MarkService { @Override public String watermark(File image, String imageFileName, String uploadPath, String realUploadPath) { String logoFileName = "logo_" + imageFileName; OutputStream os = null; try { Image image2 = ImageIO.read(image); // ImageIO工具类,通过read方法去解码对应的图片文件,解码成一个相应的图片对象,在这个对象中就存储这图片的高度、宽度等信息 int width = image2.getWidth(null); int height = image2.getHeight(null); BufferedImage bufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);// 三个参数,图片的高度、宽度、颜色信息 // BufferedImage.TYPE_INT_RGB 图像颜色设置,用我们这个对象具有整数像素的8位RGB颜色 // 创建绘图工具,专门用于二维图像和文本的处理 Graphics2D g = bufferedImage.createGraphics(); // 将原图通过绘图工具绘制到缓存图片对象 g.drawImage(image2, 0, 0, width, height, null); // 参数:1.原图; 23.绘制坐标:因为原图和缓存图片对象高度宽度一致,所以绘制过程中坐标为0; 45.绘制图片的高度宽度:设置为原图的高度宽度即可 // 创建一个变量,指向我们添加的图片logo的水印 String logoPath = realUploadPath + File.separator + LOGO; File logo = new File(logoPath); Image imageLogo = ImageIO.read(logo);// 通过ImageIo工具类去分析logo图片的高度宽度等信息 int width1 = imageLogo.getWidth(null); int height1 = imageLogo.getHeight(null); // 设置文字水印的透明度 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,ALPHA)); // 倾斜图片,参数1:倾斜角度(单位:幅度),所需需要通过Math将角度转换位幅度,参数23: 为旋转圆心坐标,设置为图片的中心,即高度和宽度的1/2 g.rotate(Math.toRadians(30), bufferedImage.getWidth()/2, bufferedImage.getHeight()/2); // X,Y坐标的设置,由于倾斜之后,X,Y坐标都在一定程度增大了,但是为了避免不必要的计算,我们直接扩大一倍,所以X和Y的向左向上做一个移动 int x = -width/2; int y = -height/2; // 将宽度扩展1/2 while(x < width * 1.5){ y = -height/2;// 每次移动之后,y值做一个重新的设定,保证文字水印是从上到下的添加 while(y < height * 1.5){ // 将高度扩展1/2,再通过循环最终完成多个水印的添加 g.drawImage(imageLogo, x, y, null); y += height1 + 240; // 每次y坐标向下移动,并且在添加新的水印时,加上一定的高度间隔,设置为240px } x += width1 + 240; // 每次x坐标向右移动,并且在添加新的水印时,加上一定的宽度间隔,设置为240px } g.dispose();// 释放图片绘制工具,此时添加了水印的图片已经生成,但仍然在内存中 // 创建文件输出流,指向最终目标文件 os = new FileOutputStream(realUploadPath + File.separator + logoFileName); // 创建图像编码工具类 JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os); // 使用图片编码工具类对象将内存中的图片对象输出到目标文件中去 en.encode(bufferedImage); } catch (Exception e) { e.printStackTrace(); }finally { if(os!=null){ try { os.close(); } catch (Exception e2) { e2.printStackTrace(); } } } return uploadPath + File.separator + logoFileName;// 返回添加水印后的图像路径 } }
- 接收添加水印请求的WaterMarkAction类
package com.watermark.action; import java.io.File; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; import com.watermark.entity.PicInfo; import com.watermark.service.ImageMarkService; import com.watermark.service.MultiImageMarkServie; import com.watermark.service.MultiTextMarkService; import com.watermark.service.TextMarkService; import com.watermark.service.UploadService; /** * 水印处理的Action * @author aibinxiao * @date 2017年6月6日 上午10:44:07 */ public class WaterMarkAction extends ActionSupport{ private File image; // 要上传的图片文件 private String imageFileName; // 要上传的图片文件名 private String uploadPath; // 要上传的图片文件相对路径 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; } PicInfo picInfo = new PicInfo(); public PicInfo getPicInfo() { return picInfo; } public void setPicInfo(PicInfo picInfo) { this.picInfo = picInfo; } /** * 添加单个文字水印的图片上传以及添加文字水印的添加请求 * @return * @throws Exception */ public String textWaterMark() throws Exception{ // 绝对路径,是基于我们的相对路径来获取的 String realUploadPath = ServletActionContext.getServletContext().getRealPath(uploadPath); UploadService uploadService = new UploadService(); TextMarkService textMarkService = new TextMarkService(); // 设置图片上传后返回的相对路径 picInfo.setImageURL(uploadService.uploadImage(image, imageFileName, uploadPath, realUploadPath)); // 设置文字水印 picInfo.setLogoImageURL(textMarkService.watermark(image, imageFileName, uploadPath, realUploadPath)); return SUCCESS; } /** * 添加多个文字水印的图片上传以及添加文字水印的添加请求 * @return * @throws Exception */ public String multiTextWaterMark() throws Exception{ // 绝对路径,是基于我们的相对路径来获取的 String realUploadPath = ServletActionContext.getServletContext().getRealPath(uploadPath); UploadService uploadService = new UploadService(); MultiTextMarkService multiTextMarkService = new MultiTextMarkService(); // 设置图片上传后返回的相对路径 picInfo.setImageURL(uploadService.uploadImage(image, imageFileName, uploadPath, realUploadPath)); // 设置文字水印 picInfo.setLogoImageURL(multiTextMarkService.watermark(image, imageFileName, uploadPath, realUploadPath)); return SUCCESS; } /** * 添加单个图片水印的图片上传以及添加文字水印的添加请求 * @return * @throws Exception */ public String imageWaterMark() throws Exception{ // 绝对路径,是基于我们的相对路径来获取的 String realUploadPath = ServletActionContext.getServletContext().getRealPath(uploadPath); UploadService uploadService = new UploadService(); ImageMarkService imageMarkService = new ImageMarkService(); // 设置图片上传后返回的相对路径 picInfo.setImageURL(uploadService.uploadImage(image, imageFileName, uploadPath, realUploadPath)); // 设置文字水印 picInfo.setLogoImageURL(imageMarkService.watermark(image, imageFileName, uploadPath, realUploadPath)); return SUCCESS; } /** * 添加多个图片水印的图片上传以及添加文字水印的添加请求 * @return * @throws Exception */ public String multiImageWaterMark() throws Exception{ // 绝对路径,是基于我们的相对路径来获取的 String realUploadPath = ServletActionContext.getServletContext().getRealPath(uploadPath); UploadService uploadService = new UploadService(); MultiImageMarkServie multiImageMarkService = new MultiImageMarkServie(); // 设置图片上传后返回的相对路径 picInfo.setImageURL(uploadService.uploadImage(image, imageFileName, uploadPath, realUploadPath)); // 设置文字水印 picInfo.setLogoImageURL(multiImageMarkService.watermark(image, imageFileName, uploadPath, realUploadPath)); return SUCCESS; } }
- 接收批量添加水印请求的BatchWaterMarkAction类
package com.watermark.action; import java.io.File; import java.util.ArrayList; import java.util.List; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; import com.watermark.entity.PicInfo; import com.watermark.service.ImageMarkService; import com.watermark.service.MultiImageMarkServie; import com.watermark.service.MultiTextMarkService; import com.watermark.service.TextMarkService; import com.watermark.service.UploadService; /** * 批量水印处理的Action * @author aibinxiao * @date 2017年6月6日 上午10:44:07 */ public class BatchWaterMarkAction extends ActionSupport{ private File[] image; // 要上传的图片文件数组 private String[] imageFileName; // 要上传的图片文件名数组 private String uploadPath; // 要上传的图片文件相对路径 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; } private List<PicInfo> picInfo = new ArrayList<PicInfo>(); public List<PicInfo> getPicInfo() { return picInfo; } public void setPicInfo(List<PicInfo> picInfo) { this.picInfo = picInfo; } /** * 批量处理添加单个文字水印的图片上传以及添加文字水印的添加请求 * @return * @throws Exception */ public String textWaterMark() throws Exception{ // 绝对路径,是基于我们的相对路径来获取的 String realUploadPath = ServletActionContext.getServletContext().getRealPath(uploadPath); UploadService uploadService = new UploadService(); TextMarkService textMarkService = new TextMarkService(); // 对上传文件数组做一个判断 if(image!=null && image.length>0){ for (int i=0;i<image.length;i++) { PicInfo pic = new PicInfo(); // 设置图片上传后返回的相对路径 pic.setImageURL(uploadService.uploadImage(image[i], imageFileName[i], uploadPath, realUploadPath)); // 设置文字水印 pic.setLogoImageURL(textMarkService.watermark(image[i], imageFileName[i], uploadPath, realUploadPath)); // 将每个处理好的,添加到数组中 picInfo.add(pic); } } return SUCCESS; } /** * 批量处理添加多个文字水印的图片上传以及添加文字水印的添加请求 * @return * @throws Exception */ public String multiTextWaterMark() throws Exception{ // 绝对路径,是基于我们的相对路径来获取的 String realUploadPath = ServletActionContext.getServletContext().getRealPath(uploadPath); UploadService uploadService = new UploadService(); MultiTextMarkService multiTextMarkService = new MultiTextMarkService(); // 对上传文件数组做一个判断 if(image!=null && image.length>0){ for (int i=0;i<image.length;i++) { PicInfo pic = new PicInfo(); // 设置图片上传后返回的相对路径 pic.setImageURL(uploadService.uploadImage(image[i], imageFileName[i], uploadPath, realUploadPath)); // 设置文字水印 pic.setLogoImageURL(multiTextMarkService.watermark(image[i], imageFileName[i], uploadPath, realUploadPath)); // 将每个处理好的,添加到数组中 picInfo.add(pic); } } return SUCCESS; } /** * 批量处理添加单个图片水印的图片上传以及添加文字水印的添加请求 * @return * @throws Exception */ public String imageWaterMark() throws Exception{ // 绝对路径,是基于我们的相对路径来获取的 String realUploadPath = ServletActionContext.getServletContext().getRealPath(uploadPath); UploadService uploadService = new UploadService(); ImageMarkService imageMarkService = new ImageMarkService(); // 对上传文件数组做一个判断 if(image!=null && image.length>0){ for (int i=0;i<image.length;i++) { PicInfo pic = new PicInfo(); // 设置图片上传后返回的相对路径 pic.setImageURL(uploadService.uploadImage(image[i], imageFileName[i], uploadPath, realUploadPath)); // 设置文字水印 pic.setLogoImageURL(imageMarkService.watermark(image[i], imageFileName[i], uploadPath, realUploadPath)); // 将每个处理好的,添加到数组中 picInfo.add(pic); } } return SUCCESS; } /** * 批量处理添加多个图片水印的图片上传以及添加文字水印的添加请求 * @return * @throws Exception */ public String multiImageWaterMark() throws Exception{ // 绝对路径,是基于我们的相对路径来获取的 String realUploadPath = ServletActionContext.getServletContext().getRealPath(uploadPath); UploadService uploadService = new UploadService(); MultiImageMarkServie multiImageMarkService = new MultiImageMarkServie(); // 对上传文件数组做一个判断 if(image!=null && image.length>0){ for (int i=0;i<image.length;i++) { PicInfo pic = new PicInfo(); // 设置图片上传后返回的相对路径 pic.setImageURL(uploadService.uploadImage(image[i], imageFileName[i], uploadPath, realUploadPath)); // 设置文字水印 pic.setLogoImageURL(multiImageMarkService.watermark(image[i], imageFileName[i], uploadPath, realUploadPath)); // 将每个处理好的,添加到数组中 picInfo.add(pic); } } return SUCCESS; } }
- 写好这些之后,我们来写请求的jsp页面,首先是index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>图片上传主页</title> </head> <body> <a href="${pageContext.request.contextPath}/textmark.jsp">添加单个文字水印</a><br/> <a href="${pageContext.request.contextPath}/multitextmark.jsp">添加多个文字水印</a><br/> <a href="${pageContext.request.contextPath}/imagemark.jsp">添加单个图片水印</a><br/> <a href="${pageContext.request.contextPath}/multiimagemark.jsp">添加多个图片水印</a><br/> <a href="${pageContext.request.contextPath}/batchtextmark.jsp">批量处理添加单个文字水印</a><br/> <a href="${pageContext.request.contextPath}/batchmultitextmark.jsp">批量处理添加多个文字水印</a><br/> <a href="${pageContext.request.contextPath}/batchimagemark.jsp">批量处理添加单个图片水印</a><br/> <a href="${pageContext.request.contextPath}/batchmultiimagemark.jsp">批量处理添加多个图片水印</a><br/> </body> </html>
- 添加单个文字水印的jsp页面,textmark.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>添加单个文字水印</title> </head> <body> <h4>添加单个文字水印</h4> <h4>上传图片</h4> <hr/> <form name = "form1" action="${pageContext.request.contextPath}/textWaterMark.action" method="post" enctype="multipart/form-data"> <input type="file" name="image"/><br/> <input type="submit" value="上传需要添加文字水印的图片"/> </form> <hr/> <a href="${pageContext.request.contextPath}/index.jsp">返回首页</a><br/> </body> </html>
- 上传要添加单个文字水印的图片后,返回的jsp页面,来显示添加水印前后对比的jsp页面,showtextmark.jsp
添加单个文字水印的展示效果图:<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib uri="/struts-tags" prefix="s" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>单个文字水印添加效果展示</title> </head> <body> <table> <tr> <td width="50%"><img src='${pageContext.request.contextPath }<s:property value="picInfo.imageURL"/>' width="350" /></td> <td width="50%"><img src='${pageContext.request.contextPath }<s:property value="picInfo.logoImageURL"/>' width="350" /></td> </tr> </table> <hr/> <a href="${pageContext.request.contextPath}/index.jsp">返回首页</a><br/> </body> </html>
-
添加多个文字水印的jsp页面,multitextmark.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>添加多个文字水印</title> </head> <body> <h4>添加多个文字水印</h4> <h4>上传图片</h4> <hr/> <form name = "form1" action="${pageContext.request.contextPath}/multiTextWaterMark.action" method="post" enctype="multipart/form-data"> <input type="file" name="image"/><br/> <input type="submit" value="上传需要添加文字水印的图片"/> </form> <hr/> <a href="${pageContext.request.contextPath}/index.jsp">返回首页</a><br/> </body> </html>
- 上传要添加多个文字水印的图片后,返回的jsp页面,来显示添加水印前后对比的jsp页面,showmultitextmark.jsp
添加多个文字水印的展示效果图:<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib uri="/struts-tags" prefix="s" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>多个文字水印添加效果展示</title> </head> <body> <table> <tr> <td width="50%"><img src='${pageContext.request.contextPath }<s:property value="picInfo.imageURL"/>' width="350" /></td> <td width="50%"><img src='${pageContext.request.contextPath }<s:property value="picInfo.logoImageURL"/>' width="350" /></td> </tr> </table> <hr/> <a href="${pageContext.request.contextPath}/index.jsp">返回首页</a><br/> </body> </html>
-
批量添加单个文字水印的jsp页面,batchtextmark.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>批量处理添加单个文字水印</title> </head> <body> <h4>批量处理添加单个文字水印</h4> <h4>上传图片</h4> <hr/> <form name = "form1" action="${pageContext.request.contextPath}/batchTextWaterMark.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/> <input type="submit" value="上传需要添加文字水印的图片"/> </form> <hr/> <a href="${pageContext.request.contextPath}/index.jsp">返回首页</a><br/> </body> </html>
- 上传要添加单个文字水印的多张图片后,返回的jsp页面,来显示添加水印前后对比的jsp页面,batchshowtextmark.jsp
批量添加单个文字水印的展示效果图:<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib uri="/struts-tags" prefix="s" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>批量处理单个文字水印添加效果展示</title> </head> <body> <h4>批量处理单个文字水印添加效果展示</h4> <table> <s:iterator value="picInfo"> <tr> <td width="50%"><img src='${pageContext.request.contextPath }<s:property value="imageURL"/>' width="350" /></td> <td width="50%"><img src='${pageContext.request.contextPath }<s:property value="logoImageURL"/>' width="350" /></td> </tr> </s:iterator> </table> <hr/> <a href="${pageContext.request.contextPath}/index.jsp">返回首页</a><br/> </body> </html>
-
批量添加多个文字水印的jsp页面,batchmultitextmark.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>批量处理添加多个文字水印</title> </head> <body> <h4>批量处理添加多个文字水印</h4> <h4>上传图片</h4> <hr/> <form name = "form1" action="${pageContext.request.contextPath}/batchMultiTextWaterMark.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/> <input type="submit" value="上传需要添加文字水印的图片"/> </form> <hr/> <a href="${pageContext.request.contextPath}/index.jsp">返回首页</a><br/> </body> </html>
- 上传要添加多个文字水印的多张图片后,返回的jsp页面,来显示添加水印前后对比的jsp页面,batchshowmultitextmark.jsp
批量添加多个文字水印的展示效果图:<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib uri="/struts-tags" prefix="s" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>批量处理多个文字水印添加效果展示</title> </head> <body> <h4>批量处理多个文字水印添加效果展示</h4> <table> <s:iterator value="picInfo"> <tr> <td width="50%"><img src='${pageContext.request.contextPath }<s:property value="imageURL"/>' width="350" /></td> <td width="50%"><img src='${pageContext.request.contextPath }<s:property value="logoImageURL"/>' width="350" /></td> </tr> </s:iterator> </table> <hr/> <a href="${pageContext.request.contextPath}/index.jsp">返回首页</a><br/> </body> </html>
注意:上面效果图左上角的水印,是我在写博客时再加上去的,然后就是水印文字可以在MarkServic接口中,进行修改,其他水印处理类都继承自MarkServic接口,并实现了添加相应水印的方法。大家可以试着从前端传递要添加的文字水印,然后图片水印添加的示例就不在演示,大家可以自己试一试,不过在添加图片水印时,需要现在WebContent下创建一个images的文件夹,并放入一张名称为logo.png的水印logo图片,当然你同样可以在MarkService接口中进行修改!
这个案例的源码,大家可以在这里下载学习:https://github.com/xiaoaibin/WaterMark.git
希望对大家的学习有所帮助!
本文为原创文章,如果对你有一点点的帮助,别忘了点赞哦!比心!如需转载,请注明出处,谢谢!