图片添加水印

来源:互联网 发布: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