前面的一些博文中已经提到了zxing这个开源工具生成和读取二维码图片,仅从学习的角度来看,可以告一个段落。在实际的生产环境中,应用zxing生成和读取二维码,却存在一些问题:
- 使用扫描枪读取zxing生成的带中文的二维码图片的时候,存在中文乱码问题;
- 用zxing生成的二维码图片会随着存储信息量的增大,图片也会变大(就这一点来说,使用iText这个工具生成的二维码图片的长宽会相对固定一点,这也是选择iText生成二维码的一个因素)。
为了解决这些问题,在经过一番折腾后,找到了一个替代的解决方案,使用iText工具生成二维码图片,由于iText没有提供类读取二维码内容,这里我们仍然使用zxing,并且特别注意了中文乱码的问题。下面是代码:
package test;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import javax.imageio.ImageIO;
import org.apache.commons.lang.StringUtils;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import com.itextpdf.text.pdf.BarcodePDF417;
/**
* 功能: 1、提供生成二维码的服务 2、提供读取二维码信息的服务 3、提供生成和读取二维码的示例代码
*/
public class TwoDimBarCodeService {
/**
* 功能:生成二维码
* @param strInfo 需要存储的内容
* @param encode 编码格式,比如:GBK,UTF-8
* @param imgFileExt 生成的图片格式
* @return byte[] 图片的byte数组
* @throws Exception
*/
public byte[] generatePdf417Image(String strInfo, String encode,
String imgFileExt) throws Exception {
if (StringUtils.isBlank(strInfo)) {
throw new Exception("二维条码的文本信息参数不能为空!");
}
if (StringUtils.isBlank(encode)) {
encode = "UTF-8";
}
BarcodePDF417 barcodePDF417 = new BarcodePDF417();
barcodePDF417.setText(strInfo.getBytes(encode));
Image pdfImg = barcodePDF417.createAwtImage(Color.black, Color.white);
BufferedImage img = new BufferedImage((int) pdfImg.getWidth(null),
(int) pdfImg.getHeight(null), BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics();
g.drawImage(pdfImg, 0, 0, Color.white, null);
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(img, imgFileExt, os);
byte[] buffs = os.toByteArray();
os.close();
return buffs;
}
/**
* 功能:从图片的byte数组中读取内容
* @param imgBuff 二维码图片流的byte[]
* @param encode 编码格式,比如:GBK,UTF-8
* @return
* @throws Exception
*/
public String readInfoFromPdf417Image(byte[] imgBuff, String encode)
throws Exception {
if (imgBuff == null || imgBuff.length < 1) {
throw new Exception("二维条码的图片内容不能为空!");
}
InputStream is = new ByteArrayInputStream(imgBuff);
BufferedImage image = ImageIO.read(is);
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Result decodedValue = new MultiFormatReader().decode(bitmap);
if (decodedValue == null) {
return "";
}
String resultText = decodedValue.getText();
resultText = StringUtils.trimToEmpty(resultText);
byte[] b = resultText.getBytes("ISO-8859-1");
return new String(b, encode);
}
public static void main(String[] args) throws Exception {
TwoDimBarCodeService service = new TwoDimBarCodeService();
String strInfo = "GB0626-2005^JH-201403050005^XX公司^通知^[2014]0005^^关于推广办公自动化的通知^秘密5^特急^20140305^^^20140305^^";
byte[] buff = service.generatePdf417Image(strInfo, "GBK", "jpg");
OutputStream os = new FileOutputStream(new File("d:/test.jpg"));
os.write(buff);
os.flush();
os.close();
System.err.println("文本内容:"
+ service.readInfoFromPdf417Image(buff, "GBK"));
}
}
关键类:BufferedImage ByteArrayOutputStream
存在的一个问题:
iText生成的图片也会随着信息量的变大而变大,解决思路是使用图像缩放技术,做到图片的格式固定。
来源:oschina
链接:https://my.oschina.net/u/781254/blog/205651