本文內容與技術關係不大,純粹是一個簡單的分享,內容主要是二維碼的設計原理以及一些有趣的擴展,感興趣的同學可以繼續往下看~
二維碼原理優點二維碼出現之前,在需要使用類似編碼的場景時,採用的都是一維碼(條形碼);但是條形碼承載的信息太少,只能用於一些很簡單的場景,因此條形碼除了用於商品等信息,並沒有廣泛流行。
二維碼具有以下優點:
高密度編碼,信息容量大:可容納多達 1850 個大寫字母或 2710 個數字或 1108 個字節,或 500 多個漢字,比普通條碼信息容量約高几十倍。編碼範圍廣:該條碼可以把圖片、聲音、文字、籤字、指紋等可以數位化的信息進行編碼,用條碼表示出來;可以表示多種語言文字;可表示圖像數據。容錯能力強,具有糾錯功能:這使得二維條碼因穿孔、汙損等引起局部損壞時,照樣可以正確得到識讀,損毀面積達 50% 仍可恢復信息。解碼可靠性高:它比普通條碼解碼錯誤率百萬分之二要低得多,誤碼率不超過千萬分之一。簡介我們可以先試著生成一個二維碼。https://kazuhikoarase.github.io/qrcode-generator/js/demo/
如圖可以發現,二維碼有 4 個可變項,其中主要的 2 個為:
一共有 40 個尺寸,對應 40 個版本;Version1是 21*21 的矩形,之後每增加一個版本,就增加4的尺寸,即(v-1)4+21,最高是Version40,177177 的正方形。
容錯率(ErrorCorrectionLevel)二維碼容錯率即是指二維碼圖標被遮擋多少後,仍可以被掃描出來的能力。容錯率越高,則二維碼圖片能被遮擋的部分越多。二維碼有 4 個容錯等級:
根據以上配置不同,相同的內容,在不同的配置下產生的二維碼不一樣,但掃出的內容是一樣的。
設計原理日常我們看到的二維碼就是一張由黑白色塊混合在一起的一張圖片,我們肯定也知道這些黑白色塊就是內容的某種編碼,但其實除了內容外,二維碼還有許多其他輔助掃碼識別的信息。
如上圖,按右側標識的從上到下的順序,分別是:
功能區:
位置探測圖形:位於左上、左下、右上的三個矩形,可以說是二維碼最重要的組成部分。
確定二維碼的放置方向:不管順著掃倒著掃,都可以準確找到第一個編碼字符的位置(左上矩形的右邊);如果任一矩形被遮擋,掃描設備將無法定位。確定編碼字符的邊界:確定編碼字符的上下左右邊界,不被周圍其他信息幹擾。位置探測圖形分隔符:位置探測圖形周圍的白邊,用於分割位置探測圖形和數據。
定位圖形:三個位置探測圖形之間的兩根「線」,用於確定二維碼符號中模塊的坐標(相當於坐標軸)。
校正圖形:用於校正定位(只有版本2以上有),版本越高個數越多,以校正可能發生的定位偏移。
從谷歌搜二維碼圖片,可以觀察下,這些二維碼都具有位置探測圖形、位置探測圖形分隔符及定位圖形。其中第三幅,定位圖形不太對,也確實就掃不出來。
數據區:
數據和糾錯碼字:最主要的部分,用於存放數據和糾錯信息。除掉定位區以及格式信息,數據和糾錯碼字的排布如下:
生成流程在所有數據都完成放置之後,還有一步操作:添加掩碼。掩碼主要是為了避免,如果出現大面積的空白或黑塊,導致我們掃描識別的困難。常用的掩碼如下:
數據經過掩碼後,基本不會再出現大面積的黑塊和白塊,利於掃描。
掩碼只會與數據區進行 XOR,不會影響功能區。
代碼概覽只要遵循以上二維碼的規範,生成對應的二維碼圖形即可,具體實現邏輯不影響。這裡我們參考jquery-qrcode,簡單看下實現,主要流程如下:
makeImpl : function(test, maskPattern) {
this.moduleCount = this.typeNumber * 4 + 17;
this.modules = new Array(this.moduleCount);
for (var row = 0; row < this.moduleCount; row++) {
this.modules[row] = new Array(this.moduleCount);
for (var col = 0; col < this.moduleCount; col++) {
this.modules[row][col] = null;//(col + row) % 3;
}
}
this.setupPositionProbePattern(0, 0);// 位置探測圖形
this.setupPositionProbePattern(this.moduleCount - 7, 0);// 位置探測圖形
this.setupPositionProbePattern(0, this.moduleCount - 7);// 位置探測圖形
this.setupPositionAdjustPattern(); // 校正圖形
this.setupTimingPattern(); // 定位圖形(坐標軸)
this.setupTypeInfo(test, maskPattern); // 版本信息
if (this.typeNumber >= 7) {
this.setupTypeNumber(test);
}
if (this.dataCache == null) {
this.dataCache = QRCode.createData(this.typeNumber, this.errorCorrectLevel, this.dataList); // 生成數據
}
this.mapData(this.dataCache, maskPattern); // 加入掩碼
},生成二維數據後,再把點一一繪製出來即可:
var createCanvas = function(){
// create the qrcode itself
var qrcode = new QRCode(options.typeNumber, options.correctLevel);
qrcode.addData(options.text);
qrcode.make();
// create canvas element
var canvas = document.createElement('canvas');
canvas.width = options.width;
canvas.height = options.height;
var ctx = canvas.getContext('2d');
// compute tileW/tileH based on options.width/options.height
var tileW = options.width / qrcode.getModuleCount();
var tileH = options.height / qrcode.getModuleCount();
// draw in the canvas
for( var row = 0; row < qrcode.getModuleCount(); row++ ){
for( var col = 0; col < qrcode.getModuleCount(); col++ ){
ctx.fillStyle = qrcode.isDark(row, col) ? options.foreground : options.background;
var w = (Math.ceil((col+1)*tileW) - Math.floor(col*tileW));
var h = (Math.ceil((row+1)*tileH) - Math.floor(row*tileH));
ctx.fillRect(Math.round(col*tileW),Math.round(row*tileH), w, h);
}
}
// return just built canvas
return canvas;
}
藝術二維碼日常我們見到的二維碼都是黑白的,但其實二維碼可以多姿多彩。
這裡有很多樣式,可以試一試https://qrbtf.com/。
二維碼之所以可以五顏六色,是因為二維碼的有用信息只是 0 和 1,至於 0 和 1 用什麼信息表達,只要掃碼軟體可以識別就行。目前的掃碼軟體一般都是對圖片進行灰度處理,所以二維碼上的點無論如何表達,只要經過灰度處理後 0 和 1 沒有顛倒,則信息不會出錯,不會影響掃碼結果。
藝術二維碼實現起來也不難,只要區分特定的數據區,並用特定的圖片渲染即可,有興趣可以參考https://github.com/252860883/ArtQRCode。
更簡單一點的,也可以直接降低黑白透明度,背景渲染特定的圖片;如果只是網頁上顯示,還可以做成 gif 動圖形式。
不過,藝術二維碼由於顏色更豐富幹擾信息更多,因此相比黑白二維碼,藝術二維碼對掃描軟體的要求也更高。
小程序碼小程序碼和二維碼雖然看起來完全不一樣,但是它們的設計思想及生成流程是基本一樣的。
支持3種容量:36 射線、54 射線和 72 射線;ps:了解二維碼的原理後,其實我們自己也可以手畫二維碼。發散一下,求婚啥的,用紅玫瑰和白玫瑰擺個二維碼,女朋友掃碼出來一看寫著「Marry Me!」,哈哈哈哈豈不是有點程式設計師的浪漫😬~
參考[二維碼的生成細節和原理](<http://- https://coolshell.cn/articles/10590.html>)https://www.zhihu.com/question/21023430文內連結
https://kazuhikoarase.github.io/qrcode-generator/js/demo/https://github.com/jeromeetienne/jquery-qrcode/blob/master/src/qrcode.js#L99https://github.com/252860883/ArtQRCode