java 添加水印 清除水印
2016-07-12 12:25
691 查看
在学生时代便实现java打水印的程序,现在工作却找不到曾经写的代码,记录下来方便以后使用。
先谈谈需求:
①一张图片可以被多张logo打水印,但一张图片只能打一个水印,避免重复水印。
②支持清除本地图片水印功能(清楚已存在水印的图片,是有侵权的嫌疑)。
当然,实际业务需求复杂了很多。
开放中遇到的问题:
①A图片添加a水印后,清除水印再去添加b水印时。页面依旧显示a水印。
②清除水印时返回的图片路径有误。
添加水印的方法:
调用添加水印的方法:
清除水印方法:
测试代码:
以上便是核心代码,写的不是很精细。是考虑到业务不同,改动也会很大。
对于问题①:曾经打算用清除缓存的方法来解决,可是不能为了一个图片而影响了整个体验。就打算在生成水印图片后添加一个随机数,让其返回的路径不一样,这样显示的图片就不一样了。这样会对清除水印带来了一点麻烦。
对于问题②:水印图a,b要给图片A,B,C。当图片A,B,C的路径不一样的时候,无规律的执行打水印和清除水印的操作会导致清除图片的路径发送问题。因为点击清除水印获取的imagePath是上一个添加水印的imagePath,因为图片路径不一样,所以会导致404的问题。解决方法是用js先将图片路径全部获取,然后通过文件名匹配,因为是下班的时候遇到的bug,所以方法很low。
留着备忘,也希望能帮到大伙。
效果图:)
个人主页:http://www.itit123.cn/ 更多干货等你来拿
先谈谈需求:
①一张图片可以被多张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/ 更多干货等你来拿
相关文章推荐
- 使用Eclipse从数据库逆向生成实体类
- Java并发编程:深入剖析ThreadLocal
- eclipse使用git
- Java Web学习(6):认识JSP
- Java 数组的详解
- 如何测试java中对象的等价性
- java基础四:运算符
- java 中== equals hashcode源码剖析
- java 中关于抽象类和接口的区别
- java集合类(四)ArrayList与LinkedList比较
- Windows 7环境下配置Java Web开发环境
- 基于RESTful Web Service 的Jersey框架与Spring完美整合
- Phonegap的环境搭建
- JAVA中Properties的使用
- highcharts图形界面(Java从数据库获取值)
- Spring整合Struts2的两种方式
- 关于solr5版本的部署报错:java.lang.NoSuchMethodError: javax.servlet.ServletInputStream.isFinished()Z
- cxf+spring发布webservice接口及接口的调用
- java值数组初始化及异常
- java 路径问题