【SPOONsoftware
QRプロジェクト ソース等説明書】
SPOONsoftware
QRプロジェクト
ソース等説明書
Ver1.00-01
目次
1.はじめに 5
1.1.使用制限および免責 5
1.2.バグのご報告のお願い 5
1.3.その他の注意事項 5
2.ソース概要 6
2.1.前提条件 6
2ファイル構成 6
2.2.CQRMatrixクラス 7
2.2.1.publicな関数 8
2.2.1.1.CQRMatrix() 8
2.2.1.2.~CQRMatrix() 8
2.2.1.3.bool AddQRCharacters( const char * pcszString , int iCharacterType ) 9
2.2.1.4.bool MakeQRMatrix( int iCollectLevel , int & iErrorType ) 10
2.2.1.5.int GetTypeNumber() 11
2.2.1.6.int GetModuleNumber() 11
2.2.1.7.bool IsDarkPoint( int iColumnIndex , int iRowIndex ) 11
2.2.2.protected関数 12
2.2.2.1.void ReleaseAll(); 12
2.2.2.2.void ReleaseQRMatrix(); 12
2.2.2.3.void ReleaseMaskMatrix(); 12
2.2.2.4.void ReleaseData(); 12
2.2.2.5.void ReleaseError(); 12
2.2.2.6.bool GetDataBitNumber( int & iDataBit1_9 , int & iDataBit10_26 , int & iDataBit27_40 ); 13
2.2.2.7.bool CreateDataBits( int & iErrorType ); 14
2.2.2.8.unsigned char GetBitMask( int iBitNumber ); 14
2.2.2.9.bool SetTypeNumber(int iCollectLevel , int & iErrorType ); 15
2.2.2.10.bool InitModuleArea(int & iErrorType); 16
2.2.2.11.bool SetPositionDitectPattern( int & iErrorType ); 16
2.2.2.12.bool SetPositionCheckPattern( int & iErrorType ); 17
2.2.2.13.bool SetTimingPattern( int & iErrorType ); 18
2.2.2.14.bool SetTypeInformation( bool bReserveOnly , int & iErrorType ); 19
2.2.2.15.bool SetModelInformation( int & iErrorType ); 21
2.2.2.16.bool CreateMaskPatternArea( int & iErrorType ); 22
2.2.2.17.bool AddDataBits( unsigned char ucData , int iBitNumber , int & iErrorType ); 23
2.2.2.18.bool AddDataBits( unsigned short usData , int & iErrorType ); 24
2.2.2.19.bool AddDataBits_Numeric( const char * pcszData , int iDataLength , int & iErrorType ); 25
2.2.2.20.bool AddDataBits_Alphabet( const char * pcszData , int iDataLength , int & iErrorType ); 27
2.2.2.21.bool AddDataBits_Ascii( const char * pcszData , int iDataLength , int & iErrorType ); 29
2.2.2.22.bool AddDataBits_Kanji( const char * pcszData , int iDataLength , int & iErrorType ); 30
2.2.2.23.bool OutputDataBits( int & iErrorType ); 30
2.2.2.24.unsigned char GetDataBit( int iBitIndex , bool bDataRequest ); 30
2.2.2.25.bool GetNextDataPutPoint( int & iColumnIndex , int & iRowIndex, bool & bFirstColumn, bool & bDirectionUp ); 30
2.2.2.26.bool DecideMaskPattern( int & iErrorType ); 30
2.2.2.27.int GetLostPoint_SeqModule( int iSeqBlock ); 30
2.2.2.28.int GetLostPoint_ModuleBlock( int iColumnIndex , int iRowIndex ); 30
2.2.2.29.int GetLostPoint_PositionDitect( int iColumnIndex , int iRowIndex ); 30
2.2.2.30.int GetLostPoint_BlackWhiteRatio( int iBlackPoint ); 30
2.2.2.31.bool CreateErrorCollectData( int & iErrorType ); 30
2.2.2.32.bool SeparateTotalNumber( int iSeparateCount , int iTotalNumber, int & iFirstCount , int & iFirstNumber , int & iSecondCount , int & iSecondNumber ); 30
2.2.2.33.inline bool SetModulePoint( int iColumnIndex , int iRowIndex , int iQRPoint ) 30
2.2.2.34.inline int GetModulePoint( int iColumnIndex , int iRowIndex ) 30
2.2.2.35.inline int GetMaskPoint( int iColumnIndex , int iRowIndex , int iQRMaskPattern = -1) 30
2.2.2.36.bool GetExpressionMod( unsigned char *puszBaseData , int iBaseDataLength, unsigned char *puszCoefficients , unsigned char *puszError , int iErrorLength ); 30
2.2.3.protected変数 30
2.2.3.1.list<CQRDataElement> m_listQRData; 30
2.2.3.2.char ** m_ppucQRMatrix; 30
2.2.3.3.char ** m_ppucMaskMatrix; 30
2.2.3.4.int m_iModuleNumber; 31
2.2.3.5.int m_iModelTypeIndex; 31
2.2.3.6.int m_iDataBitNumber; 31
2.2.3.7.int m_iDataSizeNumber; 31
2.2.3.8.unsigned char * m_pucData; 31
2.2.3.9.int m_iErrorSizeNumber; 31
2.2.3.10.unsigned char * m_pucError; 31
2.2.3.11.int m_iQRMaskPattern; 31
2.3.CQRReadSolomonクラス 32
2.3.1.public関数 32
2.3.2.protected関数 32
2.3.3.protected変数 32
2.4.CQRDataElementクラス 33
2.4.1.public関数 33
2.4.2.protected関数 33
2.4.3.protected変数 33
2.5.QRInformation.h 33
2.5.1.STypeMatrix c_typeMatrix 33
2.5.2.short c_sPositionChecks 33
3.サンプルプログラムに関して 34
3.1.CommandSample.cpp 34
3.2.WindowsSample.cpp 35
3.3.GDSample.cpp 35
4.最後に 36
本QR出力プログラムはオープンソースとなっています。
ソースの改変を含む使用は自由に行なってくださってかまいません。本プログラムを使用する際は、プログラムの目的、有償・無償に関わらず弊社に通知なく使用していただいて構いません。使用するに際して、弊社モジュールを使用している旨をどこかに記載する必要もありません。
本プログラムを使用して生じた一切の不具合に対する責任を弊社は負いません。本プログラムを使用して作成されたQRコードが読み取り不可、あるいはコードの不良により読み取り結果が不正であり、それによって如何なる損害が発生した場合でも弊社はその責任を負いません。
本プログラムにバグがある場合には、ご報告いただければバグ修正を行い、通知させていただきたいと考えております。
また、プログラム自体に関する要望等があれば、その点に関してもお知らせください。とはいえプログラムの改変は自由に行って構いませんので、ご自身で改変したければそうしてくださって結構です。
バグの報告および改変要望があればこのプログラムをダウンロードしたWebサイトを御覧ください。その際、既知のバグおよび要望に関してご一読ください。
本プログラムは二次元コードシンボル−QRコード−基本仕様(JIS X 0510:2004)およびその正誤表を元に作成されています。
本プログラムはC++で書かれています。
本プログラムはWindows環境およびUNIX環境で動作することを目指して書かれていますが、標準的なC++を使用して書いてありますので、どの環境でも動作すると思われます。
Windowsコンパイラの警告メッセージに対応するため、strcpy,memcpy関数はstrcpy_s,mememcpy_s関数を使用しています。プリプロセッサマクロにWIN32がセットされている場合だけ、この関数を使用するようにしております。64bit環境等で使用する場合には、WIN32をセットすると、不都合かと思いますので、プログラム自体を改変してください。
また、Windowsでコンパイルするとき、cppファイルの先頭にstdafx.hをインクルードしないとうまくコンパイル出来ない場合があります。ソースファイル上のcppファイルにstdafx.hをインクルードするか、コンパイラの設定で「プリコンパイル済みヘッダーを使用しない」にして、回避してください。
最後に重要な点ですが、本プログラムでは1バイト文字、2バイト文字を扱う際に、以下のものとして扱っております。
1バイト文字:unsigned char
2バイト文字:unsigned short
以下のファイルからなっています。
ファイル名 |
ファイル説明 |
QRMatrix.h |
QRマトリックスコードを作成するためのクラスのヘッダファイル。 この本プログラムを使用するためには、このファイルをインクルードします。 |
QRMatrix.cpp |
QRマトリックスコードを作成するためのクラス本体ファイル。 |
QRReadSolomon.h |
QRのエラー訂正コードを生成するためのクラスのヘッダファイルおよび本体ファイル |
QRReadSolomon.cpp |
|
QRDataElement.h |
QRの出力データ情報を格納するためのデータクラスのヘッダーファイルおよび本体ファイル |
QRDataElement.cpp |
|
QRInformation.h |
QRデータを出力するためのデータ群。 |
QRReadSolomonInformation.h |
QRのエラー訂正コードを姿勢するためのデータ群。 |
本プログラムを使用する際には、使用するソースコード内で、QRMatrix.hをインクルードします。
インクルードすると、CQRMatrixクラスが使用可能となります。
基本的な使用の流れは以下のとおりとなります。
CQRMatrixのインスタンスを作成
例)CQRMatrix qrMatrix;
QRコードにしたい文字列をセット
例)qrMatrix.AddQRCharacters( "★" , QRCHARACTERTYPE_KANJI );
QRコードの作成
例)qrMatrix.MakeQRMatrix( COLLECTLEVEL_L , iErrorType);
QRの縦横サイズを取得(QRは正方形であるため、縦横のサイズは等しい)
例)int iNum = qrMatrix.GetModuleNumber();
QRの縦横サイズをループしてデータを1ドットずつ取得
例)for( int iRow=0; iRow<iNum; iRow++ ){
for( int iCol=0; iCol<iNuml; iCol++ ){
if( qrMatrix.IsDarkPoint( iCol, iRow ) )
{
<塗りつぶされている場合の処理>
}
{
<塗りつぶされない場合の処理>
}
}
}
詳しくはサンプルプログラムをご覧ください。
以下にCQRMatrixの仕様を記します。
コンストラクタ。各内部変数の初期化処理などを行う。
引数:なし
戻り値:なし
デストラクタ。内部変数の確保領域の開放などを行う。
引数:なし
戻り値:なし
QRコードに出力したい文字列を内部変数にセットするために使用する。
文字列は複数登録することも可能で、登録された文字列群は内部変数。
list<CQRDataElement> m_listQRData
に追加される(ただし、iCharacterTypeが最後に追加されたものと同一の場合には、m_listQRDataへの追加は行わず、最後の要素の文字列を追加する)
使用するユーザ側で文字タイプを指定する必要があるため、データの圧縮効率性などを念頭において使用することが必要となる。
引数:
pcszString (IN)
QRコードに出力する文字列へのポインタ。文字列はNULL終端であること。
iCharacterType (IN)
文字列の型をあらわすint型。QRコードでは4種類の文字列の出力が認められている。すなわち、数字文字列、アルファベット文字列、8ビット文字列、漢字文字列である。
iCharacterTypeは以下の定義されたマクロのいずれかを指定すること
QRCHARACTERTYPE_NUMERIC:数字文字列
QRCHARACTERTYPE_ALPHABET:アルファベット文字列
QRCHARACTERTYPE_ASCII:8ビット文字列
QRCHARACTERTYPE_KANJI:漢字文字列
※数字文字列は半角数字で指定すること。アルファベット文字列は大文字アルファベット、数字および数文字の記号のみの指定とすること。漢字文字列はシフトJISコードで指定すること。
戻り値:現状すべてtrueを返す。
指定された条件を使ってQRコード情報を作成する。
この関数を呼び出す前にAddQRCharactersを使用して、コード化したい全ての文字列を登録しておく必要がある。
引数:
iCollectLevel (IN)
QRコードのエラー訂正レベルを指定する。QRコードのエラー訂正レベルは4種類のレベルがあり、レベルによってエラー訂正を行うことが出来るコード数が異なる。精度の高いQRコードを作るにはエラー訂正レベルを上げる必要があるが、エラー訂正レベルを上げると、QRコード自体の大きさが大きくなる。QRコードのエラー訂正レベルはL,M.Q.Hの4種類があるが、一般的にはMを使用する。
iCollectLevelには以下の定義されたマクロのいずれかを指定すること。
COLLECTLEVEL_L:エラー訂正レベルL
COLLECTLEVEL_M:エラー訂正レベルM
COLLECTLEVEL_Q:エラー訂正レベルQ
COLLECTLEVEL_H:エラー訂正レベルH
iErrorType (OUT)
QRコードの作成に失敗した場合、失敗した原因を示すエラーコードが格納される。
エラーコードはQRMatrix.h内に定義されているQRERR_で始まるマクロで定義されている。
戻り値:
QRデータが正常に作成出来ればtrueを、失敗した場合にはfalseを返す。
失敗した場合には、iErrorTypeにエラーコードが登録される。
作成されたQRコードの型番を返す関数。この関数はMakeQRMatrixが成功した場合のみ有効となる。QRコードの型番は1型~40型と規定されており、それぞれの方でサイズが異なる。型は出力する文字列とその種類および、エラー訂正レベルによって決まってくる。
引数:なし
戻り値:作成されたQRコードの型番号(1~40)
作成されたQRコードのモジュール数を返す関数。この関数はMakeQRMatrixが成功した場合のみ有効となる。モジュール数とは縦横のサイズである。1型のQRコードであれば、21×21のモジュールがある。1型のQRコードで本関数を呼び出した場合には21が返る。
戻り値:作成されたQRコードのモジュール数
作成されたQRコードの指定位置が明か暗かを返す。この関数はMakeQRMatrixが成功した場合のみ有効となる。
引数:
iColumnIndex (IN)
チェックしたい列番号0~GetModuleNumber()-1の値を指定する。
iRowIndex (IN)
チェックしたい行番号0~GetModuleNumber()-1の値を指定する。
戻り値:
trueの場合、指定位置のデータが暗データであることを示す。
falseの場合、指定値のデータが名データであることを示す。
範囲外のデータが指定された場合にはfalseが返る。
クラス内で確保した全てのクラス変数のメモリをリリースする。デストラクタ内で呼び出される。
引数:なし
戻り値:なし
クラス変数m_ppucQRMatrixの確保領域を開放する
引数:なし
戻り値:なし
クラス変数m_ppucMaskMatrixの確保領域を開放する
引数:なし
戻り値:なし
クラス変数m_pucDataの確保領域を開放する
引数:なし
戻り値:なし
クラス変数m_puszErrorの確保領域を開放する
引数:なし
戻り値:なし
QRコードに出力するデータのビット数をカウントする
この処理は内部変数m_listQRDataに出力する文字列が全てセットされた後(セットするには、 2.2.1.3. bool AddQRCharacters( const char * pcszString , int iCharacterType )を使用する) 2.2.2.9. bool SetTypeNumber(int iCollectLevel , int & iErrorType );から呼び出される。
QRコードは複数の文字モードをサポートしているが、データを配置するに際し、それぞれのモードの先頭部分で、該当モードで何文字分の文字列を出力するかを指定している(この部分を仕様書上「文字数指定子」と呼んでいる)。この文字数指定子が、文字モードごとあるいはQRコードの型ごとに異なる。仕様書上からの抜粋を以下に示す。
文字数指定子のビット数
型番 |
数字モード |
英数字モード |
8ビットバイトモード |
漢字モード |
1〜9 |
10 |
9 |
8 |
8 |
10〜26 |
12 |
11 |
16 |
10 |
27〜40 |
14 |
13 |
16 |
12 |
このため、型が確定していない状態では文字数指定子が何ビットになるか分からないため、全体のデータが何ビットになるかも確定しない(逆に全体データが何ビットになるか分からないと、型番を決定できないというジレンマがある)。
そのため、本関数では、型番が1〜9までの場合のデータビット数、型番が10〜26間での場合のデータビット数、型番が27〜40までのデータビット数を分けて計算している(本関数が型番決定よりも前に呼ばれる関数であるため)
引数:
iDataBit1_9 (OUT)
型番が1〜9となったときのデータ長(ビット数)出力用
iDataBit10_26 (OUT)
型番が10〜26となったときのデータ長(ビット数)出力用
iDataBit27_40 (OUT)
型番が27〜40となったときのデータ長(ビット数)出力用
戻り値:
==true:データ長の取得に成功
==false:データ長の取得に失敗(セットされているデータのモードが対象外の場合)
内部変数m_listQRDataに登録されている各モードごとのデータから、データビット列を作成し、m_pucDataを作成する。この関数が呼ばれる前に、 2.2.2.9. bool SetTypeNumber(int iCollectLevel , int & iErrorType );を使用してQRコードの型番が決定している必要がある。
最終的にm_pucDataでセットしたデータがQRデータのデータ領域に満たない場合、仕様では埋め草コードを埋めることになっている。この埋め草コードで埋める動作も本関数内で行う。
m_pucDataに最終的にどの様なデータが格納されるかはを 2.2.3.8. unsigned char * m_pucData;参照のこと。
引数:
iErrorType (OUT)
エラーが発生した場合のエラーコードの格納用変数
戻り値:
==true:作成成功
==false:作成失敗(iErrorTypeがセットされる)
指定されたデータビット番号のビットマスクを取得する。
例えば、iBitNumberに0が指定されている場合には戻り値は0x01、1が指定されている場合には戻り値は0x02、2が指定されている場合には戻り値は0x04となる。
ビット番号
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
iBitNumber=4の場合には上記の状態から「00010000」つまり「0x10(16進数)」となる。
このマスクは特定の1バイト変数内の特定のビットがONかOFFかを判定するために使用する。
引数:
iBitNumber (IN)
マスクを作成するビット番号
戻り値:
指定ビットのマスク数。iBitNumberが0〜7でない場合の動作は不定
QRコードで表示したいデータの容量とエラーレベル番号を使用して、QRコードの型番を決定する。QRコードは型番(=サイズと考えても良い)が1〜40型までの40個あり、それぞれで全体的に登録できるデータ数が異なり、その全体領域をデータ領域とエラー訂正領域に分けて使用する。
QRコードには仕様上、エラー訂正レベルが4段階あるため、それぞれの型番でデータ領域として使用できる領域も必然的に4段階に分けられる。
例えば1型のQRコードの場合
エラー訂正レベルLだと19バイト
エラー訂正レベルMだと16バイト
エラー訂正レベルQだと13バイト
エラー訂正レベルHだと9バイト
のデータを記述できる。逆に言えば、データの必要領域とエラー訂正レベルを指定すれば逆引き的に型番を決定できるということになる。各型番で、どのくらいのデータが格納できるかは基本仕様を参照していただきたいが、ソースコードでは、 2.5.1. STypeMatrix c_typeMatrixを参照いただきたい。本関数はこの逆引きを使用して、型番の決定を行っている。また、必要なデータ領域を計測するために、本関数から 2.2.2.6. bool GetDataBitNumber( int & iDataBit1_9 , int & iDataBit10_26 , int & iDataBit27_40 );を呼び出している。
引数:
iCollectLevel (IN)
要求するエラー訂正レベル。
以下の定義されたマクロを使用すること
COLLECTLEVEL_L:エラー訂正レベルL
COLLECTLEVEL_M:エラー訂正レベルM
COLLECTLEVEL_Q:エラー訂正レベルQ
COLLECTLEVEL_H:エラー訂正レベルH
iErrorType (OUT)
エラーが発生した場合のエラーコードの格納用変数
戻り値:
==true:作成成功
==false:作成失敗(iErrorTypeがセットされる)
型番にあわせてm_ppucQRMatrixとm_ppucMaskMatrixの領域を確保する。
QRコードの型番が決定すれば、モジュール数が確定されるが、そのモジュール数分のマトリックスを各メンバ変数に確保し、内部をQR_UNKNOWN(-1)で埋める。
各変数内の格納データの詳細は 2.2.3.2. char ** m_ppucQRMatrix;または 2.2.3.3. char ** m_ppucMaskMatrix;を参照のこと
引数:
iErrorType (OUT)
エラーが発生した場合のエラーコードの格納用変数
戻り値:
==true:現在のところtrueしか返らない。
m_ppucQRMatrixの該当位置に「位置検出パターン」および「位置検出パターンの分離パターン」情報を出力する。
具体的には、m_ppucQRMatrixの
「位置検出パターン」の暗部分をQR_POSITIONDITECT_DARKに、「位置検出パターン」の明部分および「位置検出パターンの分離パターン」をQR_POSITIONDITECT_LIGHTにする。
「位置検出パターン」、「位置検出パターンの分離パターン」とは下図に示す領域のことである。
引数:
iErrorType (OUT)
エラーが発生した場合のエラーコードの格納用変数
戻り値:
==true:現在のところtrueしか返らない。
m_ppucQRMatrixの該当位置に「位置合わせパターン」情報を出力する。
具体的には「位置合わせパターン」の暗部分をQR_POSITIONCHECK_DARKに、明部分をQR_POSITIONCHECK_LIGHTとする。
「位置合わせパターン」は2型以降のQRコードに出力される、3×3のモジュールで、各型番ごとに出力位置が決まっている。出力位置の具体的な場所に関しては基本仕様にあるとおりである。プログラム上の位置定義は 2.5.2. short c_sPositionChecksを参照のこと。
「位置合わせパターン」とは下図に示す部分のことである。
引数:
iErrorType (OUT)
エラーが発生した場合のエラーコードの格納用変数
戻り値:
==true:現在のところtrueしか返らない。
m_ppucQRMatrixの該当位置に「タイミングパターン」を出力する。
具体的には「タイミングパターン」の暗部分にQR_TIMING_DARK、明部分にQR_TIMING_LIGHTを出力する。
タイミングパターンはQRコードの7行目、7列目のうち「位置検出パターン」「位置検出パターンの分離パターン」「位置合わせパターン」で内部分に暗・明を交互に配置する。
タイミングパターンの出力位置に関しては以下を参照
引数:
iErrorType (OUT)
エラーが発生した場合のエラーコードの格納用変数
戻り値:
==true:現在のところtrueしか返らない。
m_ppucQRMatrixの該当位置に「形式情報」を出力する。
具体的には「形式情報」の暗部分にQR_TYPE_DARKを明部分にQR_TYPE_LIGHTを出力する。
形式情報の出力は、データとエラー訂正符号を全て出力した後に8種類のマスクパターンを適用し、失点を計算後、マスクパターンを決定してから出ないと出力できない(形式情報にマスクパターンが含まれるため)。当然ながら、形式情報にはそのマスクパターンは適用されない。本プログラムではデータ領域とエラー訂正領域以外の全ての領域にマスクパターンを適用するための仕組みとして、データ領域とエラー訂正領域以外の全てのデータを出力してから、データがセットされていない領域を拾い出し、マスク適用領域としている( 2.2.2.16. bool CreateMaskPatternArea( int & iErrorType );を参照)。
そのため、形式情報が確定する前に形式情報が出力されるべき領域にダミーデータを挿し込んでおく必要がある。第一引数はその用途の為に存在する。
形式情報のQRコード上の位置は以下を参照。
尚、形式情報にはエラー訂正レベル(2ビット)とマスクパターン(3ビット)のデータとそのエラー訂正符号(10ビット)の合計15ビットとなる。また、作成されたビットパターンが偏ったデータにならないように、それらのデータに特定のマスクパターンで処理を施している。
エラー訂正レベル2ビットは以下のような組み合わせとなる。
エラー訂正レベルL: 01
エラー訂正レベルM: 00
エラー訂正レベルQ: 11
エラー訂正レベルH: 10
またマスクパターンは0番〜7番まであり、それぞれを2進数に変換する。
エラー訂正レベルはそれらのデータをある演算によって処理して作成するが、この演算方法は割愛する。
作成された15ビットのデータ列に101010000010010のマスクパターンを適用(XOR演算すること)し、配置する。
どのように配置するかは基本仕様書を参照していただきたいが、QRコード左下のビット配置だけ説明すると以下のとおりとなる。
上記の数字はビット番号である。ビット番号はビットの最下位(右端)が0となる。今回の形式情報のビット数は15であるためビット番号14は最上位ビットと言うことになる。
前頁のQRコード例の形式情報を見てみると、上記の部分が「010101」となっていることが分かる。
これに、マスクパターンの上位6桁「101010」を再適用すると、「111111」となるので、
エラー訂正符号:Q
マスクパターン:7番
と言うことが読み取れる。説明が長くなったが、本関数の仕様については以下のとおりとなる。
引数:
bReserveOnly (IN)
trueを指定すると、領域にダミーデータ(QR_TYPE_LIGHT)を埋め込む。falseを指定すると、エラー訂正レベルとマスクパターンから形式情報を作成し、形式情報のエラー訂正符号を付加して該当場所に出力する。
iErrorType (OUT)
エラーが発生した場合のエラーコードの格納用変数
戻り値:
==true:出力に成功。
==false:出力に失敗
m_ppucQRMatrixの該当位置に 「型番情報」を出力する。
7型以上のQRコードにはそのQRコードが何型かを示す型番情報が埋め込まれる。
型番情報は7〜40であり、それを6ビットの2進数表記したものに、エラー訂正符号12ビットを付加した合計18ビットとなる。
型番情報は特定のマスクを適用することなく、そのまま記述される。
QRコード上で、型番情報が記述される位置は以下の通りとなる。
型番情報の各ビットが実際にはどう埋め込まれるかは基本仕様書を参照のこと。
左下の型番情報のビットの並びは以下の通りとなる。
上記のQRコードの上位6ビット(ビット番号12〜17)を見ると、001000であるため、このQRコードが8型であることが確認できる。
本関数の仕様については以下のとおりとなる。
引数:
iErrorType (OUT)
エラーが発生した場合のエラーコードの格納用変数
戻り値:
==true:現在のところtrueしか返らない。
現在のQRデータのマトリックスm_ppucQRMatrixを全検索し、データが未セット(QR_UNKNOWN)の部分に対応するマスクマトリックスm_ppucMaskMatrixをマスクの明部分(QR_MASK_LIGHT)に変更する。
この関数はQRデータ内に「位置検出パターン」、「位置検出パターンの分離パターン」、「位置合わせパターン」、「タイミングパターン」、「形式情報(ダミー)」、「型番情報」が出力された後に呼び出される。これにより、m_ppucMaskMatrixにはマスクを適用すべきモジュールにQR_MASK_LIGHT、マスクを適用すべきでないモジュールにQR_UNKNOWNがセットされた状態となり、後に実際にマスクをかけるときやマスクの失点を計算するときに、どの部分にマスク処理を施すかが分かるようになる。
マスク適用領域は概ね以下の通りとなる。
引数:
iErrorType (OUT)
エラーが発生した場合のエラーコードの格納用変数
戻り値:
==true:現在のところtrueしか返らない。
クラス変数m_pucDataに対して、指定されたビットデータを追加する。
m_pucDataはunsigned char型の配列であり、データは1バイトごとで管理される。本関数はm_pucDataに関数の引数であるucDataの下位iBitNumberビット分のデータを追加する。追加するに際して、m_pucDataの確保領域が足らない場合には自動拡張(128バイトごと)し、何ビットのデータが登録されているかはクラス変数m_iDataBitNumberにて管理する。
本関数をコールしたときの簡単な流れを以下に示す。
前提条件:m_iDataBitNumberが0、m_pucDataが空
関数コール:AddDataBits( 0xff , 4 , iErrorType );
結果:
m_pucDataに128バイトのデータが確保され、内部を0x00で初期化
m_pucData[0]の上位4ビットが1111となり、m_pucData[0]は0xf0となる。
m_iDataBitNumberが4となる。
↓↓↓↓
関数コール:AddDataBits( 0xA5 , 6 , iErrorType );
結果:
0xA5を2進数に直すと10100101、下位6ビットをとると100101となる。
m_pucData[0]の下位4ビットが1001となり、m_pucData[0]は0xf9となる。
m_pucData[1]の上位2ビットが01となり、m_pucData[1]は0x40となる。
m_iDataBitNumberが10となる。
↓↓↓↓
関数コール:AddDataBits( 0x9c , 8 , iErrorType );
0x9cを2新数に直すと10011100
m_pucData[1]の下位6ビットが100111となり、m_pucData[1]は0xA7となる。
m_pucData[2]の上位2ビットが00となり、m_pucData[2]は0x00となる。
m_iDataBitNumberが18となる。
上記の要領で、現在セットされているm_pucDataにビットごとのデータを追加しながら、最終的なm_pucDataを作成する動作を本関数で行う。
引数:
ucData (IN)
m_pucDataに追加したいデータが格納された1バイト変数。
最大で8ビットまでのデータを出力することができるが、有効とされるのはiBitNumberで示された下位ビットのみ
iBitNumber (IN)
ucDataで示されたデータのうち、下位何ビットまでをm_pucDataに追加するかを示す数。
1〜8を指定する。
iErrorType (OUT)
エラーが発生した場合のエラーコードの格納用変数
戻り値:
==true:データのセットに成功
==false:データのセットに失敗。(iBitNumber不良)
クラス変数m_pucDataに対して指定された2バイトデータを出力する。
内部的には、上位8ビットと下位8ビットを 2.2.2.17. bool AddDataBits( unsigned char ucData , int iBitNumber , int & iErrorType );を使用して追加している。
引数:
usData (IN)
追加する2バイトデータを格納する。
iErrorType (OUT)
エラーが発生した場合のエラーコードの格納用変数
戻り値:
==true:データのセットに成功
==false:データのセットに失敗
指定された文字列を数字文字列として、m_pucDataへ追加する。
数字文字列の出力は以下のような形式となる
項目 |
ビット数 |
備考 |
モード指示子 |
4 |
数字モードの場合、0001(2進数)となる |
文字数指示子 |
10 |
QRコード型番が1〜9型の場合 |
12 |
QRコード型番が10〜26型の場合 |
|
14 |
QRコード型番が27〜40型の場合 |
|
数字3文字分データ |
10 |
数字を3文字ごとに区切り、10ビットデータで指定する。 |
数字3文字分データ |
10 |
|
……………… |
||
最終データ |
10 |
最終データが3文字の場合 |
7 |
最終データが2文字の場合 |
|
4 |
最終データが1文字の場合 |
数字データの出力は、該当となる数字3文字をひとまとめにして、10ビットで記述する。
10ビットで記述できる数字は0〜1023となるため、10ビットあれば、0〜999までの数字を記述することが可能である。
数字文字列が3の倍数でない場合には、最後の2文字を7ビットで表すか、最後の1文字を4ビットで表すかで調整する。
今、pcszDataが「31415926536」、iDataLengthが「11」の場合、本関数を使用して出力されるデータ列は以下のとおりとなる(QRコードは1〜9型と仮定する)
数字文字列であるため、先頭4ビットは「0001」
文字数11文字をビットに直し、10ビットとすると「0000001011」(前提より1〜9型であるため)
最初の3文字314をビットに直し、10ビットとすると「0100111010」
次の3文字159をビットに直し、10ビットとすると「0010011111」
次の3文字265をビットに直し、10ビットとすると「0100001001」
最後の2文字36をビットに直し、7ビットとすると「0100100」
全てをつなぎあわせて、16進数とすると、
「10 2D 3A 27 D0 94 80」このうち、末尾5ビットは残余ビットであるので、データビットには追加されない計算となる。
これら追加されたデータを関数 2.2.2.17. bool AddDataBits( unsigned char ucData , int iBitNumber , int & iErrorType );を使用してm_pucDataに追加する。
引数:
pcszData (IN)
追加する文字列(半角数字のみを指定)
iDataLength (IN)
追加する文字列の文字数
iErrorType (OUT)
エラーが発生した場合のエラーコードの格納用変数
戻り値:
==true:データのセットに成功
==false:データのセットに失敗。文字列内に半角数字以外が含まれている場合など
指定された文字列をアルファベット文字列として、m_pucDataへ追加する。
アルファベット文字列の出力は以下のような形式となる
項目 |
ビット数 |
備考 |
モード指示子 |
4 |
アルファベットモードの場合、0010(2進数)となる |
文字数指示子 |
9 |
QRコード型番が1〜9型の場合 |
11 |
QRコード型番が10〜26型の場合 |
|
13 |
QRコード型番が27〜40型の場合 |
|
2文字分データ |
11 |
アルファベット文字を2文字ずつに区切り、それぞれを11ビットデータで指定する。 |
2文字分データ |
11 |
|
……………… |
||
最終データ |
11 |
最終データが2文字の場合 |
|
6 |
最終データが1文字の場合 |
アルファベット1文字は以下の様にコード化する
数字の0〜9 : 値0〜9
アルファベットのA〜Z : 値10〜35
「 」スペース : 値36
「$」(ダラー) : 値37
「%」(パーセント) : 値38
「*」(アスタリスク) : 値39
「+」(プラス) : 値40
「-」(マイナス) : 値41
「.」(ピリオド) : 値42
「/」(スラッシュ) : 値43
「:」(コロン) : 値44
アルファベット2文字を扱う際には1文字目のアルファベットを上記の様に数値化し、それに45を乗じて2文字目のアルファベットを数値化したものを足す。アルファベット1文字を扱う際にはその文字を数値化したものを使用する。
今、「pcszData」が「**SPOON2011**」、iDataLengthが「13」のとき、本関数を使用して出力されるデータ列は以下のとおりとなる(QRコードは1〜9型と仮定する)
アルファベット文字列であるため、先頭4ビットは「0010」
文字数13文字を9ビットの2進数に変換すると「000001101」(前提より1〜9型であるため)
最初の2文字**を上述の方法で変換すると、39×45+39=1794
11ビットの2進数に直して「11100000010」
次の2文字SPも同様に28×45+25=1285→「10100000101」
次の2文字OOも同様に24×45+24=1104→「10001010000」
次の2文字N2も同様に23×45+2=1037→「10000001101」
次の2文字01も同様に0×45+1=1→「00000000001」
次の2文字1*も同様に1×45+33=「00001001110」
最後の1文字*を6ビットの2進数に変換33→「100001」
全てをつなぎ合わせて16新数にすると
「40 DE 05 41 62 84 0D 00 21 3A 10」
となる。(最終の4ビットは残余ビットとなり、実際には追加されない)
これら追加されたデータを関数 2.2.2.17. bool AddDataBits( unsigned char ucData , int iBitNumber , int & iErrorType );を使用してm_pucDataに追加する。
引数:
pcszData (IN)
追加する文字列(半角英数字(大文字)と適切な記号のみ)
iDataLength (IN)
追加する文字列の文字数
iErrorType (OUT)
エラーが発生した場合のエラーコードの格納用変数
戻り値:
==true:データのセットに成功
==false:データのセットに失敗。文字列内にアルファベットで指定できる文字以外が含まれている場合など
指定された文字列をASCII文字列として、m_pucDataへ追加する。
ASCII文字列の出力は以下のような形式となる
項目 |
ビット数 |
備考 |
モード指示子 |
4 |
ASCIIモードの場合、0100(2進数)となる |
文字数指示子 |
8 |
QRコード型番が1〜9型の場合 |
16 |
QRコード型番が10〜26型の場合 |
|
16 |
QRコード型番が27〜40型の場合 |
|
1文字分データ |
8 |
1文字分のデータを8ビットで指定する |
1文字分データ |
8 |
|
……………… |
||
最終文字データ |
8 |
|
各文字列はASCII文字列として扱うため、それぞれの文字をそのまま8ビットで表現する。
今、「pcszData」が「@QRcode」、iDataLengthが「13」のとき、本関数を使用して出力されるデータ列は以下のとおりとなる(QRコードは1〜9型と仮定する)
ASCII文字列であるため、先頭4ビットは「0100」
文字数13文字を8ビットの2進数に変換すると「00001101」(前提より1〜9型であるため)
@のキャラクターコード :0x40
Qのキャラクタコード :0x51
Rのキャラクタコード :0x52
cのキャラクタコード :0x63
oのキャラクタコード :0x6f
dのキャラクタコード :0x64
eのキャラクタコード :0x65
全てをつなぎ合わせて16進数にすると
「40 D4 05 15 25 36 F6 46 50」
となる。(最終の4ビットは残余ビットとなり、実際には追加されない)
これら追加されたデータを関数 2.2.2.17. bool AddDataBits( unsigned char ucData , int iBitNumber , int & iErrorType );を使用してm_pucDataに追加する。
引数:
pcszData (IN)
追加する文字列
iDataLength (IN)
追加する文字列の文字数
iErrorType (OUT)
エラーが発生した場合のエラーコードの格納用変数
戻り値:
==true:データのセットに成功
==false:データのセットに失敗。
指定された文字列を漢字文字列として、m_pucDataへ追加する。漢字文字列はシフトJISで指定すること。
漢字文字列の出力は以下のような形式となる
項目 |
ビット数 |
備考 |
モード指示子 |
4 |
漢字モードの場合、1000(2進数)となる |
文字数指示子 |
8 |
QRコード型番が1〜9型の場合 |
10 |
QRコード型番が10〜26型の場合 |
|
12 |
QRコード型番が27〜40型の場合 |
|
漢字1文字分データ |
13 |
pcszData2バイト分を1文字として、下に述べる方法を用いてコード化し、13ビットにまとめる。 |
漢字1文字分データ |
13 |
|
……………… |
||
最終文字データ |
13 |
|
漢字1文字分データは以下の方法を用いて11ビットに変換する
漢字1文字分のコードが0x8140〜0x9FFCの場合、1文字分のコードから0x8140を引く(引いたコードを(A)とする)
コードが0xE040〜0xEBBFの場合、1文字分のコードから0xC140を引く(引いたコードを(A)とする)
それ以外のコードの場合はエラーとなる。
(A)の上位バイトを(AH)、下位バイトを(AL)とする。
(AH)に0xC0を乗じ、(AL)を足し、その値を13ビットの2進数に変換する
今、「pcszData」が「★鵝」、iDataLengthが「2」のとき、本関数を使用して出力されるデータ列は以下のとおりとなる(QRコードは1〜9型と仮定する)
漢字文字列であるため、先頭4ビットは「1000」
文字数2文字を8ビットの2進数に変換すると「00000010」(前提より1〜9型であるため)
★のキャラクタコード :0x819A
0x8140〜0x9FFCなので、0x8140を引く →0x0054(上位バイト0x00、下位バイト0x54)
上位バイトに0xC0を乗じ、下位バイトを足す。
0x00×0xC0+0x54=0x54 →13ビット2進数に変換「0000001010100」
鵝のキャラクタコード:0xEA40
0xE040〜0xEBBFなので、0xC140を引く →0x2900(上位バイト0x29、下位バイト0x00)
上位バイトに0xc0を乗じ、下位バイトを足す
0x29×0xC0+0x00=0x1EC0 →13ビット2進数に変換「1111011000000」
全てをつなぎ合わせて16進数にすると
「20 08 0A 9E C0」
となる。
これら追加されたデータを関数 2.2.2.17. bool AddDataBits( unsigned char ucData , int iBitNumber , int & iErrorType );を使用してm_pucDataに追加する。
引数:
pcszData (IN)
追加する文字列(漢字文字列のみ)
iDataLength (IN)
追加する文字列の文字数
iErrorType (OUT)
エラーが発生した場合のエラーコードの格納用変数
戻り値:
==true:データのセットに成功
==false:データのセットに失敗(漢字文字列以外が指定された場合など)
データビット列(m_pucData)とエラー訂正ビット列(m_pucError)をQRコードのデータ領域とエラー訂正領域に出力する。これによりm_ppucQRMatrixにデータとエラー訂正が埋め込まれる。
本関数を出力する前に「位置検出パターン」「位置検出パターンの分離パターン」「位置合わせパターン」「タイミングパターン」「型番情報」「形式情報(ダミー)」が出力されている必要がある。
また、m_pucData( 2.2.2.7. bool CreateDataBits( int & iErrorType );)とm_pucError( 2.2.2.31. bool CreateErrorCollectData( int & iErrorType );)が作成されている必要がある。
データの出力はまずデータビット列をQRコードの右下から出力していく、その後続きの部分にエラー訂正ビット列を出力する。データビット列・エラー訂正ビット列は一定の法則に従って出力する。一定の法則とは以下のとおり
最初のデータの出力方向は上方向とする。
QRコードの右端から2モジュールずつを出力ブロックとする(左側のタイミングパターンの部分は縦側にひとつも出力領域がないため、出力ブロックには設定しない)
データの1ビット目をQRコードの一番右下に出力し、その後2ビット目を1モジュール左側に出力する。3ビット目は2ビット目の右上(1ビット目の上)に出力し、4ビット目はその左側に出力する。
上記のように、2モジュールずつの出力ブロックの右側・左側を埋め順次上に向かって出力する。QRコードの上端に達したら、その後、同じ法則に従って、下方向への出力を行う。
既に位置合わせパターンなどが出力されている部分に関しては、それらを避けてデータの出力を行う。
各ビットの出力パターンに関しては、基本仕様書に詳しく述べられているため、これを参照すること。また、本関数を見るのも出力方法を調べるのに役立つと思われる。
さて、データビットの出力、エラー訂正ビットの出力は、データの先頭から単純に出力を行うわけではない。QRコードの型によってデータビット及びエラー訂正ビットは複数のRSブロックに分けられる(RSブロック=リードソロモンブロック)。分けられたRSブロック毎の1バイト目のデータを出力し、次に2バイト目のデータを出力すると行った具合に、データの出力を行う。説明がうまくないので、具体的な例を下記に示す。
5型のQRコードで、エラー訂正レベルがHのものを考えてみる。
基本仕様書(あるいはSTypeMatrixでも良いが)を見ると、本QRコードの全領域が134バイト(1072ビット)で、そのうちデータとして使用できる領域が46バイト(368ビット)であることが分かる。また、RSブロック数は4となる。全領域からデータ領域を引いた88バイト(704ビット)がエラー訂正領域で有ることも分かる。
データ領域をRSブロック数で割ると、1ブロック当たりのバイト数は幾つになるだろうか?
46÷4=11バイトあまり2バイトとなる。このことから、RSブロック2つが11バイト、残りのRSブロック2つが12バイトとなる。
エラー訂正領域をRSブロック数で割ると幾つになるだろうか?
88÷4=22バイト(エラー訂正領域は必ずRSブロック数で割り切れる様に設計されている)
5型のエラー訂正レベルHのデータ領域は46バイトあることは前述のとおりであるが、これらを先頭バイトから便宜上D1〜D46と呼ぶことにする。
上述のとおり、データ領域を4つのRSブロックに分けたとき、前の2つのブロックが11バイト、後の2つのブロックが12バイトとなる。これを各データに割り振ると下記のようになる。
RSブロック1 : D1〜D11
RSブロック2 : D12〜D22
RSブロック3 : D23〜D34
RSブロック4 : D35〜D46
同様にエラー訂正領域をE1〜E88とすると、
RSブロック1 : E1〜E22
RSブロック2 : E23〜E44
RSブロック3 : E45〜E66
RSブロック4 : E67〜E88
となる。
データの出力、エラー訂正の出力は各RSブロックのバイトごとに行われるため、
[D1][D12][D23][D35][D2][D13]…[D11][D22][D33][D44][D34][D36][E1][E23][E45][E67][E2]…[E22][E44][E66][E88]
という順序で行われることになる。
★リードソロモンを使用したエラー訂正符号化の際にも同様のブロックのくくりを用いて行う。リードソロモンを使用したエラー訂正符号化に関しては 2.2.2.31. bool CreateErrorCollectData( int & iErrorType );を参照のこと。
実際にQRコードの型によってどのように分けられるかに関してはSTypeMatrix構造体のメンバm_iRSBlockNumberに記述されている。各RSブロックごとのデータ数、エラー訂正数に関しては 2.5.1. STypeMatrix c_typeMatrixを参照のこと。
本関数の仕様に関しては以下のとおりとなる。
引数:
iErrorType (OUT)
エラーが発生した場合のエラーコードの格納用変数
戻り値:
==true:データのセットに成功
==false:データのセットに失敗
リードソロモン法によるQRのエラー訂正コードを取得するためのクラスです。QRReadSolomon.hをインクルードすることによって使用可能となります。
本クラスはCQRMatrix内で使用されます。
以下にCQRReadSolomonクラスの仕様を記します。
現在製作中
現在製作中
現在製作中
QRコードに出力する文字列を管理するためのクラスです。QRDataElement.hをインクルードすることによって使用可能となります。
本クラスはCQRMatrix内で使用されます。
以下にCQRDataElementクラスの仕様を記します。
現在製作中
現在製作中
現在製作中
サンプルプログラムはSampleフォルダ内にある以下の3つのプログラムです。
CommandSample.cpp
WindowsSample.cpp
GDSample.cpp
コマンドプロンプトベースのサンプルプログラムです。
WindowsでもUNIXでも動作します。
実行すると、暗モジュールが「■」で、明モジュールが「 」で表示sれます。このデータは「■」に余白があるため、QRコードとしての読み取りは出来ないと思われますが、動作のサンプルプログラムとしては分かりやすいため、本プログラムを使用するにはこのサンプルを使うのが良いと思われます。
Windowsの場合、コマンドプロンプトで空のプロジェクトを作成し、プロジェクトにQRコード出力用の各プログラム(QRMatrix.h、QRMatrix.cpp、QRReadSolomon.h、QRReadSolomon.cpp、QRDataElement.h、QRDataElement.cpp、QRMatrixInformation.h、QRReadSolomonInformation.h)と、サンプルプログラムCommandSample.cppをプロジェクトに追加後、コンパイルして実行します。全てのプログラムは同一のフォルダ内に入れてください。
UNIXの場合、gcコンパイラでコンパイルするには、全てのプログラムを同一のディレクトリに入れ、
cc -c QRMatrix.cpp
cc -c QRReadSolomon.cpp
cc -c QRDataElement.cpp
cc -c CommandSample.cpp
としてコンパイルを実行し、
cc -o CommandSample CommandSample.o QRMatrix.o QRReadSolomon.o QRDataElement.o -lstdc++
として実行ファイルを作成します。
Windowsのウィンドウを表示し、そこにQRコードを表示するサンプルです。
コードの大半はウィンドウの表示と制御絡みとなっており、サンプルとしてはシンプルではありませんが、ここで表示されたQRコードは携帯電話などを含む各読み取り装置で読み取ることが出来ます。
実行するには、WIN32プロジェクトで空のプロジェクトを作成し、QRコード出力用の各プログラムおよび、WindowsSample.cppをプロジェクトに追加します。各プログラムは同一のフォルダに置いてください。また、コンパイル設定はマルチバイト文字セットで行ってください。(サンプルはユニコードに対応していません)
その後、ビルドを行い、実行します。
UNIXでGDを使用してJPEGファイルを作成するサンプルです。実行すると、カレントディレクトリに「qrimage.jpg」ファイルが作られます。
コンパイルするには、QRコード出力用の各プログラム及びGDSample.cppを同一のディレクトリに入れ、
cc -c QRMatrix.cpp
cc -c QRReadSolomon.cpp
cc -c QRDataElement.cpp
cc -c GDSample.cpp
として、コンパイルを行い、
cc -o GDSample GDSample.o QRMatrix.o QRReadSolomon.o QRDataElement.o -lstdc++ -lm -ljpeg -lm
として、実行モジュールを作成します。
GDがインストールされていることが前提条件となります。もし、gd.hがインクルード出来ない場合は、「-I/usr/local/include」(ディレクトリはGDのインクルードディレクトリにより異なります)をGDSample.cppのコンパイル時に指定してください。また、リンクするときにGD絡みでリンクエラーが発生する場合はリンク時に「-L/usr/local/lib」をリンク時に指定してください。
本ドキュメントの著作権はSPOONsoftwareに帰属します。
本ドキュメントを改変しないでください。