1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161 |
- <?php
- 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);
- define('QR_CACHE_DIR',false);
- define('QR_LOG_DIR',false);
- define('QR_FIND_BEST_MASK',true);
- define('QR_FIND_FROM_RANDOM',2);
- define('QR_DEFAULT_MASK',2);
- define('QR_PNG_MAXIMUM_SIZE',1024);
- class QRtools {
- public static function binarize($frame)
- {
- $len = count($frame);
- foreach ($frame as &$frameLine) {
- for($i=0;$i<$len;$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 <= QRSPEC_VERSION_MAX;$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<8;$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;$y<$width;$y++) {
- for($x=0;$x<$width;$x++) {
- echo 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 '<table cellpadding="3" cellspacing="1">
- <thead><tr style="border-bottom:1px solid silver"><td colspan="2" style="text-align:center">BENCHMARK</td></tr></thead>
- <tbody>';
- foreach($GLOBALS['qr_time_bench'] as $markerId=>$thisTime) {
- if ($p >0) {
- echo '<tr><th style="text-align:right">till '.$markerId.': </th><td>'.number_format($thisTime-$lastTime,6).'s</td></tr>';
- }else {
- $startTime = $thisTime;
- }
- $p++;
- $lastTime = $thisTime;
- }
- echo '</tbody><tfoot>
- <tr style="border-top:2px solid black"><th style="text-align:right">TOTAL: </th><td>'.number_format($lastTime-$startTime,6).'s</td></tr>
- </tfoot>
- </table>';
- }
- }
- 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)),
- 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)),
- 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)),
- 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)),
- 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)),
- 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)),
- 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)),
- 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)),
- 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))
- );
- 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;
- }
- 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 <= 9) {
- $l = 0;
- }else if ($version <= 26) {
- $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 <= 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)),
- 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)),
- 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)),
- 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)),
- 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)),
- 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)),
- 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)),
- 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)),
- 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)),
- );
- public static function 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),
- array(34,0),array(22,38),array(24,42),array(26,46),array(28,50),
- array(30,54),array(32,58),array(34,62),array(26,46),array(26,48),
- array(26,50),array(30,54),array(30,56),array(30,58),array(34,62),
- array(28,50),array(26,50),array(30,54),array(28,54),array(32,58),
- array(30,58),array(34,62),array(26,50),array(30,54),array(26,52),
- array(30,56),array(34,60),array(30,58),array(34,62),array(30,54),
- array(24,50),array(28,54),array(32,58),array(26,54),array(30,58),
- );
- 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;$y<5;$y++) {
- QRstr::set($frame,$xStart,$yStart+$y,$finder[$y]);
- }
- }
- public static function 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);
- return;
- }
- $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,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 <7 ||$version >QRSPEC_VERSION_MAX)
- return 0;
- return self::$versionPattern[$version -7];
- }
- 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 <0 ||$mask >7)
- return 0;
- if($level <0 ||$level >3)
- return 0;
- return self::$formatInfo[$level][$mask];
- }
- 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;$y<7;$y++) {
- QRstr::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);
- self::putFinderPattern($frame,0,0);
- self::putFinderPattern($frame,$width -7,0);
- self::putFinderPattern($frame,0,$width -7);
- $yOffset = $width -7;
- for($y=0;$y<7;$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<8;$y++,$yOffset++) {
- $frame[$y][8] = "\x84";
- $frame[$yOffset][8] = "\x84";
- }
- for($i=1;$i<$width-15;$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;$x<6;$x++) {
- for($y=0;$y<3;$y++) {
- $frame[($width -11)+$y][$x] = chr(0x88 |($v &1));
- $v = $v >>1;
- }
- }
- $v = $vinf;
- for($y=0;$y<6;$y++) {
- for($x=0;$x<3;$x++) {
- $frame[$y][$x+($width -11)] = chr(0x88 |($v &1));
- $v = $v >>1;
- }
- }
- }
- $frame[$width -8][8] = "\x81";
- return $frame;
- }
- public static function debug($frame,$binary_mode = false)
- {
- if ($binary_mode) {
- foreach ($frame as &$frameLine) {
- $frameLine = join('<span class="m"> </span>',explode('0',$frameLine));
- $frameLine = join('██',explode('1',$frameLine));
- }
- ;echo ' <style>
- .m { background-color: white; }
- </style>
- ';
- echo '<pre><tt><br/ ><br/ ><br/ > ';
- echo join("<br/ > ",$frame);
- echo '</tt></pre><br/ ><br/ ><br/ ><br/ ><br/ ><br/ >';
- }else {
- foreach ($frame as &$frameLine) {
- $frameLine = join('<span class="m"> </span>',explode("\xc0",$frameLine));
- $frameLine = join('<span class="m">▒</span>',explode("\xc1",$frameLine));
- $frameLine = join('<span class="p"> </span>',explode("\xa0",$frameLine));
- $frameLine = join('<span class="p">▒</span>',explode("\xa1",$frameLine));
- $frameLine = join('<span class="s">◇</span>',explode("\x84",$frameLine));
- $frameLine = join('<span class="s">◆</span>',explode("\x85",$frameLine));
- $frameLine = join('<span class="x">☢</span>',explode("\x81",$frameLine));
- $frameLine = join('<span class="c"> </span>',explode("\x90",$frameLine));
- $frameLine = join('<span class="c">◷</span>',explode("\x91",$frameLine));
- $frameLine = join('<span class="f"> </span>',explode("\x88",$frameLine));
- $frameLine = join('<span class="f">▒</span>',explode("\x89",$frameLine));
- $frameLine = join('♦',explode("\x01",$frameLine));
- $frameLine = join('⋅',explode("\0",$frameLine));
- }
- ;echo ' <style>
- .p { background-color: yellow; }
- .m { background-color: #00FF00; }
- .s { background-color: #FF0000; }
- .c { background-color: aqua; }
- .x { background-color: pink; }
- .f { background-color: gold; }
- </style>
- ';
- echo "<pre><tt>";
- echo join("<br/ >",$frame);
- echo "</tt></pre>";
- }
- }
- 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 <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];
- }
- 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;$y<$h;$y++) {
- for($x=0;$x<$w;$x++) {
- if ($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) <$size) {
- $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<$words;$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<$words;$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;$i<$this->size;$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;$i<$this->size;$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;
- 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 <<$l;
- $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 <0)
- 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 <0 ||$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 <0 ||$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 <= 0 ||$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;$i<$size;$i++) {
- if((ord($data[$i]) <ord('0')) ||(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;$i<$size;$i++) {
- if (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<$size;$i+=2) {
- $val = (ord($data[$i]) <<8) |ord($data[$i+1]);
- if( $val <0x8140
- ||($val >0x9ffc &&$val <0xe040)
- ||$val >0xebbf) {
- return false;
- }
- }
- return true;
- }
- public static function check($mode,$size,$data)
- {
- if($size <= 0)
- 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 <0) {
- 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 <0) $size = 0;
- if($size >$maxsize) $size = $maxsize;
- return $size;
- }
- public function createBitStream()
- {
- $total = 0;
- foreach($this->items as $item) {
- $bits = $item->encodeBitStream($this->version);
- if($bits <0)
- 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 <0)
- return -1;
- $ver = QRspec::getMinimumVersion((int)(($bits +7) / 8),$this->level);
- if($ver <0) {
- 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 <5) {
- 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 <0)
- return $ret;
- $padlen = $maxwords -$words;
- if($padlen >0) {
- $padbuf = array();
- for($i=0;$i<$padlen;$i++) {
- $padbuf[$i] = ($i&1)?0x11:0xec;
- }
- $ret = $padding->appendBytes($padlen,$padbuf);
- if($ret <0)
- return $ret;
- }
- $ret = $bstream->append($padding);
- return $ret;
- }
- public function mergeBitStream()
- {
- if($this->convertData() <0) {
- return null;
- }
- $bstream = new QRbitstream();
- foreach($this->items as $item) {
- $ret = $bstream->append($item->bstream);
- if($ret <0) {
- return null;
- }
- }
- return $bstream;
- }
- public function getBitStream()
- {
- $bstream = $this->mergeBitStream();
- if($bstream == null) {
- return null;
- }
- $ret = $this->appendPaddingBit($bstream);
- if($ret <0) {
- 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 <<($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;
- }
- public static function newFromBytes($size,$data)
- {
- $bstream = new QRbitstream();
- $bstream->allocate($size * 8);
- $p=0;
- for($i=0;$i<$size;$i++) {
- $mask = 0x80;
- for($j=0;$j<8;$j++) {
- if($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<$bytes;$i++) {
- $v = 0;
- for($j=0;$j<8;$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;
- }
- 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]) <= ord('9')));
- }
- 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 <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;
- }
- }
- }
- 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)
- -QRinput::estimateBitsMode8($run +1);
- if($dif >0) {
- return $this->eat8();
- }
- }
- if($mode == QR_MODE_AN) {
- $dif = QRinput::estimateBitsModeNum($run) +4 +$ln
- +QRinput::estimateBitsModeAn(1)
- -QRinput::estimateBitsModeAn($run +1);
- if($dif >0) {
- return $this->eatAn();
- }
- }
- $ret = $this->input->append(QR_MODE_NUM,$run,str_split($this->dataStr));
- if($ret <0)
- 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)
- +QRinput::estimateBitsModeNum($q -$p) +4 +$ln
- -QRinput::estimateBitsModeAn($q);
- if($dif <0) {
- break;
- }else {
- $p = $q;
- }
- }else {
- $p++;
- }
- }
- $run = $p;
- if(!self::isalnumat($this->dataStr,$p)) {
- $dif = QRinput::estimateBitsModeAn($run) +4 +$la
- +QRinput::estimateBitsMode8(1)
- -QRinput::estimateBitsMode8($run +1);
- if($dif >0) {
- return $this->eat8();
- }
- }
- $ret = $this->input->append(QR_MODE_AN,$run,str_split($this->dataStr));
- if($ret <0)
- 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 <0)
- 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 <$dataStrLen) {
- $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)
- +QRinput::estimateBitsModeNum($q -$p) +4 +$ln
- -QRinput::estimateBitsMode8($q);
- if($dif <0) {
- break;
- }else {
- $p = $q;
- }
- }else if($mode == QR_MODE_AN) {
- $q = $p;
- while(self::isalnumat($this->dataStr,$q)) {
- $q++;
- }
- $dif = QRinput::estimateBitsMode8($p)
- +QRinput::estimateBitsModeAn($q -$p) +4 +$la
- -QRinput::estimateBitsMode8($q);
- 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;
- 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 <0) return -1;
- $this->dataStr = substr($this->dataStr,$length);
- }
- }
- public function 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 == '\0'||$string == '') {
- throw new Exception('empty string!!!');
- }
- $split = new QRsplit($string,$input,$modeHint);
- if(!$casesensitive)
- $split->toUpper();
- return $split->splitString();
- }
- }
- class QRrsItem {
- public $mm;
- public $nn;
- public $alpha_to = array();
- public $index_of = array();
- public $genpoly = array();
- public $nroots;
- public $fcr;
- public $prim;
- public $iprim;
- public $pad;
- 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)
- {
- $rs = null;
- if($symsize <0 ||$symsize >8) return $rs;
- if($fcr <0 ||$fcr >= (1<<$symsize)) return $rs;
- if($prim <= 0 ||$prim >= (1<<$symsize)) return $rs;
- if($nroots <0 ||$nroots >= (1<<$symsize)) return $rs;
- if($pad <0 ||$pad >= ((1<<$symsize) -1 -$nroots)) return $rs;
- $rs = new QRrsItem();
- $rs->mm = $symsize;
- $rs->nn = (1<<$symsize)-1;
- $rs->pad = $pad;
- $rs->alpha_to = array_fill(0,$rs->nn+1,0);
- $rs->index_of = array_fill(0,$rs->nn+1,0);
- $NN =&$rs->nn;
- $A0 =&$NN;
- $rs->index_of[0] = $A0;
- $rs->alpha_to[$A0] = 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<<$symsize)) {
- $sr ^= $gfpoly;
- }
- $sr &= $rs->nn;
- }
- if($sr != 1){
- $rs = NULL;
- return $rs;
- }
- $rs->genpoly = array_fill(0,$nroots+1,0);
- $rs->fcr = $fcr;
- $rs->prim = $prim;
- $rs->nroots = $nroots;
- $rs->gfpoly = $gfpoly;
- 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;
- 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->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[0]] +$root)];
- }
- for ($i = 0;$i <= $nroots;$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<($NN-$NROOTS-$PAD);$i++) {
- $feedback = $INDEX_OF[$data[$i] ^$parity[0]];
- if($feedback != $A0) {
- $feedback = $this->modnn($NN -$GENPOLY[$NROOTS] +$feedback);
- for($j=1;$j<$NROOTS;$j++) {
- $parity[$j] ^= $ALPHA_TO[$this->modnn($feedback +$GENPOLY[$NROOTS-$j])];
- }
- }
- 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;$i<8;$i++) {
- if($format &1) {
- $blacks += 2;
- $v = 0x85;
- }else {
- $v = 0x84;
- }
- $frame[8][$width -1 -$i] = chr($v);
- if($i <6) {
- $frame[$i][8] = chr($v);
- }else {
- $frame[$i +1][8] = chr($v);
- }
- $format = $format >>1;
- }
- for($i=0;$i<7;$i++) {
- if($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;$y<$width;$y++) {
- for($x=0;$x<$width;$x++) {
- if(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;$y<$width;$y++) {
- for($x=0;$x<$width;$x++) {
- if($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;$i<$length;$i++) {
- if($this->runLength[$i] >= 5) {
- $demerit += (N1 +($this->runLength[$i] -5));
- }
- if($i &1) {
- if(($i >= 3) &&($i <($length-2)) &&($this->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] <0) ||($this->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<$width;$y++) {
- $head = 0;
- $this->runLength[0] = 1;
- $frameY = $frame[$y];
- if ($y>0)
- $frameYM = $frame[$y-1];
- for($x=0;$x<$width;$x++) {
- if(($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<$width;$x++) {
- $head = 0;
- $this->runLength[0] = 1;
- for($y=0;$y<$width;$y++) {
- if($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 <$howManuOut;$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) {
- $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();
- 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 <0) {
- 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<QRspec::rsBlockNum1($spec);$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<QRspec::rsBlockNum2($spec);$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 <$this->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 <$this->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() <0 ||$input->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;
- }
- for($i=0;$i<$raw->dataLength +$raw->eccLength;$i++) {
- $code = $raw->getCode();
- $bit = 0x80;
- for($j=0;$j<8;$j++) {
- $addr = $filler->next();
- $filler->setFrameAt($addr,0x02 |(($bit &$code) != 0));
- $bit = $bit >>1;
- }
- }
- QRtools::markTime('after_filler');
- unset($raw);
- $j = QRspec::getRemainder($version);
- for($i=0;$i<$j;$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;
- 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 <0) {
- 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);
- if($input == NULL) return NULL;
- $ret = QRsplit::splitStringToQRinput($string,$input,$hint,$casesensitive);
- if($ret <0) {
- return NULL;
- }
- return $this->encodeInput($input);
- }
- public static function png($text,$outfile = false,$level = QR_ECLEVEL_L,$size = 3,$margin = 4,$saveandprint=false)
- {
- $enc = QRencode::factory($level,$size,$margin);
- return $enc->encodePNG($text,$outfile,$saveandprint=false);
- }
- public static function text($text,$outfile = false,$level = QR_ECLEVEL_L,$size = 3,$margin = 4)
- {
- $enc = QRencode::factory($level,$size,$margin);
- return $enc->encode($text,$outfile);
- }
- public static function raw($text,$outfile = false,$level = QR_ECLEVEL_L,$size = 3,$margin = 4)
- {
- $enc = QRencode::factory($level,$size,$margin);
- return $enc->encodeRAW($text,$outfile);
- }
- }
- class FrameFiller {
- public $width;
- public $frame;
- public $x;
- public $y;
- public $dir;
- public $bit;
- public function __construct($width,&$frame)
- {
- $this->width = $width;
- $this->frame = $frame;
- $this->x = $width -1;
- $this->y = $width -1;
- $this->dir = -1;
- $this->bit = -1;
- }
- public function setFrameAt($at,$val)
- {
- $this->frame[$at['y']][$at['x']] = chr($val);
- }
- public function getFrameAt($at)
- {
- return ord($this->frame[$at['y']][$at['x']]);
- }
- public function next()
- {
- do {
- if($this->bit == -1) {
- $this->bit = 0;
- return array('x'=>$this->x,'y'=>$this->y);
- }
- $x = $this->x;
- $y = $this->y;
- $w = $this->width;
- if($this->bit == 0) {
- $x--;
- $this->bit++;
- }else {
- $x++;
- $y += $this->dir;
- $this->bit--;
- }
- if($this->dir <0) {
- if($y <0) {
- $y = 0;
- $x -= 2;
- $this->dir = 1;
- if($x == 6) {
- $x--;
- $y = 9;
- }
- }
- }else {
- if($y == $w) {
- $y = $w -1;
- $x -= 2;
- $this->dir = -1;
- if($x == 6) {
- $x--;
- $y -= 8;
- }
- }
- }
- if($x <0 ||$y <0) return null;
- $this->x = $x;
- $this->y = $y;
- }while(ord($this->frame[$y][$x]) &0x80);
- return array('x'=>$x,'y'=>$y);
- }
- };
- class QRencode {
- public $casesensitive = true;
- public $eightbit = false;
- public $version = 0;
- public $size = 3;
- public $margin = 4;
- public $structured = 0;
- public $level = QR_ECLEVEL_L;
- public $hint = QR_MODE_8;
- public static function factory($level = QR_ECLEVEL_L,$size = 3,$margin = 4)
- {
- $enc = new QRencode();
- $enc->size = $size;
- $enc->margin = $margin;
- switch ($level.'') {
- case '0':
- case '1':
- case '2':
- case '3':
- $enc->level = $level;
- break;
- case 'l':
- case 'L':
- $enc->level = QR_ECLEVEL_L;
- break;
- case 'm':
- case 'M':
- $enc->level = QR_ECLEVEL_M;
- break;
- case 'q':
- case 'Q':
- $enc->level = QR_ECLEVEL_Q;
- break;
- case 'h':
- case 'H':
- $enc->level = QR_ECLEVEL_H;
- break;
- }
- return $enc;
- }
- public function encodeRAW($intext,$outfile = false)
- {
- $code = new QRcode();
- if($this->eightbit) {
- $code->encodeString8bit($intext,$this->version,$this->level);
- }else {
- $code->encodeString($intext,$this->version,$this->level,$this->hint,$this->casesensitive);
- }
- return $code->data;
- }
- public function encode($intext,$outfile = false)
- {
- $code = new QRcode();
- if($this->eightbit) {
- $code->encodeString8bit($intext,$this->version,$this->level);
- }else {
- $code->encodeString($intext,$this->version,$this->level,$this->hint,$this->casesensitive);
- }
- QRtools::markTime('after_encode');
- if ($outfile!== false) {
- file_put_contents($outfile,join("\n",QRtools::binarize($code->data)));
- }else {
- return QRtools::binarize($code->data);
- }
- }
- public function encodePNG($intext,$outfile = false,$saveandprint=false)
- {
- try {
- ob_start();
- $tab = $this->encode($intext);
- $err = ob_get_contents();
- ob_end_clean();
- if ($err != '')
- QRtools::log($outfile,$err);
- $maxSize = (int)(QR_PNG_MAXIMUM_SIZE / (count($tab)+2*$this->margin));
- QRimage::png($tab,$outfile,min(max(1,$this->size),$maxSize),$this->margin,$saveandprint);
- }catch (Exception $e) {
- QRtools::log($outfile,$e->getMessage());
- }
- }
- }
- echo QRcode::png(isset($_GET['link']) ?$_GET['link'] : NULL);
- ?>
|