二維碼:二維碼識別

1. WEB項目實現二維碼識別

1.1. 問題

通常實現二維碼掃描都是app調用手機,或者調用微信的庫便可。可是因爲web項目直接調用app的庫,而調用微信的掃一掃功能必須在微信上使用。所以要在web項目中實現二維碼識別的話,就要本身從新搞一下了。不弄不知道,發現二維碼識別涉及的東西仍是蠻多的。javascript

1.2. 實現思路

WEB項目上面實現二維碼識別思路,前端用h5實現調用手機攝像頭拍照,而後將照片上傳到後端。在後端將二維碼圖片識別,再將相關信息返回處理。html

1.3. 前端

1.3.1. 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>

 

1.3.2. sys.js

上傳圖片須要對圖片進行壓縮,轉化成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 }

 

1.4. 後端解析二維碼

1.4.1. java解析二維碼

使用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

相關文章
相關標籤/搜索