java二維碼生成

/**
 * 
 */
package com.spg.test;

/**
 * 項目名稱:weixinpay
 * 
 * @description:二維碼生成<br>
 * 注意生成二維碼和解析過程中的編碼必須爲GBK,否則解析過程會出錯。
 * 
 * @author spg
 * 
 * @create_time:2014年5月20日 上午11:26:27
 * 
 * @version V1.0.0
 * 
 */
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.FileOutputStream;
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.BinaryBitmap;
import com.google.zxing.DecodeHintType;
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;

public class QRCodeUtil
{

	/**
	 * 二維碼寬高度默認200
	 */
	private static final int DEFAULT_IMAGE_WIDTH = 300;
	private static final int DEFAULT_IMAGE_HEIGHT = 300;
	
	/**
	 * 生成帶圖片二維碼時內部圖片大小
	 */
	private static final int INNER_IMAGE_WIDTH = 60;
	private static final int INNER_IMAGE_HEIGHT = 60;
	private static final int IMAGE_HALF_WIDTH = INNER_IMAGE_WIDTH / 2;
	private static final int FRAME_WIDTH = 2;

	/**
	 * 生成普通二維碼
	 * 
	 * @param contents 內容
	 * @param width 二維碼寬度,如果小於0,則按默認大小生成
	 * @param height 二維碼高度,如果小於0,則按默認大小生成
	 * @param imgPath 生成後的文件完整存放路徑,包含文件名。形如D:\aa.jpg
	 */
	public static void encodePR(String contents, int width, int height,
			String imgPath)
	{
		Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
		// 指定糾錯等級
		hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
		// 指定編碼格式
		hints.put(EncodeHintType.CHARACTER_SET, "GBK");
		if (width <= 0 || height <= 0)
		{
			width = DEFAULT_IMAGE_WIDTH;
			height = DEFAULT_IMAGE_HEIGHT;
		}
		try
		{
			BitMatrix bitMatrix = new MultiFormatWriter().encode(contents,
					BarcodeFormat.QR_CODE, width, height, hints);
			MatrixToImageWriter.writeToStream(bitMatrix, "jpg",
					new FileOutputStream(imgPath));
		} catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * 生成帶圖片的二維碼
	 * 
	 * @param content
	 * @param width
	 * @param height
	 * @param srcImagePath
	 * @param destImagePath
	 */
	public static void encodePR(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();
		}
	}

	/**
	 * 針對二維碼進行解析
	 * 
	 * @param imgPath 二維碼文件路徑
	 * @return
	 */
	public static String decodePR(String imgPath)
	{
		BufferedImage image = null;
		Result result = null;
		try
		{
			image = ImageIO.read(new File(imgPath));
			if (image == null)
			{
				throw new RuntimeException("the decode image may be not exists.");
			}
			LuminanceSource source = new BufferedImageLuminanceSource(image);
			BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

			Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
			hints.put(DecodeHintType.CHARACTER_SET, "GBK");

			result = new MultiFormatReader().decode(bitmap, hints);
			return result.getText();

		} catch (Exception e)
		{
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 創建條形碼
	 * 
	 * @param contents
	 * @param width
	 * @param height
	 * @param imgPath
	 */
	public static void encodeBar(String contents, int width, int height,
			String imgPath)
	{
		// 條形碼的最小寬度
		int codeWidth = 98;
		codeWidth = Math.max(codeWidth, width);
		try
		{
			BitMatrix bitMatrix = new MultiFormatWriter().encode(contents,
					BarcodeFormat.EAN_13, codeWidth, height, null);

			MatrixToImageWriter.writeToStream(bitMatrix, "png",
					new FileOutputStream(imgPath));

		} catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * 針對條形碼進行解析
	 * 
	 * @param imgPath
	 * @return
	 */
	public static String decodeBar(String imgPath)
	{
		BufferedImage image = null;
		Result result = null;
		try
		{
			image = ImageIO.read(new File(imgPath));
			if (image == null)
			{
				System.out.println("the decode image may be not exit.");
			}
			LuminanceSource source = new BufferedImageLuminanceSource(image);
			BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

			result = new MultiFormatReader().decode(bitmap, null);
			return result.getText();
		} catch (Exception e)
		{
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 把傳入的原始圖像按高度和寬度進行縮放,生成符合要求的圖標
	 * 
	 * @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;
	}

	/**
	 * 產生帶有圖片的二維碼緩衝圖像
	 * 
	 * @param content
	 * @param width
	 * @param height
	 * @param srcImagePath
	 * @return
	 * @throws WriterException
	 * @throws IOException
	 */
	private static BufferedImage genBarcode(String content, int width,
			int height, String srcImagePath) throws WriterException,
			IOException
	{
		// 讀取源圖像
		BufferedImage scaleImage = scale(srcImagePath, INNER_IMAGE_WIDTH,
				INNER_IMAGE_HEIGHT, true);
		int[][] srcPixels = new int[INNER_IMAGE_WIDTH][INNER_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, "GBK");
		hint.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
		// 生成二維碼
		MultiFormatWriter mutiWriter = new MultiFormatWriter();
		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;
	}

	public static void main(String[] args)
	{
		String imgPath = "d:/pr1.jpg";
		String contents = "你好,李四! welcome to zxing!"
				+ "\n李四的博客[http://my.oschina.net/cloudcoder]"
				+ "\nEmail[[email protected]]";
		// 普通二維碼的生成與解析
		QRCodeUtil.encodePR(contents, 0, 10, imgPath);
		System.out.println("生成二維碼成功");
		System.out.println(QRCodeUtil.decodePR(imgPath));

		 // 帶圖片的二維的生成與解析
		 imgPath = "d:/pr2.png";
		 String srcPath = "d:/src.jpg";
		 QRCodeUtil.encodePR(contents, 300, 300, srcPath, imgPath);
		 System.out.println("生成帶圖片的二維碼成功");
		 System.out.println(QRCodeUtil.decodePR(imgPath));
		
		 // 條形碼的生成與解析
		 imgPath = "d:/bar.png";
		 QRCodeUtil.encodeBar("6923450657713", 105, 50, imgPath);
		 System.out.println("生成條形碼成功");
		 System.out.println(QRCodeUtil.decodeBar(imgPath));
	}
}


注意:如果使用JDK1.7版本,jar包的maven庫爲:

	<dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>3.0.1</version>
        </dependency>


但是如果使用JDK1.6一下版本編譯,用以上jar包會報錯,改用2.2版本jar包可解決。

zxing2.2.jar下載地址:http://download.csdn.net/detail/fengspg/7378425


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章