版权声明:本文为博主原创文章,转载请标明出处,非常感谢! https://blog.csdn.net/joyous/article/details/87748303
二维码是国际标准,由日本某公司发明,并保留版权,免费让全世界使用,目前在中国金融支付领域大放异彩。
条码的联合发明人诺曼·约瑟夫·伍德兰德(Norman Joseph Woodland)于上世纪70年代发明了条形码,这一技术的发明几乎对全球商业活动产生了一场革命,并为消费者在超市的购物节约了大量时间。日前在自己位于新泽西的家中不幸去世,享年91岁。
二维码和条码的生成使用 zxing,zxing 是开源的条码及二维码生成框架,https://github.com/zxing/zxing/ 免费获取,目前版本 ver 3.3.3。
以下是测试生成的代码,内容将保存在 c:\temp\a.png 和 c:\temp\b.png 两个图片文件内。
/*
* 2019-2-20
* 测试 zxing 3.3.3 二维码和条码生成
*/
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Hashtable;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
public class WriteQRCode
{
public static void main(String[] args)
{
int width = 200;
int height = 200;
// 写 二维码
TestWriteRCode("c:/temp/a.png", BarcodeFormat.QR_CODE, "二维码文字信息, Hello world", width, height);
// 写条码
height = 50;
TestWriteRCode("c:/temp/b.png", BarcodeFormat.CODE_128, "ABC123456abc", width, height);
}
/**
* 将字符串信息写入 QRCode
*
* @param fileName
* 指定文件名
* @param strContents
* 写入的内容
* @param width
* 尺寸宽
* @param height
* 尺寸高
*/
public static void TestWriteRCode(String fileName, BarcodeFormat typeCode, String strContents, int width, int height)
{
Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
// 字符集
hints.put(EncodeHintType.CHARACTER_SET, "GBK");// Constant.CHARACTER);
// 容错质量
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
try
{
// 尺寸
BitMatrix bitMatrix = new MultiFormatWriter().encode(strContents, typeCode, width, height, hints);
BufferedOutputStream buffer = null;
buffer = new BufferedOutputStream(new FileOutputStream(fileName));
// ok
MatrixToImageWriter.writeToStream(bitMatrix, "png", new FileOutputStream(new File(fileName)));
buffer.close();
}
catch (WriterException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
生成成功将得到两个 png 文件。
以下是读取 c:\temp\a.png 和 c:\temp\b.png 内的条码及二维码。
/*
* 2019-2-20
* 测试 zxing 3.3.3 二维码和条码读取
*/
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Map;
import javax.imageio.ImageIO;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.ChecksumException;
import com.google.zxing.DecodeHintType;
import com.google.zxing.FormatException;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.NotFoundException;
import com.google.zxing.Reader;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.ImageReader;
import com.google.zxing.common.GlobalHistogramBinarizer;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.multi.GenericMultipleBarcodeReader;
import com.google.zxing.multi.MultipleBarcodeReader;
public class ReadCode
{
private static final Map<DecodeHintType, Object> HINTS;
private static final Map<DecodeHintType, Object> HINTS_PURE;
static
{
HINTS = new EnumMap<>(DecodeHintType.class);
HINTS.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
HINTS.put(DecodeHintType.POSSIBLE_FORMATS, EnumSet.allOf(BarcodeFormat.class));
HINTS_PURE = new EnumMap<>(HINTS);
HINTS_PURE.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
}
public static void main(String[] args)
{
BufferedImage image = null;
try
{
image = ImageIO.read(new File("c:/temp/a.jpg"));
ProcessImage(image);
image = ImageIO.read(new File("c:/temp/b.png"));
ProcessImage(image);
}
catch (IOException e)
{
}
}
private static void ProcessImage(BufferedImage image)
{
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new GlobalHistogramBinarizer(source));
Collection<Result> results = new ArrayList<>(1);
try
{
Reader reader = new MultiFormatReader();
ReaderException savedException = null;
try
{
// Look for multiple barcodes
MultipleBarcodeReader multiReader = new GenericMultipleBarcodeReader(reader);
Result[] theResults = multiReader.decodeMultiple(bitmap, HINTS);
if (theResults != null)
{
results.addAll(Arrays.asList(theResults));
}
}
catch (ReaderException re)
{
savedException = re;
}
if (results.isEmpty())
{
try
{
// Look for pure barcode
Result theResult = reader.decode(bitmap, HINTS_PURE);
if (theResult != null)
{
results.add(theResult);
}
}
catch (ReaderException re)
{
savedException = re;
}
}
if (results.isEmpty())
{
try
{
// Look for normal barcode in photo
Result theResult = reader.decode(bitmap, HINTS);
if (theResult != null)
{
results.add(theResult);
}
}
catch (ReaderException re)
{
savedException = re;
}
}
if (results.isEmpty())
{
try
{
// Try again with other binarizer
BinaryBitmap hybridBitmap = new BinaryBitmap(new HybridBinarizer(source));
Result theResult = reader.decode(hybridBitmap, HINTS);
if (theResult != null)
{
results.add(theResult);
}
}
catch (ReaderException re)
{
savedException = re;
}
}
if (results.isEmpty())
{
try
{
throw savedException == null ? NotFoundException.getNotFoundInstance() : savedException;
}
catch (FormatException | ChecksumException e)
{
// log.info(e.toString());
}
catch (ReaderException e)
{ // Including NotFoundException
// log.info(e.toString());
}
return;
}
for (Result result : results)
{
System.out.println(result.getText());
}
}
catch (RuntimeException re)
{
// Call out unexpected errors in the log clearly
// log.log(Level.WARNING, "Unexpected exception from library", re);
}
}
}
运行读取测试程序,将输出相应的内容。
这里顺便提一下,若二维码或者条码在一个含有表格、文字的富文本文档转换的图片中,也是可以被识别出来的,但会略微消耗一点时间。
Q群讨论:236201801