`

java实现为图片添加水印

阅读更多

这个水印功能是看的慕课网的视频自己跟着学的,视频连接如下:http://www.imooc.com/learn/482

 

图片文件的上传界面、上传功能以及页面展示,这里就不再写了,可以去struts2环境下实现文件上传看,也可以去慕课网看视频。这里就记录下生成水印的代码。

先说说实现水印功能的思路:
1、创建图片缓存对象
2、创建绘图工具对象(有点类似于画布)
3、使用绘图工具对象将原图绘制到缓存图像对象中
4、使用绘图工具对象将水印(文字/图片)绘制到缓存图片对象中
5、创建图像编码工具类
6、使用图像编码工具类输出缓存图像到目标文件中

以下为水印功能的具体实现:

1、用来集中处理业务逻辑的Action(这里用的例子是一次性为多张图片添加水印):

public class WaterMarkAction extends ActionSupport{
	private File[] image;
	private String[] imageFileName;
	private String uploadPath;
	private List<PicInfo> picInfo = new ArrayList<PicInfo>();
	public String waterMark() throws Exception{
		String realUploadPath = ServletActionContext.getServletContext().getRealPath(uploadPath);
		if(image!=null && image.length>0){
			PicInfo pic=null;
			UploadService uploadService = new UploadService();//该service用来上传文件
			//MarkService markService = new TextMarkService();//文字水印
			//MarkService markService = new ImageMarkService();//图片水印
			//MarkService markService = new MoreTextMarkService();//多文字水印
			MarkService markService = new MoreImageMarkService();//多图片水印
			for(int i=0;i<image.length;i++){
				pic = new PicInfo();
				//上传图片
				pic.setImageURL(uploadService.uploadImage(image[i], imageFileName[i], uploadPath, realUploadPath));
				//添加水印效果
				pic.setLogoImageURL(markService.watermark(image[i], imageFileName[i], uploadPath, realUploadPath));
				picInfo.add(pic);
			}
		}
		return SUCCESS;
	}

	//image、imageFileName、uploadPath、pic的get/set方法
}

 

2、定义实现水印功能的接口:添加的水印包括四种情况:单一文字水印、单一图片水印、多文字水印、多图片水印。所以这里将实现水印的功能定义成了一个抽象类(除了有需要子类实现的方法外还有子类需要用到的公用方法),抽象类代码如下:

public abstract class MarkService {
	public static final String MARK_TEXT="慕课网";//添加水印的文字
	
	public static final String FONT_NAME="微软雅黑";//所用字体
	public static final int FONT_STYLE = Font.BOLD;//文字样式,这里设置为加粗
	public static final  int FONT_SIZE = 80;//文字大小
	public static final  Color FONT_COLOR = Color.BLACK;//文字颜色
	
	//文字/图片位置
	public static final int X=10;//横坐标
	public static final int Y=10;//纵坐标
	public static final float ALPHA=0.3F;//透明度
	
	//作为水印添加到图片文件中的图片名称
	public static final String LOGO="logo.png";
	
	/**
	 * 添加水印功能
	 * @param image:需要添加水印的图片文件
	 * @param imageFileName:图片文件名称
	 * @param uploadPath:文件上传的相对路径
	 * @param realUploadPath:处理后的文件所在的绝对路径(目前上传的文件与处理后的文件在同一目录下)
	 * */
	public abstract String watermark(File image,String imageFileName,String uploadPath,String realUploadPath);
	
	//获取文本长度
	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){//字节长度大于1,说明是中文,那么需要延长文本长度
				length++;
			}
		}
		//计算总共有多少个字节,也就是有多少个字
		length = (length%2==0)?length/2:length/2+1;
		return length;
	}
}

3、单一文字水印的实现:

public class TextMarkService extends MarkService {
	public String watermark(File image, String imageFileName,
			String uploadPath, String realUploadPath) {
		String logoImageName = "logo_"+imageFileName;
		OutputStream out = null;
		try{
			//1、创建图片缓存对象
			//获取原图信息
			Image image2 = ImageIO.read(image);
			int width = image2.getWidth(null);//宽
			int height = image2.getHeight(null);//高
			
			//构造一个类型为预定义图像类型之一的 BufferedImage
			//TYPE_INT_RGB:表示一个图像,它具有合成整数像素的 8 位 RGB 颜色分量
			BufferedImage bfImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
			
			//2、创建绘图工具对象(有点类似于画布)
			Graphics2D graph = bfImage.createGraphics();
			
			//3、使用绘图工具对象将原图绘制到缓存图像对象中
			graph.drawImage(image2, 0, 0, width, height, null);
			graph.setFont(new Font(FONT_NAME,FONT_STYLE,FONT_SIZE));//设置字体
			graph.setColor(FONT_COLOR);//设置字体颜色
			
			//4、使用绘图工具对象将水印(文字/图片)绘制到缓存图片对象中
			//获取水印文字的宽高
			int textW = FONT_SIZE * getTextLength(MARK_TEXT);
			int textH = FONT_SIZE;
			
			//获取原图与水印图的宽度、高度之差
			int wDiff = width-textW;
			int hDiff = height-textH;
			//设置初始位置
			int x=X;
			int y=Y;
			//保证当前图片至少可以放下一个水印文字
			if(x>wDiff){
				x = wDiff;
			}
			if(y>hDiff){
				y = hDiff;
			}
			//设置透明度
			//AlphaComposite.getInstance:创建一个 AlphaComposite 对象,
			//它具有指定的规则和用来乘源色 alpha 值的常量 alpha 值。
			//在将源色与目标色合成前,要将源色乘以指定的 alpha 值。
			graph.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,ALPHA));
			//添加水印效果
			graph.drawString(MARK_TEXT, x, y+FONT_SIZE);//y保证至少可以显示一个水印的高度
			//释放graph
			graph.dispose();
			
			out = new FileOutputStream(realUploadPath+File.separator+logoImageName);
			//5、创建图像编码工具类
			JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(out);
			//6、使用图像编码工具类输出缓存图像到目标文件中
			en.encode(bfImage);
			
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			//关闭流
			try{
				if(out!=null){
					out.close();
				}
			}catch(Exception e){
				e.printStackTrace();
			}
		}
		return uploadPath+File.separator+logoImageName;
	}
}

 4、多文字水印功能实现:多文字水印与单一文字水印的实现差不多,所不同的是:需要旋转画布并且每次都需要计算水印与画布之间的间距以保证整个图片上都有水印。

public class MoreTextMarkService extends MarkService {
	public String watermark(File image, String imageFileName,
			String uploadPath, String realUploadPath) {
		String logoImageName = "logo_"+imageFileName;
		OutputStream out = null;
		//1、创建图片缓存对象
		try{
			//获取原图信息
			Image image2 = ImageIO.read(image);
			int width = image2.getWidth(null);//宽
			int height = image2.getHeight(null);//高
			
			BufferedImage bfImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
			
			//2、创建绘图工具对象
			Graphics2D graph = bfImage.createGraphics();
			
			//3、使用绘图工具对象将原图绘制到缓存图像对象中
			graph.drawImage(image2, 0, 0, width, height, null);
			graph.setFont(new Font(FONT_NAME,FONT_STYLE,FONT_SIZE));//设置字体
			graph.setColor(FONT_COLOR);//设置字体颜色
			
			//4、使用绘图工具对象将水印(文字/图片)绘制到缓存图片对象中
			//获取水印文字的宽高
			int textW = FONT_SIZE * getTextLength(MARK_TEXT);
			int textH = FONT_SIZE;
			
			//设置透明度
			graph.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,ALPHA));
			
			//设置旋转角度及旋转中心
			//Math.toDegrees():将用弧度表示的角转换为近似相等的用角度表示的角
			//Math.toRadians():将用角度表示的角转换为近似相等的用弧度表示的角,rotate的第一个参数是用弧度表示的,所以使用toRadians方法
			//相同的设置成30,结果为:toDegrees方法添加倒置的水印,toRadians添加正置的水印
			graph.rotate(Math.toRadians(30),bfImage.getWidth()/2, bfImage.getHeight()/2);
			
			int x = -width/2;
			int y= -height/2;
			while(x<width*1.5){
				y = -height/2;
				while(y<height*1.5){
					//添加水印效果
					graph.drawString(MARK_TEXT, x, y);//y保证至少可以显示一个水印的高度
					y +=textH+200;//200为间隔值,即每个水印之间的间隔
				}
				x +=textW+200;
			}
			//释放graph
			graph.dispose();
			
			out = new FileOutputStream(realUploadPath+File.separator+logoImageName);
			//5、创建图像编码工具类
			JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(out);
			//6、使用图像编码工具类输出缓存图像到目标文件中
			en.encode(bfImage);
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			//关闭流
			try{
				if(out!=null){
					out.close();
				}
			}catch(Exception e){
				e.printStackTrace();
			}
		}
		return uploadPath+File.separator+logoImageName;
	}
}

代码中while循环是用来计算水印和画布之间的间距问题的,我能理解原理但是说不出来,可以看这个视频(http://www.imooc.com/video/10602)去参悟参悟,人家用动画说的可清楚啦。

这里还有个容易误导的地方:我们平时看到的水印都是相对于图片偏转一定角度的,实际上在实现的过程中,水印文字没有倾斜,图片也没有偏转,偏转的是画布。使用绘图工具Graphics2D绘画都是水平画的,也就是从左往右画,画布是水平的绘画的内容也是水平的,画出来的东西也自然是水平的。但是在绘画过程中将画布倾斜再水平画内容,画完后再将画布放水平,画出来的东西自然也就有一定的倾斜角度了。这是水印文字总会有一定倾斜幅度的原理。(讲原理的视频链接:http://www.imooc.com/video/10760

 

5、单一图片水印功能实现:与文字所不同的是,文字计算文字的大小这里计算图片的大小,且还需要读取图片文件。

public class ImageMarkService extends MarkService {
	public String watermark(File image, String imageFileName,
			String uploadPath, String realUploadPath) {
		String logoImageName = "logo_"+imageFileName;
		OutputStream out = null;
		//用来作为水印的图片位置
		String logoFilePath = realUploadPath+File.separator+LOGO;
		try{
			//1、创建图片缓存对象
			//获取原图信息
			Image image2 = ImageIO.read(image);
			int width = image2.getWidth(null);//宽
			int height = image2.getHeight(null);//高
			
			BufferedImage bfImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
			
			//2、创建绘图工具对象
			Graphics2D graph = bfImage.createGraphics();
			
			//3、使用绘图工具对象将原图绘制到缓存图像对象中
			graph.drawImage(image2, 0, 0, width, height, null);
			
			//获取水印图片文件
			File logoFile = new File(logoFilePath);
			Image logoImage = ImageIO.read(logoFile);
			
			//4、使用绘图工具对象将水印(文字/图片)绘制到缓存图片对象中
			//获取水印文字的宽高
			int imageW = logoImage.getWidth(null);
			int imageH = logoImage.getHeight(null);
			
			//获取原图与水印图的宽度、高度之差
			int wDiff = width-imageW;
			int hDiff = height-imageH;
			//设置初始位置
			int x=X;
			int y=Y;
			if(x>wDiff){
				x = wDiff;
			}
			if(y>hDiff){
				y = hDiff;
			}
			//设置透明度
			graph.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,ALPHA));
			//添加水印效果
			graph.drawImage(logoImage, x, y,null);//y保证至少可以显示一个水印的高度
			//释放graph
			graph.dispose();
			
			out = new FileOutputStream(realUploadPath+File.separator+logoImageName);
			//5、创建图像编码工具类
			JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(out);
			//6、使用图像编码工具类输出缓存图像到目标文件中
			en.encode(bfImage);
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			try{
				if(out!=null){
					out.close();//关闭流
				}
			}catch(Exception e){
				e.printStackTrace();
			}
		}
		return uploadPath+File.separator+logoImageName;
	}
}

6、多图片水印功能实现:这个就是综合了单一图片和多文字水印的功能。

public class MoreImageMarkService extends MarkService {
	public String watermark(File image, String imageFileName,
			String uploadPath, String realUploadPath) {
		String logoImageName = "logo_"+imageFileName;
		OutputStream out = null;
		String logoFilePath = realUploadPath+File.separator+LOGO;
		//1、创建图片缓存对象
		try{
			//获取原图信息
			Image image2 = ImageIO.read(image);
			int width = image2.getWidth(null);//宽
			int height = image2.getHeight(null);//高
			
			BufferedImage bfImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
			
			//2、创建绘图工具对象
			Graphics2D graph = bfImage.createGraphics();
			
			//3、使用绘图工具对象将原图绘制到缓存图像对象中
			graph.drawImage(image2, 0, 0, width, height, null);
			//获取水印图片文件
			File logoFile = new File(logoFilePath);
			Image logoImage = ImageIO.read(logoFile);
			
			//4、使用绘图工具对象将水印(文字/图片)绘制到缓存图片对象中
			//获取水印文字的宽高
			int imageW = logoImage.getWidth(null);
			int imageH = logoImage.getHeight(null);
			
			//设置透明度
			graph.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,ALPHA));
			
			//设置旋转角度及旋转中心
			//Math.toDegrees():将用弧度表示的角转换为近似相等的用角度表示的角
			//Math.toRadians():将用角度表示的角转换为近似相等的用弧度表示的角,rotate的第一个参数是用弧度表示的,所以使用toRadians方法
			//相同的设置成30,结果为:toDegrees方法添加倒置的水印,toRadians添加正置的水印
			graph.rotate(Math.toRadians(30),bfImage.getWidth()/2, bfImage.getHeight()/2);
			
			int x = -width/2;
			int y= -height/2;
			while(x<width*1.5){
				y = -height/2;
				while(y<height*1.5){
					//添加水印效果
					graph.drawImage(logoImage, x, y,null);//y保证至少可以显示一个水印的高度
					y +=imageH+200;//200为间隔值,即每个水印之间的间隔
				}
				x +=imageW+200;
			}
			//释放graph
			graph.dispose();
			
			out = new FileOutputStream(realUploadPath+File.separator+logoImageName);
			//5、创建图像编码工具类
			JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(out);
			//6、使用图像编码工具类输出缓存图像到目标文件中
			en.encode(bfImage);
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			try{
				if(out!=null){
					out.close();//关闭流
				}
			}catch(Exception e){
				e.printStackTrace();
			}
		}
		return uploadPath+File.separator+logoImageName;
	}
}

 

分享到:
评论

相关推荐

    JAVA实现给图片增加图片水印或者文字水印-依赖包

    在Java编程中,给图片添加水印是一项常见的需求,无论是为了版权保护还是...但以上代码已经足够作为基础,帮助你开始在Java中实现图片加水印的功能。记得在运行此代码前,确保已经正确引入了Apache Commons Imaging库。

    java实现对图片加水印

    总结一下,Java 2D API和JAI库都能帮助我们实现图片加水印的功能。选择哪种方式取决于具体需求,如性能、复杂性和可用资源。理解这些概念和步骤,开发者就能根据实际情况编写出自己的Java代码,实现个性化的图片水印...

    采用java实现图片水印

    本篇文章将详细探讨如何使用Java实现图片水印的添加,以及相关的知识点。 首先,我们需要了解Java中的图像处理库。Java标准库提供了`java.awt`和`javax.imageio`包,它们包含了处理图像的基本功能。`java.awt`包中...

    java给图片添加水印

    以上就是使用Java和`Apache Commons Imaging`库为图片添加水印的基本步骤。这个工具类可以方便地对图片进行处理,无论是添加文字还是图片水印,都能灵活控制水印的位置、大小、透明度等属性。在实际项目中,可以根据...

    java实现图片上传并添加水印效果(文字水印,蒙版,logo图片),自动进行文字大小行数位置匹配 ,文字自动换行

    在Java编程中,实现图片上传并添加水印效果是一项常见的任务,这通常涉及到图像处理、图形用户界面(GUI)和文件I/O等多个方面。在这个项目中,我们将关注以下几个关键知识点: 1. **Java图像处理库**:Java标准库...

    java图片加水印(适应铺满)

    开发一个项目,需要用到图片加水印的功能,这里考虑使用后台加水印,在上传的时候或者回显到页面时候,取图片文件的流数据,进行加水印在返回流数据就行了,非常简单,不懂可以问我

    Java 实现word文件增加图片水印 jacob实现 用到的jar

    3. **添加水印**:利用Jacob提供的接口,创建并设置图片作为水印,然后将其插入Word文档。 ```java // 假设已有一个Image对象image代表你的水印图片 Dispatch insertImage = Dispatch.get(doc, "InlineShapes")....

    java Jacob完美实现word添加图片水印(内附源码及jar包)

    java Jacob完美实现word添加图片...公司最近让搞Word文档添加水印,所有下载的文档需要添加公司印章,搞了好多天才实现,利用Jacob完美实现word添加图片水印(注意需要把dll文件放到jdk的bin目录下)。欢迎大家下载指教。

    java操作excel实现水印图片

    java操作excel实现水印图片

    Java实现在图片上添加水印图片和水印文字.doc

    Java 实现图片添加水印图片和水印文字 Java 是一种广泛应用于企业级开发的编程语言,拥有强大灵活的图形处理能力。本文将详细介绍如何使用 Java 实现图片添加水印图片和水印文字,并对代码进行解释。 图片添加水印...

    java 图片水印 改变图片大小

    在Java编程领域,图片处理是一项常见的任务,包括添加水印、改变图片大小等。这里我们将深入探讨这些知识点,以及如何在Struts2框架下实现它们。 首先,让我们了解"图片水印"。水印通常用于保护版权或者为图片增加...

    springboot实现上传图片添加水印

    接下来,我们需要处理图片添加水印的逻辑。这个过程通常包括读取图片,生成水印(可以是文本或图像),然后将水印合并到原始图片上。在Java中,我们可以使用Java Advanced Imaging (JAI)库或者更现代的ImageMagick的...

    图片加水印 java代码实现

    图片加水印 java代码实现

    java+给图片添加水印

    在Java中给图片添加水印是一种常见的保护图片的方法,特别是在需要防止图片被盗用或者滥用的情况下。为了实现这一功能,Java提供了多种方式,其中常用的是使用ImageIO和Apache的Commons Imaging库。 ImageIO是Java...

    java 图片缩放、加水印

    图片操作类源代码,该类主要用于给图片进行缩放、加水印和得到图片的高、宽及类型。 具体操作请自己参照方法说明自己测试改写。

    水印 java Graphics2D实现文字图片水印

    下面将详细介绍如何使用Java Graphics2D实现文字和图片水印,以及如何在四个角落添加水印。 首先,我们要导入必要的Java库,包括java.awt和javax.imageio: ```java import java.awt.*; import java.awt.image....

    java 水印(水印适应图片大小,但个别图片太小不支持)

    要实现在Java中添加水印,我们可以利用开源的图像处理库,如Apache Commons Imaging(原名:Sanselan)、ImageMagick的Java绑定(JMagick)或Java Advanced Imaging (JAI)。这里以Apache Commons Imaging为例,因为...

    Java给图片加水印

    总之,Java通过其2D图形API提供了强大的功能,使得为图片添加水印变得相对简单。开发者可以根据实际需求调整水印的样式、位置和透明度,以达到理想的视觉效果。通过不断实践和学习,可以掌握更多关于Java图像处理的...

    java实现图片水印添加

    下面将详细介绍如何使用Java实现图片水印的添加。 首先,我们需要引入处理图像的库。Java标准库中的`javax.imageio`包提供了读取、写入和处理图像的基本功能,但不支持直接在图像上绘制文本或图形。因此,我们通常...

Global site tag (gtag.js) - Google Analytics