不依赖GD的PNG图片生成对象

网络整理 - 08-10
完整的代码如下:

<?php
interface zxpngInterface
{
    /*生成图片(图片宽度, 图片高度, 图片内容)*/
    function build($width, $height, $content);
}
class zxpng implements zxpngInterface
{
    private $kernel;
    /*
    * 库主控文件
    *
    * @var kernel
    * @access private
    */
    private $status;
    /*
    * 处理状态说明
    *
    * @var bool
    * @access private
    */
    private $info;
    /*
    * png图片信息集合
    *
    * @var array
    * @access private
    */
    
    public function __construct($kernel)
    {
        $this->kernel = &$kernel;
    }
    /*生成图片(图片宽度, 图片高度, 图片内容)*/
    public function build($width, $height, $content)
    {
        self::createBackground($width, $height);
        $contentLength = strlen($content);
        $table = self::table( );
        $space = 12;
        
        for($i = 0; $i < $contentLength; $i++)
        {
            self::draw($table[$content[$i]], $width, $height, $space);
            $space += 12;
        }  
        self::crcTable( );
        $data = self::headTag( );
        $data .= self::ihdr($width, $height);
        $data .= self::idat($width, $height);
        $data .= self::iend( );
        return($data);
    }
    /*创建背景颜色(宽度, 高度)*/
    private function createBackground($width, $height)
    {
        $rnd1 = mt_rand(90, 0);
        $rnd2 = mt_rand(90, 0);
        $rnd3 = mt_rand(90, 0);
        $data = '';
        
        for($i = 0; $i < $height; $i++)
        {
            for($j = 0; $j < $width; $j++)
            {
                $data .= chr((($i * $j) + $width + $height + $rnd1) & 255) . chr($rnd2 & 255) . chr($rnd3 & 255);
            }
        }
        return(self::save('img', $data));
    }
    /*绘制像素点(x, y, 宽度, 高度, r, g, b, 像素大小)*/
    private function drawPixel($x, $y, $width, $height, $r=0, $g=0, $b=0, $size=1)
    {
        $img = self::read('img');
        $offset = 3 * ($width * $y + $x);
        
        for($i = 0; $i < $size;)
        {
            $img[$offset + $i] = chr($r);
            $i++;
            $img[$offset + $i] = chr($g);
            $i++;
            $img[$offset + $i] = chr($b);
            $i++;
        }
        
        return(self::save('img', $img));
    }
    /*绘制字符(字模, 宽度, 高度, 间隔)*/
    private function draw($table, $width, $height, $space=16)
    {
        for($i = 0; $i < 16; $i++)
        {
            for($j = 0; $j < 8; $j++)
            {
                if(($table[$i] >> (7 - $j)) & 0x01)
                {
                    self::drawPixel($space + $j, $i + 2, $width, $height, 255, 255, 255, 1);
                }
            }
        }
        return(true);
    }
    /*ascii码字模表*/
    private function table( )
    {
        $ascii = array
                (
                    '0' => array(0x00,0x00,0x38,0x6C,0xC6,0xC6,0xD6,0xD6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00),
                    '1' => array(0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00),
                    '2' => array(0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00),
                    '3' => array(0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00),
                    '4' => array(0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00),
                    '5' => array(0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00),
                    '6' => array(0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00),
                    '7' => array(0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00),
                    '8' => array(0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00),
                    '9' => array(0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00),
                    'A' => array(0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00),
                    'B' => array(0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00),
                    'C' => array(0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00),
                    'D' => array(0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00),
                    'E' => array(0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00),
                    'F' => array(0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00),
                    'G' => array(0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xDE,0xC6,0xC6,0x66,0x3A,0x00,0x00,0x00,0x00),
                    'H' => array(0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00),
                    'I' => array(0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00),
                    'J' => array(0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00),
                    'K' => array(0x00,0x00,0xE6,0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00),
                    'L' => array(0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00),
                    'M' => array(0x00,0x00,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00),
                    'N' => array(0x00,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00),
                    'O' => array(0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00),
                    'P' => array(0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00),
                    'Q' => array(0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xDE,0x7C,0x0C,0x0E,0x00,0x00),
                    'R' => array(0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00),
                    'S' => array(0x00,0x00,0x7C,0xC6,0xC6,0x60,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00),
                    'T' => array(0x00,0x00,0x7E,0x7E,0x5A,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00),
                    'U' => array(0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00),
                    'V' => array(0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00),
                    'W' => array(0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00),
                    'X' => array(0x00,0x00,0xC6,0xC6,0x6C,0x7C,0x38,0x38,0x7C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00),
                    'Y' => array(0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00),
                    'Z' => array(0x00,0x00,0xFE,0xC6,0x86,0x0C,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00),
                    'a' => array(0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00),
                    'b' => array(0x00,0x00,0xE0,0x60,0x60,0x78,0x6C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00),
                    'c' => array(0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00),
                    'd' => array(0x00,0x00,0x1C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00),
                    'e' => array(0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00),
                    'f' => array(0x00,0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00),
                    'g' => array(0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0xCC,0x78,0x00),
                    'h' => array(0x00,0x00,0xE0,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00),
                    'i' => array(0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00),
                    'j' => array(0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00),
                    'k' => array(0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00),
                    'l' => array(0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00),
                    'm' => array(0x00,0x00,0x00,0x00,0x00,0xEC,0xFE,0xD6,0xD6,0xD6,0xD6,0xC6,0x00,0x00,0x00,0x00),
                    'n' => array(0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00),
                    'o' => array(0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00),
                    'p' => array(0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00),
                    'q' => array(0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00),
                    'r' => array(0x00,0x00,0x00,0x00,0x00,0xDC,0x76,0x66,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00),
                    's' => array(0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x60,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00),
                    't' => array(0x00,0x00,0x10,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00),
                    'u' => array(0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00),
                    'v' => array(0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00),
                    'w' => array(0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x00,0x00,0x00,0x00),
                    'x' => array(0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00),
                    'y' => array(0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00),
                    'z' => array(0x00,0x00,0x00,0x00,0x00,0xFE,0xCC,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00)
                );     
        return($ascii);
    } 
    /*创建CRC校验表*/
    private function crcTable( )
    {
        $z = -306674912;  // = 0xedb88320     
        for ($n = 0; $n < 256; $n++)
        {
            $c = $n;          
            for($k = 0; $k < 8; $k++)
            {
                $c = ($c & 1) ? $z ^ (($c >> 1) & 0x7fffffff) : ($c >> 1) & 0x7fffffff;
            }         
            $crcTable[$n] = $c;
        }    
        return(self::save('crcTable', $crcTable));
    }
    /*png图片文件头*/
    private function headTag( )
    {
        return(pack("c*", 137, 80, 78, 71, 13, 10, 26, 10));
    }
    /*IHDR数据块信息(宽度, 高度)*/
    private function ihdr($width, $height)
    {
        $body = pack("c*", ($width >> 24) & 255, ($width >> 16) & 255, ($width >> 8) & 255, $width & 255, ($height >> 24) & 255, ($height >> 16) & 255, ($height >> 8) & 255, $height & 255, self::depth( ), self::type( ), 0, 0, 0);
        return(self::chunk($body, "IHDR"));
    }
    /*图像深度*/
    private function depth( )
    {
        return(8);
    }
    /*图像类型*/
    private function type( )
    {
        return(2);
    }
    /*数据块(数据, 类型)*/
    private function chunk($data, $type)
    {
        $len = strlen($data);
        $chunk = pack("c*", ($len >> 24) & 255, ($len >> 16) & 255, ($len >> 8) & 255, $len & 255) . $type . $data;
        $c = $z = 16777215 | 255 << 24;
        $chunkLength = strlen($chunk);
        $crcTable = self::read('crcTable');
        for ($i = 4; $i < $chunkLength; $i++)
        {
             $z8 = ($z >> 8) & 0xffffff;
             $z = $crcTable[($z ^ ord($chunk[$i])) & 0xff] ^ $z8;
        }
        $crc = $c ^ $z;
        $chunk .= chr(($crc >> 24) & 255) . chr(($crc >> 16) & 255) . chr(($crc >> 8) & 255) . chr($crc & 255);
        return($chunk);
    }
    /*IDAT数据块(宽度, 高度)*/
    private function idat($width, $height)
    {
        $data = self::read('img');
        $body = '';
        $k = 0;  
        for($h = 0; $h < $height; $h++)
        {
            $body .= chr(0);
            
            for($w = 0; $w < $width * 3; $w++)
            {
                 $body .= $data[$k++];
            }
        } 
        return(self::chunk(self::idatHead($width, $height) . $body . self::adler($body), "IDAT"));
    }
    /*IDAT头信息(宽度, 高度)*/
    private function idatHead($width, $height)
    {
        $len = ($width * 3 + 1) * $height;
        return(pack("c*", 0x78, 0x01, 1, $len & 255, ($len >> 8) & 255, 255 - ($len & 255), 255 - (($len >> 8) & 255)));
    }
    /*计算adler32码(内容数据)*/
    private function adler($data)
    {
        $dataLen = strlen($data);
        $s1 = 1;
        $s2 = 0; 
        for($i = 0; $i < $dataLen; $i++)
        {
            $s1 = ($s1 + ord($data[$i])) % 65521;
            $s2 = ($s2 + $s1) % 65521;
        }
        $adler = ($s2 << 16) | $s1;
        return(chr(($adler >> 24) & 255) . chr(($adler >> 16) & 255) . chr(($adler >> 8) & 255) . chr($adler & 255));
    } 
    /*iend*/
    private function iend( )
    {
        return(self::chunk('', "IEND"));
    }
    /*保存(字段名, 值)*/
    private function save($field, $value)
    {
        $this->info[$field] = $value;
        return(true);
    }
    /*读取(字段名)*/
    private function read($field)
    {
        return($this->info[$field]);
    }
    public function __destruct( )
    {
    }
}
?>