1. 程式人生 > >Qt淺談之三十二二維碼條形碼解析

Qt淺談之三十二二維碼條形碼解析

一、簡介

        二維條碼/二維碼(2-dimensional bar code)是用某種特定的幾何圖形按一定規律在平面(二維方向上)分佈的黑白相間的圖形記錄資料符號資訊的,其應用廣泛,如:產品防偽/溯源、廣告推送、網站連結、資料下載、商品交易、定位/導航、電子憑證、車輛管理、資訊傳遞、名片交流、wifi共享等。
     一維碼是用條空在水平方向上表達資訊的條碼,外形更接近矩形;二維碼可以說是正方形,在其內部有三個“回”字型的定位點,可以幫助條碼裝置對焦,便於讀取資料。一維碼的資訊部分只能是字母和數字,它的資料容量較小一般只可容納30個字元左右。二維碼的資訊承載量很大,最大資料含量可達1850個字元,資訊內容可包含,字母,數字,漢字,字元,片假名等。一維碼的常用碼制包括:EAN碼、39碼、交叉25碼、UPC碼、128碼、93碼,ISBN碼,及Codabar(庫德巴碼)等;二維碼常用的碼制有:PDF417二維條碼,Datamatrix二維條碼,QR Code,Code 49,Code 16K,Code one等。



二、詳解

1、libqrencode庫(生成二維碼)

(1)qrcodewidget.h

#ifndef QRCODE_H
#define QRCODE_H

#include <QWidget>
#include <QTextCodec>

namespace Ui {
class QRCode;
}

class QRCodeWidget : public QWidget
{
    Q_OBJECT

public:
    explicit QRCodeWidget(QWidget *parent = 0);
    ~QRCodeWidget();

private slots:
    void on_pushButton_clicked();

private:
    Ui::QRCode *ui;
};

#endif // QRCODE_H

(2)qrcodewidget.cpp

#include <QPicture>
#include "qrcodewidget.h"
#include "ui_qrcode.h"
#include "qrencode.h"
#include "qrenc.c"

QRCodeWidget::QRCodeWidget(QWidget *parent) :
    QWidget(parent, Qt::Dialog),
    ui(new Ui::QRCode)
{
    QTextCodec *codec = QTextCodec::codecForName("utf8");
    QTextCodec::setCodecForLocale(codec);
    QTextCodec::setCodecForCStrings(codec);
    QTextCodec::setCodecForTr(codec);
    ui->setupUi(this);
}

QRCodeWidget::~QRCodeWidget()
{
    delete ui;
}

void QRCodeWidget::on_pushButton_clicked()
{
    QString info = ui->lineEdit->text();
    if (info.isEmpty()) {
        return;
    }
    char outfile[] = "output.png";
    margin = 2;
    ::size = 7;
    version = 2;
    //QRcode *qrcode = QRcode_encodeString(info.toStdString().data(), 2, QR_ECLEVEL_L, QR_MODE_8, 0);
    //writePNG(qrcode, outfile);

    qrencode((unsigned char *)info.toStdString().data(), info.length(), outfile);
    ui->label_3->setPixmap(QPixmap(outfile));
}

(3)main.cpp

#include "qrcodewidget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QRCodeWidget w;
    w.show();

    return a.exec();
}

(4)執行

           

       也可是使用QrenCode 的命令列工具生成二維碼,在centos6.6下執行# yum install qrencode(或下載qrencode-3.4.4.tar.gz使用./configure、make、make install安裝);使用qrencode -o output.png https://www.baidu.com/即可在當前目錄下生成百度的二維碼圖片output.png;若想自定義尺寸的話,加上 -s 引數,比如 -s 6 表示尺寸為 6x6 平方像表大小,qrencode -s 6 -o output.png https://www.baidu.com/。命令列下識別二維碼的是#yum install libdecodeqr-examples,libdecodeqr-simpletest <二維碼圖片>。安裝zbar-0.10.tar.bz2,也可一識別二維碼。

      

2、zbar庫(識別二維碼)

/usr/local/include下,庫檔案在/usr/local/lib。
(1)qrcodezbar.h
#ifndef QRCODEZBAR_H
#define QRCODEZBAR_H

#include <QWidget>
#include <QTextCodec>
#include <QFileDialog>
#include <zbar/QZBar.h>

namespace Ui {
class QZbar;
}


class QRCodeZbar : public QWidget
{
    Q_OBJECT

public:
    QRCodeZbar(QWidget *parent = 0);
    ~QRCodeZbar();

private:


private slots:
    void on_pushButton_clicked();

private:
    Ui::QZbar *ui;
    zbar::QZBar *qz;
};

#endif // QRCODEZBAR_H
(2)qrcodezbar.cpp
#include "qrcodezbar.h"
#include "ui_qzbar.h"
#include "scanimage.h"
#ifdef QRDECODE
    #include "scanimagemagick.h"
#endif

QRCodeZbar::QRCodeZbar(QWidget *parent)
    : QWidget(parent, Qt::Dialog)
    , ui(new Ui::QZbar)
{
    QTextCodec *codec = QTextCodec::codecForName("utf8");
    QTextCodec::setCodecForLocale(codec);
    QTextCodec::setCodecForCStrings(codec);
    QTextCodec::setCodecForTr(codec);
    ui->setupUi(this);
}

QRCodeZbar::~QRCodeZbar()
{

}

void QRCodeZbar::on_pushButton_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(this, tr("choose a picture"),
                                                    QApplication::applicationDirPath(),
                                                    tr("all Files (*.*)"));
    ui->lineEdit->setText(fileName);
    ui->label_3->setPixmap(QPixmap(ui->lineEdit->text()));
    char result[1024] = {0};
    #ifdef QRDECODE
        scanimagemagick(ui->lineEdit->text().toStdString().data(), result);
    #else
        scanimage(ui->lineEdit->text().toStdString().data(), result);
    #endif
    ui->textEdit->setText(result);
}
(3)scanimagemagick.h
#ifndef SCANIMAGEMAGICK_H
#define SCANIMAGEMAGICK_H
#include <iostream>
#include <Magick++.h>
#include <zbar.h>
#define STR(s) #s
/*****************
 * yum install ImageMagick
 ***********/
using namespace std;
using namespace zbar;

int scanimagemagick (const char *filename, char *result);

#endif // SCANIMAGE_H
(4)scanimagemagick.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "scanimagemagick.h"

int scanimagemagick(const char *filename, char *result)
{
#ifdef MAGICK_HOME
    // http://www.imagemagick.org/Magick++/
    //    under Windows it is necessary to initialize the ImageMagick
    //    library prior to using the Magick++ library
    Magick::InitializeMagick(MAGICK_HOME);
#endif

    // create a reader
    ImageScanner scanner;

    // configure the reader
    scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);

    // obtain image data
    Magick::Image magick(filename);  // read an image file
    int width = magick.columns();   // extract dimensions
    int height = magick.rows();
    Magick::Blob blob;              // extract the raw data
    magick.modifyImage();
    magick.write(&blob, "GRAY", 8);
    const void *raw = blob.data();

    // wrap image data
    Image image(width, height, "Y800", raw, width * height);

    // scan the image for barcodes
    int n = scanner.scan(image);

    // extract results
    for(Image::SymbolIterator symbol = image.symbol_begin();
        symbol != image.symbol_end();
        ++symbol) {
        // do something useful with results
//        cout << "decoded " << symbol->get_type_name()
//             << " symbol \"" << symbol->get_data() << '"' << endl;
        sprintf(result, "%s:%s", symbol->get_type_name().data(), symbol->get_data().data());
    }

    // clean up
    image.set_data(NULL, 0);

    return(0);
}
(5)執行結果
 
(6)
(7)提示
       開啟編譯選項DEFINES *= QRDECODE,則使用了ImageMagick,則需要安裝#yum install ImageMagick,並加入標頭檔案路徑/usr/include/ImageMagick/。若不是用QRDECODE,用C庫,再識別有些png檔案時會出現段錯誤。上述zbar有中文亂碼,可參考網上修改。

3、QZxing庫(識別二維碼)

        從http://sourceforge.net/projects/qzxing/files/下載QZxing的decoding library的原始碼,在工程中加入include(QZXing_sourceV2.3/QZXing.pri)。
(1)qrcondezxing.h

#ifndef QRCONDEZXING_H
#define QRCONDEZXING_H

#include <QWidget>
#include <QTextCodec>
#include <QFileDialog>

namespace Ui {
class QRCondeZxing;
}

class QRCondeZxing : public QWidget
{
    Q_OBJECT

public:
    explicit QRCondeZxing(QWidget *parent = 0);
    ~QRCondeZxing();

private slots:
    void on_pushButton_clicked();

private:
    Ui::QRCondeZxing *ui;
};

#endif // QRCONDEZXING_H
(2)qrcondezxing.cpp
#include "qrcondezxing.h"
#include "ui_qrcondezxing.h"
#include "QZXing.h"

QRCondeZxing::QRCondeZxing(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::QRCondeZxing)
{
    QTextCodec *codec = QTextCodec::codecForName("utf8");
    QTextCodec::setCodecForLocale(codec);
    QTextCodec::setCodecForCStrings(codec);
    QTextCodec::setCodecForTr(codec);
    ui->setupUi(this);
}

QRCondeZxing::~QRCondeZxing()
{
    delete ui;
}

void QRCondeZxing::on_pushButton_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(this, tr("choose a picture"),
                                                    QApplication::applicationDirPath(),
                                                    tr("all Files (*.*)"));
    ui->lineEdit->setText(fileName);
    ui->label_3->setPixmap(QPixmap(ui->lineEdit->text()));
    QZXing decoder;
    QString qrmsg = decoder.decodeImageFromFile(ui->lineEdit->text());
    ui->textEdit->setText(qrmsg);
}
(3)執行結果:

 

三、條形碼/二維碼開源軟體

(1)二維碼掃描工具和開發包ZBar
        ZBar是款桌面電腦用條形碼/二維碼掃描工具,支援攝像頭及圖片掃描,支援多平臺包括 iPhone 手機。同時 ZBar 提供了二維碼掃描的 API 開發包。 ZBar 目前支援掃描,除了 Windows 平臺外,還支援 Linux 及 iPhone 平臺。網址:http://zbar.sourceforge.net
(2)C語言二維條形碼解析庫libqrencode
        libqrencode (QRencode) 是一個用C語言編寫的用來解析二維條形碼(QR Code)的程式庫,libqrencode通過手機的CCD攝像頭來掃描二維條形碼。網址:http://zbar.sourceforge.net
(3)條形碼掃描軟體 Zebra barcode reader
        Zebra barcode reader是一個小型的,分層次的條形碼掃描軟體。它支援許多流行的條碼符號:EAN,UPC,128碼,39碼等。能抓獲條碼解碼影象和使用視訊裝置(如攝像頭)作為一個條形碼掃描器。
(4)QZXing

四、總結

(1)二維碼和條形碼的開源軟體種類很多,可針對C、Java、ios等不同介面來選擇自己的需求。
(2)二維碼的庫在中文方面的也是有支援的。
(3)原始碼使用中僅僅進行了簡單的呼叫,沒有實現更深層次的開發,主要是自己沒有專案需求,其他的開發讀者可繼續開發。
(4)若有建議,請留言,在此先感謝!