mirror of
https://github.com/chillerlan/php-qrcode.git
synced 2026-08-31 12:38:22 +00:00
:octocat:
This commit is contained in:
+22
@@ -0,0 +1,22 @@
|
||||
#################
|
||||
## PHPStorm
|
||||
#################
|
||||
|
||||
.idea/
|
||||
|
||||
#################
|
||||
## Eclipse
|
||||
#################
|
||||
|
||||
.settings/
|
||||
.buildpath
|
||||
.project
|
||||
|
||||
#################
|
||||
## Misc
|
||||
#################
|
||||
|
||||
pdoc.bat
|
||||
composer.lock
|
||||
docs
|
||||
vendor
|
||||
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Smiley <smiley@chillerlan.net>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -0,0 +1,7 @@
|
||||
# codemasher/php-qrcode
|
||||
|
||||
[](https://packagist.org/packages/codemasher/php-qrcode)
|
||||
[](LICENSE)
|
||||
|
||||
## Requirements
|
||||
- PHP 5.6+, PHP 7
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "codemasher/php-qrcode",
|
||||
"description": "A QR code generator. PHP 5.6+, PHP 7",
|
||||
"homepage": "https://github.com/codemasher/php-qrcode",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"QR code",
|
||||
"library"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Smiley",
|
||||
"email": "smiley@chillerlan.net"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.6.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"codemasher\\QRCode\\": "src/"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
require_once '../vendor/autoload.php';
|
||||
|
||||
use codemasher\QRCode\QRCode;
|
||||
use codemasher\QRCode\QRConst;
|
||||
|
||||
$qrcode = new QRCode;
|
||||
$qr = $qrcode->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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
require_once '../vendor/autoload.php';
|
||||
|
||||
use codemasher\QRCode\QRCode;
|
||||
use codemasher\QRCode\QRConst;
|
||||
//---------------------------------------------------------
|
||||
|
||||
$qrcode = new QRCode;
|
||||
|
||||
|
||||
print('<h4>明示的に型番を指定</h4>');
|
||||
|
||||
// エラー訂正レベルを設定
|
||||
// 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出力
|
||||
$qrcode->printHTML();
|
||||
|
||||
//---------------------------------------------------------
|
||||
print('<h4>型番自動</h4>');
|
||||
|
||||
// 型番が最小となるQRコードを作成
|
||||
$qr = $qrcode->getMinimumQRCode('QRコード', QRConst::ERROR_CORRECT_LEVEL_L);
|
||||
|
||||
// HTML出力
|
||||
$qr->printHTML();
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
require_once '../vendor/autoload.php';
|
||||
|
||||
use codemasher\QRCode\QRCode;
|
||||
use codemasher\QRCode\QRConst;
|
||||
|
||||
$qrcode = new QRCode;
|
||||
$qr = $qrcode->getMinimumQRCode('QRコード', QRConst::ERROR_CORRECT_LEVEL_L);
|
||||
|
||||
// イメージ作成(引数:サイズ,マージン)
|
||||
$im = $qr->createImage(2, 4);
|
||||
|
||||
header('Content-type: image/png');
|
||||
imagepng($im);
|
||||
|
||||
imagedestroy($im);
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* @filesource BitBuffer.php
|
||||
* @created 25.11.2015
|
||||
* @package codemasher\QRCode
|
||||
* @author Smiley <smiley@chillerlan.net>
|
||||
* @copyright 2015 Smiley
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace codemasher\QRCode;
|
||||
|
||||
/**
|
||||
* Class BitBuffer
|
||||
*/
|
||||
class BitBuffer{
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $buffer = [];
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $length = 0;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getBuffer(){
|
||||
return $this->buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getLengthInBits(){
|
||||
return $this->length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString(){
|
||||
$buffer = '';
|
||||
|
||||
for($i = 0; $i < $this->getLengthInBits(); $i++){
|
||||
$buffer .= $this->get($i) ? '1' : '0';
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
public function put($num, $length){
|
||||
for($i = 0; $i < $length; $i++){
|
||||
$this->putBit((($num >> ($length - $i - 1))&1) === 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $bit
|
||||
*/
|
||||
public function putBit($bit){
|
||||
$bufIndex = floor($this->length / 8);
|
||||
|
||||
if(count($this->buffer) <= $bufIndex){
|
||||
$this->buffer[] = 0;
|
||||
}
|
||||
|
||||
if($bit){
|
||||
$this->buffer[(int)$bufIndex] |= (0x80 >> ($this->length % 8));
|
||||
}
|
||||
|
||||
$this->length++;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* @filesource AlphaNum.php
|
||||
* @created 25.11.2015
|
||||
* @package codemasher\QRCode
|
||||
* @author Smiley <smiley@chillerlan.net>
|
||||
* @copyright 2015 Smiley
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace codemasher\QRCode\Data;
|
||||
|
||||
use codemasher\QRCode\BitBuffer;
|
||||
use codemasher\QRCode\Data;
|
||||
use codemasher\QRCode\Data\QRDataBase;
|
||||
use codemasher\QRCode\Data\QRDataInterface;
|
||||
use codemasher\QRCode\QRCodeException;
|
||||
use codemasher\QRCode\QRConst;
|
||||
|
||||
/**
|
||||
* Class AlphaNum
|
||||
*/
|
||||
class AlphaNum extends QRDataBase implements QRDataInterface{
|
||||
|
||||
|
||||
/**
|
||||
* AlphaNum constructor.
|
||||
*
|
||||
* @param $data
|
||||
*/
|
||||
public function __construct($data){
|
||||
parent::__construct($data, QRConst::MODE_ALPHA_NUM);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $buffer
|
||||
*/
|
||||
public function write(BitBuffer &$buffer){
|
||||
|
||||
$i = 0;
|
||||
$c = $this->getData();
|
||||
|
||||
while($i + 1 < strlen($c)){
|
||||
$buffer->put($this->getCode(ord($c[$i])) * 45
|
||||
+ $this->getCode(ord($c[$i + 1])), 11);
|
||||
$i += 2;
|
||||
}
|
||||
|
||||
if($i < strlen($c)){
|
||||
$buffer->put($this->getCode(ord($c[$i])), 6);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getLength(){
|
||||
return strlen($this->getData());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $c
|
||||
*
|
||||
* @return int
|
||||
* @throws \codemasher\QRCode\QRCodeException
|
||||
*/
|
||||
protected function getCode($c){
|
||||
|
||||
if($this->util->toCharCode('0') <= $c
|
||||
&& $c <= $this->util->toCharCode('9')
|
||||
){
|
||||
return $c - $this->util->toCharCode('0');
|
||||
}
|
||||
else if($this->util->toCharCode('A') <= $c
|
||||
&& $c <= $this->util->toCharCode('Z')
|
||||
){
|
||||
return $c - $this->util->toCharCode('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;
|
||||
default :
|
||||
throw new QRCodeException('illegal char: '.$c);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* @filesource EightBitByte.php
|
||||
* @created 25.11.2015
|
||||
* @package codemasher\QRCode
|
||||
* @author Smiley <smiley@chillerlan.net>
|
||||
* @copyright 2015 Smiley
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace codemasher\QRCode\Data;
|
||||
|
||||
use codemasher\QRCode\BitBuffer;
|
||||
use codemasher\QRCode\QRConst;
|
||||
use codemasher\QRCode\Data\QRDataBase;
|
||||
use codemasher\QRCode\Data\QRDataInterface;
|
||||
|
||||
|
||||
/**
|
||||
* Class EightBitByte
|
||||
*/
|
||||
class EightBitByte extends QRDataBase implements QRDataInterface{
|
||||
|
||||
/**
|
||||
* EightBitByte constructor.
|
||||
*
|
||||
* @param $data
|
||||
*/
|
||||
public function __construct($data){
|
||||
parent::__construct($data, QRConst::MODE_8BIT_BYTE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $buffer
|
||||
*/
|
||||
public function write(BitBuffer &$buffer){
|
||||
$data = $this->getData();
|
||||
|
||||
for($i = 0; $i < strlen($data); $i++){
|
||||
$buffer->put(ord($data[$i]), 8);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getLength(){
|
||||
return strlen($this->getData());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* @filesource Kanji.php
|
||||
* @created 25.11.2015
|
||||
* @package codemasher\QRCode
|
||||
* @author Smiley <smiley@chillerlan.net>
|
||||
* @copyright 2015 Smiley
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace codemasher\QRCode\Data;
|
||||
|
||||
use codemasher\QRCode\BitBuffer;
|
||||
use codemasher\QRCode\Data\QRDataBase;
|
||||
use codemasher\QRCode\Data\QRDataInterface;
|
||||
use codemasher\QRCode\QRCodeException;
|
||||
use codemasher\QRCode\QRConst;
|
||||
|
||||
/**
|
||||
* Class Kanji
|
||||
*/
|
||||
class Kanji extends QRDataBase implements QRDataInterface{
|
||||
|
||||
/**
|
||||
* Kanji constructor.
|
||||
*
|
||||
* @param $data
|
||||
*/
|
||||
public function __construct($data){
|
||||
parent::__construct($data, QRConst::MODE_KANJI);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $buffer
|
||||
*
|
||||
* @throws \codemasher\QRCode\QRCodeException
|
||||
*/
|
||||
public function write(BitBuffer &$buffer){
|
||||
$data = $this->getData();
|
||||
|
||||
$i = 0;
|
||||
while($i + 1 < strlen($data)){
|
||||
$c = ((0xff&ord($data[$i])) << 8)|(0xff&ord($data[$i + 1]));
|
||||
|
||||
if(0x8140 <= $c && $c <= 0x9FFC){
|
||||
$c -= 0x8140;
|
||||
}
|
||||
else if(0xE040 <= $c && $c <= 0xEBBF){
|
||||
$c -= 0xC140;
|
||||
}
|
||||
else{
|
||||
throw new QRCodeException('illegal char at '.($i + 1).' ('.$c.')');
|
||||
}
|
||||
|
||||
$c = (($c >> 8)&0xff) * 0xC0 + ($c&0xff);
|
||||
$buffer->put($c, 13);
|
||||
$i += 2;
|
||||
}
|
||||
|
||||
if($i < strlen($data)){
|
||||
throw new QRCodeException('illegal char at '.($i + 1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getLength(){
|
||||
return floor(strlen($this->getData()) / 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* @filesource Number.php
|
||||
* @created 26.11.2015
|
||||
* @package codemasher\QRCode
|
||||
* @author Smiley <smiley@chillerlan.net>
|
||||
* @copyright 2015 Smiley
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace codemasher\QRCode\Data;
|
||||
|
||||
use codemasher\QRCode\BitBuffer;
|
||||
use codemasher\QRCode\Data\QRDataBase;
|
||||
use codemasher\QRCode\Data\QRDataInterface;
|
||||
use codemasher\QRCode\QRCodeException;
|
||||
use codemasher\QRCode\QRConst;
|
||||
|
||||
/**
|
||||
* Class Number
|
||||
*/
|
||||
class Number extends QRDataBase implements QRDataInterface{
|
||||
|
||||
/**
|
||||
* @var \codemasher\QRCode\Util
|
||||
*/
|
||||
protected $util;
|
||||
|
||||
/**
|
||||
* Number constructor.
|
||||
*
|
||||
* @param $data
|
||||
*/
|
||||
public function __construct($data){
|
||||
parent::__construct($data, QRConst::MODE_NUMBER);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $buffer
|
||||
*/
|
||||
public function write(BitBuffer &$buffer){
|
||||
$data = $this->getData();
|
||||
|
||||
$i = 0;
|
||||
while($i + 2 < strlen($data)){
|
||||
$num = $this->parseInt(substr($data, $i, 3));
|
||||
$buffer->put($num, 10);
|
||||
$i += 3;
|
||||
}
|
||||
|
||||
if($i < strlen($data)){
|
||||
|
||||
if(strlen($data) - $i == 1){
|
||||
$num = $this->parseInt(substr($data, $i, $i + 1));
|
||||
$buffer->put($num, 4);
|
||||
}
|
||||
else if(strlen($data) - $i == 2){
|
||||
$num = $this->parseInt(substr($data, $i, $i + 2));
|
||||
$buffer->put($num, 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getLength(){
|
||||
return strlen($this->getData());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $s
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function parseInt($s){
|
||||
$num = 0;
|
||||
|
||||
for($i = 0; $i < strlen($s); $i++){
|
||||
$num = $num * 10 + $this->parseIntAt(ord($s[$i]));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* @filesource QRDataBase.php
|
||||
* @created 25.11.2015
|
||||
* @package codemasher\QRCode
|
||||
* @author Smiley <smiley@chillerlan.net>
|
||||
* @copyright 2015 Smiley
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace codemasher\QRCode\Data;
|
||||
|
||||
use codemasher\QRCode\BitBuffer;
|
||||
use codemasher\QRCode\QRConst;
|
||||
use codemasher\QRCode\QRCodeException;
|
||||
use codemasher\QRCode\Util;
|
||||
|
||||
/**
|
||||
* Class QRDataBase
|
||||
*/
|
||||
class QRDataBase{
|
||||
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
protected $mode;
|
||||
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @var \codemasher\QRCode\Util
|
||||
*/
|
||||
protected $util;
|
||||
|
||||
/**
|
||||
* QRDataBase constructor.
|
||||
*
|
||||
* @param $data
|
||||
* @param $mode
|
||||
*/
|
||||
public function __construct($data, $mode){
|
||||
$this->data = $data;
|
||||
$this->mode = $mode;
|
||||
$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.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $type
|
||||
*
|
||||
* @return int
|
||||
* @throws \codemasher\QRCode\QRCodeException
|
||||
*/
|
||||
public function getLengthInBits($type){
|
||||
if(1 <= $type && $type < 10){
|
||||
|
||||
// 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;
|
||||
default :
|
||||
throw new QRCodeException('mode: '.$this->mode);
|
||||
}
|
||||
|
||||
}
|
||||
else if($type < 27){
|
||||
|
||||
// 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;
|
||||
default :
|
||||
throw new QRCodeException('mode: '.$this->mode);
|
||||
}
|
||||
|
||||
}
|
||||
else if($type < 41){
|
||||
|
||||
// 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;
|
||||
default :
|
||||
throw new QRCodeException('mode: '.$this->mode);
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
throw new QRCodeException('mode: '.$this->mode);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* @filesource QRDataInterface.php
|
||||
* @created 01.12.2015
|
||||
* @author Smiley <smiley@chillerlan.net>
|
||||
* @copyright 2015 Smiley
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace codemasher\QRCode\Data;
|
||||
|
||||
use codemasher\QRCode\BitBuffer;
|
||||
|
||||
/**
|
||||
* Interface QRDataInterface
|
||||
*/
|
||||
interface QRDataInterface{
|
||||
|
||||
/**
|
||||
* @param \codemasher\QRCode\BitBuffer $buffer
|
||||
*/
|
||||
public function write(BitBuffer &$buffer);
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getLength();
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getData();
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getMode();
|
||||
|
||||
/**
|
||||
* @param $type
|
||||
*
|
||||
* @return int
|
||||
* @throws \codemasher\QRCode\QRCodeException
|
||||
*/
|
||||
public function getLengthInBits($type);
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* @filesource Math.php
|
||||
* @created 25.11.2015
|
||||
* @package codemasher\QRCode
|
||||
* @author Smiley <smiley@chillerlan.net>
|
||||
* @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];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* @filesource Polynomial.php
|
||||
* @created 25.11.2015
|
||||
* @package codemasher\QRCode
|
||||
* @author Smiley <smiley@chillerlan.net>
|
||||
* @copyright 2015 Smiley
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace codemasher\QRCode;
|
||||
|
||||
use codemasher\QRCode\Math;
|
||||
|
||||
/**
|
||||
* Class Polynomial
|
||||
*/
|
||||
class Polynomial{
|
||||
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
protected $num;
|
||||
|
||||
/**
|
||||
* @var \codemasher\QRCode\Math
|
||||
*/
|
||||
protected $math;
|
||||
|
||||
/**
|
||||
* Polynomial constructor.
|
||||
*
|
||||
* @param array $num
|
||||
* @param int $shift
|
||||
*/
|
||||
public function __construct(array $num, $shift = 0){
|
||||
$this->math = new Math;
|
||||
|
||||
$offset = 0;
|
||||
while($offset < count($num) && $num[$offset] === 0){
|
||||
$offset++;
|
||||
}
|
||||
|
||||
$this->num = $this->math->createNumArray(count($num) - $offset + $shift);
|
||||
for($i = 0; $i < count($num) - $offset; $i++){
|
||||
$this->num[$i] = $num[$i + $offset];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $index
|
||||
* @todo rename!
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($index){
|
||||
return $this->num[$index];
|
||||
}
|
||||
|
||||
/**
|
||||
* @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++){
|
||||
if($i > 0){
|
||||
$buffer .= ',';
|
||||
}
|
||||
$buffer .= $this->get($i);
|
||||
}
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function toLogString(){
|
||||
$buffer = '';
|
||||
|
||||
for($i = 0; $i < $this->getLength(); $i++){
|
||||
if($i > 0){
|
||||
$buffer .= ',';
|
||||
}
|
||||
$buffer .= $this->math->glog($this->get($i));
|
||||
}
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \codemasher\QRCode\Polynomial $e
|
||||
*
|
||||
* @return \codemasher\QRCode\Polynomial
|
||||
*/
|
||||
public function multiply($e){
|
||||
$num = $this->math->createNumArray($this->getLength() + $e->getLength() - 1);
|
||||
|
||||
for($i = 0; $i < $this->getLength(); $i++){
|
||||
for($j = 0; $j < $e->getLength(); $j++){
|
||||
$num[$i + $j] ^= $this->math->gexp($this->math->glog($this->get($i)) + $this->math->glog($e->get($j)));
|
||||
}
|
||||
}
|
||||
|
||||
return new Polynomial($num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \codemasher\QRCode\Polynomial $e
|
||||
*
|
||||
* @return $this|\codemasher\QRCode\Polynomial
|
||||
*/
|
||||
public function mod($e){
|
||||
|
||||
if($this->getLength() - $e->getLength() < 0){
|
||||
return $this;
|
||||
}
|
||||
|
||||
$ratio = $this->math->glog($this->get(0)) - $this->math->glog($e->get(0));
|
||||
|
||||
$num = $this->math->createNumArray($this->getLength());
|
||||
for($i = 0; $i < $this->getLength(); $i++){
|
||||
$num[$i] = $this->get($i);
|
||||
}
|
||||
|
||||
for($i = 0; $i < $e->getLength(); $i++){
|
||||
$num[$i] ^= $this->math->gexp($this->math->glog($e->get($i)) + $ratio);
|
||||
}
|
||||
|
||||
return (new Polynomial($num))->mod($e);
|
||||
}
|
||||
|
||||
}
|
||||
+597
@@ -0,0 +1,597 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* @filesource QRCode.php
|
||||
* @created 26.11.2015
|
||||
* @package codemasher\QRCode
|
||||
* @author Smiley <smiley@chillerlan.net>
|
||||
* @copyright 2015 Smiley
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace codemasher\QRCode;
|
||||
use codemasher\QRCode\Data\AlphaNum;
|
||||
use codemasher\QRCode\Data\EightBitByte;
|
||||
use codemasher\QRCode\Data\Kanji;
|
||||
use codemasher\QRCode\Data\Number;
|
||||
use codemasher\QRCode\QRConst;
|
||||
|
||||
/**
|
||||
* Class QRCode
|
||||
*/
|
||||
class QRCode{
|
||||
|
||||
const QR_PAD0 = 0xEC;
|
||||
const QR_PAD1 = 0x11;
|
||||
|
||||
protected $typeNumber;
|
||||
|
||||
protected $modules;
|
||||
|
||||
protected $moduleCount;
|
||||
|
||||
protected $errorCorrectLevel;
|
||||
|
||||
protected $qrDataList;
|
||||
|
||||
protected $util;
|
||||
|
||||
protected $rs_block;
|
||||
|
||||
public function __construct(){
|
||||
$this->typeNumber = 1;
|
||||
$this->errorCorrectLevel = QRConst::ERROR_CORRECT_LEVEL_H;
|
||||
$this->qrDataList = [];
|
||||
$this->util = new Util;
|
||||
$this->rs_block = new RSBlock;
|
||||
}
|
||||
|
||||
public function getTypeNumber(){
|
||||
return $this->typeNumber;
|
||||
}
|
||||
|
||||
public function setTypeNumber($typeNumber){
|
||||
$this->typeNumber = $typeNumber;
|
||||
}
|
||||
|
||||
public function getErrorCorrectLevel(){
|
||||
return $this->errorCorrectLevel;
|
||||
}
|
||||
|
||||
public function setErrorCorrectLevel($errorCorrectLevel){
|
||||
$this->errorCorrectLevel = $errorCorrectLevel;
|
||||
}
|
||||
|
||||
public function addData($data, $mode = 0){
|
||||
|
||||
if($mode == 0){
|
||||
$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 :
|
||||
trigger_error("mode:$mode", E_USER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
public function clearData(){
|
||||
$this->qrDataList = [];
|
||||
}
|
||||
|
||||
public function addDataImpl(&$qrData){
|
||||
$this->qrDataList[] = $qrData;
|
||||
}
|
||||
|
||||
public function getDataCount(){
|
||||
return count($this->qrDataList);
|
||||
}
|
||||
|
||||
public function getData($index){
|
||||
return $this->qrDataList[$index];
|
||||
}
|
||||
|
||||
public function isDark($row, $col){
|
||||
if($this->modules[$row][$col] !== null){
|
||||
return $this->modules[$row][$col];
|
||||
}
|
||||
else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getModuleCount(){
|
||||
return $this->moduleCount;
|
||||
}
|
||||
|
||||
// used for converting fg/bg colors (e.g. #0000ff = 0x0000FF)
|
||||
// added 2015.07.27 ~ DoktorJ
|
||||
public function hex2rgb($hex = 0x0){
|
||||
return [
|
||||
'r' => floor($hex / 65536),
|
||||
'g' => floor($hex / 256) % 256,
|
||||
'b' => $hex % 256,
|
||||
];
|
||||
}
|
||||
|
||||
public function make(){
|
||||
$this->makeImpl(false, $this->getBestMaskPattern());
|
||||
}
|
||||
|
||||
public function getBestMaskPattern(){
|
||||
|
||||
$minLostPoint = 0;
|
||||
$pattern = 0;
|
||||
|
||||
for($i = 0; $i < 8; $i++){
|
||||
|
||||
$this->makeImpl(true, $i);
|
||||
|
||||
$lostPoint = $this->util->getLostPoint($this);
|
||||
|
||||
if($i == 0 || $minLostPoint > $lostPoint){
|
||||
$minLostPoint = $lostPoint;
|
||||
$pattern = $i;
|
||||
}
|
||||
}
|
||||
|
||||
return $pattern;
|
||||
}
|
||||
|
||||
public function createNullArray($length){
|
||||
$nullArray = [];
|
||||
for($i = 0; $i < $length; $i++){
|
||||
$nullArray[] = null;
|
||||
}
|
||||
return $nullArray;
|
||||
}
|
||||
|
||||
public function makeImpl($test, $maskPattern){
|
||||
|
||||
$this->moduleCount = $this->typeNumber * 4 + 17;
|
||||
|
||||
$this->modules = [];
|
||||
for($i = 0; $i < $this->moduleCount; $i++){
|
||||
$this->modules[] = $this->createNullArray($this->moduleCount);
|
||||
}
|
||||
|
||||
$this->setupPositionProbePattern(0, 0);
|
||||
$this->setupPositionProbePattern($this->moduleCount - 7, 0);
|
||||
$this->setupPositionProbePattern(0, $this->moduleCount - 7);
|
||||
|
||||
$this->setupPositionAdjustPattern();
|
||||
$this->setupTimingPattern();
|
||||
|
||||
$this->setupTypeInfo($test, $maskPattern);
|
||||
|
||||
if($this->typeNumber >= 7){
|
||||
$this->setupTypeNumber($test);
|
||||
}
|
||||
|
||||
$dataArray = $this->qrDataList;
|
||||
|
||||
$data = $this->createData($this->typeNumber, $this->errorCorrectLevel, $dataArray);
|
||||
|
||||
$this->mapData($data, $maskPattern);
|
||||
}
|
||||
|
||||
public function mapData(&$data, $maskPattern){
|
||||
|
||||
$inc = -1;
|
||||
$row = $this->moduleCount - 1;
|
||||
$bitIndex = 7;
|
||||
$byteIndex = 0;
|
||||
|
||||
for($col = $this->moduleCount - 1; $col > 0; $col -= 2){
|
||||
|
||||
if($col == 6){
|
||||
$col--;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
$mask = $this->util->getMask($maskPattern, $row, $col - $c);
|
||||
|
||||
if($mask){
|
||||
$dark = !$dark;
|
||||
}
|
||||
|
||||
$this->modules[$row][$col - $c] = $dark;
|
||||
$bitIndex--;
|
||||
|
||||
if($bitIndex == -1){
|
||||
$byteIndex++;
|
||||
$bitIndex = 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$row += $inc;
|
||||
|
||||
if($row < 0 || $this->moduleCount <= $row){
|
||||
$row -= $inc;
|
||||
$inc = -$inc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function setupPositionAdjustPattern(){
|
||||
|
||||
$pos = $this->util->getPatternPosition($this->typeNumber);
|
||||
|
||||
for($i = 0; $i < count($pos); $i++){
|
||||
|
||||
for($j = 0; $j < count($pos); $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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public 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
|
||||
){
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
public function setupTypeNumber($test){
|
||||
|
||||
$bits = $this->util->getBCHTypeNumber($this->typeNumber);
|
||||
|
||||
for($i = 0; $i < 18; $i++){
|
||||
$mod = (!$test && (($bits >> $i)&1) == 1);
|
||||
$this->modules[(int)floor($i / 3)][$i % 3 + $this->moduleCount - 8 - 3] = $mod;
|
||||
}
|
||||
|
||||
for($i = 0; $i < 18; $i++){
|
||||
$mod = (!$test && (($bits >> $i)&1) == 1);
|
||||
$this->modules[$i % 3 + $this->moduleCount - 8 - 3][(int)floor($i / 3)] = $mod;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public function createData($typeNumber, $errorCorrectLevel, $dataArray){
|
||||
|
||||
$rsBlocks = $this->rs_block->getRSBlocks($typeNumber, $errorCorrectLevel);
|
||||
|
||||
$buffer = new BitBuffer;
|
||||
|
||||
for($i = 0; $i < count($dataArray); $i++){
|
||||
$data = $dataArray[$i];
|
||||
$buffer->put($data->getMode(), 4);
|
||||
$buffer->put($data->getLength(), $data->getLengthInBits($typeNumber));
|
||||
$data->write($buffer);
|
||||
}
|
||||
|
||||
$totalDataCount = 0;
|
||||
for($i = 0; $i < count($rsBlocks); $i++){
|
||||
$totalDataCount += $rsBlocks[$i]->getDataCount();
|
||||
}
|
||||
|
||||
if($buffer->getLengthInBits() > $totalDataCount * 8){
|
||||
trigger_error("code length overflow. ("
|
||||
.$buffer->getLengthInBits()
|
||||
.">"
|
||||
.$totalDataCount * 8
|
||||
.")", E_USER_ERROR);
|
||||
}
|
||||
|
||||
// end code.
|
||||
if($buffer->getLengthInBits() + 4 <= $totalDataCount * 8){
|
||||
$buffer->put(0, 4);
|
||||
}
|
||||
|
||||
// padding
|
||||
while($buffer->getLengthInBits() % 8 != 0){
|
||||
$buffer->putBit(false);
|
||||
}
|
||||
|
||||
// padding
|
||||
while(true){
|
||||
|
||||
if($buffer->getLengthInBits() >= $totalDataCount * 8){
|
||||
break;
|
||||
}
|
||||
$buffer->put(self::QR_PAD0, 8);
|
||||
|
||||
if($buffer->getLengthInBits() >= $totalDataCount * 8){
|
||||
break;
|
||||
}
|
||||
$buffer->put(self::QR_PAD1, 8);
|
||||
}
|
||||
|
||||
return $this->createBytes($buffer, $rsBlocks);
|
||||
}
|
||||
|
||||
public function createBytes(&$buffer, &$rsBlocks){
|
||||
|
||||
$offset = 0;
|
||||
|
||||
$maxDcCount = 0;
|
||||
$maxEcCount = 0;
|
||||
|
||||
$dcdata = $this->createNullArray(count($rsBlocks));
|
||||
$ecdata = $this->createNullArray(count($rsBlocks));
|
||||
|
||||
for($r = 0; $r < count($rsBlocks); $r++){
|
||||
|
||||
$dcCount = $rsBlocks[$r]->getDataCount();
|
||||
$ecCount = $rsBlocks[$r]->getTotalCount() - $dcCount;
|
||||
|
||||
$maxDcCount = max($maxDcCount, $dcCount);
|
||||
$maxEcCount = max($maxEcCount, $ecCount);
|
||||
|
||||
$dcdata[$r] = $this->createNullArray($dcCount);
|
||||
for($i = 0; $i < count($dcdata[$r]); $i++){
|
||||
$bdata = $buffer->getBuffer();
|
||||
$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);
|
||||
for($i = 0; $i < count($ecdata[$r]); $i++){
|
||||
$modIndex = $i + $modPoly->getLength() - count($ecdata[$r]);
|
||||
$ecdata[$r][$i] = ($modIndex >= 0) ? $modPoly->get($modIndex) : 0;
|
||||
}
|
||||
}
|
||||
|
||||
$totalCodeCount = 0;
|
||||
for($i = 0; $i < count($rsBlocks); $i++){
|
||||
$totalCodeCount += $rsBlocks[$i]->getTotalCount();
|
||||
}
|
||||
|
||||
$data = $this->createNullArray($totalCodeCount);
|
||||
|
||||
$index = 0;
|
||||
|
||||
for($i = 0; $i < $maxDcCount; $i++){
|
||||
for($r = 0; $r < count($rsBlocks); $r++){
|
||||
if($i < count($dcdata[$r])){
|
||||
$data[$index++] = $dcdata[$r][$i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for($i = 0; $i < $maxEcCount; $i++){
|
||||
for($r = 0; $r < count($rsBlocks); $r++){
|
||||
if($i < count($ecdata[$r])){
|
||||
$data[$index++] = $ecdata[$r][$i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getMinimumQRCode($data, $errorCorrectLevel){
|
||||
|
||||
$mode = $this->util->getMode($data);
|
||||
|
||||
$qr = new QRCode();
|
||||
$qr->setErrorCorrectLevel($errorCorrectLevel);
|
||||
$qr->addData($data, $mode);
|
||||
|
||||
$qrData = $qr->getData(0);
|
||||
$length = $qrData->getLength();
|
||||
|
||||
for($typeNumber = 1; $typeNumber <= 10; $typeNumber++){
|
||||
if($length <= $this->util->getMaxLength($typeNumber, $mode, $errorCorrectLevel)){
|
||||
$qr->setTypeNumber($typeNumber);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$qr->make();
|
||||
|
||||
return $qr;
|
||||
}
|
||||
|
||||
// added $fg (foreground), $bg (background), and $bgtrans (use transparent bg) parameters
|
||||
// also added some simple error checking on parameters
|
||||
// updated 2015.07.27 ~ DoktorJ
|
||||
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->getModuleCount() * $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->hex2rgb($fg);
|
||||
$bgrgb = $this->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->getModuleCount(); $r++){
|
||||
for($c = 0; $c < $this->getModuleCount(); $c++){
|
||||
if($this->isDark($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;
|
||||
}
|
||||
|
||||
public function printHTML($size = "2px"){
|
||||
|
||||
$style = "border-style:none;border-collapse:collapse;margin:0px;padding:0px;";
|
||||
|
||||
print("<table style='$style'>");
|
||||
|
||||
for($r = 0; $r < $this->getModuleCount(); $r++){
|
||||
|
||||
print("<tr style='$style'>");
|
||||
|
||||
for($c = 0; $c < $this->getModuleCount(); $c++){
|
||||
$color = $this->isDark($r, $c) ? "#000000" : "#ffffff";
|
||||
print("<td style='$style;width:$size;height:$size;background-color:$color'></td>");
|
||||
}
|
||||
|
||||
print("</tr>");
|
||||
}
|
||||
|
||||
print("</table>");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
* Class QRCodeException
|
||||
*
|
||||
* @filesource QRCodeException.php
|
||||
* @created 27.11.2015
|
||||
* @package codemasher\QRCode
|
||||
* @author Smiley <smiley@chillerlan.net>
|
||||
* @copyright 2015 Smiley
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace codemasher\QRCode;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Placeholder
|
||||
*/
|
||||
class QRCodeException extends Exception{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* @filesource QRConst.php
|
||||
* @created 26.11.2015
|
||||
* @package codemasher\QRCode
|
||||
* @author Smiley <smiley@chillerlan.net>
|
||||
* @copyright 2015 Smiley
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace codemasher\QRCode;
|
||||
|
||||
/**
|
||||
* Class QRConst
|
||||
*/
|
||||
class QRConst{
|
||||
|
||||
const MODE_NUMBER = 1 << 0;
|
||||
const MODE_ALPHA_NUM = 1 << 1;
|
||||
const MODE_8BIT_BYTE = 1 << 2;
|
||||
const MODE_KANJI = 1 << 3;
|
||||
|
||||
const MASK_PATTERN000 = 0;
|
||||
const MASK_PATTERN001 = 1;
|
||||
const MASK_PATTERN010 = 2;
|
||||
const MASK_PATTERN011 = 3;
|
||||
const MASK_PATTERN100 = 4;
|
||||
const MASK_PATTERN101 = 5;
|
||||
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%.
|
||||
|
||||
}
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
<?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
|
||||
*/
|
||||
protected $totalCount;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $dataCount;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $QR_RS_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],
|
||||
|
||||
];
|
||||
|
||||
|
||||
public function __construct($totalCount = null, $dataCount = null){
|
||||
if(isset($totalCount, $dataCount)){
|
||||
$this->setCount($totalCount, $dataCount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RSBlock constructor.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
public function getRSBlocks($typeNumber, $errorCorrectLevel){
|
||||
$rsBlock = $this->getRsBlockTable($typeNumber, $errorCorrectLevel);
|
||||
$length = count($rsBlock) / 3;
|
||||
$list = [];
|
||||
|
||||
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[] = new RSBlock($totalCount, $dataCount);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+466
@@ -0,0 +1,466 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* @filesource Util.php
|
||||
* @created 25.11.2015
|
||||
* @package codemasher\QRCode
|
||||
* @author Smiley <smiley@chillerlan.net>
|
||||
* @copyright 2015 Smiley
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace codemasher\QRCode;
|
||||
|
||||
use codemasher\QRCode\Math;
|
||||
use codemasher\QRCode\Polynomial;
|
||||
use codemasher\QRCode\QRCode;
|
||||
use codemasher\QRCode\QRConst;
|
||||
use codemasher\QRCode\QRCodeException;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
protected $QR_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]],
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $QR_PATTERN_POSITION_TABLE = [
|
||||
[],
|
||||
[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],
|
||||
];
|
||||
|
||||
/**
|
||||
* @var \codemasher\QRCode\Math
|
||||
*/
|
||||
protected $math;
|
||||
|
||||
/**
|
||||
* Util constructor.
|
||||
*/
|
||||
public function __construct(){
|
||||
$this->math = new Math;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $typeNumber
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getPatternPosition($typeNumber){
|
||||
return $this->QR_PATTERN_POSITION_TABLE[$typeNumber - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $typeNumber
|
||||
* @param int $mode
|
||||
* @param int $errorCorrectLevel
|
||||
*
|
||||
* @return mixed
|
||||
* @throws \codemasher\QRCode\QRCodeException
|
||||
*/
|
||||
public function getMaxLength($typeNumber, $mode, $errorCorrectLevel){
|
||||
$_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;
|
||||
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;
|
||||
default :
|
||||
throw new QRCodeException('$_mode: '.$mode);
|
||||
}
|
||||
|
||||
return $this->QR_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
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getMode($s){
|
||||
if($this->isAlphaNum($s)){
|
||||
if($this->isNumber($s)){
|
||||
return QRConst::MODE_NUMBER;
|
||||
}
|
||||
return QRConst::MODE_ALPHA_NUM;
|
||||
}
|
||||
else if($this->isKanji($s)){
|
||||
return QRConst::MODE_KANJI;
|
||||
}
|
||||
else{
|
||||
return QRConst::MODE_8BIT_BYTE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $s
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isNumber($s){
|
||||
for($i = 0; $i < strlen($s); $i++){
|
||||
$c = ord($s[$i]);
|
||||
|
||||
if(!($this->toCharCode('0') <= $c && $c <= $this->toCharCode('9'))){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $s
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isAlphaNum($s){
|
||||
for($i = 0; $i < strlen($s); $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
|
||||
){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $s
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isKanji($s){
|
||||
$data = $s;
|
||||
$i = 0;
|
||||
|
||||
while($i + 1 < strlen($data)){
|
||||
$c = ((0xff&ord($data[$i])) << 8)|(0xff&ord($data[$i + 1]));
|
||||
|
||||
if(!(0x8140 <= $c && $c <= 0x9FFC) && !(0xE040 <= $c && $c <= 0xEBBF)){
|
||||
return false;
|
||||
}
|
||||
|
||||
$i += 2;
|
||||
}
|
||||
|
||||
if($i < strlen($data)){
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $s
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function toCharCode($s){
|
||||
return ord($s[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public 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)));
|
||||
}
|
||||
|
||||
return (($data << 10)|$d)^self::QR_G15_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public 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)));
|
||||
}
|
||||
|
||||
return ($data << 12)|$d;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getBCHDigit($data){
|
||||
$digit = 0;
|
||||
|
||||
while($data != 0){
|
||||
$digit++;
|
||||
$data >>= 1;
|
||||
}
|
||||
|
||||
return $digit;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user