已知一張二維碼圖片,怎么生成一張一模一樣的圖片出來?
最近有個項目,需要用到QRCode,之前只做過Datamatrix格式的,想著應該也是差不多的,于是就依葫蘆畫瓢,掏出我的陳年OnBarcode類庫,一通修改,生成了個嶄新的QRCode,與客戶提供的二維碼圖片一比對,雖然掃出來內容一樣,但明顯圖案并不相同,于是我就意識到,事情并不簡單。原圖如下:
首先第一個懷疑的就是參數(shù)問題啦,看了一下OnBarcode.Barcode.QRCode的屬性,可疑的參數(shù)有DataMode、ECL、Version等等,畢竟這幾個應該是常見的參數(shù)。最大的可能就是ECL,這個是二維碼的糾錯級別,一般是L/M/Q/H四個等級,對應可遮擋7%/15%/25%/30%,一般如果想在二維碼中插入logo的話,就要把糾錯級別調高一些。
于是我嘗試了一下,修改了不同的ECL,對應輸出的圖案都是不同的,但還是沒有生成我想要的圖案。
難道是我的陳年OnBarcode類庫跟不上時代了?于是我換成了QRCoder,又是一通折騰,還是沒對上。再是找了一些在線生成二維碼網(wǎng)站(見下方鏈接),逐個比較,發(fā)現(xiàn)還真是五花八門,有些是不提供設置直接生成,有些是可修改版本及ECL的,最后結果都不太一樣,幸好有些網(wǎng)站生成的圖片是對上了的,總算有條退路。
既然有了備用方案,那我就可以慢慢研究了。查了下QRCode的生成原理,參考《【來龍去脈系列】QRCode二維碼的生成細節(jié)和原理》,這一篇講得不錯,不過他在講Mask那里有點模糊,這也導致我一不留神就掉坑了,后面看了另外兩篇才糾正回來。看完大概有了概念,至少明確了,我這個碼應該是version1,Alphanumeric mode 字符編碼,同時也知道還有個掩碼參數(shù)(即Mask),而且從圖案中可以看到Format Information,那里面存放著ECL跟Mask。文中將Format Information標注0-14,在左上角從上往下從右往左,并且說15個bits中包括5個數(shù)據(jù)bits:其中,2個bits用于表示使用什么樣的Error Correction Level, 3個bits表示使用什么樣的Mask,那我自然就認為0-4就是所謂的數(shù)據(jù)bits了,看了下是11100,跟10101異或得出01001,ECL是01-L?但我在線生成的時候是選的H,那就肯定不對。
這時候我發(fā)現(xiàn)有個在線生成網(wǎng)站寫明了用的是ZXing,于是我又引用了ZXing嘗試了一下,按照常規(guī)的參數(shù)配置了ECL-H,還是不行,一度陷入瓶頸。
我還突發(fā)奇想試著把原圖上傳到在線網(wǎng)站去解析,說不定有哪個網(wǎng)站能給出點提示,但最終也只是能看到內容。不過這么一來我又打開了思路,我可以自己解析,說不定就能拿到配置參數(shù)了,感覺可行性還是有的。
剛好ZXing就有解碼的功能,嘗試一下:
1 static void ParseQRCode(string imagePath, out string data, out IDictionary<ResultMetadataType, object> hints) 2 { 3 hints = null; 4 BarcodeReader reader = new BarcodeReader(); 5 reader.Options.PossibleFormats = new List<BarcodeFormat> { BarcodeFormat.QR_CODE };//可加可不加 6 Bitmap bitmap = new Bitmap(imagePath); 7 Result result = reader.Decode(bitmap); 8 if (result != null) 9 { 10 data = result.Text; 11 hints = result.ResultMetadata; 12 } 13 else 14 { 15 data = null; 16 } 17 }
輸入圖片路徑,找了一下result的屬性,果然在ResultMetadata里面存放著我要的信息:
? ECL是H,那就沒錯了,剩下的參數(shù)里面,這個QR_MASK_PATTERN不就是掩碼參數(shù)咯,剩下兩個看了下參數(shù)介紹,應該不是很重要,于是重點關注QR_MASK_PATTERN。剛好手頭的代碼引用的是ZXing,這里要注意的是,ZXing的Hints是不能整個賦值的,只能用Add的方式逐個插入?yún)?shù):
1 public static Bitmap CreateQRCode(string data) 2 { 3 Bitmap bitmap = null; 4 GC.Collect(); 5 BarcodeWriter barCodeWriter = new BarcodeWriter(); 6 barCodeWriter.Format = BarcodeFormat.QR_CODE; // 生成碼的方式(這里設置的是二維碼),有條形碼\二維碼\還有中間嵌入圖片的二維碼等 7 //barCodeWriter.Options.Hints.Add(EncodeHintType.CHARACTER_SET, "UTF-8");// 支持中文字符串 8 barCodeWriter.Options.Hints.Add(EncodeHintType.ERROR_CORRECTION, ZXing.QrCode.Internal.ErrorCorrectionLevel.H); 9 barCodeWriter.Options.Hints.Add(EncodeHintType.QR_MASK_PATTERN, 2); 10 barCodeWriter.Options.Height = 200; 11 barCodeWriter.Options.Width = 200; 12 barCodeWriter.Options.Margin = 0; //設置的白邊大小 13 ZXing.Common.BitMatrix bm = barCodeWriter.Encode(data); 14 bitmap = barCodeWriter.Write(bm); 15 return bitmap; 16 }
果然,結果跟原圖一樣(外面的圈是我自己加的):
問題已經(jīng)解決了,但我還是有個疑惑,為什么我根據(jù)圖案的Format Information得出的參數(shù)是不對的,于是我繼續(xù)翻資料,終于在《[譯] 為程序員寫的Reed-Solomon碼解釋》這一篇里面看到了,是逆時針讀的bit,wxxxx,最開始看的那一篇是順時針標注的啊,那不就是反過來,仔細一看,讀出來是00111,跟10101異或得10010,ECL是10-H,Mask是010-2,對上了。只能說,還是得多方考證吧。
完結撒花。
?
- 參考資料:
《【來龍去脈系列】QRCode二維碼的生成細節(jié)和原理》 https://www.cnblogs.com/tuyile006/p/10916075.html
《二維碼生成原理》 https://zhuanlan.zhihu.com/p/543574464
《[譯] 為程序員寫的Reed-Solomon碼解釋》 https://www.felix021.com/blog/read.php?2116
《C# 生成二維碼方法(QRCoder)》 https://www.cnblogs.com/yakniu/p/16917897.html
《.NET Core(C#)使用ZXing.Net生成條碼(Barcode)和二維碼(QR code)圖片及示例代碼》 https://www.cnblogs.com/fireicesion/p/16809637.html
《C# 利用ZXing.Net來生成條形碼和二維碼》 https://blog.csdn.net/lwf3115841/article/details/128429605
- 在線工具:
OSCHINA https://tool.oschina.net/qr
互聯(lián)二維碼 https://www.hlcode.cn/decode
草料二維碼 https://cli.im/text文章來源:http://www.zghlxwxcb.cn/news/detail-655545.html
二維碼工坊 https://www.2weima.com/?text=A0010101文章來源地址http://www.zghlxwxcb.cn/news/detail-655545.html
到了這里,關于C# QRCode二維碼的解析與生成的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!