qrcode 生成二维码,带logo 带文字描述

1.引入 pom.xml

整合了一下二维码的生成,并且带有文字提示可以加可以不加

		<!-- zxing 二维码生成依赖 -->
		<!-- https://mvnrepository.com/artifact/com.google.zxing/core -->
		<dependency>
			<groupId>com.google.zxing</groupId>
			<artifactId>core</artifactId>
			<version>3.3.0</version>
		</dependency>
		<dependency>
		    <groupId>com.google.zxing</groupId>
		    <artifactId>javase</artifactId>
		    <version>3.1.0</version>
		</dependency>

2. ResourceRenderer

这个类是处理一个后台访问静态文件夹的一个封装, 这个类访问静态文件可以保证就算打jar 包也可以访问的到。

import java.io.IOException;
import java.io.InputStream;

import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;

public class ResourceRenderer {
	public static InputStream resourceLoader(String fileFullPath) throws IOException {
        ResourceLoader resourceLoader = new DefaultResourceLoader();
        return resourceLoader.getResource(fileFullPath).getInputStream();
    }
}

3. QRCodeUtil

然后就是引入QRCode uitil 实现生成


import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;

import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.ResourceUtils;

import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * 二维码工具类 Created by fuli.shen on 2017/3/31.
 */
public class QRCodeUtil {

	private static final String CHARSET = "utf-8";
	// 生成文件后缀
	private static final String FORMAT_NAME = "JPG";
	// 二维码尺寸
	private static final int QRCODE_SIZE = 210;
	// LOGO宽度
	private static final int WIDTH = 40;
	// LOGO高度
	private static final int HEIGHT = 40;
	
	/**
	 * 生成二维码的方法
	 *
	 * @param content      目标URL
	 * @param imgPath      LOGO图片地址
	 * @param needCompress 是否压缩LOGO
	 * @return 二维码图片
	 * @throws Exception
	 */
	public static BufferedImage createImage(String content, String imgPath, boolean needCompress) throws Exception {
		Hashtable hints = new Hashtable();
		hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
		hints.put(EncodeHintType.CHARACTER_SET, CHARSET); 
		hints.put(EncodeHintType.MARGIN, 4); // 外边距
		BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE,
				hints);
		int width = bitMatrix.getWidth();
		int height = bitMatrix.getHeight();
		
		// 重新定义一个BufferedImage 网图片上添加rgb颜色
		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, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
			}
		}
		if (imgPath == null || "".equals(imgPath)) {
			return image;
		}
		// 插入图片
		QRCodeUtil.insertImage(image, imgPath, needCompress);
		return image;
	}

	/**
	 * 插入LOGO
	 *
	 * @param source       二维码图片
	 * @param imgPath      LOGO图片地址
	 * @param needCompress 是否压缩
	 * @throws Exception
	 */	
	private static void insertImage(BufferedImage source, String imgPath, boolean needCompress) throws Exception {
		/*
		 * File file = new File(imgPath); if (!file.exists()) { System.err.println("" +
		 * imgPath + "   该文件不存在!"); return; }
		 */
		//Image src = ImageIO.read(ResourceUtils.getFile(imgPath));

		Image src = ImageIO.read(ResourceRenderer.resourceLoader(imgPath));
		int width = src.getWidth(null);
		int height = src.getHeight(null);
		if (needCompress) { // 压缩LOGO
			if (width > WIDTH) {
				width = WIDTH;
			}
			if (height > HEIGHT) {
				height = HEIGHT;
			}
			Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
			BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
			// 用Graphics 在 BufferedImage 上指定位置绘制
			Graphics g = tag.getGraphics();
			g.drawImage(image, 0, 0, null); // 绘制缩小后的图
			g.dispose();
			src = image;
		}
		// 插入LOGO
		Graphics2D graph = source.createGraphics();
		int x = (QRCODE_SIZE - width) / 2;
		int y = (QRCODE_SIZE - height) / 2;
		graph.drawImage(src, x, y, width, height, null);
		Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
		graph.setStroke(new BasicStroke(3f));
		graph.draw(shape);
		graph.dispose();
	}

	/**
	 * 生成二维码(内嵌LOGO)
	 *
	 * @param content      内容
	 * @param imgPath      LOGO地址
	 * @param destPath     存放目录
	 * @param needCompress 是否压缩LOGO
	 * @throws Exception
	 */
	public static void encode(String content, String imgPath, String destPath, boolean needCompress) throws Exception {
		BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);
		mkdirs(destPath);
		String file = new Random().nextInt(99999999) + ".jpg";
		ImageIO.write(image, FORMAT_NAME, new File(destPath + "/" + file));
	}

	/**
	 * 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常)
	 *
	 * @param destPath 存放目录
	 */
	public static void mkdirs(String destPath) {
		File file = new File(destPath);
		if (!file.exists() && !file.isDirectory()) {
			file.mkdirs();
		}
	}

	/**
	 * 生成二维码(内嵌LOGO)
	 *
	 * @param content  内容
	 * @param imgPath  LOGO地址
	 * @param destPath 存储地址
	 * @throws Exception
	 */
	public static void encode(String content, String imgPath, String destPath) throws Exception {
		QRCodeUtil.encode(content, imgPath, destPath, false);
	}

	/**
	 * 生成二维码
	 *
	 * @param content      内容
	 * @param destPath     存储地址
	 * @param needCompress 是否压缩LOGO
	 * @throws Exception
	 */
	public static void encode(String content, String destPath, boolean needCompress) throws Exception {
		QRCodeUtil.encode(content, null, destPath, needCompress);
	}

	/**
	 * 生成二维码
	 *
	 * @param content  内容
	 * @param destPath 存储地址
	 * @throws Exception
	 */
	public static void encode(String content, String destPath) throws Exception {
		QRCodeUtil.encode(content, null, destPath, false);
	}

	/**
	 * 生成二维码(内嵌LOGO)
	 *
	 * @param content      内容
	 * @param imgPath      LOGO地址
	 * @param output       输出流
	 * @param needCompress 是否压缩LOGO
	 * @throws Exception
	 */
	public static void encode(String content, String imgPath, OutputStream output, boolean needCompress)
			throws Exception {
		BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);
		ImageIO.write(image, FORMAT_NAME, output);
	}

	/**
	 * 生成二维码
	 *
	 * @param content 内容
	 * @param output  输出流
	 * @throws Exception
	 */
	public static void encode(String content, OutputStream output) throws Exception {
		QRCodeUtil.encode(content, null, output, false);
	}

	/**
	 * 解析二维码
	 *
	 * @param file 二维码图片
	 * @return
	 * @throws Exception
	 */
	public static String decode(File file) throws Exception {
		BufferedImage image;
		image = ImageIO.read(file);
		if (image == null) {
			return null;
		}
		BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
		BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
		Result result;
		Hashtable hints = new Hashtable();
		hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
		result = new MultiFormatReader().decode(bitmap, hints);
		String resultStr = result.getText();
		return resultStr;
	}

	/**
	 * 解析二维码
	 *
	 * @param path 二维码图片地址
	 * @return 不是二维码的内容返回null,是二维码直接返回识别的结果
	 * @throws Exception
	 */
	public static String decode(String path) throws Exception {
		return QRCodeUtil.decode(new File(path));
	}

	/**
	 * Java拼接多张图片
	 * 
	 * @param imgs     图片地址集合
	 * @param type     图片类型
	 * @param dst_pic  //输出的文件:F:/test2.jpg
	 * @param rowCount //一行几张
	 * @return
	 */
	public static boolean merge(String[] imgs, String type, String dst_pic, int rowCount) {
		// 获取需要拼接的图片长度
		int len = imgs.length;
		// 判断长度是否大于0
		if (len < 1) {
			return false;
		}
		File[] src = new File[len];
		BufferedImage[] images = new BufferedImage[len];
		int[][] ImageArrays = new int[len][];
		for (int i = 0; i < len; i++) {
			try {
				src[i] = new File(imgs[i]);
				images[i] = ImageIO.read(src[i]);
			} catch (Exception e) {
				e.printStackTrace();
				return false;
			}
			int width = images[i].getWidth() + 2;
			int height = images[i].getHeight() + 2;
			// 从图片中读取RGB 像素
			ImageArrays[i] = new int[width * height];
			ImageArrays[i] = images[i].getRGB(0, 0, width, height, ImageArrays[i], 0, width);
		}

		int dst_height = images[0].getHeight();
		int dst_width = 0;
		// 合成图片像素
		for (int i = 0; i < images.length; i++) {
			if ((i + 1) % rowCount == 0 && i > 0 && (i + 1) != images.length) {
				dst_height += images[i].getHeight();

			}
		}
		dst_width = images.length > rowCount ? rowCount * images[0].getWidth() : images.length * images[0].getWidth();
		// 合成后的图片
		System.out.println("宽度:" + dst_width);
		System.out.println("高度:" + dst_height);
		if (dst_height < 1) {
			System.out.println("dst_height < 1");
			return false;
		}
		// 生成新图片
		try {
			int startX = 0;
			BufferedImage ImageNew = new BufferedImage(dst_width, dst_height, BufferedImage.TYPE_INT_RGB);
			dst_width = images[0].getWidth();
			int height_i = 0;
			for (int i = 0; i < images.length; i++) {
				ImageNew.setRGB(startX, height_i, dst_width, images[i].getHeight(), ImageArrays[i], 0, dst_width);
				// height_i += images[i].getHeight();
				if ((i + 1) % rowCount == 0 && i > 0) {
					height_i += images[i].getHeight();
					startX = 0;
				} else {
					startX += images[i].getWidth();
				}
				// System.out.println(startX+" "+height_i);
			}

			File outFile = new File(dst_pic);
			ImageIO.write(ImageNew, type, outFile);// 写图片 ,输出到硬盘
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 * Java拼接多张图片
	 * 
	 * @param imgs     图片地址集合
	 * @param type     图片类型
	 * @param dst_pic  //输出的文件:F:/test2.jpg
	 * @param rowCount //一行几张
	 * @return
	 */
	public static boolean merge(BufferedImage[] imgs, String type, int rowCount, OutputStream outputStream) {
		// 获取需要拼接的图片长度
		int len = imgs.length;
		// 判断长度是否大于0
		if (len < 1) {
			return false;
		}
		BufferedImage[] images = imgs;
		int[][] ImageArrays = new int[len][];
		for (int i = 0; i < len; i++) {
			int width = images[i].getWidth();
			int height = images[i].getHeight();
			// 从图片中读取RGB 像素
			ImageArrays[i] = new int[width * height];
			ImageArrays[i] = images[i].getRGB(0, 0, width, height, ImageArrays[i], 0, width);
		}

		int dst_height = images[0].getHeight();
		int dst_width = 0;
		// 合成图片像素
		for (int i = 0; i < images.length; i++) {
			if ((i + 1) % rowCount == 0 && i > 0 && (i + 1) != images.length) {
				dst_height += images[i].getHeight();

			}
		}
		dst_width = images.length > rowCount ? rowCount * images[0].getWidth() : images.length * images[0].getWidth();
		// 合成后的图片
		System.out.println("宽度:" + dst_width);
		System.out.println("高度:" + dst_height);
		if (dst_height < 1) {
			System.out.println("dst_height < 1");
			return false;
		}
		// 生成新图片
		try {
			int startX = 0;
			BufferedImage ImageNew = new BufferedImage(dst_width, dst_height, BufferedImage.TYPE_INT_RGB);
			dst_width = images[0].getWidth();
			int height_i = 0;
			for (int i = 0; i < images.length; i++) {
				ImageNew.setRGB(startX, height_i, dst_width, images[i].getHeight(), ImageArrays[i], 0, dst_width);
				// height_i += images[i].getHeight();
				if ((i + 1) % rowCount == 0 && i > 0) {
					height_i += images[i].getHeight();
					startX = 0;
				} else {
					startX += images[i].getWidth();
				}
			}

			ImageIO.write(ImageNew, type, outputStream);// 写图片 ,输出到输出流
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}
	/**
	 * Java拼接多张图片,不足的用空格补齐
	 * 
	 * @param imgs     图片地址集合
	 * @param type     图片类型
	 * @param pageSize 一张有多少张
	 * @param rowCount //一行几张
	 * @return
	 */
	public static BufferedImage merge(List<BufferedImage> imgss, String type, int rowCount,int pageSize, OutputStream outputStream) {
		if(imgss.size() < pageSize) {
			// 如果要生成的图片不足pageSize 则用空白图片补齐
			for(int i = 0;i < pageSize - imgss.size();i++) {
				Color color = new Color(255, 255, 255);
				imgss.add(QRCodeUtil.forceFill(color.getRGB()));
			}
		}
		// 开始接图片
		BufferedImage[] imgs = new BufferedImage[imgss.size()];
		// 获取需要拼接的图片长度
				int len = imgs.length;
				// 判断长度是否大于0
				if (len < 1) {
					return null;
				}
				BufferedImage[] images = imgs;
				int[][] ImageArrays = new int[len][];
				for (int i = 0; i < len; i++) {
					int width = images[i].getWidth();
					int height = images[i].getHeight();
					// 从图片中读取RGB 像素
					ImageArrays[i] = new int[width * height];
					ImageArrays[i] = images[i].getRGB(0, 0, width, height, ImageArrays[i], 0, width);
				}

				int dst_height = images[0].getHeight();
				int dst_width = 0;
				// 合成图片像素
				for (int i = 0; i < images.length; i++) {
					if ((i + 1) % rowCount == 0 && i > 0 && (i + 1) != images.length) {
						dst_height += images[i].getHeight();
					}
				}
				dst_width = images.length > rowCount ? rowCount * images[0].getWidth() : images.length * images[0].getWidth();
				// 合成后的图片
				System.out.println("宽度:" + dst_width);
				System.out.println("高度:" + dst_height);
				if (dst_height < 1) {
					System.out.println("dst_height < 1");
				}
				// 生成新图片
				try {
					int startX = 0;
					BufferedImage ImageNew = new BufferedImage(dst_width, dst_height, BufferedImage.TYPE_INT_RGB);
					dst_width = images[0].getWidth();
					int height_i = 0;
					for (int i = 0; i < images.length; i++) {
						ImageNew.setRGB(startX, height_i, dst_width, images[i].getHeight(), ImageArrays[i], 0, dst_width);
						// height_i += images[i].getHeight();
						if ((i + 1) % rowCount == 0 && i > 0) {
							height_i += images[i].getHeight();
							startX = 0;
						} else {
							startX += images[i].getWidth();
						}
					}
					return ImageNew;
				} catch (Exception e) {
					e.printStackTrace();
					return null;
				}
	}
	
	/**
	 * Java拼接多张图片
	 * 
	 * @param imgs     图片地址集合
	 * @param type     图片类型
	 * @param dst_pic  //输出的文件:F:/test2.jpg
	 * @param rowCount //一行几张
	 * @return
	 */
	public static boolean merge(BufferedImage[] imgs, String type, String dst_pic, int rowCount) {
		// 获取需要拼接的图片长度
		int len = imgs.length;
		// 判断长度是否大于0
		if (len < 1) {
			return false;
		}
		BufferedImage[] images = imgs;
		int[][] ImageArrays = new int[len][];
		for (int i = 0; i < len; i++) {
			int width = images[i].getWidth();
			int height = images[i].getHeight();
			// 从图片中读取RGB 像素
			ImageArrays[i] = new int[width * height];
			ImageArrays[i] = images[i].getRGB(0, 0, width, height, ImageArrays[i], 0, width);
		}

		int dst_height = images[0].getHeight();
		int dst_width = 0;
		// 合成图片像素
		for (int i = 0; i < images.length; i++) {
			if ((i + 1) % rowCount == 0 && i > 0 && (i + 1) != images.length) {
				dst_height += images[i].getHeight();

			}
		}
		dst_width = images.length > rowCount ? rowCount * images[0].getWidth() : images.length * images[0].getWidth();
		// 合成后的图片
		System.out.println("宽度:" + dst_width);
		System.out.println("高度:" + dst_height);
		if (dst_height < 1) {
			System.out.println("dst_height < 1");
			return false;
		}
		// 生成新图片
		try {
			int startX = 0;
			BufferedImage ImageNew = new BufferedImage(dst_width, dst_height, BufferedImage.TYPE_INT_RGB);
			dst_width = images[0].getWidth();
			int height_i = 0;
			for (int i = 0; i < images.length; i++) {
				ImageNew.setRGB(startX, height_i, dst_width, images[i].getHeight(), ImageArrays[i], 0, dst_width);
				// height_i += images[i].getHeight();
				if ((i + 1) % rowCount == 0 && i > 0) {
					height_i += images[i].getHeight();
					startX = 0;
				} else {
					startX += images[i].getWidth();
				}

				// System.out.println(startX+" "+height_i);
			}

			File outFile = new File(dst_pic);
			ImageIO.write(ImageNew, type, outFile);// 写图片 ,输出到硬盘
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	/**
	 * Java拼接多张图片
	 * 
	 * @param imgs
	 *            图片地址集合
	 * @param type
	 *            图片类型
	 * @param dst_pic
	 *            //输出的文件:F:/test2.jpg
	 * @param rowCount
	 *            //一行几张
	 * @return
	 */
	public static InputStream merge(BufferedImage[] imgs, String type, int rowCount) {
		// 获取需要拼接的图片长度
		int len = imgs.length;
		// 判断长度是否大于0
		if (len < 1) {
			System.out.println("要拼接的长度为零!!!!!!!!!!!!!!!!");
			return null;
		}
		BufferedImage[] images = imgs;
		int[][] ImageArrays = new int[len][];
		for (int i = 0; i < len; i++) {
			int width = images[i].getWidth();
			int height = images[i].getHeight();
			// 从图片中读取RGB 像素
			ImageArrays[i] = new int[width * height];
			ImageArrays[i] = images[i].getRGB(0, 0, width, height,
					ImageArrays[i], 0, width);
		}

		int dst_height = images[0].getHeight();
		int dst_width = 0;
		// 合成图片像素
		for (int i = 0; i < images.length; i++) {
			if ((i + 1) % rowCount == 0 && i > 0 && (i + 1) != images.length) {
				dst_height += images[i].getHeight();

			}
		}
		dst_width = images.length > rowCount ? rowCount * images[0].getWidth()
				: images.length * images[0].getWidth();
		// 合成后的图片
		System.out.println("宽度:" + dst_width);
		System.out.println("高度:" + dst_height);
		if (dst_height < 1) {
			System.out.println("dst_height < 1");
			return null;
		}
		// 生成新图片
		try {
			int startX = 0;
			BufferedImage ImageNew = new BufferedImage(dst_width, dst_height,
					BufferedImage.TYPE_INT_RGB);
			dst_width = images[0].getWidth();
			int height_i = 0;
			for (int i = 0; i < images.length; i++) {
				ImageNew.setRGB(startX, height_i, dst_width,
						images[i].getHeight(), ImageArrays[i], 0, dst_width);
				// height_i += images[i].getHeight();
				if ((i + 1) % rowCount == 0 && i > 0) {
					height_i += images[i].getHeight();
					startX = 0;
				} else {
					startX += images[i].getWidth();
				}

				// System.out.println(startX+" "+height_i);
			}

			// File outFile = new File(dst_pic);

			ByteArrayOutputStream os = new ByteArrayOutputStream();
			ImageIO.write(ImageNew, "jpg", os);
			InputStream is = new ByteArrayInputStream(os.toByteArray());
			// ImageIO.write(ImageNew, type, outputStream);// 写图片 ,输出到zip输出流
			return is;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	 /**
	  * 给二维码下方附加说明文字
    * @param pressText 文字
    * @param image     需要添加文字的图片
    * @为图片添加文字
    */
   public static void pressText(String pressText, BufferedImage image, int fontStyle, Color color, int fontSize) {
   		
       //计算文字开始的位置
       //x开始的位置:(二维码-字体大小*字的个数)/2
   	   //int startX = (QRCODE_SIZE - (fontSize * pressText.length()))/3 - 28;
	   int ci = (fontSize-2) * pressText.length();
	   int startX = (QRCODE_SIZE-ci)/2;
       //y开始的位置:二维码高度 - 文字大小
       int startY = QRCODE_SIZE - fontSize;
       //y开始的位置:二维码高度 - 文字大小
       int startY = QRCODE_SIZE - fontSize;
       
       System.out.println("startX: " + startX);
       System.out.println("startY: " + startY);
       System.out.println("fontSize: " + fontSize);
       System.out.println("pressText.length(): " + pressText.length());

       try {
    	   // 创建一个 Graphics 
           Graphics g = image.createGraphics();
           // 设置 Graphics 的绘制颜色
           g.setColor(color);
           // 设置字体
           g.setFont(new Font("微软雅黑", Font.PLAIN, fontSize));
           // 开始绘制
           g.drawString(pressText, startX, startY);
           // 保存
           g.dispose();
           System.out.println("添加的pressText 为:【"+pressText+"】");
           System.out.println("image press success");
       } catch (Exception e) {
           e.printStackTrace();
           System.out.println(e);
       }
   }
   /**
    * 生成一张纯色图片
    * @param rgb
    * @return
    */
   public static BufferedImage forceFill( int rgb) {
	   BufferedImage img = new BufferedImage(QRCODE_SIZE, QRCODE_SIZE, BufferedImage.TYPE_3BYTE_BGR);
	    for(int x = 0; x < img.getWidth(); x++) {
	        for(int y = 0; y < img.getHeight(); y++) {
	            //img.setRGB(x, y, rgb);
	        	img.setRGB(x, y, rgb);
	        }
	    }
	    return img;
	}
	public static void main(String[] args) throws Exception {

		// 生成二维码
		String text = "https://www.baidu.com/";
		// String imagePath = System.getProperty("user.dir") + "/data/1.jpg";
		String destPath = "C:\\Users\\admin\\Desktop\\";
		List<BufferedImage> bufferedImages = new ArrayList<BufferedImage>();
		for (int i = 0; i < 12; i++) {
			BufferedImage bufferedImage = QRCodeUtil.createImage("hello", "classpath:static/image/olt.obd_01.png",
					true);
			bufferedImages.add(bufferedImage);
		}

		// QRCodeUtil.encode(content, output);
		// 验证图片是否含有二维码
		/*
		 * String destPath1 = "C:\\Users\\admin\\Desktop\\3.jpg"; try { String result =
		 * decode(destPath1); System.out.println(result); }catch (Exception e){
		 * e.printStackTrace(); System.out.println(destPath1+"不是二维码"); }
		 */
		// 输入图片地址
		String[] imgs = { "C:\\Users\\admin\\Desktop\\2.jpg", "C:\\Users\\admin\\Desktop\\1.jpg",
				"C:\\Users\\admin\\Desktop\\2.jpg", "C:\\Users\\admin\\Desktop\\1.jpg",
				"C:\\Users\\admin\\Desktop\\2.jpg", "C:\\Users\\admin\\Desktop\\1.jpg",
				"C:\\Users\\admin\\Desktop\\2.jpg", "C:\\Users\\admin\\Desktop\\1.jpg",
				"C:\\Users\\admin\\Desktop\\2.jpg", "C:\\Users\\admin\\Desktop\\1.jpg",
				"C:\\Users\\admin\\Desktop\\2.jpg", "C:\\Users\\admin\\Desktop\\1.jpg",
				"C:\\Users\\admin\\Desktop\\2.jpg", "C:\\Users\\admin\\Desktop\\1.jpg",
				"C:\\Users\\admin\\Desktop\\2.jpg" };
		BufferedImage[] bfs = new BufferedImage[bufferedImages.size()];
		// 调用方法生成图片
		merge(bufferedImages.toArray(bfs), "jpg", "C:\\Users\\admin\\Desktop\\test.jpg", 4);
	}
}

4. QRCodeController

然后就是 控制类了,在这个类里面,我控制好了,多张生成的时候会自动补齐一个a4 规格的纸张 也就是 4:6 的比例,刚好可以打印到A4 纸上。如果有需要可以修改我的生成代码,在controller 141 行。底下的ZipUtil 是一个zip 的压缩类,可以看看

import java.awt.Color;
import java.awt.Font;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;

import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.example.demo.util.QRCodeUtil;
import com.example.demo.util.ResourceRenderer;

import org.springframework.util.StringUtils;

@Controller
public class QRCodeController {

	private Integer fontSize = 16;
	private Integer pageSize = 24; // 每张图片的二维码个数
	private Integer line = 4; // 二维码每行的个数
	private String imgPath = "classpath:static/image/image.jpg";
	
	// 存放存取List 的键
	private String preeText = "preeText";
	private String content = "content";
	
	@RequestMapping(value= {"/","/index"})
	public String index() {
		return "index";
	}
	
	@RequestMapping("/hello")
	@ResponseBody
	public String helloWorld() throws IOException {
		return "helloWorld";
	}
	/**
	 * 开始生成二维码
	 * 
	 * @param response
	 * @param content  二维码扫码出来的内容 ☆只在单个二维码生成中有效
	 * @param num      生成二维码的数量
	 * @param preeText 二维码上面的文字 ☆只在单个二维码生成中有效
	 * @throws Exception
	 */
	@RequestMapping("/qrcode")
	public void qrcode(HttpServletResponse response, String text) throws Exception {
		response.setContentType("text/html;charset=UTF-8");
		response.setContentType("application/x-octet-stream");
		// response.setHeader("Content-Disposition", "attachment;filename="+
		// System.currentTimeMillis() + ".zip");// 下载文件的名称
		response.setHeader("Content-Disposition", "attachment;");
		
		// 开始解析数字
		List<Map<String,String>> list = new ArrayList<>();
		if(StringUtils.isEmpty(text)) {
			System.out.println("请输入要生成的二维码");
			return;
		}
		String[] contents = text.split("\n");
		for(String str :contents) {
			int index = str.indexOf(",");
			if(index == -1) {
				list.add(new HashMap<String, String>(){{
					System.out.println(str);
					put(content, str);
					put(preeText, "");
				}});
			}else {
				list.add(new HashMap<String, String>(){{
					System.out.println(str);
					put(content, str.substring(0,index));
					put(preeText, str.substring(index+1));
				}});
			}
		}
		
		Integer num = list.size();
		if (num != null && num == 1) {
			// 生成单个二维码
			response.setHeader("Content-Disposition", "attachment;filename=a.jpg");
			Map<String,String> aaa = list.get(0);
			BufferedImage bufferedImage = makeQRCodeImg(aaa.get(preeText), aaa.get(this.content));
			// 把图片输出出去
			ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
		} else if (num != null && num > 1) {
			// 生成批量的时候
			response.setHeader("Content-Disposition", "attachment;filename=a.zip");
			downMoreImg(response, list);
		} else {
			System.out.println("请指定正确的二维码数量");
		}
	}
	/**
	 * 生成压缩包图片
	 * @param response
	 * @param list
	 * @throws Exception
	 */
	@SuppressWarnings("unused")
	private void downMoreImg(HttpServletResponse response,List<Map<String,String>> list) throws Exception {
		// 创建一个压缩包
		ZipOutputStream zip = new ZipOutputStream(response.getOutputStream());
		Integer count = list.size();
		Integer big = count % pageSize; // 最后一页的个数
		Integer page = big == 0 ? count / pageSize : (count / pageSize) + 1; // 总页数
		// 图片名 +   图片流
		Map<String, InputStream> imgs = new HashMap<String, InputStream>();
		for (int i = 0; i < page; i++) {
			// 开始生成图片 i 表示的是当前页
			//起始行下标  等于  当前页减去1  乘以 每页个数  也就是说    i*pageSize
			Integer begin = i*pageSize,end = begin+pageSize;
			if(end > count) end = count; // 防止下标越界
			imgs.put("第("+(i+1)+")页",makeImages( list.subList(begin, end)));
			System.out.println("第("+(i+1)+") 页生成成功");
		}
		ZipUtil.zipPut(zip, imgs, "jpg");
		// 保存缓存 
		response.flushBuffer();
	}
	/**
	 * 生成一张二维码 
	 * @param content
	 * @return
	 * @throws Exception 
	 */
	private InputStream makeImages(List<Map<String,String>> content) throws Exception {
		int size = content.size();
		List<BufferedImage> bufferedImages = new ArrayList<BufferedImage>();
		System.out.println("当前拼接二维码的个数为:" + size);
		for(int i = 0; i < pageSize; i++) {
			if(i >= size)
				bufferedImages.add(makeWhiteImg());
			else {
				// 生成二维码图片
				BufferedImage img = makeQRCodeImg(content.get(i).get(preeText), content.get(i).get(this.content));
				bufferedImages.add(img);
			}
		}
		BufferedImage[] images = new BufferedImage[size];
		InputStream img = QRCodeUtil.merge(bufferedImages.toArray(images), "jpg", line);
		return img;
	}
	/**
	 * 纯色图片
	 * @return
	 */
	private BufferedImage makeWhiteImg() {
		Color color = new Color(255, 255, 255);
		// System.out.println(color.getRGB());
		return QRCodeUtil.forceFill(color.getRGB());
	}
	/**
	 * 生成单个二维码
	 * @param preeText
	 * @param content
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unused")
	private BufferedImage makeQRCodeImg(String preeText,String content) throws Exception {
		BufferedImage bufferedImage = QRCodeUtil.createImage(content, imgPath, true);
		// 给图片添加文字
		QRCodeUtil.pressText(preeText, bufferedImage, Font.BOLD, Color.black, fontSize);
		return bufferedImage;
	}
}
class ZipUtil {
	/**
	 * 打包
	 * @param out
	 * @param fil
	 * @param suffix
	 * @return
	 * @throws IOException
	 */
	public static ZipOutputStream zipPut(ZipOutputStream out,Map<String,InputStream> fil,String suffix) throws IOException{
		for(String name : fil.keySet()){
			out.putNextEntry(new ZipEntry(name+"."+suffix));
			byte[] buffer = new byte[1024];     
            int r = 0;     
            while ((r = fil.get(name).read(buffer)) != -1) {     
                out.write(buffer, 0, r);     
            }     
            fil.get(name).close();   
		}
		out.flush();     
        out.close();
        return out;
	}
}

5. HTML

我写了一个html 测试使用他

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<style>
	*{
		margin:0px auto;
	}
	form{
		margin-left:25%;
		margin-top:10%;
	}
</style>
<body>
	<form action="/qrcode" method="post">
		<p>多个二维码请换行,提示于生成二维码的内容中间要用,隔开</p>
		<textarea rows="10" cols="100" name = "text"></textarea>
		<br />
		<input type="submit" value="提交">
	</form>
</body>

6. 测试

我输入了百度的网址,然后用英文的 , 隔开,就出来了这样的二维码
在这里插入图片描述
这样就可以生成多个并且打包一个了,
在这里插入图片描述

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值