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("\r\n");
        }
    }


    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; }

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM