zoukankan      html  css  js  c++  java
  • 二维码

    package com.avcon.util;
    
    import java.awt.Color;
    import java.awt.Graphics2D;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    
    import javax.imageio.ImageIO;
    
    import com.swetake.util.Qrcode;
    
    public class RQCodeUtils {
    	public static int max_data_size_small = 84;
    	public static int max_data_size_large = 500;
    
    	/**
    	 * 
    	 * @param srcValue
    	 * @param qrcodePicfilePath
    	 * @return
    	 */
    	public static boolean encode(String srcValue, String qrcodePicfilePath) {
    		return encode_84(srcValue, qrcodePicfilePath);
    	}
    
    	/**
    	 * Encoding the information to a QRCode, size of the information must be less than 84 byte.
    	 * 
    	 * @param srcValue
    	 * @param qrcodePicfilePath
    	 * @return
    	 */
    	public static boolean encode_84(String srcValue, String qrcodePicfilePath) {
    		int MAX_DATA_LENGTH = max_data_size_small; // 限制生成二维码的数据最大大小
    		byte[] d = srcValue.getBytes();
    		int dataLength = d.length;
    		int imageWidth = 113; /* 113是预先计算出来的. 注意:图像宽度必须比生成的二维码图像宽度大,至少相等,否则,二维码识别不出来 */
    		int imageHeight = imageWidth;
    		BufferedImage bi = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);
    		Graphics2D g = bi.createGraphics();
    		g.setBackground(Color.WHITE);
    		g.clearRect(0, 0, imageWidth, imageHeight);
    		g.setColor(Color.BLACK);
    		if (dataLength > 0 && dataLength <= MAX_DATA_LENGTH) {
    			/* 生成二维码 */
    			Qrcode qrcode = new Qrcode();
    			qrcode.setQrcodeErrorCorrect('M'); // L, Q, H, 默认
    			qrcode.setQrcodeEncodeMode('B'); // A, N, 默认
    			qrcode.setQrcodeVersion(5); // 37字节, (37-1)*3+2+3-1+1 = 113
    			boolean[][] b = qrcode.calQrcode(d);
    			int qrcodeDataLen = b.length;
    			for (int i = 0; i < qrcodeDataLen; i++) {
    				for (int j = 0; j < qrcodeDataLen; j++) {
    					if (b[j][i]) {
    						g.fillRect(j * 3 + 2, i * 3 + 2, 3, 3); /*
    																 * 画二维码图形, 画出的图形宽度是 ((qrcodeDataLen-1)*3+2) + 3 -1 ; 生成的image的宽度大小必须>=该值,外围的1个像素用来标识此块区域为二维码
    																 */
    						/*
    						 * fillRect(int x, int y, int width, int height) 函数作用: 填充指定的矩形。该矩形左边和右边位于 x 和 x + width - 1。顶边和底边位于 y 和 y + height - 1。 得到的矩形覆盖的区域宽度为 width 像素,高度为 height 像素。 使用图形上下文的当前颜色填充该矩形。 参数: x - 要填充矩形的 x 坐标。 y - 要填充矩形的 y 坐标。 width - 要填充矩形的宽度。 height - 要填充矩形的高度。
    						 * 
    						 * 参考:http://bk.chinaar.com/index.php?doc-view-2999
    						 */
    					}
    				}
    			}
    			System.out.println("二维码数据长度(字节):" + qrcodeDataLen);
    		} else {
    			System.out.println("Generate QRCode image error! Data size is " + dataLength + ", it is lager than 84 bytes.");
    			return false;
    		}
    		g.dispose();
    		bi.flush();
    		/* generate image */
    		File f = new File(qrcodePicfilePath);
    		if (f.exists()) {
    			return true;
    		}
    		System.out.println(qrcodePicfilePath);
    		String suffix = f.getName().substring(f.getName().indexOf(".") + 1, f.getName().length());
    		try {
    			ImageIO.write(bi, suffix, f); // "png"
    		} catch (IOException ioe) {
    			System.out.println("Generate QRCode image error!" + ioe.getMessage());
    			return false;
    		}
    
    		return true;
    	}
    
    	/**
    	 * Encoding the information to a QRCode, size of the information must be less tah 500 byte.
    	 * 
    	 * @param srcValue
    	 * @param qrcodePicfilePath
    	 * @return
    	 */
    	public static boolean encode_500(String srcValue, String qrcodePicfilePath) {
    		int MAX_DATA_LENGTH = max_data_size_large; // 限制生成二维码的数据最大大小. 500字节的原始数据, 生成二维码时, 是89宽度
    		byte[] d = srcValue.getBytes();
    		int dataLength = d.length;
    		int imageWidth = 269; /* 269是预先计算出来的. 注意:图像宽度必须比生成的二维码图像宽度大,至少相等,否则,二维码识别不出来 */
    		int imageHeight = imageWidth;
    		BufferedImage bi = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);
    		Graphics2D g = bi.createGraphics();
    		g.setBackground(Color.WHITE);
    		g.clearRect(0, 0, imageWidth, imageHeight);
    		g.setColor(Color.BLACK);
    		if (dataLength > 0 && dataLength <= MAX_DATA_LENGTH) {
    			/* 生成二维码 */
    			Qrcode qrcode = new Qrcode();
    			qrcode.setQrcodeErrorCorrect('M'); // L, Q, H, 默认
    			qrcode.setQrcodeEncodeMode('B'); // A, N, 默认
    			qrcode.setQrcodeVersion(18); // 0<= version <=40; 89字节,
    											// (89-1)*3+2+3-1+1 = 269
    			boolean[][] b = qrcode.calQrcode(d);
    			int qrcodeDataLen = b.length;
    			for (int i = 0; i < qrcodeDataLen; i++) {
    				for (int j = 0; j < qrcodeDataLen; j++) {
    					if (b[j][i]) {
    						g.fillRect(j * 3 + 2, i * 3 + 2, 3, 3); /*
    																 * 画二维码图形, 画出的图形宽度是 ((qrcodeDataLen-1)*3+2) + 3 -1 = 136; 生成的image的宽度大小必须>=(136+1),外围的1个像素用来标识此块区域为二维码
    																 */
    						/*
    						 * fillRect(int x, int y, int width, int height) 函数作用: 填充指定的矩形。该矩形左边和右边位于 x 和 x + width - 1。顶边和底边位于 y 和 y + height - 1。 得到的矩形覆盖的区域宽度为 width 像素,高度为 height 像素。 使用图形上下文的当前颜色填充该矩形。 参数: x - 要填充矩形的 x 坐标。 y - 要填充矩形的 y 坐标。 width - 要填充矩形的宽度。 height - 要填充矩形的高度。
    						 * 
    						 * 参考:http://bk.chinaar.com/index.php?doc-view-2999
    						 */
    					}
    				}
    			}
    			System.out.println("二维码数据长度(字节):" + qrcodeDataLen);
    		} else {
    			return false;
    		}
    		g.dispose();
    		bi.flush();
    		/* generate image */
    		File f = new File(qrcodePicfilePath);
    		String suffix = f.getName().substring(f.getName().indexOf(".") + 1, f.getName().length());
    		System.out.println(suffix);
    		try {
    			ImageIO.write(bi, suffix, f); // "png"
    		} catch (IOException ioe) {
    			System.out.println("Generate QRCode image error!" + ioe.getMessage());
    			return false;
    		}
    		return true;
    	}
    }
    

      

    package com.avcon.util;
    
    import java.awt.Color;
    import java.awt.Graphics2D;
    import java.awt.Image;
    import java.awt.geom.AffineTransform;
    import java.awt.image.AffineTransformOp;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    
    import javax.imageio.ImageIO;
    
    import com.google.zxing.BarcodeFormat;
    import com.google.zxing.EncodeHintType;
    import com.google.zxing.MultiFormatWriter;
    import com.google.zxing.WriterException;
    import com.google.zxing.common.BitMatrix;
    import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
    
    public class RQCodeImageUtils {
    	// 图片宽度的一般
    	private static final int IMAGE_WIDTH = 50;
    	private static final int IMAGE_HEIGHT = 50;
    	private static final int IMAGE_HALF_WIDTH = IMAGE_WIDTH / 2;
    	private static final int FRAME_WIDTH = 2;
    
    	// 二维码写码器
    	private static MultiFormatWriter mutiWriter = new MultiFormatWriter();
    
    	public static void encode(String content, int width, int height, String srcImagePath, String destImagePath) {
    		try {
    			ImageIO.write(genBarcode(content, width, height, srcImagePath), "jpg", new File(destImagePath));
    		} catch (IOException e) {
    			e.printStackTrace();
    		} catch (WriterException e) {
    			e.printStackTrace();
    		}
    	}
    
    	private static BufferedImage genBarcode(String content, int width, int height, String srcImagePath) throws WriterException, IOException {
    		// 读取源图像
    		BufferedImage scaleImage = scale(srcImagePath, IMAGE_WIDTH, IMAGE_HEIGHT, true);
    		int[][] srcPixels = new int[IMAGE_WIDTH][IMAGE_HEIGHT];
    		for (int i = 0; i < scaleImage.getWidth(); i++) {
    			for (int j = 0; j < scaleImage.getHeight(); j++) {
    				srcPixels[i][j] = scaleImage.getRGB(i, j);
    			}
    		}
    
    		Map<EncodeHintType, Object> hint = new HashMap<EncodeHintType, Object>();
    		hint.put(EncodeHintType.CHARACTER_SET, "utf-8");
    		hint.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
    		// 生成二维码
    		BitMatrix matrix = mutiWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hint);
    
    		// 二维矩阵转为一维像素数组
    		int halfW = matrix.getWidth() / 2;
    		int halfH = matrix.getHeight() / 2;
    		int[] pixels = new int[width * height];
    
    		for (int y = 0; y < matrix.getHeight(); y++) {
    			for (int x = 0; x < matrix.getWidth(); x++) {
    				// 读取图片
    				if (x > halfW - IMAGE_HALF_WIDTH && x < halfW + IMAGE_HALF_WIDTH && y > halfH - IMAGE_HALF_WIDTH && y < halfH + IMAGE_HALF_WIDTH) {
    					pixels[y * width + x] = srcPixels[x - halfW + IMAGE_HALF_WIDTH][y - halfH + IMAGE_HALF_WIDTH];
    				}
    				// 在图片四周形成边框
    				else if ((x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH && x < halfW - IMAGE_HALF_WIDTH + FRAME_WIDTH && y > halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH && y < halfH + IMAGE_HALF_WIDTH + FRAME_WIDTH) || (x > halfW + IMAGE_HALF_WIDTH - FRAME_WIDTH && x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH && y > halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH && y < halfH + IMAGE_HALF_WIDTH + FRAME_WIDTH) || (x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH && x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH && y > halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH && y < halfH - IMAGE_HALF_WIDTH + FRAME_WIDTH) || (x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH && x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH && y > halfH + IMAGE_HALF_WIDTH - FRAME_WIDTH && y < halfH + IMAGE_HALF_WIDTH + FRAME_WIDTH)) {
    					pixels[y * width + x] = 0xfffffff;
    				} else {
    					// 此处可以修改二维码的颜色,可以分别制定二维码和背景的颜色;
    					pixels[y * width + x] = matrix.get(x, y) ? 0xff000000 : 0xfffffff;
    				}
    			}
    		}
    
    		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    		image.getRaster().setDataElements(0, 0, width, height, pixels);
    
    		return image;
    	}
    
    	/**
    	 * 把传入的原始图像按高度和宽度进行缩放,生成符合要求的图标
    	 * 
    	 * @param srcImageFile
    	 *            源文件地址
    	 * @param height
    	 *            目标高度
    	 * @param width
    	 *            目标宽度
    	 * @param hasFiller
    	 *            比例不对时是否需要补白:true为补白; false为不补白;
    	 * @throws IOException
    	 */
    	private static BufferedImage scale(String srcImageFile, int height, int width, boolean hasFiller) throws IOException {
    		double ratio = 0.0; // 缩放比例
    		File file = new File(srcImageFile);
    		BufferedImage srcImage = ImageIO.read(file);
    		Image destImage = srcImage.getScaledInstance(width, height, BufferedImage.SCALE_SMOOTH);
    		// 计算比例
    		if ((srcImage.getHeight() > height) || (srcImage.getWidth() > width)) {
    			if (srcImage.getHeight() > srcImage.getWidth()) {
    				ratio = (new Integer(height)).doubleValue() / srcImage.getHeight();
    			} else {
    				ratio = (new Integer(width)).doubleValue() / srcImage.getWidth();
    			}
    			AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(ratio, ratio), null);
    			destImage = op.filter(srcImage, null);
    		}
    		if (hasFiller) {// 补白
    			BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    			Graphics2D graphic = image.createGraphics();
    			graphic.setColor(Color.white);
    			graphic.fillRect(0, 0, width, height);
    			if (width == destImage.getWidth(null))
    				graphic.drawImage(destImage, 0, (height - destImage.getHeight(null)) / 2, destImage.getWidth(null), destImage.getHeight(null), Color.white, null);
    			else
    				graphic.drawImage(destImage, (width - destImage.getWidth(null)) / 2, 0, destImage.getWidth(null), destImage.getHeight(null), Color.white, null);
    			graphic.dispose();
    			destImage = image;
    		}
    		return (BufferedImage) destImage;
    	}
    }
    

      

  • 相关阅读:
    java io系列23之 BufferedReader(字符缓冲输入流)
    java io系列22之 FileReader和FileWriter
    java io系列21之 InputStreamReader和OutputStreamWriter
    java io系列20之 PipedReader和PipedWriter
    java io系列19之 CharArrayWriter(字符数组输出流)
    java io系列18之 CharArrayReader(字符数组输入流)
    java io系列17之 System.out.println("hello world")原理
    java io系列16之 PrintStream(打印输出流)详解
    java io系列15之 DataOutputStream(数据输出流)的认知、源码和示例
    java io系列14之 DataInputStream(数据输入流)的认知、源码和示例
  • 原文地址:https://www.cnblogs.com/zhoucx66/p/9627804.html
Copyright © 2011-2022 走看看