为什么我的二维码生成过程中会留下未定义的模块?
Why are undefined modules left during my QR code generation?
我尝试用 JavaScript 生成二维码。根据一些教程,生成必须放置在 QR 矩阵内的位串是可行的,我的位串(由交错数据码字、交错纠错码字和其余位组成)与教程中的示例相同。因此我相信我在放置 QR 码模块时犯了一个错误,由函数 addDataToMatrix
.
完成
对于版本一到版本五的 QR 码,一切似乎都有效。但是对于高于六的二维码版本,并不是二维二维矩阵的所有模块都会被填充,其中一些会留下“未定义”。
这是一个例子:
// input string: Why are these damned undefined modules left after the placement?
// alternative string: Hello, world!
// error correction level: H
let version=7;
// version for alternative input / bit string: 2
// generated bit string (interleaved data codewords, interleaved error correction codewords, remainder bits)
let bitString="01000100001101100101011000110010010001100000010101010010011001100000011010000110011101100000011010010110110001100101001010000111010001101110011001010110000001111001001000010110010101100110011100000110000001101101011001000010010000101100011000010111111001100000011000000110000101100010011001010110110101100001011000110110010100100100001011110110011001110101011000000111000001110100011101000110110101100100011001010110010101100101011101010110100001101110011011000110001000101110011101010111010001100101011100000111010000111111000011011100001100010001110000110010011010101110100101101100011000100101101001001010010100000000010100001000011110101000100110011100111000101000011001011010110100110001100101011101110111110011111000100010011100110110011010001110010100111001111110011010011011010010110100010011110011101100001010000101110111110100101111000011010101011111001001000011010011111101010110101111000001010110100111010011011001101111001111111011010101101111010011010101001100010010000101100101101110011101100111001100010010100101010101100011010011100110000100111000000101000000010101101010111010011100111010100100101010111110100001111101101100110001100101010001101001010011101110000001101000010000100010010110111000111000000010110100000111110110111010100111101010001001100001001010010100100110010100110010011011100011100011001100100100000000100111010110111000101100010011110000011110011111011001011011110101101000000000010101000110000011000011010111101111010110010101011110011000100010111111111000101000000001000011001011110101001010001010010111110100011011011110110011";
// alternative bit string: 01000000110101001000011001010110110001101100011011110010110000100000011101110110111101110010011011000110010000100001000011101100011011110111111010111111101011111101001111001100010110100111111000100110000110001111111111101100011000000001011001011100100010011010110110100000010011011111000111000000111000001000111111000011000000110011100111110010000011010000000
const ALIGNMENT_PATTERN_COORDINATES={
coordinates1: [18, 22, 26, 30, 34, 22, 24, 26, 28, 30, 32, 34, 26, 26, 26, 30, 30, 30, 34, 28, 26, 30, 28, 32, 30, 34, 26, 30, 26, 30, 34, 30, 34, 30, 24, 28, 32, 26, 30],
coordinates2: [undefined, undefined, undefined, undefined, undefined, 38, 42, 46, 50, 54, 58, 62, 46, 48, 50, 54, 56, 58, 62, 50, 50, 54, 54, 58, 58, 62, 50, 54, 52, 56, 60, 58, 62, 54, 50, 54, 58, 54, 58],
coordinates3: [undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, 66, 70, 74, 78, 82, 86, 90, 72, 74, 78, 80, 84, 86, 90, 74, 78, 78, 82, 86, 86, 90, 78, 76, 80, 84, 82, 86],
coordinates4: [undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, 94, 98, 102, 106, 110, 114, 118, 98, 102, 104, 108, 112, 114, 118, 102, 102, 106, 110, 110, 114],
coordinates5: [undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, 122, 126, 130, 134, 138, 142, 146, 126, 128, 132, 136, 138, 142],
coordinates6: [undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, 150, 154, 158, 162, 166, 170]
};
let matrix=generateMatrix(version);
generateSeparators(matrix);
generateFinderPatterns(matrix);
generateAlignmentPatterns(version, matrix);
generateTimingPatterns(matrix);
reserveAreas(version, matrix);
addDataToMatrix(matrix, bitString);
drawMatrix(matrix);
function generateMatrix(version){
let size=21+(version-1)*4;
let matrix=[];
for(let i=0; i<size; i++){
matrix[i]=[];
for(let j=0; j<size; j++) matrix[i][j]=undefined;
}
matrix[version*4+9][8]=1;
return matrix;
}
function generateSeparators(matrix){
for(let i=0; i<8; i++){
for(let j=0; j<8; j++){
matrix[i][j]=0;
matrix[i][matrix[i].length-1-j]=0;
matrix[matrix[i].length-1-i][j]=0;
}
}
}
function generateFinderPatterns(matrix){
for(let i=0; i<7; i++){
for(let j=0; j<7; j++){
matrix[i][j]=1;
matrix[i][matrix[i].length-1-j]=1;
matrix[matrix[i].length-1-i][j]=1;
}
}
for(let i=1; i<6; i++){
for(let j=1; j<6; j++){
matrix[i][j]=0;
matrix[i][matrix[i].length-1-j]=0;
matrix[matrix[i].length-1-i][j]=0;
}
}
for(let i=2; i<5; i++){
for(let j=2; j<5; j++){
matrix[i][j]=1;
matrix[i][matrix[i].length-1-j]=1;
matrix[matrix[i].length-1-i][j]=1;
}
}
}
function generateAlignmentPatterns(version, matrix){
if(version>1){
let coordinates=[6, ALIGNMENT_PATTERN_COORDINATES.coordinates1[version-2], ALIGNMENT_PATTERN_COORDINATES.coordinates2[version-2], ALIGNMENT_PATTERN_COORDINATES.coordinates3[version-2], ALIGNMENT_PATTERN_COORDINATES.coordinates4[version-2], ALIGNMENT_PATTERN_COORDINATES.coordinates5[version-2], ALIGNMENT_PATTERN_COORDINATES.coordinates6[version-2]].filter(Number);
let moduleCenters=[];
for(let i=0; i<coordinates.length; i++) moduleCenters.push([coordinates[i], coordinates[i]]);
for(let i=0; i<coordinates.length-1; i++){
for(let j=i+1; j<coordinates.length; j++){
moduleCenters.push([coordinates[i], coordinates[j]]);
moduleCenters.push([coordinates[j], coordinates[i]]);
}
}
for(let i=0; i<moduleCenters.length; i++){
let isEmpty=true;
for(let j=-2; j<3; j++){
for(let k=-2; k<3; k++){
if(matrix[moduleCenters[i][0]+j][moduleCenters[i][1]+k]!==undefined) isEmpty=false;
}
}
if(isEmpty){
for(let j=-2; j<3; j++){
for(let k=-2; k<3; k++) matrix[moduleCenters[i][0]+j][moduleCenters[i][1]+k]=1;
}
for(let j=-1; j<2; j++){
for(let k=-1; k<2; k++) matrix[moduleCenters[i][0]+j][moduleCenters[i][1]+k]=0;
}
matrix[moduleCenters[i][0]][moduleCenters[i][1]]=1;
}
}
}
}
function generateTimingPatterns(matrix){
for(let i=8; i<matrix.length-8; i++){
matrix[6][i]=(i%2==0)?1:0;
matrix[i][6]=(i%2==0)?1:0;
}
}
function reserveAreas(version, matrix){
if(version<7){
for(let i=0; i<9; i++){
if(matrix[i][8]===undefined) matrix[i][8]="reserved";
if(matrix[8][i]===undefined) matrix[8][i]="reserved";
}
for(let i=0; i<8; i++) matrix[8][matrix[8].length-1-i]="reserved";
for(let i=0; i<7; i++) matrix[matrix[8].length-1-i][8]="reserved";
}
else{
for(let i=0; i<6; i++){
for(let j=0; j<3; j++){
matrix[i][matrix[i].length-9-j]="reserved";
matrix[matrix[i].length-9-j][i]="reserved";
}
}
}
}
function addDataToMatrix(matrix, bitString){
let j=matrix[0].length-1;
while(bitString.length>0){
for(let i=0; i<matrix.length; i++){
if(bitString.length>0&&matrix[matrix.length-1-i][j]===undefined){
matrix[matrix.length-1-i][j]=bitString.charAt(bitString.length-1);
bitString=bitString.slice(0, -1);
}
if(bitString.length>0&&matrix[matrix.length-1-i][j-1]===undefined){
matrix[matrix.length-1-i][j-1]=bitString.charAt(bitString.length-1);
bitString=bitString.slice(0, -1);
}
}
j-=2;
if(j==6) j--;
for(let i=0; i<matrix.length; i++){
if(bitString.length>0&&matrix[i][j]===undefined){
matrix[i][j]=bitString.charAt(bitString.length-1);
bitString=bitString.slice(0, -1);
}
if(bitString.length>0&&matrix[i][j-1]===undefined){
matrix[i][j-1]=bitString.charAt(bitString.length-1);
bitString=bitString.slice(0, -1);
}
}
j-=2;
}
}
function drawMatrix(matrix){
let cssClass;
let code="";
for(let i=0; i<matrix.length; i++){
for(let j=0; j<matrix[i].length; j++){
if(matrix[i][j]===undefined) cssClass="undefined";
if(matrix[i][j]=="reserved") cssClass="reserved";
if(matrix[i][j]==0) cssClass="white";
if(matrix[i][j]==1) cssClass="black";
code+='<div class="module '+cssClass+'"></div>';
if(j==matrix[i].length-1) code+='<div class="break"></div>';
}
}
document.getElementById("result").innerHTML=code;
}
*{
box-sizing: border-box;
}
#result{
border-width: 1px;
border-style: solid;
border-color: lightgray;
overflow: auto;
padding: 28px;
width: -webkit-max-content;
width: -moz-max-content;
width: max-content;
}
.module{
border-width: 1px;
border-style: solid;
border-color: lightgray;
float: left;
height: 7px;
width: 7px;
}
.module.undefined{
background-color: lightslategray;
}
.module.reserved{
background-color: lightskyblue;
}
.module.white{
background-color: white;
}
.module.black{
background-color: black;
}
.break{
display: block;
}
<!DOCTYPE html>
<html>
<head>
<title>QR Generator</title>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
</head>
<body>
<div id="result"></div>
</body>
</html>
如你所见,输入“为什么这些该死的未定义模块在放置后留下来?”导致位串导致一些未定义的灰色模块。尝试另一个输入,例如“Hello, world!”没有未定义的模块了。
谁能解释一下我哪里出错了?我希望我的例子足够好。
编辑:
我发现给函数addDataToMatrix
的位串的长度正好比矩阵中从版本7到版本40的未定义模块总数短30个字符。
我发现了错误。我误解了格式和版本位放置规则。
对于版本 1 到 6,需要格式信息。对于版本 7 到 40,需要版本信息和格式信息。我只放了七到四十版本的二维码版本信息
我尝试用 JavaScript 生成二维码。根据一些教程,生成必须放置在 QR 矩阵内的位串是可行的,我的位串(由交错数据码字、交错纠错码字和其余位组成)与教程中的示例相同。因此我相信我在放置 QR 码模块时犯了一个错误,由函数 addDataToMatrix
.
对于版本一到版本五的 QR 码,一切似乎都有效。但是对于高于六的二维码版本,并不是二维二维矩阵的所有模块都会被填充,其中一些会留下“未定义”。
这是一个例子:
// input string: Why are these damned undefined modules left after the placement?
// alternative string: Hello, world!
// error correction level: H
let version=7;
// version for alternative input / bit string: 2
// generated bit string (interleaved data codewords, interleaved error correction codewords, remainder bits)
let bitString="01000100001101100101011000110010010001100000010101010010011001100000011010000110011101100000011010010110110001100101001010000111010001101110011001010110000001111001001000010110010101100110011100000110000001101101011001000010010000101100011000010111111001100000011000000110000101100010011001010110110101100001011000110110010100100100001011110110011001110101011000000111000001110100011101000110110101100100011001010110010101100101011101010110100001101110011011000110001000101110011101010111010001100101011100000111010000111111000011011100001100010001110000110010011010101110100101101100011000100101101001001010010100000000010100001000011110101000100110011100111000101000011001011010110100110001100101011101110111110011111000100010011100110110011010001110010100111001111110011010011011010010110100010011110011101100001010000101110111110100101111000011010101011111001001000011010011111101010110101111000001010110100111010011011001101111001111111011010101101111010011010101001100010010000101100101101110011101100111001100010010100101010101100011010011100110000100111000000101000000010101101010111010011100111010100100101010111110100001111101101100110001100101010001101001010011101110000001101000010000100010010110111000111000000010110100000111110110111010100111101010001001100001001010010100100110010100110010011011100011100011001100100100000000100111010110111000101100010011110000011110011111011001011011110101101000000000010101000110000011000011010111101111010110010101011110011000100010111111111000101000000001000011001011110101001010001010010111110100011011011110110011";
// alternative bit string: 01000000110101001000011001010110110001101100011011110010110000100000011101110110111101110010011011000110010000100001000011101100011011110111111010111111101011111101001111001100010110100111111000100110000110001111111111101100011000000001011001011100100010011010110110100000010011011111000111000000111000001000111111000011000000110011100111110010000011010000000
const ALIGNMENT_PATTERN_COORDINATES={
coordinates1: [18, 22, 26, 30, 34, 22, 24, 26, 28, 30, 32, 34, 26, 26, 26, 30, 30, 30, 34, 28, 26, 30, 28, 32, 30, 34, 26, 30, 26, 30, 34, 30, 34, 30, 24, 28, 32, 26, 30],
coordinates2: [undefined, undefined, undefined, undefined, undefined, 38, 42, 46, 50, 54, 58, 62, 46, 48, 50, 54, 56, 58, 62, 50, 50, 54, 54, 58, 58, 62, 50, 54, 52, 56, 60, 58, 62, 54, 50, 54, 58, 54, 58],
coordinates3: [undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, 66, 70, 74, 78, 82, 86, 90, 72, 74, 78, 80, 84, 86, 90, 74, 78, 78, 82, 86, 86, 90, 78, 76, 80, 84, 82, 86],
coordinates4: [undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, 94, 98, 102, 106, 110, 114, 118, 98, 102, 104, 108, 112, 114, 118, 102, 102, 106, 110, 110, 114],
coordinates5: [undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, 122, 126, 130, 134, 138, 142, 146, 126, 128, 132, 136, 138, 142],
coordinates6: [undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, 150, 154, 158, 162, 166, 170]
};
let matrix=generateMatrix(version);
generateSeparators(matrix);
generateFinderPatterns(matrix);
generateAlignmentPatterns(version, matrix);
generateTimingPatterns(matrix);
reserveAreas(version, matrix);
addDataToMatrix(matrix, bitString);
drawMatrix(matrix);
function generateMatrix(version){
let size=21+(version-1)*4;
let matrix=[];
for(let i=0; i<size; i++){
matrix[i]=[];
for(let j=0; j<size; j++) matrix[i][j]=undefined;
}
matrix[version*4+9][8]=1;
return matrix;
}
function generateSeparators(matrix){
for(let i=0; i<8; i++){
for(let j=0; j<8; j++){
matrix[i][j]=0;
matrix[i][matrix[i].length-1-j]=0;
matrix[matrix[i].length-1-i][j]=0;
}
}
}
function generateFinderPatterns(matrix){
for(let i=0; i<7; i++){
for(let j=0; j<7; j++){
matrix[i][j]=1;
matrix[i][matrix[i].length-1-j]=1;
matrix[matrix[i].length-1-i][j]=1;
}
}
for(let i=1; i<6; i++){
for(let j=1; j<6; j++){
matrix[i][j]=0;
matrix[i][matrix[i].length-1-j]=0;
matrix[matrix[i].length-1-i][j]=0;
}
}
for(let i=2; i<5; i++){
for(let j=2; j<5; j++){
matrix[i][j]=1;
matrix[i][matrix[i].length-1-j]=1;
matrix[matrix[i].length-1-i][j]=1;
}
}
}
function generateAlignmentPatterns(version, matrix){
if(version>1){
let coordinates=[6, ALIGNMENT_PATTERN_COORDINATES.coordinates1[version-2], ALIGNMENT_PATTERN_COORDINATES.coordinates2[version-2], ALIGNMENT_PATTERN_COORDINATES.coordinates3[version-2], ALIGNMENT_PATTERN_COORDINATES.coordinates4[version-2], ALIGNMENT_PATTERN_COORDINATES.coordinates5[version-2], ALIGNMENT_PATTERN_COORDINATES.coordinates6[version-2]].filter(Number);
let moduleCenters=[];
for(let i=0; i<coordinates.length; i++) moduleCenters.push([coordinates[i], coordinates[i]]);
for(let i=0; i<coordinates.length-1; i++){
for(let j=i+1; j<coordinates.length; j++){
moduleCenters.push([coordinates[i], coordinates[j]]);
moduleCenters.push([coordinates[j], coordinates[i]]);
}
}
for(let i=0; i<moduleCenters.length; i++){
let isEmpty=true;
for(let j=-2; j<3; j++){
for(let k=-2; k<3; k++){
if(matrix[moduleCenters[i][0]+j][moduleCenters[i][1]+k]!==undefined) isEmpty=false;
}
}
if(isEmpty){
for(let j=-2; j<3; j++){
for(let k=-2; k<3; k++) matrix[moduleCenters[i][0]+j][moduleCenters[i][1]+k]=1;
}
for(let j=-1; j<2; j++){
for(let k=-1; k<2; k++) matrix[moduleCenters[i][0]+j][moduleCenters[i][1]+k]=0;
}
matrix[moduleCenters[i][0]][moduleCenters[i][1]]=1;
}
}
}
}
function generateTimingPatterns(matrix){
for(let i=8; i<matrix.length-8; i++){
matrix[6][i]=(i%2==0)?1:0;
matrix[i][6]=(i%2==0)?1:0;
}
}
function reserveAreas(version, matrix){
if(version<7){
for(let i=0; i<9; i++){
if(matrix[i][8]===undefined) matrix[i][8]="reserved";
if(matrix[8][i]===undefined) matrix[8][i]="reserved";
}
for(let i=0; i<8; i++) matrix[8][matrix[8].length-1-i]="reserved";
for(let i=0; i<7; i++) matrix[matrix[8].length-1-i][8]="reserved";
}
else{
for(let i=0; i<6; i++){
for(let j=0; j<3; j++){
matrix[i][matrix[i].length-9-j]="reserved";
matrix[matrix[i].length-9-j][i]="reserved";
}
}
}
}
function addDataToMatrix(matrix, bitString){
let j=matrix[0].length-1;
while(bitString.length>0){
for(let i=0; i<matrix.length; i++){
if(bitString.length>0&&matrix[matrix.length-1-i][j]===undefined){
matrix[matrix.length-1-i][j]=bitString.charAt(bitString.length-1);
bitString=bitString.slice(0, -1);
}
if(bitString.length>0&&matrix[matrix.length-1-i][j-1]===undefined){
matrix[matrix.length-1-i][j-1]=bitString.charAt(bitString.length-1);
bitString=bitString.slice(0, -1);
}
}
j-=2;
if(j==6) j--;
for(let i=0; i<matrix.length; i++){
if(bitString.length>0&&matrix[i][j]===undefined){
matrix[i][j]=bitString.charAt(bitString.length-1);
bitString=bitString.slice(0, -1);
}
if(bitString.length>0&&matrix[i][j-1]===undefined){
matrix[i][j-1]=bitString.charAt(bitString.length-1);
bitString=bitString.slice(0, -1);
}
}
j-=2;
}
}
function drawMatrix(matrix){
let cssClass;
let code="";
for(let i=0; i<matrix.length; i++){
for(let j=0; j<matrix[i].length; j++){
if(matrix[i][j]===undefined) cssClass="undefined";
if(matrix[i][j]=="reserved") cssClass="reserved";
if(matrix[i][j]==0) cssClass="white";
if(matrix[i][j]==1) cssClass="black";
code+='<div class="module '+cssClass+'"></div>';
if(j==matrix[i].length-1) code+='<div class="break"></div>';
}
}
document.getElementById("result").innerHTML=code;
}
*{
box-sizing: border-box;
}
#result{
border-width: 1px;
border-style: solid;
border-color: lightgray;
overflow: auto;
padding: 28px;
width: -webkit-max-content;
width: -moz-max-content;
width: max-content;
}
.module{
border-width: 1px;
border-style: solid;
border-color: lightgray;
float: left;
height: 7px;
width: 7px;
}
.module.undefined{
background-color: lightslategray;
}
.module.reserved{
background-color: lightskyblue;
}
.module.white{
background-color: white;
}
.module.black{
background-color: black;
}
.break{
display: block;
}
<!DOCTYPE html>
<html>
<head>
<title>QR Generator</title>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
</head>
<body>
<div id="result"></div>
</body>
</html>
如你所见,输入“为什么这些该死的未定义模块在放置后留下来?”导致位串导致一些未定义的灰色模块。尝试另一个输入,例如“Hello, world!”没有未定义的模块了。
谁能解释一下我哪里出错了?我希望我的例子足够好。
编辑:
我发现给函数addDataToMatrix
的位串的长度正好比矩阵中从版本7到版本40的未定义模块总数短30个字符。
我发现了错误。我误解了格式和版本位放置规则。 对于版本 1 到 6,需要格式信息。对于版本 7 到 40,需要版本信息和格式信息。我只放了七到四十版本的二维码版本信息