PHPでQRコードをつくる

(1/1)
QRコード(2次元バーコード)が流行である。雑誌などに印刷してある QR コードをスマホのカメラで取り込むとURLとして解釈され、キー操作する必要なくアクセスできるし、PayPay や LINE Pay など QR コードを使った電子決済も普及している。
ぱふぅ家のホームページもスマホに対応しているので、PC版のトップページに QR コードを表示してみようと考えた。
Y.Swetake さんのサイトに PHPのプログラムが公開されている。今回は、これを利用させていただくことにした。なお、このライブラリを利用するには、GD 2.0以上 が組み込まれている必要がある。

なお、QR コード株式会社デンソーウェーブが開発し、その規格・仕様自体はオープンであるが、QR コードという名称だけはデンソーウェーブの登録商標となっている。

(2025年8月16日)pahooQRimage.php,全面改訂。

目次

サンプル・プログラムの実行例

PHPでQRコードをつくる

サンプル・プログラム

圧縮ファイルの内容
qr_sample.phpサンプル・プログラム本体
qr_img.phpQRcode PHP scriptsのPHP7/8対応版
圧縮ファイルの内容
qr_sample.phpサンプル・プログラム本体。
pahooQRimage.phpQRコード(2次元バーコード)作成に関わる暮らす。
使い方は「PHPでQRコードをつくる」などを参照。include_path が通ったディレクトリに配置すること。
qr_sample.php 更新履歴
バージョン 更新日 内容
4.0.1 2025/08/24 makeCommonBody() -- bug-fix
4.0.0 2025/08/16 pahooQRimage.php,全面改訂。
3.0 2020/12/19 PHP8対応。全面改訂。
2.0 2008/05/10 ヒアドキュメント化,UTF-8
1.1 2007/01/20 XSS対策
pahooInputData.php 更新履歴
バージョン 更新日 内容
2.0.1 2025/08/11 getParam() bug-fix
2.0.0 2025/08/11 pahooLoadEnv() 追加
1.9.0 2025/07/26 getParam() 引数に$trim追加
1.8.1 2025/03/15 validRegexPattern() debug
1.8.0 2024/11/12 validRegexPattern() 追加
pahooQRimage.php 更新履歴
バージョン 更新日 内容
1.0.1 2025/07/29 text2QRimage() -- bug-fix
1.0.0 2025/07/29 初版

準備:pahooInputData 関数群

PHPのバージョンや入力データのバリデーションなど、汎用的に使う関数群を収めたファイル "pahooInputData.php" が同梱されているが、include_path が通ったディレクトリに配置してほしい。他のプログラムでも "pahooInputData.php" を利用するが、常に最新のファイルを1つ配置すればよい。

また、各種クラウドサービスに登録したときに取得するアカウント情報、アプリケーションパスワードなどを登録した .pahooEnv ファイルから読み込む関数 pahooLoadEnv を備えている。こちらについては、「各種クラウド連携サービス(WebAPI)の登録方法」をご覧いただきたい。

準備:pahooQRimage クラス

pahooQRimage.php

  41: class pahooQRimage {
  42: public $dataPath;               // データファイルのあるパス
  43: public $imagePath;              // QRコードのイメージフレームのあるパス
  44: public $maxQRversion = 40;      // 最大バージョン
  45: public $maxImageSize = 1480;    // QRコードの最大サイズ(一辺のピクセル)
  46: 
  47: public $qrcode_data_string;
  48: public $qrcode_module_size;
  49: public $qrcode_image_type;
  50: 
  51: public $qrcode_structureappend_n;
  52: public $qrcode_structureappend_m;
  53: public $qrcode_structureappend_parity;
  54: public $qrcode_structureappend_originaldata;
  55: 
  56: function __construct() {
  57:     $this->dataPath = __DIR__ . '/QRdata';
  58:     $this->imagePath = __DIR__ . '/QRimage';
  59: 
  60:     $this->qrcode_structureappend_n = '';
  61:     $this->qrcode_structureappend_m = '';
  62:     $this->qrcode_structureappend_parity = '';
  63:     $this->qrcode_structureappend_originaldata = '';
  64: }

QRコード(2次元バーコード)を生成するためのメソッドを集めたのが pahooQRimageクラス である。同梱のクラス・ファイル "pahooQRimage.php" は include_path が通ったディレクトリに配置してほしい。内容については「PHPでQRコードをつくる」をご覧いただきたい。他のプログラムでも pahooQRimageクラス を利用することがあるが、常に最新のクラス・ファイルを1つ配置すればよい。

なお、QRコードを生成するのに、"QRimage" フォルダに格納している画像ファイル群と、"QRdata" フォルダに格納しているデータ・ファイル群が必要になる。クラス・ファイル "pahooQRimage.php" と同じディレクトリに配置してほしい。

解説:各種定数

各種定数は、とくに断り書きがないものについては自由に変更可能である。

qr_sample.php

  55: // 各種定数(START) ===========================================================
  56: 
  57: // 表示幅(ピクセル)
  58: define('WIDTH', 500);
  59: 
  60: // 入力できる最大文字数
  61: define('MAX_TEXT_LENGTH', 1000);
  62: 
  63: // メッセージ(初期値)
  64: define('DEF_TEXT', 'ぱふぅ家のホームページ https://www.pahoo.org/');
  65: 
  66: // QRコードのサイズ(単位:ピクセル)
  67: define('WIDTH_QRCODE', 300);
  68: 
  69: // 各種定数(END) ===========================================================

解説:text2QRimageメソッド

ユーザー定義メソッド text2QRimage は、引数で指定したテキストから QRコードを生成し、そのままimgタグに代入できるよう、BASE64にエンコードされたデータとして返す。
引数として、QRコードのサイズや画像形式、ECCレベル、QRコードコードのバージョンを指定できる。

pahooQRimage.php

  66: /**
  67:  * テキストをQRイメージデータに変換する.
  68:  * @param   string $text      QRコードにしたいテキスト
  69:  * @param   int    $imageSize QRコードの一辺のサイズ(単位:ピクセル)(省略時 200)
  70:  * @param   string $imageType 画像形式(jpeg, png)(省略時 png)
  71:  * @param   string $eccLevel  ECCレベル(L, M, Q, H)(省略時 M)
  72:  * @param   int    $versionQR QRコードのバージョン(0:自動, 1〜40)(省略時 0)
  73:  * @return  string 応答データ/FALSE=失敗
  74: */
  75: function text2QRimage($text, $imageSize=200, $imageType='png', $eccLevel='M', $versionQR=0) {
  76:     // テキストのバリデーション
  77:     $sourText = rawurldecode($text);
  78:     $data_length = strlen($sourText);
  79:     if ($data_length <0) {
  80:         throw new Exception($imageSize . 'テキストがありません');
  81:         return FALSE;
  82:     }
  83: 
  84:     // 画像サイズのバリデーション
  85:     if (($imageSize < 1|| ($imageSize > $this->maxImageSize)) {
  86:         throw new Exception($imageSize . ' -- 対応していない画像サイズです');
  87:         return FALSE;
  88:     }
  89: 
  90:     // 画像形式のバリデーション
  91:     $imageTypeList = [ 'jpeg', 'png' ];
  92:     $imageType = strtolower($imageType);
  93:     if (array_search($imageType, $imageTypeList) === FALSE) {
  94:         throw new Exception($imageType . ' -- 対応していない画像形式です');
  95:         return FALSE;
  96:     }
  97: 
  98:     // QRコードのバージョンのバリデーション
  99:     if (! is_numeric($versionQR)) {
 100:         $versionQR = 0;
 101:     }
 102:     if ($versionQR > $this->maxQRversion) {
 103:         throw new Exception($imageType . ' -- 対応していないQRバージョンです');
 104:         return FALSE;
 105:     }
 106: 
 107:     $data_counter = 0;
 108:     if ($this->qrcode_structureappend_n > 1
 109:         && $this->qrcode_structureappend_n <16
 110:         && $this->qrcode_structureappend_m > 0
 111:         && $this->qrcode_structureqppend_m <16) {
 112: 
 113:         $data_value[0] = 3;
 114:         $data_bits[0] = 4;
 115: 
 116:         $data_value[1] = $this->qrcode_structureappend_m - 1;
 117:         $data_bits[1] = 4;
 118: 
 119:         $data_value[2] = $this->qrcode_structureappend_n - 1;
 120:         $data_bits[2] = 4;
 121: 
 122:         $originaldata_length = strlen($this->qrcode_structureappend_originaldata);
 123:         if ($originaldata_length > 1) {
 124:             $this->qrcode_structureappend_parity = 0;
 125:             $i=0;
 126:             while ($i<$originaldata_length){
 127:                 $this->qrcode_structureappend_parity=($this->qrcode_structureappend_parity ^ ord(substr($this->qrcode_structureappend_originaldata,$i,1)));
 128:                 $i++;
 129:             }
 130:         }
 131: 
 132:         $data_value[3]=$this->qrcode_structureappend_parity;
 133:         $data_bits[3]=8;
 134: 
 135:         $data_counter=4;
 136:     }
 137: 
 138:     $data_bits[$data_counter] = 4;
 139: 
 140: /*  --- determine encode mode */
 141: 
 142: if (preg_match('/[^0-9]/ui', $sourText)) {
 143:     if (preg_match('/[^0-9A-Z \$\*\%\+\-\.\/\:]/ui', $sourText)) {
 144: 
 145:      /*  --- 8bit byte mode */
 146: 
 147:         $codeword_num_plus=array(0,0,0,0,0,0,0,0,0,0,
 148: 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
 149: 8,8,8,8,8,8,8,8,8,8,8,8,8,8);
 150: 
 151:         $data_value[$data_counter]=4;
 152:         $data_counter++;
 153:         $data_value[$data_counter]=$data_length;
 154:         $data_bits[$data_counter]=8;   /* #version 1-9 */
 155:         $codeword_num_counter_value=$data_counter;
 156: 
 157:         $data_counter++;
 158:         $i=0;
 159:         while ($i<$data_length){
 160:             $data_value[$data_counter] = ord(substr($sourText,$i, 1));
 161:             $data_bits[$data_counter] = 8;
 162:             $data_counter++;
 163:             $i++;
 164:         }
 165:     } else {
 166: 
 167:     /* ---- alphanumeric mode */
 168: 
 169:         $codeword_num_plus=array(0,0,0,0,0,0,0,0,0,0,
 170: 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
 171: 4,4,4,4,4,4,4,4,4,4,4,4,4,4);
 172: 
 173:         $data_value[$data_counter]=2;
 174:         $data_counter++;
 175:         $data_value[$data_counter]=$data_length;
 176:         $data_bits[$data_counter]=9;  /* #version 1-9 */
 177:         $codeword_num_counter_value=$data_counter;
 178: 
 179: 
 180:         $alphanumeric_character_hash=array("0"=>0,"1"=>1,"2"=>2,"3"=>3,"4"=>4,
 181: "5"=>5,"6"=>6,"7"=>7,"8"=>8,"9"=>9,"A"=>10,"B"=>11,"C"=>12,"D"=>13,"E"=>14,
 182: "F"=>15,"G"=>16,"H"=>17,"I"=>18,"J"=>19,"K"=>20,"L"=>21,"M"=>22,"N"=>23,
 183: "O"=>24,"P"=>25,"Q"=>26,"R"=>27,"S"=>28,"T"=>29,"U"=>30,"V"=>31,
 184: "W"=>32,"X"=>33,"Y"=>34,"Z"=>35," "=>36,"$"=>37,"%"=>38,"*"=>39,
 185: "+"=>40,"-"=>41,"."=>42,"/"=>43,":"=>44);
 186: 
 187:         $i=0;
 188:         $data_counter++;
 189:         while ($i<$data_length){
 190:             if (($i %2)==0){
 191:                 $data_value[$data_counter]=$alphanumeric_character_hash[substr($sourText, $i ,1)];
 192:                 $data_bits[$data_counter]=6;
 193:             } else {
 194:                 $data_value[$data_counter]=$data_value[$data_counter]*45+$alphanumeric_character_hash[substr($sourText, $i, 1)];
 195:                 $data_bits[$data_counter]=11;
 196:                 $data_counter++;
 197:             }
 198:             $i++;
 199:         }
 200:     }
 201: else {
 202: 
 203:     /* ---- numeric mode */
 204: 
 205:     $codeword_num_plus=array(0,0,0,0,0,0,0,0,0,0,
 206: 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
 207: 4,4,4,4,4,4,4,4,4,4,4,4,4,4);
 208: 
 209:     $data_value[$data_counter]=1;
 210:     $data_counter++;
 211:     $data_value[$data_counter]=$data_length;
 212:     $data_bits[$data_counter]=10;   /* #version 1-9 */
 213:     $codeword_num_counter_value=$data_counter;
 214: 
 215:     $i=0;
 216:     $data_counter++;
 217:     while ($i<$data_length){
 218:         if (($i % 3)==0){
 219:             $data_value[$data_counter]=substr($sourText, $i, 1);
 220:             $data_bits[$data_counter]=4;
 221:         } else {
 222:              $data_value[$data_counter]=$data_value[$data_counter]*10+substr($sourText, $i, 1);
 223:          if (($i % 3)==1){
 224:              $data_bits[$data_counter]=7;
 225:          } else {
 226:              $data_bits[$data_counter]=10;
 227:              $data_counter++;
 228:          }
 229:         }
 230:         $i++;
 231:     }
 232: }
 233: if (isset($data_bits[$data_counter]) && ($data_bits[$data_counter> 0)) {
 234:     $data_counter++;
 235: }
 236: $i=0;
 237: $total_data_bits=0;
 238: while($i<$data_counter){
 239:     $total_data_bits+=$data_bits[$i];
 240:     $i++;
 241: }
 242: 
 243: 
 244: $ecc_character_hash=array("L"=>"1",
 245: "l"=>"1",
 246: "M"=>"0",
 247: "m"=>"0",
 248: "Q"=>"3",
 249: "q"=>"3",
 250: "H"=>"2",
 251: "h"=>"2");
 252: 
 253:  $ec = @$ecc_character_hash[$eccLevel]; 
 254: 
 255:  if (!$ec){$ec=0;}
 256: 
 257: $max_data_bits_array=array(
 258: 0,128,224,352,512,688,864,992,1232,1456,1728,
 259: 2032,2320,2672,2920,3320,3624,4056,4504,5016,5352,
 260: 5712,6256,6880,7312,8000,8496,9024,9544,10136,10984,
 261: 11640,12328,13048,13800,14496,15312,15936,16816,17728,18672,
 262: 
 263: 152,272,440,640,864,1088,1248,1552,1856,2192,
 264: 2592,2960,3424,3688,4184,4712,5176,5768,6360,6888,
 265: 7456,8048,8752,9392,10208,10960,11744,12248,13048,13880,
 266: 14744,15640,16568,17528,18448,19472,20528,21616,22496,23648,
 267: 
 268: 72,128,208,288,368,480,528,688,800,976,
 269: 1120,1264,1440,1576,1784,2024,2264,2504,2728,3080,
 270: 3248,3536,3712,4112,4304,4768,5024,5288,5608,5960,
 271: 6344,6760,7208,7688,7888,8432,8768,9136,9776,10208,
 272: 
 273: 104,176,272,384,496,608,704,880,1056,1232,
 274: 1440,1648,1952,2088,2360,2600,2936,3176,3560,3880,
 275: 4096,4544,4912,5312,5744,6032,6464,6968,7288,7880,
 276: 8264,8920,9368,9848,10288,10832,11408,12016,12656,13328
 277: );
 278: 
 279: if (! $versionQR) {
 280:  /* #--- auto version select */
 281:     $i = 1 + 40 * $ec;
 282:     $j = $i + 39;
 283:     $versionQR = 1
 284:     while ($i<=$j){
 285:         if (($max_data_bits_array[$i])>=$total_data_bits+$codeword_num_plus[$versionQR]     ){
 286:             $max_data_bits=$max_data_bits_array[$i];
 287:             break;
 288:         }
 289:      $i++;
 290:      $versionQR++;
 291:     }
 292: else {
 293:      $max_data_bits=$max_data_bits_array[$versionQR + 40 * $ec];
 294: }
 295: 
 296: $total_data_bits+=$codeword_num_plus[$versionQR];
 297:     $data_bits[$codeword_num_counter_value]+=$codeword_num_plus[$versionQR];
 298: 
 299: $max_codewords_array=array(0,26,44,70,100,134,172,196,242,
 300: 292,346,404,466,532,581,655,733,815,901,991,1085,1156,
 301: 1258,1364,1474,1588,1706,1828,1921,2051,2185,2323,2465,
 302: 2611,2761,2876,3034,3196,3362,3532,3706);
 303: 
 304: $max_codewords=$max_codewords_array[$versionQR];
 305: $max_modules_1side=17+($versionQR << 2);
 306: 
 307: $matrix_remain_bit=array(0,0,7,7,7,7,7,0,0,0,0,0,0,0,3,3,3,3,3,3,3,
 308: 4,4,4,4,4,4,4,3,3,3,3,3,3,3,0,0,0,0,0,0);
 309: 
 310: /* ---- read version ECC data file */
 311: 
 312: $byte_num=$matrix_remain_bit[$versionQR]+($max_codewords << 3);
 313: $filename=$this->dataPath . "/qrv" . $versionQR . "_" . $ec . ".dat";
 314: 
 315: $fp1 = fopen ($filename, "rb");
 316:     $matx=fread($fp1,$byte_num);
 317:     $maty=fread($fp1,$byte_num);
 318:     $masks=fread($fp1,$byte_num);
 319:     $fi_x=fread($fp1,15);
 320:     $fi_y=fread($fp1,15);
 321:     $rs_ecc_codewords=ord(fread($fp1,1));
 322:     $rso=fread($fp1,128);
 323: fclose($fp1);
 324: 
 325: $matrix_x_array=unpack("C*",$matx);
 326: $matrix_y_array=unpack("C*",$maty);
 327: $mask_array=unpack("C*",$masks);
 328: 
 329: $rs_block_order=unpack("C*",$rso);
 330: 
 331: $format_information_x2=unpack("C*",$fi_x);
 332: $format_information_y2=unpack("C*",$fi_y);
 333: 
 334: $format_information_x1=array(0,1,2,3,4,5,7,8,8,8,8,8,8,8,8);
 335: $format_information_y1=array(8,8,8,8,8,8,8,8,7,5,4,3,2,1,0);
 336: 
 337: $max_data_codewords=($max_data_bits >>3);
 338: 
 339: $filename = $this->dataPath."/rsc".$rs_ecc_codewords.".dat";
 340: $fp0 = fopen ($filename, "rb");
 341: $i=0;
 342: while ($i<256) {
 343:     $rs_cal_table_array[$i]=fread ($fp0,$rs_ecc_codewords);
 344:     $i++;
 345: }
 346: fclose ($fp0);
 347: 
 348: /*  --- set terminator */
 349: 
 350: if ($total_data_bits<=$max_data_bits-4){
 351:     $data_value[$data_counter]=0;
 352:     $data_bits[$data_counter]=4;
 353: else {
 354:     if ($total_data_bits<$max_data_bits){
 355:     $data_value[$data_counter]=0;
 356:         $data_bits[$data_counter]=$max_data_bits-$total_data_bits;
 357:     } else {
 358:         if ($total_data_bits>$max_data_bits){
 359:         trigger_error("QRcode : Overflow error",E_USER_ERROR);
 360:         exit;
 361:         }
 362:     }
 363: }
 364: 
 365: /* ----divide data by 8bit */
 366: 
 367: $i=0;
 368: $codewords_counter=0;
 369: $codewords[0]=0;
 370: $remaining_bits=8;
 371: 
 372: while ($i<=$data_counter) {
 373:     $buffer=@$data_value[$i];
 374:     $buffer_bits=@$data_bits[$i];
 375: 
 376:     $flag=1;
 377:     while ($flag) {
 378:         if ($remaining_bits>$buffer_bits){  
 379:             $codewords[$codewords_counter]=((@$codewords[$codewords_counter]<<$buffer_bits| $buffer);
 380:             $remaining_bits-=$buffer_bits;
 381:             $flag=0;
 382:         } else {
 383:             $buffer_bits-=$remaining_bits;
 384:             $codewords[$codewords_counter]=(($codewords[$codewords_counter<< $remaining_bits| ($buffer >> $buffer_bits));
 385: 
 386:             if ($buffer_bits==0) {
 387:                 $flag=0;
 388:             } else {
 389:                 $buffer= ($buffer & ((1 << $buffer_bits)-1) );
 390:                 $flag=1;   
 391:             }
 392: 
 393:             $codewords_counter++;
 394:             if ($codewords_counter<$max_data_codewords-1){
 395:                 $codewords[$codewords_counter]=0;
 396:             }
 397:             $remaining_bits=8;
 398:         }
 399:     }
 400:     $i++;
 401: }
 402: if ($remaining_bits!=8) {
 403:     $codewords[$codewords_counter]=$codewords[$codewords_counter<< $remaining_bits;
 404: else {
 405:     $codewords_counter--;
 406: }
 407: 
 408: /* ----  set padding character */
 409: 
 410: if ($codewords_counter<$max_data_codewords-1){
 411:     $flag=1;
 412:     while ($codewords_counter<$max_data_codewords-1){
 413:         $codewords_counter++;
 414:         if ($flag==1) {
 415:             $codewords[$codewords_counter]=236;
 416:         } else {
 417:             $codewords[$codewords_counter]=17;
 418:         }
 419:         $flag=$flag*(-1);
 420:     }
 421: }
 422: 
 423: /* ---- RS-ECC prepare */
 424: 
 425: $i=0;
 426: $j=0;
 427: $rs_block_number=0;
 428: $rs_temp[0]="";
 429: 
 430: while($i<$max_data_codewords){
 431: 
 432:     $rs_temp[$rs_block_number].=chr($codewords[$i]);
 433:     $j++;
 434: 
 435:     if ($j>=$rs_block_order[$rs_block_number+1]-$rs_ecc_codewords){
 436:         $j=0;
 437:         $rs_block_number++;
 438:         $rs_temp[$rs_block_number]="";
 439:     }
 440:     $i++;
 441: }
 442: 
 443: 
 444: /*
 445: #
 446: # RS-ECC main
 447: #
 448: */
 449: 
 450: $rs_block_number=0;
 451: $rs_block_order_num=count($rs_block_order);
 452: 
 453: while ($rs_block_number<$rs_block_order_num){
 454: 
 455:     $rs_codewords=$rs_block_order[$rs_block_number+1];
 456:     $rs_data_codewords=$rs_codewords-$rs_ecc_codewords;
 457: 
 458:     $rstemp=$rs_temp[$rs_block_number].str_repeat(chr(0),$rs_ecc_codewords);
 459:     $padding_data=str_repeat(chr(0),$rs_data_codewords);
 460: 
 461:     $j=$rs_data_codewords;
 462:     while($j>0){
 463:         $first=ord(substr($rstemp,0,1));
 464: 
 465:         if ($first){
 466:             $left_chr=substr($rstemp,1);
 467:             $cal=$rs_cal_table_array[$first].$padding_data;
 468:             $rstemp=$left_chr ^ $cal;
 469:         } else {
 470:             $rstemp=substr($rstemp,1);
 471:         }
 472: 
 473:         $j--;
 474:     }
 475: 
 476:     $codewords=array_merge($codewords,unpack("C*",$rstemp));
 477: 
 478:     $rs_block_number++;
 479: }
 480: 
 481: /* ---- flash matrix */
 482: 
 483: $i=0;
 484: while ($i<$max_modules_1side){
 485:     $j=0;
 486:     while ($j<$max_modules_1side){
 487:         $matrix_content[$j][$i]=0;
 488:         $j++;
 489:     }
 490:     $i++;
 491: }
 492: 
 493: /* --- attach data */
 494: 
 495: $i=0;
 496: while ($i<$max_codewords){
 497:     $codeword_i=$codewords[$i];
 498:     $j=8;
 499:     while ($j>=1){
 500:         $codeword_bits_number=($i << 3+  $j;
 501:         $matrix_content$matrix_x_array[$codeword_bits_number] ][ $matrix_y_array[$codeword_bits_number] ]=((255*($codeword_i & 1)) ^ $mask_array[$codeword_bits_number] ); 
 502:         $codeword_i$codeword_i >> 1;
 503:         $j--;
 504:     }
 505:     $i++;
 506: }
 507: 
 508: $matrix_remain=$matrix_remain_bit[$versionQR];
 509: while ($matrix_remain){
 510:     $remain_bit_temp = $matrix_remain + ( $max_codewords <<3);
 511:     $matrix_content$matrix_x_array[$remain_bit_temp] ][ $matrix_y_array[$remain_bit_temp] ]  =  ( 255 ^ $mask_array[$remain_bit_temp] );
 512:     $matrix_remain--;
 513: }
 514: 
 515: #--- mask select
 516: 
 517: $min_demerit_score=0;
 518:     $hor_master="";
 519:     $ver_master="";
 520:     $k=0;
 521:     while($k<$max_modules_1side){
 522:         $l=0;
 523:         while($l<$max_modules_1side){
 524:             $hor_master=$hor_master.chr($matrix_content[$l][$k]);
 525:             $ver_master=$ver_master.chr($matrix_content[$k][$l]);
 526:             $l++;
 527:         }
 528:         $k++;
 529:     }
 530: $i=0;
 531: $all_matrix=$max_modules_1side * $max_modules_1side
 532: while ($i<8){
 533:     $demerit_n1=0;
 534:     $ptn_temp=array();
 535:     $bit1<< $i;
 536:     $bit_r=(~$bit)&255;
 537:     $bit_mask=str_repeat(chr($bit),$all_matrix);
 538:     $hor = $hor_master & $bit_mask;
 539:     $ver = $ver_master & $bit_mask;
 540: 
 541:     $ver_shift1=$ver.str_repeat(chr(170),$max_modules_1side);
 542:     $ver_shift2=str_repeat(chr(170),$max_modules_1side).$ver;
 543:     $ver_shift1_0=$ver.str_repeat(chr(0),$max_modules_1side);
 544:     $ver_shift2_0=str_repeat(chr(0),$max_modules_1side).$ver;
 545:     $ver_or=chunk_split(~($ver_shift1 | $ver_shift2),$max_modules_1side,chr(170));
 546:     $ver_and=chunk_split(~($ver_shift1_0 & $ver_shift2_0),$max_modules_1side,chr(170));
 547: 
 548:     $hor=chunk_split(~$hor,$max_modules_1side,chr(170));
 549:     $ver=chunk_split(~$ver,$max_modules_1side,chr(170));
 550:     $hor=$hor.chr(170).$ver;
 551: 
 552:     $n1_search="/".str_repeat(chr(255),5)."+|".str_repeat(chr($bit_r),5)."+/";
 553:     $n3_search=chr($bit_r).chr(255).chr($bit_r).chr($bit_r).chr($bit_r).chr(255).chr($bit_r);
 554: 
 555:    $demerit_n3=substr_count($hor,$n3_search)*40;
 556:    $demerit_n4=floor(abs(( (100* (substr_count($ver,chr($bit_r))/($byte_num)) )-50)/5))*10;
 557: 
 558: 
 559:    $n2_search1="/".chr($bit_r).chr($bit_r)."+/";
 560:    $n2_search2="/".chr(255).chr(255)."+/";
 561:    $demerit_n2=0;
 562:    preg_match_all($n2_search1,$ver_and,$ptn_temp);
 563:    foreach($ptn_temp[0as $str_temp){
 564:        $demerit_n2+=(strlen($str_temp)-1);
 565:    }
 566:    $ptn_temp=array();
 567:    preg_match_all($n2_search2,$ver_or,$ptn_temp);
 568:    foreach($ptn_temp[0as $str_temp){
 569:        $demerit_n2+=(strlen($str_temp)-1);
 570:    }
 571:    $demerit_n2*=3;
 572:   
 573:    $ptn_temp=array();
 574: 
 575:    preg_match_all($n1_search,$hor,$ptn_temp);
 576:    foreach($ptn_temp[0as $str_temp){
 577:        $demerit_n1+=(strlen($str_temp)-2);
 578:    }
 579: 
 580:    $demerit_score=$demerit_n1+$demerit_n2+$demerit_n3+$demerit_n4;
 581: 
 582:    if ($demerit_score<=$min_demerit_score || $i==0){
 583:         $mask_number=$i;
 584:         $min_demerit_score=$demerit_score;
 585:    }
 586: 
 587: $i++;
 588: }
 589: 
 590: $mask_content=1 << $mask_number;
 591: 
 592: # --- format information
 593: 
 594: $format_information_value=(($ec << 3| $mask_number);
 595: $format_information_array=array("101010000010010","101000100100101",
 596: "101111001111100","101101101001011","100010111111001","100000011001110",
 597: "100111110010111","100101010100000","111011111000100","111001011110011",
 598: "111110110101010","111100010011101","110011000101111","110001100011000",
 599: "110110001000001","110100101110110","001011010001001","001001110111110",
 600: "001110011100111","001100111010000","000011101100010","000001001010101",
 601: "000110100001100","000100000111011","011010101011111","011000001101000",
 602: "011111100110001","011101000000110","010010010110100","010000110000011",
 603: "010111011011010","010101111101101");
 604: $i=0;
 605: while ($i<15){
 606:     $content=substr($format_information_array[$format_information_value],$i,1);
 607: 
 608:     $matrix_content[$format_information_x1[$i]][$format_information_y1[$i]]=$content * 255;
 609:     $matrix_content[$format_information_x2[$i+1]][$format_information_y2[$i+1]]=$content * 255;
 610:     $i++;
 611: }
 612: 
 613: 
 614: $mib = $max_modules_1side + 8;
 615: // $qrcode_image_size = $mib * $this->qrcode_module_size;
 616: 
 617: $output_image = imagecreate($imageSize, $imageSize);
 618: 
 619: $this->imagePath = $this->imagePath . '/qrv' . $versionQR . '.png';
 620: 
 621: $base_image = imagecreatefrompng($this->imagePath);
 622: 
 623: $col[1] = ImageColorAllocate($base_image, 0, 0, 0);
 624: $col[0] = ImageColorAllocate($base_image, 255, 255, 255);
 625: 
 626: $i = 4;
 627: $mxe = 4 + $max_modules_1side;
 628: $ii = 0;
 629: while ($i<$mxe){
 630:     $j = 4;
 631:     $jj = 0;
 632:     while ($j < $mxe){
 633:         if ($matrix_content[$ii][$jj& $mask_content){
 634:             ImageSetPixel($base_image,$i,$j,$col[1]); 
 635:         }
 636:         $j++;
 637:         $jj++;
 638:     }
 639:     $i++;
 640:     $ii++;
 641: }
 642: 
 643: /*
 644: #--- output image
 645: #
 646: */
 647: //Header("Content-type: image/" . $imageType);
 648: imagecopyresized($output_image, $base_image, 0, 0, 0, 0, $imageSize, $imageSize, $mib, $mib);
 649: if ($imageType == 'jpeg'){
 650:     $mimeType = 'image' . $imageType;
 651:     ob_start();
 652:     imagejpeg($output_image);
 653:     $imageData = ob_get_clean();
 654: else {
 655:     $mimeType = 'image' . $imageType;
 656:     ob_start();
 657:     imagepng($output_image);
 658:     $imageData = ob_get_clean();
 659: }
 660: 
 661:     return $imageData;
 662: }

解説:メイン・プログラム

メイン・プログラムは、入力テキストを text2QRimage メソッドに渡し、QRコードの画像データを作成するという単純な流れである。

qr_sample.php

 317: // インスタンス生成
 318: $pqi = new pahooQRimage();
 319: 
 320: // パラメータ取得
 321: $errmsg = '';
 322: $text = getValidString('text', $errmsg, DEF_TEXT, 0, MAX_TEXT_LENGTH);
 323: 
 324: // QRコード生成
 325: if (($errmsg === ''&& ($text !== '')) {
 326:     $imageData = $pqi->text2QRimage($text, WIDTH_QRCODE);
 327:     $base64 = $pqi->image2base64($imageData);
 328: else {
 329:     $url = '';
 330: }
 331: 
 332: // 表示HTML生成
 333: $HtmlBody = makeCommonBody($text, $base64, $errmsg);
 334: 
 335: // 表示処理
 336: echo $HtmlHeader;
 337: echo $HtmlBody;
 338: echo $HtmlFooter;
 339: 
 340: // インスタンス解放
 341: $pqi = NULL;

解説:HTML BODYを作成する

HTMLのtextareaタグを使い、QRコードにしたいテキストを入力する。
QRコードは、imgタグの中でQRimageのリクエストURLを呼び出している。

qr_sample.php

 225: /**
 226:  * HTML BODYを作成する
 227:  * @param   string $text   QRコードにするテキスト
 228:  * @param   string $base64 QRコード画像データ(BASE64エンコード)
 229:  * @param   string $errmsg エラー・メッセージ
 230:  * @return  string HTML BODY
 231: */
 232: function makeCommonBody($text, $base64, $errmsg) {
 233:     $myself  = MYSELF;
 234:     $refere  = REFERENCE;
 235:     $width   = WIDTH;
 236:     $title   = TITLE;
 237:     $maxChars = MAX_TEXT_LENGTH + 10;
 238:     $version = '<span style="font-size:small;">' . date('Y/m/d版', filemtime(__FILE__)) . '</span>';
 239:     $debug   = '';
 240: 
 241:     // QRコード(画像)のタグ
 242:     if ($errmsg === '') {
 243:         $res =<<< EOT
 244: <img src="{$base64}" alt="base64">
 245: 
 246: EOT;
 247:     } else {
 248:         $res =<<< EOT
 249: <p style="color:ref;">{$errmsg}</p>
 250: 
 251: EOT;
 252:     }
 253: 
 254:     // デバッグ情報
 255:     if (! FLAG_RELEASE) {
 256:         $phpver = phpversion();
 257:         $debug =<<< EOT
 258: <div>
 259: <span style="font-weight:bold;">★デバックモードで動作中...</span><br>
 260: PHPver : {$phpver}
 261: </div>
 262: 
 263: EOT;
 264:     }
 265:     $body =<<< EOT
 266: <body>
 267: <h2>{$title} {$version}</h2>
 268: <form name="myform" method="post" action="{$myself}" enctype="multipart/form-data">
 269: テキスト<br>
 270: <textarea id="text" name="text" maxlength="{$maxChars}">
 271: {$text}
 272: </textarea>
 273: 
 274: <div class="counter">
 275: <input type="submit" name="exec" id="exec" value="作成">
 276: 
 277: <span id="counterContainar">
 278: <span id="charCounter"></span>
 279: <svg class="progress" viewBox="0 0 36 36">
 280:     <path
 281:         d="M18 2a16 16 0 1 1 0 32 16 16 0 0 1 0-32"
 282:         fill="none"
 283:         stroke="lightsteelblue"
 284:         stroke-width="4.0"
 285:     />
 286:     <path
 287:         id="progressBar"
 288:         d="M18 2a16 16 0 1 1 0 32 16 16 0 0 1 0-32"
 289:         fill="none"
 290:         stroke="royalblue"
 291:         stroke-width="4.0"
 292:         stroke-dasharray="100, 100"
 293:     />
 294: </svg>
 295: </span>
 296: </div>
 297: 
 298: {$res}
 299: </form>
 300: 
 301: <div style="border-style:solid; border-width:1px; margin:20px 0px 0px 0px; padding:5px; width:{$width}px; font-size:small; overflow-wrap:break-word; word-break:break-all;">
 302: <h3>使い方</h3>
 303: <ol>
 304: <li>[<span style="font-weight:bold;">テキスト</span>]にQRコードにしたいテキストを入力し,[<span style="font-weight:bold;">作成</span>] ボタンを押してください.</li>
 305: <li>QRコードを表示します.</li>
 306: </ol>
 307: ※参考サイト:<a href="{$refere}">{$refere}</a>
 308: {$debug}
 309: </div>
 310: </body>
 311: 
 312: EOT;
 313:     return $body;
 314: }

参考サイト

(この項おわり)
header