java 添加水印 清除水印

在学生时代便实现java打水印的程序,现在工作却找不到曾经写的代码,记录下来方便以后使用。

先谈谈需求:

①一张图片可以被多张logo打水印,但一张图片只能打一个水印,避免重复水印。

②支持清除本地图片水印功能(清楚已存在水印的图片,是有侵权的嫌疑)。

当然,实际业务需求复杂了很多。

开放中遇到的问题:

①A图片添加a水印后,清除水印再去添加b水印时。页面依旧显示a水印。

②清除水印时返回的图片路径有误。


添加水印的方法:

/**
     * 水印图 
     * @param originalImagePath 	需打水印的原图片路径
     * @param watermarkImagePath 	水印后的图片路径
     * @param alpha 				透明度
     * @param x 					距x轴的距离
     * @param y 					距y轴的距离
     * @return
     */
    public static byte[] imageWatermarkProcess(String originalImagePath,String watermarkImagePath, float alpha, int x, int y) {
		try {
			// 原图
			Image original = Toolkit.getDefaultToolkit().getImage(originalImagePath);
			original = new ImageIcon(original).getImage();
			int width = original.getWidth(null);
			int height = original.getHeight(null);
			BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
			Graphics2D graphics2d = bufferedImage.createGraphics();
			graphics2d.drawImage(original, 0, 0, width, height, null);
			// 水印图
			Image watermark = Toolkit.getDefaultToolkit().getImage(watermarkImagePath);
			watermark = new ImageIcon(watermark).getImage();
			int watermarkWidth = watermark.getWidth(null);
			int watermarkHeight = watermark.getHeight(null);
			graphics2d.setComposite(AlphaComposite.getInstance(10, alpha));
			graphics2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
			int widthDiff = width - watermarkWidth;
			int heightDiff = height - watermarkHeight;
			// 若水印图尺寸大于原图,等比例缩小1/4
			if (widthDiff <= 0 || heightDiff <= 0) {
				watermarkWidth /= 4;
				watermarkHeight /= 4;
				widthDiff = width - watermarkWidth;
				heightDiff = height - watermarkHeight;
			}
			// 保证水印图全部出现在原图中
			if (x < 0)
				x = widthDiff / 2;
			else if (x > widthDiff) {
				x = widthDiff;
			}
			if (y < 0)
				y = heightDiff / 2;
			else if (y > heightDiff) {
				y = heightDiff;
			}
			graphics2d.drawImage(watermark, x, y, watermarkWidth,watermarkHeight, null);
			graphics2d.dispose();
			String fileType = originalImagePath.substring(originalImagePath.lastIndexOf(".") + 1);
			ByteArrayOutputStream baops = new ByteArrayOutputStream();
			ImageIO.write(bufferedImage, fileType, baops);
			return baops.toByteArray();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

调用添加水印的方法:

public static String mergeWaterMark(String imagePath,String logoPath) {
    	if (null == imagePath || -1 != imagePath.indexOf("-merge-") || null == logoPath) {
    		return "ERROR";
    	}
    	String watermarkPath = imagePath.substring(0,imagePath.lastIndexOf('/')+1);
    	// 添加随机4位的数字目的是为了避免切换其他logo合成水印后,页面图片依然显示第一次logo水印合成图片(缓存的原因)
    	String watermarkImagePath = imagePath.substring(0,imagePath.lastIndexOf("."))+"-merge-"+ new Random().nextInt(9999) +".jpg";
    	FileOutputStream fos = null;
		BufferedOutputStream bos = null;
    	File imgDir = new File(watermarkPath);
		if(!imgDir.exists()){
			imgDir.mkdirs();
		}
		File fileImg = new File(watermarkImagePath);
		try {
			fos = new FileOutputStream(fileImg);
			bos = new BufferedOutputStream(fos);
			bos.write(imageWatermarkProcess(imagePath, logoPath, 1.0F,10,10));
		} catch (Exception e) {
			e.printStackTrace();
			return "ERROR";
		} finally {
			try {
				if(null != bos){
					bos.close();
				}
				if(null != fos){
					fos.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return watermarkImagePath;
	}

清除水印方法:

public static String clearWaterMark(String imagePath){
    	String clearName = imagePath.substring(imagePath.lastIndexOf("-merge-"),imagePath.lastIndexOf('.'));
    	String originalImagePath = imagePath.replace(clearName,"");
    	// 清除水印后删除水印图片
    	File fileImg = new File(imagePath);
		if (fileImg.isFile()) {
			fileImg.delete();
		}
		// 返回原图地址
		return originalImagePath;
    }

测试代码:

public static void main(String[] args) {
    	// 路径为绝对路径
    	String logoImg = "F:/myWebsite/sierew/src/main/java/com/real/utils/logo.png";
    	String originalImg = "F:/myWebsite/sierew/src/main/java/com/real/utils/no1.jpg";
//    	String watermarkImage = mergeWaterMark(originalImg,logoImg);
    	String watermarkImage = "F:/myWebsite/sierew/src/main/java/com/real/utils/no1-merge-9458.jpg";
//    	System.out.println(watermarkImage);
    	String originalImgage = clearWaterMark(watermarkImage);
    	System.out.println(originalImgage);
	}

以上便是核心代码,写的不是很精细。是考虑到业务不同,改动也会很大。


对于问题①:曾经打算用清除缓存的方法来解决,可是不能为了一个图片而影响了整个体验。就打算在生成水印图片后添加一个随机数,让其返回的路径不一样,这样显示的图片就不一样了。这样会对清除水印带来了一点麻烦。

对于问题②:水印图a,b要给图片A,B,C。当图片A,B,C的路径不一样的时候,无规律的执行打水印和清除水印的操作会导致清除图片的路径发送问题。因为点击清除水印获取的imagePath是上一个添加水印的imagePath,因为图片路径不一样,所以会导致404的问题。解决方法是用js先将图片路径全部获取,然后通过文件名匹配,因为是下班的时候遇到的bug,所以方法很low。

留着备忘,也希望能帮到大伙。


效果图:)



个人主页:http://www.itit123.cn/ 更多干货等你来拿
















  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值