ホームページ >php教程 >php手册 >あなたと共有する PHP QRcode クラス

あなたと共有する PHP QRcode クラス

WBOY
WBOYオリジナル
2016-06-13 12:04:15917ブラウズ

クラスコード:

コードをコピー コードは次のとおりです:


define('QR_MODE_NUL', -1);
define('QR_MODE_NUM', 0);
define('QR_MODE_AN', 1);
define('QR_MODE_8', 2);
define('QR_MODE_KANJI', 3);
define('QR_MODE_STRUCTURE', 4);
// エラー修正のレベル。
define('QR_ECLEVEL_L', 0);
define('QR_ECLEVEL_M', 1);
define('QR_ECLEVEL_Q', 2);
define('QR_ECLEVEL_H', 3);
// サポートされている出力形式
define('QR_FORMAT_TEXT', 0);
define('QR_FORMAT_PNG', 1);
class qrstr {
public static function set(&$srctab, $x, $y, $repl, $replLen = false) {
$srctab[$y] = substr_replace($srctab[$y] ], ($replLen !== false)?substr($repl,0,$replLen):$repl, $x, ($replLen !== false)?$replLen:strlen($repl));
}
}
define('QR_CACHEABLE', false); // キャッシュを使用します - ディスク読み取りは増加しますが、CPU パワーは低下し、マスクとフォーマット テンプレートがそこに保存されます
define('QR_CACHE_DIR', false); // QR_CACHEABLE === true の場合に使用
define('QR_LOG_DIR', false); // デフォルトのエラー ログ dir
define('QR_FIND_BEST_MASK', true); // true の場合、最良のマスクを推定します (仕様はデフォルトですが、非常に遅いです。 false に設定するとパフォーマンスが大幅に向上しますが、(おそらく) 最悪の品質のコードになります。
define('QR_FIND_FROM_RANDOM', 2); // false の場合、すべてをチェックしますマスクが利用可能、そうでない場合、値はマスクの数をチェックする必要があることを示し、マスク ID はランダムに取得されます。
define('QR_DEFAULT_MASK', 2) // QR_FIND_BEST_MASK === false の場合
define('QR_PNG_MAXIMUM_SIZE', 1024); ; // 許可される PNG 画像の最大幅 (ピクセル単位)、GD と PHP がそのような大きな画像を処理できるように調整します
class QRtools {
public static function binarize($frame){
$len = count ($frame);
foreach ($frame as &$frameLine) {
for($i=0; $i$frameLine[$i] = (ord ($frameLine[$i])&1)?'1':'0';
}
}
return $frame;
}
パブリック静的関数 tcpdfBarcodeArray($code, $ mode = 'QR,L', $tcPdfVersion = '4.5.037'){
$barcode_array = array();
if (!is_array($mode))
$mode =explode(', ', $mode);
$eccLevel = 'L';
if (count($mode) > 1) {
$eccLevel = $mode[1];
}
$qrTab = QRcode::text($code, false, $eccLevel);
$size = count($qrTab);
$barcode_array['num_rows'] = $size;
$barcode_array['num_cols'] = $size;
$barcode_array['bcode'] = array();
foreach ($qrTab as $line) {
$arrAdd = array();
foreach(str_split($line) as $char)
$arrAdd[] = ($char=='1')?1:0;
$barcode_array['bcode'][] = $arrAdd;
}
$barcode_array を返す;
}
パブリック静的関数 clearCache(){
self::$frames = array();
}
パブリック静的関数 buildCache(){
QRtools::markTime('before_build_cache');
$mask = 新しい QRmask();
for ($a=1; $a $frame = QRspec::newFrame($a);
if (QR_IMAGE) {
$fileName = QR_CACHE_DIR.'frame_'.$a.'.png';
QRimage::png(self::binarize($frame), $fileName, 1, 0);
}
$width = count($frame);
$bitMask = array_fill(0, $width, array_fill(0, $width, 0));
for ($maskNo=0; $maskNo$mask->makeMaskNo($maskNo, $width, $frame, $bitMask, true);
}
QRtools::markTime('after_build_cache');
}
public static function log($outfile, $err){
if (QR_LOG_DIR !== false) {
if ($err != '') {
if ($ outfile !== false) {
file_put_contents(QR_LOG_DIR.basename($outfile).'-errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND);
} else {
file_put_contents(QR_LOG_DIR.'errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND);
}
}
}
}
パブリック静的関数 dumpMask($frame){
$width = count($frame);
for($y=0;$yfor($x=0;$xecho ord($frame[$ y][$x]).',';
}
}
}
パブリック静的関数 markTime($markerId){
list($usec, $sec) =explode(" ", microtime());
$time = ((float)$usec (float)$sec);
if (!isset($GLOBALS['qr_time_bench']))
$GLOBALS['qr_time_bench'] = array();
$GLOBALS['qr_time_bench'][$markerId] = $time;
}
パブリック静的関数 timeBenchmark(){
self::markTime('finish');
$lastTime = 0;
$startTime = 0;
$p = 0;
エコー '


ベンチマーク
<みんな>';
foreach($GLOBALS['qr_time_bench'] as $markerId=>$thisTime) {
if ($p > 0) {
echo '';
} else {
$startTime = $thisTime;
}
$p ;
$lastTime = $thisTime;
}
エコー '


till '.$markerId.': '.number_format($thisTime-$lastTime, 6).'s
合計: '.number_format($lastTime -$startTime, 6).の
';
}
}
//#################################### #####################################
QRtools::markTime('start');
define('QRSPEC_VERSION_MAX', 40);
define('QRSPEC_WIDTH_MAX', 177);
define('QRCAP_WIDTH', 0);
define('QRCAP_WORDS', 1);
define('QRCAP_REMINDER', 2);
define('QRCAP_EC', 3);
class QRspec {
public static $capacity = array(
array( 0, 0, 0, array( 0, 0, 0, 0)),
array( 21, 26, 0, array( 7, 10, 13, 17)), // 1
array( 25, 44, 7, array( 10, 16, 22, 28)),
array( 29, 70, 7, array ( 15, 26, 36, 44))、
array( 33, 100, 7, array( 20, 36, 52, 64))、
array( 37, 134, 7, array( 26, 48) , 72, 88)), // 5
array( 41, 172, 7, array( 36, 64, 96, 112)),
array( 45, 196, 0, array( 40, 72, 108, 130))、
array( 49, 242, 0, array( 48, 88, 132, 156)),
array( 53, 292, 0, array( 60, 110, 160, 192) ),
array( 57, 346, 0, array( 72, 130, 192, 224)), //10
array( 61, 404, 0, array( 80, 150, 224, 264)) ,
array( 65, 466, 0, array( 96, 176, 260, 308)),
array( 69, 532, 0, array( 104, 198, 288, 352)),
array( 73, 581, 3, array( 120, 216, 320, 384)),
array( 77, 655, 3, array( 132, 240, 360, 432)), //15
array ( 81, 733, 3, array( 144, 280, 408, 480)),
array( 85, 815, 3, array( 168, 308, 448, 532)),
array( 89, 901 , 3, array( 180, 338, 504, 588)),
array( 93, 991, 3, array( 196, 364, 546, 650)),
array( 97, 1085, 3, array ( 224, 416, 600, 700)), //20
array(101, 1156, 4, array( 224, 442, 644, 750)),
array(105, 1258, 4, array( 252, 476, 690, 816))、
array(109, 1364, 4, array( 270, 504, 750, 900))、
array(113, 1474, 4, array( 300, 560, 810, 960)),
array(117, 1588, 4, array( 312, 588, 870, 1050)), //25
array(121, 1706, 4, array( 336, 644, 952) , 1110))、
array(125, 1828, 4, array( 360, 700, 1020, 1200)),
array(129, 1921, 3, array( 390, 728, 1050, 1260)) ,
array(133, 2051, 3, array( 420, 784, 1140, 1350)),
array(137, 2185, 3, array( 450, 812, 1200, 1440)), //30
配列(141, 2323, 3, 配列(480, 868, 1290, 1530)),
配列(145, 2465, 3, 配列(510, 924, 1350, 1620)),
配列(149, 2611, 3, array( 540, 980, 1440, 1710)),
array(153, 2761, 3, array( 570, 1036, 1530, 1800)),
array(157, 2876) , 0, array( 570, 1064, 1590, 1890)), //35
array(161, 3034, 0, array( 600, 1120, 1680, 1980)),
array(165, 3196, 0, array( 630, 1204, 1770, 2100)),
array(169, 3362, 0, array( 660, 1260, 1860, 2220)),
array(173, 3532, 0, array( 720, 1316, 1950, 2310)),
array(177, 3706, 0, array( 750, 1372, 2040, 2430)) //40
);
public static function getDataLength($version, $level){
return self::$capacity[$version][QRCAP_WORDS] - self::$capacity[$version][QRCAP_EC][$level];
}
public static function getECCLength($version, $level){
return self::$capacity[$version][QRCAP_EC][$level];
}
public static function getWidth($version){
return self::$capacity[$version][QRCAP_WIDTH];
}
public static function getRemainder($version){
return self::$capacity[$version][QRCAP_REMINDER];
}
public static function getMinimumVersion($size, $level){
for($i=1; $i<= QRSPEC_VERSION_MAX; $i ) {
$words = self::$capacity [$i][QRCAP_WORDS] - self::$capacity[$i][QRCAP_EC][$level];
if($words >= $size)
return $i;
}
-1 を返す;
}
//######################################## ###########################
public static $lengthTableBits = array(
array(10, 12, 14) ,
array( 9, 11, 13),
array( 8, 16, 16),
array( 8, 10, 12)
);
public static function lengthIndicator($mode, $version){
if ($mode == QR_MODE_STRUCTURE)
return 0;
if ($version <= 9) {
$l = 0;
} else if ($version <= 26) {
$l = 1;
} else {
$l = 2;
}
return self::$lengthTableBits[$mode][$l];
}
public static function minimumWords($mode, $version){
if($mode == QR_MODE_STRUCTURE)
return 3;
if($version <= 9) {
$l = 0;
} else if($version <= 26) {
$l = 1;
} else {
$l = 2;
}
$bits = self::$lengthTableBits[$mode][$l];
$words = (1 << $bits) - 1;
if($mode == QR_MODE_KANJI) {
$words *= 2; // バイト数は必須です
}
return $words;
}
public static $eccTable = array(
array(array( 0, 0), array( 0, 0), array( 0, 0), array( 0, 0)),
array(array ( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), // 1
array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)),
array(array( 1, 0), array( 1, 0), array( 2, 0), array( 2, 0)),
array(array( 1, 0), array( 2, 0), array( 2, 0), array( 4, 0)),
array(array( 1, 0), array( 2, 0) ), array( 2, 2), array( 2, 2)), // 5
array(array( 2, 0), array( 4, 0), array( 4, 0), array( 4, 0))、
array(array( 2, 0)、array( 4, 0)、array( 2, 4)、array( 4, 1))、
array(array( 2, 0)、 array( 2, 2), array( 4, 2), array( 4, 2)),
array(array( 2, 0), array( 3, 2), array( 4, 4), array( 4, 4)),
array(array( 2, 2), array( 4, 1), array( 6, 2), array( 6, 2)), //10
array(array( 4, 0)、array( 1, 4)、array( 4, 4)、array( 3, 8))、
array(array( 2, 2)、array( 6, 2)、array( 4, 6), array( 7, 4)),
array(array( 4, 0), array( 8, 1), array( 8, 4), array(12, 4)),
array( array( 3, 1), array( 4, 5), array(11, 5), array(11, 5)),
array(array( 5, 1), array( 5, 5), array( 5, 7), array(11, 7)), //15
array(array( 5, 1), array( 7, 3), array(15, 2), array( 3, 13)),
array(array( 1, 5), array(10, 1), array( 1, 15), array( 2, 17)),
array(array( 5, 1), array( 9, 4)、array(17, 1)、array( 2, 19))、
array(array( 3, 4)、array( 3, 11)、array(17, 4)、array( 9, 16) ),
array(array( 3, 5), array( 3, 13), array(15, 5), array(15, 10)), //20
array(array( 4, 4) 、配列(17, 0)、配列(17, 6)、配列(19, 6))、
配列(配列( 2, 7)、配列(17, 0)、配列(7, 16)、配列(34, 0))、
array(array( 4, 5), array( 4, 14), array(11, 14), array(16, 14)),
array(array( 6, 4)、配列( 6, 14)、配列(11, 16)、配列(30, 2))、
配列(配列( 8, 4)、配列( 8, 13)、配列( 7, 22) , array(22, 13)), //25
array(array(10, 2), array(19, 4), array(28, 6), array(33, 4)),
array (配列( 8, 4), 配列(22, 3), 配列( 8, 26), 配列(12, 28)),
配列(配列( 3, 10), 配列( 3, 23), 配列( 4, 31), array(11, 31)),
array(array( 7, 7), array(21, 7), array( 1, 37), array(19, 26)),
array(array( 5, 10), array(19, 10), array(15, 25), array(23, 25)), //30
array(array(13, 3), array( 2 、29)、配列(42, 1)、配列(23, 28))、
配列(配列(17, 0)、配列(10, 23)、配列(10, 35)、配列(19, 35) ))、
array(array(17, 1), array(14, 21), array(29, 19), array(11, 46)),
array(array(13, 6), array (14, 23)、配列(44, 7)、配列(59, 1))、
配列(配列(12, 7)、配列(12, 26)、配列(39, 14)、配列(22) , 41)), //35
array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)),
array(array(17) , 4)、配列(29, 14)、配列(49, 10)、配列(24, 46))、
配列(配列( 4, 18)、配列(13, 32)、配列(48, 14) ), array(42, 32)),
array(array(20, 4), array(40, 7), array(43, 22), array(10, 67)),
array(array (19, 6), array(18, 31), array(34, 34), array(20, 61)),//40
);
// キャッシュ可能!!!
パブリック静的関数 getEccSpec($version, $level, array &$spec){
if (count($spec) < 5) {
$spec = array(0,0,0,0) ,0);
}
$b1 = self::$eccTable[$version][$level][0];
$b2 = self::$eccTable[$version][$level][1];
$data = self::getDataLength($version, $level);
$ecc = self::getECCLength($version, $level);
if($b2 == 0) {
$spec[0] = $b1;
$spec[1] = (int)($data / $b1);
$spec[2] = (int)($ecc / $b1);
$spec[3] = 0;
$spec[4] = 0;
} else {
$spec[0] = $b1;
$spec[1] = (int)($data / ($b1 $b2));
$spec[2] = (int)($ecc / ($b1 $b2));
$spec[3] = $b2;
$spec[4] = $spec[1] 1;
}
}
public static $alignmentPattern = array(
array( 0, 0),
array( 0, 0), array(18, 0), array(22, 0) ), array(26, 0), array(30, 0), // 1-5
array(34, 0), array(22, 38), array(24, 42), array(26, 46) ), array(28, 50), // 6-10
array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48) ), //11-15
配列(26, 50), 配列(30, 54), 配列(30, 56), 配列(30, 58), 配列(34, 62), //16-20
array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58), //21-25
array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52), //26-30
array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54), //31-35
array(24, 50), array(28, 54), array(32, 58)、配列(26, 54)、配列(30, 58)、//35-40
);
public static function putAlignmentMarker(array &$frame, $ox, $oy){
$finder = array(
"xa1xa1xa1xa1xa1",
"xa1xa0xa0xa0xa1",
"xa1xa0xa1xa0xa1",
"xa1xa0xa0xa0xa1",
"xa1xa1xa1xa1xa1"
);
$yStart = $oy-2;
$xStart = $ox-2;
for($y=0; $y<5; $y ) {
QRstr::set($frame, $xStart, $yStart $y, $finder[$y]);
}
}
パブリック静的関数 putAlignmentPattern($version, &$frame, $width){
if($version < 2)
return;
$d = self::$alignmentPattern[$version][1] - self::$alignmentPattern[$version][0];
if($d < 0) {
$w = 2;
}else {
$w = (int)(($width - self::$alignmentPattern[$version][0]) / $d 2);
}
if($w * $w - 3 == 1) {
$x = self::$alignmentPattern[$version][0];
$y = self::$alignmentPattern[$version][0];
self::putAlignmentMarker($frame, $x, $y);
戻る;
}
$cx = self::$alignmentPattern[$version][0];
for($x=1; $x<$w - 1; $x ) {
self::putAlignmentMarker($frame, 6, $cx);
self::putAlignmentMarker($frame, $cx, 6);
$cx = $d;
}
$cy = self::$alignmentPattern[$version][0];
for($y=0; $y<$w-1; $y ) {
$cx = self::$alignmentPattern[$version][0];
for($x=0; $x<$w-1; $x ) {
self::putAlignmentMarker($frame, $cx, $cy);
$cx = $d;
}
$cy = $d;
}
}
public static $versionPattern = array(
0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
0x0f928, 10b78、0x1145d、0x12a17、0x13532、 0x149a6、0x15683、0x168c9、
0x177ec、0x18ec4、0x191e1、0x1afab、0x1b08e、0x1cc1a、0x1d33f、0x1ed75、
0x1f250、0x209d5、0 x216f0、0x228ba、0x2379f、0x24b0b、0x2542e、0x26a64、
0x27541、0x28c69
);
public static function getVersionPattern($version){
if($version < 7 || $version > QRSPEC_VERSION_MAX)
return 0;
return self::$versionPattern[$version -7];
}
// フォーマット情報 -------------------------------------- -----------
// testing/test_qrspec.c の calcFormatInfo を参照 (オリジナルの qrencode C lib)
public static $formatInfo = array(
array(0x77c4, 0x72f3, 0x7daa) 、0x789d、0x662f、0x6318、0x6c41、0x6976)、
配列(0x5412、0x5125、0x5e7c、0x5b4b、0x45f9、0x40ce、0x4f97、0x4aa0)、 0x355f、0x3068、0x3f31、0x3a06、0x24b4、0x2183 、0x2eda、0x2bed)、
array(0x1689、0x13be、0x1ce7、0x19d0、0x0762、0x0255、0x0d0c、0x083b)
);
public static function getFormatInfo($mask, $level){
if($mask 7)
return 0;
if($level 3)
return 0;
return self::$formatInfo[$level][$mask];
}
// フレーム -------------------------------------- -----------------------
// 初期フレームのキャッシュ。
パブリック静的 $frames = array();
public static function putFinderPattern(&$frame, $ox, $oy){
$finder = array(
"xc1xc1xc1xc1xc1xc1xc1",
"xc1xc0xc0xc0xc0xc0xc1",
"xc1xc0xc1xc1xc1 xc0xc1"、
"xc1xc0xc1xc1xc1xc0xc1"、
"xc1xc0xc1xc1xc1xc0xc1"、
"xc1xc0xc0xc0xc0xc0xc1"、
"xc1xc1xc1xc1xc1xc1xc1"
);
for($y=0; $yQRstr::set($frame, $ox, $oy $y, $finder[$y]);
}
}
public static function createFrame($version){
$width = self::$capacity[$version][QRCAP_WIDTH];
$frameLine = str_repeat (" ", $width);
$frame = array_fill(0, $width, $frameLine);
// ファインダーパターン
self::putFinderPattern($frame, 0, 0);
self::putFinderPattern($frame, $width - 7, 0);
self::putFinderPattern($frame, 0, $width - 7);
// 区切り文字
$yOffset = $width - 7;
for($y=0; $y$frame[$y][7] = "xc0";
$frame[$y][$width - 8] = "xc0";
$frame[$yOffset][7] = "xc0";
$yOffset ;
}
$setPattern = str_repeat("xc0", 8);
QRstr::set($frame, 0, 7, $setPattern);
QRstr::set($frame, $width-8, 7, $setPattern);
QRstr::set($frame, 0, $width - 8, $setPattern);
// フォーマット情報
$setPattern = str_repeat("x84", 9);
QRstr::set($frame, 0, 8, $setPattern);
QRstr::set($frame, $width - 8, 8, $setPattern, 8);
$yOffset = $width - 8;
for($y=0; $y$frame[$y][8] = "x84";
$frame[$yOffset][8] = "x84";
}
// タイミング パターン
for($i=1; $i$frame[6][7 $i] = chr(0x90 | ($i & 1));
$frame[7 $i][6] = chr(0x90 | ($i & 1));
}
// 配置パターン
self::putAlignmentPattern($version, $frame, $width);
// バージョン情報
if($version >= 7) {
$vinf = self::getVersionPattern($version);
$v = $vinf;
for($x=0; $xfor($y=0; $y$frame[($width - 11) $y][$x] = chr(0x88 | ($v & 1));
$v = $v >> 1;
}
}
$v = $vinf;
for($y=0; $yfor($x=0; $x$frame[$y][$x ($width - 11)] = chr(0x88 | ($v & 1));
$v = $v >> 1;
}
}
}
// そして少し...
$frame[$width - 8][8] = "x81";
$frame を返します;
}
public static function debug($frame, $binary_mode = false){
if ($binary_mode) {
foreach ($frame as &$frameLine) {
$frameLine = join (' ',explode('0', $frameLine));
$frameLine = join('██',explode('1', $frameLine));
}
<スタイル>
.m {背景色: 白; }

echo '

<tt><br>gt;<br>gt;<br>        '; <br>echo join("<br/ > ", $frame); <br>エコー '</tt>






} else {
foreach ($frame as &$frameLine) {
$frameLine = join(' ',explode("xc0" 、$frameLine));
$frameLine = join('',explode("xc1", $frameLine));
$frameLine = join(' ',explode("xa0", $frameLine));
$frameLine = join('',explode("xa1", $frameLine));
$frameLine = join('',explode("x84", $frameLine)); //フォーマット 0
$frameLine = join('',explode("x85", $frameLine)); //形式 1
$frameLine = join('',explode("x81", $frameLine)); //特別なビット
$frameLine = join(' ',explode("x90", $frameLine)); //クロック 0
$frameLine = join('',explode("x91", $frameLine)); //クロック 1
$frameLine = join(' ',explode("x88", $frameLine)); //バージョン
$frameLine = join('',explode("x89", $frameLine)); //バージョン
$frameLine = join('♦',explode("x01", $frameLine));
$frameLine = join('⋅',explode(" ", $frameLine));
}
<スタイル>
.p {背景色: 黄色; }
.m {背景色: #00FF00; }
.s {背景色: #FF0000; }
.c {背景色: アクア; }
.x {背景色: ピンク; }
.f {背景色: ゴールド; }

echo "
<tt>"; <br>echo join("<br/ >", $frame); <br>エコー "</tt>
";
}
}
パブリック静的関数 Serial($frame){
return gzcompress(join("n", $frame), 9);
}
public static function unserial($code){
returnexplode("n", gzuncompress($code));
}
public static function newFrame($version){
if($version < 1 || $version > QRSPEC_VERSION_MAX)
return null;
if(!isset(self::$frames[$version])) {
$fileName = QR_CACHE_DIR.'frame_'.$version.'.dat';
if (QR_CACHEABLE) {
if (file_exists($fileName)) {
self::$frames[$version] = self::unserial(file_get_contents($fileName));
} else {
self::$frames[$version] = self::createFrame($version);
file_put_contents($fileName, self::serial(self::$frames[$version]));
}
} else {
self::$frames[$version] = self::createFrame($version);
}
}
if(is_null(self::$frames[$version]))
return null;
return self::$frames[$version];
}
パブリック静的関数 rsBlockNum($spec) { return $spec[0] $spec[3]; }
パブリック静的関数 rsBlockNum1($spec) { return $spec[0]; }
パブリック静的関数 rsDataCodes1($spec) { return $spec[1]; }
パブリック静的関数 rsEccCodes1($spec) { return $spec[2]; }
パブリック静的関数 rsBlockNum2($spec) { return $spec[3]; }
パブリック静的関数 rsDataCodes2($spec) { return $spec[4]; }
パブリック静的関数 rsEccCodes2($spec) { return $spec[2]; }
public static function rsDataLength($spec) { return ($spec[0] * $spec[1]) ($spec[3] * $spec[4]); }
パブリック静的関数 rsEccLength($spec) { return ($spec[0] $spec[3]) * $spec[2];
}
define('QR_IMAGE', true);
class QRimage {
public static function png($frame, $filename = false, $pixelPerPoint = 4, $outerFrame = 4,$saveandprint=FALSE){
$image = self::image($フレーム、$pixelPerPoint、$outerFrame);
if ($filename === false) {
Header("Content-type: image/png");
ImagePng($image);
} else {
if($saveandprint===TRUE){
ImagePng($image, $filename);
header("Content-type: image/png");
ImagePng($image);
}else{
ImagePng($image, $filename);
}
}
ImageDestroy($image);
}
パブリック静的関数 jpg($frame, $filename = false, $pixelPerPoint = 8, $outerFrame = 4, $q = 85){
$image = self::image($frame, $pixelPerPoint、$outerFrame);
if ($filename === false) {
Header("Content-type: image/jpeg");
ImageJpeg($image, null, $q);
} else {
ImageJpeg($image, $filename, $q);
}
ImageDestroy($image);
}
プライベート静的関数 image($frame, $pixelPerPoint = 4, $outerFrame = 4){
$h = count($frame);
$w = strlen($frame[0]);
$imgW = $w 2*$outerFrame;
$imgH = $h 2*$outerFrame;
$base_image =ImageCreate($imgW, $imgH);
$col[0] = ImageColorAllocate($base_image,255,255,255);
$col[1] = ImageColorAllocate($base_image,0,0,0);
imagefill($base_image, 0, 0, $col[0]);
for($y=0; $yfor($x=0; $xif ($frame[$y ][$x] == '1') {
ImageSetPixel($base_image,$x $outerFrame,$y $outerFrame,$col[1]);
}
}
}
$target_image =ImageCreate($imgW * $pixelPerPoint, $imgH * $pixelPerPoint);
ImageCopyResize($target_image, $base_image, 0, 0, 0, 0, $imgW * $pixelPerPoint, $imgH * $pixelPerPoint, $imgW, $imgH);
ImageDestroy($base_image);
$target_image を返す;
}
}
define('STRUCTURE_HEADER_BITS', 20);
define('MAX_STRUCTURED_SYMBOLS', 16);
class QRinputItem {
public $mode;
パブリック $size;
パブリック $data;
パブリック $bstream;
パブリック関数 __construct($mode, $size, $data, $bstream = null){
$setData = array_slice($data, 0, $size);
if (count($setData) $setData = array_merge($setData, array_fill(0,$size-count($setData),0));
}
if(!QRinput::check($mode, $size, $setData)) {
throw new Exception('Error m:'.$mode.',s:'.$size .',d:'.join(',',$setData));
null を返します。
}
$this->mode = $mode;
$this->size = $size;
$this->data = $setData;
$this->bstream = $bstream;
}
public function encodeModeNum($version){
try {
$words = (int)($this->size / 3);
$bs = 新しい QRbitstream();
$val = 0x1;
$bs->appendNum(4, $val);
$bs->appendNum(QRspec::lengthIndicator(QR_MODE_NUM, $version), $this->size);
for($i=0; $i$val = (ord($this->data[$i*3 ]) - ord('0')) * 100;
$val = (ord($this->data[$i*3 1]) - ord('0')) * 10;
$val = (ord($this->data[$i*3 2]) - ord('0'));
$bs->appendNum(10, $val);
}
if($this->size - $words * 3 == 1) {
$val = ord($this->data[$words*3]) - ord(' 0');
$bs->appendNum(4, $val);
} else if($this->size - $words * 3 == 2) {
$val = (ord($this->data[$words*3 ]) - ord('0 ')) * 10;
$val = (ord($this->data[$words*3 1]) - ord('0'));
$bs->appendNum(7, $val);
}
$this->bstream = $bs;
0 を返す;
} catch (Exception $e) {
return -1;
}
}
public function encodeModeAn($version){
try {
$words = (int)($this->size / 2);
$bs = 新しい QRbitstream();
$bs->appendNum(4, 0x02);
$bs->appendNum(QRspec::lengthIndicator(QR_MODE_AN, $version), $this->size);
for($i=0; $i$val = (int)QRinput::lookAnTable(ord($this->data[$i*2 ])) * 45;
$val = (int)QRinput::lookAnTable(ord($this->data[$i*2 1]));
$bs->appendNum(11, $val);
}
if($this->size & 1) {
$val = QRinput::lookAnTable(ord($this->data[$words * 2]));
$bs->appendNum(6, $val);
}
$this->bstream = $bs;
0 を返す;
} catch (Exception $e) {
return -1;
}
}
public function encodeMode8($version){
try {
$bs = new QRbitstream();
$bs->appendNum(4, 0x4);
$bs->appendNum(QRspec::lengthIndicator(QR_MODE_8, $version), $this->size);
for($i=0; $isize; $i ) {
$bs->appendNum(8, ord($this->data[$i])) ;
}
$this->bstream = $bs;
0 を返す;
} catch (Exception $e) {
return -1;
}
}
public function encodeModeKanji($version){
try {
$bs = new QRbitrtream();
$bs->appendNum(4, 0x8);
$bs->appendNum(QRspec::lengthIndicator(QR_MODE_KANJI, $version), (int)($this->size / 2));
for($i=0; $isize; $i =2) {
$val = (ord($this->data[$i]) << 8) | ord($this->data[$i 1]);
if($val <= 0x9ffc) {
$val -= 0x8140;
} else {
$val -= 0xc140;
}
$h = ($val >> 8) * 0xc0;
$val = ($val & 0xff) $h;
$bs->appendNum(13, $val);
}
$this->bstream = $bs;
0 を返す;
} catch (Exception $e) {
return -1;
}
}
public function encodeModeStructure(){
try {
$bs = new QRbitstream();
$bs->appendNum(4, 0x03);
$bs->appendNum(4, ord($this->data[1]) - 1);
$bs->appendNum(4, ord($this->data[0]) - 1);
$bs->appendNum(8, ord($this->data[2]));
$this->bstream = $bs;
0 を返す;
} catch (Exception $e) {
return -1;
}
}
パブリック関数estimateBitStreamSizeOfEntry($version){
$bits = 0;
if($version == 0)
$version = 1;
switch($this->mode) {
case QR_MODE_NUM: $bits = QRinput::estimateBitsModeNum($this->size);壊す;
case QR_MODE_AN: $bits = QRinput::estimateBitsModeAn($this->size);壊す;
case QR_MODE_8: $bits = QRinput::estimateBitsMode8($this->size);壊す;
case QR_MODE_KANJI: $bits = QRinput::estimateBitsModeKanji($this->size);break;
QR_MODE_STRUCTURE の場合: STRUCTURE_HEADER_BITS を返します。
デフォルト:
0 を返します。
}
$l = QRspec::lengthIndicator($this->mode, $version);
$m = 1 << $l;
$num = (int)(($this->size $m - 1) / $m);
$bits = $num * (4 $l);
$bits を返します;
}
public function encodeBitStream($version){
try {
unset($this->bstream);
$words = QRspec::maximumWords($this->mode, $version);
if($this->size > $words) {
$st1 = new QRinputItem($this->mode, $words, $this->data);
$st2 = new QRinputItem($this->mode, $this->size - $words, array_slice($this->data, $words));
$st1->encodeBitStream($version);
$st2->encodeBitStream($version);
$this->bstream = new QRbitstream();
$this->bstream->append($st1->bstream);
$this->bstream->append($st2->bstream);
設定を解除($st1);
設定を解除($st2);
} else {
$ret = 0;
switch($this->mode) {
case QR_MODE_NUM: $ret = $this->encodeModeNum($version);壊す;
case QR_MODE_AN: $ret = $this->encodeModeAn($version);壊す;
case QR_MODE_8: $ret = $this->encodeMode8($version);壊す;
case QR_MODE_KANJI: $ret = $this->encodeModeKanji($version);break;
case QR_MODE_STRUCTURE: $ret = $this->encodeModeStructure();壊す;
デフォルト:
ブレーク;
}
if($ret return -1;
}
return $this->bstream->size();
} catch (Exception $e) {
return -1;
}
}
};
class QRinput {
public $items;
プライベート $バージョン;
プライベート $レベル;
public function __construct($version = 0, $level = QR_ECLEVEL_L){
if ($version < 0 || $version > QRSPEC_VERSION_MAX || $level > QR_ECLEVEL_H) {
新しい例外をスローする('無効なバージョン番号');
NULL を返します。
}
$this->version = $version;
$this->level = $level;
}
public function getVersion(){
return $this->version;
}
public function setVersion($version){
if($version < 0 || $version > QRSPEC_VERSION_MAX) {
throw new Exception('無効なバージョン番号');
-1 を返す;
}
$this->version = $version;
0 を返す;
}
public function getErrorCorrectionLevel(){
return $this->level;
}
public function setErrorCorrectionLevel($level){
if($level > QR_ECLEVEL_H) {
throw new Exception('Invalid ECLEVEL');
-1 を返す;
}
$this->level = $level;
0 を返す;
}
public function appendEntry(QRinputItem $entry){
$this->items[] = $entry;
}
public function append($mode, $size, $data){
try {
$entry = new QRinputItem($mode, $size, $data);
$this->items[] = $entry;
0 を返す;
} catch (Exception $e) {
return -1;
}
}
public function insertStructuredAppendHeader($size, $index, $parity){
if( $size > MAX_STRUCTURED_SYMBOLS ) {
throw new Exception('insertStructuredAppendHeader のサイズが間違っています') ;
}
if( $index throw new Exception('insertStructuredAppendHeader 間違ったインデックス');
}
$buf = array($size, $index, $parity);
try {
$entry = new QRinputItem(QR_MODE_STRUCTURE, 3, buf);
array_unshift($this->items, $entry);
0 を返す;
} catch (Exception $e) {
return -1;
}
}
パブリック関数 calcParity(){
$parity = 0;
foreach($this->items as $item) {
if($item->mode != QR_MODE_STRUCTURE) {
for($i=$item->size-1; $ i>=0; $i--) {
$parity ^= $item->data[$i];
}
}
}
return $parity;
}
パブリック静的関数 checkModeNum($size, $data){
for($i=0; $iif((ord($data[ $i]) < ord('0')) || (ord($data[$i]) > ord('9')){
return false;
}
}
true を返します。
}
パブリック静的関数estimateBitsModeNum($size){
$w = (int)$size / 3;
$bits = $w * 10;
switch($size - $w * 3) {
ケース 1:
$bits = 4;
休憩;
ケース 2:
$bits = 7;
休憩;
デフォルト:
ブレーク;
}
$bits を返します。
}
public static $anTable = array(
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 1、-1、-1、-1、
-1、-1、-1、-1、-1、-1、-1、-1、-1、-1、-1、-1、 -1、-1、-1、-1、
36、-1、-1、-1、37、38、-1、-1、-1、-1、39、40、-1、41 、42、43、
0、1、2、3、4、5、6、7、8、9、44、-1、-1、-1、-1、-1、
-1 、10、11、12、13、14、15、16、17、18、19、20、21、22、23、24、
25、26、27、28、29、30、31、32、 33、34、35、-1、-1、-1、-1、-1、
-1、-1、-1、-1、-1、-1、-1、-1、-1 、-1、-1、-1、-1、-1、-1、-1、
-1、-1、-1、-1、-1、-1、-1、-1、- 1、-1、-1、-1、-1、-1、-1、-1
);
public static function lookAnTable($c){
return (($c > 127)?-1:self::$anTable[$c]);
}
public static function checkModeAn($size, $data){
for($i=0; $iif (self::lookAnTable(ord) ($data[$i])) == -1) {
return false;
}
}
true を返します。
}
パブリック静的関数estimateBitsModeAn($size){
$w = (int)($size / 2);
$bits = $w * 11;
if($size & 1) {
$bits = 6;
}
$bits を返します。
}
パブリック静的関数estimateBitsMode8($size){
return $size * 8;
}
パブリック関数estimateBitsModeKanji($size){
return (int)(($size / 2) * 13);
}
パブリック静的関数 checkModeKanji($size, $data){
if($size & 1)
return false;
for($i=0; $i$val = (ord($data[$i]) << 8) | ord($data[$i 1]);
if( $val < 0x8140
|| ($val > 0x9ffc && $val < 0xe040)
|| $val > 0xebbf) {
return false;
}
}
true を返します。
}
public static function check($mode, $size, $data){
if($size <= 0)
return false;
switch($mode) {
case QR_MODE_NUM: return self::checkModeNum($size, $data);壊す;
case QR_MODE_AN: return self::checkModeAn($size, $data);壊す;
case QR_MODE_KANJI: return self::checkModeKanji($size, $data);壊す;
QR_MODE_8 の場合: true を返します。壊す;
QR_MODE_STRUCTURE の場合: true を返します。壊す;
デフォルト:
ブレーク;
}
false を返します。
}
パブリック関数estimateBitStreamSize($version){
$bits = 0;
foreach($this->items as $item) {
$bits = $item->estimateBitStreamSizeOfEntry($version);
}
$bits を返します。
}
パブリック関数estimateVersion(){
$version = 0;
$prev = 0;
do {
$prev = $version;
$bits = $this->estimateBitStreamSize($prev);
$version = QRspec::getMinimumVersion((int)(($bits 7) / 8), $this->level);
if ($version < 0) {
return -1;
}
} while ($version > $prev);
$version を返します;
}
public static function lengthOfCode($mode, $version, $bits){
$payload = $bits - 4 - QRspec::lengthIndicator($mode, $version);
switch($mode) {
case QR_MODE_NUM:
$chunks = (int)($payload / 10);
$remain = $payload - $chunks * 10;
$size = $chunks * 3;
if($remain >= 7) {
$size = 2;
} else if($remain >= 4) {
$size = 1;
}
休憩;
ケース QR_MODE_AN:
$chunks = (int)($payload / 11);
$remain = $payload - $chunks * 11;
$size = $chunks * 2;
if($remain >= 6)
$size ;
休憩;
ケース QR_MODE_8:
$size = (int)($payload / 8);
休憩;
case QR_MODE_KANJI:
$size = (int)(($payload / 13) * 2);
休憩;
ケース QR_MODE_STRUCTURE:
$size = (int)($payload / 8);
休憩;
デフォルト:
$size = 0;
休憩;
}
$maxsize = QRspec::maximumWords($mode, $version);
if($size if($size > $maxsize) $size = $maxsize;
$size を返します;
}
パブリック関数 createBitStream(){
$total = 0;
foreach($this->items as $item) {
$bits = $item->encodeBitStream($this->version);
if($bits return -1;
$total = $bits;
}
$total を返す;
}
パブリック関数 ConvertData(){
$ver = $this->estimateVersion();
if($ver > $this->getVersion()) {
$this->setVersion($ver);
}
for(;;) {
$bits = $this->createBitStream();
if($bits return -1;
$ver = QRspec::getMinimumVersion((int)(($bits 7) / 8), $this->level);
if($ver < 0) {
throw new Exception('WRONG VERSION');
-1 を返す;
} else if($ver > $this->getVersion()) {
$this->setVersion($ver);
} else {
ブレーク;
}
}
0 を返す;
}
public function appendPaddingBit(&$bstream){
$bits = $bstream->size();
$maxwords = QRspec::getDataLength($this->version, $this->level);
$maxbits = $maxwords * 8;
if ($maxbits == $bits) {
return 0;
}
if ($maxbits - $bits return $bstream->appendNum($maxbits - $bits, 0);
}
$ビット = 4;
$words = (int)(($bits 7) / 8);
$padding = 新しい QRbitstream();
$ret = $padding->appendNum($words * 8 - $bits 4, 0);
if($ret return $ret;
$padlen = $maxwords - $words;
if($padlen > 0) {
$padbuf = array();
for($i=0; $i$padbuf[$i] = ($i&1)?0x11:0xec;
}
$ret = $padding->appendBytes($padlen, $padbuf);
if($ret return $ret;
}
$ret = $bstream->append($padding);
$ret を返す;
}
public function mergeBitStream(){
if($this->convertData() return null;
}
$bstream = 新しい QRbitstream();
foreach($this->items as $item) {
$ret = $bstream->append($item->bstream);
if($ret null を返す;
}
}
return $bstream;
}
パブリック関数 getBitStream(){
$bstream = $this->mergeBitStream();
if($bstream == null) {
return null;
}
$ret = $this->appendPaddingBit($bstream);
if($ret null を返す;
}
return $bstream;
}
パブリック関数 getByteStream(){
$bstream = $this->getBitStream();
if($bstream == null) {
return null;
}
return $bstream->toByte();
}
}
class QRbitstream {
public $data = array();
パブリック関数 size(){
return count($this->data);
}
public function assign($setLength){
$this->data = array_fill(0, $setLength, 0);
0 を返す;
}
パブリック静的関数 newFromNum($bits, $num){
$bstream = new QRbitstream();
$bstream->allocate($bits);
$マスク = 1 << ($bits - 1);
for($i=0; $i<$bits; $i ) {
if($num & $mask) {
$bstream->data[$i] = 1;
} else {
$bstream->data[$i] = 0;
}
$mask = $mask >> 1;
}
return $bstream;
}
パブリック静的関数 newFromBytes($size, $data){
$bstream = new QRbitstream();
$bstream->allocate($size * 8);
$p=0;
for($i=0; $i$mask = 0x80;
for($j=0; $jif($data[$i] & $mask) {
$bstream->data[$p] = 1 ;
} else {
$bstream->data[$p] = 0;
}
$p ;
$マスク = $マスク>> 1;
}
}
return $bstream;
}
public function append(QRbitstream $arg){
if (is_null($arg)) {
return -1;
}
if($arg->size() == 0) {
return 0;
}
if($this->size() == 0) {
$this->data = $arg->data;
0 を返す;
}
$this->data = array_values(array_merge($this->data, $arg->data));
0 を返す;
}
public function appendNum($bits, $num){
if ($bits == 0)
return 0;
$b = QRbitstream::newFromNum($bits, $num);
if(is_null($b))
return -1;
$ret = $this->append($b);
設定を解除($b);
$ret を返す;
}
public function appendBytes($size, $data){
if ($size == 0)
return 0;
$b = QRbitstream::newFromBytes($size, $data);
if(is_null($b))
return -1;
$ret = $this->append($b);
設定を解除($b);
$ret を返す;
}
パブリック関数 toByte(){
$size = $this->size();
if($size == 0) {
return array();
}
$data = array_fill(0, (int)(($size 7) / 8), 0);
$bytes = (int)($size / 8);
$p = 0;
for($i=0; $i$v = 0;
for($j=0; $j$v = $v << 1;
$v |= $this->data[$p];
$p ;
}
$data[$i] = $v;
}
if($size & 7) {
$v = 0;
for($j=0; $j<($size & 7); $j ) {
$v = $v << 1;
$v |= $this->data[$p];
$p ;
}
$data[$bytes] = $v;
}
$data を返します。
}
}
class QRsplit {
public $dataStr = '';
パブリック $input;
パブリック $modeHint;
パブリック関数 __construct($dataStr, $input, $modeHint){
$this->dataStr = $dataStr;
$this->input = $input;
$this->modeHint = $modeHint;
}
public static function isdigitalat($str, $pos){
if ($pos >= strlen($str))
return false;
return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) }
public static function isalnumat($str, $pos){
if ($pos >= strlen($str))
return false;
return (QRinput::lookAnTable(ord($str[$pos])) >= 0);
}
public functionidentifyMode($pos){
if ($pos >= strlen($this->dataStr))
return QR_MODE_NUL;
$c = $this->dataStr[$pos];
if(self::isdigitalat($this->dataStr, $pos)) {
return QR_MODE_NUM;
} else if(self::isalnutat($this->dataStr, $pos)) {
return QR_MODE_AN;
}else if($this->modeHint == QR_MODE_KANJI) {
if ($pos 1 < strlen($this->dataStr))
{
$d = $this->dataStr [$pos 1];
$word = (ord($c) << 8) | ord($d);
if(($word >= 0x8140 && $word <= 0x9ffc) || ($word >= 0xe040 && $word <= 0xebbf)) {
return QR_MODE_KANJI;
}
}
}
QR_MODE_8 を返す;
}
public function EatNum(){
$ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
$p = 0;
while(self::isdigitalat($this->dataStr, $p)) {
$p ;
}
$run = $p;
$mode = $this->identifyMode($p);
if($mode == QR_MODE_8) {
$dif = QRinput::estimateBitsModeNum($run) 4 $ln
QRinput::estimateBitsMode8(1) // 4 l8
- QRinput:: estimateBitsMode8($run 1); // - 4 - l8
if($dif > 0) {
return $this->eat8();
}
}
if($mode == QR_MODE_AN) {
$dif = QRinput::estimateBitsModeNum($run) 4 $ln
QRinput::estimateBitsModeAn(1) // 4 la
- QRinput::estimateBitsModeAn($run 1);// - 4 - la
if($dif > 0) {
return $this->eatAn();
}
}
$ret = $this->input->append(QR_MODE_NUM, $run, str_split($this->dataStr));
if($ret < 0)
return -1;
$run を返す;
}
public function EatAn(){
$la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion());
$ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
$p = 0;
while(self::isalumat($this->dataStr, $p)) {
if(self::isdigitalat($this->dataStr, $p)) {
$q = $p;
while(self::isdigitalat($this->dataStr, $q)) {
$q ;
}
$dif = QRinput::estimateBitsModeAn($p) // 4 la
QRinput::estimateBitsModeNum($q - $p) 4 $ln
- QRinput::estimateBitsModeAn($q) ); // - 4 - la
if($dif <0) {
break;
} else {
$p = $q;
}
} else {
$p ;
}
}
$run = $p;
if(!self::isalnutat($this->dataStr, $p)) {
$dif = QRinput::estimateBitsModeAn($run) 4 $la
QRinput::estimateBitsMode8(1) // 4 l8
- QRinput::estimateBitsMode8($run 1); // - 4 - l8
if($dif > 0) {
return $this->eat8();
}
}
$ret = $this->input->append(QR_MODE_AN, $run, str_split($this->dataStr));
if($ret < 0)
return -1;
$run を返す;
}
パブリック関数 EatKanji(){
$p = 0;
while($this->identifyMode($p) == QR_MODE_KANJI) {
$p = 2;
}
$ret = $this->input->append(QR_MODE_KANJI, $p, str_split($this->dataStr));
if($ret < 0)
return -1;
$run を返す;
}
public function Eat8(){
$la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion());
$ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
$p = 1;
$dataStrLen = strlen($this->dataStr);
while($p < $dataStrLen) {
$mode = $this->identifyMode($p);
if($mode == QR_MODE_KANJI) {
ブレーク;
}
if($mode == QR_MODE_NUM) {
$q = $p;
while(self::isdigitalat($this->dataStr, $q)) {
$q ;
}
$dif = QRinput::estimateBitsMode8($p) // 4 l8
QRinput::estimateBitsModeNum($q - $p) 4 $ln
- QRinput::estimateBitsMode8($q) ); // - 4 - l8
if($dif < 0) {
break;
} else {
$p = $q;
}
} else if($mode == QR_MODE_AN) {
$q = $p;
while(self::isalnutat($this->dataStr, $q)) {
$q ;
}
$dif = QRinput::estimateBitsMode8($p) // 4 l8
QRinput::estimateBitsModeAn($q - $p) 4 $la
- QRinput::estimateBitsMode8($q) ); // - 4 - l8
if($dif < 0) {
break;
} else {
$p = $q;
}
} else {
$p ;
}
}
$run = $p;
$ret = $this->input->append(QR_MODE_8, $run, str_split($this->dataStr));
if($ret < 0)
return -1;
$run を返す;
}
public function splitString(){
while (strlen($this->dataStr) > 0)
{
if($this->dataStr == '' )
0 を返す;
$mode = $this->identifyMode(0);
switch ($mode) {
case QR_MODE_NUM: $length = $this->eatNum();壊す;
ケース QR_MODE_AN: $length = $this->eatAn();壊す;
case QR_MODE_KANJI:
if ($hint == QR_MODE_KANJI)
$length = $this->eatKanji();
else $length = $this->eat8();
休憩;
デフォルト: $length = $this->eat8();壊す;
}
if($length == 0) 0 を返します。
if($length < 0) は -1 を返します。
$this->dataStr = substr($this->dataStr, $length);
}
}
パブリック関数 toUpper(){
$stringLen = strlen($this->dataStr);
$p = 0;
while ($p<$stringLen) {
$mode = self::identifyMode(substr($this->dataStr, $p), $this->modeHint);
if($mode == QR_MODE_KANJI) {
$p = 2;
} else {
if (ord($this->dataStr[$p]) >= ord('a') && ord($this->dataStr[$p]) <= ord('z')) {
$this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32);
}
$p ;
}
}
return $this->dataStr;
}
public static function splitStringToQRinput($string, QRinput $input, $modeHint, $casesensitive = true){
if(is_null($string) || $string == ' ' || $string == '') {
新しい例外をスローします('空の文字列!!!');
}
$split = new QRsplit($string, $input, $modeHint);
if(!$casesensitive)
$split->toUpper();
return $split->splitString();
}
}
class QRrsItem {
public $mm; // シンボルあたりのビット数
public $nn; // ブロックごとのシンボル数 (= (1<public $alpha_to = array(); // ログ検索テーブル
public $index_of = array(); // 逆対数ルックアップ テーブル
public $genpoly = array(); // 生成多項式
public $nroots; // ジェネレーターのルートの数 = パリティ シンボルの数
public $fcr; // 最初の連続したルート、インデックス形式
public $prim; // プリミティブ要素、インデックス形式
public $iprim; // 1 の主根、インデックス形式
public $pad; // 短縮されたブロックにバイトを埋め込みます
public $gfpoly;
public function modnn($x){
while ($x >= $this->nn) {
$x -= $this->nn;
$x = ($x >> $this->mm) ($x & $this->nn);
}
$x を返す;
}
public static function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad){
// リードソロモン制御ブロックを初期化するための共通コード (char または int)記号)
// Copyright 2004 Phil Karn, KA9Q
// GNU Lesser General Public License (LGPL) の条件に基づいて使用できます
$rs = null;
// パラメータの範囲を確認します
if($symssize < 0 || $shmsize > 8) return $rs;
if($fcr < 0 || $fcr >= (1<<$shmsize)) return $rs;
if($prim <= 0 || $prim >= (1<<$shmsize)) return $rs;
if($nroots < 0 || $nroots >= (1<<$shmsize)) return $rs; // シンボル値より多くのルートを持つことはできません。
if($pad < 0 || $pad >= ((1<<$sonymize) -1 - $nroots)) return $rs; // パディングが多すぎます
$rs = new QRrsItem();
$rs->mm = $shmsize;
$rs->nn = (1<<$sonymsize)-1;
$rs->pad = $pad;
$rs->alpha_to = array_fill(0, $rs->nn 1, 0);
$rs->index_of = array_fill(0, $rs->nn 1, 0);
// PHP スタイルのマクロ置換 ;)
$NN =& $rs->nn;
$A0 =& $NN;
// ガロア体ルックアップ テーブルを生成します
$rs->index_of[0] = $A0; // log(zero) = -inf
$rs->alpha_to[$A0] = 0; // alpha**-inf = 0
$sr = 1;
for($i=0; $i<$rs->nn; $i ) {
$rs->index_of[$sr] = $i;
$rs->alpha_to[$i] = $sr;
$sr <<= 1;
if($sr & (1<<$sonymsize)) {
$sr ^= $gfpoly;
}
$sr &= $rs->nn;
}
if($sr != 1){
// 場生成多項式は原始的ではありません!
$rs = NULL;
$rs を返します;
}
/* RS コード生成多項式を根から作成します */
$rs->genpoly = array_fill(0, $nroots 1, 0);
$rs->fcr = $fcr;
$rs->prim = $prim;
$rs->nroots = $nroots;
$rs->gfpoly = $gfpoly;
/* デコードに使用される 1 の主根を検索します */
for($iprim=1;($iprim % $prim) != 0;$iprim = $rs->nn)
; // 意図的な空のループ!
$rs->iprim = (int)($iprim / $prim);
$rs->genpoly[0] = 1;
for ($i = 0,$root=$fcr*$prim; $i <$nroots; $i , $root = $prim) {
$rs->genpoly[$i 1] = 1;
// rs->genpoly[] に @**(root x) を掛けます
for ($j = $i; $j > 0; $j--) {
if ($ rs->genpoly[$j] != 0) {
$rs->genpoly[$j] = $rs->genpoly[$j-1] ^ $rs->alpha_to[$rs ->modnn($rs->index_of[$rs->genpoly[$j]] $root)];
} else {
$rs->genpoly[$j] = $rs->genpoly[$j-1];
}
}
// rs->genpoly[0] をゼロにすることはできません
$rs->genpoly[0] = $rs->gt;alpha_to[$rs->> modnn($rs->index_of[$rs->genpoly[0]] $root)];
}
// rs->genpoly[] をインデックス形式に変換してエンコードを高速化します
for ($i = 0; $i <= $nroots; $i )
$rs- >genpoly[$i] = $rs->index_of[$rs->genpoly[$i]];
$rs を返します;
}
パブリック関数 encode_rs_char($data, &$parity){
$MM =& $this->mm;
$NN =& $this->nn;
$ALPHA_TO =& $this->alpha_to;
$INDEX_OF =& $this->index_of;
$GENPOLY =& $this->genpoly;
$NROOTS =& $this->nroots;
$FCR =& $this->fcr;
$PRIM =& $this->プリム;
$IPRIM =& $this->iprim;
$PAD =& $this->パッド;
$A0 =& $NN;
$parity = array_fill(0, $NROOTS, 0);
for($i=0; $i$フィードバック = $INDEX_OF[$data[$i] ^ $parity[0]] ;
if($フィードバック != $A0) {
// フィードバック項はゼロ以外です
// GENPOLY[NROOTS] が 1 の場合、常に
// でなければならないため、この行は不要ですinit_rs()
$フィードバック = $this->modnn($NN - $GENPOLY[$NROOTS] $フィードバック); によって構築された多項式の場合です。
for($j=1;$j$parity[$j] ^= $ALPHA_TO[$this->modnn($フィードバック $GENPOLY[$NROOTS-$ j])];
}
}
// シフト
array_shift($parity);
if($フィードバック != $A0) {
array_push($parity, $ALPHA_TO[$this->modnn($フィードバック $GENPOLY[0])]);
} else {
array_push($parity, 0);
}
}
}
}
class QRrs {
public static $items = array();
パブリック静的関数 init_rs($sonymize, $gfpoly, $fcr, $prim, $nroots, $pad){
foreach(self::$items as $rs) {
if($rs- >pad != $pad) 続行;
if($rs->nroots != $nroots) 続行;
if($rs->mm != $shmsize) 続行;
if($rs->gfpoly != $gfpoly) 続行;
if($rs->fcr != $fcr) 続行;
if($rs->prim != $prim) 続行;
$rs を返します;
}
$rs = QRrsItem::init_rs_char($shmsize, $gfpoly, $fcr, $prim, $nroots, $pad);
array_unshift(self::$items, $rs);
$rs を返します;
}
}
define('N1', 3);
define('N2', 3);
define('N3', 40);
define('N4', 10);
class QRmask {
public $runLength = array();
//------------------------------------------ -------------------------
public function __construct(){
$this->runLength = array_fill(0, QRSPEC_WIDTH_MAX 1) 、0);
}
public function writeFormatInformation($width, &$frame, $mask, $level){
$blacks = 0;
$format = QRspec::getFormatInfo($mask, $level);
for($i=0; $iif($format & 1) {
$blacks = 2;
$v = 0x85;
} else {
$v = 0x84;
}
$frame[8][$width - 1 - $i] = chr($v);
if($i $frame[$i][8] = chr($v);
} else {
$frame[$i 1][8] = chr($v);
}
$format = $format >> 1;
}
for($i=0; $iif($format & 1) {
$blacks = 2;
$v = 0x85;
} else {
$v = 0x84;
}
$frame[$width - 7 $i][8] = chr($v);
if($i == 0) {
$frame[8][7] = chr($v);
} else {
$frame[8][6 - $i] = chr($v);
}
$format = $format >> 1;
}
$blacks を返します。
}
パブリック関数マスク0($x, $y) { return ($x $y)&1;
パブリック関数マスク1($x, $y) { return ($y&1); }
パブリック関数マスク 2($x, $y) { return ($x%3); }
パブリック関数マスク3($x, $y) { return ($x $y)%3;
パブリック関数マスク4($x, $y) { return (((int)($y/2)) ((int)($x/3)))&1;
パブリック関数マスク5($x, $y) { return (($x*$y)&1) ($x*$y)%3;
パブリック関数マスク6($x, $y) { return ((($x*$y)&1) ($x*$y)%3)&1;
パブリック関数マスク7($x, $y) { return ((($x*$y)%3) (($x $y)&1))&1; }
プライベート関数generateMaskNo($maskNo, $width, $frame){
$bitMask = array_fill(0, $width, array_fill(0, $width, 0));
for($y=0; $yfor($x=0; $xif(ord($frame[ $y][$x]) & 0x80) {
$bitMask[$y][$x] = 0;
} else {
$maskFunc = call_user_func(array($this, 'mask'.$maskNo), $x, $y);
$bitMask[$y][$x] = ($maskFunc == 0)?1:0;
}
}
}
return $bitMask;
}
パブリック静的関数 Serial($bitFrame){
$codeArr = array();
foreach ($bitFrame as $line)
$codeArr[] = join('', $line);
return gzcompress(join("n", $codeArr), 9);
}
パブリック静的関数 unserial($code){
$codeArr = array();
$codeLines =explode("n", gzuncompress($code));
foreach ($codeLines as $line)
$codeArr[] = str_split($line);
$codeArr を返す;
}
パブリック関数 makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly = false){
$b = 0;
$bitMask = array();
$fileName = QR_CACHE_DIR.'mask_'.$maskNo.DIRECTORY_SEPARATOR.'mask_'.$width.'_'.$maskNo.'.dat';
if (QR_CACHEABLE) {
if (file_exists($fileName)) {
$bitMask = self::unserial(file_get_contents($fileName));
} else {
$bitMask = $this->generateMaskNo($maskNo, $width, $s, $d);
if (!file_exists(QR_CACHE_DIR.'mask_'.$maskNo))
mkdir(QR_CACHE_DIR.'mask_'.$maskNo);
file_put_contents($fileName, self::serial($bitMask));
}
} else {
$bitMask = $this->generateMaskNo($maskNo, $width, $s, $d);
}
if ($maskGenOnly)
return;
$d = $s;
for($y=0; $yfor($x=0; $xif($bitMask[$y ][$x] == 1) {
$d[$y][$x] = chr(ord($s[$y][$x]) ^ (int)$bitMask[$y][ $x]);
}
$b = (int)(ord($d[$y][$x]) & 1);
}
}
$b を返す;
}
public function makeMask($width, $frame, $maskNo, $level){
$masked = array_fill(0, $width, str_repeat(" ", $width));
$this->makeMaskNo($maskNo, $width, $frame, $masked);
$this->writeFormatInformation($width, $masked, $maskNo, $level);
$masked を返します;
}
パブリック関数 calcN1N3($length){
$デメリット = 0;
for($i=0; $iif($this->runLength[$i] >= 5) {
$デメリット = (N1 ( $this->runLength[$i] - 5));
}
if($i & 1) {
if(($i >= 3) && ($i runLength[ $i] % 3 == 0)) {
$fact = (int)($this->runLength[$i] / 3);
if(($this->runLength[$i-2] == $fact) &&
($this->runLength[$i-1] == $fact) &&
( $this->runLength[$i 1] == $fact) &&
($this->runLength[$i 2] == $fact)) {
if(($this->gt; runLength[$i-3] runLength[$i-3] >= (4 * $fact)) {
$デメリット = N3;
} else if((($i 3) >= $length) || ($this->runLength[$i 3] >= (4 * $fact))) {
$デメリット= N3;
}
}
}
}
}
リターン$デメリット;
}
パブリック関数 EvaluateSymbol($width, $frame){
$head = 0;
$デメリット = 0;
for($y=0; $y$head = 0;
$this->runLength[0] = 1;
$frameY = $frame[$y];
if ($y>0)
$frameYM = $frame[$y-1];
for($x=0; $xif(($x > 0) && ($y > 0)) {
$b22 = ord( $frameY[$x]) & ord($frameY[$x-1]) & ord($frameYM[$x]) & ord($frameYM[$x-1]);
$w22 = ord($frameY[$x]) | ord($frameY[$x-1]) | ord($frameYM[$x]) | ord($frameYM[$x-1]);
if(($b22 | ($w22 ^ 1))&1) {
$デメリット = N2;
}
}
if(($x == 0) && (ord($frameY[$x]) & 1)) {
$this->runLength[0] = - 1;
$head = 1;
$this->runLength[$head] = 1;
} else if($x > 0) {
if((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) {
$頭 ;
$this->runLength[$head] = 1;
} else {
$this->runLength[$head] ;
}
}
}
$デメリット = $this->calcN1N3($head 1);
}
for($x=0; $x$head = 0;
$this->runLength[0] = 1;
for($y=0; $yif($y == 0 && (ord($frame[$y][$x]) & 1)) {
$this->runLength[0] = -1;
$head = 1;
$this->runLength[$head] = 1;
} else if($y > 0) {
if((ord($frame[$y][$x]) ^ ord($frame[$y-1][$x])) & 1) {
$head ;
$this->runLength[$head] = 1;
} else {
$this->runLength[$head] ;
}
}
}
$デメリット = $this->calcN1N3($head 1);
}
$デメリットを返します;
}
パブリック関数マスク($width, $frame, $level){
$minDemerit = PHP_INT_MAX;
$bestMaskNum = 0;
$bestMask = array();
$checked_masks = array(0,1,2,3,4,5,6,7);
if (QR_FIND_FROM_RANDOM !== false) {
$howManuOut = 8-(QR_FIND_FROM_RANDOM % 9);
for ($i = 0; $i $remPos = rand (0, count($checked_masks)-1);
unset($checked_masks[$remPos]);
$checked_masks = array_values($checked_masks);
}
}
$bestMask = $frame;
foreach($checked_masks as $i) {
$mask = array_fill(0, $width, str_repeat(" ", $width));
$デメリット = 0;
$blacks = 0;
$blacks = $this->makeMaskNo($i, $width, $frame, $mask);
$blacks = $this->writeFormatInformation($width, $mask, $i, $level);
$blacks = (int)(100 * $blacks / ($width * $width));
$デメリット = (int)((int)(abs($blacks - 50) / 5) * N4);
$demerit = $this->evaluateSymbol($width, $mask);
if($demerit < $minDemerit) {
$minDemerit = $minDemerit;
$bestMask = $mask;
$bestMaskNum = $i;
}
}
$bestMask を返す;
}
}
class QRrsblock {
public $dataLength;
パブリック $data = array();
パブリック $eccLength;
パブリック $ecc = array();
パブリック関数 __construct($dl, $data, $el, &$ecc, QRrsItem $rs){
$rs->encode_rs_char($data, $ecc);
$this->dataLength = $dl;
$this->data = $data;
$this->eccLength = $el;
$this->ecc = $ecc;
}
};
//############################################# ###########################
class QRrawcode {
public $version;
パブリック $datacode = array();
パブリック $ecccode = array();
パブリック $ブロック;
パブリック $rsblocks = array(); //RSblock の
public $count;
パブリック $dataLength;
パブリック $eccLength;
パブリック $b1;
パブリック関数 __construct(QRinput $input){
$spec = array(0,0,0,0,0);
$this->datacode = $input->getByteStream();
if(is_null($this->datacode)) {
throw new Exception('null input string');
}
QRspec::getEccSpec($input->getVersion(), $input->getErrorCorrectionLevel(), $spec);
$this->version = $input->getVersion();
$this->b1 = QRspec::rsBlockNum1($spec);
$this->dataLength = QRspec::rsDataLength($spec);
$this->eccLength = QRspec::rsEccLength($spec);
$this->ecccode = array_fill(0, $this->eccLength, 0);
$this->blocks = QRspec::rsBlockNum($spec);
$ret = $this->init($spec);
if($ret < 0) {
throw new Exception('ブロック割り当てエラー');
null を返します。
}
$this->count = 0;
}
public function init(array $spec){
$dl = QRspec::rsDataCodes1($spec);
$el = QRspec::rsEccCodes1($spec);
$rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
$blockNo = 0;
$dataPos = 0;
$eccPos = 0;
for($i=0; $i$ecc = array_slice($this->ecccode,$eccPos);
$this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs);
$this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc);
$dataPos = $dl;
$eccPos = $el;
$blockNo ;
}
if(QRspec::rsBlockNum2($spec) == 0)
return 0;
$dl = QRspec::rsDataCodes2($spec);
$el = QRspec::rsEccCodes2($spec);
$rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
if($rs == NULL) は -1 を返します。
for($i=0; $i$ecc = array_slice($this->ecccode,$eccPos);
$this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs);
$this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc);
$dataPos = $dl;
$eccPos = $el;
$blockNo ;
}
0 を返す;
}
パブリック関数 getCode(){
$ret;
if($this->count < $this->dataLength) {
$row = $this->count % $this->blocks;
$col = $this->カウント / $this->ブロック;
if($col >= $this->rsblocks[0]->dataLength) {
$row = $this->b1;
}
$ret = $this->rsblocks[$row]->data[$col];
} else if($this->count < $this->gt;dataLength $this->eccLength) {
$row = ($this->count - $this->dataLength) % $this->ブロック;
$col = ($this->count - $this->dataLength) / $this->blocks;
$ret = $this->rsblocks[$row]->ecc[$col];
} else {
return 0;
}
$this->count ;
$ret を返す;
}
}
クラス QRcode {
public $version;
パブリック $width;
パブリック $data;
public function encodeMask(QRinput $input, $mask){
if($input->getVersion() < 0 || $input->getVersion() > QRSPEC_VERSION_MAX) {
throw new Exception('間違ったバージョン');
}
if($input->getErrorCorrectionLevel() > QR_ECLEVEL_H) {
throw new Exception('wrong level');
}
$raw = 新しい QRrawcode($input);
QRtools::markTime('after_raw');
$version = $raw->version;
$width = QRspec::getWidth($version);
$frame = QRspec::newFrame($version);
$filler = new FrameFiller($width, $frame);
if(is_null($filler)) {
NULL を返す;
}
// インターリーブされたデータと ecc コード
for($i=0; $idataLength $raw->eccLength; $i ) {
$code = $raw->getCode();
$ビット = 0x80;
for($j=0; $j$addr = $filler->next();
$filler->setFrameAt($addr, 0x02 | (($bit & $code) != 0));
$bit = $bit >> 1;
}
}
QRtools::markTime('after_filler');
設定を解除($raw);
// 残りビット
$j = QRspec::getRemainder($version);
for($i=0; $i$addr = $filler->next();
$filler->setFrameAt($addr, 0x02);
}
$frame = $filler->frame;
unset($filler);
// マスキング
$maskObj = new QRmask();
if($mask < 0) {
if (QR_FIND_BEST_MASK) {
$masked = $maskObj->mask($width, $frame, $input->getErrorCorrectionLevel());
} else {
$masked = $maskObj->makeMask($width, $frame, (intval(QR_DEFAULT_MASK) % 8), $input->getErrorCorrectionLevel());
}
}else {
$masked = $maskObj->makeMask($width, $frame, $mask, $input->getErrorCorrectionLevel());
}
if($masked == NULL) {
return NULL;
}
QRtools::markTime('after_mask');
$this->version = $version;
$this->width = $width;
$this->data = $masked;
$this を返します;
}
public function encodeInput(QRinput $input){
return $this->encodeMask($input, -1);
}
public function encodeString8bit($string, $version, $level){
if(string == NULL) {
throw new Exception('empty string!');
NULL を返します。
}
$input = new QRinput($version, $level);
if($input == NULL) NULL を返します。
$ret = $input->append($input, QR_MODE_8, strlen($string), str_split($string));
if($ret unset($input);
NULL を返します。
}
return $this->encodeInput($input);
}
public function encodeString($string, $version, $level, $hint, $casesensitive){
if($hint != QR_MODE_8 && $hint != QR_MODE_KANJI) {
throw new Exception('悪いヒント');
NULL を返します。
}
$input = new QRinput($version, $level);
if($
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。