<!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:1; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:0 0 0 0 0 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-1610611985 1073750139 0 0 159 0;} @font-face {font-family:"/@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin-top:0cm; margin-right:0cm; margin-bottom:10.0pt; margin-left:0cm; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:宋体; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:宋体; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} .MsoPapDefault {mso-style-type:export-only; margin-bottom:10.0pt; line-height:115%;} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:35.4pt; mso-footer-margin:35.4pt; mso-paper-source:0;} div.Section1 {page:Section1;} -->
1. 生成的 QR code 的网址是: http://swetake.com/qr/ ;
支持的原因版本还比较丰富,支持 QRcode Perl 的 CGI 和 PHP 脚本的版本, Ruby 和 java 都有对应的支持类库等源代码,用起来还是很方便的;
2 。读取和摄像头读取的是 Open Source QR Code Library ,官方网站为: http://qrcode.sourceforge.jp/ ,读取 QR Code 的所有代码,可以直接读取图片直接进行解析,也可以正常支持中文等,其中有个 jmfexample 就能实现通过摄像头读取 QR Code ;
把对应的 java 的代码,汇总打成了一个 jar 包,用起来也方便多了, jar 包下载方式是: QRCode.jar
生成和读取的代码示例如下:
生成的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | package com.liyz.qrcode.test;
import java.awt.Color; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.File; import javax.imageio.ImageIO; import com.swetake.util.Qrcode;
public class MakeQrcodeImages { /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { Qrcode qrcode=new Qrcode(); qrcode.setQrcodeErrorCorrect('M'); qrcode.setQrcodeEncodeMode('B'); qrcode.setQrcodeVersion(7);
String str="中国人 nice5";
byte[] bstr=str.getBytes("UTF-8"); BufferedImage bi = new BufferedImage(139, 139, BufferedImage.TYPE_INT_RGB); Graphics2D g = bi.createGraphics();
g.setBackground(Color.WHITE); g.clearRect(0, 0, 139, 139); g.setColor(Color.BLACK);
if (bstr.length>0 && bstr.length <123){ boolean[][] b = qrcode.calQrcode(bstr); for (int i=0;i<b.length;i++){ for (int j=0;j<b.length;j++){ if (b[j][i]) { g.fillRect(j*3+2,i*3+2,3,3); } }
} } g.dispose(); bi.flush(); String FilePath="d:/QRCode.png"; File f = new File(FilePath); ImageIO.write(bi, "png", f); System.out.println("now doned!"); }
} |
解码(读取图片)的测试对应代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | package com.liyz.qrcode.test;
import jp.sourceforge.qrcode.QRCodeDecoder; import jp.sourceforge.qrcode.util.ContentConverter; import jp.sourceforge.qrcode.data.QRCodeImage; import jp.sourceforge.qrcode.exception.DecodingFailedException;
import java.awt.image.BufferedImage; import javax.imageio.ImageIO; import java.io.File; import java.io.IOException; import jp.sourceforge.qrcode.util.DebugCanvas; import jp.sourceforge.qrcode.util.DebugCanvasAdapter; import java.net.URL;
// Smallest example of QRCode Decoder
public class QRCodeDecoderCUIExample {
public static void main(String[] args) { args = new String[1]; args[0] = "d:/QRCode.png";
if (args.length < 1) { System.err.println("Usage: QRCodeDecoderCUIExample imageFilePath"); System.exit(1); } int numSuccesses = 0; int numFailures = 0; QRCodeDecoder decoder = new QRCodeDecoder(); long start = System.currentTimeMillis(); for (String filename : args) { if (processDecode(filename, decoder)) { System.err.print("[Success] "); numSuccesses++; } else { System.err.print("[Failure] "); numFailures++; } System.err.println(filename); } long processTime = System.currentTimeMillis() - start; System.err.println("Processed " + args.length + " images in " + processTime + "ms (" + processTime / args.length + " images/sec)"); System.err.println("OK: " + numSuccesses + " NG: " + numFailures); }
/** * 此处解析使用了 utf-8的编码,生成的时候因为用了 utf-8生成了中文,也都正常的读取和生成,感觉还是很不错的 * @param filename * @param decoder * @return */ static boolean processDecode(String filename, QRCodeDecoder decoder) { DebugCanvas canvas = new J2SECanvas(); decoder.setCanvas(canvas); BufferedImage image = null; try { if (filename.startsWith("http://")) image = ImageIO.read(new URL(filename)); else image = ImageIO.read(new File(filename)); String decodedString = new String(decoder.decode(new J2SEImage( image)), "UTF-8"); decodedString = ContentConverter.convert(decodedString); System.out.println(decodedString); } catch (IOException e) { canvas.println("Error: " + e.getMessage() + " " + filename); return false; } catch (DecodingFailedException dfe) { canvas.println("Error: " + dfe.getMessage()); return false; } catch (Exception e) { canvas.println("Error: " + e.getMessage()); return false; } return true; } }
class J2SEImage implements QRCodeImage { BufferedImage image;
public J2SEImage(BufferedImage source) { this.image = source; }
public int getWidth() { return image.getWidth(); }
public int getHeight() { return image.getHeight(); }
public int getPixel(int x, int y) { return image.getRGB(x, y);
} }
class J2SECanvas extends DebugCanvasAdapter { public void println(String s) { // System.err.println(s); } } |
另计:在网上看到可以通过摄像头读取条形码的,因为自己的摄像头换了也没有去测试,估计应该也是没有问题的,把对应的方法贴出来吧:下面为引用,具 体地址不记得了:
二维条形码比普通的条形码能保存更多的信息,已经应用到很多领域里面。例如手机电影票,就是一个嵌在彩信里面的二维码图像。南航也推出了网上办理登机牌业 务,办理完成之后往手机发送一条包含二维码的彩信,到了机场就可以通过自助设备扫描二维码,打印登机牌。
然而,专业的二维码扫描设备价格十分昂贵,最便宜的都在 1000 元以上,到淘宝上搜搜就知道了。借助 Java 和一个开源的库,我们却可以通过普通的网络摄 像头实现相同的效果,成本只需要几十块。
Open Source QR Code Library 是一个开源的 QR Code (二维条形码的一种)生成和读取的库,官方网站为: http://qrcode.sourceforge.jp/ ,里面包含了生成和读取 QR Code 的所有代码,其中有个 jmfexample 就能实现通过摄像头读取 QR Code ,经过本人尝试,几十块的普通摄像头效果已经不错了,一次读取几百字节都没问题。
使用这个库的步骤如下:
1 、到其官方网站下载回来;
2 、到 sun 的网站下载 JMF 包并安装;
3 、插上摄像头,打开我的电脑,查看是否出现 “USB 视频设备 ” ,然后打开,看摄像头工作是否正常
4 、运行 JMF 里面的 JMF Registry 程序,点击 “Detect Capture Devices” ,查找视频设备,查找到之后会在左边的列表里出现 “vfw:Microsoft WDM Image Capture (Win32):0” 类似的设备,点击就会在右边出现其详细信息,我的摄像头是这样的:
Name = vfw:Microsoft WDM Image Capture (Win32):0
Locator = vfw://0
Output Formats—->
0. javax.media.format.YUVFormat
YUV Video Format: Size = java.awt.Dimension[width=640,height=480] MaxDataLength = 614400 DataType = class [B yuvType = 32 StrideY = 1280 StrideUV = 1280 OffsetY = 0 OffsetU = 1 OffsetV = 3
1. javax.media.format.YUVFormat
YUV Video Format: Size = java.awt.Dimension[width=160,height=120] MaxDataLength = 38400 DataType = class [B yuvType = 32 StrideY = 320 StrideUV = 320 OffsetY = 0 OffsetU = 1 OffsetV = 3
2. javax.media.format.YUVFormat
YUV Video Format: Size = java.awt.Dimension[width=176,height=144] MaxDataLength = 50688 DataType = class [B yuvType = 32 StrideY = 352 StrideUV = 352 OffsetY = 0 OffsetU = 1 OffsetV = 3
3. javax.media.format.YUVFormat
YUV Video Format: Size = java.awt.Dimension[width=320,height=240] MaxDataLength = 153600 DataType = class [B yuvType = 32 StrideY = 640 StrideUV = 640 OffsetY = 0 OffsetU = 1 OffsetV = 3
4. javax.media.format.YUVFormat
YUV Video Format: Size = java.awt.Dimension[width=352,height=288] MaxDataLength = 202752 DataType = class [B yuvType = 32 StrideY = 704 StrideUV = 704 OffsetY = 0 OffsetU = 1 OffsetV = 3
注意,其中 Output Formats 都是 javax.media.format.YUVFormat ,而 QR Code Library 里默认的设备不是这种格式的,所以需要对源码作一定的修改。
5 、用 Eclipse 打开 QR Code Library 的源码,作出一些适当的修改:
如果摄像头是上面所说的只支持 YUV 格式,则需要修改 jp.sourceforge.qrcode.example.jmf.camDataSource.java ,把 setMainSource 函数里的
VideoFormat vidformat = new VideoFormat(VideoFormat.RGB);
修改为
VideoFormat vidformat = new VideoFormat(VideoFormat.YUV);
否则永远也找不到摄像头。
6 、把 JMF 包里的 jmf.jar 放到 Classpath 里
7 、执行 jp.sourceforge.qrcode.example.jmf.jmfexample ,搞定
当然,由于源码开放的,只要符合许可,你想怎么改都行,可以把它嵌入到某个应用程序里面,这个程序就具有了扫描 QR Code 的功能了。