package org.yeshi.utils;
|
|
import java.awt.BasicStroke;
|
import java.awt.Graphics;
|
import java.awt.Graphics2D;
|
import java.awt.Image;
|
import java.awt.Shape;
|
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.IOException;
|
import java.io.InputStream;
|
import java.io.OutputStream;
|
import java.util.Hashtable;
|
|
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.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 Administrator
|
*/
|
public class QRCodeUtil {
|
private static final String CHARSET = "UTF-8";
|
private static final String FORMAT_NAME = "JPG";
|
|
// 二维码尺寸
|
int QRCODE_SIZE = 200;
|
// LOGO宽度
|
int WIDTH = 60;
|
// LOGO高度
|
int HEIGHT = 60;
|
|
static QRCodeUtil qrCodeUtil;
|
|
public static QRCodeUtil getInstance(int size) {
|
if (qrCodeUtil == null) {
|
qrCodeUtil = new QRCodeUtil();
|
}
|
qrCodeUtil.QRCODE_SIZE = size;
|
return qrCodeUtil;
|
}
|
|
public static QRCodeUtil getInstance(int size, int imgSize) {
|
if (qrCodeUtil == null) {
|
qrCodeUtil = new QRCodeUtil();
|
}
|
qrCodeUtil.QRCODE_SIZE = size;
|
qrCodeUtil.HEIGHT = imgSize;
|
qrCodeUtil.WIDTH = imgSize;
|
return qrCodeUtil;
|
}
|
|
/**
|
* user: Rex date: 2016年12月29日 上午12:31:29
|
*
|
* @param content 二维码内容
|
* @param logoImgPath Logo
|
* @param needCompress 是否压缩Logo
|
* @return 返回二维码图片
|
* @throws WriterException
|
* @throws IOException
|
*/
|
private BufferedImage createImage(String content, InputStream logoImg, boolean needCompress)
|
throws WriterException, IOException {
|
return this.createImage(content, logoImg, 0xFF000000, 0xFFFFFFFF, needCompress);
|
}
|
|
|
public BufferedImage createImage(String content, InputStream logoImg, int color, int bgColor, boolean needCompress)
|
throws WriterException, IOException {
|
Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
|
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
|
hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
|
hints.put(EncodeHintType.MARGIN, 1);
|
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE,
|
hints);
|
|
int width = bitMatrix.getWidth();
|
int height = bitMatrix.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, bitMatrix.get(x, y) ? color : bgColor);
|
}
|
}
|
if (logoImg == null) {
|
return image;
|
}
|
|
if (logoImg != null) {
|
// 插入图片
|
insertImage(image, logoImg, needCompress);
|
}
|
|
return image;
|
}
|
|
/**
|
* user: Rex date: 2016年12月29日 上午12:31:29
|
*
|
* @param content 二维码内容
|
* @param logoImgPath Logo
|
* @param needCompress 是否压缩Logo
|
* @return 返回二维码图片
|
* @throws WriterException
|
* @throws IOException
|
*/
|
private BufferedImage createImageDeleteWhite(String content, InputStream logoImg, boolean needCompress)
|
throws WriterException, IOException {
|
return createImageDeleteWhite(content, logoImg, 0xFF000000, 0xFFFFFFFF, needCompress);
|
}
|
|
|
public BufferedImage createImageDeleteWhite(String content, InputStream logoImg, int color, int bgColor, boolean needCompress)
|
throws WriterException, IOException {
|
Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
|
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
|
hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
|
hints.put(EncodeHintType.MARGIN, 1);
|
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE,
|
hints);
|
|
//调用去除白边方法
|
bitMatrix = deleteWhite(bitMatrix);
|
|
int width = bitMatrix.getWidth();
|
int height = bitMatrix.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, bitMatrix.get(x, y) ? color : bgColor);
|
}
|
}
|
if (logoImg == null) {
|
return image;
|
}
|
|
// 插入图片
|
if (logoImg != null) {
|
insertImage(image, logoImg, needCompress);
|
}
|
return image;
|
}
|
|
/**
|
* user: Rex date: 2016年12月29日 上午12:30:09
|
*
|
* @param source 二维码图片
|
* @param logoImgPath Logo
|
* @param needCompress 是否压缩Logo
|
* @throws IOException void TODO 添加Logo
|
*/
|
private void insertImage(BufferedImage source, InputStream logoImg, boolean needCompress) throws IOException {
|
Image src = ImageIO.read(logoImg);
|
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 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();
|
}
|
|
/**
|
* user: Rex date: 2016年12月29日 上午12:32:32
|
*
|
* @param content 二维码内容
|
* @param logoImgPath Logo
|
* @param destPath 二维码输出路径
|
* @param needCompress 是否压缩Logo
|
* @throws Exception void TODO 生成带Logo的二维码
|
*/
|
public void encode(String content, InputStream logoImg, String destPath, boolean needCompress) throws Exception {
|
BufferedImage image = createImage(content, logoImg, needCompress);
|
ImageIO.write(image, FORMAT_NAME, new File(destPath));
|
}
|
|
/**
|
* user: Rex date: 2016年12月29日 上午12:35:44
|
*
|
* @param content 二维码内容
|
* @param destPath 二维码输出路径
|
* @throws Exception void TODO 生成不带Logo的二维码
|
*/
|
public void encode(String content, String destPath) throws Exception {
|
encode(content, null, destPath, false);
|
}
|
|
public InputStream encode(String content) throws Exception {
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
encode(content, null, out, false);
|
return new ByteArrayInputStream(out.toByteArray());
|
}
|
|
|
public InputStream encodeDeleteWhite(String content) throws Exception {
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
encodeDeleteWhite(content, null, out, false);
|
return new ByteArrayInputStream(out.toByteArray());
|
}
|
|
|
/**
|
* user: Rex date: 2016年12月29日 上午12:36:58
|
*
|
* @param content 二维码内容
|
* @param logoImgPath Logo
|
* @param output 输出流
|
* @param needCompress 是否压缩Logo
|
* @throws Exception void TODO 生成带Logo的二维码,并输出到指定的输出流
|
*/
|
public void encode(String content, InputStream logoImg, OutputStream output, boolean needCompress)
|
throws Exception {
|
BufferedImage image = createImage(content, logoImg, needCompress);
|
ImageIO.write(image, FORMAT_NAME, output);
|
}
|
|
/**
|
* @param content
|
* @param logoImg
|
* @param output 二进制输出流
|
* @param needCompress
|
* @throws Exception
|
*/
|
public void encode(String content, InputStream logoImg, ByteArrayOutputStream output, boolean needCompress)
|
throws Exception {
|
BufferedImage image = createImage(content, logoImg, needCompress);
|
ImageIO.write(image, FORMAT_NAME, output);
|
}
|
|
/**
|
* @param content
|
* @param logoImg
|
* @param output 二进制输出流
|
* @param needCompress
|
* @throws Exception
|
*/
|
public void encodeDeleteWhite(String content, InputStream logoImg, ByteArrayOutputStream output, boolean needCompress)
|
throws Exception {
|
BufferedImage image = createImageDeleteWhite(content, logoImg, needCompress);
|
ImageIO.write(image, FORMAT_NAME, output);
|
}
|
|
/**
|
* user: Rex date: 2016年12月29日 上午12:38:02
|
*
|
* @param content 二维码内容
|
* @param output 输出流
|
* @throws Exception void TODO 生成不带Logo的二维码,并输出到指定的输出流
|
*/
|
public void encode(String content, OutputStream output) throws Exception {
|
encode(content, null, output, false);
|
}
|
|
/**
|
* user: Rex date: 2016年12月29日 上午12:39:10
|
*
|
* @param file 二维码
|
* @return 返回解析得到的二维码内容
|
* @throws Exception String TODO 二维码解析
|
*/
|
public 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<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
|
hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
|
result = new MultiFormatReader().decode(bitmap, hints);
|
String resultStr = result.getText();
|
return resultStr;
|
}
|
|
/**
|
* user: Rex date: 2016年12月29日 上午12:39:48
|
*
|
* @param path 二维码存储位置
|
* @return 返回解析得到的二维码内容
|
* @throws Exception String TODO 二维码解析
|
*/
|
public String decode(String path) throws Exception {
|
return decode(new File(path));
|
}
|
|
private static BitMatrix deleteWhite(BitMatrix matrix) {
|
int[] rec = matrix.getEnclosingRectangle();
|
int resWidth = rec[2] + 1;
|
int resHeight = rec[3] + 1;
|
|
BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
|
resMatrix.clear();
|
for (int i = 0; i < resWidth; i++) {
|
for (int j = 0; j < resHeight; j++) {
|
if (matrix.get(i + rec[0], j + rec[1]))
|
resMatrix.set(i, j);
|
}
|
}
|
return resMatrix;
|
}
|
}
|