二维码原理

本文介绍了二维码的编码过程,包括模式标识符、文本串计数标识符、数据编码、码字布置等步骤。详细阐述了如何根据不同的模式进行编码,并解释了码字在二维码矩阵中的布置规则,有助于理解二维码的工作机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二维码的码字布置
一、模式标识符(Mode Indicator)  QR码的模式(Mode)就是前文提到的数字、字符、8bit 字节码、多字节码等。对于不同的模式,都有对应的模式标识符(Mode Indicator)来帮助解码程序进行匹配,模式标识符是4bit的二进制数: 
     1、数字模式(numeric mode ): 0001 
     2、混合字符模式(alphanumeric mode) : 0010
     3、8bit byte mode: 0100 
     4、日本汉字(KANJI mode) : 1000 
     5、中国汉字(GB2312):1101  由于示例文本串是混合字符,因此将选择alphanumeric mode,其标识码为:0010 

二、文本串计数标识符(Character count indicator)  文本串计数标识符用来存储源内容字符串的长度,在版本1-9的QR码中,文本串长度标识符自身的长度被定义为: 
     数字 : 10bit 
     混合字符 : 9bit 
    8bit 字节码 : 8bit 
    多字节码 : 8bit  在本例中,源文本串的长度为8个字符,混合字符的长度用9bit表示,因此将字符个数8编码为9位二进制表示:000001000  加上混合字符模式标识码,总的编码为0010 000001000


三、数据的编码请参照网络资料。 如果编码后的字符长度不足当前版本和纠错级别所存储的容量,则在后续补"0000",如果容量已满则无需添加终止符。各个版本和纠错级别存储容量网络查表得知。

四、将以上编码数据编码成8bit码字将以上的编码再按8bit一组,形成码字(code words):   00100000 01000001 11001101 01000101 00101001 11011100 00101110 10000 如果尾部数据不足8bit,则在尾部充0。
        如果编码后的数据不足版本及纠错级别的最大容量,则在尾部补充 "11101100" 和 "00010001",直到全部填满。 各个版本和纠错级别最大容量网络查表得知。

五、码字的布置: (以垂直布置为例)
        码字大多数以2*4模块(2宽4高)规则分布,遇到功能图则跳过成不规则分布 :
        码字从最下角依次由从右向左、从下向上或从上向下交替布局。(也就是将所有码字看成一数据流,依次从最高位开始将其放在矩阵中从右向左,向上或向下(先2宽向上,再2宽向下,依次交替))的位置,遇到功能图形跳过其区域。


读码字:
uchar data=0;
        int bit_count=0,word_count=0;
        int dir=-1;
        int x=codes->width-1;
        int y=codes->height-1;
        
        do{
            data<<=1;
            bit_count++;
            //x,y是否是数据元素(非边界,非功能数据?)
            if(CV_IMAGE_ELEM(codes,uchar,y,x)>=128)
                data|=1;
            //每8个元素一个码字。
            if(!(bit_count%8)){
                if(this->qr->push_codedata(data))
                    word_count++;
                data=0;
            }
            
            //当x为2宽右边一列,判断其左边的元素是否数据元素(非边界、非功能数据?)不是则判断其上边元素,当y到边界,则此2宽读完,x-2读下一个2宽。
            if(x&0x1){
                if(CV_IMAGE_ELEM(funcs,uchar,y,x-1))  //
funcs的功能区全为黑色,其他区为白色,故非零的点x,y对应的codes
                    x--;                                                        //的点即为编码区。
                else{
                    do{
                        y+=dir;
                        if(y<0||y>=codes->height){
                            x-=2;
                            dir*=-1;
                            y+=dir;
                            if(x<0)
                                break;
                        }
                    }while(!CV_IMAGE_ELEM(funcs,uchar,y,x));
                }
            }

 //当x为2宽左边一列,判断其右边的上边的元素是否数据元素(非边界、非功能数据?)不是则判断其上边(右边的上边的左边)元素,当y到边界,则此2宽读完,x-2读下一个2宽。
            else{
                x++;
                do{
                    y+=dir;
                    if(y>=0&&y<codes->height){
                        if(CV_IMAGE_ELEM(funcs,uchar,y,x)){
                            break;
                        }
                        else if(CV_IMAGE_ELEM(funcs,uchar,y,x-1)){
                            x--;
                            break;
                        }
                        else{
                            y+=dir;
                        }
                    }
                    else{
                        x-=2;
                        dir*=-1;
                        y+=dir;
                        if(x<0)
                            break;
                    }
                }while(!CV_IMAGE_ELEM(funcs,uchar,y,x));
            }
        }while(x>=0);
        
        if(data){
            if(this->qr->push_codedata(data))
                word_count++;
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值