smiley 10 лет назад
Родитель
Сommit
e21a7da686
14 измененных файлов с 673 добавлено и 878 удалено
  1. 15 8
      examples/custom.php
  2. 13 20
      src/BitBuffer.php
  3. 10 39
      src/Data/AlphaNum.php
  4. 6 6
      src/Data/Byte.php
  5. 9 10
      src/Data/Kanji.php
  6. 9 42
      src/Data/Number.php
  7. 10 27
      src/Data/QRDataBase.php
  8. 6 6
      src/Data/QRDataInterface.php
  9. 21 61
      src/Polynomial.php
  10. 283 388
      src/QRCode.php
  11. 2 2
      src/QRCodeException.php
  12. 178 10
      src/QRConst.php
  13. 0 144
      src/RSBlock.php
  14. 111 115
      src/Util.php

+ 15 - 8
examples/custom.php

@@ -2,21 +2,28 @@
 
 require_once '../vendor/autoload.php';
 
-use codemasher\QRCode\QRCode;
-use codemasher\QRCode\QRConst;
+use chillerlan\QRCode\QRCode;
+use chillerlan\QRCode\QRConst;
 
 $starttime = microtime(true);
 
+$qrcode = (new QRCode)
+	->setErrorCorrectLevel(QRConst::ERROR_CORRECT_LEVEL_M)
+	->setQRType(QRConst::TYPE_05)
+;
+
 // google authenticator
 // https://chart.googleapis.com/chart?chs=200x200&chld=M%7C0&cht=qr&chl=otpauth%3A%2F%2Ftotp%2Ftest%3Fsecret%3DB3JX4VCVJDVNXNZ5%26issuer%3Dchillerlan.net
+$qrcode
+	->setData('otpauth://totp/test?secret=B3JX4VCVJDVNXNZ5&issuer=chillerlan.net')
+	->getRawData()
+;
 
-$qrcode = new QRCode('otpauth://totp/test?secret=B3JX4VCVJDVNXNZ5&issuer=chillerlan.net', QRConst::ERROR_CORRECT_LEVEL_M, 5);
-
-for($row = 0; $row < $qrcode->moduleCount; $row++){
-	for($col = 0; $col < $qrcode->moduleCount; $col++){
-		echo (bool)$qrcode->modules[$row][$col] ? '#' : ' ';
+for($row = 0; $row < $qrcode->pixelCount; $row++){
+	for($col = 0; $col < $qrcode->pixelCount; $col++){
+		echo $qrcode->matrix[$row][$col] ? '*' : ' ';
 	}
 	echo PHP_EOL;
 }
 
-echo 'QRCode '.round((microtime(true)-$starttime), 5).PHP_EOL;
+echo 'QRCode: '.round((microtime(true)-$starttime), 5).PHP_EOL;

+ 13 - 20
src/BitBuffer.php

@@ -1,18 +1,19 @@
 <?php
 /**
+ * Class BitBuffer
  *
  * @filesource   BitBuffer.php
  * @created      25.11.2015
- * @package      codemasher\QRCode
+ * @package      chillerlan\QRCode
  * @author       Smiley <smiley@chillerlan.net>
  * @copyright    2015 Smiley
  * @license      MIT
  */
 
-namespace codemasher\QRCode;
+namespace chillerlan\QRCode;
 
 /**
- * Class BitBuffer
+ *
  */
 class BitBuffer{
 
@@ -27,35 +28,29 @@ class BitBuffer{
 	public $length = 0;
 
 	/**
-	 * @return string
+	 *
 	 */
-/*	public function __toString(){
-		$buffer = '';
-
-		for($i = 0; $i < $this->length; $i++){
-			$buffer .= (string)(int)(($this->buffer[(int)floor($i / 8)] >> (7 - $i % 8))&1) === 1;
-		}
-
-		return $buffer;
+	public function clear(){
+		$this->buffer = [];
+		$this->length = 0;
 	}
-*/
+
 	/**
-	 * @param $num
-	 * @param $length
+	 * @param int $num
+	 * @param int $length
 	 *
 	 * @return $this
 	 */
 	public function put($num, $length){
 
 		for($i = 0; $i < $length; $i++){
-			$this->putBit((($num >> ($length - $i - 1))&1) === 1);
+			$this->putBit(($num >> ($length - $i - 1))&1 === 1);
 		}
 
-		return $this;
 	}
 
 	/**
-	 * @param $bit
+	 * @param bool $bit
 	 *
 	 * @return $this
 	 */
@@ -71,8 +66,6 @@ class BitBuffer{
 		}
 
 		$this->length++;
-
-		return $this;
 	}
 
 }

+ 10 - 39
src/Data/AlphaNum.php

@@ -4,17 +4,17 @@
  *
  * @filesource   AlphaNum.php
  * @created      25.11.2015
- * @package      codemasher\QRCode\Data
+ * @package      chillerlan\QRCode\Data
  * @author       Smiley <smiley@chillerlan.net>
  * @copyright    2015 Smiley
  * @license      MIT
  */
 
-namespace codemasher\QRCode\Data;
+namespace chillerlan\QRCode\Data;
 
-use codemasher\QRCode\BitBuffer;
-use codemasher\QRCode\QRCodeException;
-use codemasher\QRCode\QRConst;
+use chillerlan\QRCode\BitBuffer;
+use chillerlan\QRCode\QRConst;
+use chillerlan\QRCode\Util;
 
 /**
  *
@@ -22,7 +22,7 @@ use codemasher\QRCode\QRConst;
 class AlphaNum extends QRDataBase implements QRDataInterface{
 
 	/**
-	 * @var
+	 * @var int
 	 */
 	public $mode = QRConst::MODE_ALPHANUM;
 
@@ -32,47 +32,18 @@ class AlphaNum extends QRDataBase implements QRDataInterface{
 	protected $lengthBits = [9, 11, 13];
 
 	/**
-	 * @param $buffer
+	 * @param \chillerlan\QRCode\BitBuffer $buffer
 	 */
 	public function write(BitBuffer &$buffer){
-
 		$i = 0;
+
 		while($i + 1 < $this->dataLength){
-			$buffer->put($this->getCode(ord($this->data[$i])) * 45 + $this->getCode(ord($this->data[$i + 1])), 11);
+			$buffer->put(Util::getCharCode($this->data[$i]) * 45 + Util::getCharCode($this->data[$i + 1]), 11);
 			$i += 2;
 		}
 
 		if($i < $this->dataLength){
-			$buffer->put($this->getCode(ord($this->data[$i])), 6);
-		}
-
-	}
-
-	/**
-	 * @param $c
-	 *
-	 * @return int
-	 * @throws \codemasher\QRCode\QRCodeException
-	 */
-	protected function getCode($c){
-
-		switch(true){
-			case ord('0') <= $c && $c <= ord('9'): return $c - ord('0');
-			case ord('A') <= $c && $c <= ord('Z'): return $c - ord('A') + 10;
-			default:
-				switch($c){
-					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);
-				}
+			$buffer->put(Util::getCharCode($this->data[$i]), 6);
 		}
 
 	}

+ 6 - 6
src/Data/Byte.php

@@ -4,16 +4,16 @@
  *
  * @filesource   Byte.php
  * @created      25.11.2015
- * @package      codemasher\QRCode\Data
+ * @package      chillerlan\QRCode\Data
  * @author       Smiley <smiley@chillerlan.net>
  * @copyright    2015 Smiley
  * @license      MIT
  */
 
-namespace codemasher\QRCode\Data;
+namespace chillerlan\QRCode\Data;
 
-use codemasher\QRCode\BitBuffer;
-use codemasher\QRCode\QRConst;
+use chillerlan\QRCode\BitBuffer;
+use chillerlan\QRCode\QRConst;
 
 /**
  *
@@ -21,7 +21,7 @@ use codemasher\QRCode\QRConst;
 class Byte extends QRDataBase implements QRDataInterface{
 
 	/**
-	 * @var
+	 * @var int
 	 */
 	public $mode = QRConst::MODE_BYTE;
 
@@ -31,7 +31,7 @@ class Byte extends QRDataBase implements QRDataInterface{
 	protected $lengthBits = [8, 16, 16];
 
 	/**
-	 * @param $buffer
+	 * @param \chillerlan\QRCode\BitBuffer $buffer
 	 */
 	public function write(BitBuffer &$buffer){
 		for($i = 0; $i < $this->dataLength; $i++){

+ 9 - 10
src/Data/Kanji.php

@@ -4,17 +4,17 @@
  *
  * @filesource   Kanji.php
  * @created      25.11.2015
- * @package      codemasher\QRCode\Data
+ * @package      chillerlan\QRCode\Data
  * @author       Smiley <smiley@chillerlan.net>
  * @copyright    2015 Smiley
  * @license      MIT
  */
 
-namespace codemasher\QRCode\Data;
+namespace chillerlan\QRCode\Data;
 
-use codemasher\QRCode\BitBuffer;
-use codemasher\QRCode\QRCodeException;
-use codemasher\QRCode\QRConst;
+use chillerlan\QRCode\BitBuffer;
+use chillerlan\QRCode\QRCodeException;
+use chillerlan\QRCode\QRConst;
 
 /**
  *
@@ -22,7 +22,7 @@ use codemasher\QRCode\QRConst;
 class Kanji extends QRDataBase implements QRDataInterface{
 
 	/**
-	 * @var
+	 * @var int
 	 */
 	public $mode = QRConst::MODE_KANJI;
 
@@ -32,9 +32,9 @@ class Kanji extends QRDataBase implements QRDataInterface{
 	protected $lengthBits = [8, 10, 12];
 
 	/**
-	 * @param $buffer
+	 * @param \chillerlan\QRCode\BitBuffer $buffer
 	 *
-	 * @throws \codemasher\QRCode\QRCodeException
+	 * @throws \chillerlan\QRCode\QRCodeException
 	 */
 	public function write(BitBuffer &$buffer){
 
@@ -52,8 +52,7 @@ class Kanji extends QRDataBase implements QRDataInterface{
 				throw new QRCodeException('illegal char at '.($i + 1).' ('.$c.')');
 			}
 
-			$c = (($c >> 8)&0xff) * 0xC0 + ($c&0xff);
-			$buffer->put($c, 13);
+			$buffer->put((($c >> 8)&0xff) * 0xC0 + ($c&0xff), 13);
 			$i += 2;
 		}
 

+ 9 - 42
src/Data/Number.php

@@ -10,11 +10,11 @@
  * @license      MIT
  */
 
-namespace codemasher\QRCode\Data;
+namespace chillerlan\QRCode\Data;
 
-use codemasher\QRCode\BitBuffer;
-use codemasher\QRCode\QRCodeException;
-use codemasher\QRCode\QRConst;
+use chillerlan\QRCode\BitBuffer;
+use chillerlan\QRCode\QRConst;
+use chillerlan\QRCode\Util;
 
 /**
  *
@@ -32,60 +32,27 @@ class Number extends QRDataBase implements QRDataInterface{
 	protected $lengthBits = [10, 12, 14];
 
 	/**
-	 * @param $buffer
-	 *
-	 * @return $this
+	 * @param \chillerlan\QRCode\BitBuffer $buffer
 	 */
 	public function write(BitBuffer &$buffer){
-
 		$i = 0;
+
 		while($i + 2 < $this->dataLength){
-			$num = $this->parseInt(substr($this->data, $i, 3));
-			$buffer->put($num, 10);
+			$buffer->put(Util::parseInt(substr($this->data, $i, 3)), 10);
 			$i += 3;
 		}
 
 		if($i < $this->dataLength){
 
 			if($this->dataLength - $i === 1){
-				$num = $this->parseInt(substr($this->data, $i, $i + 1));
-				$buffer->put($num, 4);
+				$buffer->put(Util::parseInt(substr($this->data, $i, $i + 1)), 4);
 			}
 			else if($this->dataLength - $i === 2){
-				$num = $this->parseInt(substr($this->data, $i, $i + 2));
-				$buffer->put($num, 7);
-			}
-
-		}
-
-		return $this;
-	}
-
-	/**
-	 * @param string $string
-	 *
-	 * @return int
-	 * @throws \codemasher\QRCode\QRCodeException
-	 */
-	protected function parseInt($string){
-
-		$num = 0;
-		$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);
+				$buffer->put(Util::parseInt(substr($this->data, $i, $i + 2)), 7);
 			}
 
-			$num = $num * 10 + $c;
 		}
 
-		return $num;
 	}
 
 }

+ 10 - 27
src/Data/QRDataBase.php

@@ -4,26 +4,20 @@
  *
  * @filesource   QRDataBase.php
  * @created      25.11.2015
- * @package      codemasher\QRCode\Data
+ * @package      chillerlan\QRCode\Data
  * @author       Smiley <smiley@chillerlan.net>
  * @copyright    2015 Smiley
  * @license      MIT
  */
 
-namespace codemasher\QRCode\Data;
+namespace chillerlan\QRCode\Data;
 
-use codemasher\QRCode\BitBuffer;
-use codemasher\QRCode\QRCodeException;
+use chillerlan\QRCode\QRCodeException;
 
 /**
  *
  */
-class QRDataBase implements QRDataInterface{
-
-	/**
-	 * @var
-	 */
-	public $mode;
+class QRDataBase{
 
 	/**
 	 * @var string
@@ -43,7 +37,7 @@ class QRDataBase implements QRDataInterface{
 	/**
 	 * QRDataBase constructor.
 	 *
-	 * @param $data
+	 * @param string $data
 	 */
 	public function __construct($data){
 		$this->data = $data;
@@ -51,32 +45,21 @@ class QRDataBase implements QRDataInterface{
 	}
 
 	/**
-	 * @param $type
+	 * @param int $type
 	 *
 	 * @return int
-	 * @throws \codemasher\QRCode\QRCodeException
+	 * @throws \chillerlan\QRCode\QRCodeException
 	 */
 	public function getLengthInBits($type){
 
 		switch(true){
-			case $type >= 1 && $type <= 9: return $this->lengthBits[0]; // 1 - 9
-			case $type <= 26             : return $this->lengthBits[1]; // 10 - 26
-			case $type <= 40             : return $this->lengthBits[2]; // 27 - 40
+			case $type >=  1 && $type <= 9: return $this->lengthBits[0]; //  1 -  9
+			case $type <= 26              : return $this->lengthBits[1]; // 10 - 26
+			case $type <= 40              : return $this->lengthBits[2]; // 27 - 40
 			default:
 				throw new QRCodeException('$type: '.$type);
 		}
 
 	}
 
-	/**
-	 * @todo  Implement write() method.
-	 *
-	 * @param \codemasher\QRCode\BitBuffer $buffer
-	 *
-	 * @throws \codemasher\QRCode\QRCodeException
-	 */
-	public function write(BitBuffer &$buffer){
-		throw new QRCodeException('Method should be implemented in child classes');
-	}
-
 }

+ 6 - 6
src/Data/QRDataInterface.php

@@ -4,15 +4,15 @@
  *
  * @filesource   QRDataInterface.php
  * @created      01.12.2015
- * @package      codemasher\QRCode\Data
+ * @package      chillerlan\QRCode\Data
  * @author       Smiley <smiley@chillerlan.net>
  * @copyright    2015 Smiley
  * @license      MIT
  */
 
-namespace codemasher\QRCode\Data;
+namespace chillerlan\QRCode\Data;
 
-use codemasher\QRCode\BitBuffer;
+use chillerlan\QRCode\BitBuffer;
 
 /**
  *
@@ -20,7 +20,7 @@ use codemasher\QRCode\BitBuffer;
 interface QRDataInterface{
 
 	/**
-	 * @param \codemasher\QRCode\BitBuffer $buffer
+	 * @param \chillerlan\QRCode\BitBuffer $buffer
 	 */
 	public function write(BitBuffer &$buffer);
 
@@ -28,8 +28,8 @@ interface QRDataInterface{
 	 * @param $type
 	 *
 	 * @return int
-	 * @throws \codemasher\QRCode\QRCodeException
+	 * @throws \chillerlan\QRCode\QRCodeException
 	 */
 	public function getLengthInBits($type);
 
-}
+}

+ 21 - 61
src/Polynomial.php

@@ -1,18 +1,19 @@
 <?php
 /**
+ * Class Polynomial
  *
  * @filesource   Polynomial.php
  * @created      25.11.2015
- * @package      codemasher\QRCode
+ * @package      chillerlan\QRCode
  * @author       Smiley <smiley@chillerlan.net>
  * @copyright    2015 Smiley
  * @license      MIT
  */
 
-namespace codemasher\QRCode;
+namespace chillerlan\QRCode;
 
 /**
- * Class Polynomial
+ *
  */
 class Polynomial{
 
@@ -65,10 +66,9 @@ class Polynomial{
 	}
 
 	/**
-	 * @return $this
+	 *
 	 */
 	protected function setTables(){
-
 		$this->EXP_TABLE = $this->LOG_TABLE = array_fill(0, 256, 0);
 
 		for($i = 0; $i < 8; $i++){
@@ -83,86 +83,46 @@ class Polynomial{
 			$this->LOG_TABLE[$this->EXP_TABLE[$i]] = $i;
 		}
 
-		return $this;
-	}
-
-	/**
-	 * @return string
-	 */
-/*	public function __toString(){
-		$buffer = '';
-
-		foreach($this->num as $i => $value){
-			if($i > 0){
-				$buffer .= ',';
-			}
-			$buffer .= $value;
-		}
-
-		return $buffer;
 	}
-*/
-	/**
-	 * @return string
-	 */
-/*	public function toLogString(){
-		$buffer = '';
 
-		foreach($this->num as $i => $value){
-			if($i > 0){
-				$buffer .= ',';
-			}
-			$buffer .= $this->glog($value);
-		}
-
-		return $buffer;
-	}
-*/
 	/**
 	 * @param array $e
-	 *
-	 * @return $this
 	 */
 	public function multiply(array $e){
+		$n = array_fill(0, count($this->num) + count($e) - 1, 0);
 
-		$num = array_fill(0, count($this->num) + count($e) - 1, 0);
-		foreach($this->num as $i => $vi){
-			foreach($e as $j => $vj){
-				$num[$i + $j] ^= $this->gexp($this->glog($vi) + $this->glog($vj));
+		foreach($this->num as $i => &$vi){
+			foreach($e as $j => &$vj){
+				$n[$i + $j] ^= $this->gexp($this->glog($vi) + $this->glog($vj));
 			}
 		}
 
-		$this->setNum($num);
-
-		return $this;
+		$this->setNum($n);
 	}
 
 	/**
 	 * @param array $e
-	 *
-	 * @return $this
 	 */
-	public function mod($e){
+	public function mod(array $e){
+		$n = $this->num;
 
-		if(count($this->num) - count($e) < 0){
-			return $this;
+		if(count($n) - count($e) < 0){
+			return;
 		}
 
-		$ratio = $this->glog($this->num[0]) - $this->glog($e[0]);
-		foreach($e as $i => $value){
-			$this->num[$i] ^= $this->gexp($this->glog($e[$i]) + $ratio);
+		$ratio = $this->glog($n[0]) - $this->glog($e[0]);
+		foreach($e as $i => &$v){
+			$n[$i] ^= $this->gexp($this->glog($v) + $ratio);
 		}
 
-		$this->setNum($this->num)->mod($e);
-
-		return $this->num;
+		$this->setNum($n)->mod($e);
 	}
 
 	/**
 	 * @param int $n
 	 *
-	 * @return mixed
-	 * @throws \codemasher\QRCode\QRCodeException
+	 * @return int
+	 * @throws \chillerlan\QRCode\QRCodeException
 	 */
 	public function glog($n){
 
@@ -176,7 +136,7 @@ class Polynomial{
 	/**
 	 * @param int $n
 	 *
-	 * @return mixed
+	 * @return int
 	 */
 	public function gexp($n){
 

+ 283 - 388
src/QRCode.php

@@ -4,259 +4,220 @@
  *
  * @filesource   QRCode.php
  * @created      26.11.2015
- * @package      codemasher\QRCode
+ * @package      chillerlan\QRCode
  * @author       Smiley <smiley@chillerlan.net>
  * @copyright    2015 Smiley
  * @license      MIT
  */
 
-namespace codemasher\QRCode;
+namespace chillerlan\QRCode;
 
-use codemasher\QRCode\Data\QRDataBase;
+use chillerlan\QRCode\Data\QRDataInterface;
 
 /**
  * @link https://github.com/kazuhikoarase/qrcode-generator/tree/master/php
  */
 class QRCode{
 
-	const QR_PAD0 = 0xEC;
-	const QR_PAD1 = 0x11;
-
 	/**
 	 * @var int
 	 */
-	public $moduleCount;
+	public $pixelCount;
 
 	/**
 	 * @var array
 	 */
-	public $modules;
+	public $matrix;
 
 	/**
 	 * @var int
 	 */
-	protected $typeNumber;
+	protected $mode;
 
 	/**
 	 * @var int
 	 */
-	protected $errorCorrectLevel;
-
-	/**
-	 * @var array -> \codemasher\QRCode\Data\QRDataInterface
-	 */
-	protected $qrDataList = [];
-
-	/**
-	 * @var array
-	 */
-	protected $rsBlockList = [];
-
-	/**
-	 * @var
-	 */
-	protected $data;
+	protected $typeNumber;
 
 	/**
 	 * @var int
 	 */
-	protected $mode;
-
-	/**
-	 * @var array
-	 */
-	protected $ERROR_CORRECT_LEVEL = [
-		QRConst::ERROR_CORRECT_LEVEL_L,
-		QRConst::ERROR_CORRECT_LEVEL_M,
-		QRConst::ERROR_CORRECT_LEVEL_Q,
-		QRConst::ERROR_CORRECT_LEVEL_H,
-	];
-
-	/**
-	 * @var array
-	 */
-	protected $qrDataInterface = [
-		QRConst::MODE_ALPHANUM => '\\codemasher\\QRCode\\Data\\AlphaNum',
-		QRConst::MODE_BYTE     => '\\codemasher\\QRCode\\Data\\Byte',
-		QRConst::MODE_KANJI    => '\\codemasher\\QRCode\\Data\\Kanji',
-		QRConst::MODE_NUMBER   => '\\codemasher\\QRCode\\Data\\Number',
-	];
-
-	/**
-	 * @var \codemasher\QRCode\Util
-	 */
-	protected $util;
+	protected $errorCorrectLevel;
 
 	/**
-	 * @var \codemasher\QRCode\RSBlock
+	 * @var \chillerlan\QRCode\Data\QRDataInterface
 	 */
-	protected $rsBlock;
+	protected $qrDataInterface;
 
 	/**
-	 * @var \codemasher\QRCode\BitBuffer
+	 * @var \chillerlan\QRCode\BitBuffer
 	 */
 	protected $bitBuffer;
 
 	/**
-	 * @todo WIP
-	 *
 	 * QRCode constructor.
 	 *
 	 * @param string $data
 	 * @param int    $errorCorrectLevel
 	 * @param int    $typeNumber
 	 *
-	 * @throws \codemasher\QRCode\QRCodeException
+	 * @throws \chillerlan\QRCode\QRCodeException
 	 */
 	public function __construct($data = '', $errorCorrectLevel = QRConst::ERROR_CORRECT_LEVEL_M, $typeNumber = null){
-		$this->util = new Util;
-		$this->rsBlock = new RSBlock;
 		$this->bitBuffer = new BitBuffer;
 
-		$this->setErrorCorrectLevel($errorCorrectLevel)->setTypeNumber($typeNumber);
-
 		if(!empty($data)){
-			$this->getMinimumQRCode($data);
+			$this->getQRCode($data, $errorCorrectLevel, $typeNumber);
 		}
 
 	}
 
 	/**
-	 * @todo WIP
-	 *
-	 * @param $data
+	 * @param string $data
 	 *
-	 * @return \codemasher\QRCode\QRCode
-	 * @throws \codemasher\QRCode\QRCodeException
+	 * @return $this
+	 * @throws \chillerlan\QRCode\QRCodeException
 	 */
-	public function getMinimumQRCode($data){
-		$mode = $this->util->getMode($data);
-		$this->addData($data, $mode);
-
-		/** @var \codemasher\QRCode\Data\QRDataBase $qrData */
-		$qrData = $this->qrDataList[0];
-		$length = $qrData->mode === QRConst::MODE_KANJI ? floor($qrData->dataLength / 2) : $qrData->dataLength;
+	public function setData($data){
+		$data = trim((string)$data);
 
-		for($typeNumber = 1; $typeNumber <= 10; $typeNumber++){
-			if($length <= $this->util->getMaxLength($typeNumber, $mode, $this->errorCorrectLevel)){
-				$this->typeNumber = $typeNumber;
-				break;
-			}
+		if(empty($data)){
+			throw new QRCodeException('No data given.');
 		}
 
-		$this->make();
+		$this->mode = Util::getMode($data);
+
+		$qrDataInterface = __NAMESPACE__.'\\Data\\'.[
+			QRConst::MODE_ALPHANUM => 'AlphaNum',
+			QRConst::MODE_BYTE     => 'Byte',
+			QRConst::MODE_KANJI    => 'Kanji',
+			QRConst::MODE_NUMBER   => 'Number',
+		][$this->mode];
+
+		$this->qrDataInterface = new $qrDataInterface($data);
 
 		return $this;
 	}
 
 	/**
-	 * @todo WIP
-	 *
-	 * @param string $data
-	 *
-	 * @param null   $mode
+	 * @param int $errorCorrectLevel
 	 *
 	 * @return $this
-	 * @throws \codemasher\QRCode\QRCodeException
+	 * @throws \chillerlan\QRCode\QRCodeException
 	 */
-	public function addData($data, $mode = null){
-		if($mode === null){
-			$mode = $this->util->getMode($data);
-		}
+	public function setErrorCorrectLevel($errorCorrectLevel){
 
-		if(!isset($this->qrDataInterface[$mode])){
-			throw new QRCodeException('mode: '.$mode);
+		if(!array_key_exists($errorCorrectLevel, QRConst::RSBLOCK)){
+			throw new QRCodeException('Invalid error correct level: '.$errorCorrectLevel);
 		}
 
-		$this->qrDataList[] = new $this->qrDataInterface[$mode]($data);
+		$this->errorCorrectLevel = $errorCorrectLevel;
 
 		return $this;
 	}
 
-
 	/**
-	 * @param $errorCorrectLevel
+	 * @param int $typeNumber
 	 *
 	 * @return $this
-	 * @throws \codemasher\QRCode\QRCodeException
+	 * @throws \chillerlan\QRCode\QRCodeException
 	 */
-	public function setErrorCorrectLevel($errorCorrectLevel){
+	public function setQRType($typeNumber){
+		$this->typeNumber = intval($typeNumber);
 
-		if(!in_array($errorCorrectLevel, $this->ERROR_CORRECT_LEVEL)){
-			throw new QRCodeException('Invalid error correct level: '.$errorCorrectLevel);
-		}
+		if($this->typeNumber < 1 || $this->typeNumber > 10){
 
-		$this->errorCorrectLevel = $errorCorrectLevel;
+			$length = $this->qrDataInterface->mode === QRConst::MODE_KANJI ? floor($this->qrDataInterface->dataLength / 2) : $this->qrDataInterface->dataLength;
+
+			for($type = 1; $type <= 10; $type++){
+				if($length <= Util::getMaxLength($type, $this->mode, $this->errorCorrectLevel)){
+					$this->typeNumber = $type;
+
+					return $this;
+				}
+			}
+
+		}
 
 		return $this;
 	}
 
 	/**
-	 * @param int $typeNumber
+	 * @param string $data
+	 * @param int    $errorCorrectLevel
+	 * @param int    $typeNumber
 	 *
 	 * @return $this
-	 * @throws \codemasher\QRCode\QRCodeException
+	 * @throws \chillerlan\QRCode\QRCodeException
 	 */
-	public function setTypeNumber($typeNumber){
-		$typeNumber = intval($typeNumber);
+	public function getQRCode($data, $errorCorrectLevel = QRConst::ERROR_CORRECT_LEVEL_M, $typeNumber = null){
 
-		if($typeNumber < 1 || $typeNumber > 10){
-			throw new QRCodeException('Invalid type number: '.$typeNumber);
-		}
-
-		$this->typeNumber = $typeNumber;
+		$this
+		     ->setData($data)
+		     ->setErrorCorrectLevel($errorCorrectLevel)
+		     ->setQRType($typeNumber)
+		     ->getRawData()
+		;
 
 		return $this;
 	}
 
 	/**
-	 *
+	 * @return $this
 	 */
-	public function make(){
+	public function getRawData(){
+
+		// getLostPoint
 		$minLostPoint = 0;
 		$pattern = 0;
 
 		for($i = 0; $i < 8; $i++){
-			$this->makeImpl(true, $i);
+			$this->getMatrix(true, $i);
 			$lostPoint = 0;
 
 			// LEVEL1
-			for($row = 0; $row < $this->moduleCount; $row++){
-				for($col = 0; $col < $this->moduleCount; $col++){
+			for($row = 0; $row < $this->pixelCount; $row++){
+				for($col = 0; $col < $this->pixelCount; $col++){
 					$sameCount = 0;
-					$dark = $this->modules[$row][$col];
+					$dark = $this->matrix[$row][$col];
 
 					for($r = -1; $r <= 1; $r++){
-						if($row + $r < 0 || $this->moduleCount <= $row + $r){
+
+						if($row + $r < 0 || $this->pixelCount <= $row + $r){
 							continue;
 						}
 
 						for($c = -1; $c <= 1; $c++){
 
-							if(($r === 0 && $c === 0) || ($col + $c < 0 || $this->moduleCount <= $col + $c)){
+							if(($r === 0 && $c === 0) || ($col + $c < 0 || $this->pixelCount <= $col + $c)){
 								continue;
 							}
 
-							if($this->modules[$row + $r][$col + $c] === $dark){
+							if($this->matrix[$row + $r][$col + $c] === $dark){
 								$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++){
+			for($row = 0; $row < $this->pixelCount - 1; $row++){
+				for($col = 0; $col < $this->pixelCount - 1; $col++){
 					$count = 0;
 
-					if($this->modules[$row][$col] || $this->modules[$row][$col + 1]
-						|| $this->modules[$row + 1][$col] || $this->modules[$row + 1][$col + 1]
+					if(
+						   $this->matrix[$row    ][$col    ]
+						|| $this->matrix[$row    ][$col + 1]
+						|| $this->matrix[$row + 1][$col    ]
+						|| $this->matrix[$row + 1][$col + 1]
 					){
 						$count++;
 					}
@@ -269,30 +230,32 @@ class QRCode{
 			}
 
 			// LEVEL3
-			for($row = 0; $row < $this->moduleCount; $row++){
-				for($col = 0; $col < $this->moduleCount - 6; $col++){
-					if($this->modules[$row][$col]
-						&& !$this->modules[$row][$col + 1]
-						&&  $this->modules[$row][$col + 2]
-						&&  $this->modules[$row][$col + 3]
-						&&  $this->modules[$row][$col + 4]
-						&& !$this->modules[$row][$col + 5]
-						&&  $this->modules[$row][$col + 6]
+			for($row = 0; $row < $this->pixelCount; $row++){
+				for($col = 0; $col < $this->pixelCount - 6; $col++){
+					if(
+						    $this->matrix[$row][$col    ]
+						&& !$this->matrix[$row][$col + 1]
+						&&  $this->matrix[$row][$col + 2]
+						&&  $this->matrix[$row][$col + 3]
+						&&  $this->matrix[$row][$col + 4]
+						&& !$this->matrix[$row][$col + 5]
+						&&  $this->matrix[$row][$col + 6]
 					){
 						$lostPoint += 40;
 					}
 				}
 			}
 
-			for($col = 0; $col < $this->moduleCount; $col++){
-				for($row = 0; $row < $this->moduleCount - 6; $row++){
-					if($this->modules[$row][$col]
-						&& !$this->modules[$row + 1][$col]
-						&&  $this->modules[$row + 2][$col]
-						&&  $this->modules[$row + 3][$col]
-						&&  $this->modules[$row + 4][$col]
-						&& !$this->modules[$row + 5][$col]
-						&&  $this->modules[$row + 6][$col]
+			for($col = 0; $col < $this->pixelCount; $col++){
+				for($row = 0; $row < $this->pixelCount - 6; $row++){
+					if(
+						    $this->matrix[$row    ][$col]
+						&& !$this->matrix[$row + 1][$col]
+						&&  $this->matrix[$row + 2][$col]
+						&&  $this->matrix[$row + 3][$col]
+						&&  $this->matrix[$row + 4][$col]
+						&& !$this->matrix[$row + 5][$col]
+						&&  $this->matrix[$row + 6][$col]
 					){
 						$lostPoint += 40;
 					}
@@ -301,15 +264,15 @@ class QRCode{
 
 			// LEVEL4
 			$darkCount = 0;
-			for($col = 0; $col < $this->moduleCount; $col++){
-				for($row = 0; $row < $this->moduleCount; $row++){
-					if($this->modules[$row][$col]){
+			for($col = 0; $col < $this->pixelCount; $col++){
+				for($row = 0; $row < $this->pixelCount; $row++){
+					if($this->matrix[$row][$col]){
 						$darkCount++;
 					}
 				}
 			}
 
-			$ratio = abs(100 * $darkCount / $this->moduleCount / $this->moduleCount - 50) / 5;
+			$ratio = abs(100 * $darkCount / $this->pixelCount / $this->pixelCount - 50) / 5;
 			$lostPoint += $ratio * 10;
 
 			if($i === 0 || $minLostPoint > $lostPoint){
@@ -319,7 +282,7 @@ class QRCode{
 
 		}
 
-		$this->makeImpl(false, $pattern);
+		$this->getMatrix(false, $pattern);
 
 		return $this;
 	}
@@ -327,35 +290,74 @@ class QRCode{
 	/**
 	 * @param bool $test
 	 * @param int  $pattern
-	 *
-	 * @return $this
-	 * @throws \codemasher\QRCode\QRCodeException
 	 */
-	protected function makeImpl($test, $pattern){
-		$this->moduleCount = $this->typeNumber * 4 + 17;
-		$this->modules = [];
+	protected function setTypeInfo($test, $pattern){
+		$this->setPattern();
+		$bits = Util::getBCHTypeInfo(($this->errorCorrectLevel << 3) | $pattern);
+
+		for($i = 0; $i < 15; $i++){
+			$mod = !$test && (($bits >> $i) & 1) === 1;
+
+			switch(true){
+				case $i < 6:$this->matrix[$i    ][8] = $mod; break;
+				case $i < 8:$this->matrix[$i + 1][8] = $mod; break;
+				default:
+					$this->matrix[$this->pixelCount - 15 + $i][8] = $mod;
+			}
+
+			switch(true){
+				case $i < 8:$this->matrix[8][$this->pixelCount - $i - 1] = $mod; break;
+				case $i < 9:$this->matrix[8][           15 + 1 - $i - 1] = $mod; break;
+				default:
+					$this->matrix[8][15 - $i - 1] = $mod;
+			}
 
-		$nullArray = array_fill(0, $this->moduleCount, 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);
+		$this->matrix[$this->pixelCount - 8][8] = !$test;
+	}
+
+	/**
+	 * @throws \chillerlan\QRCode\QRCodeException
+	 */
+	protected function setPattern(){
+
+		// setupPositionProbePattern
+		foreach([[0, 0], [$this->pixelCount - 7, 0], [0, $this->pixelCount - 7]] as $grid){
+			$row = $grid[0];
+			$col = $grid[1];
+
+			for($r = -1; $r <= 7; $r++){
+				for($c = -1; $c <= 7; $c++){
+
+					if($row + $r <= -1 || $this->pixelCount <= $row + $r || $col + $c <= -1 || $this->pixelCount <= $col + $c){
+						continue;
+					}
+
+					$this->matrix[$row + $r][$col + $c] =
+						   (0 <= $r && $r <= 6 && ($c === 0 || $c === 6))
+						|| (0 <= $c && $c <= 6 && ($r === 0 || $r === 6))
+						|| (2 <= $c && $c <= 4 && 2 <= $r && $r <= 4);
+				}
+			}
+		}
 
 		// setupPositionAdjustPattern
-		$pos = $this->util->PATTERN_POSITION[$this->typeNumber - 1];
+		$PATTERN_POSITION = QRConst::PATTERN_POSITION; // PHP5 compat
+		$pos = $PATTERN_POSITION[$this->typeNumber - 1];
 		foreach($pos as $i => $posI){
 			foreach($pos as $j => $posJ){
-				if($this->modules[$posI][$posJ] !== null){
+
+				if($this->matrix[$posI][$posJ] !== null){
 					continue;
 				}
 
 				for($row = -2; $row <= 2; $row++){
 					for($col = -2; $col <= 2; $col++){
-						$this->modules[$posI + $row][$posJ + $col] =
-							(bool)$row === -2 || $row === 2 || $col === -2 || $col === 2 || ($row === 0 && $col === 0);
+						$this->matrix[$posI + $row][$posJ + $col] =
+							   $row === -2 || $row === 2
+							|| $col === -2 || $col === 2
+							||($row ===  0 && $col === 0);
 					}
 				}
 
@@ -363,59 +365,71 @@ class QRCode{
 		}
 
 		// setupTimingPattern
-		for($i = 8; $i < $this->moduleCount - 8; $i++){
-			if($this->modules[$i][6] !== null){
+		for($i = 8; $i < $this->pixelCount - 8; $i++){
+
+			if($this->matrix[$i][6] !== null){
 				continue;
 			}
 
-			$this->modules[$i][6] = $this->modules[6][$i] = (bool)$i % 2 === 0;
+			$this->matrix[$i][6] = $this->matrix[6][$i] = $i % 2 === 0;
 		}
 
+	}
 
-		$data = ($this->errorCorrectLevel << 3) | $pattern;
-		$bits = $this->util->getBCHTypeInfo($data);
+	/**
+	 * @param bool $test
+	 *
+	 * @return $this
+	 */
+	protected function setTypeNumber($test){
+		$bits = Util::getBCHTypeNumber($this->typeNumber);
 
-		for($i = 0; $i < 15; $i++){
-			$mod = (bool)!$test && (($bits >> $i) & 1) === 1;
+		for($i = 0; $i < 18; $i++){
+			$a = (int)floor($i / 3);
+			$b = $i % 3 + $this->pixelCount - 8 - 3;
 
-			switch(true){
-				case $i < 6: $this->modules[$i][8] = $mod; break;
-				case $i < 8: $this->modules[$i + 1][8] = $mod; break;
-				default:
-					$this->modules[$this->moduleCount - 15 + $i][8] = $mod;
-			}
+			$this->matrix[$a][$b] = $this->matrix[$b][$a] = !$test && (($bits >> $i) & 1) === 1;
+		}
 
-			switch(true){
-				case $i < 8: $this->modules[8][$this->moduleCount - $i - 1] = $mod; break;
-				case $i < 9: $this->modules[8][15 - $i - 1 + 1] = $mod; break;
-				default:
-					$this->modules[8][15 - $i - 1] = $mod;
-			}
+	}
 
+	/**
+	 * @param bool $test
+	 * @param int  $pattern
+	 *
+	 * @throws \chillerlan\QRCode\QRCodeException
+	 */
+	protected function getMatrix($test, $pattern){
+		if($this->typeNumber < 1 || $this->typeNumber > 10){
+			throw new QRCodeException('Invalid type number '.$this->typeNumber);
 		}
 
-		$this->modules[$this->moduleCount - 8][8] = !$test;
+		$this->pixelCount = $this->typeNumber * 4 + 17;
+		$this->matrix = array_fill(0, $this->pixelCount, array_fill(0, $this->pixelCount, null));
+		$this->setTypeInfo($test, $pattern);
 
 		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;
-
-				$this->modules[$a][$b] = $this->modules[$b][$a] = (bool)!$test && (($bits >> $i) & 1) === 1;
-			}
+			$this->setTypeNumber($test);
 		}
 
-		$this->data = $this->createData($this->typeNumber, $this->errorCorrectLevel);
+		$this->mapData($pattern);
+	}
 
+	/**
+	 * @param int $pattern
+	 *
+	 * @throws \chillerlan\QRCode\QRCodeException
+	 */
+	protected function mapData($pattern){
+		$this->createData();
+		$data = $this->createBytes();
 		$inc = -1;
-		$row = $this->moduleCount - 1;
+		$row = $this->pixelCount - 1;
 		$bitIndex = 7;
 		$byteIndex = 0;
-		$dataCount = count($this->data);
+		$dataCount = count($data);
 
-		for($col = $this->moduleCount - 1; $col > 0; $col -= 2){
+		for($col = $this->pixelCount - 1; $col > 0; $col -= 2){
 
 			if($col === 6){
 				$col--;
@@ -423,38 +437,36 @@ class QRCode{
 
 			while(true){
 				for($c = 0; $c < 2; $c++){
+					$_col = $col - $c;
 
-					if($this->modules[$row][$col - $c] === null){
+					if($this->matrix[$row][$_col] === null){
 						$dark = false;
 
 						if($byteIndex < $dataCount){
-							$dark = (($this->data[$byteIndex] >> $bitIndex) & 1) === 1;
+							$dark = (($data[$byteIndex] >> $bitIndex) & 1) === 1;
 						}
 
-						$_col = $col - $c;
+						$a = $row + $_col;
+						$m = $row * $_col;
 
 						$MASK_PATTERN = [
-							QRConst::MASK_PATTERN000 => ($row + $_col) % 2 === 0,
-							QRConst::MASK_PATTERN001 => $row % 2 === 0,
-							QRConst::MASK_PATTERN010 => $_col % 3 === 0,
-							QRConst::MASK_PATTERN011 => ($row + $_col) % 3 === 0,
-							QRConst::MASK_PATTERN100 => (floor($row / 2) + floor($_col / 3)) % 2 === 0,
-							QRConst::MASK_PATTERN101 => ($row * $_col) % 2 + ($row * $_col) % 3 === 0,
-							QRConst::MASK_PATTERN110 => (($row * $_col) % 2 + ($row * $_col) % 3) % 2 === 0,
-							QRConst::MASK_PATTERN111 => (($row * $_col) % 3 + ($row + $_col) % 2) % 2 === 0,
-						];
-
-						if(!isset($MASK_PATTERN[$pattern])){
-							throw new QRCodeException('mask: '.$pattern);
-						}
-
-						if($MASK_PATTERN[$pattern]){
+							QRConst::MASK_PATTERN000 => $a % 2,
+							QRConst::MASK_PATTERN001 => $row % 2,
+							QRConst::MASK_PATTERN010 => $_col % 3,
+							QRConst::MASK_PATTERN011 => $a % 3,
+							QRConst::MASK_PATTERN100 => (floor($row / 2) + floor($_col / 3)) % 2,
+							QRConst::MASK_PATTERN101 => $m % 2 + $m % 3,
+							QRConst::MASK_PATTERN110 => ($m % 2 + $m % 3) % 2,
+							QRConst::MASK_PATTERN111 => ($m % 3 + $a % 2) % 2,
+						][$pattern];
+
+						if($MASK_PATTERN === 0){
 							$dark = !$dark;
 						}
 
-						$this->modules[$row][$col - $c] = (bool)$dark;
-						$bitIndex--;
+						$this->matrix[$row][$_col] = $dark;
 
+						$bitIndex--;
 						if($bitIndex === -1){
 							$byteIndex++;
 							$bitIndex = 7;
@@ -465,82 +477,47 @@ class QRCode{
 
 				$row += $inc;
 
-				if($row < 0 || $this->moduleCount <= $row){
+				if($row < 0 || $this->pixelCount <= $row){
 					$row -= $inc;
 					$inc = -$inc;
 					break;
 				}
+
 			}
+
 		}
 
-		return $this;
 	}
 
 	/**
-	 * @param $row
-	 * @param $col
-	 *
 	 * @return $this
+	 * @throws \chillerlan\QRCode\QRCodeException
 	 */
-	protected function setupPositionProbePattern($row, $col){
-		$range = range(-1, 7);
-
-		foreach($range as $r){
-			foreach($range as $c){
-
-				if($row + $r <= -1 || $this->moduleCount <= $row + $r || $col + $c <= -1 || $this->moduleCount <= $col + $c){
-					continue;
-				}
+	protected function createData(){
 
-				$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);
-			}
+		if(!isset($this->errorCorrectLevel)){
+			throw new QRCodeException('Invalid error correct level '.$this->errorCorrectLevel);
 		}
 
-		return $this;
-	}
-
-	/**
-	 * @param $typeNumber
-	 * @param $errorCorrectLevel
-	 *
-	 * @return array
-	 * @throws \codemasher\QRCode\QRCodeException
-	 */
-	protected function createData($typeNumber, $errorCorrectLevel){
-		$this->bitBuffer->buffer = [];
-		$this->bitBuffer->length = 0;
-		$this->rsBlockList = $this->rsBlock->getRSBlocks($typeNumber, $errorCorrectLevel);
-		$rsBlockCount = count($this->rsBlockList);
-
-		$totalDataCount = $totalCodeCount = $offset = $maxDcCount = $maxEcCount = $index = 0;
-		$dcdata = $ecdata = array_fill(0, $rsBlockCount, null);
+		$this->bitBuffer->clear();
 
+		$MAX_BITS = QRConst::MAX_BITS; // php5 compat
+		$MAX_BITS = $MAX_BITS[$this->typeNumber][$this->errorCorrectLevel];
 
-		/** @var \codemasher\QRCode\Data\QRDataBase $data */
-		foreach($this->qrDataList as &$data){
-			$this->bitBuffer
-				->put($data->mode, 4)
-				->put($data->mode === QRConst::MODE_KANJI ? floor($data->dataLength / 2) : $data->dataLength, $data->getLengthInBits($typeNumber));
-
-			$data->write($this->bitBuffer);
-		}
-
-		foreach($this->rsBlockList as &$data){
-			$this->rsBlock->totalCount = $data[0];
-			$this->rsBlock->dataCount = $data[1];
+		$this->bitBuffer->put($this->qrDataInterface->mode, 4);
+		$this->bitBuffer->put(
+			$this->qrDataInterface->mode === QRConst::MODE_KANJI ? floor($this->qrDataInterface->dataLength / 2) : $this->qrDataInterface->dataLength,
+			$this->qrDataInterface->getLengthInBits($this->typeNumber)
+		);
 
-			$totalDataCount += $this->rsBlock->dataCount;
-		}
+		$this->qrDataInterface->write($this->bitBuffer);
 
-		if($this->bitBuffer->length > $totalDataCount * 8){
-			throw new QRCodeException('code length overflow. ('.$this->bitBuffer->length.'>'.($totalDataCount * 8).')');
+		if($this->bitBuffer->length > $MAX_BITS){
+			throw new QRCodeException('code length overflow. ('.$this->bitBuffer->length.' > '.$MAX_BITS.'bit)');
 		}
 
 		// end code.
-		if($this->bitBuffer->length + 4 <= $totalDataCount * 8){
+		if($this->bitBuffer->length + 4 <= $MAX_BITS){
 			$this->bitBuffer->put(0, 4);
 		}
 
@@ -552,70 +529,82 @@ class QRCode{
 		// padding
 		while(true){
 
-			if($this->bitBuffer->length >= $totalDataCount * 8){
+			if($this->bitBuffer->length >= $MAX_BITS){
 				break;
 			}
 
-			$this->bitBuffer->put(self::QR_PAD0, 8);
+			$this->bitBuffer->put(QRConst::PAD0, 8);
 
-			if($this->bitBuffer->length >= $totalDataCount * 8){
+			if($this->bitBuffer->length >= $MAX_BITS){
 				break;
 			}
 
-			$this->bitBuffer->put(self::QR_PAD1, 8);
+			$this->bitBuffer->put(QRConst::PAD1, 8);
 		}
 
-		foreach($this->rsBlockList as $r => &$_rsData){
-			$this->rsBlock->totalCount = $_rsData[0];
-			$this->rsBlock->dataCount = $_rsData[1];
+	}
 
-			$maxDcCount = max($maxDcCount, $this->rsBlock->dataCount);
-			$maxEcCount = max($maxEcCount, $this->rsBlock->totalCount - $this->rsBlock->dataCount);
+	/**
+	 * @return array
+	 * @throws \chillerlan\QRCode\QRCodeException
+	 */
+	protected function createBytes(){
+		$totalCodeCount = $maxDcCount = $maxEcCount = $offset = $index = 0;
+		$rsBlocks = Util::getRSBlocks($this->typeNumber, $this->errorCorrectLevel);
+		$rsBlockCount = count($rsBlocks);
+		$dcdata = $ecdata = array_fill(0, $rsBlockCount, null);
 
-			$dcdata[$r] = array_fill(0, $this->rsBlock->dataCount, null);
+		foreach($rsBlocks as $key => $value){
+			$rsBlockTotal = $value[0];
+			$rsBlockDataCount = $value[1];
 
-			$rsPoly = new Polynomial;
-			$modPoly = new Polynomial;
+			$maxDcCount = max($maxDcCount, $rsBlockDataCount);
+			$maxEcCount = max($maxEcCount, $rsBlockTotal - $rsBlockDataCount);
+
+			$dcdata[$key] = array_fill(0, $rsBlockDataCount, null);
 
-			foreach($dcdata[$r] as $i => &$_dcdata){
+			foreach($dcdata[$key] as $i => &$_dcdata){
 				$bdata = $this->bitBuffer->buffer;
 				$_dcdata = 0xff & $bdata[$i + $offset];
 			}
 
-			$offset += $this->rsBlock->dataCount;
+			$offset += $rsBlockDataCount;
+
+			$rsPoly = new Polynomial;
+			$modPoly = new Polynomial;
 
-			for($i = 0; $i < $this->rsBlock->totalCount - $this->rsBlock->dataCount; $i++){
+			for($i = 0; $i < $rsBlockTotal - $rsBlockDataCount; $i++){
 				$modPoly->setNum([1, $modPoly->gexp($i)]);
 				$rsPoly->multiply($modPoly->num);
 			}
 
 			$rsPolyCount = count($rsPoly->num);
-			$modPoly->setNum($dcdata[$r], $rsPolyCount - 1)->mod($rsPoly->num);
-			$ecdata[$r] = array_fill(0, $rsPolyCount - 1, null);
-			$add = count($modPoly->num) - count($ecdata[$r]);
+			$modPoly->setNum($dcdata[$key], $rsPolyCount - 1)->mod($rsPoly->num);
+			$ecdata[$key] = array_fill(0, $rsPolyCount - 1, null);
+			$add = count($modPoly->num) - count($ecdata[$key]);
 
-			foreach($ecdata[$r] as $i => &$_ecdata){
+			foreach($ecdata[$key] as $i => &$_ecdata){
 				$modIndex = $i + $add;
 				$_ecdata = $modIndex >= 0 ? $modPoly->num[$modIndex] : 0;
 			}
 
-			$totalCodeCount += $this->rsBlock->totalCount;
+			$totalCodeCount += $rsBlockTotal;
 		}
 
 		$data = array_fill(0, $totalCodeCount, null);
 
 		for($i = 0; $i < $maxDcCount; $i++){
-			for($r = 0; $r < $rsBlockCount; $r++){
-				if($i < count($dcdata[$r])){
-					$data[$index++] = $dcdata[$r][$i];
+			for($key = 0; $key < $rsBlockCount; $key++){
+				if($i < count($dcdata[$key])){
+					$data[$index++] = $dcdata[$key][$i];
 				}
 			}
 		}
 
 		for($i = 0; $i < $maxEcCount; $i++){
-			for($r = 0; $r < $rsBlockCount; $r++){
-				if($i < count($ecdata[$r])){
-					$data[$index++] = $ecdata[$r][$i];
+			for($key = 0; $key < $rsBlockCount; $key++){
+				if($i < count($ecdata[$key])){
+					$data[$index++] = $ecdata[$key][$i];
 				}
 			}
 		}
@@ -623,98 +612,4 @@ class QRCode{
 		return $data;
 	}
 
-	/**
-	 * added $fg (foreground), $bg (background), and $bgtrans (use transparent bg) parameters
-	 * also added some simple error checking on parameters
-	 * updated 2015.07.27 ~ DoktorJ
-	 *
-	 * @param int        $size
-	 * @param int        $margin
-	 * @param int        $fg
-	 * @param int        $bg
-	 * @param bool|false $bgtrans
-	 *
-	 * @return resource
-	 */
-	public function createImage($size = 2, $margin = 2, $fg = 0x000000, $bg = 0xFFFFFF, $bgtrans = false){
-
-		// size/margin EC
-		if(!is_numeric($size)){
-			$size = 2;
-		}
-		if(!is_numeric($margin)){
-			$margin = 2;
-		}
-		if($size < 1){
-			$size = 1;
-		}
-		if($margin < 0){
-			$margin = 0;
-		}
-
-		$image_size = $this->moduleCount * $size + $margin * 2;
-
-		$image = imagecreatetruecolor($image_size, $image_size);
-
-		// fg/bg EC
-		if($fg < 0 || $fg > 0xFFFFFF){
-			$fg = 0x0;
-		}
-		if($bg < 0 || $bg > 0xFFFFFF){
-			$bg = 0xFFFFFF;
-		}
-
-		// convert hexadecimal RGB to arrays for imagecolorallocate
-		$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']);
-		$bgc = imagecolorallocate($image, $bgrgb['r'], $bgrgb['g'], $bgrgb['b']);
-		if($bgtrans){
-			imagecolortransparent($image, $bgc);
-		}
-
-		// update $white to $bgc
-		imagefilledrectangle($image, 0, 0, $image_size, $image_size, $bgc);
-
-		for($r = 0; $r < $this->moduleCount; $r++){
-			for($c = 0; $c < $this->moduleCount; $c++){
-				if($this->modules[$r][$c]){
-
-					// update $black to $fgc
-					imagefilledrectangle($image,
-						$margin + $c * $size,
-						$margin + $r * $size,
-						$margin + ($c + 1) * $size - 1,
-						$margin + ($r + 1) * $size - 1,
-						$fgc);
-				}
-			}
-		}
-
-		return $image;
-	}
-
-	/**
-	 * @return string
-	 */
-	public function printHTML(){
-		$html = '<table class="qrcode">';
-
-		for($row = 0; $row < $this->moduleCount; $row++){
-			$html .= '<tr>';
-
-			for($col = 0; $col < $this->moduleCount; $col++){
-				$html .= '<td class="'.($this->modules[$row][$col] ? 'dark' : 'light').'"></td>';
-			}
-
-			$html .= '</tr>';
-		}
-
-		$html .= '</table>';
-
-		return $html;
-	}
-
 }

+ 2 - 2
src/QRCodeException.php

@@ -4,13 +4,13 @@
  *
  * @filesource   QRCodeException.php
  * @created      27.11.2015
- * @package      codemasher\QRCode
+ * @package      chillerlan\QRCode
  * @author       Smiley <smiley@chillerlan.net>
  * @copyright    2015 Smiley
  * @license      MIT
  */
 
-namespace codemasher\QRCode;
+namespace chillerlan\QRCode;
 
 use Exception;
 

+ 178 - 10
src/QRConst.php

@@ -1,25 +1,70 @@
 <?php
 /**
+ * Class QRConst
  *
  * @filesource   QRConst.php
  * @created      26.11.2015
- * @package      codemasher\QRCode
+ * @package      chillerlan\QRCode
  * @author       Smiley <smiley@chillerlan.net>
  * @copyright    2015 Smiley
  * @license      MIT
  */
 
-namespace codemasher\QRCode;
+namespace chillerlan\QRCode;
 
 /**
- * Class QRConst
+ * const ALL THE THINGS! ~John Carmack
  */
 class QRConst{
 
-	const MODE_NUMBER = 1 << 0;
+	const ERROR_CORRECT_LEVEL_L = 1; // 7%.
+	const ERROR_CORRECT_LEVEL_M = 0; // 15%.
+	const ERROR_CORRECT_LEVEL_Q = 3; // 25%.
+	const ERROR_CORRECT_LEVEL_H = 2; // 30%.
+
+	const RSBLOCK = [
+		self::ERROR_CORRECT_LEVEL_L => 0,
+		self::ERROR_CORRECT_LEVEL_M => 1,
+		self::ERROR_CORRECT_LEVEL_Q => 2,
+		self::ERROR_CORRECT_LEVEL_H => 3,
+	];
+
+	// max bits @ ec level L:07 M:15 Q:25 H:30 %
+	const TYPE_01 =  1; //  152  128  104   72
+	const TYPE_02 =  2; //  272  224  176  128
+	const TYPE_03 =  3; //  440  352  272  208
+	const TYPE_04 =  4; //  640  512  384  288
+	const TYPE_05 =  5; //  864  688  496  368
+	const TYPE_06 =  6; // 1088  864  608  480
+	const TYPE_07 =  7; // 1248  992  704  528
+	const TYPE_08 =  8; // 1552 1232  880  688
+	const TYPE_09 =  9; // 1856 1456 1056  800
+	const TYPE_10 = 10; // 2192 1728 1232  976
+
+	const MAX_BITS = [
+		self::TYPE_01 => [ 128,  152,   72,  104],
+		self::TYPE_02 => [ 224,  272,  128,  176],
+		self::TYPE_03 => [ 352,  440,  208,  272],
+		self::TYPE_04 => [ 512,  640,  288,  384],
+		self::TYPE_05 => [ 688,  864,  368,  496],
+		self::TYPE_06 => [ 864, 1088,  480,  608],
+		self::TYPE_07 => [ 992, 1248,  528,  704],
+		self::TYPE_08 => [1232, 1552,  688,  880],
+		self::TYPE_09 => [1456, 1856,  800, 1056],
+		self::TYPE_10 => [1728, 2192,  976, 1232],
+	];
+
+	const MODE_NUMBER   = 1 << 0;
 	const MODE_ALPHANUM = 1 << 1;
-	const MODE_BYTE = 1 << 2;
-	const MODE_KANJI = 1 << 3;
+	const MODE_BYTE     = 1 << 2;
+	const MODE_KANJI    = 1 << 3;
+
+	const MODE = [
+		self::MODE_NUMBER   => 0,
+		self::MODE_ALPHANUM => 1,
+		self::MODE_BYTE     => 2,
+		self::MODE_KANJI    => 3,
+	];
 
 	const MASK_PATTERN000 = 0;
 	const MASK_PATTERN001 = 1;
@@ -30,9 +75,132 @@ class QRConst{
 	const MASK_PATTERN110 = 6;
 	const MASK_PATTERN111 = 7;
 
-	const ERROR_CORRECT_LEVEL_L = 1; // 7%.
-	const ERROR_CORRECT_LEVEL_M = 0; // 15%.
-	const ERROR_CORRECT_LEVEL_Q = 3; // 25%.
-	const ERROR_CORRECT_LEVEL_H = 2; // 30%.
+	const G15_MASK = (1 << 14)|(1 << 12)|(1 << 10)|(1 << 4)|(1 << 1);
+	const G15 = (1 << 10)|(1 << 8)|(1 << 5)|(1 << 4)|(1 << 2)|(1 << 1)|(1 << 0);
+	const G18 = (1 << 12)|(1 << 11)|(1 << 10)|(1 << 9)|(1 << 8)|(1 << 5)|(1 << 2)|(1 << 0);
+
+	const PAD0 = 0xEC;
+	const PAD1 = 0x11;
+
+	const CHAR_MAP = [
+		36 => ' ',
+		37 => '$',
+		38 => '%',
+		39 => '*',
+		40 => '+',
+		41 => '-',
+		42 => '.',
+		43 => '/',
+		44 => ':',
+	];
+
+	const 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]],
+		[[187, 114,  78,  48], [149,  90,  62,  38], [111,  67,  46,  28], [ 82,  50,  34,  21]],
+		[[255, 154, 106,  65], [202, 122,  84,  52], [144,  87,  60,  37], [106,  64,  44,  27]],
+		[[322, 195, 134,  82], [255, 154, 106,  65], [178, 108,  74,  45], [139,  84,  58,  36]],
+		[[370, 224, 154,  95], [293, 178, 122,  75], [207, 125,  86,  53], [154,  93,  64,  39]],
+		[[461, 279, 192, 118], [365, 221, 152,  93], [259, 157, 108,  66], [202, 122,  84,  52]],
+		[[552, 335, 230, 141], [432, 262, 180, 111], [312, 189, 130,  80], [235, 143,  98,  60]],
+		[[652, 395, 271, 167], [513, 311, 213, 131], [364, 221, 151,  93], [288, 174, 119,  74]],
+	];
+
+	const BLOCK_TABLE = [
+		// 1
+		[1, 26, 19], // L
+		[1, 26, 16], // M
+		[1, 26, 13], // Q
+		[1, 26,  9], // H
+		// 2
+		[1, 44, 34],
+		[1, 44, 28],
+		[1, 44, 22],
+		[1, 44, 16],
+		// 3
+		[1, 70, 55],
+		[1, 70, 44],
+		[2, 35, 17],
+		[2, 35, 13],
+		// 4
+		[1, 100, 80],
+		[2,  50, 32],
+		[2,  50, 24],
+		[4,  25,  9],
+		// 5
+		[1, 134, 108],
+		[2,  67,  43],
+		[2,  33,  15, 2, 34, 16],
+		[2,  33,  11, 2, 34, 12],
+		// 6
+		[2, 86, 68],
+		[4, 43, 27],
+		[4, 43, 19],
+		[4, 43, 15],
+		// 7
+		[2, 98, 78],
+		[4, 49, 31],
+		[2, 32, 14, 4, 33, 15],
+		[4, 39, 13, 1, 40, 14],
+		// 8
+		[2, 121, 97],
+		[2,  60, 38, 2, 61, 39],
+		[4,  40, 18, 2, 41, 19],
+		[4,  40, 14, 2, 41, 15],
+		// 9
+		[2, 146, 116],
+		[3,  58,  36, 2, 59, 37],
+		[4,  36,  16, 4, 37, 17],
+		[4,  36,  12, 4, 37, 13],
+		// 10
+		[2, 86, 68, 2, 87, 69],
+		[4, 69, 43, 1, 70, 44],
+		[6, 43, 19, 2, 44, 20],
+		[6, 43, 15, 2, 44, 16],
+	];
+
+	const PATTERN_POSITION = [
+		[],
+		[6, 18],
+		[6, 22],
+		[6, 26],
+		[6, 30],
+		[6, 34],
+		[6, 22, 38],
+		[6, 24, 42],
+		[6, 26, 46],
+		[6, 28, 50],
+		[6, 30, 54],
+		[6, 32, 58],
+		[6, 34, 62],
+		[6, 26, 46, 66],
+		[6, 26, 48, 70],
+		[6, 26, 50, 74],
+		[6, 30, 54, 78],
+		[6, 30, 56, 82],
+		[6, 30, 58, 86],
+		[6, 34, 62, 90],
+		[6, 28, 50, 72, 94],
+		[6, 26, 50, 74, 98],
+		[6, 30, 54, 78, 102],
+		[6, 28, 54, 80, 106],
+		[6, 32, 58, 84, 110],
+		[6, 30, 58, 86, 114],
+		[6, 34, 62, 90, 118],
+		[6, 26, 50, 74, 98, 122],
+		[6, 30, 54, 78, 102, 126],
+		[6, 26, 52, 78, 104, 130],
+		[6, 30, 56, 82, 108, 134],
+		[6, 34, 60, 86, 112, 138],
+		[6, 30, 58, 86, 114, 142],
+		[6, 34, 62, 90, 118, 146],
+		[6, 30, 54, 78, 102, 126, 150],
+		[6, 24, 50, 76, 102, 128, 154],
+		[6, 28, 54, 80, 106, 132, 158],
+		[6, 32, 58, 84, 110, 136, 162],
+		[6, 26, 54, 82, 110, 138, 166],
+		[6, 30, 58, 86, 114, 142, 170],
+	];
 
 }

+ 0 - 144
src/RSBlock.php

@@ -1,144 +0,0 @@
-<?php
-/**
- *
- * @filesource   RSBlock.php
- * @created      26.11.2015
- * @package      codemasher\QRCode
- * @author       Smiley <smiley@chillerlan.net>
- * @copyright    2015 Smiley
- * @license      MIT
- */
-
-namespace codemasher\QRCode;
-
-use codemasher\QRCode\QRConst;
-use codemasher\QRCode\QRCodeException;
-
-/**
- * Class RSBlock
- */
-class RSBlock{
-
-	/**
-	 * @var int
-	 */
-	public $totalCount;
-
-	/**
-	 * @var int
-	 */
-	public $dataCount;
-
-	/**
-	 * @var array
-	 */
-	protected $BLOCK_TABLE = [
-
-		// L
-		// M
-		// Q
-		// H
-
-		// 1
-		[1, 26, 19],
-		[1, 26, 16],
-		[1, 26, 13],
-		[1, 26, 9],
-
-		// 2
-		[1, 44, 34],
-		[1, 44, 28],
-		[1, 44, 22],
-		[1, 44, 16],
-
-		// 3
-		[1, 70, 55],
-		[1, 70, 44],
-		[2, 35, 17],
-		[2, 35, 13],
-
-		// 4
-		[1, 100, 80],
-		[2, 50, 32],
-		[2, 50, 24],
-		[4, 25, 9],
-
-		// 5
-		[1, 134, 108],
-		[2, 67, 43],
-		[2, 33, 15, 2, 34, 16],
-		[2, 33, 11, 2, 34, 12],
-
-		// 6
-		[2, 86, 68],
-		[4, 43, 27],
-		[4, 43, 19],
-		[4, 43, 15],
-
-		// 7
-		[2, 98, 78],
-		[4, 49, 31],
-		[2, 32, 14, 4, 33, 15],
-		[4, 39, 13, 1, 40, 14],
-
-		// 8
-		[2, 121, 97],
-		[2, 60, 38, 2, 61, 39],
-		[4, 40, 18, 2, 41, 19],
-		[4, 40, 14, 2, 41, 15],
-
-		// 9
-		[2, 146, 116],
-		[3, 58, 36, 2, 59, 37],
-		[4, 36, 16, 4, 37, 17],
-		[4, 36, 12, 4, 37, 13],
-
-		// 10
-		[2, 86, 68, 2, 87, 69],
-		[4, 69, 43, 1, 70, 44],
-		[6, 43, 19, 2, 44, 20],
-		[6, 43, 15, 2, 44, 16],
-
-	];
-
-	/**
-	 * @var array
-	 */
-	protected $RSBLOCK = [
-		QRConst::ERROR_CORRECT_LEVEL_L => 0,
-		QRConst::ERROR_CORRECT_LEVEL_M => 1,
-		QRConst::ERROR_CORRECT_LEVEL_Q => 2,
-		QRConst::ERROR_CORRECT_LEVEL_H => 3,
-	];
-
-	/**
-	 * @param $typeNumber
-	 * @param $errorCorrectLevel
-	 *
-	 * @return array
-	 * @throws \codemasher\QRCode\QRCodeException
-	 */
-	public function getRSBlocks($typeNumber, $errorCorrectLevel){
-
-		if(!isset($this->RSBLOCK[$errorCorrectLevel])){
-			throw new QRCodeException('$typeNumber: '.$typeNumber.' / $errorCorrectLevel: '.$errorCorrectLevel.PHP_EOL.print_r($this->RSBLOCK, true));
-		}
-
-		$rsBlock = $this->BLOCK_TABLE[($typeNumber - 1) * 4 + $this->RSBLOCK[$errorCorrectLevel]];
-
-		$list = [];
-		$length = count($rsBlock) / 3;
-		for($i = 0; $i < $length; $i++){
-			$count = $rsBlock[$i * 3 + 0];
-			$totalCount = $rsBlock[$i * 3 + 1];
-			$dataCount = $rsBlock[$i * 3 + 2];
-
-			for($j = 0; $j < $count; $j++){
-				$list[] = [$totalCount, $dataCount];
-			}
-		}
-
-		return $list;
-	}
-
-}

+ 111 - 115
src/Util.php

@@ -1,138 +1,85 @@
 <?php
 /**
+ * Class Util
  *
  * @filesource   Util.php
  * @created      25.11.2015
- * @package      codemasher\QRCode
+ * @package      chillerlan\QRCode
  * @author       Smiley <smiley@chillerlan.net>
  * @copyright    2015 Smiley
  * @license      MIT
  */
 
-namespace codemasher\QRCode;
+namespace chillerlan\QRCode;
 
 /**
- * Class Util
+ *
  */
 class Util{
 
-	const QR_G15 = (1 << 10)|(1 << 8)|(1 << 5)|(1 << 4)|(1 << 2)|(1 << 1)|(1 << 0);
-	const QR_G18 = (1 << 12)|(1 << 11)|(1 << 10)|(1 << 9)|(1 << 8)|(1 << 5)|(1 << 2)|(1 << 0);
-	const QR_G15_MASK = (1 << 14)|(1 << 12)|(1 << 10)|(1 << 4)|(1 << 1);
-
 	/**
-	 * @var array
+	 * @param int $typeNumber
+	 * @param int $errorCorrectLevel
+	 *
+	 * @return array
+	 * @throws \chillerlan\QRCode\QRCodeException
 	 */
-	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]],
-		[[187, 114, 78, 48], [149, 90, 62, 38], [111, 67, 46, 28], [82, 50, 34, 21]],
-		[[255, 154, 106, 65], [202, 122, 84, 52], [144, 87, 60, 37], [106, 64, 44, 27]],
-		[[322, 195, 134, 82], [255, 154, 106, 65], [178, 108, 74, 45], [139, 84, 58, 36]],
-		[[370, 224, 154, 95], [293, 178, 122, 75], [207, 125, 86, 53], [154, 93, 64, 39]],
-		[[461, 279, 192, 118], [365, 221, 152, 93], [259, 157, 108, 66], [202, 122, 84, 52]],
-		[[552, 335, 230, 141], [432, 262, 180, 111], [312, 189, 130, 80], [235, 143, 98, 60]],
-		[[652, 395, 271, 167], [513, 311, 213, 131], [364, 221, 151, 93], [288, 174, 119, 74]],
-	];
+	public static function getRSBlocks($typeNumber, $errorCorrectLevel){
+		// PHP5 compat
+		$RSBLOCK = QRConst::RSBLOCK;
+		$BLOCK_TABLE = QRConst::BLOCK_TABLE;
 
-	/**
-	 * @var array
-	 */
-	public $PATTERN_POSITION = [
-		[],
-		[6, 18],
-		[6, 22],
-		[6, 26],
-		[6, 30],
-		[6, 34],
-		[6, 22, 38],
-		[6, 24, 42],
-		[6, 26, 46],
-		[6, 28, 50],
-		[6, 30, 54],
-		[6, 32, 58],
-		[6, 34, 62],
-		[6, 26, 46, 66],
-		[6, 26, 48, 70],
-		[6, 26, 50, 74],
-		[6, 30, 54, 78],
-		[6, 30, 56, 82],
-		[6, 30, 58, 86],
-		[6, 34, 62, 90],
-		[6, 28, 50, 72, 94],
-		[6, 26, 50, 74, 98],
-		[6, 30, 54, 78, 102],
-		[6, 28, 54, 80, 106],
-		[6, 32, 58, 84, 110],
-		[6, 30, 58, 86, 114],
-		[6, 34, 62, 90, 118],
-		[6, 26, 50, 74, 98, 122],
-		[6, 30, 54, 78, 102, 126],
-		[6, 26, 52, 78, 104, 130],
-		[6, 30, 56, 82, 108, 134],
-		[6, 34, 60, 86, 112, 138],
-		[6, 30, 58, 86, 114, 142],
-		[6, 34, 62, 90, 118, 146],
-		[6, 30, 54, 78, 102, 126, 150],
-		[6, 24, 50, 76, 102, 128, 154],
-		[6, 28, 54, 80, 106, 132, 158],
-		[6, 32, 58, 84, 110, 136, 162],
-		[6, 26, 54, 82, 110, 138, 166],
-		[6, 30, 58, 86, 114, 142, 170],
-	];
+		if(!isset($RSBLOCK[$errorCorrectLevel])){
+			throw new QRCodeException('$typeNumber: '.$typeNumber.' / $errorCorrectLevel: '.$errorCorrectLevel.PHP_EOL.print_r($RSBLOCK, true));
+		}
 
-	/**
-	 * @var array
-	 */
-	protected $ERROR_CORRECT_LEVEL = [
-		QRConst::ERROR_CORRECT_LEVEL_L => 0,
-		QRConst::ERROR_CORRECT_LEVEL_M => 1,
-		QRConst::ERROR_CORRECT_LEVEL_Q => 2,
-		QRConst::ERROR_CORRECT_LEVEL_H => 3,
-	];
+		$rsBlock = $BLOCK_TABLE[($typeNumber - 1) * 4 + $RSBLOCK[$errorCorrectLevel]];
 
-	/**
-	 * @var array
-	 */
-	protected $MODE = [
-		QRConst::MODE_NUMBER => 0,
-		QRConst::MODE_ALPHANUM => 1,
-		QRConst::MODE_BYTE => 2,
-		QRConst::MODE_KANJI => 3,
-	];
+		$list = [];
+		$length = count($rsBlock) / 3;
+		for($i = 0; $i < $length; $i++){
+			for($j = 0; $j < $rsBlock[$i * 3 + 0]; $j++){
+				$list[] = [$rsBlock[$i * 3 + 1], $rsBlock[$i * 3 + 2]];
+			}
+		}
+
+		return $list;
+	}
 
 	/**
 	 * @param int $typeNumber
 	 * @param int $mode
 	 * @param int $ecLevel
 	 *
-	 * @return mixed
-	 * @throws \codemasher\QRCode\QRCodeException
+	 * @return int
+	 * @throws \chillerlan\QRCode\QRCodeException
 	 */
-	public function getMaxLength($typeNumber, $mode, $ecLevel){
+	public static function getMaxLength($typeNumber, $mode, $ecLevel){
+		$RSBLOCK = QRConst::RSBLOCK;
+		$MAX_LENGTH = QRConst::MAX_LENGTH;
+		$MODE = QRConst::MODE;
 
-		if(!isset($this->ERROR_CORRECT_LEVEL[$ecLevel])){
+		if(!isset($RSBLOCK[$ecLevel])){
 			throw new QRCodeException('$_err: '.$ecLevel);
 		}
 
-		if(!isset($this->MODE[$mode])){
+		if(!isset($MODE[$mode])){
 			throw new QRCodeException('$_mode: '.$mode);
 		}
 
-		return $this->MAX_LENGTH[$typeNumber - 1][$this->ERROR_CORRECT_LEVEL[$ecLevel]][$this->MODE[$mode]];
+		return $MAX_LENGTH[$typeNumber - 1][$RSBLOCK[$ecLevel]][$MODE[$mode]];
 	}
 
 	/**
-	 * @param $s
+	 * @param string $s
 	 *
 	 * @return int
 	 */
-	public function getMode($s){
+	public static function getMode($s){
 
 		switch(true){
-			case $this->isAlphaNum($s): return $this->isNumber($s) ? QRConst::MODE_NUMBER : QRConst::MODE_ALPHANUM;
-			case $this->isKanji($s)   : return QRConst::MODE_KANJI;
+			case self::isAlphaNum($s): return self::isNumber($s) ? QRConst::MODE_NUMBER : QRConst::MODE_ALPHANUM;
+			case self::isKanji($s)   : return QRConst::MODE_KANJI;
 			default:
 				return QRConst::MODE_BYTE;
 		}
@@ -140,11 +87,11 @@ class Util{
 	}
 
 	/**
-	 * @param $s
+	 * @param string $s
 	 *
 	 * @return bool
 	 */
-	protected function isNumber($s){
+	protected static function isNumber($s){
 
 		$len = strlen($s);
 		for($i = 0; $i < $len; $i++){
@@ -159,11 +106,11 @@ class Util{
 	}
 
 	/**
-	 * @param $s
+	 * @param string $s
 	 *
 	 * @return bool
 	 */
-	protected function isAlphaNum($s){
+	protected static function isAlphaNum($s){
 
 		$len = strlen($s);
 		for($i = 0; $i < $len; $i++){
@@ -178,11 +125,11 @@ class Util{
 	}
 
 	/**
-	 * @param $s
+	 * @param string $s
 	 *
 	 * @return bool
 	 */
-	protected function isKanji($s){
+	protected static function isKanji($s){
 
 		$i = 0;
 		$len = strlen($s);
@@ -204,41 +151,41 @@ class Util{
 	}
 
 	/**
-	 * @param $data
+	 * @param int $data
 	 *
 	 * @return int
 	 */
-	public function getBCHTypeInfo($data){
+	public static function getBCHTypeInfo($data){
 		$d = $data << 10;
 
-		while($this->getBCHDigit($d) - $this->getBCHDigit(self::QR_G15) >= 0){
-			$d ^= (self::QR_G15 << ($this->getBCHDigit($d) - $this->getBCHDigit(self::QR_G15)));
+		while(self::getBCHDigit($d) - self::getBCHDigit(QRConst::G15) >= 0){
+			$d ^= (QRConst::G15 << (self::getBCHDigit($d) - self::getBCHDigit(QRConst::G15)));
 		}
 
-		return (($data << 10)|$d)^self::QR_G15_MASK;
+		return (($data << 10)|$d)^QRConst::G15_MASK;
 	}
 
 	/**
-	 * @param $data
+	 * @param int $data
 	 *
 	 * @return int
 	 */
-	public function getBCHTypeNumber($data){
+	public static function getBCHTypeNumber($data){
 		$d = $data << 12;
 
-		while($this->getBCHDigit($d) - $this->getBCHDigit(self::QR_G18) >= 0){
-			$d ^= (self::QR_G18 << ($this->getBCHDigit($d) - $this->getBCHDigit(self::QR_G18)));
+		while(self::getBCHDigit($d) - self::getBCHDigit(QRConst::G18) >= 0){
+			$d ^= (QRConst::G18 << (self::getBCHDigit($d) - self::getBCHDigit(QRConst::G18)));
 		}
 
 		return ($data << 12)|$d;
 	}
 
 	/**
-	 * @param $data
+	 * @param int $data
 	 *
 	 * @return int
 	 */
-	public function getBCHDigit($data){
+	public static function getBCHDigit($data){
 		$digit = 0;
 
 		while($data !== 0){
@@ -249,7 +196,6 @@ class Util{
 		return $digit;
 	}
 
-
 	/**
 	 * used for converting fg/bg colors (e.g. #0000ff = 0x0000FF) - added 2015.07.27 ~ DoktorJ
 	 *
@@ -257,12 +203,62 @@ class Util{
 	 *
 	 * @return array
 	 */
-	public function hex2rgb($hex = 0x0){
+	public static function hex2rgb($hex = 0x0){
 		return [
-			'r' => floor($hex / 65536),
-			'g' => floor($hex / 256) % 256,
-			'b' => $hex % 256,
+			'r' => (int)floor($hex / 65536),
+			'g' => (int)floor($hex / 256) % 256,
+			'b' => (int)$hex % 256,
 		];
 	}
 
+	/**
+	 * @param string $c
+	 *
+	 * @return int
+	 * @throws \chillerlan\QRCode\QRCodeException
+	 */
+	public static function getCharCode($c){
+		$c = ord($c);
+
+		switch(true){
+			case ord('0') <= $c && $c <= ord('9'): return $c - ord('0');
+			case ord('A') <= $c && $c <= ord('Z'): return $c - ord('A') + 10;
+			default:
+				foreach(QRConst::CHAR_MAP as $i => $char){
+					if(ord($char) === $c){
+						return $i;
+					}
+				}
+		}
+
+		throw new QRCodeException('illegal char: '.$c);
+	}
+
+	/**
+	 * @param string $string
+	 *
+	 * @return int
+	 * @throws \chillerlan\QRCode\QRCodeException
+	 */
+	public static function parseInt($string){
+		$num = 0;
+
+		$len = strlen($string);
+		for($i = 0; $i < $len; $i++){
+			$c = ord($string[$i]);
+			$ord0 = ord('0');
+
+			if($ord0 <= $c && $c <= ord('9')){
+				$c = $c - $ord0;
+			}
+			else{
+				throw new QRCodeException('illegal char: '.$c);
+			}
+
+			$num = $num * 10 + $c;
+		}
+
+		return $num;
+	}
+
 }