首先說壹下二維碼壹共40個維度。官方名稱是版本。版本1是21 x 21的矩陣,版本2是25 x 25的矩陣,版本3是29的大小。每增加壹個版本,4的大小就會增加。公式為:(V-1)*4+21(V為版本號)最高。(40-1)* 4+21 = 177,所以最高的平方是177 x 177。
讓我們看壹個二維碼的例子:
定位模式
位置檢測圖案是壹種定位圖案,用於標記二維碼的矩形尺寸。這三種定位模式有白邊,稱為後檢測模式的分隔符。之所以說三而不是四,是指三可以識別壹個長方形。
定時模式也用於定位。原因是二維碼有40種大小。如果尺寸過大,需要有壹條標準線,否則掃描時可能會歪。
對準圖案只有2版以上(含2版)的二維碼需要這個東西,也是用來定位的。
功能數據
格式信息以各種大小存在,用於存儲壹些格式化的數據。
>以上=版本7中的版本信息,需要預留兩個3 x 6的區域來存儲壹些版本信息。
數據碼和糾錯碼
除上述位置外,其余位置存儲數據碼和糾錯碼。
數據編碼
先說數據編碼。二維碼支持以下編碼:
數字模式數字編碼,從0到9。如果要編碼的位數不是3的倍數,那麽最後剩余的1或2位將被轉換成4或7位,另外3位將被編碼成10、12、14位,編碼的長度取決於二維碼的大小(下面的表3說明了這壹點)。
字母數字模式字符編碼。包括0-9,大寫A到Z(無小寫),以及符號$ % *+–。/:包括空格。這些字符被映射到字符索引表中。如下圖:(其中SP為空格,Char為字符,Value為其索引值)編碼過程是將字符成對分組,然後轉換成下表中的45位制,再轉換成11位的二進制,如果最後只有壹個,則轉換成6位的二進制。編碼方式和字符數需要根據不同的版本大小編碼成9,11或13二進制(下表表3)。
字節模式,字節碼,可以是0-255 ISO-8859-1個字符。壹些二維碼掃描儀可以自動檢測是否是UTF-8編碼。
漢字模式,這是日語碼和雙字節碼。同樣,也可以用於中文編碼。日文和中文字符的編碼將減去壹個值。比如8140減去0X8140到0x 9 FCC的字符,0XC140減去0XE040到0XEBBF的字符。然後取出結果的前兩位16位乘以0XC0,再加上後兩位16位,最後。下面是壹個例子:
擴展通道解釋(ECI)模式主要用於特殊字符集。並非所有掃描儀都支持這種編碼。
結構化追加模式用於混合編碼,即這個二維碼包含多種編碼格式。
FNC1模式主要用於壹些特殊的行業或行業。比如GS1條碼等等。
為簡單起見,本文將不討論後三者。
在下面的兩個表中,
表2是每個編碼格式的“數”,這個東西要寫在格式信息裏。註:中文是1101。
表3顯示了不同版本(大小)的二維碼,用於數字、字符、字節和漢字模式,用於單壹編碼的二進制數字。(在二維碼的規範中,有各種編碼規範表,後面會提到)
我們來看幾個例子。
示例1:數字編碼
在版本1的大小下,糾錯級別為H,代碼為01234567。
1.把上面的數字分成三組:012 345 67。
2.把它們轉換成二進制:012轉換成000001100;345轉換成0101011001;67轉1000011。
3.把這三個二進制串起來:00000010001011001 1 10001。
4.將位數轉換成二進制(版本1-H為10位):八位數的二進制為000001000。
5.將數字代碼符號0001和步驟4中的代碼加到前面:000100000100000100010001065438+。
示例2:字符編碼
在版本1的大小下,糾錯級別為H,代碼為AC-42。
1.從字符索引表中找出五個音符AC-42的索引(10,12,41,4,2)。
2.成對分組:(10,12) (41,4) (2)
3.將每個組轉換為11位的二進制數:
(10,12)10 * 45+110011165438(465438 4)41 * 45+4等於1849到
4.連接這些二進制:00110011111110065438。
5.將字符數轉換為二進制(版本1-H為9位):5個字符,5轉換為00000101。
6.添加代碼標記0010和第五步的數字代碼:001000000101110010065438+。
終止符和補碼
如果我們有壹個HELLO WORLD字符串要編碼,根據上面的第二個例子,我們可以得到下面的編碼。
編碼
字符數
妳好世界編碼
0010 000001011 01100001011 01111000110 1000106543 8+01100 10110111000 10011010100 001101
我們必須加上終結者:
編碼
字符數
妳好世界編碼
結束
0010 000001011 01100001011 01111000110 1000106543 8+01100 10110111000 10011010100 001101 0000
按8位重新排列
如果所有的碼加起來不是8的倍數,我們需要在後面加足夠多的零,比如上面有78位,那麽我們需要加2個零,然後按照8位分組:
00100000 01011011 00001011 01111000 11010001 0654 38+0110010 11011100 01001101 01000011 01000000
填充字節
最後,如果我們還沒有達到最大位數,我們需要添加壹些填充字節。填充字節就是重復下面兩個字節:1101000010001(這兩個二進制是236和17,不知道為什麽,各版本各糾錯級別的最大比特數限制見QR Code Spec第28頁到32頁的表-7。
假設我們需要對版本1的Q糾錯級別進行編碼,那麽它的最大需要量是104比特,而我們在它上面只有80比特,所以我們需要補充24比特,也就是需要3個填充字節,所以我們加3,我們得到如下編碼:
00100000 01011011 00001011 01111000 11010001 0654 38+0110010 11011100 01001101 01000011 01000000 16 5438+0101100 00010001 11101100
上述代碼是數據代碼,稱為數據碼字,每8位稱為壹個碼字。我們還需要向這些數據代碼添加糾錯信息。
糾錯碼
上面我們講了壹些糾錯級別,糾錯碼級別。二維碼有四級糾錯,這也是為什麽二維碼不完整也可以掃描,這也是為什麽有人在二維碼中央加圖標。
糾錯能力
L級中7%的字碼可以改正。
m級15%字代碼可以糾正。
25%的Q級代碼可以被糾正。
H級30%的代碼可以糾正。
那麽,QR是如何給數據碼添加糾錯碼的呢?首先我們需要對數據碼進行分組,即分成不同的塊,然後對每個塊進行糾錯編碼。關於如何分組,我們可以查看《二維碼規範》第33至44頁的表-13至表-22的定義表。請註意最後兩列:
錯誤代碼糾正塊的數量:需要劃分多少塊。
每塊糾錯碼:每個塊中的碼數,所謂碼數,即8位是多少字節。
例如,上述版本5+Q糾錯階段需要四個塊(兩個塊為壹組,共兩組),第壹組中兩個塊的糾錯碼分別為15比特+9比特(註:表中碼字為壹個8比特字節)(註:(c,k,r)上例中。
下圖舉了壹個5-Q的例子(因為二進制寫會讓表太大,所以我用十進制,我們可以看到每個塊有18個碼字,也就是18個8比特的二進制數)。
組
塊
數據
每個塊的糾錯碼
1 1 67 85 70 134 87 38 85 194 119 50 6 18 6 103 38 213 199 11 45 11 5 247 241 223 229 248 154 117 154 111 86 161 111 39
2 246 246 66 7 118 134 242 7 38 86 22 198 199 146 6 87 204 96 60 202 182 124 157 200 134 27 129 209 17 163 163 120 133
2 1 182 230 247 119 50 7 118 134 87 38 82 6 134 151 50 7 148 116 17 7 212 76 133 75 242 238 76 195 230 189 10 108 240 192 141
2 70 247 118 86 194 6 151 50 16 236 17 236 17 236 17 236 235 159 5 173 24 147 5 9 33 106 40 255 172 82 2 131 32 178 236
註:二維碼的糾錯碼主要是通過裏德-所羅門糾錯(Reed-Solomon糾錯算法)來實現的。對我來說,這個算法相當復雜,有很多數學計算,比如多項式除法,把1-255這個數映射到2的n次方(0
最終編碼
交替放置
如果妳認為我們可以開始畫畫,那妳就錯了。二維碼的混沌技術還沒有完成,還需要把數據碼和糾錯碼的碼字交替放在壹起。如何交替,規則如下:
對於數據碼:取出每個塊的第壹個碼字並按順序排列,然後取第壹個塊的第二個,以此類推。例如,上述示例中的數據碼字如下:
block 1 67 85 70 134 87 38 85 194 119 50 6 18 6 103 38
block 2 246 246 66 7 18 134 242 7 38 86 22 198 199 65438 6
block 3 182 230 247 119 50 7 1134 87 38 82 6 134 151 507。
block 4 70 247 118 86 194 6 15150 16 236 17 236 17 236。
先說第壹列:6724618270。
然後取第二列:67,246,182,70,85,246,230,247。
以此類推:67,246,182,70,85,246,230,247……67,246,182,70,85,246,230,247
糾錯碼也是如此:
block 1 213 199 11 45 15 247 241 223 229 248 154 117 6558。
block 2 87 204 96 60 202 182 124 157 200 134 27 129 209 17 163 120 65438。
block 3 148 116177 21276 133 75 242 238 76 195 230 189 108 240。
block 4 235 159 5 173 24 147 59 33 106 40 255 172 82 136 5438+032 178 236。
與數據代碼相同,我們得到:213,87,148,235,199,204,116,159,……
然後,將這兩組放在壹起(糾錯碼在數據碼之後)得到:
67, 246, 182, 70, 85, 246, 230, 247, 70, 66, 247, 118, 134, 7, 119, 86, 87, 118, 50, 194, 38, 134, 7, 6, 85, 242, 118, 151, 194, 7, 134, 50, 119, 38, 87, 16, 50, 86, 38, 236, 6, 22, 82, 17, 18, 198, 6, 236, 6, 199, 134, 17, 103, 146, 151, 236, 38, 6, 50, 17, 7, 236, 213, 87, 148, 235, 199, 204, 116, 159, 11, 96, 177, 5, 45, 60, 212, 173, 115, 202, 76, 24, 247, 182, 133, 147, 241, 124, 75, 59, 223, 157, 242, 33, 229, 200, 238, 106, 248, 134, 76, 40, 154, 27, 195, 255, 117, 129, 230, 172, 154, 209, 189, 82, 111, 17, 10, 2, 86, 163, 108, 131, 161, 163, 240, 32, 111, 120, 192, 178, 39, 133, 141, 236
這是我們的數據區。
剩余位
最後,添加提醒位。對於部分版本的QR,上面不夠長,需要添加Remainer位,比如上面5Q版本的QR碼,加7位,Remainer位加零。請參考QR碼規範第15頁上表-1的定義表,了解哪個版本需要多少剩余位的詳細信息。
畫壹個二維碼圖
位置檢測模式
首先,在三個角上畫出位置檢測圖案。(不管是哪個版本,這個圖案的尺寸都這麽大。)
對齊模式
然後,畫對齊圖案(先不說版本,這個圖案的尺寸好大)
對齊的位置請參考二維碼規範第81頁表-E.1的定義表(下表為不完整表格)。
下圖是上表中版本8的示例(6,24,42)。
定時模式
接下來是時序模式線(不用說了)
格式信息
然後就是陣型信息,下圖藍色部分。
格式信息是壹條15位的信息,每壹位的位置如下圖所示:(註意圖中的深色模塊,會壹直出現)。
這15位包括:
5個數據位:2位用於指示使用哪種糾錯級別,3位用於指示使用哪種掩碼。
10個糾錯位。主要由BCH電碼計算。
那麽15位將與10101000010010進行異或運算。這樣就保證了我們不會因為選擇00的糾錯級別和000的掩碼而全白,增加我們掃描儀的圖像識別難度。
這裏有壹個例子:
下表顯示了糾錯級別:
屏蔽模式如下表23所示。
版本信息
然後是版本信息(7版以後需要這個編碼),下圖藍色部分。
版本信息共有18位,包括6位版本號和12位糾錯碼。下面是壹個例子:
其填充位置如下:
數據和數據糾錯碼
然後填寫我們的最終代碼。最終代碼的填寫方法如下:從左下角開始沿著紅線填寫我們的位,1為黑色,0為白色。如果遇到上述非數據區,則繞過或跳過。
掩模圖案
這樣我們的地圖就填好了,但是可能那些點不平衡。如果有大面積的空白或者黑塊,會告訴我們掃描識別的難度。所以還是要做蒙版操作(該死的,壹點都不復雜)。根據QR的Spec,QR有八個遮罩可以使用,如下圖:其中,每個遮罩的公式都在每個圖的下方。所謂屏蔽,說白了就是和上面生成的圖進行異或運算。掩碼只會與數據區域進行異或運算,不會影響功能區。(註:選擇合適的口罩也有算法。)
其掩模的識別碼如下:(其中I和J分別對應上圖中的X和Y)
以下是面膜後的樣子。我們可以看到被壹些掩碼異或的數據變得散亂。
蒙版後的二維碼成為最終的圖片。
嗯,妳可以試試寫二維碼程序。當然,妳可以在網上找壹個Reed Soloman的糾錯算法庫,或者看看別人的源代碼是如何實現這種復雜的編碼的。