图片添加二维码水印教程详解编程语言

本博客介绍一下用jdk awt实现图片加文字水印和图片水印的方法

一、图片文字水印

import java.awt.AlphaComposite; 
import java.awt.Color; 
import java.awt.Font; 
import java.awt.Graphics2D; 
import java.awt.Image; 
import java.awt.RenderingHints; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.FileOutputStream; 
import java.io.OutputStream; 
 
import javax.imageio.ImageIO; 
import javax.swing.ImageIcon; 
 
 
public class WaterMarkIMGUtils { 
 
    /** 
     * @param args 
     */ 
    public static void main(String[] args) { 
        String srcImgPath = "C:/Users/zhaoh/Desktop/test.jpg"; 
        String targerPath1 = "C:/Users/zhaoh/Desktop/target1.jpg"; 
        WaterMarkIMGUtils.setWaterMarkForIMGByFontString(srcImgPath, targerPath1, 
                Color.blue, "公司内部资料"); 
    } 
 
    public static void setWaterMarkForIMGByFontString(String srcImgPath, String targerPath, Color markContentColor, String waterMarkContent){ 
        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); 
            // 得到画笔对象 
            Graphics2D g = buffImg.createGraphics(); 
            // 设置对线段的锯齿状边缘处理 
            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); 
            
            Font font = new Font("宋体", Font.PLAIN, 20); 
            g.setColor(markContentColor); // 根据图片的背景设置水印颜色 
            g.setFont(font); 
            int srcImgWidth = srcImg.getWidth(null); 
            int srcImgHeight = srcImg.getHeight(null); 
            int waterMarkLength = g.getFontMetrics(g.getFont()).charsWidth(waterMarkContent.toCharArray(), 0, waterMarkContent.length()); 
            int x = srcImgWidth - waterMarkLength - 3; 
            int y = srcImgHeight - 3; 
            g.drawString(waterMarkContent, x, y); 
             
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); 
            g.dispose(); 
 
            os = new FileOutputStream(targerPath); 
            // 生成图片 
            ImageIO.write(buffImg, "JPG", os); 
       } catch (Exception e) { 
           e.printStackTrace(); 
       } finally { 
           try { 
               if (null != os) 
                   os.close(); 
           } catch (Exception e) { 
               e.printStackTrace(); 
           } 
       } 
    } 
}

原来图片
在这里插入图片描述

加上文字水印后图片
在这里插入图片描述

二、图片加图片水印

 
import java.awt.AlphaComposite; 
import java.awt.Graphics2D; 
import java.awt.Image; 
import java.awt.RenderingHints; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.FileOutputStream; 
import java.io.OutputStream; 
 
import javax.imageio.ImageIO; 
import javax.swing.ImageIcon; 
public class WaterMarkIMGUtils { 
/** 
     * 给图片添加水印 
     * @param iconPath 
     *            水印图片路径 
     * @param srcImgPath 
     *            源图片路径 
     * @param targerPath 
     *            目标图片路径 
     * @param imgType 
     *          上传附件的类型 
     */ 
    public static void setWaterMarkForIMGByIcon(BufferedImage bufferedImage, InputStream in, OutputStream os, String imgType) { 
        setWaterMarkForIMG(iconPath, srcImgPath, targerPath, null, imgType); 
    } 
 
    /** 
     * 给图片添加水印 
     * @date   2019年6月12日下午2:11:11 
     * @param iconPath 
     *            水印图片路径 
     * @param srcImgPath 
     *            源图片路径 
     * @param targerPath 
     *            目标图片路径 
     * @param degree 
     *          选择角度 
     * @param imgType 
     *          上传附件的类型 
     */ 
    public static void setWaterMarkForIMGByIcon(String iconPath, String srcImgPath, String targerPath, Integer degree,String imgType) { 
        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); 
            // 得到画笔对象 
            Graphics2D g = buffImg.createGraphics(); 
            // 设置对线段的锯齿状边缘处理 
            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); 
            if (null != degree) { 
                // 设置水印旋转 
                g.rotate(Math.toRadians(degree), (double) buffImg.getWidth() / 2, (double) buffImg.getHeight() / 2); 
            } 
 
            // 水印图象的路径 水印一般为gif或者png的,这样可设置透明度 
            ImageIcon imgIcon = new ImageIcon(iconPath); 
            // 得到Image对象。 
            Image img = imgIcon.getImage(); 
            float alpha = 0.5f; // 透明度 
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha)); 
            // 表示水印图片的位置 
            g.drawImage(img, 150, 300, null); 
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); 
            g.dispose(); 
 
            os = new FileOutputStream(targerPath); 
            // 生成图片 
            ImageIO.write(buffImg, imgType, os); 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } finally { 
            try { 
                if (null != os) 
                    os.close(); 
            } catch (Exception e) { 
                e.printStackTrace(); 
            } 
        } 
    } 
 public static void main(String[] args) { 
        String srcImgPath = "C:/Users/admin/Desktop/test.jpg"; 
        String iconPath = "C:/Users/admin/Desktop/logo.png"; 
        String targerPath1 = "C:/Users/admin/Desktop/target1.jpg"; 
        String targerPath2 = "C:/Users/admin/Desktop/target2.jpg"; 
        // 给图片添加水印 
        WaterMarkIMGUtils.setWaterMarkForIMGByIcon(iconPath, srcImgPath, targerPath1,"JPG"); 
        // 给图片添加水印,水印旋转-10 
        WaterMarkIMGUtils.setWaterMarkForIMGByIcon(iconPath, srcImgPath, targerPath2, -10,"JPG"); 
 
    } 
 
}

原来图片:
在这里插入图片描述

水印图片:
在这里插入图片描述
添加水印后的图片:
在这里插入图片描述

【拓展功能】
上面代码参考网上教程,很多地方都有分享代码,然后下面对其进行拓展

业务场景,基于图片加图片水印的功能,现在要求上传图片时候就给加上二维码,用户可以扫描二维码获取对应数据

首先二维码里面其实也就是一些数据,比如一个链接,或者一堆文字等等,这里可以通过Google开源的zxing库来事项生成二维码图片,然后附加到图片,形成水印

maven配置zxing对应jar:

<!-- 条形码、二维码生成 --> 
        <dependency> 
            <groupId>com.google.zxing</groupId> 
            <artifactId>core</artifactId> 
            <version>2.2</version> 
        </dependency> 
        <dependency> 
            <groupId>com.google.zxing</groupId> 
            <artifactId>javase</artifactId> 
            <version>2.2</version> 
        </dependency>

写个工具类用于生成二维码图片:

 
import java.awt.image.BufferedImage; 
import java.io.IOException; 
import java.util.Hashtable; 
 
import com.google.zxing.BarcodeFormat; 
import com.google.zxing.EncodeHintType; 
import com.google.zxing.MultiFormatWriter; 
import com.google.zxing.WriterException; 
import com.google.zxing.client.j2se.MatrixToImageWriter; 
import com.google.zxing.common.BitMatrix; 
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; 
 
/** 
 * 二维码生成工具类 
 */ 
public class QrCodeUtils { 
     
    /** 
     * 生成二维码 
     * @author nicky.ma 
     * @date   2019年6月11日下午4:39:16 
     * @param contents 二维码的内容 
     * @param width 二维码图片宽度 
     * @param height 二维码图片高度 
     */ 
    public static BufferedImage createQrCodeBufferdImage(String contents, int width, int height){ 
        Hashtable hints= new Hashtable();    
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");   
        BufferedImage image = null; 
        try { 
            BitMatrix bitMatrix = new MultiFormatWriter().encode( 
                    contents,BarcodeFormat.QR_CODE, width, height, hints); 
            image = toBufferedImage(bitMatrix); 
        } catch (WriterException e) { 
            e.printStackTrace(); 
        }  
        return image; 
    } 
 
    public static BufferedImage toBufferedImage(BitMatrix matrix) { 
        int width = matrix.getWidth(); 
        int height = matrix.getHeight(); 
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 
        for (int x = 0; x < width; x++) { 
          for (int y = 0; y < height; y++) { 
            image.setRGB(x, y, matrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF); 
          } 
        } 
        return image; 
    } 
}

写个图片添加图片水印的工具类,代码仅供参考
注意:二维码要清晰度要求比较高,就不要设置透明效果了

 
import java.awt.AlphaComposite; 
import java.awt.Color; 
import java.awt.Graphics2D; 
import java.awt.Image; 
import java.awt.RenderingHints; 
import java.awt.image.BufferedImage; 
import java.io.BufferedOutputStream; 
import java.io.File; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.text.SimpleDateFormat; 
import java.util.Date; 
 
import javax.imageio.ImageIO; 
import javax.swing.ImageIcon; 
 
import com.itextpdf.text.BadElementException; 
import com.itextpdf.text.DocumentException; 
import com.itextpdf.text.Rectangle; 
import com.itextpdf.text.pdf.PdfContentByte; 
import com.itextpdf.text.pdf.PdfGState; 
import com.itextpdf.text.pdf.PdfReader; 
import com.itextpdf.text.pdf.PdfStamper; 
import com.itextpdf.text.pdf.PdfStructTreeController.returnType; 
import com.itextpdf.text.pdf.parser.PdfImageObject.ImageBytesType; 
import com.stuff.stuffmanage.model.CommonStuffModel; 
/** 
 *  
 * 
 
 *  水印处理工具类. <br> 
 * 

*
* @author nicky.ma
* @date 2019/06/11
*/
public class WaterMarkUtils {

/**
* 生成二维码
* @author nicky.ma
* @date 2019年6月12日下午2:15:51
* @param commonStuffModel
* @return
*/
private static BufferedImage createQrCodeImg(CommonStuffModel commonStuffModel){
StringBuffer strBuf = new StringBuffer();
strBuf.append("材料入库时间:").append(new SimpleDateFormat("yyyy-MM-dd").format(new Date())).append("/n");
strBuf.append("材料有效期:").append(commonStuffModel.getValidEndDateStr()).append("/n");
strBuf.append("材料名称:").append(commonStuffModel.getStuffName()).append("/n");
strBuf.append("材料目录:").append(commonStuffModel.getDirName()).append("/n");
strBuf.append("材料版本:").append(commonStuffModel.getVersion()).append("/n");
strBuf.append("出具单位:").append(commonStuffModel.getIssueUnit()).append("/n");
// 生成二维码
BufferedImage bufferedImage = QrCodeUtils.createQrCodeBufferdImage(strBuf.toString(), 175, 175);
return bufferedImage;
}

/**
* 图片附件添加二维码水印
* @author nicky.ma
* @date 2019年6月12日下午2:13:29
* @param bos
* 文件保存 IO stream
* @param input
* 获取文件上传IO stream
* @param commonStuffModel
* 公共材料库信息实体
* @param imgType
* 附件类型
*/
public static void setQrCodeForIMG(BufferedOutputStream bos, InputStream input,
ApprCommonStuffModel apprCommonStuffModel, String imgType){
BufferedImage bufferedImage = createQrCodeImg(apprCommonStuffModel);
//图片附件加上二维码水印
setWaterMarkForIMG(bufferedImage, input, bos, imgType);
}

/**
* 给图片添加水印
* @param bufferedImage
* 水印图片
* @param in
* 获取附件上传stream
* @param os
* 附件保存stream
* @param imgType
* 上传附件的类型
*/
public static void setWaterMarkForIMG(BufferedImage bufferedImage, InputStream in, OutputStream os, String imgType) {
setWaterMarkForIMG(bufferedImage, in, os, null, imgType);
}

/**
* 给图片添加水印、可设置水印图片旋转角度
* @author nicky.ma
* @date 2019年6月12日下午2:11:11
* @param bufferedImage
* 水印图片
* @param in
* 获取附件上传stream
* @param os
* 附件保存stream
* @param degree
* 选择角度
* @param imgType
* 上传附件的类型
*/
public static void setWaterMarkForIMG(BufferedImage bufferedImage, InputStream in, OutputStream os, Integer degree,String imgType) {
//OutputStream os = null;
long startTime = System.currentTimeMillis();
System.out.println("图片附件添加图片水印 start");
try {
Image srcImg = ImageIO.read(in);
BufferedImage buffImg = new BufferedImage(srcImg.getWidth(null), srcImg.getHeight(null),
BufferedImage.TYPE_INT_RGB);
// 得到画笔对象
Graphics2D g = buffImg.createGraphics();
// 设置对线段的锯齿状边缘处理
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);
if (null != degree) {
// 设置水印旋转
g.rotate(Math.toRadians(degree), (double) buffImg.getWidth() / 2, (double) buffImg.getHeight() / 2);
}
//float alpha = 0.2f; // 透明度
//g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));

// 水印图象的路径 水印一般为gif或者png的,这样可设置透明度
//ImageIcon imgIcon = new ImageIcon(iconPath);
// 得到Image对象。
//Image img = imgIcon.getImage();
// 表示水印图片的位置
g.drawImage(bufferedImage, buffImg.getWidth()-180, 0, null);

g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
g.dispose();

//os = new FileOutputStream(targerPath);
// 生成图片
ImageIO.write(buffImg, imgType, os);

long endTime = System.currentTimeMillis();
System.out.println("图片附件添加图片水印 ok 所用时间:"+(endTime-startTime)+"s");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != os)
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

对于上传的文件,我们怎么知道类型?如果用Spring提供的MultipartFile,这里可以获取ContentType来判断,这里只提供思路

 
    /**文件类型集合*/ 
    private static Map<String,String> FILE_TYPES =new HashMap<String,String>(); 
    /**图片类型集合*/ 
    private static Map<String,String> IMG_TYPES = new HashMap<String,String>(); 
 
    static{ 
        FILE_TYPES.put("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");//xlsx 
        FILE_TYPES.put("xls", "application/vnd.ms-excel");//xls 
        FILE_TYPES.put("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");//docx 
        FILE_TYPES.put("doc", "application/msword");//doc 
        FILE_TYPES.put("jpg", "image/jpeg");//jpg 
        FILE_TYPES.put("png", "image/png");//png 
        FILE_TYPES.put("gif", "image/gif");//gif 
        FILE_TYPES.put("bmp", "image/bmp");//bmp 
        FILE_TYPES.put("txt", "text/plain");//txt 
        FILE_TYPES.put("pdf", "application/pdf");//pdf 
        FILE_TYPES.put("zip", "application/x-zip-compressed");//zip 
        FILE_TYPES.put("rar", "application/octet-stream");//rar 
    } 
    static{ 
        IMG_TYPES.put("jpg", "image/jpeg");//jpg 
        IMG_TYPES.put("png", "image/png");//png 
        IMG_TYPES.put("gif", "image/gif");//gif 
        IMG_TYPES.put("bmp", "image/bmp");//bmp 
    } 
 
    /** 
     * 校验上传附件是否为图片类型的 
     * @author nicky.ma 
     * @date   2019年6月12日上午11:15:30 
     * @param fileContentType  
     *          response格式ContentType 
     */ 
    public static boolean checkContainImgType(String fileContentType){ 
        if(!StringUtils.isEmpty(fileContentType)){ 
            return IMG_TYPES.containsValue(fileContentType); 
        } 
        return false; 
    } 
 
    public static String loadFileType(String fileContentType){ 
        for(Map.Entry<String, String> entry : FILE_TYPES.entrySet()){ 
            if(entry.getValue().equals(fileContentType)){ 
                return entry.getKey(); 
            } 
        } 
        return null; 
    }

有了工具类之后,我们需要获取文件上传的inputStream

public void upload(MultipartFile myfiles,String url,String rootPath,CommonStuffModel commonStuffModel)throws Exception{ 
     
        if(!myfiles.isEmpty()){    
            File localFile = new File(rootPath+url);   
            File parentFile = localFile.getParentFile(); 
            if(!parentFile.exists()){ 
                parentFile.mkdirs(); 
            } 
            
            String contentType = myfiles.getContentType(); 
           if(checkContainImgType(contentType)){//上传了图片类型附件 
                    InputStream inputStream = myfiles.getInputStream(); 
                    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(localFile)); 
                    WaterMarkUtils.setQrCodeForIMG(bos, inputStream,        commonStuffModel,CommonFileUtil.loadFileType(contentType)); 
             }else{ 
                    myfiles.transferTo(localFile); 
              } 
        } 
}

ok,生成二维码水印
在这里插入图片描述

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/17037.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论