Java 给图片和动图添加水印的方法

 更新时间:2018年04月22日 12:56:21   作者:TheSmallWhite  
本篇文章主要介绍了Java 给图片和动图添加水印的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

这两天根据需求在做图片上传添加水印,实话说重来不知道java还可以这样操作,既然有个这要求我就去找资料研究了一番,现在把它分享一下,希望能帮到有需要的兄弟。

给普通图片添加水印和给动图添加水印是不一样的,给普通图片添加水印用的是java自带的方法写的,给动图使用了gif4j框架,这个框架在CSDN里面很多可以下载,建议下载破解版的,因为原来的jar包会有自带的一个水印是去不了的。

import java.awt.*; 
import java.awt.image.BufferedImage; 
import java.io.*;  
import javax.imageio.ImageIO; 
import javax.swing.ImageIcon;   
//这下面是 gif4j 框架的类 
import com.gif4j.GifDecoder; 
import com.gif4j.GifEncoder; 
import com.gif4j.GifImage; 
import com.gif4j.GifTransformer; 
import com.gif4j.TextPainter; 
import com.gif4j.Watermark;   
/** 
 * Created by ZXD on 2018/1/18. 
 */ 
public class ImageRemarkUtil { 
  // 水印透明度 
  private float alpha = 0.5f; 
  // 水印横向位置 
  private int positionWidth = 150; 
  // 水印纵向位置 
  private int positionHeight = 300; 
  //水印宽 
  private int width = 80; 
  //水印高 
  private int height = 80; 
  // 水印文字字体 
  private Font font = new Font("宋体", Font.BOLD, 72); 
  // 水印文字颜色 
  private Color color = Color.red; 
  
  
  /***********普通图片加水印***********/ 
  
  /** 
   * 
   * @param alpha 
   *      水印透明度 
   * @param positionWidth 
   *      水印横向位置 
   * @param positionHeight 
   *      水印纵向位置 
   * @param font 
   *      水印文字字体 
   * @param color 
   *      水印文字颜色 
   */ 
  public void setImageMarkOptions(float alpha, int positionWidth, 
                      int positionHeight,int width,int height, Font font, Color color) { 
    if (alpha != 0.0f) 
      this.alpha = alpha; 
    if (positionWidth != 0) 
      this.positionWidth = positionWidth; 
    if (positionHeight != 0) 
      this.positionHeight = positionHeight; 
    if (height != 0) 
      this.height = height; 
    if (width != 0) 
      this.width = width; 
    if (font != null) 
      this.font = font; 
    if (color != null) 
      this.color = color; 
  } 
  
  /** 
   * 给图片添加水印图片 
   * 
   * @param iconPath 
   *      水印图片路径 
   * @param srcImgPath 
   *      源图片路径 
   * @param targerPath 
   *      目标图片路径 
   */ 
  public void markImageByIcon(String iconPath, String srcImgPath, 
                    String targerPath) { 
    markImageByIcon(iconPath, srcImgPath, targerPath, null); 
  } 
  
  /** 
   * 给图片添加水印图片、可设置水印图片旋转角度 
   * 
   * @param iconPath 
   *      水印图片路径 
   * @param srcImgPath 
   *      源图片路径 
   * @param targerPath 
   *      目标图片路径 
   * @param degree 
   *      水印图片旋转角度 
   */ 
  public void markImageByIcon(String iconPath, String srcImgPath, 
                    String targerPath, Integer degree) { 
    OutputStream os = null; 
    try { 
  
      Image srcImg = ImageIO.read(new File(srcImgPath)); 
      BufferedImage buffImg = new BufferedImage(srcImg.getWidth(null), 
          srcImg.getHeight(null), BufferedImage.TYPE_INT_RGB); 
  
      // 1、得到画笔对象 
      Graphics2D g = buffImg.createGraphics(); 
  
      // 2、设置对线段的锯齿状边缘处理 
      g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 
          RenderingHints.VALUE_INTERPOLATION_BILINEAR); 
  
      g.drawImage( 
          srcImg.getScaledInstance(srcImg.getWidth(null), 
              srcImg.getHeight(null), Image.SCALE_SMOOTH), 0, 0, 
          null); 
      // 3、设置水印旋转 
      if (null != degree) { 
        g.rotate(Math.toRadians(degree), 
            (double) buffImg.getWidth() / 2, 
            (double) buffImg.getHeight() / 2); 
      } 
  
      // 4、水印图片的路径 水印图片一般为gif或者png的,这样可设置透明度 
      ImageIcon imgIcon = new ImageIcon(iconPath); 
  
      // 5、得到Image对象。 
      Image img = imgIcon.getImage(); 
  
      g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 
          alpha)); 
  
      Integer X = srcImg.getWidth(null); 
  
      Integer Y = srcImg.getHeight(null); 
  
      // 6、水印图片的位置 
      g.drawImage(img, X-(positionWidth+width), Y-(positionHeight+height),width,height,null); 
  
      g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); 
      // 7、释放资源 
      g.dispose(); 
  
      // 8、生成图片 
      os = new FileOutputStream(targerPath); 
      ImageIO.write(buffImg, "JPG", os); 
  
      System.out.println("图片完成添加水印图片"); 
  
    } catch (Exception e) { 
      e.printStackTrace(); 
    } finally { 
      try { 
        if (null != os) 
          os.close(); 
      } catch (Exception e) { 
        e.printStackTrace(); 
      } 
    } 
  } 
  
  /** 
   * 给图片添加水印文字 
   * 
   * @param logoText 
   *      水印文字 
   * @param srcImgPath 
   *      源图片路径 
   * @param targerPath 
   *      目标图片路径 
   */ 
  public void markImageByText(String logoText, String srcImgPath, 
                    String targerPath) { 
    markImageByText(logoText, srcImgPath, targerPath, null); 
  } 
  
  /** 
   * 给图片添加水印文字、可设置水印文字的旋转角度 
   * 
   * @param logoText 
   * @param srcImgPath 
   * @param targerPath 
   * @param degree 
   */ 
  public void markImageByText(String logoText, String srcImgPath, 
                    String targerPath, Integer degree) { 
  
    InputStream is = null; 
    OutputStream os = null; 
    try { 
      // 1、源图片 
      Image srcImg = ImageIO.read(new File(srcImgPath)); 
      BufferedImage buffImg = new BufferedImage(srcImg.getWidth(null), 
          srcImg.getHeight(null), BufferedImage.TYPE_INT_RGB); 
  
      // 2、得到画笔对象 
      Graphics2D g = buffImg.createGraphics(); 
      // 3、设置对线段的锯齿状边缘处理 
      g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 
          RenderingHints.VALUE_INTERPOLATION_BILINEAR); 
      g.drawImage( 
          srcImg.getScaledInstance(srcImg.getWidth(null), 
              srcImg.getHeight(null), Image.SCALE_SMOOTH), 0, 0, 
          null); 
      // 4、设置水印旋转 
      if (null != degree) { 
        g.rotate(Math.toRadians(degree), 
            (double) buffImg.getWidth() / 2, 
            (double) buffImg.getHeight() / 2); 
      } 
      // 5、设置水印文字颜色 
      g.setColor(color); 
      // 6、设置水印文字Font 
      g.setFont(font); 
      // 7、设置水印文字透明度 
      g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 
          alpha)); 
      // 8、第一参数->设置的内容,后面两个参数->文字在图片上的坐标位置(x,y) 
      g.drawString(logoText, positionWidth, positionHeight); 
      // 9、释放资源 
      g.dispose(); 
      // 10、生成图片 
      os = new FileOutputStream(targerPath); 
      ImageIO.write(buffImg, "JPG", os); 
  
      System.out.println("图片完成添加水印文字"); 
  
    } catch (Exception e) { 
      e.printStackTrace(); 
    } finally { 
      try { 
        if (null != is) 
          is.close(); 
      } catch (Exception e) { 
        e.printStackTrace(); 
      } 
      try { 
        if (null != os) 
          os.close(); 
      } catch (Exception e) { 
        e.printStackTrace(); 
      } 
    } 
  } 
   
  /*********** 动图加水印 ************/ 
  
  /** 
   * 缩放gif图片,直接传的File文件,可设置宽和高 
   */ 
  public void makeGif(File src, File dest, int width, int height) throws IOException { 
      GifImage gifImage = GifDecoder.decode(src);// 创建一个GifImage对象. 
      GifImage resizeIMG = GifTransformer.resize(gifImage, width, height, true); 
      GifEncoder.encode(resizeIMG, dest); 
    } 
   //缩放gif图片,直接传文件路径,可设置宽和高 
  public void makeGif(String src, String dest, int width, int height) throws IOException { 
    GifImage gifImage = GifDecoder.decode(new File(src));// 创建一个GifImage对象.   
    makeGif(new File(src), new File(dest), gifImage.getScreenWidth() / 2, 
        gifImage.getScreenHeight() / 2); 
  
  } 
   //缩放gif图片,传文件File文件,不可设置宽和高 
  public void makeGif(File src, File dest) throws IOException {   
    GifImage gifImage = GifDecoder.decode(src);// 创建一个GifImage对象.   
    makeGif(src, dest, gifImage.getScreenWidth() / 2, gifImage.getScreenHeight() / 2);   
  } 
   //缩放gif图片,传文件路径,不可设置宽和高 
  public void makeGif(String src, String dest) throws IOException {   
    makeGif(new File(src), new File(dest));   
  } 
  
  /** 
   * 动图中加文字水印 
   */ 
  public void addTextWatermarkToGif(File src, String watermarkText, File dest)throws IOException {   
    //水印初始化、设置(字体、样式、大小、颜色)   
    TextPainter textPainter = new TextPainter(new Font("黑体", Font.ITALIC, 12));   
    textPainter.setOutlinePaint(Color.WHITE);   
    BufferedImage renderedWatermarkText = textPainter.renderString(watermarkText, true);   
    //图片对象 
    GifImage gf = GifDecoder.decode(src);   
    //获取图片大小   
    int iw = gf.getScreenWidth();   
    int ih = gf.getScreenHeight();   
    //获取水印大小 
      int tw = renderedWatermarkText.getWidth();   
    int th = renderedWatermarkText.getHeight();   
    //水印位置   
    Point p = new Point(); 
    p.x = iw - tw - 5; 
    p.y = ih - th - 4; 
      //加水印 
    Watermark watermark = new Watermark(renderedWatermarkText, p); 
    gf = watermark.apply(GifDecoder.decode(src), true); 
    //输出 
    GifEncoder.encode(gf, dest); 
  } 
  
  /** 
   * 动图中加图片水印 
   */ 
  public void addImageWatermarkToGif(File src, String watermarkPath, File dest){ 
  
    try{ 
  
      BufferedImage renderedWatermarkText = ImageIO.read(new File(watermarkPath)); 
  
      //图片对象 
      GifImage gf = GifDecoder.decode(src); 
  
      //获取图片大小 
      int iw = gf.getScreenWidth(); 
      int ih = gf.getScreenHeight(); 
  
      //获取水印大小 
      int tw = renderedWatermarkText.getWidth(); 
      int th = renderedWatermarkText.getHeight(); 
  
      //水印位置 
      Point p = new Point(); 
      p.x = iw-tw-20; 
      p.y = ih-th-20; 
  
      //加水印 
      Watermark watermark = new Watermark(renderedWatermarkText, p); 
      //水印透明度 
      watermark.setTransparency(1); 
      gf = watermark.apply(GifDecoder.decode(src), false); 
      //输出 
      GifEncoder.encode(gf, dest); 
    } catch (IOException e){ 
      e.printStackTrace(); 
    } 
  }  
  
  public static void main(String[] args) { 
    //需要加水印图片的路径 
    String srcImgPath = "d:/1.jpg"; 
    String logoText = "复 印 无 效"; 
    //图片水印的路径 
    String iconPath = "d:/2.jpg"; 
  
     //添加完水印文件的输出路径 
    String targerTextPath = "d:/qie_text.jpg"; 
    String targerTextPath2 = "d:/qie_text_rotate.jpg"; 
    String targerIconPath = "d:/qie_icon.jpg"; 
    String targerIconPath2 = "d:/qie_icon_rotate.jpg"; 
  
    System.out.println("给图片添加水印文字开始..."); 
    // 给图片添加水印文字 
    markImageByText(logoText, srcImgPath, targerTextPath); 
    // 给图片添加水印文字,水印文字旋转-45 
    markImageByText(logoText, srcImgPath, targerTextPath2, -45); 
    System.out.println("给图片添加水印文字结束..."); 
  
    System.out.println("给图片添加水印图片开始..."); 
    setImageMarkOptions(0.3f, 1, 1, null, null); 
     // 给图片添加水印图片 
    markImageByIcon(iconPath, srcImgPath, targerIconPath); 
    // 给图片添加水印图片,水印图片旋转-45 
    markImageByIcon(iconPath, srcImgPath, targerIconPath2, -45); 
    System.out.println("给图片添加水印图片结束..."); 
  
    //动图添加水印(添加水印动图文件,添加的水印,添加完输出文件) 
    addTextWatermarkToGif(new File("d:\\10.gif"), "复 印 无 效", new File("d:\\11.gif")); 
    addImageWatermarkToGif(new File("d:\\gif\\10.gif"), "d:\\gif\\3.png", new File("d:\\gif\\4.gif"));   
  }   
} 

这里面有普通图片添加水印和动图添加水印,普通图片添加水印方法如果传的是动图能添加成功,但是动图就成静态的了,动图添加水印方法如果传的是普通图片,会直接报错了。

这些我在做的时候都有试过,现在就当记笔记记录在此,也希望能帮助到有需要的兄弟。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Java数组操作的10大方法

    Java数组操作的10大方法

    下面是精心整理的Java数组操作的10大方法,大部分代码都来自Stack Overflow,需要的朋友可以参考下
    2014-09-09
  • SpringBoot整合Redis实现刷票过滤功能

    SpringBoot整合Redis实现刷票过滤功能

    随着互联网的不断发展,网站或APP的用户流量增加,也衍生出了一些恶意刷量等问题,给数据分析及运营带来极大的困难,所以本文使用SpringBoot和Redis实现一个刷票过滤功能,需要的可以参考一下
    2023-06-06
  • SpringMVC如何获取表单数据(radio和checkbox)

    SpringMVC如何获取表单数据(radio和checkbox)

    这篇文章主要介绍了SpringMVC如何获取表单数据(radio和checkbox)的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • java设计模式--建造者模式详解

    java设计模式--建造者模式详解

    这篇文章主要介绍了Java设计模式之建造者模式,结合具体实例形式分析了建造者模式的概念、原理、实现方法与相关使用注意事项,需要的朋友可以参考下
    2021-07-07
  • 图解Java排序算法之3种简单排序

    图解Java排序算法之3种简单排序

    这篇文章主要为大家详细介绍了Java排序算法之3种简单排序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • 利用maven引入第三方jar包以及打包

    利用maven引入第三方jar包以及打包

    Maven是通过仓库对依赖进行管理的,当Maven项目需要某个依赖时,只要其POM中声明了依赖的坐标信息,Maven就会自动从仓库中去下载该构件使用,如何将jar引用到项目,并且能够让项目正常调用该jar包的方法,本篇文章重点针对于这两点进行讲解
    2023-05-05
  • 浅谈Java虚拟机对内部锁的四种优化方式

    浅谈Java虚拟机对内部锁的四种优化方式

    这篇文章主要介绍了浅谈Java虚拟机对内部锁的四种优化方式,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • Spring 中 PageHelper 不生效问题及解决方法

    Spring 中 PageHelper 不生效问题及解决方法

    这篇文章主要介绍了Spring 中 PageHelper 不生效问题,使用这个插件时要注意版本的问题,不同的版本可能 PageHelper 不会生效,本文结合示例代码给大家介绍的非常详细,需要的朋友可以参考下
    2022-12-12
  • Java中负数的绝对值竟然不一定是正数

    Java中负数的绝对值竟然不一定是正数

    这篇文章主要介绍了Java中负数的绝对值竟然不一定是正数,文中给大家提到Java 中怎么把负数转换为正数,需要的朋友可以参考下
    2021-07-07
  • 为什么wait和notify必须放在synchronized中使用

    为什么wait和notify必须放在synchronized中使用

    这篇文章主要介绍了为什么wait和notify必须放在synchronized中使用,文章围绕主题的相关问题展开详细介绍,具有一定的参考价值,需要的小伙伴可以参考以参考一下
    2022-05-05

最新评论