这里只有对数字进行编码(由于只研究几天时间,相较而言这块较容易,主要研究算法去了,如果自己想扩展可以自己写写代码)
示例一:数字编码
在Version 1的尺寸下,纠错级别为H的情况下,编码: 01234567
1. 把上述数字分成三组: 012 345 67
2. 把他们转成二进制: 012 转成 0000001100; 345 转成 0101011001; 67 转成 1000011。
3. 把这三个二进制串起来: 0000001100 0101011001 1000011
4. 把数字的个数转成二进制 (version 1-H是10 bits ): 8个数字的二进制是 0000001000
5. 把数字编码的标志0001和第4步的编码加到前面: 0001 0000001000 0000001100 0101011001 1000011
2.补位
按8bits重排
如果所有的编码加起来不是8个倍数我们还要在后面加上足够的0,比如上面一共有78个bits,所以,我们还要加上2个0,然后按8个bits分好组:
00100000 01011011 00001011 01111000 11010001 01110010 11011100 01001101 01000011 01000000
也就是按8的倍数重排如果不是8的倍数就在后面补0直至8的倍数
然后
"11101100","00010001" 重复添加也就是236 17
剩余位的计算方法等于下图黄色区域的块数除以8 的余数
代码:
package com;
import java.util.regex.Pattern;
/**
* 二维码数据码生成工具类
* Created by 常发均 on 2020/5/21.
*/
public class makeDataCode {
public String data;
public int jcmDj=2;//Q
public int[] codeNumTotal=new int[]{26,44,70};
public int[] codeTcNum=new int[]{10,8,13};
public int[][] jcCodeNumTotal=new int[][]{{7,10,13,17}};
public int modeNumber;
public int[] sjmArr;
public int jcmNum;
/*
* 码字总数v1 26 v2 44 v3 70
* */
//19 16 13 9
/**
* 1 表示Numeric mode 数字编码
* 2 表示Byte mode, 字节编码
* 3 表示中文编码
* 其他的 不想搞了
*/
public makeDataCode(){}
public makeDataCode(String data){
this.data=data;
if(data.matches("^\\d+$")){
modeNumber=1;
getNumArr();
}else if(isContainChinese(data)){
modeNumber=3;
}else{
modeNumber=2;
}
this.jcmNum=jcCodeNumTotal[0][jcmDj];
}
public makeDataCode(String data, String dj){
this.data=data;
if(dj.equals("L")){
this.jcmDj=0;
}else if(dj.equals("M")){
this.jcmDj=1;
}else if(dj.equals("H")){
this.jcmDj=3;
}
this.jcmNum=jcCodeNumTotal[0][jcmDj];
if(data.matches("^\\d+$")){
modeNumber=1;
getNumArr();
}else if(isContainChinese(data)){
modeNumber=3;
}else{
modeNumber=2;
}
}
public void getNumArr(){
sjmArr=new int[codeNumTotal[0]-jcmNum];
StringBuffer sbf=new StringBuffer("0001");
sbf.append(numToEjzQbl(String.valueOf(data.length())));
for(int i=0;i<data.length();i+=3){
if(i>data.length()-3){
int length=(data.length()-i)*3+1;
String a=sjzZejz(Integer.valueOf(data.substring(i,data.length())));
for(int j=0;j<length-a.length();j++){
a="0"+a;
}
sbf.append(a);
continue;
}
sbf.append(numToEjzQbl(data.substring(i,i+3)));
}
if((sbf.length()%8)!=0){
for(int i=1;i<=(sbf.length()%8);i++){
sbf.append("0");
}
}
for(int i=0;i<sjmArr.length;i++){
if(8*i+8<=sbf.length()){
sjmArr[i]=Integer.parseInt(sbf.substring(8*i,8*i+8),2);
}else{
int m=(i-sbf.length()/8)%2;
if(m==0){
sjmArr[i]=236;
}else{
sjmArr[i]=17;
}
}
}
for(int i=0;i<sjmArr.length;i++){
System.out.print(sjmArr[i]+" ");
}
}
/*
* 数字转换为二进制不足前补零
* */
public String numToEjzQbl(String code){
String a=sjzZejz(Integer.valueOf(code));
String b=a;
for(int j=0;j<codeTcNum[modeNumber-1]-a.length();j++){
b="0"+b;
}
return b;
}
/*
* 十进制转换成二进制
* */
public String sjzZejz(int num){
String str="";
do{
str = num % 2 + str;
num = num / 2;
}while(num!=0);
return str;
}
public boolean isContainChinese(String str) {
return Pattern.compile("[\\u4e00-\\u9fa5]").matcher(str).find()?true:false;
}
public static void main(String[] args) {
makeDataCde d1=new makeDataCde("01234567","H");
}
}