qrcode.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. <?php
  2. /**
  3. *
  4. * QRcode image PHP script version 0.50i (C)2000-2009,Y.Swetake
  5. *
  6. * ****************************************************************
  7. * Converted to PHP class, reorganized, tweaked with memory release
  8. * by michal@freelogic.pl (http://freelogic.pl/thumbnailer).
  9. * ****************************************************************
  10. *
  11. * This program outputs a png image of "QRcode model 2".
  12. * You cannot use a several functions of QRcode in this version.
  13. * See README.txt .
  14. *
  15. * This version supports QRcode model2 version 1-40.
  16. * This program requires PHP5 and gd 1.6 or higher.
  17. * You must set $path & $this->image_path the path to QRcode data file.
  18. *
  19. * [settings]
  20. * d=data URL encoded data.
  21. * e=ECC level L or M or Q or H (default M)
  22. * s=module size (dafault PNG:4 JPEG:8)
  23. * v=version 1-40 or Auto select if you do not set.
  24. * t=image type J:jpeg image , other: PNG image
  25. *
  26. * structured append m of n (experimental)
  27. * n=structure append n (2-16)
  28. * m=structure append m (1-16)
  29. * p=parity
  30. * o=original data (URL encoded data) for calculating parity
  31. *
  32. * THIS SOFTWARE IS PROVIDED BY Y.Swetake ``AS IS'' AND ANY EXPRESS OR
  33. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  34. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  35. * IN NO EVENT SHALL Y.Swetake OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  36. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  37. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  38. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  39. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  40. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  41. * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  42. */
  43. namespace app\components\qrcode;
  44. use Yii;
  45. class qrcode extends \yii\base\Component{
  46. /**
  47. * Path to data files.
  48. * @var string Path
  49. */
  50. public $path;
  51. /**
  52. * Path for QRCode frame images.
  53. * @var string Path
  54. */
  55. public $image_path;
  56. /**
  57. * Upper limit for version.
  58. * @var int
  59. */
  60. public $version_ul=40;
  61. /**
  62. * Data string
  63. * @var string
  64. */
  65. public $data_string;
  66. /**
  67. * Error correction.
  68. * @var string
  69. */
  70. public $error_correct;
  71. /**
  72. * Module size
  73. * @var int
  74. */
  75. public $module_size;
  76. /**
  77. * Version.
  78. * @var int
  79. */
  80. public $version;
  81. /**
  82. * Image type.
  83. * @var string
  84. */
  85. public $image_type='P';
  86. public $structureappend_n;
  87. public $structureappend_m;
  88. public $structureappend_parity;
  89. public $structureappend_originaldata;
  90. public function __construct($data)
  91. {
  92. $this->data_string=$data;
  93. $this->error_correct='M';
  94. $this->path=dirname(__FILE__).'/data';
  95. $this->image_path=dirname(__FILE__).'/image';
  96. }
  97. /**
  98. * Generate QR Code matrix
  99. * @param string $output Output file. If not set will flush directly to browser
  100. */
  101. public function create($output=null)
  102. {
  103. if (($this->image_type=='J')||($this->image_type=='j')){
  104. $this->image_type='jpeg';
  105. }else {
  106. $this->image_type='png';
  107. }
  108. if ($this->module_size>0) {
  109. } else {
  110. if ($this->image_type=='png'){
  111. $this->module_size=8;
  112. } else {
  113. $this->module_size=4;
  114. }
  115. }
  116. $data_length=strlen($this->data_string);
  117. if ($data_length<=0) {
  118. throw new \Exception('Data must not be empty');
  119. }
  120. $data_counter=0;
  121. if ($this->structureappend_n>1
  122. && $this->structureappend_n<=16
  123. && $this->structureappend_m>0
  124. && $qrcode_structureqppend_m<=16){
  125. $data_value[0]=3;
  126. $data_bits[0]=4;
  127. $data_value[1]=$this->structureappend_m-1;
  128. $data_bits[1]=4;
  129. $data_value[2]=$this->structureappend_n-1;
  130. $data_bits[2]=4;
  131. $originaldata_length=strlen($this->structureappend_originaldata);
  132. if ($originaldata_length>1){
  133. $this->structureappend_parity=0;
  134. $i=0;
  135. while ($i<$originaldata_length){
  136. $this->structureappend_parity=($this->structureappend_parity ^ ord(substr($this->structureappend_originaldata,$i,1)));
  137. $i++;
  138. }
  139. }
  140. $data_value[3]=$this->structureappend_parity;
  141. $data_bits[3]=8;
  142. $data_counter=4;
  143. }
  144. $data_bits[$data_counter]=4;
  145. /* --- determine encode mode */
  146. if (preg_match("/[^0-9]/",$this->data_string)!=0){
  147. if (preg_match("/[^0-9A-Z \$\*\%\+\.\/\:\-]/",$this->data_string)!=0) {
  148. /* --- 8bit byte mode */
  149. $codeword_num_plus=array(0,0,0,0,0,0,0,0,0,0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8);
  150. $data_value[$data_counter]=4;
  151. $data_counter++;
  152. $data_value[$data_counter]=$data_length;
  153. $data_bits[$data_counter]=8; /* #version 1-9 */
  154. $codeword_num_counter_value=$data_counter;
  155. $data_counter++;
  156. $i=0;
  157. while ($i<$data_length){
  158. $data_value[$data_counter]=ord(substr($this->data_string,$i,1));
  159. $data_bits[$data_counter]=8;
  160. $data_counter++;
  161. $i++;
  162. }
  163. } else {
  164. /* ---- alphanumeric mode */
  165. $codeword_num_plus=array(0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4);
  166. $data_value[$data_counter]=2;
  167. $data_counter++;
  168. $data_value[$data_counter]=$data_length;
  169. $data_bits[$data_counter]=9; /* #version 1-9 */
  170. $codeword_num_counter_value=$data_counter;
  171. $alphanumeric_character_hash=array("0"=>0,"1"=>1,"2"=>2,"3"=>3,"4"=>4,"5"=>5,"6"=>6,"7"=>7,"8"=>8,"9"=>9,"A"=>10,"B"=>11,"C"=>12,"D"=>13,"E"=>14,"F"=>15,"G"=>16,"H"=>17,"I"=>18,"J"=>19,"K"=>20,"L"=>21,"M"=>22,"N"=>23,"O"=>24,"P"=>25,"Q"=>26,"R"=>27,"S"=>28,"T"=>29,"U"=>30,"V"=>31,"W"=>32,"X"=>33,"Y"=>34,"Z"=>35," "=>36,"$"=>37,"%"=>38,"*"=>39,"+"=>40,"-"=>41,"."=>42,"/"=>43,":"=>44);
  172. $i=0;
  173. $data_counter++;
  174. while ($i<$data_length){
  175. if (($i %2)==0){
  176. $data_value[$data_counter]=$alphanumeric_character_hash[substr($this->data_string,$i,1)];
  177. $data_bits[$data_counter]=6;
  178. } else {
  179. $data_value[$data_counter]=$data_value[$data_counter]*45+$alphanumeric_character_hash[substr($this->data_string,$i,1)];
  180. $data_bits[$data_counter]=11;
  181. $data_counter++;
  182. }
  183. $i++;
  184. }
  185. }
  186. } else {
  187. /* ---- numeric mode */
  188. $codeword_num_plus=array(0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4);
  189. $data_value[$data_counter]=1;
  190. $data_counter++;
  191. $data_value[$data_counter]=$data_length;
  192. $data_bits[$data_counter]=10; /* #version 1-9 */
  193. $codeword_num_counter_value=$data_counter;
  194. $i=0;
  195. $data_counter++;
  196. while ($i<$data_length){
  197. if (($i % 3)==0){
  198. $data_value[$data_counter]=substr($this->data_string,$i,1);
  199. $data_bits[$data_counter]=4;
  200. } else {
  201. $data_value[$data_counter]=$data_value[$data_counter]*10+substr($this->data_string,$i,1);
  202. if (($i % 3)==1){
  203. $data_bits[$data_counter]=7;
  204. } else {
  205. $data_bits[$data_counter]=10;
  206. $data_counter++;
  207. }
  208. }
  209. $i++;
  210. }
  211. }
  212. if (@$data_bits[$data_counter]>0) {
  213. $data_counter++;
  214. }
  215. $i=0;
  216. $total_data_bits=0;
  217. while($i<$data_counter){
  218. $total_data_bits+=$data_bits[$i];
  219. $i++;
  220. }
  221. $ecc_character_hash=array("L"=>"1",
  222. "l"=>"1",
  223. "M"=>"0",
  224. "m"=>"0",
  225. "Q"=>"3",
  226. "q"=>"3",
  227. "H"=>"2",
  228. "h"=>"2");
  229. $ec=@$ecc_character_hash[$this->error_correct];
  230. if (!$ec){$ec=0;}
  231. $max_data_bits_array=array(
  232. 0,128,224,352,512,688,864,992,1232,1456,1728,
  233. 2032,2320,2672,2920,3320,3624,4056,4504,5016,5352,
  234. 5712,6256,6880,7312,8000,8496,9024,9544,10136,10984,
  235. 11640,12328,13048,13800,14496,15312,15936,16816,17728,18672,
  236. 152,272,440,640,864,1088,1248,1552,1856,2192,
  237. 2592,2960,3424,3688,4184,4712,5176,5768,6360,6888,
  238. 7456,8048,8752,9392,10208,10960,11744,12248,13048,13880,
  239. 14744,15640,16568,17528,18448,19472,20528,21616,22496,23648,
  240. 72,128,208,288,368,480,528,688,800,976,
  241. 1120,1264,1440,1576,1784,2024,2264,2504,2728,3080,
  242. 3248,3536,3712,4112,4304,4768,5024,5288,5608,5960,
  243. 6344,6760,7208,7688,7888,8432,8768,9136,9776,10208,
  244. 104,176,272,384,496,608,704,880,1056,1232,
  245. 1440,1648,1952,2088,2360,2600,2936,3176,3560,3880,
  246. 4096,4544,4912,5312,5744,6032,6464,6968,7288,7880,
  247. 8264,8920,9368,9848,10288,10832,11408,12016,12656,13328
  248. );
  249. if (!$this->version){
  250. /* #--- auto version select */
  251. $i=1+40*$ec;
  252. $j=$i+39;
  253. $this->version=1;
  254. while ($i<=$j){
  255. if (($max_data_bits_array[$i])>=$total_data_bits+$codeword_num_plus[$this->version] ){
  256. $max_data_bits=$max_data_bits_array[$i];
  257. break;
  258. }
  259. $i++;
  260. $this->version++;
  261. }
  262. } else {
  263. $max_data_bits=$max_data_bits_array[$this->version+40*$ec];
  264. }
  265. if ($this->version>$this->version_ul){
  266. throw new \Exception('QRcode : too large version');
  267. }
  268. $total_data_bits+=$codeword_num_plus[$this->version];
  269. $data_bits[$codeword_num_counter_value]+=$codeword_num_plus[$this->version];
  270. $max_codewords_array=array(0,26,44,70,100,134,172,196,242,
  271. 292,346,404,466,532,581,655,733,815,901,991,1085,1156,
  272. 1258,1364,1474,1588,1706,1828,1921,2051,2185,2323,2465,
  273. 2611,2761,2876,3034,3196,3362,3532,3706);
  274. $max_codewords=$max_codewords_array[$this->version];
  275. $max_modules_1side=17+($this->version <<2);
  276. $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,
  277. 4,4,4,4,4,4,4,3,3,3,3,3,3,3,0,0,0,0,0,0);
  278. /* ---- read version ECC data file */
  279. $byte_num=$matrix_remain_bit[$this->version]+($max_codewords << 3);
  280. $filename=$this->path."/qrv".$this->version."_".$ec.".dat";
  281. $fp1=fopen ($filename, "rb");
  282. $matx=fread($fp1,$byte_num);
  283. $maty=fread($fp1,$byte_num);
  284. $masks=fread($fp1,$byte_num);
  285. $fi_x=fread($fp1,15);
  286. $fi_y=fread($fp1,15);
  287. $rs_ecc_codewords=ord(fread($fp1,1));
  288. $rso=fread($fp1,128);
  289. fclose($fp1);
  290. $matrix_x_array=unpack("C*",$matx);
  291. $matrix_y_array=unpack("C*",$maty);
  292. $mask_array=unpack("C*",$masks);
  293. $rs_block_order=unpack("C*",$rso);
  294. $format_information_x2=unpack("C*",$fi_x);
  295. $format_information_y2=unpack("C*",$fi_y);
  296. $format_information_x1=array(0,1,2,3,4,5,7,8,8,8,8,8,8,8,8);
  297. $format_information_y1=array(8,8,8,8,8,8,8,8,7,5,4,3,2,1,0);
  298. $max_data_codewords=($max_data_bits >>3);
  299. $filename=$this->path."/rsc".$rs_ecc_codewords.".dat";
  300. $fp0=fopen ($filename, "rb");
  301. $i=0;
  302. while ($i<256) {
  303. $rs_cal_table_array[$i]=fread ($fp0,$rs_ecc_codewords);
  304. $i++;
  305. }
  306. fclose ($fp0);
  307. /* --- set terminator */
  308. if ($total_data_bits<=$max_data_bits-4){
  309. $data_value[$data_counter]=0;
  310. $data_bits[$data_counter]=4;
  311. } else {
  312. if ($total_data_bits<$max_data_bits){
  313. $data_value[$data_counter]=0;
  314. $data_bits[$data_counter]=$max_data_bits-$total_data_bits;
  315. } else {
  316. if ($total_data_bits>$max_data_bits){
  317. trigger_error("QRcode : Overflow error",E_USER_ERROR);
  318. exit;
  319. }
  320. }
  321. }
  322. /* ----divide data by 8bit */
  323. $i=0;
  324. $codewords_counter=0;
  325. $codewords[0]=0;
  326. $remaining_bits=8;
  327. while ($i<=$data_counter) {
  328. $buffer=@$data_value[$i];
  329. $buffer_bits=@$data_bits[$i];
  330. $flag=1;
  331. while ($flag) {
  332. if ($remaining_bits>$buffer_bits){
  333. $codewords[$codewords_counter]=((@$codewords[$codewords_counter]<<$buffer_bits) | $buffer);
  334. $remaining_bits-=$buffer_bits;
  335. $flag=0;
  336. } else {
  337. $buffer_bits-=$remaining_bits;
  338. $codewords[$codewords_counter]=(($codewords[$codewords_counter] << $remaining_bits) | ($buffer >> $buffer_bits));
  339. if ($buffer_bits==0) {
  340. $flag=0;
  341. } else {
  342. $buffer=($buffer & ((1 << $buffer_bits)-1) );
  343. $flag=1;
  344. }
  345. $codewords_counter++;
  346. if ($codewords_counter<$max_data_codewords-1){
  347. $codewords[$codewords_counter]=0;
  348. }
  349. $remaining_bits=8;
  350. }
  351. }
  352. $i++;
  353. }
  354. if ($remaining_bits!=8) {
  355. $codewords[$codewords_counter]=$codewords[$codewords_counter] << $remaining_bits;
  356. } else {
  357. $codewords_counter--;
  358. }
  359. /* ---- set padding character */
  360. if ($codewords_counter<$max_data_codewords-1){
  361. $flag=1;
  362. while ($codewords_counter<$max_data_codewords-1){
  363. $codewords_counter++;
  364. if ($flag==1) {
  365. $codewords[$codewords_counter]=236;
  366. } else {
  367. $codewords[$codewords_counter]=17;
  368. }
  369. $flag=$flag*(-1);
  370. }
  371. }
  372. /* ---- RS-ECC prepare */
  373. $i=0;
  374. $j=0;
  375. $rs_block_number=0;
  376. $rs_temp[0]="";
  377. while($i<$max_data_codewords){
  378. $rs_temp[$rs_block_number].=chr($codewords[$i]);
  379. $j++;
  380. if ($j>=$rs_block_order[$rs_block_number+1]-$rs_ecc_codewords){
  381. $j=0;
  382. $rs_block_number++;
  383. $rs_temp[$rs_block_number]="";
  384. }
  385. $i++;
  386. }
  387. /*
  388. #
  389. # RS-ECC main
  390. #
  391. */
  392. $rs_block_number=0;
  393. $rs_block_order_num=count($rs_block_order);
  394. while ($rs_block_number<$rs_block_order_num){
  395. $rs_codewords=$rs_block_order[$rs_block_number+1];
  396. $rs_data_codewords=$rs_codewords-$rs_ecc_codewords;
  397. $rstemp=$rs_temp[$rs_block_number].str_repeat(chr(0),$rs_ecc_codewords);
  398. $padding_data=str_repeat(chr(0),$rs_data_codewords);
  399. $j=$rs_data_codewords;
  400. while($j>0){
  401. $first=ord(substr($rstemp,0,1));
  402. if ($first){
  403. $left_chr=substr($rstemp,1);
  404. $cal=$rs_cal_table_array[$first].$padding_data;
  405. $rstemp=$left_chr ^ $cal;
  406. } else {
  407. $rstemp=substr($rstemp,1);
  408. }
  409. $j--;
  410. }
  411. $codewords=array_merge($codewords,unpack("C*",$rstemp));
  412. $rs_block_number++;
  413. }
  414. /* ---- flash matrix */
  415. $i=0;
  416. while ($i<$max_modules_1side){
  417. $j=0;
  418. while ($j<$max_modules_1side){
  419. $matrix_content[$j][$i]=0;
  420. $j++;
  421. }
  422. $i++;
  423. }
  424. /* --- attach data */
  425. $i=0;
  426. while ($i<$max_codewords){
  427. $codeword_i=$codewords[$i];
  428. $j=8;
  429. while ($j>=1){
  430. $codeword_bits_number=($i << 3) + $j;
  431. $matrix_content[ $matrix_x_array[$codeword_bits_number] ][ $matrix_y_array[$codeword_bits_number] ]=((255*($codeword_i & 1)) ^ $mask_array[$codeword_bits_number] );
  432. $codeword_i=$codeword_i >> 1;
  433. $j--;
  434. }
  435. $i++;
  436. }
  437. $matrix_remain=$matrix_remain_bit[$this->version];
  438. while ($matrix_remain){
  439. $remain_bit_temp=$matrix_remain + ( $max_codewords <<3);
  440. $matrix_content[ $matrix_x_array[$remain_bit_temp] ][ $matrix_y_array[$remain_bit_temp] ]=( 255 ^ $mask_array[$remain_bit_temp] );
  441. $matrix_remain--;
  442. }
  443. #--- mask select
  444. $min_demerit_score=0;
  445. $hor_master="";
  446. $ver_master="";
  447. $k=0;
  448. while($k<$max_modules_1side){
  449. $l=0;
  450. while($l<$max_modules_1side){
  451. $hor_master=$hor_master.chr($matrix_content[$l][$k]);
  452. $ver_master=$ver_master.chr($matrix_content[$k][$l]);
  453. $l++;
  454. }
  455. $k++;
  456. }
  457. $i=0;
  458. $all_matrix=$max_modules_1side * $max_modules_1side;
  459. while ($i<8){
  460. $demerit_n1=0;
  461. $ptn_temp=array();
  462. $bit=1<< $i;
  463. $bit_r=(~$bit)&255;
  464. $bit_mask=str_repeat(chr($bit),$all_matrix);
  465. $hor=$hor_master & $bit_mask;
  466. $ver=$ver_master & $bit_mask;
  467. $ver_shift1=$ver.str_repeat(chr(170),$max_modules_1side);
  468. $ver_shift2=str_repeat(chr(170),$max_modules_1side).$ver;
  469. $ver_shift1_0=$ver.str_repeat(chr(0),$max_modules_1side);
  470. $ver_shift2_0=str_repeat(chr(0),$max_modules_1side).$ver;
  471. $ver_or=chunk_split(~($ver_shift1 | $ver_shift2),$max_modules_1side,chr(170));
  472. $ver_and=chunk_split(~($ver_shift1_0 & $ver_shift2_0),$max_modules_1side,chr(170));
  473. $hor=chunk_split(~$hor,$max_modules_1side,chr(170));
  474. $ver=chunk_split(~$ver,$max_modules_1side,chr(170));
  475. $hor=$hor.chr(170).$ver;
  476. $n1_search="/".str_repeat(chr(255),5)."+|".str_repeat(chr($bit_r),5)."+/";
  477. $n3_search=chr($bit_r).chr(255).chr($bit_r).chr($bit_r).chr($bit_r).chr(255).chr($bit_r);
  478. $demerit_n3=substr_count($hor,$n3_search)*40;
  479. $demerit_n4=floor(abs(( (100* (substr_count($ver,chr($bit_r))/($byte_num)) )-50)/5))*10;
  480. $n2_search1="/".chr($bit_r).chr($bit_r)."+/";
  481. $n2_search2="/".chr(255).chr(255)."+/";
  482. $demerit_n2=0;
  483. preg_match_all($n2_search1,$ver_and,$ptn_temp);
  484. foreach($ptn_temp[0] as $str_temp){
  485. $demerit_n2+=(strlen($str_temp)-1);
  486. }
  487. $ptn_temp=array();
  488. preg_match_all($n2_search2,$ver_or,$ptn_temp);
  489. foreach($ptn_temp[0] as $str_temp){
  490. $demerit_n2+=(strlen($str_temp)-1);
  491. }
  492. $demerit_n2*=3;
  493. $ptn_temp=array();
  494. preg_match_all($n1_search,$hor,$ptn_temp);
  495. foreach($ptn_temp[0] as $str_temp){
  496. $demerit_n1+=(strlen($str_temp)-2);
  497. }
  498. $demerit_score=$demerit_n1+$demerit_n2+$demerit_n3+$demerit_n4;
  499. if ($demerit_score<=$min_demerit_score || $i==0){
  500. $mask_number=$i;
  501. $min_demerit_score=$demerit_score;
  502. }
  503. $i++;
  504. }
  505. $mask_content=1 << $mask_number;
  506. # --- format information
  507. $format_information_value=(($ec << 3) | $mask_number);
  508. $format_information_array=array("101010000010010","101000100100101",
  509. "101111001111100","101101101001011","100010111111001","100000011001110",
  510. "100111110010111","100101010100000","111011111000100","111001011110011",
  511. "111110110101010","111100010011101","110011000101111","110001100011000",
  512. "110110001000001","110100101110110","001011010001001","001001110111110",
  513. "001110011100111","001100111010000","000011101100010","000001001010101",
  514. "000110100001100","000100000111011","011010101011111","011000001101000",
  515. "011111100110001","011101000000110","010010010110100","010000110000011",
  516. "010111011011010","010101111101101");
  517. $i=0;
  518. while ($i<15){
  519. $content=substr($format_information_array[$format_information_value],$i,1);
  520. $matrix_content[$format_information_x1[$i]][$format_information_y1[$i]]=$content * 255;
  521. $matrix_content[$format_information_x2[$i+1]][$format_information_y2[$i+1]]=$content * 255;
  522. $i++;
  523. }
  524. $mib=$max_modules_1side+8;
  525. $qrcode_image_size=$mib*$this->module_size;
  526. if ($qrcode_image_size>1480){
  527. throw new \Exception('QRcode : Too large image size');
  528. }
  529. $output_image=ImageCreate($qrcode_image_size,$qrcode_image_size);
  530. $this->image_path=$this->image_path.'/qrv'.$this->version.'.png';
  531. $base_image=ImageCreateFromPNG($this->image_path);
  532. $col[1]=ImageColorAllocate($base_image,0,0,0);
  533. $col[0]=ImageColorAllocate($base_image,255,255,255);
  534. $i=4;
  535. $mxe=4+$max_modules_1side;
  536. $ii=0;
  537. while ($i<$mxe){
  538. $j=4;
  539. $jj=0;
  540. while ($j<$mxe){
  541. if ($matrix_content[$ii][$jj] & $mask_content){
  542. ImageSetPixel($base_image,$i,$j,$col[1]);
  543. }
  544. $j++;
  545. $jj++;
  546. }
  547. $i++;
  548. $ii++;
  549. }
  550. imagecolordeallocate($base_image, $col[1]);
  551. imagecolordeallocate($base_image, $col[0]);
  552. imagecopyresampled($output_image,$base_image,0,0,0,0,$qrcode_image_size,$qrcode_image_size,$mib,$mib);
  553. if ($output == null) {
  554. header('Content-type: image/'.$this->image_type);
  555. }
  556. if ($this->image_type=='jpeg'){
  557. ImageJpeg($output_image, $output);
  558. } else {
  559. ImagePng($output_image, $output);
  560. }
  561. imagedestroy($output_image);
  562. }
  563. }
  564. ?>