diff --git a/examples/custom.php b/examples/custom.php
new file mode 100644
index 000000000..4f552b5c1
--- /dev/null
+++ b/examples/custom.php
@@ -0,0 +1,24 @@
+addData('otpauth://totp/test?secret=B3JX4VCVJDVNXNZ5&issuer=chillerlan.net')
+ ->make();
+
+for($row = 0; $row < $qrcode->moduleCount; $row++){
+ for($col = 0; $col < $qrcode->moduleCount; $col++){
+ echo $qrcode->isDark($row, $col) ? 'X' : ' ';
+ }
+ echo PHP_EOL;
+}
+
+echo 'QRCode '.round((microtime(true)-$starttime), 5).PHP_EOL;
diff --git a/examples/html.php b/examples/html.php
new file mode 100644
index 000000000..196c87d1f
--- /dev/null
+++ b/examples/html.php
@@ -0,0 +1,35 @@
+
+.qrcode{
+ border-style:none;
+ border-collapse:collapse;
+ margin:0;
+ padding:0;
+}
+
+.dark, .light{
+ margin:0;
+ padding:0;
+ width: 1.25mm;
+ height: 1.25mm;
+}
+
+.dark{
+ background-color: #000;
+}
+
+.light{
+ background-color: #fff;
+}
+';
+
+// google authenticator
+$qr = (new QRCode)->getMinimumQRCode('otpauth://totp/test?secret=B3JX4VCVJDVNXNZ5&issuer=chillerlan.net', QRConst::ERROR_CORRECT_LEVEL_M);
+echo $qr->printHTML();
diff --git a/examples/image.php b/examples/image.php
new file mode 100644
index 000000000..91a814c8b
--- /dev/null
+++ b/examples/image.php
@@ -0,0 +1,15 @@
+getMinimumQRCode('otpauth://totp/test?secret=B3JX4VCVJDVNXNZ5&issuer=chillerlan.net', QRConst::ERROR_CORRECT_LEVEL_L);
+
+header('Content-type: image/png');
+
+$im = $qr->createImage(5, 5);
+imagepng($im);
+imagedestroy($im);
diff --git a/examples/sample_custom.php b/examples/sample_custom.php
deleted file mode 100644
index 21e68420a..000000000
--- a/examples/sample_custom.php
+++ /dev/null
@@ -1,22 +0,0 @@
-getMinimumQRCode('イメージ作成(引数:サイズ,マージン', QRConst::ERROR_CORRECT_LEVEL_L);
-
-
-header('Content-type: text/plain');
-
-$m = $qr->getModuleCount();
-
-for($row = 0; $row < $m; $row++){
- for($col = 0; $col < $m; $col++){
- echo $qr->isDark($row, $col) ? '#' : ' ';
- }
- echo PHP_EOL;
-}
-
diff --git a/examples/sample_html.php b/examples/sample_html.php
deleted file mode 100644
index d31a4414a..000000000
--- a/examples/sample_html.php
+++ /dev/null
@@ -1,42 +0,0 @@
-明示的に型番を指定');
-
-// エラー訂正レベルを設定
-// QR_ERROR_CORRECT_LEVEL_L : 7%
-// QR_ERROR_CORRECT_LEVEL_M : 15%
-// QR_ERROR_CORRECT_LEVEL_Q : 25%
-// QR_ERROR_CORRECT_LEVEL_H : 30%
-$qrcode->setErrorCorrectLevel(QRConst::ERROR_CORRECT_LEVEL_L);
-
-// 型番(大きさ)を設定
-// 1~10
-$qrcode->setTypeNumber(3);
-
-// データ(文字列※)を設定
-// ※日本語はSJIS
-$qrcode->addData('QRコード');
-
-// QRコードを作成
-$qrcode->make();
-
-// HTML出力
-echo $qrcode->printHTML();
-
-//---------------------------------------------------------
-print('
型番自動
');
-
-// 型番が最小となるQRコードを作成
-$qr = $qrcode->getMinimumQRCode('QRコード', QRConst::ERROR_CORRECT_LEVEL_L);
-
-// HTML出力
-echo $qr->printHTML();
\ No newline at end of file
diff --git a/examples/sample_image.php b/examples/sample_image.php
deleted file mode 100644
index 6f57ff69e..000000000
--- a/examples/sample_image.php
+++ /dev/null
@@ -1,18 +0,0 @@
-getMinimumQRCode('QRコード', QRConst::ERROR_CORRECT_LEVEL_L);
-
-// イメージ作成(引数:サイズ,マージン)
-$im = $qr->createImage(2, 4);
-
-header('Content-type: image/png');
-imagepng($im);
-
-imagedestroy($im);
-
diff --git a/src/BitBuffer.php b/src/BitBuffer.php
index cb53e2d76..90ee961e7 100644
--- a/src/BitBuffer.php
+++ b/src/BitBuffer.php
@@ -19,12 +19,12 @@ class BitBuffer{
/**
* @var array
*/
- protected $buffer = [];
+ public $buffer = [];
/**
* @var int
*/
- protected $length = 0;
+ public $length = 0;
/**
*
@@ -34,43 +34,19 @@ class BitBuffer{
$this->length = 0;
}
- /**
- * @return array
- */
- public function getBuffer(){
- return $this->buffer;
- }
-
- /**
- * @return int
- */
- public function getLengthInBits(){
- return $this->length;
- }
-
/**
* @return string
*/
public function __toString(){
$buffer = '';
- $count = $this->getLengthInBits();
- for($i = 0; $i < $count; $i++){
- $buffer .= $this->get($i) ? '1' : '0';
+ for($i = 0; $i < $this->length; $i++){
+ $buffer .= (string)(int)(($this->buffer[(int)floor($i / 8)] >> (7 - $i % 8))&1) === 1;
}
return $buffer;
}
- /**
- * @param $index
- *
- * @return bool
- */
- public function get($index){
- return (($this->buffer[(int)floor($index / 8)] >> (7 - $index % 8))&1) === 1;
- }
-
/**
* @param $num
* @param $length
diff --git a/src/Data/AlphaNum.php b/src/Data/AlphaNum.php
index 113744270..57b54f2da 100644
--- a/src/Data/AlphaNum.php
+++ b/src/Data/AlphaNum.php
@@ -26,33 +26,25 @@ class AlphaNum extends QRDataBase implements QRDataInterface{
/**
* @var
*/
- protected $mode = QRConst::MODE_ALPHA_NUM;
+ public $mode = QRConst::MODE_ALPHANUM;
/**
* @param $buffer
*/
public function write(BitBuffer &$buffer){
- $data = $this->getData();
$i = 0;
- $len = strlen($data);
+ $len = strlen($this->data);
while($i + 1 < $len){
- $buffer->put($this->getCode(ord($data[$i])) * 45 + $this->getCode(ord($data[$i + 1])), 11);
+ $buffer->put($this->getCode(ord($this->data[$i])) * 45 + $this->getCode(ord($this->data[$i + 1])), 11);
$i += 2;
}
if($i < $len){
- $buffer->put($this->getCode(ord($data[$i])), 6);
+ $buffer->put($this->getCode(ord($this->data[$i])), 6);
}
}
- /**
- * @return int
- */
- public function getLength(){
- return strlen($this->getData());
- }
-
/**
* @param $c
*
@@ -61,23 +53,23 @@ class AlphaNum extends QRDataBase implements QRDataInterface{
*/
protected function getCode($c){
- if($this->util->toCharCode('0') <= $c && $c <= $this->util->toCharCode('9')){
- return $c - $this->util->toCharCode('0');
+ if(ord('0') <= $c && $c <= ord('9')){
+ return $c - ord('0');
}
- else if($this->util->toCharCode('A') <= $c && $c <= $this->util->toCharCode('Z')){
- return $c - $this->util->toCharCode('A') + 10;
+ else if(ord('A') <= $c && $c <= ord('Z')){
+ return $c - ord('A') + 10;
}
else{
switch($c){
- case $this->util->toCharCode(' '): return 36;
- case $this->util->toCharCode('$'): return 37;
- case $this->util->toCharCode('%'): return 38;
- case $this->util->toCharCode('*'): return 39;
- case $this->util->toCharCode('+'): return 40;
- case $this->util->toCharCode('-'): return 41;
- case $this->util->toCharCode('.'): return 42;
- case $this->util->toCharCode('/'): return 43;
- case $this->util->toCharCode(':'): return 44;
+ case ord(' '): return 36;
+ case ord('$'): return 37;
+ case ord('%'): return 38;
+ case ord('*'): return 39;
+ case ord('+'): return 40;
+ case ord('-'): return 41;
+ case ord('.'): return 42;
+ case ord('/'): return 43;
+ case ord(':'): return 44;
default :
throw new QRCodeException('illegal char: '.$c);
}
diff --git a/src/Data/EightBitByte.php b/src/Data/Byte.php
similarity index 59%
rename from src/Data/EightBitByte.php
rename to src/Data/Byte.php
index d8173c747..9d134d11a 100644
--- a/src/Data/EightBitByte.php
+++ b/src/Data/Byte.php
@@ -1,7 +1,7 @@
@@ -18,32 +18,23 @@ use codemasher\QRCode\Data\QRDataInterface;
/**
- * Class EightBitByte
+ * Class Byte
*/
-class EightBitByte extends QRDataBase implements QRDataInterface{
+class Byte extends QRDataBase implements QRDataInterface{
/**
* @var
*/
- protected $mode = QRConst::MODE_8BIT_BYTE;
+ public $mode = QRConst::MODE_BYTE;
/**
* @param $buffer
*/
public function write(BitBuffer &$buffer){
- $data = $this->getData();
-
- $len = strlen($data);
+ $len = strlen($this->data);
for($i = 0; $i < $len; $i++){
- $buffer->put(ord($data[$i]), 8);
+ $buffer->put(ord($this->data[$i]), 8);
}
}
- /**
- * @return int
- */
- public function getLength(){
- return strlen($this->getData());
- }
-
}
\ No newline at end of file
diff --git a/src/Data/Kanji.php b/src/Data/Kanji.php
index d81968ad7..f921a78b4 100644
--- a/src/Data/Kanji.php
+++ b/src/Data/Kanji.php
@@ -25,7 +25,7 @@ class Kanji extends QRDataBase implements QRDataInterface{
/**
* @var
*/
- protected $mode = QRConst::MODE_KANJI;
+ public $mode = QRConst::MODE_KANJI;
/**
* @param $buffer
@@ -33,12 +33,11 @@ class Kanji extends QRDataBase implements QRDataInterface{
* @throws \codemasher\QRCode\QRCodeException
*/
public function write(BitBuffer &$buffer){
- $data = $this->getData();
$i = 0;
- $len = strlen($data);
+ $len = strlen($this->data);
while($i + 1 < $len){
- $c = ((0xff&ord($data[$i])) << 8)|(0xff&ord($data[$i + 1]));
+ $c = ((0xff&ord($this->data[$i])) << 8)|(0xff&ord($this->data[$i + 1]));
if(0x8140 <= $c && $c <= 0x9FFC){
$c -= 0x8140;
@@ -55,7 +54,7 @@ class Kanji extends QRDataBase implements QRDataInterface{
$i += 2;
}
- if($i < strlen($data)){
+ if($i < $len){
throw new QRCodeException('illegal char at '.($i + 1));
}
}
@@ -64,6 +63,7 @@ class Kanji extends QRDataBase implements QRDataInterface{
* @return float
*/
public function getLength(){
- return floor(strlen($this->getData()) / 2);
+ return floor(strlen($this->data) / 2);
}
+
}
diff --git a/src/Data/Number.php b/src/Data/Number.php
index 68349a4e2..401a5e9c0 100644
--- a/src/Data/Number.php
+++ b/src/Data/Number.php
@@ -23,25 +23,21 @@ use codemasher\QRCode\QRConst;
class Number extends QRDataBase implements QRDataInterface{
/**
- * @var
+ * @var int
*/
- protected $mode = QRConst::MODE_NUMBER;
-
- /**
- * @var \codemasher\QRCode\Util
- */
- protected $util;
+ public $mode = QRConst::MODE_NUMBER;
/**
* @param $buffer
+ *
+ * @return $this
*/
public function write(BitBuffer &$buffer){
- $data = $this->getData();
$i = 0;
- $len = strlen($data);
+ $len = strlen($this->data);
while($i + 2 < $len){
- $num = $this->parseInt(substr($data, $i, 3));
+ $num = $this->parseInt(substr($this->data, $i, 3));
$buffer->put($num, 10);
$i += 3;
}
@@ -49,50 +45,44 @@ class Number extends QRDataBase implements QRDataInterface{
if($i < $len){
if($len - $i === 1){
- $num = $this->parseInt(substr($data, $i, $i + 1));
+ $num = $this->parseInt(substr($this->data, $i, $i + 1));
$buffer->put($num, 4);
}
else if($len - $i === 2){
- $num = $this->parseInt(substr($data, $i, $i + 2));
+ $num = $this->parseInt(substr($this->data, $i, $i + 2));
$buffer->put($num, 7);
}
+
}
+
+ return $this;
}
/**
- * @return int
- */
- public function getLength(){
- return strlen($this->getData());
- }
-
- /**
- * @param $s
+ * @param string $string
*
* @return int
+ * @throws \codemasher\QRCode\QRCodeException
*/
- protected function parseInt($s){
+ protected function parseInt($string){
$num = 0;
- for($i = 0; $i < strlen($s); $i++){
- $num = $num * 10 + $this->parseIntAt(ord($s[$i]));
+ $len = strlen($string);
+ for($i = 0; $i < $len; $i++){
+ $c = ord($string[$i]);
+
+ $ord0 = ord('0');
+ if(ord('0') <= $c && $c <= ord('9')){
+ $c = $c - $ord0;
+ }
+ else{
+ throw new QRCodeException('illegal char: '.$c);
+ }
+
+ $num = $num * 10 + $c;
}
return $num;
}
- /**
- * @param $c
- *
- * @return mixed
- * @throws \codemasher\QRCode\QRCodeException
- */
- protected function parseIntAt($c){
- if($this->util->toCharCode('0') <= $c && $c <= $this->util->toCharCode('9')){
- return $c - $this->util->toCharCode('0');
- }
-
- throw new QRCodeException('illegal char: '.$c);
- }
-
}
diff --git a/src/Data/QRDataBase.php b/src/Data/QRDataBase.php
index e0026e0aa..59c97a75a 100644
--- a/src/Data/QRDataBase.php
+++ b/src/Data/QRDataBase.php
@@ -15,22 +15,21 @@ use codemasher\QRCode\BitBuffer;
use codemasher\QRCode\QRConst;
use codemasher\QRCode\QRCodeException;
use codemasher\QRCode\Util;
-use codemasher\QRCode\Data\QRDataInterface;
/**
* Class QRDataBase
*/
-class QRDataBase implements QRDataInterface{
+class QRDataBase{
/**
* @var
*/
- protected $mode;
+ public $mode;
/**
* @var
*/
- protected $data;
+ public $data;
/**
* @var \codemasher\QRCode\Util
@@ -47,34 +46,11 @@ class QRDataBase implements QRDataInterface{
$this->util = new Util;
}
- /**
- * @return mixed
- */
- public function getMode(){
- return $this->mode;
- }
-
- /**
- * @return mixed
- */
- public function getData(){
- return $this->data;
- }
-
/**
* @throws \codemasher\QRCode\QRCodeException
*/
public function getLength(){
- throw new QRCodeException('not implemented.');
- }
-
- /**
- * @param $buffer
- *
- * @throws \codemasher\QRCode\QRCodeException
- */
- public function write(BitBuffer &$buffer){
- throw new QRCodeException('not implemented.');
+ return strlen($this->data);
}
/**
@@ -88,10 +64,10 @@ class QRDataBase implements QRDataInterface{
// 1 - 9
switch($this->mode){
- case QRConst::MODE_NUMBER : return 10;
- case QRConst::MODE_ALPHA_NUM: return 9;
- case QRConst::MODE_8BIT_BYTE: return 8;
- case QRConst::MODE_KANJI : return 8;
+ case QRConst::MODE_NUMBER : return 10;
+ case QRConst::MODE_ALPHANUM: return 9;
+ case QRConst::MODE_BYTE : return 8;
+ case QRConst::MODE_KANJI : return 8;
default :
throw new QRCodeException('mode: '.$this->mode);
}
@@ -101,10 +77,10 @@ class QRDataBase implements QRDataInterface{
// 10 - 26
switch($this->mode){
- case QRConst::MODE_NUMBER : return 12;
- case QRConst::MODE_ALPHA_NUM: return 11;
- case QRConst::MODE_8BIT_BYTE: return 16;
- case QRConst::MODE_KANJI : return 10;
+ case QRConst::MODE_NUMBER : return 12;
+ case QRConst::MODE_ALPHANUM: return 11;
+ case QRConst::MODE_BYTE : return 16;
+ case QRConst::MODE_KANJI : return 10;
default :
throw new QRCodeException('mode: '.$this->mode);
}
@@ -114,10 +90,10 @@ class QRDataBase implements QRDataInterface{
// 27 - 40
switch($this->mode){
- case QRConst::MODE_NUMBER : return 14;
- case QRConst::MODE_ALPHA_NUM: return 13;
- case QRConst::MODE_8BIT_BYTE: return 16;
- case QRConst::MODE_KANJI : return 12;
+ case QRConst::MODE_NUMBER : return 14;
+ case QRConst::MODE_ALPHANUM: return 13;
+ case QRConst::MODE_BYTE : return 16;
+ case QRConst::MODE_KANJI : return 12;
default :
throw new QRCodeException('mode: '.$this->mode);
}
diff --git a/src/Data/QRDataInterface.php b/src/Data/QRDataInterface.php
index fe740bb03..c473ff00b 100644
--- a/src/Data/QRDataInterface.php
+++ b/src/Data/QRDataInterface.php
@@ -27,16 +27,6 @@ interface QRDataInterface{
*/
public function getLength();
- /**
- * @return mixed
- */
- public function getData();
-
- /**
- * @return mixed
- */
- public function getMode();
-
/**
* @param $type
*
@@ -44,4 +34,5 @@ interface QRDataInterface{
* @throws \codemasher\QRCode\QRCodeException
*/
public function getLengthInBits($type);
+
}
\ No newline at end of file
diff --git a/src/Math.php b/src/Math.php
deleted file mode 100644
index 0dac5160a..000000000
--- a/src/Math.php
+++ /dev/null
@@ -1,104 +0,0 @@
-
- * @copyright 2015 Smiley
- * @license MIT
- */
-
-namespace codemasher\QRCode;
-
-use codemasher\QRCode\QRCodeException;
-
-/**
- * Class Math
- */
-class Math{
-
- /**
- * @var array
- */
- protected $QR_MATH_EXP_TABLE;
-
- /**
- * @var array
- */
- protected $QR_MATH_LOG_TABLE;
-
- /**
- * Math constructor.
- */
- public function __construct(){
- $this->QR_MATH_EXP_TABLE = $this->createNumArray(256);
-
- for($i = 0; $i < 8; $i++){
- $this->QR_MATH_EXP_TABLE[$i] = 1 << $i;
- }
-
- for($i = 8; $i < 256; $i++){
- $this->QR_MATH_EXP_TABLE[$i] =
- $this->QR_MATH_EXP_TABLE[$i - 4]
- ^$this->QR_MATH_EXP_TABLE[$i - 5]
- ^$this->QR_MATH_EXP_TABLE[$i - 6]
- ^$this->QR_MATH_EXP_TABLE[$i - 8];
- }
-
- $this->QR_MATH_LOG_TABLE = $this->createNumArray(256);
-
- for($i = 0; $i < 255; $i++){
- $this->QR_MATH_LOG_TABLE[$this->QR_MATH_EXP_TABLE[$i]] = $i;
- }
- }
-
- /**
- * @param int $length
- *
- * @return array
- */
- public function createNumArray($length){
- $num_array = [];
-
- for($i = 0; $i < $length; $i++){
- $num_array[] = 0;
- }
-
- return $num_array;
- }
-
- /**
- * @param int $n
- *
- * @return mixed
- * @throws \codemasher\QRCode\QRCodeException
- */
- public function glog($n){
-
- if($n < 1){
- throw new QRCodeException('log('.$n.')');
- }
-
- return $this->QR_MATH_LOG_TABLE[$n];
- }
-
- /**
- * @param int $n
- *
- * @return mixed
- */
- public function gexp($n){
-
- while($n < 0){
- $n += 255;
- }
-
- while($n >= 256){
- $n -= 255;
- }
-
- return $this->QR_MATH_EXP_TABLE[$n];
- }
-
-}
diff --git a/src/Output/QROutputInterface.php b/src/Output/QROutputInterface.php
new file mode 100644
index 000000000..6c7bd3b45
--- /dev/null
+++ b/src/Output/QROutputInterface.php
@@ -0,0 +1,20 @@
+
+ * @copyright 2015 Smiley
+ * @license MIT
+ */
+
+namespace codemasher\QRCode\Output;
+
+/**
+ *
+ */
+interface QROutputInterface{
+
+}
diff --git a/src/Polynomial.php b/src/Polynomial.php
index 8ba93a3e2..c32440488 100644
--- a/src/Polynomial.php
+++ b/src/Polynomial.php
@@ -11,22 +11,25 @@
namespace codemasher\QRCode;
-use codemasher\QRCode\Math;
-
/**
* Class Polynomial
*/
class Polynomial{
/**
- * @var
+ * @var array
*/
- protected $num;
+ public $num = [];
/**
- * @var \codemasher\QRCode\Math
+ * @var array
*/
- protected $math;
+ protected $EXP_TABLE = [];
+
+ /**
+ * @var array
+ */
+ protected $LOG_TABLE = [];
/**
* Polynomial constructor.
@@ -34,56 +37,74 @@ class Polynomial{
* @param array $num
* @param int $shift
*/
- public function __construct(array $num, $shift = 0){
- $this->math = new Math;
+ public function __construct(array $num = [1], $shift = 0){
+ $this->setNum($num, $shift)
+ ->setTables();
+ }
+ /**
+ * @param array $num
+ * @param int $shift
+ *
+ * @return $this
+ */
+ public function setNum(array $num, $shift = 0){
$offset = 0;
- while($offset < count($num) && $num[$offset] === 0){
+ $numCount = count($num);
+
+ while($offset < $numCount && $num[$offset] === 0){
$offset++;
}
- $this->num = $this->math->createNumArray(count($num) - $offset + $shift);
- for($i = 0; $i < count($num) - $offset; $i++){
+ $this->num = [];
+ for($i = 0; $i < $numCount - $offset + $shift; $i++){
+ $this->num[] = 0;
+ }
+
+ for($i = 0; $i < $numCount - $offset; $i++){
$this->num[$i] = $num[$i + $offset];
}
+
+ return $this;
}
/**
- * @param $index
- * @todo rename!
- *
- * @return mixed
+ * @return $this
*/
- public function getNum($index){
- return $this->num[$index];
+ protected function setTables(){
+ $numArr = [];
+ for($i = 0; $i < 256; $i++){
+ $numArr[] = 0;
+ }
+
+ $this->EXP_TABLE = $this->LOG_TABLE = $numArr;
+
+ for($i = 0; $i < 8; $i++){
+ $this->EXP_TABLE[$i] = 1 << $i;
+ }
+
+ for($i = 8; $i < 256; $i++){
+ $this->EXP_TABLE[$i] = $this->EXP_TABLE[$i - 4] ^ $this->EXP_TABLE[$i - 5] ^ $this->EXP_TABLE[$i - 6] ^ $this->EXP_TABLE[$i - 8];
+ }
+
+ for($i = 0; $i < 255; $i++){
+ $this->LOG_TABLE[$this->EXP_TABLE[$i]] = $i;
+ }
+
+ return $this;
}
/**
- * @return int
- */
- public function getLength(){
- return count($this->num);
- }
-
- /**
- * PHP5
* @return string
*/
public function __toString(){
- return $this->toString();
- }
-
- /**
- * @return string
- */
- public function toString(){
$buffer = '';
- for($i = 0; $i < $this->getLength(); $i++){
+ foreach($this->num as $i => $value){
if($i > 0){
$buffer .= ',';
}
- $buffer .= $this->getNum($i);
+ $buffer .= $value;
}
return $buffer;
@@ -95,56 +116,101 @@ class Polynomial{
public function toLogString(){
$buffer = '';
- for($i = 0; $i < $this->getLength(); $i++){
+ foreach($this->num as $i => $value){
if($i > 0){
$buffer .= ',';
}
- $buffer .= $this->math->glog($this->getNum($i));
+ $buffer .= $this->glog($value);
}
return $buffer;
}
/**
- * @param \codemasher\QRCode\Polynomial $e
+ * @param array $e
*
- * @return \codemasher\QRCode\Polynomial
+ * @return $this
*/
- public function multiply($e){
- $num = $this->math->createNumArray($this->getLength() + $e->getLength() - 1);
+ public function multiply(array $e){
- for($i = 0; $i < $this->getLength(); $i++){
- for($j = 0; $j < $e->getLength(); $j++){
- $num[$i + $j] ^= $this->math->gexp($this->math->glog($this->getNum($i)) + $this->math->glog($e->getNum($j)));
+ $num = [];
+ $len = count($this->num) + count($e) - 1;
+ for($i = 0; $i < $len; $i++){
+ $num[] = 0;
+ }
+
+ foreach($this->num as $i => $vi){
+ foreach($e as $j => $vj){
+ $num[$i + $j] ^= $this->gexp($this->glog($vi) + $this->glog($vj));
}
}
- return new Polynomial($num);
+ $this->setNum($num);
+
+ return $this;
}
/**
- * @param \codemasher\QRCode\Polynomial $e
+ * @param array $e
*
- * @return $this|\codemasher\QRCode\Polynomial
+ * @return $this
*/
public function mod($e){
+# $starttime = microtime(true);
- if($this->getLength() - $e->getLength() < 0){
+ if(count($this->num) - count($e) < 0){
return $this;
}
- $ratio = $this->math->glog($this->getNum(0)) - $this->math->glog($e->getNum(0));
+ $ratio = $this->glog($this->num[0]) - $this->glog($e[0]);
- $num = $this->math->createNumArray($this->getLength());
- for($i = 0; $i < $this->getLength(); $i++){
- $num[$i] = $this->getNum($i);
+ $num = [];
+ foreach($this->num as $i => $value){
+ $num[$i] = $value;
}
- for($i = 0; $i < $e->getLength(); $i++){
- $num[$i] ^= $this->math->gexp($this->math->glog($e->getNum($i)) + $ratio);
+ foreach($e as $i => $value){
+ $num[$i] ^= $this->gexp($this->glog($e[$i]) + $ratio);
}
- return (new Polynomial($num))->mod($e);
+ $this->setNum($num)->mod($e);
+
+# echo 'Polynomial::mod '.round((microtime(true)-$starttime), 5).PHP_EOL;
+
+ return $num;
+ }
+
+ /**
+ * @param int $n
+ *
+ * @return mixed
+ * @throws \codemasher\QRCode\QRCodeException
+ */
+ public function glog($n){
+
+ if($n < 1){
+ throw new QRCodeException('log('.$n.')');
+ }
+
+ return $this->LOG_TABLE[$n];
+ }
+
+ /**
+ * @param int $n
+ *
+ * @return mixed
+ */
+ public function gexp($n){
+
+ while($n < 0){
+ $n += 255;
+ }
+
+ while($n >= 256){
+ $n -= 255;
+ }
+
+ return $this->EXP_TABLE[$n];
}
}
diff --git a/src/QRCode.php b/src/QRCode.php
index 2c0b142d0..b7b507b89 100644
--- a/src/QRCode.php
+++ b/src/QRCode.php
@@ -1,5 +1,6 @@
errorCorrectLevel = $errorCorrectLevel;
}
- /**
- * @return int
- */
- public function getTypeNumber(){
- return $this->typeNumber;
- }
-
- /**
- * @param int $typeNumber
- */
- public function setTypeNumber($typeNumber){
- $this->typeNumber = $typeNumber;
- }
-
- /**
- * @return int
- */
- public function getErrorCorrectLevel(){
- return $this->errorCorrectLevel;
- }
-
- /**
- * @param int $errorCorrectLevel
- */
- public function setErrorCorrectLevel($errorCorrectLevel){
- $this->errorCorrectLevel = $errorCorrectLevel;
- }
-
/**
* @param string $data
* @param int $mode
*
+ * @return $this
* @throws \codemasher\QRCode\QRCodeException
*/
- public function addData($data, $mode = 0){
- if($mode === 0){
+ public function addData($data, $mode = null){
+ if($mode === null){
$mode = $this->util->getMode($data);
}
switch($mode){
- case QRConst::MODE_NUMBER :
- $this->addDataImpl(new Number($data));
- break;
- case QRConst::MODE_ALPHA_NUM:
- $this->addDataImpl(new AlphaNum($data));
- break;
- case QRConst::MODE_8BIT_BYTE:
- $this->addDataImpl(new EightBitByte($data));
- break;
- case QRConst::MODE_KANJI :
- $this->addDataImpl(new Kanji($data));
- break;
- default :
+ case QRConst::MODE_NUMBER : $this->qrDataList[] = new Number($data); break;
+ case QRConst::MODE_ALPHANUM:$this->qrDataList[] = new AlphaNum($data); break;
+ case QRConst::MODE_BYTE:$this->qrDataList[] = new Byte($data); break;
+ case QRConst::MODE_KANJI : $this->qrDataList[] = new Kanji($data); break;
+ default:
throw new QRCodeException('mode: '.$mode);
}
- }
-
- /**
- *
- */
- public function clearData(){
- $this->qrDataList = [];
- }
-
- /**
- * @param \codemasher\QRCode\Data\QRDataInterface $qrData
- *
- * @return $this
- */
- public function addDataImpl(QRDataInterface &$qrData){
- $this->qrDataList[] = $qrData;
return $this;
}
- /**
- * @return int
- */
- public function getDataCount(){
- return count($this->qrDataList);
- }
-
- /**
- * @param int $index
- *
- * @return \codemasher\QRCode\Data\QRDataInterface
- */
- public function getData($index){
- return $this->qrDataList[$index];
- }
-
/**
* @param int $row
* @param int $col
*
- * @return mixed
+ * @return bool
*/
public function isDark($row, $col){
if($this->modules[$row][$col] !== null){
- return $this->modules[$row][$col];
+ return (bool)$this->modules[$row][$col];
}
else{
return false;
}
}
- /**
- * @return mixed
- */
- public function getModuleCount(){
- return $this->moduleCount;
- }
-
- /**
- * used for converting fg/bg colors (e.g. #0000ff = 0x0000FF) - added 2015.07.27 ~ DoktorJ
- *
- * @param int $hex
- *
- * @return array
- */
- public function hex2rgb($hex = 0x0){
- return [
- 'r' => floor($hex / 65536),
- 'g' => floor($hex / 256) % 256,
- 'b' => $hex % 256,
- ];
- }
-
/**
*
*/
@@ -226,15 +144,123 @@ class QRCode{
/**
* @return int
*/
- public function getBestMaskPattern(){
+ protected function getBestMaskPattern(){
$minLostPoint = 0;
$pattern = 0;
for($i = 0; $i < 8; $i++){
$this->makeImpl(true, $i);
- $lostPoint = $this->util->getLostPoint($this);
+ $lostPoint = 0;
- if($i == 0 || $minLostPoint > $lostPoint){
+ // LEVEL1
+
+ for($row = 0; $row < $this->moduleCount; $row++){
+ for($col = 0; $col < $this->moduleCount; $col++){
+ $sameCount = 0;
+ $dark = $this->isDark($row, $col);
+
+ for($r = -1; $r <= 1; $r++){
+ if($row + $r < 0 || $this->moduleCount <= $row + $r){
+ continue;
+ }
+
+ for($c = -1; $c <= 1; $c++){
+
+ if($col + $c < 0 || $this->moduleCount <= $col + $c){
+ continue;
+ }
+
+ if($r == 0 && $c == 0){
+ continue;
+ }
+
+ if($dark === $this->isDark($row + $r, $col + $c)){
+ $sameCount++;
+ }
+ }
+ }
+
+ if($sameCount > 5){
+ $lostPoint += (3 + $sameCount - 5);
+ }
+ }
+ }
+
+ // LEVEL2
+
+ for($row = 0; $row < $this->moduleCount - 1; $row++){
+ for($col = 0; $col < $this->moduleCount - 1; $col++){
+ $count = 0;
+
+ if($this->isDark($row, $col)){
+ $count++;
+ }
+
+ if($this->isDark($row + 1, $col)){
+ $count++;
+ }
+
+ if($this->isDark($row, $col + 1)){
+ $count++;
+ }
+
+ if($this->isDark($row + 1, $col + 1)){
+ $count++;
+ }
+
+ if($count === 0 || $count === 4){
+ $lostPoint += 3;
+ }
+ }
+ }
+
+ // LEVEL3
+
+ for($row = 0; $row < $this->moduleCount; $row++){
+ for($col = 0; $col < $this->moduleCount - 6; $col++){
+ if($this->isDark($row, $col)
+ && !$this->isDark($row, $col + 1)
+ && $this->isDark($row, $col + 2)
+ && $this->isDark($row, $col + 3)
+ && $this->isDark($row, $col + 4)
+ && !$this->isDark($row, $col + 5)
+ && $this->isDark($row, $col + 6)
+ ){
+ $lostPoint += 40;
+ }
+ }
+ }
+
+ for($col = 0; $col < $this->moduleCount; $col++){
+ for($row = 0; $row < $this->moduleCount - 6; $row++){
+ if($this->isDark($row, $col)
+ && !$this->isDark($row + 1, $col)
+ && $this->isDark($row + 2, $col)
+ && $this->isDark($row + 3, $col)
+ && $this->isDark($row + 4, $col)
+ && !$this->isDark($row + 5, $col)
+ && $this->isDark($row + 6, $col)
+ ){
+ $lostPoint += 40;
+ }
+ }
+ }
+
+ // LEVEL4
+
+ $darkCount = 0;
+ for($col = 0; $col < $this->moduleCount; $col++){
+ for($row = 0; $row < $this->moduleCount; $row++){
+ if($this->isDark($row, $col)){
+ $darkCount++;
+ }
+ }
+ }
+
+ $ratio = abs(100 * $darkCount / $this->moduleCount / $this->moduleCount - 50) / 5;
+ $lostPoint += $ratio * 10;
+
+ if($i === 0 || $minLostPoint > $lostPoint){
$minLostPoint = $lostPoint;
$pattern = $i;
}
@@ -244,63 +270,117 @@ class QRCode{
}
/**
- * @param int $length
- *
- * @return array
- */
- public function createNullArray($length){
- $nullArray = [];
- for($i = 0; $i < $length; $i++){
- $nullArray[] = null;
- }
-
- return $nullArray;
- }
-
- /**
- * @param $test
- * @param $maskPattern
+ * @param bool $test
+ * @param int $maskPattern
*
* @return $this
*/
- public function makeImpl($test, $maskPattern){
+ protected function makeImpl($test, $maskPattern){
$this->moduleCount = $this->typeNumber * 4 + 17;
$this->modules = [];
+ $nullArray = [];
for($i = 0; $i < $this->moduleCount; $i++){
- $this->modules[] = $this->createNullArray($this->moduleCount);
+ $nullArray[] = null;
+ }
+
+ for($i = 0; $i < $this->moduleCount; $i++){
+ $this->modules[] = $nullArray;
}
$this->setupPositionProbePattern(0, 0)
->setupPositionProbePattern($this->moduleCount - 7, 0)
- ->setupPositionProbePattern(0, $this->moduleCount - 7)
- ->setupPositionAdjustPattern()
- ->setupTimingPattern()
- ->setupTypeInfo($test, $maskPattern);
+ ->setupPositionProbePattern(0, $this->moduleCount - 7);
- if($this->typeNumber >= 7){
- $this->setupTypeNumber($test);
+
+ $pos = $this->util->PATTERN_POSITION[$this->typeNumber - 1];
+ $posCount = count($pos);
+
+ for($i = 0; $i < $posCount; $i++){
+ for($j = 0; $j < $posCount; $j++){
+ if($this->modules[$pos[$i]][$pos[$j]] !== null){
+ continue;
+ }
+
+ for($r = -2; $r <= 2; $r++){
+ for($c = -2; $c <= 2; $c++){
+ $this->modules[$pos[$i] + $r][$pos[$j] + $c] =
+ $r === -2 || $r === 2 || $c === -2 || $c === 2 || ($r === 0 && $c === 0);
+ }
+ }
+
+ }
}
- $data = $this->createData($this->typeNumber, $this->errorCorrectLevel);
+ for($r = 8; $r < $this->moduleCount - 8; $r++){
+ if($this->modules[$r][6] !== null){
+ continue;
+ }
- $this->mapData($data, $maskPattern);
+ $this->modules[$r][6] = $this->modules[6][$r] = $r % 2 === 0;
+ }
+
+ $data = ($this->errorCorrectLevel << 3) | $maskPattern;
+ $bits = $this->util->getBCHTypeInfo($data);
+
+ for($i = 0; $i < 15; $i++){
+ $mod = !$test && (($bits >> $i) & 1) === 1;
+
+ if($i < 6){
+ $this->modules[$i][8] = $mod;
+ }
+ else if($i < 8){
+ $this->modules[$i + 1][8] = $mod;
+ }
+ else{
+ $this->modules[$this->moduleCount - 15 + $i][8] = $mod;
+ }
+
+ if($i < 8){
+ $this->modules[8][$this->moduleCount - $i - 1] = $mod;
+ }
+ else if($i < 9){
+ $this->modules[8][15 - $i - 1 + 1] = $mod;
+ }
+ else{
+ $this->modules[8][15 - $i - 1] = $mod;
+ }
+
+ }
+
+ $this->modules[$this->moduleCount - 8][8] = !$test;
+
+ if($this->typeNumber >= 7){
+ $bits = $this->util->getBCHTypeNumber($this->typeNumber);
+
+ for($i = 0; $i < 18; $i++){
+ $a = (int)floor($i / 3);
+ $b = $i % 3 + $this->moduleCount - 8 - 3;
+ $mod = !$test && (($bits >> $i) & 1) === 1;
+
+ $this->modules[$a][$b] = $this->modules[$b][$a] = $mod;
+ }
+ }
+
+ $this->data = $this->createData($this->typeNumber, $this->errorCorrectLevel);
+
+ $this->mapData($maskPattern);
return $this;
}
/**
- * @param $data
* @param $maskPattern
*
* @return $this
* @throws \codemasher\QRCode\QRCodeException
*/
- public function mapData(&$data, $maskPattern){
+ protected function mapData($maskPattern){
$inc = -1;
$row = $this->moduleCount - 1;
$bitIndex = 7;
$byteIndex = 0;
+ $dataCount = count($this->data);
for($col = $this->moduleCount - 1; $col > 0; $col -= 2){
@@ -309,18 +389,28 @@ class QRCode{
}
while(true){
-
for($c = 0; $c < 2; $c++){
if($this->modules[$row][$col - $c] === null){
-
$dark = false;
- if($byteIndex < count($data)){
- $dark = ((($data[$byteIndex] >> $bitIndex) & 1) == 1);
+ if($byteIndex < $dataCount){
+ $dark = (($this->data[$byteIndex] >> $bitIndex) & 1) === 1;
}
- $mask = $this->util->getMask($maskPattern, $row, $col - $c);
+ $_col = $col - $c;
+ switch($maskPattern){
+ case QRConst::MASK_PATTERN000: $mask = ($row + $_col) % 2 === 0; break;
+ case QRConst::MASK_PATTERN001: $mask = $row % 2 === 0; break;
+ case QRConst::MASK_PATTERN010: $mask = $_col % 3 === 0; break;
+ case QRConst::MASK_PATTERN011: $mask = ($row + $_col) % 3 === 0; break;
+ case QRConst::MASK_PATTERN100: $mask = (floor($row / 2) + floor($_col / 3)) % 2 === 0; break;
+ case QRConst::MASK_PATTERN101: $mask = ($row * $_col) % 2 + ($row * $_col) % 3 === 0; break;
+ case QRConst::MASK_PATTERN110: $mask = (($row * $_col) % 2 + ($row * $_col) % 3) % 2 === 0; break;
+ case QRConst::MASK_PATTERN111: $mask = (($row * $_col) % 3 + ($row + $_col) % 2) % 2 === 0; break;
+ default :
+ throw new QRCodeException('mask: '.$maskPattern);
+ }
if($mask){
$dark = !$dark;
@@ -329,10 +419,11 @@ class QRCode{
$this->modules[$row][$col - $c] = $dark;
$bitIndex--;
- if($bitIndex == -1){
+ if($bitIndex === -1){
$byteIndex++;
$bitIndex = 7;
}
+
}
}
@@ -349,171 +440,41 @@ class QRCode{
return $this;
}
- /**
- * @return $this
- */
- public function setupPositionAdjustPattern(){
- $pos = $this->util->getPatternPosition($this->typeNumber);
-
- $posCount = count($pos);
- for($i = 0; $i < $posCount; $i++){
- for($j = 0; $j < $posCount; $j++){
-
- $row = $pos[$i];
- $col = $pos[$j];
-
- if($this->modules[$row][$col] !== null){
- continue;
- }
-
- for($r = -2; $r <= 2; $r++){
- for($c = -2; $c <= 2; $c++){
-
- if($r == -2 || $r == 2 || $c == -2 || $c == 2
- || ($r == 0 && $c == 0)
- ){
- $this->modules[$row + $r][$col + $c] = true;
- }
- else{
- $this->modules[$row + $r][$col + $c] = false;
- }
- }
- }
- }
- }
-
- return $this;
- }
-
/**
* @param $row
* @param $col
*
* @return $this
*/
- public function setupPositionProbePattern($row, $col){
+ protected function setupPositionProbePattern($row, $col){
for($r = -1; $r <= 7; $r++){
for($c = -1; $c <= 7; $c++){
- if($row + $r <= -1 || $this->moduleCount <= $row + $r
- || $col + $c <= -1 || $this->moduleCount <= $col + $c
- ){
+ if($row + $r <= -1 || $this->moduleCount <= $row + $r || $col + $c <= -1 || $this->moduleCount <= $col + $c){
continue;
}
- if((0 <= $r && $r <= 6 && ($c == 0 || $c == 6))
- || (0 <= $c && $c <= 6 && ($r == 0 || $r == 6))
- || (2 <= $r && $r <= 4 && 2 <= $c && $c <= 4)
- ){
- $this->modules[$row + $r][$col + $c] = true;
- }
- else{
- $this->modules[$row + $r][$col + $c] = false;
- }
+ $this->modules[$row + $r][$col + $c] =
+ (0 <= $r && $r <= 6 && ($c === 0 || $c === 6))
+ || (0 <= $c && $c <= 6 && ($r == 0 || $r === 6))
+ || (2 <= $r && $r <= 4 && 2 <= $c && $c <= 4);
}
}
return $this;
}
- /**
- * @return $this
- */
- public function setupTimingPattern(){
-
- for($r = 8; $r < $this->moduleCount - 8; $r++){
- if($this->modules[$r][6] !== null){
- continue;
- }
- $this->modules[$r][6] = ($r % 2 == 0);
- }
-
- for($c = 8; $c < $this->moduleCount - 8; $c++){
- if($this->modules[6][$c] !== null){
- continue;
- }
- $this->modules[6][$c] = ($c % 2 == 0);
- }
-
- return $this;
- }
-
- /**
- * @param $test
- *
- * @return $this
- */
- public function setupTypeNumber($test){
- $bits = $this->util->getBCHTypeNumber($this->typeNumber);
-
- for($i = 0; $i < 18; $i++){
- $this->modules[(int)floor($i / 3)][$i % 3 + $this->moduleCount - 8 - 3] = !$test && (($bits >> $i) & 1) === 1;
- }
-
- for($i = 0; $i < 18; $i++){
- $this->modules[$i % 3 + $this->moduleCount - 8 - 3][(int)floor($i / 3)] = !$test && (($bits >> $i) & 1) === 1;
- }
-
- return $this;
- }
-
- /**
- * @param $test
- * @param $maskPattern
- *
- * @return $this
- */
- public function setupTypeInfo($test, $maskPattern){
-
- $data = ($this->errorCorrectLevel << 3) | $maskPattern;
- $bits = $this->util->getBCHTypeInfo($data);
-
- for($i = 0; $i < 15; $i++){
-
- $mod = !$test && (($bits >> $i) & 1) === 1;
-
- if($i < 6){
- $this->modules[$i][8] = $mod;
- }
- else if($i < 8){
- $this->modules[$i + 1][8] = $mod;
- }
- else{
- $this->modules[$this->moduleCount - 15 + $i][8] = $mod;
- }
- }
-
- for($i = 0; $i < 15; $i++){
-
- $mod = !$test && (($bits >> $i) & 1) === 1;
-
- if($i < 8){
- $this->modules[8][$this->moduleCount - $i - 1] = $mod;
- }
- else if($i < 9){
- $this->modules[8][15 - $i - 1 + 1] = $mod;
- }
- else{
- $this->modules[8][15 - $i - 1] = $mod;
- }
- }
-
- $this->modules[$this->moduleCount - 8][8] = !$test;
-
- return $this;
- }
-
/**
* @param $typeNumber
* @param $errorCorrectLevel
*
* @return array
* @throws \codemasher\QRCode\QRCodeException
- * @todo: slooooow
+ * @todo: slooooow in PHP5
*
*/
- public function createData($typeNumber, $errorCorrectLevel){
+ protected function createData($typeNumber, $errorCorrectLevel){
$this->bitBuffer->reset();
$count = count($this->qrDataList);
@@ -521,7 +482,7 @@ class QRCode{
/** @var \codemasher\QRCode\Data\QRDataInterface $data */
$data = $this->qrDataList[$i];
- $this->bitBuffer->put($data->getMode(), 4);
+ $this->bitBuffer->put($data->mode, 4);
$this->bitBuffer->put($data->getLength(), $data->getLengthInBits($typeNumber));
$data->write($this->bitBuffer);
}
@@ -531,88 +492,122 @@ class QRCode{
$count = count($this->rsBlockList);
for($i = 0; $i < $count; $i++){
- $this->rsBlock->setCount($this->rsBlockList[$i][0], $this->rsBlockList[$i][1]);
+ $this->rsBlock->totalCount = $this->rsBlockList[$i][0];
+ $this->rsBlock->dataCount = $this->rsBlockList[$i][1];
- $totalDataCount += $this->rsBlock->getDataCount();
+ $totalDataCount += $this->rsBlock->dataCount;
}
- if($this->bitBuffer->getLengthInBits() > $totalDataCount * 8){
- throw new QRCodeException('code length overflow. ('.$this->bitBuffer->getLengthInBits().'>'.($totalDataCount * 8).')');
+ if($this->bitBuffer->length > $totalDataCount * 8){
+ throw new QRCodeException('code length overflow. ('.$this->bitBuffer->length.'>'.($totalDataCount * 8).')');
}
// end code.
- if($this->bitBuffer->getLengthInBits() + 4 <= $totalDataCount * 8){
+ if($this->bitBuffer->length + 4 <= $totalDataCount * 8){
$this->bitBuffer->put(0, 4);
}
// padding
- while($this->bitBuffer->getLengthInBits() % 8 != 0){
+ while($this->bitBuffer->length % 8 != 0){
$this->bitBuffer->putBit(false);
}
// padding
while(true){
- if($this->bitBuffer->getLengthInBits() >= $totalDataCount * 8){
+ if($this->bitBuffer->length >= $totalDataCount * 8){
break;
}
$this->bitBuffer->put(self::QR_PAD0, 8);
- if($this->bitBuffer->getLengthInBits() >= $totalDataCount * 8){
+ if($this->bitBuffer->length >= $totalDataCount * 8){
break;
}
$this->bitBuffer->put(self::QR_PAD1, 8);
}
- return $this->createBytes();
- }
- /**
- * @return array
- */
- public function createBytes(){
$offset = $maxDcCount = $maxEcCount = 0;
- $dcdata = $ecdata = $this->createNullArray(count($this->rsBlockList));
$rsBlockCount = count($this->rsBlockList);
- for($r = 0; $r < $rsBlockCount; $r++){
- $this->rsBlock->setCount($this->rsBlockList[$r][0], $this->rsBlockList[$r][1]);
+ $nullArray = [];
+ for($i = 0; $i < $rsBlockCount; $i++){
+ $nullArray[] = null;
+ }
- $dcCount = $this->rsBlock->getDataCount();
- $ecCount = $this->rsBlock->getTotalCount() - $dcCount;
+ $dcdata = $ecdata = $nullArray;
+ $totalCodeCount = 0;
+
+ for($r = 0; $r < $rsBlockCount; $r++){
+ $this->rsBlock->totalCount = $this->rsBlockList[$r][0];
+ $this->rsBlock->dataCount = $this->rsBlockList[$r][1];
+
+
+ $dcCount = $this->rsBlock->dataCount;
+ $ecCount = $this->rsBlock->totalCount - $dcCount;
$maxDcCount = max($maxDcCount, $dcCount);
$maxEcCount = max($maxEcCount, $ecCount);
- $dcdata[$r] = $this->createNullArray($dcCount);
+ $_nullArray = [];
+ for($i = 0; $i < $dcCount; $i++){
+ $_nullArray[] = null;
+ }
+
+ $dcdata[$r] = $_nullArray;
$dcdataCount = count($dcdata[$r]);
for($i = 0; $i < $dcdataCount; $i++){
- $bdata = $this->bitBuffer->getBuffer();
+ $bdata = $this->bitBuffer->buffer;
$dcdata[$r][$i] = 0xff & $bdata[$i + $offset];
}
$offset += $dcCount;
- $rsPoly = $this->util->getErrorCorrectPolynomial($ecCount);
- $rawPoly = new Polynomial($dcdata[$r], $rsPoly->getLength() - 1);
- $modPoly = $rawPoly->mod($rsPoly);
- $ecdata[$r] = $this->createNullArray($rsPoly->getLength() - 1);
- $ecdataCount = count($ecdata[$r]);
- for($i = 0; $i < $ecdataCount; $i++){
- $modIndex = $i + $modPoly->getLength() - count($ecdata[$r]);
- $ecdata[$r][$i] = ($modIndex >= 0) ? $modPoly->getNum($modIndex) : 0;
+ $rsPoly = new Polynomial;
+ $modPoly = new Polynomial;
+
+$starttime = microtime(true);
+ // 0.09s
+ for($i = 0; $i < $ecCount; $i++){
+ $modPoly->setNum([1, $modPoly->gexp($i)]);
+ $rsPoly->multiply($modPoly->num);
}
+
+ $rsPolyCount = count($rsPoly->num);
+
+ // 0.11s
+ $modPoly->setNum($dcdata[$r], $rsPolyCount - 1)->mod($rsPoly->num);
+
+echo 'QRCode::createData '.round((microtime(true)-$starttime), 5).PHP_EOL;
+
+ $modPolyCount = count($modPoly->num);
+
+ $_nullArray = [];
+ for($i = 0; $i < $rsPolyCount - 1; $i++){
+ $_nullArray[] = null;
+ }
+
+ $ecdata[$r] = $_nullArray;
+ $ecdataCount = count($ecdata[$r]);
+
+ for($i = 0; $i < $ecdataCount; $i++){
+ $modIndex = $i + $modPolyCount - $ecdataCount;
+ $ecdata[$r][$i] = ($modIndex >= 0) ? $modPoly->num[$modIndex] : 0;
+ }
+
+ $this->rsBlock->totalCount = $this->rsBlockList[$r][0];
+ $this->rsBlock->dataCount = $this->rsBlockList[$r][1];
+
+ $totalCodeCount += $this->rsBlock->totalCount;
}
- $totalCodeCount = 0;
- for($i = 0; $i < $rsBlockCount; $i++){
- $this->rsBlock->setCount($this->rsBlockList[$i][0], $this->rsBlockList[$i][1]);
-
- $totalCodeCount += $this->rsBlock->getTotalCount();
+ $nullArray = [];
+ for($i = 0; $i < $totalCodeCount; $i++){
+ $nullArray[] = null;
}
- $data = $this->createNullArray($totalCodeCount);
+ $data = $nullArray;
$index = 0;
for($i = 0; $i < $maxDcCount; $i++){
for($r = 0; $r < $rsBlockCount; $r++){
@@ -640,27 +635,26 @@ class QRCode{
* @return \codemasher\QRCode\QRCode
* @throws \codemasher\QRCode\QRCodeException
*/
- public function getMinimumQRCode($data, $errorCorrectLevel){
-
+ public function getMinimumQRCode($data, $errorCorrectLevel = QRConst::ERROR_CORRECT_LEVEL_H){
$mode = $this->util->getMode($data);
+ $this->addData($data, $mode);
- $qr = new QRCode();
- $qr->setErrorCorrectLevel($errorCorrectLevel);
- $qr->addData($data, $mode);
+ $this->errorCorrectLevel = $errorCorrectLevel;
- $qrData = $qr->getData(0);
+ /** @var \codemasher\QRCode\Data\QRDataBase $qrData */
+ $qrData = $this->qrDataList[0];
$length = $qrData->getLength();
for($typeNumber = 1; $typeNumber <= 10; $typeNumber++){
- if($length <= $this->util->getMaxLength($typeNumber, $mode, $errorCorrectLevel)){
- $qr->setTypeNumber($typeNumber);
+ if($length <= $this->util->getMaxLength($typeNumber, $mode, $this->errorCorrectLevel)){
+ $this->typeNumber = $typeNumber;
break;
}
}
- $qr->make();
+ $this->makeImpl(false, $this->getBestMaskPattern());
- return $qr;
+ return $this;
}
/**
@@ -692,7 +686,7 @@ class QRCode{
$margin = 0;
}
- $image_size = $this->getModuleCount() * $size + $margin * 2;
+ $image_size = $this->moduleCount * $size + $margin * 2;
$image = imagecreatetruecolor($image_size, $image_size);
@@ -705,8 +699,8 @@ class QRCode{
}
// convert hexadecimal RGB to arrays for imagecolorallocate
- $fgrgb = $this->hex2rgb($fg);
- $bgrgb = $this->hex2rgb($bg);
+ $fgrgb = $this->util->hex2rgb($fg);
+ $bgrgb = $this->util->hex2rgb($bg);
// replace $black and $white with $fgc and $bgc
$fgc = imagecolorallocate($image, $fgrgb['r'], $fgrgb['g'], $fgrgb['b']);
@@ -718,9 +712,8 @@ class QRCode{
// update $white to $bgc
imagefilledrectangle($image, 0, 0, $image_size, $image_size, $bgc);
- $count = $this->getModuleCount();
- for($r = 0; $r < $count; $r++){
- for($c = 0; $c < $count; $c++){
+ for($r = 0; $r < $this->moduleCount; $r++){
+ for($c = 0; $c < $this->moduleCount; $c++){
if($this->isDark($r, $c)){
// update $black to $fgc
@@ -742,7 +735,7 @@ class QRCode{
*/
public function printHTML(){
$html = '';
- $count = $this->getModuleCount();
+ $count = $this->moduleCount;
for($r = 0; $r < $count; $r++){
$html .= '';
diff --git a/src/QRConst.php b/src/QRConst.php
index 22f34b546..3aefb28a8 100644
--- a/src/QRConst.php
+++ b/src/QRConst.php
@@ -17,8 +17,8 @@ namespace codemasher\QRCode;
class QRConst{
const MODE_NUMBER = 1 << 0;
- const MODE_ALPHA_NUM = 1 << 1;
- const MODE_8BIT_BYTE = 1 << 2;
+ const MODE_ALPHANUM = 1 << 1;
+ const MODE_BYTE = 1 << 2;
const MODE_KANJI = 1 << 3;
const MASK_PATTERN000 = 0;
diff --git a/src/RSBlock.php b/src/RSBlock.php
index ec11ddd69..0befe44f2 100644
--- a/src/RSBlock.php
+++ b/src/RSBlock.php
@@ -22,12 +22,12 @@ class RSBlock{
/**
* @var int
*/
- protected $totalCount;
+ public $totalCount;
/**
* @var int
*/
- protected $dataCount;
+ public $dataCount;
/**
* @var array
@@ -101,40 +101,28 @@ class RSBlock{
];
- /**
- * @param int $totalCount
- * @param int $dataCount
- */
- public function setCount($totalCount, $dataCount){
- $this->totalCount = $totalCount;
- $this->dataCount = $dataCount;
- }
-
- /**
- * @return int
- */
- public function getDataCount(){
- return $this->dataCount;
- }
-
- /**
- * @return int
- */
- public function getTotalCount(){
- return $this->totalCount;
- }
-
/**
* @param $typeNumber
* @param $errorCorrectLevel
*
* @return array
+ * @throws \codemasher\QRCode\QRCodeException
*/
public function getRSBlocks($typeNumber, $errorCorrectLevel){
- $rsBlock = $this->getRsBlockTable($typeNumber, $errorCorrectLevel);
- $length = count($rsBlock) / 3;
- $list = [];
+ switch($errorCorrectLevel){
+ case QRConst::ERROR_CORRECT_LEVEL_L: $rsBlock = 0; break;
+ case QRConst::ERROR_CORRECT_LEVEL_M: $rsBlock = 1; break;
+ case QRConst::ERROR_CORRECT_LEVEL_Q: $rsBlock = 2; break;
+ case QRConst::ERROR_CORRECT_LEVEL_H: $rsBlock = 3; break;
+ default:
+ throw new QRCodeException('tn:'.$typeNumber.'/ecl:'.$errorCorrectLevel);
+ }
+
+ $rsBlock = $this->QR_RS_BLOCK_TABLE[($typeNumber - 1) * 4 + $rsBlock];
+
+ $list = [];
+ $length = count($rsBlock) / 3;
for($i = 0; $i < $length; $i++){
$count = $rsBlock[$i * 3 + 0];
$totalCount = $rsBlock[$i * 3 + 1];
@@ -148,24 +136,5 @@ class RSBlock{
return $list;
}
- /**
- * @param $typeNumber
- * @param $errorCorrectLevel
- *
- * @return mixed
- * @throws \codemasher\QRCode\QRCodeException
- */
- public function getRsBlockTable($typeNumber, $errorCorrectLevel){
-
- switch($errorCorrectLevel){
- case QRConst::ERROR_CORRECT_LEVEL_L: return $this->QR_RS_BLOCK_TABLE[($typeNumber - 1) * 4 + 0];
- case QRConst::ERROR_CORRECT_LEVEL_M: return $this->QR_RS_BLOCK_TABLE[($typeNumber - 1) * 4 + 1];
- case QRConst::ERROR_CORRECT_LEVEL_Q: return $this->QR_RS_BLOCK_TABLE[($typeNumber - 1) * 4 + 2];
- case QRConst::ERROR_CORRECT_LEVEL_H: return $this->QR_RS_BLOCK_TABLE[($typeNumber - 1) * 4 + 3];
- default:
- throw new QRCodeException('tn:'.$typeNumber.'/ecl:'.$errorCorrectLevel);
- }
-
- }
}
diff --git a/src/Util.php b/src/Util.php
index 66b482026..7445fabe7 100644
--- a/src/Util.php
+++ b/src/Util.php
@@ -11,7 +11,6 @@
namespace codemasher\QRCode;
-use codemasher\QRCode\Math;
use codemasher\QRCode\Polynomial;
use codemasher\QRCode\QRCode;
use codemasher\QRCode\QRConst;
@@ -29,7 +28,7 @@ class Util{
/**
* @var array
*/
- protected $QR_MAX_LENGTH = [
+ public $MAX_LENGTH = [
[[41, 25, 17, 10], [34, 20, 14, 8], [27, 16, 11, 7], [17, 10, 7, 4]],
[[77, 47, 32, 20], [63, 38, 26, 16], [48, 29, 20, 12], [34, 20, 14, 8]],
[[127, 77, 53, 32], [101, 61, 42, 26], [77, 47, 32, 20], [58, 35, 24, 15]],
@@ -45,7 +44,7 @@ class Util{
/**
* @var array
*/
- protected $QR_PATTERN_POSITION_TABLE = [
+ public $PATTERN_POSITION = [
[],
[6, 18],
[6, 22],
@@ -88,27 +87,6 @@ class Util{
[6, 30, 58, 86, 114, 142, 170],
];
- /**
- * @var \codemasher\QRCode\Math
- */
- protected $math;
-
- /**
- * Util constructor.
- */
- public function __construct(){
- $this->math = new Math;
- }
-
- /**
- * @param int $typeNumber
- *
- * @return array
- */
- public function getPatternPosition($typeNumber){
- return $this->QR_PATTERN_POSITION_TABLE[$typeNumber - 1];
- }
-
/**
* @param int $typeNumber
* @param int $mode
@@ -121,209 +99,26 @@ class Util{
$_type = $typeNumber - 1;
switch($errorCorrectLevel){
- case QRConst::ERROR_CORRECT_LEVEL_L:
- $_err = 0;
- break;
- case QRConst::ERROR_CORRECT_LEVEL_M:
- $_err = 1;
- break;
- case QRConst::ERROR_CORRECT_LEVEL_Q:
- $_err = 2;
- break;
- case QRConst::ERROR_CORRECT_LEVEL_H:
- $_err = 3;
- break;
+ case QRConst::ERROR_CORRECT_LEVEL_L: $_err = 0; break;
+ case QRConst::ERROR_CORRECT_LEVEL_M: $_err = 1; break;
+ case QRConst::ERROR_CORRECT_LEVEL_Q: $_err = 2; break;
+ case QRConst::ERROR_CORRECT_LEVEL_H: $_err = 3; break;
default:
throw new QRCodeException('$_err: '.$errorCorrectLevel);
}
switch($mode){
- case QRConst::MODE_NUMBER:
- $_mode = 0;
- break;
- case QRConst::MODE_ALPHA_NUM:
- $_mode = 1;
- break;
- case QRConst::MODE_8BIT_BYTE:
- $_mode = 2;
- break;
- case QRConst::MODE_KANJI:
- $_mode = 3;
- break;
+ case QRConst::MODE_NUMBER : $_mode = 0; break;
+ case QRConst::MODE_ALPHANUM: $_mode = 1; break;
+ case QRConst::MODE_BYTE: $_mode = 2; break;
+ case QRConst::MODE_KANJI : $_mode = 3; break;
default :
throw new QRCodeException('$_mode: '.$mode);
}
- return $this->QR_MAX_LENGTH[$_type][$_err][$_mode];
+ return $this->MAX_LENGTH[$_type][$_err][$_mode];
}
- /**
- * @param $errorCorrectLength
- *
- * @return \codemasher\QRCode\Polynomial
- */
- public function getErrorCorrectPolynomial($errorCorrectLength){
- $a = new Polynomial([1]);
-
- for($i = 0; $i < $errorCorrectLength; $i++){
- $a = $a->multiply(new Polynomial([1, $this->math->gexp($i)]));
- }
-
- return $a;
- }
-
- /**
- * @param $maskPattern
- * @param $i
- * @param $j
- *
- * @return bool
- * @throws \codemasher\QRCode\QRCodeException
- */
- public function getMask($maskPattern, $i, $j){
-
- switch($maskPattern){
- case QRConst::MASK_PATTERN000:
- return ($i + $j) % 2 === 0;
- case QRConst::MASK_PATTERN001:
- return $i % 2 === 0;
- case QRConst::MASK_PATTERN010:
- return $j % 3 === 0;
- case QRConst::MASK_PATTERN011:
- return ($i + $j) % 3 === 0;
- case QRConst::MASK_PATTERN100:
- return (floor($i / 2) + floor($j / 3)) % 2 === 0;
- case QRConst::MASK_PATTERN101:
- return ($i * $j) % 2 + ($i * $j) % 3 === 0;
- case QRConst::MASK_PATTERN110:
- return (($i * $j) % 2 + ($i * $j) % 3) % 2 === 0;
- case QRConst::MASK_PATTERN111:
- return (($i * $j) % 3 + ($i + $j) % 2) % 2 === 0;
- default :
- throw new QRCodeException('mask: '.$maskPattern);
- }
- }
-
- /**
- * @param \codemasher\QRCode\QRCode $qrCode
- *
- * @return float|int
- */
- public function getLostPoint(QRCode $qrCode){
- $moduleCount = $qrCode->getModuleCount();
-
- $lostPoint = 0;
-
- // LEVEL1
-
- for($row = 0; $row < $moduleCount; $row++){
- for($col = 0; $col < $moduleCount; $col++){
- $sameCount = 0;
- $dark = $qrCode->isDark($row, $col);
-
- for($r = -1; $r <= 1; $r++){
- if($row + $r < 0 || $moduleCount <= $row + $r){
- continue;
- }
-
- for($c = -1; $c <= 1; $c++){
-
- if($col + $c < 0 || $moduleCount <= $col + $c){
- continue;
- }
-
- if($r == 0 && $c == 0){
- continue;
- }
-
- if($dark == $qrCode->isDark($row + $r, $col + $c)){
- $sameCount++;
- }
- }
- }
-
- if($sameCount > 5){
- $lostPoint += (3 + $sameCount - 5);
- }
- }
- }
-
- // LEVEL2
-
- for($row = 0; $row < $moduleCount - 1; $row++){
- for($col = 0; $col < $moduleCount - 1; $col++){
- $count = 0;
-
- if($qrCode->isDark($row, $col)){
- $count++;
- }
-
- if($qrCode->isDark($row + 1, $col)){
- $count++;
- }
-
- if($qrCode->isDark($row, $col + 1)){
- $count++;
- }
-
- if($qrCode->isDark($row + 1, $col + 1)){
- $count++;
- }
-
- if($count === 0 || $count === 4){
- $lostPoint += 3;
- }
- }
- }
-
- // LEVEL3
-
- for($row = 0; $row < $moduleCount; $row++){
- for($col = 0; $col < $moduleCount - 6; $col++){
- if($qrCode->isDark($row, $col)
- && !$qrCode->isDark($row, $col + 1)
- && $qrCode->isDark($row, $col + 2)
- && $qrCode->isDark($row, $col + 3)
- && $qrCode->isDark($row, $col + 4)
- && !$qrCode->isDark($row, $col + 5)
- && $qrCode->isDark($row, $col + 6)
- ){
- $lostPoint += 40;
- }
- }
- }
-
- for($col = 0; $col < $moduleCount; $col++){
- for($row = 0; $row < $moduleCount - 6; $row++){
- if($qrCode->isDark($row, $col)
- && !$qrCode->isDark($row + 1, $col)
- && $qrCode->isDark($row + 2, $col)
- && $qrCode->isDark($row + 3, $col)
- && $qrCode->isDark($row + 4, $col)
- && !$qrCode->isDark($row + 5, $col)
- && $qrCode->isDark($row + 6, $col)
- ){
- $lostPoint += 40;
- }
- }
- }
-
- // LEVEL4
-
- $darkCount = 0;
- for($col = 0; $col < $moduleCount; $col++){
- for($row = 0; $row < $moduleCount; $row++){
- if($qrCode->isDark($row, $col)){
- $darkCount++;
- }
- }
- }
-
- $ratio = abs(100 * $darkCount / $moduleCount / $moduleCount - 50) / 5;
- $lostPoint += $ratio * 10;
-
- return $lostPoint;
- }
/**
* @param $s
@@ -331,18 +126,20 @@ class Util{
* @return int
*/
public function getMode($s){
+
if($this->isAlphaNum($s)){
if($this->isNumber($s)){
return QRConst::MODE_NUMBER;
}
- return QRConst::MODE_ALPHA_NUM;
+ return QRConst::MODE_ALPHANUM;
}
else if($this->isKanji($s)){
return QRConst::MODE_KANJI;
}
else{
- return QRConst::MODE_8BIT_BYTE;
+ return QRConst::MODE_BYTE;
}
+
}
/**
@@ -350,11 +147,13 @@ class Util{
*
* @return bool
*/
- public function isNumber($s){
- for($i = 0; $i < strlen($s); $i++){
+ protected function isNumber($s){
+
+ $len = strlen($s);
+ for($i = 0; $i < $len; $i++){
$c = ord($s[$i]);
- if(!($this->toCharCode('0') <= $c && $c <= $this->toCharCode('9'))){
+ if(!(ord('0') <= $c && $c <= ord('9'))){
return false;
}
}
@@ -367,14 +166,13 @@ class Util{
*
* @return bool
*/
- public function isAlphaNum($s){
- for($i = 0; $i < strlen($s); $i++){
+ protected function isAlphaNum($s){
+
+ $len = strlen($s);
+ for($i = 0; $i < $len; $i++){
$c = ord($s[$i]);
- if(!($this->toCharCode('0') <= $c && $c <= $this->toCharCode('9'))
- && !($this->toCharCode('A') <= $c && $c <= $this->toCharCode('Z'))
- && strpos(' $%*+-./:', $s[$i]) === false
- ){
+ if(!(ord('0') <= $c && $c <= ord('9')) && !(ord('A') <= $c && $c <= ord('Z')) && strpos(' $%*+-./:', $s[$i]) === false){
return false;
}
}
@@ -387,12 +185,12 @@ class Util{
*
* @return bool
*/
- public function isKanji($s){
- $data = $s;
+ protected function isKanji($s){
+
$i = 0;
-
- while($i + 1 < strlen($data)){
- $c = ((0xff&ord($data[$i])) << 8)|(0xff&ord($data[$i + 1]));
+ $len = strlen($s);
+ while($i + 1 < $len){
+ $c = ((0xff&ord($s[$i])) << 8)|(0xff&ord($s[$i + 1]));
if(!(0x8140 <= $c && $c <= 0x9FFC) && !(0xE040 <= $c && $c <= 0xEBBF)){
return false;
@@ -401,22 +199,13 @@ class Util{
$i += 2;
}
- if($i < strlen($data)){
+ if($i < $len){
return false;
}
return true;
}
- /**
- * @param $s
- *
- * @return int
- */
- public function toCharCode($s){
- return ord($s[0]);
- }
-
/**
* @param $data
*
@@ -455,7 +244,7 @@ class Util{
public function getBCHDigit($data){
$digit = 0;
- while($data != 0){
+ while($data !== 0){
$digit++;
$data >>= 1;
}
@@ -463,4 +252,20 @@ class Util{
return $digit;
}
+
+ /**
+ * used for converting fg/bg colors (e.g. #0000ff = 0x0000FF) - added 2015.07.27 ~ DoktorJ
+ *
+ * @param int $hex
+ *
+ * @return array
+ */
+ public function hex2rgb($hex = 0x0){
+ return [
+ 'r' => floor($hex / 65536),
+ 'g' => floor($hex / 256) % 256,
+ 'b' => $hex % 256,
+ ];
+ }
+
}