通常實現二維碼掃描都是app調用手機,或者調用微信的庫便可。可是因爲web項目直接調用app的庫,而調用微信的掃一掃功能必須在微信上使用。所以要在web項目中實現二維碼識別的話,就要本身從新搞一下了。不弄不知道,發現二維碼識別涉及的東西仍是蠻多的。javascript
在WEB項目上面實現二維碼識別思路,前端用h5實現調用手機攝像頭拍照,而後將照片上傳到後端。在後端將二維碼圖片識別,再將相關信息返回處理。html
1 <!DOCTYPE html> 2 3 <html> 4 5 <head> 6 7 <meta charset="utf-8"> 8 9 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, 10 11 maximum-scale=1.0, minimum-scale=1.0"> 12 13 <title>二維碼識別</title> 14 15 <style> 16 17 *{ margin: 0; padding: 0;} 18 19 </style> 20 21 </head> 22 23 <body> 24 25 <button id="Sys" type="button" class="layui-btn" style="margin-left: 22px;" > 26 27 <img style="width:26px;" alt="掃一掃" src="/images/erweima.png"> 掃一掃 28 29 </button> 30 31 </div> 32 33 </div> 34 35 <!-- </form> --> 36 37 </div> 38 39 40 41 <input type="file" id='p_image' accept="image/*" capture='camera' style="opacity: 0"/> 42 43 <img id="tempImage" src="" style="display:none;"/> 44 45 46 47 <script src="/jquery/jquery-1.11.3.js"></script> <!-- 你必須先引入jQuery1.8或以上版本 --> 48 49 <script type="text/javascript" src="/js/exif.js"></script> 50 51 <script type="text/javascript" src="/js/sys.js"></script> 52 53 </body> 54 55 </html>
上傳圖片須要對圖片進行壓縮,轉化成base64字符串前端
1 // 掃一掃 2 3 $("#Sys").on('click', function(){ 4 5 $("#p_image").click(); 6 7 }); 8 9 10 11 //處理掃一掃 12 13 $(function () { 14 15 $("#p_image").change(function (e) { 16 17 var file = e.currentTarget.files[0]; 18 19 20 21 //建立一個文件讀取的工具類 22 23 var reader = new FileReader(); 24 25 //這裏利用了閉包的特性,來保留文件名 26 27 (function (x) { 28 29 reader.onload = function (e) { 30 31 //調用壓縮文件的方法,具體實現邏輯見下面 32 33 render(this.result, x); 34 35 } 36 37 })(file.name); 38 39 //告訴文件讀取工具類讀取那個文件 40 41 reader.readAsDataURL(file); 42 43 }); 44 45 46 47 }); 48 49 50 51 //壓縮圖片 52 53 function render(src) { 54 55 // 須要壓縮的最大尺寸 56 57 var MAX_SIZE = 500; 58 59 //建立Image對象 60 61 var image = new Image(); 62 63 //圖片方向角 64 65 var orientation = null; 66 67 image.src = src; 68 69 image.onload = function () { 70 71 var canvas = document.createElement("canvas"); 72 73 //獲取2d畫布 74 75 var ctx = canvas.getContext("2d"); 76 77 canvas.width = image.width; 78 79 canvas.height = image.height; 80 81 ctx.clearRect(0, 0, canvas.width, canvas.height); 82 83 //繪製圖片 84 85 ctx.drawImage(image, 0, 0, image.width, image.height); 86 87 //獲取照片方向角屬性,用戶旋轉控制 88 89 EXIF.getData(image, function() { 90 91 EXIF.getAllTags(this); 92 93 orientation = EXIF.getTag(this,'Orientation'); 94 95 }); 96 97 98 99 //經過固定的寬高比壓縮 100 101 //寬大於高的狀況 102 103 if (image.width > MAX_SIZE && image.width >= image.height) { 104 105 image.height *= MAX_SIZE / image.width; 106 107 image.width = MAX_SIZE; 108 109 } else if (image.height > MAX_SIZE && image.height > image.width) {//寬小於高的狀況 110 111 image.width *= MAX_SIZE / image.height; 112 113 image.height = MAX_SIZE; 114 115 } 116 117 canvas.width = image.width; 118 119 canvas.height = image.height; 120 121 ctx.clearRect(0, 0, canvas.width, canvas.height); 122 123 //繪製圖片 124 125 ctx.drawImage(image, 0, 0, image.width, image.height); 126 127 //生成base64碼 128 129 var base64Code = canvas.toDataURL("image/png"); 130 131 $("#tempImage").attr("src", base64Code); 132 133 }; 134 135 136 137 138 139 var img = document.getElementById('tempImage'); 140 141 img.onload = function(){ 142 143 var canvas = document.createElement("canvas"); 144 145 //獲取2d畫布 146 147 var ctx = canvas.getContext("2d"); 148 149 canvas.width = img.width; 150 151 canvas.height = img.height; 152 153 ctx.clearRect(0, 0, canvas.width, canvas.height); 154 155 //繪製圖片 156 157 ctx.drawImage(img, 0, 0, img.width, img.height); 158 159 //若是方向角不爲1,都須要進行旋轉 added by lzk 160 161 if(orientation != "" && orientation != 1){ 162 163 switch(orientation){ 164 165 case 6://須要順時針(向左)90度旋轉 166 167 rotateImg(img,'left',canvas); 168 169 break; 170 171 case 8://須要逆時針(向右)90度旋轉 172 173 rotateImg(img,'right',canvas); 174 175 break; 176 177 case 3://須要180度旋轉 178 179 rotateImg(img,'right',canvas);//轉兩次 180 181 rotateImg(img,'right',canvas); 182 183 break; 184 185 } 186 187 } 188 189 var base64Code = canvas.toDataURL("image/png"); 190 191 //$("#myImage1").attr("src", base64Code); 192 193 //調用上傳圖片方法 194 195 send(base64Code); 196 197 } 198 199 200 201 } 202 203 //上傳圖片 204 205 function send(baseData){ 206 207 var index = layer.load(1, {time: 15*1000}); //加載提示彈窗,而且設定最長等待15秒 208 209 $.ajax({ 210 211 url: '/scanFile.action', 212 213 type: 'post', 214 215 data: {"baseData":baseData}, 216 217 dataType: 'json', 218 219 success: function (data) { 220 221 if(data.resultcode == "success"){ 222 223 $("#FIRMNAME").val(data["ENTERPRISENAME"]); 224 225 $("#USCCODE").val(data["USCCODE"]); 226 227 layer.close(index); 228 229 } else { 230 231 layer.msg(data["resultcontent"]); 232 233 layer.close(index); 234 235 } 236 237 } 238 239 }); 240 241 } 242 243 //旋轉圖片 244 245 function rotateImg(img, direction,canvas) { 246 247 //最小與最大旋轉方向,圖片旋轉4次後回到原方向 248 249 var min_step = 0; 250 251 var max_step = 3; 252 253 if (img == null)return; 254 255 //img的高度和寬度不能在img元素隱藏後獲取,不然會出錯 256 257 var height = img.height; 258 259 var width = img.width; 260 261 var step = 2; 262 263 if (step == null) { 264 265 step = min_step; 266 267 } 268 269 if (direction == 'right') { 270 271 step++; 272 273 //旋轉到原位置,即超過最大值 274 275 step > max_step && (step = min_step); 276 277 } else { 278 279 step--; 280 281 step < min_step && (step = max_step); 282 283 } 284 285 //旋轉角度以弧度值爲參數 286 287 var degree = step * 90 * Math.PI / 180; 288 289 var ctx = canvas.getContext('2d'); 290 291 switch (step) { 292 293 case 0: 294 295 canvas.width = width; 296 297 canvas.height = height; 298 299 ctx.drawImage(img, 0, 0); 300 301 break; 302 303 case 1: 304 305 canvas.width = height; 306 307 canvas.height = width; 308 309 ctx.rotate(degree); 310 311 ctx.drawImage(img, 0, -height); 312 313 break; 314 315 case 2: 316 317 canvas.width = width; 318 319 canvas.height = height; 320 321 ctx.rotate(degree); 322 323 ctx.drawImage(img, -width, -height); 324 325 break; 326 327 case 3: 328 329 canvas.width = height; 330 331 canvas.height = width; 332 333 ctx.rotate(degree); 334 335 ctx.drawImage(img, -width, 0); 336 337 break; 338 339 } 340 341 }
使用Zxing.jar直接對二維碼圖片進行解析。java
1 import java.awt.image.BufferedImage; 2 3 import java.io.ByteArrayOutputStream; 4 5 import java.io.File; 6 7 import java.io.IOException; 8 9 import java.util.HashMap; 10 11 import java.util.Map; 12 13 14 15 import javax.imageio.ImageIO; 16 17 18 19 import com.google.zxing.BarcodeFormat; 20 21 import com.google.zxing.BinaryBitmap; 22 23 import com.google.zxing.ChecksumException; 24 25 import com.google.zxing.DecodeHintType; 26 27 import com.google.zxing.EncodeHintType; 28 29 import com.google.zxing.FormatException; 30 31 import com.google.zxing.MultiFormatWriter; 32 33 import com.google.zxing.NotFoundException; 34 35 import com.google.zxing.Result; 36 37 import com.google.zxing.WriterException; 38 39 import com.google.zxing.client.j2se.BufferedImageLuminanceSource; 40 41 import com.google.zxing.client.j2se.MatrixToImageWriter; 42 43 import com.google.zxing.common.BitMatrix; 44 45 import com.google.zxing.common.HybridBinarizer; 46 47 import com.google.zxing.qrcode.QRCodeReader; 48 49 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; 50 51 52 53 /** 54 55 * 二維碼工具類 56 57 * @author limingcheng 58 59 * 60 61 */ 62 63 public class QrCodeUtil { 64 65 66 67 /** 68 69 * 生成一個二維碼圖片 70 71 * @param width 72 73 * @param height 74 75 * @param content 76 77 * @return 78 79 * @throws WriterException 80 81 * @throws IOException 82 83 */ 84 85 public static byte[] createQRCode(int width, int height, String content) throws WriterException, IOException { 86 87 // 二維碼基本參數設置 88 89 Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>(); 90 91 hints.put(EncodeHintType.CHARACTER_SET, "utf-8");// 設置編碼字符集utf-8 92 93 hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);// 設置糾錯等級L/M/Q/H,糾錯等級越高越不易識別,當前設置等級爲最高等級H 94 95 hints.put(EncodeHintType.MARGIN, 0);// 可設置範圍爲0-10,但僅四個變化0 1(2) 3(4 5 6) 7(8 9 10) 96 97 // 生成圖片類型爲QRCode 98 99 BarcodeFormat format = BarcodeFormat.QR_CODE; 100 101 // 建立位矩陣對象 102 103 BitMatrix bitMatrix = new MultiFormatWriter().encode(content, format, width, height, hints); 104 105 // 設置位矩陣轉圖片的參數 106 107 // MatrixToImageConfig config = new MatrixToImageConfig(Color.black.getRGB(), Color.white.getRGB()); 108 109 // 位矩陣對象轉流對象 110 111 ByteArrayOutputStream os = new ByteArrayOutputStream(); 112 113 MatrixToImageWriter.writeToStream(bitMatrix, "png", os); 114 115 return os.toByteArray(); 116 117 } 118 119 120 121 /** 122 123 * 解析二維碼 124 125 * @throws FormatException 126 127 * @throws ChecksumException 128 129 * @throws NotFoundException 130 131 * @throws IOException 132 133 */ 134 135 public static void parsingQrCode() throws NotFoundException, ChecksumException, FormatException, IOException { 136 137 QRCodeReader formatReader = new QRCodeReader(); 138 139 BufferedImage image; 140 141 File file = new File("E:\\bestme.png"); 142 143 // 識別圖片中的二維碼內容 144 145 image = ImageIO.read(file); 146 147 // image = ImageUtil.binarization(image); 148 149 BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(image))); 150 151 152 153 //定義二維碼參數 154 155 HashMap hints = new HashMap(); 156 157 // 解碼設置編碼方式爲:utf-8 158 159 hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); 160 161 // 優化精度 162 163 hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE); 164 165 //複雜模式,開啓PURE_BARCODE模式 166 167 // hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE); 168 169 Result result = formatReader.decode(binaryBitmap,hints); 170 171 172 173 System.out.println("解析結果"+result.toString()); 174 175 System.out.println("二維碼類型"+result.getBarcodeFormat()); 176 177 System.out.println("二維碼內容"+result.getText()); 178 179 } 180 181 182 183 public static void main(String[] args) throws WriterException, IOException, NotFoundException, ChecksumException, FormatException { 184 185 parsingQrCode(); 186 187 188 189 // byte[] b = createQRCode(100, 100, "碰見最好的本身!"); 190 191 // OutputStream os = new FileOutputStream("E:\\bestme.png"); 192 193 // os.write(b); 194 195 // os.close(); 196 197 } 198 199 }
輸出結果:jquery
解析結果碰見最好的本身!web
二維碼類型QR_CODEajax
二維碼內容碰見最好的本身!json
注意:使用複雜模式會致使圖片識別不了,具體緣由暫沒清晰。canvas