用java实现给图片增加图片水印或者文字水印(也支持视频图像帧添加水印)

2018-06-19 16:38:06

javaCV图像处理系列:

javaCV图像处理之1:实时视频添加文字水印并截取视频图像保存成图片,实现文字水印的字体、位置、大小、粗度、翻转、平滑等操作

javaCV图像处理之2:实时视频添加图片水印,实现不同大小图片叠加,图像透明度控制

  

前言:

这是个很常用的操作,一般我们的网站在用户上传图片时都会给图片添加一个水印以防止其他站点盗图的行为

实现功能:①给图片增加文字水印②给图片增加图片水印

一、核心功能实现:

1、添加文字水印

[java] view plain copy

  1. // 加文字水印  

  2.     public void mark(BufferedImage bufImg, Image img, String text, Font font, Color color, int x, int y) {  

  3.         Graphics2D g = bufImg.createGraphics();  

  4.         g.drawImage(img, 00, bufImg.getWidth(), bufImg.getHeight(), null);  

  5.         g.setColor(color);  

  6.         g.setFont(font);  

  7.         g.drawString(text, x, y);  

  8.         g.dispose();  

  9.     }  

2、添加图片水印


[java] view plain copy

  1. // 加图片水印  

  2.     public void mark(BufferedImage bufImg, Image img, Image markImg, int width, int height, int x, int y) {  

  3.         Graphics2D g = bufImg.createGraphics();  

  4.         g.drawImage(img, 00, bufImg.getWidth(), bufImg.getHeight(), null);  

  5.         g.drawImage(markImg, x, y, width, height, null);  

  6.         g.dispose();  

  7.     }  



以上两个方法实现了最核心的功能:给图片添加水印。

补充:

为什么要这么写?

考虑到该方法不仅可以用于给图片文件增加水印,而且还可以给视频的每一帧图像也添加,所以为了方便不同场合重复使用,去除了不必要的依赖关系。

有了核心的两个方法就我们可以给图片文件增加水印了

二、功能性实现

1、给图片增加文字水印

[java] view plain copy

  1. /** 

  2.      * 给图片增加文字水印 

  3.      *  

  4.      * @param imgPath 

  5.      *            -要添加水印的图片路径 

  6.      * @param outImgPath 

  7.      *            -输出路径 

  8.      * @param text-文字 

  9.      * @param font 

  10.      *            -字体 

  11.      * @param color 

  12.      *            -颜色 

  13.      * @param x 

  14.      *            -文字位于当前图片的横坐标 

  15.      * @param y 

  16.      *            -文字位于当前图片的竖坐标 

  17.      */  

  18.     public void mark(String imgPath, String outImgPath, String text, Font font, Color color, int x, int y) {  

  19.         try {  

  20.             // 读取原图片信息  

  21.             File imgFile = null;  

  22.             Image img = null;  

  23.             if (imgPath != null) {  

  24.                 imgFile = new File(imgPath);  

  25.             }  

  26.             if (imgFile != null && imgFile.exists() && imgFile.isFile() && imgFile.canRead()) {  

  27.                 img = ImageIO.read(imgFile);  

  28.             }  

  29.             int imgWidth = img.getWidth(null);  

  30.             int imgHeight = img.getHeight(null);  

  31.             // 加水印  

  32.             BufferedImage bufImg = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);  

  33.             mark(bufImg, img, text, font, color, x, y);  

  34.             // 输出图片  

  35.             FileOutputStream outImgStream = new FileOutputStream(outImgPath);  

  36.             ImageIO.write(bufImg, "jpg", outImgStream);  

  37.             outImgStream.flush();  

  38.             outImgStream.close();  

  39.         } catch (Exception e) {  

  40.             e.printStackTrace();  

  41.         }  

  42.     }  




2、给图片增加图片水印

[java] view plain copy

  1. /** 

  2.      * 给图片增加图片水印 

  3.      *  

  4.      * @param inputImg 

  5.      *            -源图片,要添加水印的图片 

  6.      * @param markImg 

  7.      *            - 水印图片 

  8.      * @param outputImg 

  9.      *            -输出图片(可以是源图片) 

  10.      * @param width 

  11.      *            - 水印图片宽度 

  12.      * @param height 

  13.      *            -水印图片高度 

  14.      * @param x 

  15.      *            -横坐标,相对于源图片 

  16.      * @param y 

  17.      *            -纵坐标,同上 

  18.      */  

  19.     public void mark(String inputImg, String markImg, String outputImg, int width, int height, int x, int y) {  

  20.         // 读取原图片信息  

  21.         File inputImgFile = null;  

  22.         File markImgFile = null;  

  23.         Image img = null;  

  24.         Image mark = null;  

  25.         try {  

  26.             if (inputImg != null && markImg != null) {  

  27.                 inputImgFile = new File(inputImg);  

  28.                 markImgFile = new File(markImg);  

  29.             }  

  30.             if (inputImgFile != null && inputImgFile.exists() && inputImgFile.isFile() && inputImgFile.canRead()) {  

  31.   

  32.                 img = ImageIO.read(inputImgFile);  

  33.   

  34.             }  

  35.             if (markImgFile != null && markImgFile.exists() && markImgFile.isFile() && markImgFile.canRead()) {  

  36.   

  37.                 mark = ImageIO.read(markImgFile);  

  38.   

  39.             }  

  40.             int imgWidth = img.getWidth(null);  

  41.             int imgHeight = img.getHeight(null);  

  42.             BufferedImage bufImg = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);  

  43.             mark(bufImg, img, mark, width, height, x, y);  

  44.             FileOutputStream outImgStream = new FileOutputStream(outputImg);  

  45.             ImageIO.write(bufImg, "jpg", outImgStream);  

  46.             outImgStream.flush();  

  47.             outImgStream.close();  

  48.         } catch (IOException e) {  

  49.             e.printStackTrace();  

  50.         }  

  51.     }  


3、测试一下效果


文字水印的字体和颜色需要自行定义,这里我们使用宋体,14号字体,颜色选择橙色 - -!,坐标是x轴0,y轴等于字体的大小,也就是图片的左上角。

[java] view plain copy

  1. public static void main(String[] args) {  

  2.         Font font = new Font("宋体", Font.PLAIN, 14);  

  3.         // 原图位置, 输出图片位置, 水印文字颜色, 水印文字  

  4.         // new MarkText4J().mark("eguidMarkText2.jpg", "eguidMarkText2.jpg", "水印效果测试", font, Color.ORANGE, 0, 14);  

  5.         // 增加图片水印  

  6.         new MarkText4J().mark("eguidMarkText2.jpg""eguid.jpg""eguidMarkText3.jpg"4020014);  

  7.     }  

简直棒极了,至此我们可以随意的给图片任意位置添加任意文字或者图片水印了。

最后,额。。。导出的图片比原本图片还小是什么鬼?欢迎加入讨论群一起讨论:371249677。- -!

  • 2018-08-20 15:26:19

    关于OnTouch 和OnClick同时调用冲突的解决方案

    大家在搞轮播图的时候会碰到这样的情况,点击进入webview界面,长按轮播图停止轮播,手松开图又开始轮播,这里就涉及到了OnTouch 和OnClick同时调用。两者是有冲突的。这里简单介绍,给大家提供思路。

  • 2018-08-20 15:29:11

    揭开RecyclerView的神秘面纱(二):处理RecyclerView的点击事件

    主要讲述了RecyclerView的基本使用方法,不同的布局管理器而造成的多样化展示方式,展示了数据之后,一般都会与用户进行交互,因此我们需要处理用户的点击事件。在ListView和GridView提供了onItemClickListener这个监听器,然而我们查找RecyclerView的API却没有类似的监听器,因此我们需要自己手动处理它的点击事件。 以下提供两种方法来实现处理RecyclerView点击事件的功能,以下代码均基于上一篇文章的代码做出修改。

  • 2018-08-20 22:58:46

    onInterceptTouchEvent和onTouchEvent调用关系详解 ...

    老实说,这两个小东东实在是太麻烦了,很不好懂,我自己那api文档都头晕,在网上找到很多资料,才知道是怎么回事,这里总结一下,记住这个原则就会很清楚了:

  • 2018-08-23 15:32:18

    map对象拷贝问题

    最后面是使用序列化的方式,发现,更改引用类型的数据的时候,mapNew对象并没有发生变化,所以产生了深拷贝。 上述的工具类,可以实现对象的深拷贝,不仅限于HashMap,前提是实现了Serlizeable接口。

  • 2018-08-24 11:33:17

    总结和分析几种判断 RecyclerView 到达底部的方法

    SwipeRefreshLayout 写一个 RecyclerView 的上下拉 ,里面有一个判断 RecyclerView 是否到达底部的方法 isBottom。我的同事用了这个上下拉之后发现有些小 bug,没考虑周全,譬如各个子项高度不统一的时候,然后我找到原因是因为这个判断上下拉的问题。所以,我就去网上查到几种判断 RecyclerView 到达底部的方法,发现各有千秋。以下的分析都以上一篇文章的 SwipeRecyclerView 为例

  • 2018-08-26 00:18:04

    RecyclerView 图片错位空白的问题

    1.图片错位的原因是因为图片异步记载返回去展示出的问题。图片空白,是item刷新,请求图片时间上的问题。 2。viewHolder.setIsRecyclable(false); 就没有tag,不设置 就有tag,但是有没有没啥区别 设置tag,

  • 2018-08-28 10:00:24

    laravel使用队列的简单步骤

    最近需要导入大量的excel文件,数量达到十万之多。 而我又不想修改服务器的超时时间,因为这样可能影响服务器的堵塞。 而php又没有很好的异步。 后来发现了令laravel最为骄傲的部分,队列。具体文档参考下方链接。