QRinputItem.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. <?php
  2. namespace PHPQRCode;
  3. use Exception;
  4. class QRinputItem {
  5. public $mode;
  6. public $size;
  7. public $data;
  8. public $bstream;
  9. public function __construct($mode, $size, $data, $bstream = null)
  10. {
  11. $setData = array_slice($data, 0, $size);
  12. if (count($setData) < $size) {
  13. $setData = array_merge($setData, array_fill(0,$size-count($setData),0));
  14. }
  15. if(!QRinput::check($mode, $size, $setData)) {
  16. throw new Exception('Error m:'.$mode.',s:'.$size.',d:'.join(',',$setData));
  17. return null;
  18. }
  19. $this->mode = $mode;
  20. $this->size = $size;
  21. $this->data = $setData;
  22. $this->bstream = $bstream;
  23. }
  24. //----------------------------------------------------------------------
  25. public function encodeModeNum($version)
  26. {
  27. try {
  28. $words = (int)($this->size / 3);
  29. $bs = new QRbitstream();
  30. $val = 0x1;
  31. $bs->appendNum(4, $val);
  32. $bs->appendNum(QRspec::lengthIndicator(Constants::QR_MODE_NUM, $version), $this->size);
  33. for($i=0; $i<$words; $i++) {
  34. $val = (ord($this->data[$i*3 ]) - ord('0')) * 100;
  35. $val += (ord($this->data[$i*3+1]) - ord('0')) * 10;
  36. $val += (ord($this->data[$i*3+2]) - ord('0'));
  37. $bs->appendNum(10, $val);
  38. }
  39. if($this->size - $words * 3 == 1) {
  40. $val = ord($this->data[$words*3]) - ord('0');
  41. $bs->appendNum(4, $val);
  42. } else if($this->size - $words * 3 == 2) {
  43. $val = (ord($this->data[$words*3 ]) - ord('0')) * 10;
  44. $val += (ord($this->data[$words*3+1]) - ord('0'));
  45. $bs->appendNum(7, $val);
  46. }
  47. $this->bstream = $bs;
  48. return 0;
  49. } catch (Exception $e) {
  50. return -1;
  51. }
  52. }
  53. //----------------------------------------------------------------------
  54. public function encodeModeAn($version)
  55. {
  56. try {
  57. $words = (int)($this->size / 2);
  58. $bs = new QRbitstream();
  59. $bs->appendNum(4, 0x02);
  60. $bs->appendNum(QRspec::lengthIndicator(Constants::QR_MODE_AN, $version), $this->size);
  61. for($i=0; $i<$words; $i++) {
  62. $val = (int)QRinput::lookAnTable(ord($this->data[$i*2 ])) * 45;
  63. $val += (int)QRinput::lookAnTable(ord($this->data[$i*2+1]));
  64. $bs->appendNum(11, $val);
  65. }
  66. if($this->size & 1) {
  67. $val = QRinput::lookAnTable(ord($this->data[$words * 2]));
  68. $bs->appendNum(6, $val);
  69. }
  70. $this->bstream = $bs;
  71. return 0;
  72. } catch (Exception $e) {
  73. return -1;
  74. }
  75. }
  76. //----------------------------------------------------------------------
  77. public function encodeMode8($version)
  78. {
  79. try {
  80. $bs = new QRbitstream();
  81. $bs->appendNum(4, 0x4);
  82. $bs->appendNum(QRspec::lengthIndicator(Constants::QR_MODE_8, $version), $this->size);
  83. for($i=0; $i<$this->size; $i++) {
  84. $bs->appendNum(8, ord($this->data[$i]));
  85. }
  86. $this->bstream = $bs;
  87. return 0;
  88. } catch (Exception $e) {
  89. return -1;
  90. }
  91. }
  92. //----------------------------------------------------------------------
  93. public function encodeModeKanji($version)
  94. {
  95. try {
  96. $bs = new QRbitstream();
  97. $bs->appendNum(4, 0x8);
  98. $bs->appendNum(QRspec::lengthIndicator(Constants::QR_MODE_KANJI, $version), (int)($this->size / 2));
  99. for($i=0; $i<$this->size; $i+=2) {
  100. $val = (ord($this->data[$i]) << 8) | ord($this->data[$i+1]);
  101. if($val <= 0x9ffc) {
  102. $val -= 0x8140;
  103. } else {
  104. $val -= 0xc140;
  105. }
  106. $h = ($val >> 8) * 0xc0;
  107. $val = ($val & 0xff) + $h;
  108. $bs->appendNum(13, $val);
  109. }
  110. $this->bstream = $bs;
  111. return 0;
  112. } catch (Exception $e) {
  113. return -1;
  114. }
  115. }
  116. //----------------------------------------------------------------------
  117. public function encodeModeStructure()
  118. {
  119. try {
  120. $bs = new QRbitstream();
  121. $bs->appendNum(4, 0x03);
  122. $bs->appendNum(4, ord($this->data[1]) - 1);
  123. $bs->appendNum(4, ord($this->data[0]) - 1);
  124. $bs->appendNum(8, ord($this->data[2]));
  125. $this->bstream = $bs;
  126. return 0;
  127. } catch (Exception $e) {
  128. return -1;
  129. }
  130. }
  131. //----------------------------------------------------------------------
  132. public function estimateBitStreamSizeOfEntry($version)
  133. {
  134. $bits = 0;
  135. if($version == 0)
  136. $version = 1;
  137. switch($this->mode) {
  138. case Constants::QR_MODE_NUM: $bits = QRinput::estimateBitsModeNum($this->size); break;
  139. case Constants::QR_MODE_AN: $bits = QRinput::estimateBitsModeAn($this->size); break;
  140. case Constants::QR_MODE_8: $bits = QRinput::estimateBitsMode8($this->size); break;
  141. case Constants::QR_MODE_KANJI: $bits = QRinput::estimateBitsModeKanji($this->size);break;
  142. case Constants::QR_MODE_STRUCTURE: return Constants::STRUCTURE_HEADER_BITS;
  143. default:
  144. return 0;
  145. }
  146. $l = QRspec::lengthIndicator($this->mode, $version);
  147. $m = 1 << $l;
  148. $num = (int)(($this->size + $m - 1) / $m);
  149. $bits += $num * (4 + $l);
  150. return $bits;
  151. }
  152. //----------------------------------------------------------------------
  153. public function encodeBitStream($version)
  154. {
  155. try {
  156. unset($this->bstream);
  157. $words = QRspec::maximumWords($this->mode, $version);
  158. if($this->size > $words) {
  159. $st1 = new QRinputItem($this->mode, $words, $this->data);
  160. $st2 = new QRinputItem($this->mode, $this->size - $words, array_slice($this->data, $words));
  161. $st1->encodeBitStream($version);
  162. $st2->encodeBitStream($version);
  163. $this->bstream = new QRbitstream();
  164. $this->bstream->append($st1->bstream);
  165. $this->bstream->append($st2->bstream);
  166. unset($st1);
  167. unset($st2);
  168. } else {
  169. $ret = 0;
  170. switch($this->mode) {
  171. case Constants::QR_MODE_NUM: $ret = $this->encodeModeNum($version); break;
  172. case Constants::QR_MODE_AN: $ret = $this->encodeModeAn($version); break;
  173. case Constants::QR_MODE_8: $ret = $this->encodeMode8($version); break;
  174. case Constants::QR_MODE_KANJI: $ret = $this->encodeModeKanji($version);break;
  175. case Constants::QR_MODE_STRUCTURE: $ret = $this->encodeModeStructure(); break;
  176. default:
  177. break;
  178. }
  179. if($ret < 0)
  180. return -1;
  181. }
  182. return $this->bstream->size();
  183. } catch (Exception $e) {
  184. return -1;
  185. }
  186. }
  187. }