• QR code二维码简介及Qrencode库的移植与使用


    摘自并整理:http://blog.chinaunix.net/uid-22670933-id-5781511.html

    现在生活中,二维码可以说是无处不在,微信扫码支付,支付宝扫码支付,就连贴小广告的都带上了二维码了。之前一直想去了解一下,还是太懒了,就没去,现在项目中需要用到这东西,正好借此机会了解一下。

     上网一查,原来二维码的还有很多种。下表是一个简单的介绍:

    二维码的优点突出,所以大有取代条形码的趋势,二维码的特点:

    1、高密度,容量大,可容纳多达1850个大写字母(字符)或2710个数字,支持最高1108个字节的数据存储,比一维码信息容量高几十倍。

    2、 范围广,支持对图片、声音、文字、签字、指纹等各类可以数字化信息的编码,还可以表示多种语言文字和图像数据。

    3、 容错能力强,具有纠错功能,当二维码因穿孔、污损等引起局部损坏时,照样可以正常识别,损毁面积达50%仍可恢复。

    4、 成本低,易制作,持久耐用等

    本次开发使用的是QRcode,因为它目前使用的较为广泛,微信支付,扫码加好友等等都可以是QRcode。

    下面对QR Code做个详细的了解:

    QR Code码,是由Denso公司于1994年9月研制的一种矩阵二维码符号,它具有一维条码及其它二维条码所具有的信息容量大、可靠性高、可表示汉字及图象多种文字信息、保密防伪性强等优点,是目前较为常用的二维条码。

    基本特性

    编辑

    符号规格

    21×21模块(版本1)-177×177 模块(版本40)

    (每一规格:每边增加4个模块)

    容量(指最大规格符号版本40-L级)

     

    · 8位字节数据 :2,953个字符

    · 汉字数据 :1,817个字符

    数据表示方法

    深色模块表示二进制“1”,浅色模块表示二进制“0”。

    纠错能力

    · L级:约可纠错7%的数据码字

    · M级:约可纠错15%的数据码字

    · Q级:约可纠错25%的数据码字

    · H级:约可纠错30%的数据码字

    掩模(固有)

    可以使符号中深色与浅色模块的比例接近1:1,使因相邻模块的排列造成译码困难的可能性降为最小。

    模式

    1、数字模式(numeric mode ): 0001(数字0~9)

    2、混合字符模式(alphanumeric mode) : 0010(数字0~9;大写字母A~Z;9个其他字符:space ,$, %, *, +, -, ., /, :);

    3、8bit byte mode: 0100

    4、日本汉字(KANJI mode) : 1000

    5、中国汉字(GB2312):1101(GB 2312对应的汉字和非汉字字符)

    为了美观,可以在二维码上添加一张logo图片,一般放在中间。我在网上查了好久,没有找到logo的大小和二维码的等级和容错性的关系,如果大家有找到的,请告知,谢谢,我这边自己选择了长宽是二维码的20%,测试不影响识别。

    qrencode下载地址https://fukuchi.org/works/qrencode/

    编码阶段:

    在网上找了一个第三方的库,qrencode,提供了制作二维码的API,接口很简单,

    extern QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);

    这个API可以直接设置要编码的字符串内容,以及对二维码的设置,如版本(即大小等级1~40)、容错等级、模式等,返回的是一个结构体指针,QRcode,

    typedef struct {
             int version;         ///< version of the symbol
             int width;           ///< width of the symbol
             unsigned char *data; ///< symbol data
    } QRcode;

    它的数据data就是二维码的内容,1对应深色块,0对应浅色块。借助一些其他的画图的API就可以绘制出二维码。哭的详细介绍请参考:点击打开链接

    我使用的是MTK6261A做的是嵌入式开发,所以需要涉及到一些交叉编译等。

    由于qrencode 在我们项目中作为一个第三方库,只需要它的基础功能,后面不会持续去更新,所以,决定将其编译成静态库。如果想编译成动态库,可以参考http://blog.csdn.net/u010977122/article/details/52959098

    这个是我开始编译成动态库遇到的一些问题。

    静态库的编译参照了 http://blog.csdn.net/liyuanbhu/article/details/44647139 博主的配置,在此感谢。

    将博主的一些东西搬过来,从而让本文更加完整,下面是编译windows下的静态库的过程。

    将下载下来的qrencode-4.0.2.tar.gz解压缩,直接./configure;make,编译后生成config.h

    将 qrencode 的源文件(.c 和 .h)全部拷出来,除了 qrenc.c 。编译 qrencode 时还需要有个 config.h 文件(源码中的config.h.in文件修改成config.h),这个文件主要是配置库中的一些宏开关,可以用我下面提供的这个。

    /* config.h.  Generated from config.h.in by configure.  */
    /* config.h.in.  Generated from configure.ac by autoheader.  */
    
    /* Define to 1 if you have the <dlfcn.h> header file. */
    #define HAVE_DLFCN_H 1
    
    /* Define if you have the iconv() function and it works. */
    /* #undef HAVE_ICONV */
    
    /* Define to 1 if you have the <inttypes.h> header file. */
    #define HAVE_INTTYPES_H 1
    
    /* Define to 1 if using pthread is enabled. */
    #define HAVE_LIBPTHREAD 0
    
    /* Define to 1 if you have the <memory.h> header file. */
    #define HAVE_MEMORY_H 1
    
    /* Define to 1 if using libpng is enabled. */
    #define HAVE_PNG 0
    
    /* Define to 1 if using SDL is enabled. */
    /* #undef HAVE_SDL */
    
    /* Define to 1 if you have the <stdint.h> header file. */
    #define HAVE_STDINT_H 1
    
    /* Define to 1 if you have the <stdlib.h> header file. */
    #define HAVE_STDLIB_H 1
    
    /* Define to 1 if you have the `strdup' function. */
    #define HAVE_STRDUP 0
    
    /* Define to 1 if you have the <strings.h> header file. */
    #define HAVE_STRINGS_H 1
    
    /* Define to 1 if you have the <string.h> header file. */
    #define HAVE_STRING_H 1
    
    /* Define to 1 if you have the <sys/stat.h> header file. */
    #define HAVE_SYS_STAT_H 1
    
    /* Define to 1 if you have the <sys/types.h> header file. */
    #define HAVE_SYS_TYPES_H 1
    
    /* Define to 1 if you have the <unistd.h> header file. */
    #define HAVE_UNISTD_H 1
    
    /* Define to the sub-directory where libtool stores uninstalled libraries. */
    #define LT_OBJDIR ".libs/"
    
    /* Major version number */
    #define MAJOR_VERSION 4
    
    /* Micro version number */
    #define MICRO_VERSION 2
    
    /* Minor version number */
    #define MINOR_VERSION 0
    
    /* Name of package */
    #define PACKAGE "qrencode"
    
    /* Define to the address where bug reports for this package should be sent. */
    #define PACKAGE_BUGREPORT ""
    
    /* Define to the full name of this package. */
    #define PACKAGE_NAME "QRencode"
    
    /* Define to the full name and version of this package. */
    #define PACKAGE_STRING "QRencode 4.0.2"
    
    /* Define to the one symbol short name of this package. */
    #define PACKAGE_TARNAME "qrencode"
    
    /* Define to the home page for this package. */
    #define PACKAGE_URL ""
    
    /* Define to the version of this package. */
    #define PACKAGE_VERSION "4.0.2"
    
    /* Define to 1 if you have the ANSI C header files. */
    #define STDC_HEADERS 1
    
    /* Version number of package */
    #define VERSION "4.0.2"
    
    /* Define to empty if `const' does not conform to ANSI C. */
    /* #undef const */
    
    /* Define to `__inline__' or `__inline' if that's what the C compiler
       calls it, or to nothing if 'inline' is not supported under any name.  */
    #ifndef __cplusplus
    /* #undef inline */
    #endif
    
    /* Define to 'static' if no test programs will be compiled. */
    #define STATIC_IN_RELEASE static
    /* #undef WITH_TESTS */
       

    新写一个头文件,把代码弄成平台无关性。

    #ifndef __MY_QRCODE_H__
    #define __MY_QRCODE_H__
    
    #ifdef __cplusplus
    extern "C"
    {
    #endif
    
    
    #define MY_free free
    #define MY_malloc malloc
    #define MY_calloc(n, s) malloc(n*s)
    #define MY_re_malloc(a, b, c) realloc(a, b + c)
    
    
    #if IS_SUPPORT_TFT_SCREEN
    
    #define MY_DELETE_THIS  (0)
    #define HAVE_CONFIG_H        (1)
    
    #ifndef EINVAL
    #define EINVAL   22
    #endif
    
    #endif
    #ifdef __cplusplus
    }
    #endif
    
    
    #endif

    下面是自己写的Makefile

    all:my_qrcode.so
        gcc bitstream.c  mask.c  mmask.c  mqrspec.c  qrencode.c  qrinput.c  qrspec.c  rsecc.c  split.c -fPIC -shared -o $@
        strip $@

    qrencode 本身是不依赖于 libpng 库的。所以不存在什么缺少 png.h 的问题。按照本文介绍的方法按部就班的做就能生成静态库,不存在任何问题。编译时一定要排除qrenc.c 这个文件。这个文件是 qrencode 的一个使用例子,与这个库本身无关。

    生成了libqrencode.a的一个静态库,再配qrencode.h这个头文件,就可以在项目中使用了。

    qrenc.c 这个文件是 qrencode 的一个使用例子,与这个库本身无关。现在写一个库的使用例子:

    QRcode *MY_QRCODE_encode(const unsigned char *intext, int length)
    {
        QRcode *code;
    
        code = QRcode_encodeString((char *)intext, version, level, hint, casesensitive);
    
    
        return code;
    }
    
    
    static int my_writeSVG(const QRcode *qrcode)
    {
    
        unsigned char *row, *p;
        int x, y;
    
        /* Write data */
        p = qrcode->data;
        for(y = 0; y < qrcode->width; y++) {
            row = (p+(y*qrcode->width));
    
            if( !rle ) {
                /* no RLE */
                for(x = 0; x < qrcode->width; x++) {
                    printf(" %d ", *(row+x)&0x1 );
                }
    
                printf("
    ");
            }
        }
    
    
        return 0;
    }
    
    void my_draw_qrcode(const unsigned char *intext, int length)
    {
        QRcode *qrcode = NULL;
    
        qrcode = MY_QRCODE_encode(intext, length);
        if(qrcode == NULL) {
    return;
        }
    
        feitian_writeSVG(qrcode);
    
        QRcode_free(qrcode);
    qrcode = NULL; }
    int main(int argc, char *argv[]) { my_draw_qrcode(argv[1], strlen(argv[1])); return 0; }

     

     

     

  • 相关阅读:
    maven只编译某个module
    idea中java文件不显示成class标识符
    服务系统要点
    shell命令
    shell中的exit
    性能统计方法
    聚类
    java 外部类可以访问嵌套类的私有成员
    SqlServer动态生成临时表
    优化JavaScript脚本的性能(转载)
  • 原文地址:https://www.cnblogs.com/LiuYanYGZ/p/12718058.html
Copyright © 2020-2023  润新知