二维码是国际标准,由日本某公司发明,并保留版权,免费让全世界使用,目前在中国金融支付领域大放异彩。
条码的联合发明人诺曼·约瑟夫·伍德兰德(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.png")); 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); } } }
运行读取测试程序,将输出相应的内容。
这里顺便提一下,若二维码或者条码在一个含有表格、文字的富文本文档转换的图片中,也是可以被识别出来的,但会略微消耗一点时间。
————————————————
版权声明:本文为CSDN博主「___NULL」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/joyous/article/details/87748303