Qtの応用 - QRコード
概要
QRコード (Quick Response Code) は1994年にデンソーウェーブによって開発された2次元バーコードである。
従来の1次元バーコードと比較して、縦横両方向に情報を持つため、より多くのデータを格納できる特徴がある。
英数字で最大約4300文字、漢字で約1800文字までの情報を記録でき、誤り訂正機能によりコードの一部が汚れたり破損したりしても読み取りが可能である。
また、360度どの角度からでもスキャンでき、高速な読み取りが可能である。
当初は自動車部品の管理用に開発されたが、現在では商品管理、マーケティング、決済、身分証明等、幅広い用途で活用されている。
特に、スマートフォンの普及により、URLやテキスト情報の共有手段として一般的になっている。
C++で利用可能なQRコードライブラリについて、それぞれの特徴を以下に示す。
これらのライブラリの多くは、エラー処理、バージョン管理、マルチスレッド対応等、実務で必要となる機能も備えている。
また、ZXing-C++ライブラリは機能が豊富である反面、学習曲線が比較的急である。
libqrencodeライブラリは単一機能に特化しているため、導入が容易である。
- ZXing-C++ライブラリ
- URL : https://github.com/zxing-cpp/zxing-cpp
- ライセンス : Apache 2.0
- JavaのZXing (Zebra Crossing) をC++に移植したライブラリである。
- QRコードの読み取りと生成の両方に対応しており、広範なバーコードフォーマットをサポートしている。
- オープンソースであり、活発なコミュニティによって継続的にメンテナンスされている。
- QZXingライブラリ
- URL : https://github.com/ftylitak/qzxing
- ライセンス : Apache 2.0
- Qtでの使用に最適化されたQRコードライブラリである。
- ZXingをベースにしているが、Qtフレームワークとの統合が強化されている。
- QMLからの直接利用が可能であり、特に、モバイルアプリケーション開発に適している。
- また、カメラフィードからのリアルタイムデコードにも対応している。
- libqrencodeライブラリ
- URL : https://fukuchi.org/works/qrencode/ , https://github.com/fukuchi/libqrencode
- ライセンス : LGPL 2.1
- QRコード生成に特化したライブラリであり、高速な処理と高品質な出力が特徴である。
- CベースでC++からも容易に利用可能で、PNG形式での出力やSVGフォーマットもサポートしている。
- 様々な誤り訂正レベルや符号化モードに対応しており、マイクロQRコードの生成も可能である。
- また、サイズの最適化や構造化追加等の機能も備えている。
- QuickQRライブラリ
- URL : https://quickqr.art/ , https://quickqr.art/app/subscription
- ライセンス : -
- 最近のC++で記述された新しいライブラリであり、QRコードの生成に特化している。
- テンプレートベースの設計により、コンパイル時の最適化が可能である。
- また、カスタマイズ性が高く、様々なスタイルやデザインのQRコードを生成することができる。
- Quirc
- URL : https://github.com/dlbeer/quirc
- ライセンス : ISC
- 軽量で高速なQRコードデコーダライブラリである。
- 組み込みシステムやリソースが制限された環境での使用に適している。
- APIがシンプルなため、直感的な使用が可能である。
- ただし、QRコードの生成機能は無い。
ZXing-C++ライブラリ
ZXing-C++ライブラリとは
ZXing-C++ライブラリは、JavaベースのZXingバーコードライブラリをC++に移植したオープンソースプロジェクトである。
1次元および2次元バーコードの読み取りと生成を可能にするツールを提供している。
QRコード、データマトリックス、Code 128、UPC、EAN、および他の一般的なバーコード形式をサポートしている。
また、異なる角度や歪みがある場合でもバーコードを認識できる堅牢な検出アルゴリズムを実装している。
モジュール性を重視して設計されており、コア機能とプラットフォーム固有の実装を明確に分離している。
これにより、PC、モバイル、組み込みシステム等の様々なプラットフォームでの使用が容易である。
ライブラリのメリットとして、C++11以降の現代的な機能を活用していること、外部依存関係が最小限であること、クロスプラットフォーム対応が挙げられる。
最適化されたアルゴリズムとC++の特性を活かした実装により、高速な処理を実現している。
特に、OpenCVとの統合が可能であり、画像処理パイプラインに組み込むことができる。
カメラからのリアルタイムスキャン、画像ファイルからのバーコード読み取り、バーコードの生成等ができ、
実務では、在庫管理システム、モバイルアプリのQRコードリーダー、チケット認証システム等で広く使用されている。
対応しているフォーマットを以下に示す。
1D product | 1D industrial | 2D |
---|---|---|
UPC-A | Code 39 | QRコード |
UPC-E | Code 93 | Data Matrix |
EAN-8 | Code 128 | Aztec |
EAN-13 | Codebar | PDF 417 |
UPC/EAN Extension 2/5 | ITF | MaxiCode |
RSS-14 | ||
RSS-Expanded |
なお、ZXing-C++ライブラリのライセンスは、Apache-2.0となっている。
ZXing-C++ライブラリのインストール
パッケージ管理システムからインストール
# RHEL sudo dnf install zxing-cpp-devel # SUSE sudo zypper install zxing-cpp-devel
ソースコードからインストール
ZXing-C++ライブラリのビルドに必要なライブラリをインストールする。
# RHEL sudo dnf install make cmake gcc gcc-c++ stb-devel \ opencv-devel # ZXing向けOpenCVのサンプルコードもインストールする場合 qt6-qtbase-devel qt6-qtmultimedia-devel # Qt向けのサンプルコードもインストールする場合 # SUSE sudo zypper install make cmake gcc gcc-c++ stb-devel \ opencv-devel # ZXing向けOpenCVのサンプルコードもインストールする場合 qt6-gui-devel qt6-quick-devel qt6-multimedia-devel # Qt向けのサンプルコードもインストールする場合
br>
ZXing-C++のGithubにアクセスして、ソースコードをダウンロードする。
ダウンロードしたファイルを解凍する。
tar xf zxing-cpp-<バージョン>.tar.gz cd zxing-cpp-<バージョン>
または、git clone
コマンドを使用してソースコードをダウンロードする。
git clone https://github.com/zxing-cpp/zxing-cpp.git
ZXing-C++ライブラリをビルドおよびインストールする。
mkdir build && cd build cmake -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=<ZXing-C++のインストールディレクトリ> \ .. make -j $(nproc) make install
CMakeLists.txtファイルの設定
find_package(ZXing REQUIRED)
target_link_libraries(<プロジェクト名> PRIVATE
ZXing::ZXing
)
QRコードの読み込み
まず、QImageクラスを使用して画像ファイルを読み込む。
QImageクラスでは、PNG、JPEG、BMP、GIF等の一般的な画像形式に対応している。
#include <ZXing/MultiFormatReader.h>
#include <ZXing/BitMatrix.h>
#include <ZXing/BarcodeFormat.h>
#include <ZXing/ReadResult.h>
// ZXingライブラリのフォワード宣言
namespace ZXing {
class MultiFormatReader;
}
// ZXingライブラリのインスタンス
std::unique_ptr<ZXing::MultiFormatReader> reader;
QImage image(filePath);
// 画像の読み込みに失敗した場合
// ファイルが存在しない場合や破損している場合等
if (image.isNull()) {
qDebug() << "画像の読み込みに失敗 : " << filePath;
return QString();
}
次に、読み込んだ画像の幅と高さを取得する。
これらの値は、ピクセル単位で表される。
int width = image.width();
int height = image.height();
ZXingライブラリで処理するためのピクセルバッファを作成する。
そして、画像の各ピクセルをグレースケールに変換する。
// uint8_tは8ビット(0-255)のグレースケール値を格納するために使用
// 配列サイズは width * height (総ピクセル数)
std::vector<uint8_t> pixels(width * height);
// 画像の各ピクセルをグレースケールに変換
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
// QRgbはQtのRGB値を表す型(32ビット整数)
QRgb pixel = image.pixel(x, y);
// qGray関数でRGB値をグレースケール(0-255)に変換
// 変換式: Gray = (R * 11 + G * 16 + B * 5) / 32
// 1次元配列のインデックスに変換: y * width + x
pixels[y * width + x] = qGray(pixel);
}
}
ZXingのImageViewオブジェクトを生成する。
ZXing::ImageViewの第4引数 (ImageFormat) で指定可能な値
- ZXing::ImageFormat::Lum
- 輝度 (Luminance) のみの画像フォーマット
- 8ビットグレースケールであり、最も一般的で処理が高速である。
- そのため、QRコード読み取りに最適である。
- ZXing::ImageFormat::RGB
- RGBカラー形式で、各ピクセルは24ビット (R:8bit、G:8bit、B:8bit)
- ただし、メモリ使用量が多い。
- ZXing::ImageFormat::BGR
- BGRカラー形式
- RGBと同様だが、バイト順が逆となる。
- Windowsのビットマップ等で使用されている。
- ZXing::ImageFormat::RGBX
- RGBにアルファチャンネルを加えた32ビット形式
- アルファ値は無視される。
- ZXing::ImageFormat::BGRX
- BGRにアルファチャンネルを加えた32ビット形式
- アルファ値は無視される。
- ZXing::ImageFormat::XRGB
- パディングバイトの後にRGBが続く形式
- ZXing::ImageFormat::XBGR
- パディングバイトの後にBGRが続く形式
画像フォーマットの指定において、QRコード読み取りの場合は、Lumが最適 (処理が高速で十分な情報量) である。
メモリ使用量を考慮する場合は、Lumが推奨される。
カラー情報が必要な場合は、RGBまたはBGRを使用する。
元画像のフォーマットに合わせて選択することにより、変換のオーバーヘッドを削減できる。
// 第1引数 : ピクセルデータへのポインタ
// 第2引数 : 画像の幅 (ピクセル)
// 第3引数 : 画像の高さ (ピクセル)
// 第4引数 : 画像フォーマット (下記参照)
ZXing::ImageView imageView(pixels.data(), width, height, ZXing::ImageFormat::Lum);
最後に、QRコードの読み取りを行う。
// ZXing::MultiFormatReader::readメソッドは、ZXing::ReadResult型を返す
auto result = reader->read(imageView);
// 読み取り結果が有効な場合、テキストを返す
// 無効な場合は空のQStringを返す
if (result.isValid()) {
return QString::fromStdString(result.text());
}
QRコードの生成
#include <ZXing/MultiFormatWriter.h>
#include <ZXing/BitMatrix.h>
#include <ZXing/BarcodeFormat.h>
#include <ZXing/ReadResult.h>
// ZXingライブラリのフォワード宣言
namespace ZXing {
class MultiFormatWriter;
}
// ZXingライブラリのインスタンス
std::unique_ptr<ZXing::MultiFormatWriter> writer;
まず、QRコード生成のオプションを設定する。
対応するバーコードフォーマット
- ZXing::BarcodeFormat::QR_CODE
- QRコード
- ZXing::BarcodeFormat::DATA_MATRIX
- データマトリックス
- ZXing::BarcodeFormat::AZTEC
- Aztecコード
- ZXing::BarcodeFormat::PDF_417
- PDF417
- ZXing::BarcodeFormat::CODE_128
- CODE 128
- ZXing::BarcodeFormat::CODE_39
- CODE 39
- ZXing::BarcodeFormat::EAN_13
- EAN-13
- ZXing::BarcodeFormat::EAN_8
- EAN-8
- ZXing::BarcodeFormat::UPC_A
- UPC-A
- ZXing::BarcodeFormat::UPC_E
- UPC-E
エラー訂正レベル
- ZXing::ErrorCorrectionLevel::Low
- 約7%のエラー訂正
- ZXing::ErrorCorrectionLevel::Medium
- 約15%のエラー訂正
- ZXing::ErrorCorrectionLevel::Quality
- 約25%のエラー訂正
- ZXing::ErrorCorrectionLevel::High
- 約30%のエラー訂正
その他の主要なオプション
- options.characterSet
- 文字エンコーディング ("UTF-8", "Shift_JIS"等)
- options.quietZone
- 余白サイズ (-1で自動)
- options.autoColor
- 自動色設定 (true / false)
- options.foregroundColor
- 前景色 (QRコードの色)
- options.backgroundColor
- 背景色
QRコード特有のオプション
- options.qrVersion
- QRコードのバージョン (1〜40)
- options.qrMaskPattern
- マスクパターン (0〜7)
- options.minVersion
- 最小バージョン
- options.maxVersion
- 最大バージョン
ZXing::MultiFormatWriter::Option options;
// バーコードのフォーマットを指定
// QR_CODE以外にも複数のフォーマットが指定可能 (前述)
options.format = ZXing::BarcodeFormat::QR_CODE;
// QRコードの余白 (Quiet Zone) のサイズを指定
// 単位はモジュール (QRコードの最小単位となる点)
// 一般的な値は1〜4, 小さすぎると読み取りが困難になる
options.margin = 2;
// QRコードの出力サイズを指定 (ピクセル単位)
// width : 横幅, height : 高さ
// 大きすぎると処理時間が増加, 小さすぎると読み取りが困難
// 一般的な最小サイズは、21x21ピクセル
// 推奨サイズは、200x200〜1000x1000ピクセル
options.width = width;
options.height = height;
// エンコードオプション (追加可能なオプション)
// options.eccLevel = ZXing::ErrorCorrectionLevel::Medium; // エラー訂正レベル
// 高いレベルほどQRコードの損傷に強い
// ただし、データ容量は減少
// 一般用途ではMediumが推奨
// options.characterSet = "UTF-8"; // 文字エンコーディング
// 日本語を含む場合はUTF-8またはShift_JISを指定
// 英数字のみの場合は指定不要
// options.quietZone = -1; // 余白サイズ (-1で自動)
// 最低でも4モジュール分必要
// 読み取り環境が悪い場合は多めに設定
次に、任意の文字列データをQRコードにエンコードする。
// 戻り値のmatrixはビット行列 (BitMatrix) 形式
// 各ビットが黒 (true) か 白 (false) を表す
auto matrix = writer->encode(text.toStdString(), options);
// QRコードを描画するためのQImage作成
// Format_RGB32 : 32ビットRGBフォーマット (8bitずつR, G, B, 予約)
QImage image(width, height, QImage::Format_RGB32);
// 背景を白で塗りつぶし
image.fill(Qt::white);
// BitMatrixをQImageに変換
for (int y = 0; y < matrix.height(); y++) {
for (int x = 0; x < matrix.width(); x++) {
// matrix.get(x, y)がtrueの場合、その点は黒
if (matrix.get(x, y)) {
// 黒色のピクセルを設定(R=0, G=0, B=0)
image.setPixel(x, y, qRgb(0, 0, 0));
}
// falseの場合は白のまま
}
}
最後に、QRコード画像をファイルに保存する。
対応している画像形式は、PNG、JPEG、BMP等がある。
// 戻り値 : 保存成功でtrue, 失敗でfalse
image.save(filePath);