ZBar源码分析(十二)

本文详细分析了二维码解码器qr_finder.c模块,包括qr_finder_line*函数和zbar_decoder_t结构体的使用,探讨了查找器图案宽度的更新和有效性判断。同时,介绍了ean.c中ean符号的辅助模式解码,如aux_end、aux_start和aux_mid函数,这些函数用于识别和验证条形码的起始、结束和中间辅助模式。
摘要由CSDN通过智能技术生成

2021SC@SDUSC

目录

一、qr_finder.c分析

二、ean.c分析


一、qr_finder.c分析

qr_finder_line *_zbar_decoder_get_qr_finder_line (zbar_decoder_t *dcode)
{
    return(&dcode->qrf.line);
}

在这一点上,长度是从finder拥有的解码边缘NB的所有解码单元偏移量。

zbar_symbol_type_t _zbar_find_qr (zbar_decoder_t *dcode)
{
    qr_finder_t *qrf = &dcode->qrf;
    unsigned s, qz, w;
    int ei;

    qrf->s5 -= get_width(dcode, 6);
    qrf->s5 += get_width(dcode, 1);
    s = qrf->s5;

更新最新的查找器图案宽度。

    if(get_color(dcode) != ZBAR_SPACE || s < 7)
        return(0);

    dbprintf(2, "    qrf: s=%d", s);

    ei = decode_e(pair_width(dcode, 1), s, 7);
    dbprintf(2, " %d", ei);
    if(ei)
        goto invalid;

    ei = decode_e(pair_width(dcode, 2), s, 7);
    dbprintf(2, "%d", ei);
    if(ei != 2)
        goto invalid;

    ei = decode_e(pair_width(dcode, 3), s, 7);
    dbprintf(2, "%d", ei);
    if(ei != 2)
        goto invalid;

    ei = decode_e(pair_width(dcode, 4), s, 7);
    dbprintf(2, "%d", ei);
    if(ei)
        goto invalid;

如果我们发现具有相反极性的查找器模式,我们应该反转最终的二值化图像,并使用它们在其中搜索QR码。

    qz = get_width(dcode, 0);
    w = get_width(dcode, 1);
    qrf->line.eoffs = qz + (w + 1) / 2;
    qrf->line.len = qz + w + get_width(dcode, 2);
    qrf->line.pos[0] = qrf->line.len + get_width(dcode, 3);
    qrf->line.pos[1] = qrf->line.pos[0];
    w = get_width(dcode, 5);
    qrf->line.boffs = qrf->line.pos[0] + get_width(dcode, 4) + (w + 1) / 2;

    dbprintf(2, " boff=%d pos=%d len=%d eoff=%d [valid]\n",
             qrf->line.boffs, qrf->line.pos[0], qrf->line.len,
             qrf->line.eoffs);

    dcode->direction = 0;
    dcode->buflen = 0;
    return(ZBAR_QRCODE);

invalid:
    dbprintf(2, " [invalid]\n");
    return(0);

解码器所需的有效QR查找器符号标记位置。

二、ean.c分析

static inline signed char aux_end (zbar_decoder_t *dcode,
                                   unsigned char fwd)
{
    signed char code, i;

    unsigned s = calc_s(dcode, 4 + fwd, 4);

    unsigned qz = get_width(dcode, 0);
    if(!fwd && qz && qz <= s * 3 / 4) {
        dbprintf(2, " [invalid quiet]");
        return(-1);
    }

    dbprintf(2, " (");
    code = 0;
    for(i = 1 - fwd; i < 3 + fwd; i++) {
        unsigned e = get_width(dcode, i) + get_width(dcode, i + 1);
        dbprintf(2, " %d", e);
        code = (code << 2) | decode_e(e, s, 7);
        if(code < 0) {
            dbprintf(2, " [invalid end guard]");
            return(-1);
        }
    }
    dbprintf(2, ") s=%d aux=%x", s, code);
    return(code);
}

使用前面的4作为字符宽度,计算前面的N(>=2)宽度作为辅助图案。

static inline signed char aux_start (zbar_decoder_t *dcode)
{
    unsigned e1, e2 = get_width(dcode, 5) + get_width(dcode, 6);
    unsigned char E1;
    if(dcode->ean.s4 < 6)
        return(-1);

    if(decode_e(e2, dcode->ean.s4, 7)) {
        dbprintf(2, " [invalid any]");
        return(-1);
    }

    e1 = get_width(dcode, 4) + get_width(dcode, 5);
    E1 = decode_e(e1, dcode->ean.s4, 7);

    if(get_color(dcode) == ZBAR_BAR) {
        unsigned qz = get_width(dcode, 7);
        if(!qz || qz > dcode->ean.s4 * 3 / 4) {
            if(!E1) {
                dbprintf(2, " [valid normal]");
                return(0);
            }
            else if(E1 == 1) {
                dbprintf(2, " [valid add-on]");
                return(STATE_ADDON);
            }
        }
        dbprintf(2, " [invalid start]");
        return(-1);
    }

使用当前4作为可能的字符确定可能的辅助模式。

static inline signed char aux_mid (zbar_decoder_t *dcode)
{
    unsigned e = get_width(dcode, 4) + get_width(dcode, 5);
    return(decode_e(e, dcode->ean.s4, 7));
}

使用当前4作为字符检查加载项分隔符。

static inline signed char decode4 (zbar_decoder_t *dcode)
{
    signed char code;
    unsigned e1 = ((get_color(dcode) == ZBAR_BAR)
                   ? get_width(dcode, 0) + get_width(dcode, 1)
                   : get_width(dcode, 2) + get_width(dcode, 3));
    unsigned e2 = get_width(dcode, 1) + get_width(dcode, 2);
    dbprintf(2, "\n        e1=%d e2=%d", e1, e2);

    if(dcode->ean.s4 < 6)
        return(-1);

尝试将之前的4个宽度(2条和2个空格)解码为一个字符。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值