二维码技术不是什么新技术了,但是这几天工作用到,然后才现学习现使用,使用的是Google的ZXing,使用起来很简单,
我练习的两种方式,一种的简单的javase工程,一种是Android客户端生成解析二维码的demo,线面逐个介绍。
一、JavaSE生成解析二维码,就是建立一个JavaProject,然后导入jar包,我用的是maven,所以建立了一个简单的maven工程。
1、第一种形式,生成一个中间没有logo的二维码,并解析,写好之后,直接说哪个junit测试,就能生成解析二维码了
package com.wang.qr.code;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO;
import org.junit.Test;
import com.alibaba.fastjson.JSONObject;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Binarizer;
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.NotFoundException;
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;
/**
* 生成没有logo的二维码</br> 有多个信息json
*
* @author wang
*
*/
public class QRCodeTest1 {
/**
* 生成二维码</br>
*
* 二维码中的内容是json数据
*
* @throws WriterException
* @throws IOException
*/
@Test
public void testEncode() throws WriterException, IOException {
/*
* 把生成的二维码放到此目录下
*/
String filePath = "E://";
/*
* 生成的二维码名称
*/
String fileName = "zxing.png";
JSONObject json = new JSONObject();
json.put("zxing", "https://github.com/zxing/zxing/tree/zxing-3.0.0/javase/src/main/java/com/google/zxing");
json.put("author", "shihy");
/*
* 二维码中的内容
*/
String content = json.toJSONString();// 内容
int width = 200; // 图像宽度
int height = 200; // 图像高度
String format = "png";// 图像类型
Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);// 生成矩阵
Path path = FileSystems.getDefault().getPath(filePath, fileName);
MatrixToImageWriter.writeToPath(bitMatrix, format, path);// 输出图像
System.out.println("输出成功.");
}
/**
* 解析二维码</br> 二维码中的内容是json数据
*/
@Test
public void testDecode() {
/*
* 要解析的二维码
*/
String filePath = "E://zxing.png";
BufferedImage image;
try {
image = ImageIO.read(new File(filePath));
LuminanceSource source = new BufferedImageLuminanceSource(image);
Binarizer binarizer = new HybridBinarizer(source);
BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
Result result = new MultiFormatReader().decode(binaryBitmap, hints);// 对图像进行解码
/*
* 得到二维码中的字符串内容
*/
//String context = result.getText();
JSONObject content = JSONObject.parseObject(result.getText());
System.out.println("图片中内容: ");
System.out.println("author: " + content.getString("author"));
System.out.println("zxing: " + content.getString("zxing"));
System.out.println("图片中格式: ");
System.out.println("encode: " + result.getBarcodeFormat());
} catch (IOException e) {
e.printStackTrace();
} catch (NotFoundException e) {
e.printStackTrace();
}
}
}
2、第二种形式,生成有logo的二维码,工具类如下
package com.wang.qr.code.utils;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Hashtable;
import javax.imageio.ImageIO;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
/**
* 生成普通二维码和生成带logo的二维码
*
* @author wang
*
*/
public class QRCodeTestUtil3 {
private static final int BLACK = 0xFF000000;
private static final int WHITE = 0xFFFFFFFF;
/**
* 生成普通没有logo的二维码
*
* @param filePath
* 文本文件路径,该文件中的内容是生成二维码图片中的内容(文本需以UTF-8)
* @param imgFormate
* 指定生成的二维码图片的后缀名
* @param width
* 指定生成的二维码图片的宽度
* @param height
* 指定生成的二维码图片的高度
*/
public static void createTwoDimensionalCode(String filePath, String imgFormate, int width, int height) {
File file = new File(filePath);
StringBuffer contents = new StringBuffer("");
// 读取文本文件内容到 contents
try {
InputStream is = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
try {
String temp = br.readLine();
while (temp != null) {
contents.append(temp + "\r\n");
temp = br.readLine();
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// 得到图片该存放路径
String imgPath = file.getParent();
// 得到文件该设置的名字
String imgName = file.getName();
int endIndex = imgName.lastIndexOf(".");
imgName = imgName.substring(0, endIndex);
File imageFile = new File(imgPath, imgName + "." + imgFormate);
Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
// 指定纠错等级
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
// 指定编码格式
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
try {
BitMatrix bitMatrix = new MultiFormatWriter().encode(contents.toString(), BarcodeFormat.QR_CODE, width,
height, hints);
MatrixToImageWriter.writeToPath(bitMatrix, imgFormate, imageFile.toPath());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 生成带logo的二维码图片
*
* @param url
* 要生成二维码的url
* @param imgPath
* 二维码生成的绝对路径
* @param logoPath
* 二维码中间logo绝对地址
* @throws Exception
*/
public static void get2CodeImage(String url, String imgPath, String logoPath) throws Exception {
String format = "png";
Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
BitMatrix bitMatrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, 300, 300, hints);
File qrcodeFile = new File(imgPath);
writeToFile(bitMatrix, format, qrcodeFile, logoPath);
}
/**
*
* @param matrix
* 二维码矩阵相关
* @param format
* 二维码图片格式
* @param file
* 二维码图片文件
* @param logoPath
* logo路径
* @throws IOException
*/
private static void writeToFile(BitMatrix matrix, String format, File file, String logoPath) throws IOException {
BufferedImage image = toBufferedImage(matrix);
Graphics2D gs = image.createGraphics();
// 载入logo
Image img = ImageIO.read(new File(logoPath));
gs.drawImage(img, 125, 125, null);
gs.dispose();
img.flush();
if (!ImageIO.write(image, format, file)) {
throw new IOException("Could not write an image of format " + format + " to " + file);
}
}
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;
}
}
测试类:
package com.wang.qr.code;
import org.junit.Test;
import com.wang.qr.code.utils.QRCodeTestUtil3;
/**
* @author wang
*
*/
public class QRCodeTest3 {
@Test
public void createNoLogoQRCode() {
QRCodeTestUtil3.createTwoDimensionalCode("E://test.txt", "png", 200, 200);
}
@Test
public void createHaveLogoQRCode() {
try {
QRCodeTestUtil3.get2CodeImage("https://shop100133013.taobao.com/shop/view_shop.htm?spm=a1z0k.7386009.1997989141.d4915209.abFEJh&shop_id=100133013", "E://havalogoQRCode.png", "E://logo.png");
} catch (Exception e) {
e.printStackTrace();
}
}
}
效果图:(一张有用的二维码,不信可以用微信扫扫哦。。。)
在联系的时候,我是用的maven工程,附上maven工程的pom文件:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>QRCodeTest</groupId>
<artifactId>QRCodeTest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>QRCodeTest</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.7</version>
</dependency>
</dependencies>
</project>
二、第二个练习的是写了一个Android的应用程序,能够根据填写内容,和是否选择二维码logo,生成一个二维码;能够像微信一样扫描二维码(在网上找到的demo代码直接用的),
Android上生成二维码与javase生成二维码的核心代码原理一样,都是zxing,但是有不一样的地方,javase生成二维码后,能够直 接在本地保存二维码文件。Android应用程序这样的话就不要友好了,我们应该先将二维码生成bitmap的形式,然后显示在imageView上面, 由使用者选择是否保存二维码,就像下面的界面一样,
这样的话,生成二维码的代码就不一样了。下面是在Android中生成二维码bitmap的代码:
package com.wang.qrcodecreateandscantool.util;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import java.util.Hashtable;
/**
* 生成二维码的工具类
* <p/>
* Created by wang on 2015/11/12.
*/
public class QRCodeCreateUtil {
/**
* 生成没有logo的二维码Bitmap
*
* @param context 二维码内容
* @param widthPix 二维码宽度
* @param heightPix 二维码高度
* @return Bitmap
*/
public static Bitmap createNoLogoQRCode(String context, int widthPix, int heightPix) {
Bitmap bitmap = null;
try {
Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
BitMatrix bitMatrix = new MultiFormatWriter().encode(context, BarcodeFormat.QR_CODE, widthPix, heightPix, hints);
int[] pixels = new int[widthPix * heightPix];
for (int y = 0; y < heightPix; y++) {
for (int x = 0; x < widthPix; x++) {
if (bitMatrix.get(x, y)) {
pixels[y * widthPix + x] = 0xff000000;
} else {
pixels[y * widthPix + x] = 0xffffffff;
}
}
}
bitmap = Bitmap.createBitmap(widthPix, heightPix, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, widthPix, 0, 0, widthPix, heightPix);
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
/**
* 生成有logo的二维码Bitmap
*
* @param context 二维码内容
* @param widthPix 二维码宽度
* @param heightPix 二维码高度
* @param logo 二维码logo的bitmap
* @return Bitmap
*/
public static Bitmap createHaveLogoQRCode(String context, int widthPix, int heightPix, Bitmap logo) {
Bitmap haveLogoQRCodeBitmap = null;
Bitmap noLogoQRCodeBitmap = createNoLogoQRCode(context, widthPix, heightPix);
haveLogoQRCodeBitmap = addLogo(noLogoQRCodeBitmap, logo);
return haveLogoQRCodeBitmap;
}
/**
* 向原来的bitmap上面添加一个bitmap
*
* @param src 原始Bitmap
* @param logo 添加的Bitmap
* @return Bitmap
*/
private static Bitmap addLogo(Bitmap src, Bitmap logo) {
if (src == null) {
return null;
}
if (logo == null) {
return src;
}
int srcWidth = src.getWidth();
int srcHeight = src.getHeight();
int logoWidth = logo.getWidth();
int logoHeight = logo.getHeight();
if (srcWidth == 0 || srcHeight == 0) {
return null;
}
if (logoWidth == 0 || logoHeight == 0) {
return src;
}
float scaleFactor = srcWidth * 1.0f / 8 / logoWidth;
Bitmap bitmap = Bitmap.createBitmap(srcWidth, srcHeight, Bitmap.Config.ARGB_8888);
try {
Canvas canvas = new Canvas(bitmap);
canvas.drawBitmap(src, 0, 0, null);
canvas.scale(scaleFactor, scaleFactor, srcWidth / 2, srcHeight / 2);
canvas.drawBitmap(logo, (srcWidth - logoWidth) / 2, (srcHeight - logoHeight) / 2, null);
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.restore();
} catch (Exception e) {
bitmap = null;
e.getStackTrace();
}
return bitmap;
}
}
相信有点Android基础的猿们都会使用上面的代码了,就不给使用代码了。
这个Android应用程序还能够像微信一样扫描二维码,就行下面一样:
这个功能是抄的,在网上找的示例代码,一点没改直接用了。。。扫描之后,能够对二维码的内容进行解析,显示在一个界面上。
这个Android应用程序是用Android studio创建的。
来源:oschina
链接:https://my.oschina.net/u/233752/blog/529956