目錄:
前置知識
encode
decode
有任何問題和指導建議,可以聯系我討論:guchenhui1993@gmail.com
前置知識
-
不同碼制:
Data Matrix,MaxiCode, Aztec,QR Code, Vericode,PDF417,Ultracode,Code 49,Code 16K等
-
根據原理分類:
堆疊式/行排式以及矩陣式。本文講的是日常生活最常見的矩陣式QR Code.
-
堆疊式/行排式:
編碼原理建立在一維條碼基礎之上,按需要堆積成二行或多行。代表的碼制有:
Code 16K、Code 49、PDF417、MicroPDF417等.-
矩陣式:
在一個矩形空間通過黑、白像素在矩陣中的不同分布進行編碼。有占位表示1,無占位表示0.代表的碼制有:
Code One、MaxiCode、QR Code、 Data Matrix、Han Xin Code、Grid Matrix等. -
-
尺寸:
二維碼一共有40個尺寸(Version)。Version 1是21 x 21的矩陣,Version 2是 25 x25的矩陣,每增加一個version,就會增加4的尺寸,公式:(V-1)*4+21.
看下圖:
Version 40是這樣的,真是令人害怕,來五個這樣的二維碼即可存下《浮生六記》的閨房記樂:
-
信息容積
- 數字:最多7089字符
- 字母:最多4296字符
- 8位二進制數:最多2953字符
- 日文漢字:最多1817字符
-
格式信息:
- 表示形式是V-E,V是前面提到的version,E是容錯級別,分別是:L(7%),M(15%),Q(25%),R(35%).
-
容錯:
允許存儲的二維碼信息出現重復部分,級別越高,重復信息所占比例越高。
-
結構圖:
- Position Detection Patterns:
三個相同的探測圖形,用于定位視圖和方向,位于左上角、右上角、左下角.符號中遇到類似圖形的可能性極小,可以在有效識別到二維碼。
Separators:
每個探測圖形和編碼區域之間有一條1單位寬度的分隔符.由白色塊組成.Timing Pattern:
黑白色相間交替組成的一行一列兩條位于橫縱的兩兩探測圖形之間,用于確定符號的密度和版本,提供決定模塊坐標的基準位置.Alignment Patterns:
類似小號的探測圖形,中心矩形邊框變為1單位,這種校正圖形的數量由version來定,大于version 1的都有該校正圖形.Encoding region:
包含數據碼字,糾錯碼字,版本信息,格式信息,符號字符等數據。Quiet zone:
環繞整個二維碼四周的4單位寬的區域.白色.
encode
數據分析-->數據編碼-->糾錯編碼-->構造最終數據-->構造矩陣-->打上掩碼-->填充格式與版本信息
-
數據分析:
分析輸入的數據流,確定編碼的字符類型,按相應的字符集轉換成符號字符;選擇糾錯等級;如果沒有指定version,會采用能表示目標信息的最小version.
字符類型的編號(中文是1101,終止符是0000):
各尺寸的數據組成細節:
-
數據編碼
將數據字符轉換為位流,每8位一個碼字,整體構成一個數據的碼字序列.必要的時候需加入填充字符以填滿按照版本要求的數據碼字數.
先看看不同version下數據長度對應的編碼的位數約定:
支持如下編碼:
-
Numeric mode|數字編碼:
數據類型編碼(4位)+數據長度編碼(根據version轉成10或12或14位二進制數)+從左到右,
每3個數字為一組,轉成10位二進制數,剩下不滿三位的轉成4或7位二進制數。比如1314520:
- 131 452 0
- --> 131(0010000011) 452(0111000100) 0(0000)
- --> 數字長度7 -->0000000111
- --> 由上面數據分析的圖,數字的編碼是0001
- --> 0001 0000000111 0010000011 0111000100 0000 0000(結束符)
公式B=4+C+10(D DIV 3)+R.
-
Alphanumeriv mode|字符編碼:09,AZ,以及一些符號和空格。
編碼方式和數字編碼類似,區別是以2個字符為一組,轉成11位二進制數,不滿2個字符的轉成6位。(a,b)-->a*45+b-->binary
公式B = 4 + C + 11(D DIV 2) + 6(D MOD 2).
-
Byte mode|字節編碼:
公式B = 4 + C + 8D.
-
Mixing mode|混合編碼
各種類型的組合編碼。
- Kanji mode|日文編碼(不具體展開)
- ECI mode|特殊字符集(不具體展開)
- Structured Append mode|附加結構編碼(不具體展開)
- FNC1 mode|特殊工業或行業使用(不具體展開)
-
8bit重排:接下來會對二進制比特流按照8位重排,編碼總位數如果不是8的倍數,需要在末尾補0.
補齊碼:每個字碼是8位,重排補0以后,如果字碼的長度沒有到達該version的容量,需要在后面加上補齊碼。
具體姿勢是不斷重復11101100和00010001這兩個碼字。
-
糾錯編碼
為了能被糾錯算法處理,將解析出的碼字序列分塊。然后把糾錯碼字拼到數據碼字后面。有上文提到的L,M,Q,H四種糾錯級別.
-
糾錯算法:
可糾正兩種類型的錯誤,拒讀錯誤(錯誤碼字的位置已知)和替代錯誤(錯誤碼字的位置未知).拒讀錯誤是沒有掃描到或者無法譯碼的字符,替代錯誤是錯誤譯碼的字符。一個替代錯誤需要兩個糾錯碼字來糾正。
這里有個公式:e + 2t <= d - p
e:拒讀錯誤數 t:替代錯誤數 d:糾錯碼字數 p:錯誤譯碼保護碼字
主要通過里德-所羅門糾錯算法 來實現。
涉及到伽羅瓦域中的多項式算法等數學理論。這邊還需要深入學習。寫個//TODO_NEXT_TIME官方的除法電路圖示是這樣的:
-
-
構造最終數據信息
將數據碼字的塊和糾錯碼字的塊以行列交織的方式排列。
經過上一步計算出糾錯碼以后得到類似這樣的結果:
左邊是數據碼字,右邊是糾錯碼字。然后按列排列成:
D1, D12, D23, D35, D2, D13, D24, D36, ... D11, D22, D33, D45, D34, D46, E1, E23, E45, E67, E2, E24, E46, E68, ... E22, E44, E66, E88.
-
構造矩陣
將碼字模塊以及探測圖形、分隔符、定位圖形、校正圖形填充到矩陣相應位置中。具體位置如圖:
以及校驗圖形的位置:
QR Code中,符號字符以2個單位寬的縱列從符號的右下角開始布置,并且自右向左,自底向上。每個碼字最高位應放在第一個可用的位置,中途遇到障礙就跳過,在障礙物上面或者下面繼續填充。
-
打上掩碼
為了可靠性,使用掩碼圖形讓矩陣中的黑白色塊比例接近1:1并均勻分布,盡可能避免探測圖形出現在別的區域.所以每個二維碼咋一看,都是一模一樣。
有幾點需要說明
- 不會影響功能區(Function Patterns)
- 對編碼區域(Encoding Region)進行XOR運算(按照掩碼的黑色部分顏色取反)
- 對結果圖不符合人意的部分計分
- 評估后選擇最佳的掩碼(分數最低的那個)
關于掩碼方案優劣的評分標準(N1=3, N2=3, N3=40, N4=10):
掩碼標識碼:
八種掩碼:
大致步驟如下:
-
填充格式與版本信息
-
生成格式和版本信息填入矩陣相應的區域上。
- 格式信息:格式信息15位,5個數據位10個糾錯位。數據位中前兩位是糾錯等級:
第三到第五位是掩碼標識。然后根據糾錯算法算出10位糾錯碼,加載五位數據位后面。
- 版本信息:版本信息18位,6位數據位12位糾錯位。version 7~40時才有版本信息,沒有任何版本信息的結果全是0,不用對版本信息做掩碼。
-
decode
encode的逆向流程:
- 定位并獲取圖形,根據黑白色塊轉成0,1組成的數組,確定一個閾值,用該值將圖像轉化為一系列深色和淺色像素
- 識別格式信息
- 識別version信息
- 去掉掩碼,即從格式信息中得到編碼區的擺位圖進行異或處理消除掩碼
- 恢復數據碼字和糾錯碼字
- 使用糾錯碼字進行錯誤檢查,并糾錯
- 解碼數據碼字