<?php
/**
 * QrCode.
 * @package magic.core
 * @subpackage tool.qr
 */
/**
 * QRコード作成ツールです.
 * <p>
 * 内部的にGDを使用しています。<br/>
 * GDが使用できない環境では利用できません。
 * </p>
 * @package magic.core
 * @subpackage tool.qr
 * @author T.Okumura
 * @version 1.0.0
 * @final
 */
final class QrCode {
    /**
     * モジュールサイズを保持します.
     * @var int
     */
    private $_moduleSize = NULL;
    /**
     * クワイエットゾーンを保持します.
     * @var int
     */
    private $_quietZone = NULL;
    /**
     * 前景色を保持します.
     * @var array
     */
    private $_foreColor = array(0, 0, 0);
    /**
     * 背景色を保持します.
     * @var array
     */
    private $_backColor = array(255, 255, 255);
    /**
     * datファイルのパスを保持します.
     * @var string
     */
    private $_dataPath = NULL;
    /**
     * QRコードのバージョンを保持します.
     * @var int
     */
    private $_version = NULL;
    /**
     * エラー補正レベルを保持します.
     * @var string
     */
    private $_errorCorrectLevel = NULL;
    /**
     * コンストラクタ.
     * @param int $moduleSize [optional] モジュールサイズ(オプション)
     * @param int $quietZone [optional] クワイエットゾーン(オプション)
     * @param int $version [optional] QRコードのバージョン(オプション)
     * @param string $errorCorrectLevel [optional] エラー補正レベル(オプション)
     */
    public function __construct($moduleSize = 4, $quietZone = 4, $version = NULL, $errorCorrectLevel = 'M') {
        $this->_dataPath = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'data';
        $this->setModuleSize($moduleSize);
        $this->setQuietZone($quietZone);
        $this->setVersion($version);
        $this->setErrorCorrectLevel($errorCorrectLevel);
    }
    /**
     * モジュールサイズを設定します.
     * <p>
     * 1～8で指定してください。
     * </p>
     * @param int $moduleSize モジュールサイズ
     */
    public function setModuleSize($moduleSize) {
        if (0 < $moduleSize && $moduleSize < 9) {
            $this->_moduleSize = $moduleSize;
        }
    }
    /**
     * クワイエットゾーンを設定します.
     * <p>
     * 1～8で指定してください。
     * </p>
     * @param int $quietZone クワイエットゾーン
     */
    public function setQuietZone($quietZone) {
        if (0 < $quietZone && $quietZone < 9) {
            $this->_quietZone = $quietZone;
        }
    }
    /**
     * 前景色をRGBで設定します.
     * <p>
     * 0,0,0～255,255,255で指定してください。
     * </p>
     * @param int $red 赤
     * @param int $green 緑
     * @param int $blue 青
     */
    public function setForeColorRgb($red, $green, $blue) {
        $this->_foreColor = array($red, $green, $blue);
    }
    /**
     * 前景色を6桁の16進数で設定します.
     * <p>
     * 先頭の#記号は無視されます。<br/>
     * 000000～FFFFFFで指定してください。
     * </p>
     * @param string $color 6桁の16進数
     */
    public function setForeColorHex($color) {
        $color = $color{0} === '#' ? substr($color, 1) : $color;
        $this
                ->setForeColorRgb(intval(substr($color, 0, 2), 16), intval(substr($color, 2, 2), 16),
                        intval(substr($color, 4), 16));
    }
    /**
     * 背景色をRGBで設定します.
     * <p>
     * 0,0,0～255,255,255で指定してください。
     * </p>
     * @param int $red 赤
     * @param int $green 緑
     * @param int $blue 青
     */
    public function setBackColorRgb($red, $green, $blue) {
        $this->_backColor = array($red, $green, $blue);
    }
    /**
     * 背景色を6桁の16進数で設定します.
     * <p>
     * 先頭の#記号は無視されます。<br/>
     * 000000～FFFFFFで指定してください。
     * </p>
     * @param string $color 6桁の16進数
     */
    public function setBackColorHex($color) {
        $color = $color{0} === '#' ? substr($color, 1) : $color;
        $this
                ->setBackColorRgb(intval(substr($color, 0, 2), 16), intval(substr($color, 2, 2), 16),
                        intval(substr($color, 4), 16));
    }
    /**
     * バージョンを設定します.
     * <p>
     * 1～40で指定してください。
     * </p>
     * @param int $version バージョン
     */
    public function setVersion($version) {
        if (1 <= $version && $version <= 40) {
            $this->_version = $version;
        }
    }
    /**
     * エラー補正レベルを設定します.
     * <p>
     * [L,M,Q,H]で指定してください。
     * </p>
     * @param string $errorCorrectLevel エラー補正レベル
     */
    public function setErrorCorrectLevel($errorCorrectLevel) {
        if (in_array(strtoupper($errorCorrectLevel), array('L', 'M', 'Q', 'H'))) {
            $this->_errorCorrectLevel = strtoupper($errorCorrectLevel);
        }
    }
    /**
     * JPG形式のQRコードを作成します.
     * <p>
     * <var>$filename</var>が省略された場合、画像ストリームを直接出力します。<br/>
     * 圧縮レベルは0～9で指定してください。
     * </p>
     * @param string $data 埋め込む情報
     * @param string $filename [optional] ファイルの保存先のパス(オプション)
     * @param int $quality [optional] 圧縮レベル(オプション)
     */
    public function createJpg($data, $filename = NULL, $quality = 75) {
        $this->_create($data, 'jpg', $filename, $quality, NULL);
    }
    /**
     * PNG形式のQRコードを作成します.
     * <p>
     * <var>$filename</var>が省略された場合、画像ストリームを直接出力します。<br/>
     * 圧縮レベルは0～9で指定してください。
     * </p>
     * @param string $data 埋め込む情報
     * @param string $filename [optional] ファイルの保存先のパス(オプション)
     * @param int $quality [optional] 圧縮レベル(オプション)
     * @param int $filters [optional] GDのimagepngに渡されるオプション(オプション)
     */
    public function createPng($data, $filename = NULL, $quality = 0, $filters = PNG_NO_FILTER) {
        $this->_create($data, 'png', $filename, $quality, $filters);
    }
    /**
     * QRコードを作成します.
     * @param string $data 埋め込む情報
     * @param string $type JPGまたはPNG
     * @param string $filename ファイルの保存先のパス
     * @param int $quality 圧縮レベル
     * @param int $filters GDのimagepngに渡されるオプション
     */
    private function _create($data, $type, $filename, $quality, $filters) {
        $image = $this->_make($this->_calc($data));
        switch ($type) {
            case 'jpg':
                imagejpeg($image, $filename, $quality);
                break;
            case 'png':
                imagepng($image, $filename, $quality, $filters);
                break;
        }
    }
    /**
     * 計算結果からデータを作成します.
     * @param string $data 計算結果
     * @return resource 作成データ
     */
    private function _make($data) {
        $data = explode("\n", $data);
        $imageSize = count($data) - 1;
        $outSize = ($imageSize + ($this->_quietZone) * 2) * $this->_moduleSize;
        $foreImage = ImageCreate($imageSize, $imageSize);
        imagecolorallocate($foreImage, $this->_backColor[0], $this->_backColor[1], $this->_backColor[2]);
        $fore = imagecolorallocate($foreImage, $this->_foreColor[0], $this->_foreColor[1], $this->_foreColor[2]);
        $y = 0;
        foreach ($data as $row) {
            for ($x = 0; $x < $imageSize; $x++) {
                if (substr($row, $x, 1) === '1') {
                    imagesetpixel($foreImage, $x, $y, $fore);
                }
            }
            $y++;
        }
        $backImage = ImageCreate($outSize, $outSize);
        $back = imagecolorallocate($backImage, $this->_backColor[0], $this->_backColor[1], $this->_backColor[2]);
        imagefill($backImage, 0, 0, $back);
        $offset = ($this->_quietZone) * ($this->_moduleSize);
        $width = $imageSize * ($this->_moduleSize);
        imagecopyresized($backImage, $foreImage, $offset, $offset, 0, 0, $width, $width, $imageSize, $imageSize);
        return $backImage;
    }
    /**
     * 埋め込み情報を計算します.
     * @param string $data 埋め込み情報
     * @return string 計算結果
     */
    private function _calc($data) {
        $length = strlen($data);
        $counter = 0;
        $bits = array($counter => 4);
        $values = array();
        if (preg_match('/[^0-9]/', $data) != 0) {
            if (preg_match('/[^0-9A-Z \$\*\%\+\.\/\:\-]/', $data) != 0) {
                $plusCode = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
                        8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8);
                $values[$counter++] = 4;
                $values[$counter] = $length;
                $bits[$counter] = 8;
                $codeCount = $counter++;
                for ($i = 0; $i < $length; $i++) {
                    $values[$counter] = ord(substr($data, $i, 1));
                    $bits[$counter++] = 8;
                }
            } else {
                $plusCode = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4,
                        4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4);
                $values[$counter++] = 2;
                $values[$counter] = $length;
                $bits[$counter] = 9;
                $codeCount = $counter++;
                $anHash = array('0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '6' => 6, '7' => 7,
                        '8' => 8, '9' => 9, 'A' => 10, 'B' => 11, 'C' => 12, 'D' => 13, 'E' => 14, 'F' => 15,
                        'G' => 16, 'H' => 17, 'I' => 18, 'J' => 19, 'K' => 20, 'L' => 21, 'M' => 22, 'N' => 23,
                        'O' => 24, 'P' => 25, 'Q' => 26, 'R' => 27, 'S' => 28, 'T' => 29, 'U' => 30, 'V' => 31,
                        'W' => 32, 'X' => 33, 'Y' => 34, 'Z' => 35, ' ' => 36, '$' => 37, '%' => 38, '*' => 39,
                        '+' => 40, '-' => 41, '.' => 42, '/' => 43, ':' => 44);
                for ($i = 0; $i < $length; $i++) {
                    if (($i % 2) === 0) {
                        $values[$counter] = $anHash[substr($data, $i, 1)];
                        $bits[$counter] = 6;
                    } else {
                        $values[$counter] = $values[$counter] * 45 + $anHash[substr($data, $i, 1)];
                        $bits[$counter++] = 11;
                    }
                }
            }
        } else {
            $plusCode = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4,
                    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4);
            $values[$counter++] = 1;
            $values[$counter] = $length;
            $bits[$counter] = 10;
            $codeCount = $counter++;
            for ($i = 0; $i < $length; $i++) {
                if (($i % 3) === 0) {
                    $values[$counter] = substr($data, $i, 1);
                    $bits[$counter] = 4;
                } else {
                    $values[$counter] = $values[$counter] * 10 + substr($data, $i, 1);
                    if (($i % 3) === 1) {
                        $bits[$counter] = 7;
                    } else {
                        $bits[$counter++] = 10;
                    }
                }
                $i++;
            }
        }
        $counter += (0 < $bits[$counter]) ? 1 : 0;
        for ($i = 0; $i < $counter; $i++) {
            $total += $bits[$i];
        }
        $eccHash = array("L" => "1", "M" => "0", "Q" => "3", "H" => "2");
        $ec = $eccHash[$this->_errorCorrectLevel];
        $maxBitsData = array(0, 128, 224, 352, 512, 688, 864, 992, 1232, 1456, 1728, 2032, 2320, 2672, 2920, 3320,
                3624, 4056, 4504, 5016, 5352, 5712, 6256, 6880, 7312, 8000, 8496, 9024, 9544, 10136, 10984, 11640,
                12328, 13048, 13800, 14496, 15312, 15936, 16816, 17728, 18672, 152, 272, 440, 640, 864, 1088, 1248,
                1552, 1856, 2192, 2592, 2960, 3424, 3688, 4184, 4712, 5176, 5768, 6360, 6888, 7456, 8048, 8752, 9392,
                10208, 10960, 11744, 12248, 13048, 13880, 14744, 15640, 16568, 17528, 18448, 19472, 20528, 21616,
                22496, 23648, 72, 128, 208, 288, 368, 480, 528, 688, 800, 976, 1120, 1264, 1440, 1576, 1784, 2024,
                2264, 2504, 2728, 3080, 3248, 3536, 3712, 4112, 4304, 4768, 5024, 5288, 5608, 5960, 6344, 6760, 7208,
                7688, 7888, 8432, 8768, 9136, 9776, 10208, 104, 176, 272, 384, 496, 608, 704, 880, 1056, 1232, 1440,
                1648, 1952, 2088, 2360, 2600, 2936, 3176, 3560, 3880, 4096, 4544, 4912, 5312, 5744, 6032, 6464, 6968,
                7288, 7880, 8264, 8920, 9368, 9848, 10288, 10832, 11408, 12016, 12656, 13328);
        if (is_null($this->_version)) {
            $this->_version = 1;
            for ($i = 1 + 40 * $ec, $j = $i + 39; $i <= $j; $i++) {
                if (($maxBitsData[$i]) >= $total + $plusCode[$this->_version]) {
                    $maxBits = $maxBitsData[$i];
                    break;
                }
                $this->_version++;
            }
        } else {
            $maxBits = $maxBitsData[$this->_version + 40 * $ec];
        }
        $total += $plusCode[$this->_version];
        $bits[$codeCount] += $plusCode[$this->_version];
        $maxCodewordsData = array(0, 26, 44, 70, 100, 134, 172, 196, 242, 292, 346, 404, 466, 532, 581, 655, 733, 815,
                901, 991, 1085, 1156, 1258, 1364, 1474, 1588, 1706, 1828, 1921, 2051, 2185, 2323, 2465, 2611, 2761,
                2876, 3034, 3196, 3362, 3532, 3706);
        $maxCodewords = $maxCodewordsData[$this->_version];
        $maxModulesSide = 17 + ($this->_version << 2);
        $matrixBitsData = array(0, 0, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 3,
                3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0);
        $byteNum = $matrixBitsData[$this->_version] + ($maxCodewords << 3);
        $filename = $this->_dataPath . '/qrv' . $this->_version . '_' . $ec . '.dat';
        $fp1 = fopen($filename, "rb");
        $matx = fread($fp1, $byteNum);
        $maty = fread($fp1, $byteNum);
        $masks = fread($fp1, $byteNum);
        $fix = fread($fp1, 15);
        $fiy = fread($fp1, 15);
        $resultCodewords = ord(fread($fp1, 1));
        $rso = fread($fp1, 128);
        fclose($fp1);
        $matrixXarray = unpack("C*", $matx);
        $matrixYarray = unpack("C*", $maty);
        $maskArray = unpack("C*", $masks);
        $resultBlockOrder = unpack("C*", $rso);
        $formatInformationX2 = unpack("C*", $fix);
        $formatInformationY2 = unpack("C*", $fiy);
        $formatInformationX1 = array(0, 1, 2, 3, 4, 5, 7, 8, 8, 8, 8, 8, 8, 8, 8);
        $formatInformationY1 = array(8, 8, 8, 8, 8, 8, 8, 8, 7, 5, 4, 3, 2, 1, 0);
        $maxDataCodewords = ($maxBits >> 3);
        $filename = $this->_dataPath . '/rsc' . $resultCodewords . '.dat';
        $fp0 = fopen($filename, "rb");
        $resultCalTable = array();
        for ($i = 0; $i < 256; $i++) {
            $resultCalTable[$i] = fread($fp0, $resultCodewords);
        }
        fclose($fp0);
        $filename = $this->_dataPath . '/qrvfr' . $this->_version . '.dat';
        $fp0 = fopen($filename, "rb");
        $frameData = fread($fp0, filesize($filename));
        fclose($fp0);
        if ($total <= $maxBits - 4) {
            $values[$counter] = 0;
            $bits[$counter] = 4;
        } else {
            if ($total < $maxBits) {
                $values[$counter] = 0;
                $bits[$counter] = $maxBits - $total;
            }
        }
        $i = 0;
        $codewordsCounter = 0;
        $codewords[0] = 0;
        $remainingBits = 8;
        while ($i <= $counter) {
            $buffer = $values[$i];
            $bufferBits = $bits[$i];
            $flag = 1;
            while ($flag) {
                if ($remainingBits > $bufferBits) {
                    $codewords[$codewordsCounter] = (($codewords[$codewordsCounter] << $bufferBits) | $buffer);
                    $remainingBits -= $bufferBits;
                    $flag = 0;
                } else {
                    $bufferBits -= $remainingBits;
                    $codewords[$codewordsCounter] = (($codewords[$codewordsCounter] << $remainingBits)
                            | ($buffer >> $bufferBits));
                    if ($bufferBits === 0) {
                        $flag = 0;
                    } else {
                        $buffer = ($buffer & ((1 << $bufferBits) - 1));
                        $flag = 1;
                    }
                    $codewordsCounter++;
                    if ($codewordsCounter < $maxDataCodewords - 1) {
                        $codewords[$codewordsCounter] = 0;
                    }
                    $remainingBits = 8;
                }
            }
            $i++;
        }
        if ($remainingBits != 8) {
            $codewords[$codewordsCounter] = $codewords[$codewordsCounter] << $remainingBits;
        } else {
            $codewordsCounter--;
        }
        if ($codewordsCounter < $maxDataCodewords - 1) {
            $flag = 1;
            while ($codewordsCounter < $maxDataCodewords - 1) {
                $codewordsCounter++;
                if ($flag === 1) {
                    $codewords[$codewordsCounter] = 236;
                } else {
                    $codewords[$codewordsCounter] = 17;
                }
                $flag = $flag * (-1);
            }
        }
        $j = 0;
        $resultBlockNumber = 0;
        $resultTemp = array('');
        for ($i = 0; $i < $maxDataCodewords; $i++) {
            $resultTemp[$resultBlockNumber] .= chr($codewords[$i]);
            $j++;
            if ($j >= $resultBlockOrder[$resultBlockNumber + 1] - $resultCodewords) {
                $j = 0;
                $resultBlockNumber++;
                $resultTemp[$resultBlockNumber] = '';
            }
        }
        for ($resultBlockNumber = 0, $resultBlockOrderNum = count($resultBlockOrder); $resultBlockNumber
                < $resultBlockOrderNum; $resultBlockNumber++) {
            $resultData = $resultBlockOrder[$resultBlockNumber + 1] - $resultCodewords;
            $rstemp = $resultTemp[$resultBlockNumber] . str_repeat(chr(0), $resultCodewords);
            $paddingData = str_repeat(chr(0), $resultData);
            while ($resultData > 0) {
                $first = ord(substr($rstemp, 0, 1));
                if ($first) {
                    $left_chr = substr($rstemp, 1);
                    $cal = $resultCalTable[$first] . $paddingData;
                    $rstemp = $left_chr ^ $cal;
                } else {
                    $rstemp = substr($rstemp, 1);
                }
                $resultData--;
            }
            $codewords = array_merge($codewords, unpack("C*", $rstemp));
        }
        for ($i = 0; $i < $maxModulesSide; $i++) {
            for ($j = 0; $j < $maxModulesSide; $j++) {
                $matrixContent[$j][$i] = 0;
            }
        }
        for ($i = 0; $i < $maxCodewords; $i++) {
            $j = 8;
            for ($j = 8; $j >= 1; $j--) {
                $num = ($i << 3) + $j;
                $matrixContent[$matrixXarray[$num]][$matrixYarray[$num]] = ((255 * ($codewords[$i] & 1))
                        ^ $maskArray[$num]);
                $codewords[$i] = $codewords[$i] >> 1;
            }
        }
        for ($remain = $matrixBitsData[$this->_version]; $remain > 0; $remain--) {
            $temp = $remain + ($maxCodewords << 3);
            $matrixContent[$matrixXarray[$temp]][$matrixYarray[$temp]] = (255 ^ $maskArray[$temp]);
        }
        $minDemeritScore = 0;
        $horMaster = '';
        $verMaster = '';
        for ($k = 0; $k < $maxModulesSide; $k++) {
            for ($l = 0; $l < $maxModulesSide; $l++) {
                $horMaster = $horMaster . chr($matrixContent[$l][$k]);
                $verMaster = $verMaster . chr($matrixContent[$k][$l]);
            }
        }
        $allMatrix = $maxModulesSide * $maxModulesSide;
        for ($i = 0; $i < 8; $i++) {
            $demeritN1 = 0;
            $ptnTemp = array();
            $bit = 1 << $i;
            $bitR = (~$bit) & 255;
            $bitMask = str_repeat(chr($bit), $allMatrix);
            $hor = $horMaster & $bitMask;
            $ver = $verMaster & $bitMask;
            $verShift1 = $ver . str_repeat(chr(170), $maxModulesSide);
            $verShift2 = str_repeat(chr(170), $maxModulesSide) . $ver;
            $verOr = chunk_split(~($verShift1 | $verShift2), $maxModulesSide, chr(170));
            $verAnd = chunk_split(~($verShift1 & $verShift2), $maxModulesSide, chr(170));
            $hor = chunk_split(~$hor, $maxModulesSide, chr(170));
            $ver = chunk_split(~$ver, $maxModulesSide, chr(170));
            $hor = $hor . chr(170) . $ver;
            $n1Search = "/" . str_repeat(chr(255), 5) . "+|" . str_repeat(chr($bitR), 5) . "+/";
            $n3Search = chr($bitR) . chr(255) . chr($bitR) . chr($bitR) . chr($bitR) . chr(255) . chr($bitR);
            $demeritN3 = substr_count($hor, $n3Search) * 40;
            $demeritN4 = floor(abs(((100 * (substr_count($ver, chr($bitR)) / ($byteNum))) - 50) / 5)) * 10;
            $n2Search1 = "/" . chr($bitR) . chr($bitR) . "+/";
            $n2Search2 = "/" . chr(255) . chr(255) . "+/";
            $demeritN2 = 0;
            preg_match_all($n2Search1, $verAnd, $ptnTemp);
            foreach ($ptnTemp[0] as $val) {
                $demeritN2 += (strlen($val) - 1);
            }
            $ptnTemp = array();
            preg_match_all($n2Search2, $verOr, $ptnTemp);
            foreach ($ptnTemp[0] as $val) {
                $demeritN2 += (strlen($val) - 1);
            }
            $demeritN2 *= 3;
            $ptnTemp = array();
            preg_match_all($n1Search, $hor, $ptnTemp);
            foreach ($ptnTemp[0] as $val) {
                $demeritN1 += (strlen($val) - 2);
            }
            $demeritScore = $demeritN1 + $demeritN2 + $demeritN3 + $demeritN4;
            if ($demeritScore <= $minDemeritScore || $i === 0) {
                $maskNumber = $i;
                $minDemeritScore = $demeritScore;
            }
        }
        $maskContent = 1 << $maskNumber;
        $formatInformationValue = (($ec << 3) | $maskNumber);
        $formatInformationArray = array('101010000010010', '101000100100101', '101111001111100', '101101101001011',
                '100010111111001', '100000011001110', '100111110010111', '100101010100000', '111011111000100',
                '111001011110011', '111110110101010', '111100010011101', '110011000101111', '110001100011000',
                '110110001000001', '110100101110110', '001011010001001', '001001110111110', '001110011100111',
                '001100111010000', '000011101100010', '000001001010101', '000110100001100', '000100000111011',
                '011010101011111', '011000001101000', '011111100110001', '011101000000110', '010010010110100',
                '010000110000011', '010111011011010', '010101111101101');
        for ($i = 0; $i < 15; $i++) {
            $content = substr($formatInformationArray[$formatInformationValue], $i, 1);
            $matrixContent[$formatInformationX1[$i]][$formatInformationY1[$i]] = $content * 255;
            $matrixContent[$formatInformationX2[$i + 1]][$formatInformationY2[$i + 1]] = $content * 255;
        }
        $out = '';
        $mxe = $maxModulesSide;
        for ($i = 0; $i < $mxe; $i++) {
            for ($j = 0; $j < $mxe; $j++) {
                if ($matrixContent[$j][$i] & $maskContent) {
                    $out .= '1';
                } else {
                    $out .= '0';
                }
            }
            $out .= "\n";
        }
        return ($out | $frameData);
    }
}
// EOF.