百度盤工具生成二維碼:
http://pan.baidu.com/share/qrcode?w=150&h=150&url=https://qr.alipay.com/bax06945fl00z4vfiovp20c6
一.maven配置
<!-- 生成二維碼zxing工具包-->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.1.0</version>
</dependency>
二.二維碼類
package com.corefire.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.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.apache.http.client.ResponseHandler;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Binarizer;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.NotFoundException;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import javax.servlet.http.HttpServletResponse;
public class QRCodeUtil {
// 這幾項可以由其他調(diào)用的類設(shè)置依啰,因此是public static的
public static int BARCODE_WIDTH = 80;
public static int QRCODE_WIDTH = 200;
public static String FORMAT = "jpg";// 生成的圖片格式
public static int BLACK = 0x000000;// 編碼的顏色
public static int WHITE = 0xFFFFFF;// 空白的顏色
// 二維碼中間的圖像配置阎曹。注意,由于二維碼的容錯率有限花竞,因此中間遮擋的面積不要太大驮审,否則可能解析不出來鲤竹。
private static int ICON_WIDTH = (int)(QRCODE_WIDTH / 6);
private static int HALF_ICON_WIDTH = ICON_WIDTH / 2;
private static int FRAME_WIDTH = 2;// Icon四周的邊框?qū)挾?
// 二維碼讀碼器和寫碼器
private static final MultiFormatWriter WRITER = new MultiFormatWriter();
private static final MultiFormatReader READER = new MultiFormatReader();
// 測試
public static void main(String[] args) throws Exception {
/**
* 二維碼測試。
*/
String iconPath = "/home/lxf/qrcode/icon.jpg";
String content = "http://www.baidu.com";
File qrCode = new File("/home/lxf/qrcode/qrcode." + FORMAT);
File qrCodeWithIcon = new File("/home/lxf/qrcode/qrcode_img." + FORMAT);
// 生成二維碼
writeToFile(createQRCode(content), qrCode);
// 生成帶圖標的二維碼
writeToFile(createQRCodeWithIcon(content, iconPath), qrCodeWithIcon);
// 解析二維碼
System.out.println(parseImage(qrCode));
// 解析帶圖標的二維碼
System.out.println(parseImage(qrCodeWithIcon));
// 編碼成字節(jié)數(shù)組
byte[] data = createQRCodeToBytes(content);
String result = parseQRFromBytes(data);
System.out.println(result);
/**
* 一維碼測試。
*/
String barCodeContent="6936983800013";
File barCode = new File("C:\\BarCode." + FORMAT);
// 生成一維碼
writeToFile(createBarCode(barCodeContent), barCode);
// 解析一維碼
System.out.println(parseImage(barCode));
}
/**
* 將String編碼成二維碼的圖片后黍析,使用字節(jié)數(shù)組表示,便于傳輸屎开。
*
* @param content
* @return
* @throws WriterException
* @throws IOException
*/
public static byte[] createQRCodeToBytes(String content)
throws WriterException, IOException {
BufferedImage image = createQRCode(content);
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(image, FORMAT, os);
return os.toByteArray();
}
/**
* 把一個String編碼成二維碼的BufferedImage.
*
* @param content
* @return
* @throws WriterException
*/
public static final BufferedImage createQRCode(String content)
throws WriterException {
// 長和寬一樣橄仍,所以只需要定義一個SIZE即可
BitMatrix matrix = WRITER.encode(
content, BarcodeFormat.QR_CODE, QRCODE_WIDTH, QRCODE_WIDTH);
return toBufferedImage(matrix);
}
/**
* 編碼字符串為二維碼,并在該二維碼中央插入指定的圖標牍戚。
* @param content
* @param iconPath
* @return
* @throws WriterException
*/
public static final BufferedImage createQRCodeWithIcon(
String content, String iconPath) throws WriterException {
BitMatrix matrix = WRITER.encode(
content, BarcodeFormat.QR_CODE, QRCODE_WIDTH, QRCODE_WIDTH);
// 讀取Icon圖像
BufferedImage scaleImage = null;
try {
scaleImage = scaleImage(iconPath, ICON_WIDTH, ICON_WIDTH, true);
} catch (IOException e) {
e.printStackTrace();
}
int[][] iconPixels = new int[ICON_WIDTH][ICON_WIDTH];
for (int i = 0; i < scaleImage.getWidth(); i++) {
for (int j = 0; j < scaleImage.getHeight(); j++) {
iconPixels[i][j] = scaleImage.getRGB(i, j);
}
}
// 二維碼的寬和高
int halfW = matrix.getWidth() / 2;
int halfH = matrix.getHeight() / 2;
// 計算圖標的邊界:
int minX = halfW - HALF_ICON_WIDTH;//左
int maxX = halfW + HALF_ICON_WIDTH;//右
int minY = halfH - HALF_ICON_WIDTH;//上
int maxY = halfH + HALF_ICON_WIDTH;//下
int[] pixels = new int[QRCODE_WIDTH * QRCODE_WIDTH];
// 修改二維碼的字節(jié)信息侮繁,替換掉一部分為圖標的內(nèi)容。
for (int y = 0; y < matrix.getHeight(); y++) {
for (int x = 0; x < matrix.getWidth(); x++) {
// 如果點在圖標的位置如孝,用圖標的內(nèi)容替換掉二維碼的內(nèi)容
if (x > minX && x < maxX && y > minY && y < maxY) {
int indexX = x - halfW + HALF_ICON_WIDTH;
int indexY = y - halfH + HALF_ICON_WIDTH;
pixels[y * QRCODE_WIDTH + x] = iconPixels[indexX][indexY];
}
// 在圖片四周形成邊框
else if ((x > minX - FRAME_WIDTH && x < minX + FRAME_WIDTH
&& y > minY - FRAME_WIDTH && y < maxY + FRAME_WIDTH)
|| (x > maxX - FRAME_WIDTH && x < maxX + FRAME_WIDTH
&& y > minY - FRAME_WIDTH && y < maxY + FRAME_WIDTH)
|| (x > minX - FRAME_WIDTH && x < maxX + FRAME_WIDTH
&& y > minY - FRAME_WIDTH && y < minY + FRAME_WIDTH)
|| (x > minX - FRAME_WIDTH && x < maxX + FRAME_WIDTH
&& y > maxY - FRAME_WIDTH && y < maxY + FRAME_WIDTH)) {
pixels[y * QRCODE_WIDTH + x] = WHITE;
}
else {
// 這里是其他不屬于圖標的內(nèi)容宪哩。即為二維碼沒有被圖標遮蓋的內(nèi)容,用矩陣的值來顯示顏色第晰。
pixels[y * QRCODE_WIDTH + x] = matrix.get(x, y) ? BLACK : WHITE;
}
}
}
// 用修改后的字節(jié)數(shù)組創(chuàng)建新的BufferedImage.
BufferedImage image = new BufferedImage(
QRCODE_WIDTH, QRCODE_WIDTH, BufferedImage.TYPE_INT_RGB);
image.getRaster().setDataElements(0, 0, QRCODE_WIDTH, QRCODE_WIDTH, pixels);
return image;
}
/**
* 從一個二維碼圖片的字節(jié)信息解碼出二維碼中的內(nèi)容锁孟。
*
* @param data
* @return
* @throws ReaderException
* @throws IOException
*/
public static String parseQRFromBytes(byte[] data)
throws ReaderException, IOException {
ByteArrayInputStream is = new ByteArrayInputStream(data);
BufferedImage image = ImageIO.read(is);
return parseImage(image);
}
/**
* 從一個圖片文件中解碼出二維碼中的內(nèi)容。
*
* @param file
* @return 解析后的內(nèi)容茁瘦。
* @throws IOException
* @throws ReaderException
*/
public static final String parseImage(File file)
throws IOException, ReaderException {
BufferedImage image = ImageIO.read(file);
return parseImage(image);
}
/**
* 將字符串編碼成一維碼(條形碼)品抽。
* @param content
* @return
* @throws WriterException
* @throws IOException
*/
public static BufferedImage createBarCode(String content)
throws WriterException, IOException {
MultiFormatWriter writer = new MultiFormatWriter();
// 一維碼的寬>高。這里我設(shè)置為 寬:高=2:1
BitMatrix matrix = writer.encode(content,
BarcodeFormat.EAN_13, BARCODE_WIDTH * 3, BARCODE_WIDTH);
return toBufferedImage(matrix);
}
/**
* 從圖片中解析出一維碼或者二維碼的內(nèi)容甜熔。如果解析失敗圆恤,則拋出NotFoundException。
* @param image
* @return
* @throws NotFoundException
*/
public static final String parseImage(BufferedImage image)
throws NotFoundException {
LuminanceSource source = new BufferedImageLuminanceSource(image);
Binarizer binarizer = new HybridBinarizer(source);
BinaryBitmap bitmap = new BinaryBitmap(binarizer);
Result result = READER.decode(bitmap);
// 這里丟掉了Result中其他一些數(shù)據(jù)
return result.getText();
}
/**
* 將BufferedImage對象輸出到指定的文件中腔稀。
*
* @param image
* @param destFile
* @throws IOException
*/
public static final void writeToFile(BufferedImage image, File destFile)
throws IOException {
ImageIO.write(image, FORMAT, destFile);
}
/**
* 將BufferedImage對象直接response
* @param image
* @param response
* @throws IOException
*/
public static final void showQrcode(BufferedImage image, HttpServletResponse response) throws IOException
{
ImageIO.write(image, FORMAT, response.getOutputStream());
}
/**
* 將一個BitMatrix對象轉(zhuǎn)換成BufferedImage對象
*
* @param matrix
* @return
*/
private 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) ? BLACK : WHITE);
}
}
return image;
}
/**
* 把傳入的原始圖像按高度和寬度進行縮放盆昙,生成符合要求的圖標。
*
* @param srcImageFile 源文件地址
* @param height 目標高度
* @param width 目標寬度
* @param hasFiller 比例不對時是否需要補白:true為補白; false為不補白;
* @throws IOException
*/
private static BufferedImage scaleImage(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;
}
}
三.使用servlet直接將二維碼動態(tài)輸出
web.xml配置
<!-- 生成二維碼到j(luò)sp頁面 2017-07-04 liangxifeng -->
<servlet>
<servlet-name>QrcodeServlet</servlet-name>
<servlet-class>com.corefire.servlet.QrcodeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>QrcodeServlet</servlet-name>
<url-pattern>/QrcodeServlet</url-pattern>
</servlet-mapping>
<!--
<servlet-mapping>
<servlet-name>QrcodeServlet</servlet-name>
<url-pattern>/qrcode.jsp</url-pattern>
</servlet-mapping>
-->
</web-app>
QrcodeServlet配置
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
request.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
/**
* 二維碼測試焊虏。
*/
String iconPath = "/home/lxf/qrcode/icon.jpg";
String content = "http://www.baidu.com";
//一. 生成二維碼圖片直接輸出
/*
try {
QRCodeUtil.showQrcode(QRCodeUtil.createQRCode(content), response);
} catch (WriterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
// 二.生成帶圖標的二維碼直接輸出
try {
QRCodeUtil.showQrcode(QRCodeUtil.createQRCodeWithIcon(content, iconPath), response);
} catch (WriterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
四.使用
<img alt="img" width="800" height="800" src="http://localhost:8081/wxpay/QrcodeServlet">
可以將二維碼內(nèi)容作為參數(shù)傳遞淡喜,實現(xiàn)動態(tài)效果!