package cn.com.yitong.ares.qrcode;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Hashtable;import javax.imageio.ImageIO;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Binarizer;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;/**
 * 二维码的工具类
 * @author fyh
 *
 */public class ZXingUtil {
	//定义int类型的常量用于存放生成二维码时的类型
	private static final int BLACK = 0xFF000000;
	private static final int WHITE = 0xFFFFFFFF;	/**
	 * 加密:文字-->图片  将文本变成二维数组,
	 * @param imagePath
	 * @param format:文件格式及后缀名
	 * @param content
	 * @throws WriterException 
	 * @throws IOException 
	 */
	public static void encodeimage(String imagePath , String format , String content , int width , int height , String logo) throws WriterException, IOException{		Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType , Object>();
		//容错率:L(7%)<M(15%)<Q(25%)<H(35%);H容错率最高
		hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
		//编码格式
		hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
		//外边距
		hints.put(EncodeHintType.MARGIN, 1);		/***
		 * BarcodeFormat.QR_CODE:解析什么类型的文件:要解析的二维码的类型
		 * content:解析文件的内容
		 * width:生成二维码的宽
		 * height:生成二维码的高
		 * hints:涉及到加密用到的参数: 即 编码 和容错率
		 */
		BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height , hints);
		//使BufferedImage勾画QRCode  (matrixWidth 是行二维码像素点)
		int matrixWidth = bitMatrix.getWidth(); 		/**
		 * 内存中的一张图片:是RenderedImage的子类,而RenderedImage是一个接口
		 * 此时需要的图片是一个二维码-->需要一个boolean[][]数组存放二维码 --->Boolean数组是由BitMatrix产生的 
		 * BufferedImage.TYPE_INT_RGB : 表示生成图片的类型: 此处是RGB模式
		 */
		BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		//生成二维数组
		for(int x=0;x<matrixWidth;x++){
			for(int y=0 ; y<matrixWidth;y++){
				//二维坐标整个区域:画什么颜色
				img.setRGB(x, y, bitMatrix.get(x, y) ? BLACK : WHITE);
			}
		}		//画log
		img = logoImg(img, logo);		//将二维码图片转换成文件
		File file = new File(imagePath);
		//生成图片
		ImageIO.write(img, format, file); 	}
	/**
	 * 解密,将生成的二维码转换成文字
	 * @param file:二维码文件
	 * @throws Exception 
	 */
	public static String decodeImage(File file) throws Exception{		//首先判断文件是否存在
		if(!file.exists()){
			return "";
		}
		//将file转换成内存中的一张图片
		BufferedImage image = ImageIO.read(file);
		MultiFormatReader formatter = new MultiFormatReader();
		LuminanceSource source = new BufferedImageLuminanceSource(image);
		Binarizer binarizer = new HybridBinarizer(source);
		BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
		//将图片的文字信息解析到result中
		Result result = formatter.decode(binaryBitmap);
		System.out.println(result.getText());
		return result.getText();
	}	/**
	 * 传logo和二维码,生成-->带logo的二维码
	 * @param matrixImage :二维码
	 * @param logo : 中间的logo
	 * @return
	 * @throws IOException
	 */
	public static BufferedImage logoImg(BufferedImage matrixImage ,String logo) throws IOException{
		//在二维码上画logo:产生一个二维码画板
		Graphics2D g2 = matrixImage.createGraphics();
		//画logo,将String类型的logo图片存放入内存中;即 string-->BufferedImage
		BufferedImage logoImage = ImageIO.read(new File(logo));
		//获取二维码的高和宽
		int height = matrixImage.getHeight();
		int width = matrixImage.getWidth();
		/**
		 * 纯log图片
		 * logoImage:内存中的图片
		 * 在二维码的高和宽的2/5,2/5开始画log,logo占用整个二维码的高和宽的1/5,1/5
		 */
		g2.drawImage(logoImage,width*2/5, height*2/5, width*1/5, height*1/5, null);		/**
		 * 画白色的外边框
		 * 产生一个画白色圆角正方形的画笔
		 * BasicStroke.CAP_ROUND:画笔的圆滑程度,此处设置为圆滑
		 * BasicStroke.JOIN_ROUND:在边与边的连接点的圆滑程度,此处设置为圆滑
		 */
		BasicStroke stroke = new BasicStroke(5,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
		//将画板和画笔关联起来
		g2.setStroke(stroke);		/**
		 * 画一个正方形
		 * RoundRectangle2D是一个画长方形的类,folat是他的内部类
		 */
		RoundRectangle2D.Float round = new RoundRectangle2D.Float(width*2/5, height*2/5, width*1/5, height*1/5,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
		//设置为画白色
		g2.setColor(Color.WHITE);
		g2.draw(round);		//画灰色的内边框,原理与画白色边框相同
		BasicStroke stroke2 = new BasicStroke(1,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
		g2.setStroke(stroke2);		RoundRectangle2D.Float round2 = new RoundRectangle2D.Float(width*2/5+2, height*2/5+2, width*1/5-4, height*1/5-4,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
		//另一种设置灰色的方法:Color color = new Color(128,128,128);其中三个参数是 R G  B
		g2.setColor(Color.GRAY);
		g2.draw(round2);		//释放内存
		g2.dispose();
		//刷新二维码
		matrixImage.flush();
		return matrixImage;
	}
	/**
	 * 没有logo
	 * 
	 * @param content  文字→二维码
	 * @param path     二维码图片储存位置
	 * @param format 
	 * @param height2 
	 * @param width2 
	 * @return
	 */
	@SuppressWarnings("unused")
	static 
	boolean orCode(String content, String path, int width, int height, String format) {
		/*
		 * 图片的宽度和高度
		 */
		//		int width = 100;
		//		int height = 100;
		//		// 图片的格式
		//		String format = "png";   
		// 定义二维码的参数
		HashMap<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
		// 定义字符集编码格式
		hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
		// 纠错的等级 L > M > Q > H 纠错的能力越高可存储的越少,一般使用M
		hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
		// 设置图片边距
		hints.put(EncodeHintType.MARGIN, 1);		try {
			// 最终生成 参数列表 (1.内容 2.格式 3.宽度 4.高度 5.二维码参数)
			BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
			// 写入到本地
			int matrixWidth = bitMatrix.getWidth(); 			/**
			 * 内存中的一张图片:是RenderedImage的子类,而RenderedImage是一个接口
			 * 此时需要的图片是一个二维码-->需要一个boolean[][]数组存放二维码 --->Boolean数组是由BitMatrix产生的 
			 * BufferedImage.TYPE_INT_RGB : 表示生成图片的类型: 此处是RGB模式
			 */
			BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
			//生成二维数组
			for(int x=0;x<matrixWidth;x++){
				for(int y=0 ; y<matrixWidth;y++){
					//二维坐标整个区域:画什么颜色
					img.setRGB(x, y, bitMatrix.get(x, y) ? BLACK : WHITE);
				}
			}
//			Path file = new File(path).toPath();
//			MatrixToImageWriter.writeToPath(bitMatrix, format, file);
			File file = new File(path);
			//生成图片
			ImageIO.write(img, format, file);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}	}
	public static BufferedImage compositePicature(String beijingPath,String imagePath,String finalImagePath,String format) {		int fontSize=13;
		//在背景里画二维码,将String类型的图片存放入内存中;即 string-->BufferedImage
		BufferedImage beijingImage = null;
		try {
			beijingImage = ImageIO.read(new File(beijingPath));			BufferedImage logoImage = ImageIO.read(new File(imagePath));  //100*100
			//获取二维码的高和宽
			int height = logoImage.getHeight();
			int width = logoImage.getWidth();
			/**
			 * 获取背景图的高和宽
			 */
			int height2 = beijingImage.getHeight();
			int width2 = beijingImage.getWidth();
			Graphics2D g = beijingImage.createGraphics();
			g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
			g.drawImage(logoImage, width2-width-30, height2-height-30, width, height, null);			// 消除文字锯齿
			//			g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
			// 在背景添加二维码图片(地址,左边距,上边距,图片宽度,图片高度,未知)
			//			Font font1 = new Font("微软雅黑", Font.BOLD, fontSize);// 添加字体的属性设置
			//			g.setFont(font1);
			//			Color color1 = new Color(100,0,0);
			//			g.drawString("扫码了解详情",width2-width+5, height2-10);
			//			g.drawString("扫码了解详情",width2-width+5, height2-10);
			//			g.setColor(color1);
			// 抗锯齿
			Font font = new Font("微软雅黑", Font.BOLD, 13);
			g.setFont(font);
			g.setPaint(new Color(0, 0, 0, 64));
			// 先绘制一遍底色
			g.drawString("扫码了解详情", width2-width-20, height2-10);
			g.setPaint(new Color(100,0,0));
			// 再绘制一遍文字
			// 由于部分情况会出现文字模糊的情况,保险起见才出此对策。
			g.drawString("扫码了解详情", width2-width-20, height2-10);
			g.dispose();
			//将二维码图片转换成文件
			File file = new File(finalImagePath);
			//生成图片
			ImageIO.write(beijingImage, format, file); 
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} // 335*459
		return beijingImage;	}
}
 
 
 
 
 
 
 
package cn.com.yitong.ares.qrcode;
import java.awt.image.BufferedImage;
import java.io.IOException;import com.google.zxing.WriterException;
import cn.com.yitong.ares.qrcode.ZXingUtil;
import cn.com.yitong.ares.test2.IGraphics2D;
public class ZXingQR_code {
	/**
	 * 生成二维码(带内嵌的logo)
	 * @param imagePath
	 * @param format
	 * @param content
	 * @param width
	 * @param height
	 * @param logopath
	 */
	public void drawWord(String imagePath, String format, String content,int width, int height,String logopath) {
		try {
			ZXingUtil.encodeimage(imagePath, "JPEG", content, 100, 100 , logopath);
		} catch (WriterException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	/**
	 * 1.生成二维码  (不带logo)
	 * 2. 合并图片 二维码图片和海报图片
	 * @param beijingPath
	 * @param logoPath
	 * @param imagePath
	 * @param format
	 * @param content
	 */
	public void compositionDrawWord(String url,String imagePath,String beijingPath,String finalImagePath, int width, int height, String format) {
		try {
			if (ZXingUtil.orCode(url, imagePath, width, height,format)) {
				System.out.println("ok,成功");
				BufferedImage image=ZXingUtil.compositePicature(beijingPath, imagePath, finalImagePath, format);
			} else {
				System.out.println("no,失败");
			}

		} catch (Exception e) {
			// TODO: handle exception
		}

	}
	public static void main(String[] args) throws Exception {
		/**
		 * 生成二维码(带内嵌的logo)
		 * 加密:将文字其他东西放在图片里面
		 * 解密:反之
		 */
		//1.此处要根据用户id+产品类型海报+  命名图片名称 
		//2.图片存在哪里呢?
//		String imagePath = "src/main/resources/webapp1.jpg";
//		String logo = "src/main/resources/smartLogo.png";
//		String content = "";
//		//		String content = "https://www.baidu.com.cn";
//		ZXingUtil.encodeimage(imagePath, "JPEG", content, 100, 100 , logo);		int width = 100;
		int height = 100;
		String url = "https://www.baidu.com.cn?谁是世界上最美的人";
		String imagePath="src/main/resources/imagePath.png";
		String beijingPath="src/main/resources/beijing.png";
		String finalImagePath="src/main/resources/finalImagePath.png";
		String format="png";

		/**
		 * 1.生成二维码  (不带logo)
		 * 2. 合并图片 二维码图片和海报图片
		 */
		// 传参:二维码内容和生成路径
		if (ZXingUtil.orCode(url, imagePath, width, height,format)) {
			System.out.println("ok,成功");			BufferedImage image=ZXingUtil.compositePicature(beijingPath, imagePath, finalImagePath, format);
		} else {
			System.out.println("no,失败");
		}		/**
		 * 解密 -->将二维码内部的文字显示出来
		 */
		//		ZXingUtil.decodeImage(new File(imagePath));	}
}

Java画图 给图片底部添加文字标题

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

/**
 * JAVA 画图(生成文字水印)
 * 
 * @author 杰宝宝
 * 
 */
public class ImageUtil {

    /**
     * @param str
     *            生产的图片文字
     * @param oldPath
     *            原图片保存路径
     * @param newPath
     *            新图片保存路径
     * @param width
     *            定义生成图片宽度
     * @param height
     *            定义生成图片高度
     * @return
     * @throws IOException
     */
    public void create(String str, String oldPath, String newPath, int width, int height){
        try {
            File oldFile = new File(oldPath);
            Image image = ImageIO.read(oldFile);

            File file = new File(newPath);
            BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2 = bi.createGraphics();
            g2.setBackground(Color.WHITE);
            g2.clearRect(0, 0, width, height);
            g2.drawImage(image, 0, 0, width - 25, height - 25, null); //这里减去25是为了防止字和图重合
            /** 设置生成图片的文字样式 * */
            Font font = new Font("黑体", Font.BOLD, 25);
            g2.setFont(font);
            g2.setPaint(Color.BLACK);

            /** 设置字体在图片中的位置 在这里是居中* */
            FontRenderContext context = g2.getFontRenderContext();
            Rectangle2D bounds = font.getStringBounds(str, context);
            double x = (width - bounds.getWidth()) / 2;
            //double y = (height - bounds.getHeight()) / 2; //Y轴居中
            double y = (height - bounds.getHeight());
            double ascent = -bounds.getY();
            double baseY = y + ascent;

            /** 防止生成的文字带有锯齿 * */
            g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

            /** 在图片上生成文字 * */
            g2.drawString(str, (int) x, (int) baseY);

            ImageIO.write(bi, "jpg", file);
        } catch (IOException e) {
            e.printStackTrace();
        } 
    }

    public static void