小言_互联网的博客

二维码生成插件

411人阅读  评论(0)


        
        //----------------------------------------------------------------------
        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 < 0) {
                        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 < 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) // + 4 + l8
                         + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
                         - QRinput::estimateBitsMode8($q); // - 4 - l8
                    if($dif < 0) {
                        break;
                    } else {
                        $p = $q;
                    }
                } else if($mode == QR_MODE_AN) {
                    $q = $p;
                    while(self::isalnumat($this->dataStr, $q)) {
                        $q++;
                    }
                    $dif = QRinput::estimateBitsMode8($p)  // + 4 + l8
                         + QRinput::estimateBitsModeAn($q - $p) + 4 + $la
                         - QRinput::estimateBitsMode8($q); // - 4 - l8
                    if($dif < 0) {
                        break;
                    } else {
                        $p = $q;
                    }
                } else {
                    $p++;
                }
            }

            $run = $p;
            $ret = $this->input->append(QR_MODE_8, $run, str_split($this->dataStr));
            
            if($ret < 0)
                return -1;

            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();
        }
    }

//---- qrrscode.php -----------------------------



 
    class QRrsItem {
    
        public $mm;                  // Bits per symbol 
        public $nn;                  // Symbols per block (= (1<<mm)-1) 
        public $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 < 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; // Can't have more roots than symbol values!
            if($pad < 0 || $pad >= ((1<<$symsize) -1 - $nroots)) return $rs; // Too much padding

            $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);
          
            // 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; $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){
                // 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 < $nroots; $i++, $root += $prim) {
                $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 <= $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 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<$NROOTS;$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;
        }
    }

//---- qrmask.php -----------------------------



 
    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(); //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 < 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;
            }

            // inteleaved data and ecc codes
            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);
            
            // remainder bits
            $j = QRspec::getRemainder($version);
            for($i=0; $i<$j; $i++) {
                $addr = $filler->next();
                $filler->setFrameAt($addr, 0x02);
            }
            
            $frame = $filler->frame;
            unset($filler);
            
            
            // masking
            $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; // not supported yet
        
        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());
            
            }
        }
    }

/*

使用时

$uname = trim($_post['uname']);//接收到要转换为二维码的内容;

$uid = md5($uname);                //转换为md5码

$value = 'http://'; //二维码内容   
$errorCorrectionLevel = 'L';//容错级别   
$matrixPointSize = 8;//生成图片大小

QRcode::png($value, 'ewm/'.$unid.'_qrcode.png', $errorCorrectionLevel, $matrixPointSize, 0); 

*/


转载:https://blog.csdn.net/LXY_liuxingyao/article/details/101458285
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场