您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

一个PHP的QRcode类与大家分享_PHP教程

2025/8/12 15:52:11发布23次查看
类的代码:
复制代码 代码如下:
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);
// levels of error correction.
define('qr_eclevel_l', 0);
define('qr_eclevel_m', 1);
define('qr_eclevel_q', 2);
define('qr_eclevel_h', 3);
// supported output formats
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); // use cache - more disk reads but less cpu power, masks and format templates are stored there
define('qr_cache_dir', false); // used when qr_cacheable === true
define('qr_log_dir', false); // default error logs dir
define('qr_find_best_mask', true); // if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code
define('qr_find_from_random', 2); // if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly
define('qr_default_mask', 2); // when qr_find_best_mask === false
define('qr_png_maximum_size', 1024); // maximum allowed png image width (in pixels), tune to make sure gd and php can handle such big images
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;
}
public static function 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;
}
return $barcode_array;
}
public static function clearcache(){
self::$frames = array();
}
public static function buildcache(){
qrtools::marktime('before_build_cache');
$mask = new 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);
}
}
}
}
public static function dumpmask($frame){
$width = count($frame);
for($y=0;$yfor($x=0;$xecho ord($frame[$y][$x]).',';
}
}
}
public static function 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;
}
public static function timebenchmark(){
self::marktime('finish');
$lasttime = 0;
$starttime = 0;
$p = 0;
echo '
benchmark
';
foreach($globals['qr_time_bench'] as $markerid=>$thistime) {
if ($p > 0) {
echo 'till '.$markerid.': '.number_format($thistime-$lasttime, 6).'s
';
} else {
$starttime = $thistime;
}
$p++;
$lasttime = $thistime;
}
echo '
total: '.number_format($lasttime-$starttime, 6).'s
';
}
}
//##########################################################################
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
array(141, 2323, 3, array( 480, 868, 1290, 1530)),
array(145, 2465, 3, array( 510, 924, 1350, 1620)),
array(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$words = self::$capacity[$i][qrcap_words] - self::$capacity[$i][qrcap_ec][$level];
if($words >= $size)
return $i;
}
return -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 $l = 0;
} else if ($version $l = 1;
} else {
$l = 2;
}
return self::$lengthtablebits[$mode][$l];
}
public static function maximumwords($mode, $version){
if($mode == qr_mode_structure)
return 3;
if($version $l = 0;
} else if($version $l = 1;
} else {
$l = 2;
}
$bits = self::$lengthtablebits[$mode][$l];
$words = (1 if($mode == qr_mode_kanji) {
$words *= 2; // the number of bytes is required
}
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), array(17, 0), array(17, 6), array(19, 6)),
array(array( 2, 7), array(17, 0), array( 7, 16), array(34, 0)),
array(array( 4, 5), array( 4, 14), array(11, 14), array(16, 14)),
array(array( 6, 4), array( 6, 14), array(11, 16), array(30, 2)),
array(array( 8, 4), array( 8, 13), array( 7, 22), array(22, 13)), //25
array(array(10, 2), array(19, 4), array(28, 6), array(33, 4)),
array(array( 8, 4), array(22, 3), array( 8, 26), array(12, 28)),
array(array( 3, 10), array( 3, 23), array( 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), array(42, 1), array(23, 28)),
array(array(17, 0), array(10, 23), array(10, 35), array(19, 35)),
array(array(17, 1), array(14, 21), array(29, 19), array(11, 46)),
array(array(13, 6), array(14, 23), array(44, 7), array(59, 1)),
array(array(12, 7), array(12, 26), array(39, 14), array(22, 41)), //35
array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)),
array(array(17, 4), array(29, 14), array(49, 10), array(24, 46)),
array(array( 4, 18), array(13, 32), array(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
);
// cacheable!!!
public static function geteccspec($version, $level, array &$spec){
if (count($spec) $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
array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(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), array(26, 54), array(30, 58), //35-40
);
public static function putalignmentmarker(array &$frame, $ox, $oy){
$finder = array(
\xa1\xa1\xa1\xa1\xa1,
\xa1\xa0\xa0\xa0\xa1,
\xa1\xa0\xa1\xa0\xa1,
\xa1\xa0\xa0\xa0\xa1,
\xa1\xa1\xa1\xa1\xa1
);
$ystart = $oy-2;
$xstart = $ox-2;
for($y=0; $yqrstr::set($frame, $xstart, $ystart+$y, $finder[$y]);
}
}
public static function putalignmentpattern($version, &$frame, $width){
if($version return;
$d = self::$alignmentpattern[$version][1] - self::$alignmentpattern[$version][0];
if($d $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);
return;
}
$cx = self::$alignmentpattern[$version][0];
for($x=1; $xself::putalignmentmarker($frame, 6, $cx);
self::putalignmentmarker($frame, $cx, 6);
$cx += $d;
}
$cy = self::$alignmentpattern[$version][0];
for($y=0; $y$cx = self::$alignmentpattern[$version][0];
for($x=0; $xself::putalignmentmarker($frame, $cx, $cy);
$cx += $d;
}
$cy += $d;
}
}
public static $versionpattern = array(
0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
0x27541, 0x28c69
);
public static function getversionpattern($version){
if($version qrspec_version_max)
return 0;
return self::$versionpattern[$version -7];
}
// format information --------------------------------------------------
// see calcformatinfo in tests/test_qrspec.c (orginal qrencode c lib)
public static $formatinfo = array(
array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976),
array(0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0),
array(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];
}
// frame ---------------------------------------------------------------
// cache of initial frames.
public static $frames = array();
public static function putfinderpattern(&$frame, $ox, $oy){
$finder = array(
\xc1\xc1\xc1\xc1\xc1\xc1\xc1,
\xc1\xc0\xc0\xc0\xc0\xc0\xc1,
\xc1\xc0\xc1\xc1\xc1\xc0\xc1,
\xc1\xc0\xc1\xc1\xc1\xc0\xc1,
\xc1\xc0\xc1\xc1\xc1\xc0\xc1,
\xc1\xc0\xc0\xc0\xc0\xc0\xc1,
\xc1\xc1\xc1\xc1\xc1\xc1\xc1
);
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 (\0, $width);
$frame = array_fill(0, $width, $frameline);
// finder pattern
self::putfinderpattern($frame, 0, 0);
self::putfinderpattern($frame, $width - 7, 0);
self::putfinderpattern($frame, 0, $width - 7);
// separator
$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);
// format info
$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;
}
// timing pattern
for($i=1; $i$frame[6][7+$i] = chr(0x90 | ($i & 1));
$frame[7+$i][6] = chr(0x90 | ($i & 1));
}
// alignment pattern
self::putalignmentpattern($version, $frame, $width);
// version information
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;
}
}
}
// and a little bit...
$frame[$width - 8][8] = \x81;
return $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));
}
echo '
';
echo join(
        , $frame);
echo '
';
} 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)); //format 0
$frameline = join('◆', explode(\x85, $frameline)); //format 1
$frameline = join('☢', explode(\x81, $frameline)); //special bit
$frameline = join(' ', explode(\x90, $frameline)); //clock 0
$frameline = join('◷', explode(\x91, $frameline)); //clock 1
$frameline = join(' ', explode(\x88, $frameline)); //version
$frameline = join('▒', explode(\x89, $frameline)); //version
$frameline = join('♦', explode(\x01, $frameline));
$frameline = join('⋅', explode(\0, $frameline));
}
echo ;
echo join(
, $frame);
echo
;
}
}
public static function serial($frame){
return gzcompress(join(\n, $frame), 9);
}
public static function unserial($code){
return explode(\n, gzuncompress($code));
}
public static function newframe($version){
if($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];
}
public static function rsblocknum($spec) { return $spec[0] + $spec[3]; }
public static function rsblocknum1($spec) { return $spec[0]; }
public static function rsdatacodes1($spec) { return $spec[1]; }
public static function rsecccodes1($spec) { return $spec[2]; }
public static function rsblocknum2($spec) { return $spec[3]; }
public static function rsdatacodes2($spec) { return $spec[4]; }
public static function rsecccodes2($spec) { return $spec[2]; }
public static function rsdatalength($spec) { return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]); }
public static function 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($frame, $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);
}
public static function 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);
}
private static function 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);
imagecopyresized($target_image, $base_image, 0, 0, 0, 0, $imgw * $pixelperpoint, $imgh * $pixelperpoint, $imgw, $imgh);
imagedestroy($base_image);
return $target_image;
}
}
define('structure_header_bits', 20);
define('max_structured_symbols', 16);
class qrinputitem {
public $mode;
public $size;
public $data;
public $bstream;
public function __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));
return null;
}
$this->mode = $mode;
$this->size = $size;
$this->data = $setdata;
$this->bstream = $bstream;
}
public function encodemodenum($version){
try {
$words = (int)($this->size / 3);
$bs = new 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;
return 0;
} catch (exception $e) {
return -1;
}
}
public function encodemodean($version){
try {
$words = (int)($this->size / 2);
$bs = new 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;
return 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;
return 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]) data[$i+1]);
if($val $val -= 0x8140;
} else {
$val -= 0xc140;
}
$h = ($val >> 8) * 0xc0;
$val = ($val & 0xff) + $h;
$bs->appendnum(13, $val);
}
$this->bstream = $bs;
return 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;
return 0;
} catch (exception $e) {
return -1;
}
}
public function estimatebitstreamsizeofentry($version){
$bits = 0;
if($version == 0)
$version = 1;
switch($this->mode) {
case qr_mode_num: $bits = qrinput::estimatebitsmodenum($this->size); break;
case qr_mode_an: $bits = qrinput::estimatebitsmodean($this->size); break;
case qr_mode_8: $bits = qrinput::estimatebitsmode8($this->size); break;
case qr_mode_kanji: $bits = qrinput::estimatebitsmodekanji($this->size);break;
case qr_mode_structure: return structure_header_bits;
default:
return 0;
}
$l = qrspec::lengthindicator($this->mode, $version);
$m = 1 $num = (int)(($this->size + $m - 1) / $m);
$bits += $num * (4 + $l);
return $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);
unset($st1);
unset($st2);
} else {
$ret = 0;
switch($this->mode) {
case qr_mode_num: $ret = $this->encodemodenum($version); break;
case qr_mode_an: $ret = $this->encodemodean($version); break;
case qr_mode_8: $ret = $this->encodemode8($version); break;
case qr_mode_kanji: $ret = $this->encodemodekanji($version);break;
case qr_mode_structure: $ret = $this->encodemodestructure(); break;
default:
break;
}
if($ret return -1;
}
return $this->bstream->size();
} catch (exception $e) {
return -1;
}
}
};
class qrinput {
public $items;
private $version;
private $level;
public function __construct($version = 0, $level = qr_eclevel_l){
if ($version qrspec_version_max || $level > qr_eclevel_h) {
throw new exception('invalid version no');
return null;
}
$this->version = $version;
$this->level = $level;
}
public function getversion(){
return $this->version;
}
public function setversion($version){
if($version qrspec_version_max) {
throw new exception('invalid version no');
return -1;
}
$this->version = $version;
return 0;
}
public function geterrorcorrectionlevel(){
return $this->level;
}
public function seterrorcorrectionlevel($level){
if($level > qr_eclevel_h) {
throw new exception('invalid eclevel');
return -1;
}
$this->level = $level;
return 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;
return 0;
} catch (exception $e) {
return -1;
}
}
public function insertstructuredappendheader($size, $index, $parity){
if( $size > max_structured_symbols ) {
throw new exception('insertstructuredappendheader wrong size');
}
if( $index max_structured_symbols ) {
throw new exception('insertstructuredappendheader wrong index');
}
$buf = array($size, $index, $parity);
try {
$entry = new qrinputitem(qr_mode_structure, 3, buf);
array_unshift($this->items, $entry);
return 0;
} catch (exception $e) {
return -1;
}
}
public function 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;
}
public static function checkmodenum($size, $data){
for($i=0; $iif((ord($data[$i]) ord('9'))){
return false;
}
}
return true;
}
public static function estimatebitsmodenum($size){
$w = (int)$size / 3;
$bits = $w * 10;
switch($size - $w * 3) {
case 1:
$bits += 4;
break;
case 2:
$bits += 7;
break;
default:
break;
}
return $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;
}
}
return true;
}
public static function estimatebitsmodean($size){
$w = (int)($size / 2);
$bits = $w * 11;
if($size & 1) {
$bits += 6;
}
return $bits;
}
public static function estimatebitsmode8($size){
return $size * 8;
}
public function estimatebitsmodekanji($size){
return (int)(($size / 2) * 13);
}
public static function checkmodekanji($size, $data){
if($size & 1)
return false;
for($i=0; $i$val = (ord($data[$i]) if( $val || ($val > 0x9ffc && $val || $val > 0xebbf) {
return false;
}
}
return true;
}
public static function check($mode, $size, $data){
if($size return false;
switch($mode) {
case qr_mode_num: return self::checkmodenum($size, $data); break;
case qr_mode_an: return self::checkmodean($size, $data); break;
case qr_mode_kanji: return self::checkmodekanji($size, $data); break;
case qr_mode_8: return true; break;
case qr_mode_structure: return true; break;
default:
break;
}
return false;
}
public function estimatebitstreamsize($version){
$bits = 0;
foreach($this->items as $item) {
$bits += $item->estimatebitstreamsizeofentry($version);
}
return $bits;
}
public function estimateversion(){
$version = 0;
$prev = 0;
do {
$prev = $version;
$bits = $this->estimatebitstreamsize($prev);
$version = qrspec::getminimumversion((int)(($bits + 7) / 8), $this->level);
if ($version return -1;
}
} while ($version > $prev);
return $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;
}
break;
case qr_mode_an:
$chunks = (int)($payload / 11);
$remain = $payload - $chunks * 11;
$size = $chunks * 2;
if($remain >= 6)
$size++;
break;
case qr_mode_8:
$size = (int)($payload / 8);
break;
case qr_mode_kanji:
$size = (int)(($payload / 13) * 2);
break;
case qr_mode_structure:
$size = (int)($payload / 8);
break;
default:
$size = 0;
break;
}
$maxsize = qrspec::maximumwords($mode, $version);
if($size if($size > $maxsize) $size = $maxsize;
return $size;
}
public function createbitstream(){
$total = 0;
foreach($this->items as $item) {
$bits = $item->encodebitstream($this->version);
if($bits return -1;
$total += $bits;
}
return $total;
}
public function 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 throw new exception('wrong version');
return -1;
} else if($ver > $this->getversion()) {
$this->setversion($ver);
} else {
break;
}
}
return 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);
}
$bits += 4;
$words = (int)(($bits + 7) / 8);
$padding = new 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);
return $ret;
}
public function mergebitstream(){
if($this->convertdata() return null;
}
$bstream = new qrbitstream();
foreach($this->items as $item) {
$ret = $bstream->append($item->bstream);
if($ret return null;
}
}
return $bstream;
}
public function getbitstream(){
$bstream = $this->mergebitstream();
if($bstream == null) {
return null;
}
$ret = $this->appendpaddingbit($bstream);
if($ret return null;
}
return $bstream;
}
public function getbytestream(){
$bstream = $this->getbitstream();
if($bstream == null) {
return null;
}
return $bstream->tobyte();
}
}
class qrbitstream {
public $data = array();
public function size(){
return count($this->data);
}
public function allocate($setlength){
$this->data = array_fill(0, $setlength, 0);
return 0;
}
public static function newfromnum($bits, $num){
$bstream = new qrbitstream();
$bstream->allocate($bits);
$mask = 1 for($i=0; $iif($num & $mask) {
$bstream->data[$i] = 1;
} else {
$bstream->data[$i] = 0;
}
$mask = $mask >> 1;
}
return $bstream;
}
public static function 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++;
$mask = $mask >> 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;
return 0;
}
$this->data = array_values(array_merge($this->data, $arg->data));
return 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);
unset($b);
return $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);
unset($b);
return $ret;
}
public function 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 $v |= $this->data[$p];
$p++;
}
$data[$i] = $v;
}
if($size & 7) {
$v = 0;
for($j=0; $j$v = $v $v |= $this->data[$p];
$p++;
}
$data[$bytes] = $v;
}
return $data;
}
}
class qrsplit {
public $datastr = '';
public $input;
public $modehint;
public function __construct($datastr, $input, $modehint){
$this->datastr = $datastr;
$this->input = $input;
$this->modehint = $modehint;
}
public static function isdigitat($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 function identifymode($pos){
if ($pos >= strlen($this->datastr))
return qr_mode_nul;
$c = $this->datastr[$pos];
if(self::isdigitat($this->datastr, $pos)) {
return qr_mode_num;
} else if(self::isalnumat($this->datastr, $pos)) {
return qr_mode_an;
} else if($this->modehint == qr_mode_kanji) {
if ($pos+1 datastr))
{
$d = $this->datastr[$pos+1];
$word = (ord($c) if(($word >= 0x8140 && $word = 0xe040 && $word return qr_mode_kanji;
}
}
}
return qr_mode_8;
}
public function eatnum(){
$ln = qrspec::lengthindicator(qr_mode_num, $this->input->getversion());
$p = 0;
while(self::isdigitat($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 return -1;
return $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::isalnumat($this->datastr, $p)) {
if(self::isdigitat($this->datastr, $p)) {
$q = $p;
while(self::isdigitat($this->datastr, $q)) {
$q++;
}
$dif = qrinput::estimatebitsmodean($p) // + 4 + la
+ qrinput::estimatebitsmodenum($q - $p) + 4 + $ln
- qrinput::estimatebitsmodean($q); // - 4 - la
if($dif break;
} else {
$p = $q;
}
} else {
$p++;
}
}
$run = $p;
if(!self::isalnumat($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 return -1;
return $run;
}
public function 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 return -1;
return $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 $mode = $this->identifymode($p);
if($mode == qr_mode_kanji) {
break;
}
if($mode == qr_mode_num) {
$q = $p;
while(self::isdigitat($this->datastr, $q)) {
$q++;
}
$dif = qrinput::estimatebitsmode8($p) // + 4 + l8
+ qrinput::estimatebitsmodenum($q - $p) + 4 + $ln
- qrinput::estimatebitsmode8($q); // - 4 - l8
if($dif break;
} else {
$p = $q;
}
} else if($mode == qr_mode_an) {
$q = $p;
while(self::isalnumat($this->datastr, $q)) {
$q++;
}
$dif = qrinput::estimatebitsmode8($p) // + 4 + l8
+ qrinput::estimatebitsmodean($q - $p) + 4 + $la
- qrinput::estimatebitsmode8($q); // - 4 - l8
if($dif break;
} else {
$p = $q;
}
} else {
$p++;
}
}
$run = $p;
$ret = $this->input->append(qr_mode_8, $run, str_split($this->datastr));
if($ret return -1;
return $run;
}
public function splitstring(){
while (strlen($this->datastr) > 0)
{
if($this->datastr == '')
return 0;
$mode = $this->identifymode(0);
switch ($mode) {
case qr_mode_num: $length = $this->eatnum(); break;
case qr_mode_an: $length = $this->eatan(); break;
case qr_mode_kanji:
if ($hint == qr_mode_kanji)
$length = $this->eatkanji();
else $length = $this->eat8();
break;
default: $length = $this->eat8(); break;
}
if($length == 0) return 0;
if($length $this->datastr = substr($this->datastr, $length);
}
}
public function toupper(){
$stringlen = strlen($this->datastr);
$p = 0;
while ($p$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]) $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 == '\0' || $string == '') {
throw new exception('empty string!!!');
}
$split = new qrsplit($string, $input, $modehint);
if(!$casesensitive)
$split->toupper();
return $split->splitstring();
}
}
class qrrsitem {
public $mm; // bits per symbol
public $nn; // symbols per block (= (1public $alpha_to = array(); // log lookup table
public $index_of = array(); // antilog lookup table
public $genpoly = array(); // generator polynomial
public $nroots; // number of generator roots = number of parity symbols
public $fcr; // first consecutive root, index form
public $prim; // primitive element, index form
public $iprim; // prim-th root of 1, index form
public $pad; // padding bytes in shortened block
public $gfpoly;
public function modnn($x){
while ($x >= $this->nn) {
$x -= $this->nn;
$x = ($x >> $this->mm) + ($x & $this->nn);
}
return $x;
}
public static function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad){
// common code for intializing a reed-solomon control block (char or int symbols)
// copyright 2004 phil karn, ka9q
// may be used under the terms of the gnu lesser general public license (lgpl)
$rs = null;
// check parameter ranges
if($symsize 8) return $rs;
if($fcr = (1if($prim = (1if($nroots = (1if($pad = ((1$rs = new qrrsitem();
$rs->mm = $symsize;
$rs->nn = (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 style macro replacement ;)
$nn =& $rs->nn;
$a0 =& $nn;
// generate galois field lookup tables
$rs->index_of[0] = $a0; // log(zero) = -inf
$rs->alpha_to[$a0] = 0; // alpha**-inf = 0
$sr = 1;
for($i=0; $inn; $i++) {
$rs->index_of[$sr] = $i;
$rs->alpha_to[$i] = $sr;
$sr if($sr & (1$sr ^= $gfpoly;
}
$sr &= $rs->nn;
}
if($sr != 1){
// field generator polynomial is not primitive!
$rs = null;
return $rs;
}
/* form rs code generator polynomial from its roots */
$rs->genpoly = array_fill(0, $nroots+1, 0);
$rs->fcr = $fcr;
$rs->prim = $prim;
$rs->nroots = $nroots;
$rs->gfpoly = $gfpoly;
/* find prim-th root of 1, used in decoding */
for($iprim=1;($iprim % $prim) != 0;$iprim += $rs->nn)
; // intentional empty-body loop!
$rs->iprim = (int)($iprim / $prim);
$rs->genpoly[0] = 1;
for ($i = 0,$root=$fcr*$prim; $i $rs->genpoly[$i+1] = 1;
// multiply rs->genpoly[] by @**(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] can never be zero
$rs->genpoly[0] = $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[0]] + $root)];
}
// convert rs->genpoly[] to index form for quicker encoding
for ($i = 0; $i $rs->genpoly[$i] = $rs->index_of[$rs->genpoly[$i]];
return $rs;
}
public function 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->prim;
$iprim =& $this->iprim;
$pad =& $this->pad;
$a0 =& $nn;
$parity = array_fill(0, $nroots, 0);
for($i=0; $i$feedback = $index_of[$data[$i] ^ $parity[0]];
if($feedback != $a0) {
// feedback term is non-zero
// this line is unnecessary when genpoly[nroots] is unity, as it must
// always be for the polynomials constructed by init_rs()
$feedback = $this->modnn($nn - $genpoly[$nroots] + $feedback);
for($j=1;$j$parity[$j] ^= $alpha_to[$this->modnn($feedback + $genpoly[$nroots-$j])];
}
}
// shift
array_shift($parity);
if($feedback != $a0) {
array_push($parity, $alpha_to[$this->modnn($feedback + $genpoly[0])]);
} else {
array_push($parity, 0);
}
}
}
}
class qrrs {
public static $items = array();
public static function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad){
foreach(self::$items as $rs) {
if($rs->pad != $pad) continue;
if($rs->nroots != $nroots) continue;
if($rs->mm != $symsize) continue;
if($rs->gfpoly != $gfpoly) continue;
if($rs->fcr != $fcr) continue;
if($rs->prim != $prim) continue;
return $rs;
}
$rs = qrrsitem::init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad);
array_unshift(self::$items, $rs);
return $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;
}
return $blacks;
}
public function mask0($x, $y) { return ($x+$y)&1; }
public function mask1($x, $y) { return ($y&1); }
public function mask2($x, $y) { return ($x%3); }
public function mask3($x, $y) { return ($x+$y)%3; }
public function mask4($x, $y) { return (((int)($y/2))+((int)($x/3)))&1; }
public function mask5($x, $y) { return (($x*$y)&1)+($x*$y)%3; }
public function mask6($x, $y) { return ((($x*$y)&1)+($x*$y)%3)&1; }
public function mask7($x, $y) { return ((($x*$y)%3)+(($x+$y)&1))&1; }
private function 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;
}
public static function serial($bitframe){
$codearr = array();
foreach ($bitframe as $line)
$codearr[] = join('', $line);
return gzcompress(join(\n, $codearr), 9);
}
public static function unserial($code){
$codearr = array();
$codelines = explode(\n, gzuncompress($code));
foreach ($codelines as $line)
$codearr[] = str_split($line);
return $codearr;
}
public function 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);
}
}
return $b;
}
public function makemask($width, $frame, $maskno, $level){
$masked = array_fill(0, $width, str_repeat(\0, $width));
$this->makemaskno($maskno, $width, $frame, $masked);
$this->writeformatinformation($width, $masked, $maskno, $level);
return $masked;
}
public function calcn1n3($length){
$demerit = 0;
for($i=0; $iif($this->runlength[$i] >= 5) {
$demerit += (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->runlength[$i-3] runlength[$i-3] >= (4 * $fact))) {
$demerit += n3;
} else if((($i+3) >= $length) || ($this->runlength[$i+3] >= (4 * $fact))) {
$demerit += n3;
}
}
}
}
}
return $demerit;
}
public function evaluatesymbol($width, $frame){
$head = 0;
$demerit = 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) {
$demerit += 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) {
$head++;
$this->runlength[$head] = 1;
} else {
$this->runlength[$head]++;
}
}
}
$demerit += $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]++;
}
}
}
$demerit += $this->calcn1n3($head+1);
}
return $demerit;
}
public function mask($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(\0, $width));
$demerit = 0;
$blacks = 0;
$blacks = $this->makemaskno($i, $width, $frame, $mask);
$blacks += $this->writeformatinformation($width, $mask, $i, $level);
$blacks = (int)(100 * $blacks / ($width * $width));
$demerit = (int)((int)(abs($blacks - 50) / 5) * n4);
$demerit += $this->evaluatesymbol($width, $mask);
if($demerit $mindemerit = $demerit;
$bestmask = $mask;
$bestmasknum = $i;
}
}
return $bestmask;
}
}
class qrrsblock {
public $datalength;
public $data = array();
public $ecclength;
public $ecc = array();
public function __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;
public $datacode = array();
public $ecccode = array();
public $blocks;
public $rsblocks = array(); //of rsblock
public $count;
public $datalength;
public $ecclength;
public $b1;
public function __construct(qrinput $input){
$spec = array(0,0,0,0,0);
$this->datacode = $input->getbytestream();
if(is_null($this->datacode)) {
throw new exception('null imput 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 throw new exception('block alloc error');
return 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) return -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++;
}
return 0;
}
public function getcode(){
$ret;
if($this->count datalength) {
$row = $this->count % $this->blocks;
$col = $this->count / $this->blocks;
if($col >= $this->rsblocks[0]->datalength) {
$row += $this->b1;
}
$ret = $this->rsblocks[$row]->data[$col];
} else if($this->count datalength + $this->ecclength) {
$row = ($this->count - $this->datalength) % $this->blocks;
$col = ($this->count - $this->datalength) / $this->blocks;
$ret = $this->rsblocks[$row]->ecc[$col];
} else {
return 0;
}
$this->count++;
return $ret;
}
}
class qrcode {
public $version;
public $width;
public $data;
public function encodemask(qrinput $input, $mask){
if($input->getversion() getversion() > qrspec_version_max) {
throw new exception('wrong version');
}
if($input->geterrorcorrectionlevel() > qr_eclevel_h) {
throw new exception('wrong level');
}
$raw = new 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)) {
return null;
}
// inteleaved data and ecc codes
for($i=0; $idatalength + $raw->ecclength; $i++) {
$code = $raw->getcode();
$bit = 0x80;
for($j=0; $j$addr = $filler->next();
$filler->setframeat($addr, 0x02 | (($bit & $code) != 0));
$bit = $bit >> 1;
}
}
qrtools::marktime('after_filler');
unset($raw);
// remainder bits
$j = qrspec::getremainder($version);
for($i=0; $i$addr = $filler->next();
$filler->setframeat($addr, 0x02);
}
$frame = $filler->frame;
unset($filler);
// masking
$maskobj = new qrmask();
if($mask 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;
return $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!');
return null;
}
$input = new qrinput($version, $level);
if($input == null) return null;
$ret = $input->append($input, qr_mode_8, strlen($string), str_split($string));
if($ret unset($input);
return 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('bad hint');
return null;
}
$input = new qrinput($version, $level);
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product