QR碼的使用越來越多,,可以在很多地方見著,,比如火車票,、推廣產(chǎn)品上等,,以下將介紹如何用Java生成QR碼以及解碼QR碼,。 1,、涉及開源項目: ZXing :一個開源Java類庫用于解析多種格式的1D/2D條形碼,。目標(biāo)是能夠?qū)R編碼,、Data Matrix,、UPC的1D條形碼進行解碼。 其提供了多種平臺下的客戶端包括:J2ME,、J2SE和Android,。---用來解碼QRcode d-project:Kazuhiko Arase的個人項目(他具體是誰不清楚,日本的),,提供豐富的配置參數(shù),,非常靈活---用來生成QR code 2、效果圖:
3,、使用d-project生成QRcdoe 1)將com.d_project.qrcode.jar引入工程 2)QRcodeAction代碼:
public void generate(RequestContext rc) throws UnsupportedEncodingException, IOException, ServletException { //待轉(zhuǎn)數(shù)據(jù) String data = rc.param("data", "http:///qr"); //輸出圖片類型 String output = rc.param("output", "image/jpeg"); int type = rc.param("type", 4); if (type < 0 || 10 < type) { return; } int margin = rc.param("margin", 10); if (margin < 0 || 32 < margin) { return; } int cellSize = rc.param("size", 4); if (cellSize < 1 || 4 < cellSize) { return; } int errorCorrectLevel = 0; try { errorCorrectLevel = parseErrorCorrectLevel(rc, rc.param("error", "H")); } catch (Exception e) { return; } com.d_project.qrcode.QRCode qrcode = null; try { qrcode = getQRCode(data, type, errorCorrectLevel); } catch (Exception e) { return; } if ("image/jpeg".equals(output)) { BufferedImage image = qrcode.createImage(cellSize, margin); rc.response().setContentType("image/jpeg"); OutputStream out = new BufferedOutputStream(rc.response() .getOutputStream()); try { ImageIO.write(image, "jpeg", out); } finally { out.close(); } } else if ("image/png".equals(output)) { BufferedImage image = qrcode.createImage(cellSize, margin); rc.response().setContentType("image/png"); OutputStream out = new BufferedOutputStream(rc.response() .getOutputStream()); try { ImageIO.write(image, "png", out); } finally { out.close(); } } else if ("image/gif".equals(output)) { GIFImage image = createGIFImage(qrcode, cellSize, margin); rc.response().setContentType("image/gif"); OutputStream out = new BufferedOutputStream(rc.response() .getOutputStream()); try { image.write(out); } finally { out.close(); } } else { return; } } private static int parseErrorCorrectLevel(RequestContext rc, String ecl) { if ("L".equals(ecl)) { return ErrorCorrectLevel.L; } else if ("Q".equals(ecl)) { return ErrorCorrectLevel.Q; } else if ("M".equals(ecl)) { return ErrorCorrectLevel.M; } else if ("H".equals(ecl)) { return ErrorCorrectLevel.H; } else { throw rc.error("qr_error_correct_error"); } } private static QRCode getQRCode(String text, int typeNumber, int errorCorrectLevel) throws IllegalArgumentException { if (typeNumber == 0) { return QRCode.getMinimumQRCode(text, errorCorrectLevel); } else { QRCode qr = new QRCode(); qr.setTypeNumber(typeNumber); qr.setErrorCorrectLevel(errorCorrectLevel); qr.addData(text); qr.make(); return qr; } } private static GIFImage createGIFImage(QRCode qrcode, int cellSize, int margin) throws IOException { int imageSize = qrcode.getModuleCount() * cellSize + margin * 2; GIFImage image = new GIFImage(imageSize, imageSize); for (int y = 0; y < imageSize; y++) { for (int x = 0; x < imageSize; x++) { if (margin <= x && x < imageSize - margin && margin <= y && y < imageSize - margin) { int col = (x - margin) / cellSize; int row = (y - margin) / cellSize; if (qrcode.isDark(row, col)) { image.setPixel(x, y, 0); } else { image.setPixel(x, y, 1); } } else { image.setPixel(x, y, 1); } } } return image; }
3)前端頁面:
<script type="text/javascript" src="/js/jquery/jquery.form-2.82.js"></script> <script type="text/javascript"> $(document).ready(function(){ $("#submit").click(function(){ var url = "/action/qrcode/generate?" + $("#qrcode_form").serialize(); $(".QRCodeDiv img").attr("src",url+"&"+new Date().getTime()); $("#gen_url").attr("href",url); }); $("#zxing").popover({ 'title':'條形碼處理類庫 ZXing', 'content':'ZXing是一個開源Java類庫用于解析多種格式的1D/2D條形碼,。目標(biāo)是能夠?qū)R編碼,、Data Matrix、UPC的1D條形碼進行解碼,。 其提供了多種平臺下的客戶端包括:J2ME,、J2SE和Android。', 'placement':'bottom' }); }); </script> <div id="mainContent" class="wrapper"> <div class="toolName">在線生成二維碼(QR碼)-采用<a id="zxing" >ZXing</a>與<a href="http://www./">d-project</a><a data-toggle="modal" href="#advice" style="float:right;text-decoration:none;"><span class="badge badge-important"><i class="icon-envelope icon-white"></i> Feedback</span></a></div> <div class="toolUsing clearfix"> <div class="toolsTab clearfix"> <ul class="nav nav-tabs"> <li class="active"><a href="/qr">轉(zhuǎn)QR碼</a></li> <li ><a href="/qr?type=2">二維碼解碼</a></li> </ul> <div class="clear"></div> </div> <form id="qrcode_form" method="post" > <div class="leftBar"> <div class="title">URL或其他文本:</div> <textarea class="input-xlarge" name="data" onfocus="if(this.value=='http:///qr'){this.value='';};this.select();" onblur="(this.value=='')?this.value='http:///qr':this.value;">http:///qr</textarea> </div> <div class="operateLR"> <div class="OptDetail span1"> <label>輸出格式:</label> <select name="output" class="span1"> <option value="image/gif" selected>GIF</option> <option value="image/jpeg">JPEG</option> <option value="image/png">PNG</option> </select> <label>糾錯級別:</label> <select name="error" class="span1"> <option value="L" selected>L 7%</option> <option value="M">M 15%</option> <option value="Q">Q 25%</option> <option value="H">H 30%</option> </select> <label>類型:</label> <select name="type" class="span1"> <option value="0">自動</option> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> <option value="6">6</option> <option value="7">7</option> <option value="8">8</option> <option value="9">9</option> <option value="10">10</option> </select> <label>邊緣留白:</label> <select name="margin" class="span1"> <option value="0">0</option> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> <option value="6">6</option> <option value="7">7</option> <option value="8">8</option> <option value="9">9</option> <option value="10">10</option> <option value="11">11</option> <option value="12">12</option> <option value="13">13</option> <option value="14">14</option> <option value="15">15</option> <option value="16">16</option> <option value="17">17</option> <option value="18">18</option> <option value="19">19</option> <option value="20">20</option> <option value="21">21</option> <option value="22">22</option> <option value="23">23</option> <option value="24">24</option> <option value="25">25</option> <option value="26">26</option> <option value="27">27</option> <option value="28">28</option> <option value="29">29</option> <option value="30">30</option> <option value="31">31</option> <option value="32">32</option> </select> <label>原胞大小:</label> <select name="size" class="span1"> <option value="1" >1</option> <option value="2" >2</option> <option value="3" >3</option> <option value="4" selected >4</option> </select> <button class="btn btn-small btn-primary" id="submit" onclick="return false;">生成QR碼</button> </div> </div> <div class="rightBar"> <div class="title">QR碼:</div> <div class="QRCodeDiv"> <div class="QRWrapper"> <a id="gen_url" href="/action/qrcode/generate?size=4" target="_blank"><img src="/action/qrcode/generate?size=4"/></a> </div> </div> </div> </form> </div> </div>
4,、使用ZXing解碼QRcode 1)下載Zxing-2.0.zip 2)引入zxing-barcode_core.jar與zxing_barcode_j2se.jar到工程 3)QRcodeAction代碼:
@PostMethod @JSONOutputEnabled public void decode(RequestContext rc) throws IOException { //存在qrcode的網(wǎng)址 String url = rc.param("url", ""); //待解碼的qrcdoe圖像 File img = rc.file("qrcode"); if (StringUtils.isBlank(url) && img == null) { throw rc.error("qr_upload_or_url_null"); } List<Result> results = new ArrayList<Result>(); Config config = new Config(); Inputs inputs = new Inputs(); config.setHints(buildHints(config)); if (StringUtils.isNotBlank(url)) { addArgumentToInputs(url, config, inputs); } if (img != null) { inputs.addInput(img.getCanonicalPath()); } while (true) { String input = inputs.getNextInput(); if (input == null) { break; } File inputFile = new File(input); if (inputFile.exists()) { try { Result result = decode(inputFile.toURI(), config,rc); results.add(result); } catch (IOException e) { } } else { try { Result result = decode(new URI(input), config,rc); results.add(result); } catch (Exception e) { } } } rc.print(new Gson().toJson(results)); } private Result decode(URI uri,Config config,RequestContext rc) throws IOException { Map<DecodeHintType, ?> hints = config.getHints(); BufferedImage image; try { image = ImageIO.read(uri.toURL()); } catch (IllegalArgumentException iae) { throw rc.error("qr_resource_not_found"); } if (image == null) { throw rc.error("qr_could_not_load_image"); } try { LuminanceSource source = new BufferedImageLuminanceSource(image); BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); Result result = new MultiFormatReader().decode(bitmap, hints); return result; } catch (NotFoundException nfe) { throw rc.error("qr_no_barcode_found"); } } private static Map<DecodeHintType, ?> buildHints(Config config) { Map<DecodeHintType, Object> hints = new EnumMap<DecodeHintType, Object>( DecodeHintType.class); Collection<BarcodeFormat> vector = new ArrayList<BarcodeFormat>(8); vector.add(BarcodeFormat.UPC_A); vector.add(BarcodeFormat.UPC_E); vector.add(BarcodeFormat.EAN_13); vector.add(BarcodeFormat.EAN_8); vector.add(BarcodeFormat.RSS_14); vector.add(BarcodeFormat.RSS_EXPANDED); if (!config.isProductsOnly()) { vector.add(BarcodeFormat.CODE_39); vector.add(BarcodeFormat.CODE_93); vector.add(BarcodeFormat.CODE_128); vector.add(BarcodeFormat.ITF); vector.add(BarcodeFormat.QR_CODE); vector.add(BarcodeFormat.DATA_MATRIX); vector.add(BarcodeFormat.AZTEC); vector.add(BarcodeFormat.PDF_417); vector.add(BarcodeFormat.CODABAR); vector.add(BarcodeFormat.MAXICODE); } hints.put(DecodeHintType.POSSIBLE_FORMATS, vector); if (config.isTryHarder()) { hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE); } if (config.isPureBarcode()) { hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE); } return hints; } private static void addArgumentToInputs(String argument, Config config, Inputs inputs) throws IOException { File inputFile = new File(argument); if (inputFile.exists()) { inputs.addInput(inputFile.getCanonicalPath()); } else { inputs.addInput(argument); } }
4)前端頁面:
<script type="text/javascript" src="/js/jquery/jquery.form-2.82.js"></script> <script type="text/javascript"> $(document).ready(function(){ $("#qrcode_form").ajaxForm({ success:function(json){ if(json==null) return; json = eval("("+json+")"); if(json.msg){ alert(json.msg); return; } if(json[0]) $("#result").val(json[0].text); else $("#result").val("解碼失敗"); } }); $("#zxing").popover({ 'title':'條形碼處理類庫 ZXing', 'content':'ZXing是一個開源Java類庫用于解析多種格式的1D/2D條形碼,。目標(biāo)是能夠?qū)R編碼、Data Matrix,、UPC的1D條形碼進行解碼,。 其提供了多種平臺下的客戶端包括:J2ME、J2SE和Android,。', 'placement':'bottom' }); }); </script> <div id="mainContent" class="wrapper"> <div class="toolName">在線生成二維碼(QR碼)-采用<a id="zxing" >ZXing</a>與<a href="http://www./">d-project</a><a data-toggle="modal" href="#advice" style="float:right;text-decoration:none;"><span class="badge badge-important"><i class="icon-envelope icon-white"></i> Feedback</span></a></div> <div class="toolUsing clearfix"> <div class="toolsTab clearfix"> <ul class="nav nav-tabs"> <li ><a href="/qr">轉(zhuǎn)QR碼</a></li> <li class="active"><a href="/qr?type=2">二維碼解碼</a></li> </ul> <div class="clear"></div> </div> <form id="qrcode_form" method="post" action="/action/qrcode/decode"> <div class="topBar"> <div class="title"> <label class="radio" for="upload_url">圖片URL: <input checked="checked" name="upload_ctn" id="upload_url" style="margin-right:5px;" type="radio" onchange="if(this.checked){$('input[name=\'url\']').removeAttr('disabled');$('input[name=\'qrcode\']').attr('disabled','disabled')}"/> </label> </div> <input name="url" id="url" style="width:100%;height:40px;margin:0 0 10px 0;" onfocus="if(this.value=='http://www./img/qr.gif'){this.value='';};this.select();" onblur="(this.value=='')?this.value='http://www./img/qr.gif':this.value;" value="http://www./img/qr.gif"/> <div class="title"> <label class="radio" for="upload_img">上傳圖片: <input style="margin-right:5px;" name="upload_ctn" id="upload_img" type="radio" onchange="if(this.checked){$('input[name=\'qrcode\']').removeAttr('disabled');$('input[name=\'url\']').attr('disabled','disabled')}"/> </label> </div> <input disabled="disabled" name="qrcode" type="file" class="input-file"/> <input class="btn btn-primary" value="解碼" type="submit"/> </div> <div class="bottomBar"> <div class="title">解碼結(jié)果:</div> <textarea id="result"></textarea> </div> </form> </div> </div>
注意:其中牽涉到的RequestContext類,請點擊查看 |
|