/veriler/f3/lib/graphics.php
PHP | 450 lines | 312 code | 14 blank | 124 comment | 57 complexity | 0932c0615131f98fa6adfa4dd226cd27 MD5 | raw file
- <?php
- /**
- Graphics plugin for the PHP Fat-Free Framework
- The contents of this file are subject to the terms of the GNU General
- Public License Version 3.0. You may not use this file except in
- compliance with the license. Any of the license terms and conditions
- can be waived if you get permission from the copyright holder.
- Copyright (c) 2009-2011 F3::Factory
- Bong Cosca <bong.cosca@yahoo.com>
- @package Graphics
- @version 2.0.4
- **/
- //! Graphics plugin
- class Graphics extends Base {
- //@{ Locale-specific error/exception messages
- const
- TEXT_Image='Unsupported image format',
- TEXT_Color='Invalid color specified';
- //@}
- const
- // Background color
- GFX_BGColor=0xFFF,
- // Foreground transparency
- GFX_Transparency=0x020,
- // Identicon horizontal/vertical blocks
- GFX_IdBlocks=4,
- // Identicon pixels per block
- GFX_IdPixels=64,
- //! PNG compression level
- PNG_Compress=1;
- /**
- Convert RGB hex triad to array
- @return mixed
- @param $int integer
- @public
- **/
- static function rgb($int) {
- $hex=str_pad(dechex($int),$int<4096?3:6,'0',STR_PAD_LEFT);
- $len=strlen($hex);
- if ($len>6) {
- trigger_error(self::TEXT_Color);
- return FALSE;
- }
- $color=str_split($hex,$len/3);
- foreach ($color as &$hue)
- $hue=hexdec(str_repeat($hue,6/$len));
- return $color;
- }
- /**
- Generate CAPTCHA image
- @param $dimx integer
- @param $dimy integer
- @param $len integer
- @param $ttfs string
- @param $var string
- @param $die boolean
- @public
- **/
- static function captcha(
- $dimx=150,$dimy=50,$len=5,$ttfs='cube',$var='captcha',$die=TRUE) {
- $base=self::rgb(self::$vars['BGCOLOR']);
- $trans=self::$vars['FGTRANS'];
- // Specify Captcha seed
- $seed=substr(md5(uniqid()),0,$len);
- F3::set('SESSION.'.$var,$seed);
- // Font size
- $size=.9*min($dimx/$len,$dimy);
- // Load TrueType fonts
- $fonts=self::split($ttfs);
- $file=self::$vars['FONTS'].
- self::fixslashes($fonts[array_rand($fonts)]).'.ttf';
- $stats=&self::ref('STATS');
- if (!isset($stats['FILES']))
- $stats['FILES']=array('fonts'=>array());
- $stats['FILES']['fonts'][basename($file)]=filesize($file);
- $maxdeg=12;
- // Create blank image
- $captcha=imagecreatetruecolor($dimx,$dimy);
- list($r,$g,$b)=$base;
- $bg=imagecolorallocate($captcha,$r,$g,$b);
- imagefill($captcha,0,0,$bg);
- $width=0;
- // Insert each Captcha character
- for ($i=0;$i<$len;$i++) {
- // Random angle
- $angle=$maxdeg-mt_rand(0,$maxdeg*2);
- // Get CAPTCHA character from session cookie
- $char=$seed[$i];
- $fg=imagecolorallocatealpha(
- $captcha,
- mt_rand(0,255-$trans),
- mt_rand(0,255-$trans),
- mt_rand(0,255-$trans),
- $trans
- );
- // Compute bounding box metrics
- $bbox=imagettfbbox($size,0,$file,$char);
- $w=max($bbox[2],$bbox[4])-max($bbox[0],$bbox[6]);
- $h=max($bbox[1],$bbox[3])-max($bbox[5],$bbox[7]);
- $sin=sin(deg2rad($angle));
- imagettftext(
- $captcha,$size,$angle,
- .9*$width+abs($h*$sin),
- $dimy-$h/2+abs($w*$sin),
- $fg,$file,$char
- );
- $width+=$w+abs($h*$sin);
- imagecolordeallocate($captcha,$fg);
- }
- // Make the background transparent
- imagecolortransparent($captcha,$bg);
- // Send output as PNG image
- if (PHP_SAPI!='cli' && !headers_sent()) {
- header(self::HTTP_Content.': image/png');
- header(self::HTTP_Powered.': '.self::TEXT_AppName.' '.
- '('.self::TEXT_AppURL.')');
- }
- imagepng($captcha,NULL,self::PNG_Compress,PNG_NO_FILTER);
- if ($die)
- die;
- }
- /**
- Invert colors of specified image
- @param $file string
- @param $die boolean
- @public
- **/
- static function invert($file,$die=TRUE) {
- preg_match('/\.(gif|jp[e]*g|png)$/',$file,$ext);
- $ext[1]=str_replace('jpg','jpeg',$ext[1]);
- $file=self::fixslashes(self::resolve($file));
- $img=imagecreatefromstring(self::getfile($file));
- imagefilter($img,IMG_FILTER_NEGATE);
- if (PHP_SAPI!='cli' && !headers_sent())
- header(self::HTTP_Content.': image/'.$ext[1]);
- // Send output in same graphics format as original
- eval('image'.$ext[1].'($img);');
- if ($die)
- die;
- }
- /**
- Apply grayscale filter on specified image
- @param $file string
- @param $die boolean
- @public
- **/
- static function grayscale($file,$die=TRUE) {
- preg_match('/\.(gif|jp[e]*g|png)$/',$file,$ext);
- $ext[1]=str_replace('jpg','jpeg',$ext[1]);
- $file=self::fixslashes(self::resolve($file));
- $img=imagecreatefromstring(self::getfile($file));
- imagefilter($img,IMG_FILTER_GRAYSCALE);
- if (PHP_SAPI!='cli' && !headers_sent())
- header(self::HTTP_Content.': image/'.$ext[1]);
- // Send output in same graphics format as original
- eval('image'.$ext[1].'($img);');
- if ($die)
- die;
- }
- /**
- Generate thumbnail image
- @param $file string
- @param $dimx integer
- @param $dimy integer
- @param $die boolean
- @public
- **/
- static function thumb($file,$dimx,$dimy,$die=TRUE) {
- preg_match('/\.(gif|jp[e]*g|png)$/',$file,$ext);
- if ($ext) {
- $ext[1]=str_replace('jpg','jpeg',$ext[1]);
- $file=self::fixslashes(self::resolve($file));
- $img=imagecreatefromstring(self::getfile($file));
- // Get image dimensions
- $oldx=imagesx($img);
- $oldy=imagesy($img);
- // Adjust dimensions; retain aspect ratio
- $ratio=$oldx/$oldy;
- if ($dimx<=$oldx && $dimx/$ratio<=$dimy)
- // Adjust height
- $dimy=$dimx/$ratio;
- elseif ($dimy<=$oldy && $dimy*$ratio<=$dimx)
- // Adjust width
- $dimx=$dimy*$ratio;
- else {
- // Retain size if dimensions exceed original image
- $dimx=$oldx;
- $dimy=$oldy;
- }
- // Create blank image
- $tmp=imagecreatetruecolor($dimx,$dimy);
- list($r,$g,$b)=self::rgb(self::$vars['BGCOLOR']);
- $bg=imagecolorallocate($tmp,$r,$g,$b);
- imagefill($tmp,0,0,$bg);
- // Resize
- imagecopyresampled($tmp,$img,0,0,0,0,$dimx,$dimy,$oldx,$oldy);
- // Make the background transparent
- imagecolortransparent($tmp,$bg);
- if (PHP_SAPI!='cli' && !headers_sent()) {
- header(self::HTTP_Content.': image/'.$ext[1]);
- header(self::HTTP_Powered.': '.self::TEXT_AppName.' '.
- '('.self::TEXT_AppURL.')');
- }
- // Send output in same graphics format as original
- eval('image'.$ext[1].'($tmp);');
- }
- else
- trigger_error(self::TEXT_Image);
- if ($die)
- die;
- }
- /**
- Generate identicon from an MD5 hash value
- @param $hash string
- @param $size integer
- @param $die boolean
- @public
- **/
- static function identicon($hash,$size=NULL,$die=TRUE) {
- $hash=self::resolve($hash);
- $blox=self::$vars['IBLOCKS'];
- if (is_null($size))
- $size=self::$vars['IPIXELS'];
- // Rotatable shapes
- $dynamic=array(
- array(.5,1,1,0,1,1),
- array(.5,0,1,0,.5,1,0,1),
- array(.5,0,1,0,1,1,.5,1,1,.5),
- array(0,.5,.5,0,1,.5,.5,1,.5,.5),
- array(0,.5,1,0,1,1,0,1,1,.5),
- array(1,0,1,1,.5,1,1,.5,.5,.5),
- array(0,0,1,0,1,.5,0,0,.5,1,0,1),
- array(0,0,.5,0,1,.5,.5,1,0,1,.5,.5),
- array(.5,0,.5,.5,1,.5,1,1,.5,1,.5,.5,0,.5),
- array(0,0,1,0,.5,.5,1,.5,.5,1,.5,.5,0,1),
- array(0,.5,.5,1,1,.5,.5,0,1,0,1,1,0,1),
- array(.5,0,1,0,1,1,.5,1,1,.75,.5,.5,1,.25),
- array(0,.5,.5,0,.5,.5,1,0,1,.5,.5,1,.5,.5,0,1),
- array(0,0,1,0,1,1,0,1,1,.5,.5,.25,.5,.75,0,.5,.5,.25),
- array(0,.5,.5,.5,.5,0,1,0,.5,.5,1,.5,.5,1,.5,.5,0,1),
- array(0,0,1,0,.5,.5,.5,0,0,.5,1,.5,.5,1,.5,.5,0,1)
- );
- // Fixed shapes (for center sprite)
- $static=array(
- array(),
- array(0,0,1,0,1,1,0,1),
- array(.5,0,1,.5,.5,1,0,.5),
- array(0,0,1,0,1,1,0,1,0,.5,.5,1,1,.5,.5,0,0,.5),
- array(.25,0,.75,0,.5,.5,1,.25,1,.75,.5,.5,
- .75,1,.25,1,.5,.5,0,.75,0,.25,.5,.5),
- array(0,0,.5,.25,1,0,.75,.5,1,1,.5,.75,0,1,.25,.5),
- array(.33,.33,.67,.33,.67,.67,.33,.67),
- array(0,0,.33,0,.33,.33,.67,.33,.67,0,1,0,1,.33,.67,.33,
- .67,.67,1,.67,1,1,.67,1,.67,.67,.33,.67,.33,1,0,1,
- 0,.67,.33,.67,.33,.33,0,.33)
- );
- // Parse MD5 hash
- list($bgR,$bgG,$bgB)=self::rgb(self::$vars['BGCOLOR']);
- list($fgR,$fgG,$fgB)=self::rgb(hexdec(substr($hash,0,6)));
- $shapeC=hexdec($hash[6]);
- $angleC=hexdec($hash[7]%4);
- $shapeX=hexdec($hash[8]);
- for ($i=0;$i<$blox-2;$i++) {
- $shapeS[$i]=hexdec($hash[9+$i*2]);
- $angleS[$i]=hexdec($hash[10+$i*2]%4);
- }
- // Start with NxN blank slate
- $identicon=imagecreatetruecolor($size*$blox,$size*$blox);
- imageantialias($identicon,TRUE);
- $bg=imagecolorallocate($identicon,$bgR,$bgG,$bgB);
- $fg=imagecolorallocate($identicon,$fgR,$fgG,$fgB);
- // Generate corner sprites
- $corner=imagecreatetruecolor($size,$size);
- imagefill($corner,0,0,$bg);
- $sprite=$dynamic[$shapeC];
- for ($i=0,$len=count($sprite);$i<$len;$i++)
- $sprite[$i]=$sprite[$i]*$size;
- imagefilledpolygon($corner,$sprite,$len/2,$fg);
- for ($i=0;$i<$angleC;$i++)
- $corner=imagerotate($corner,90,$bg);
- // Generate side sprites
- for ($i=0;$i<$blox-2;$i++) {
- $side[$i]=imagecreatetruecolor($size,$size);
- imagefill($side[$i],0,0,$bg);
- $sprite=$dynamic[$shapeS[$i]];
- for ($j=0,$len=count($sprite);$j<$len;$j++)
- $sprite[$j]=$sprite[$j]*$size;
- imagefilledpolygon($side[$i],$sprite,$len/2,$fg);
- for ($j=0;$j<$angleS[$i];$j++)
- $side[$i]=imagerotate($side[$i],90,$bg);
- }
- // Generate center sprites
- for ($i=0;$i<$blox-2;$i++) {
- $center[$i]=imagecreatetruecolor($size,$size);
- imagefill($center[$i],0,0,$bg);
- $sprite=$dynamic[$shapeX];
- if ($blox%2>0 && $i==$blox-3)
- // Odd center sprites
- $sprite=$static[$shapeX%8];
- $len=count($sprite);
- if ($len) {
- for ($j=0;$j<$len;$j++)
- $sprite[$j]=$sprite[$j]*$size;
- imagefilledpolygon($center[$i],$sprite,$len/2,$fg);
- }
- if ($i<($blox-3))
- for ($j=0;$j<$angleS[$i];$j++)
- $center[$i]=imagerotate($center[$i],90,$bg);
- }
- // Paste sprites
- for ($i=0;$i<4;$i++) {
- imagecopy($identicon,$corner,0,0,0,0,$size,$size);
- for ($j=0;$j<$blox-2;$j++) {
- imagecopy($identicon,$side[$j],
- $size*($j+1),0,0,0,$size,$size);
- for ($k=$j;$k<$blox-3-$j;$k++)
- imagecopy($identicon,$center[$k],
- $size*($k+1),$size*($j+1),0,0,$size,$size);
- }
- $identicon=imagerotate($identicon,90,$bg);
- }
- if ($blox%2>0)
- // Paste odd center sprite
- imagecopy($identicon,$center[$blox-3],
- $size*(floor($blox/2)),$size*(floor($blox/2)),0,0,
- $size,$size);
- // Resize
- $resized=imagecreatetruecolor($size,$size);
- imagecopyresampled($resized,$identicon,0,0,0,0,$size,$size,
- $size*$blox,$size*$blox);
- // Make the background transparent
- imagecolortransparent($resized,$bg);
- if (PHP_SAPI!='cli' && !headers_sent()) {
- header(self::HTTP_Content.': image/png');
- header(self::HTTP_Powered.': '.self::TEXT_AppName.' '.
- '('.self::TEXT_AppURL.')');
- }
- imagepng($resized,NULL,self::PNG_Compress,PNG_NO_FILTER);
- if ($die)
- die;
- }
- /**
- Generate a blank image for use as a placeholder
- @param $dimx integer
- @param $dimy integer
- @param $bg string
- @param $die boolean
- @public
- **/
- static function fakeImage($dimx,$dimy,$bg=0xEEE,$die=TRUE) {
- list($r,$g,$b)=self::rgb($bg);
- $img=imagecreatetruecolor($dimx,$dimy);
- $bg=imagecolorallocate($img,$r,$g,$b);
- imagefill($img,0,0,$bg);
- if (PHP_SAPI!='cli' && !headers_sent()) {
- header(self::HTTP_Content.': image/png');
- header(self::HTTP_Powered.': '.self::TEXT_AppName.' '.
- '('.self::TEXT_AppURL.')');
- }
- imagepng($img,NULL,self::PNG_Compress,PNG_NO_FILTER);
- if ($die)
- die;
- }
- /**
- Grab HTML page and render using WebKit engine;
- Crop image and generate thumbnail, if specified
- @param $url string
- @param $dimx integer
- @param $dimy integer
- @param $cropw integer
- @param $croph integer
- @param $die boolean
- @public
- **/
- static function screenshot(
- $url,$dimx=0,$dimy=0,$cropw=0,$croph=0,$die=TRUE) {
- $file=self::$vars['TEMP'].$_SERVER['SERVER_NAME'].
- '.scr.'.self::hash($url).'.jpg';
- // Map OS to folder location
- $exec=array(
- 'Windows|WINNT'=>'windows',
- 'Darwin'=>'osx',
- 'Linux'=>'linux'
- );
- foreach ($exec as $os=>$dir)
- if (preg_match('/'.$os.'/i',PHP_OS)) {
- $win=($dir=='windows');
- // Suppress text output
- $null=$win?'nul':'null';
- exec(($win?'start /b ':'').
- self::$vars['EXTERNAL'].$dir.'/wkhtmltoimage '.
- ($cropw?('--crop-w '.$cropw.' '):'').
- ($croph?('--crop-h '.$croph.' '):'').
- $url.' '.$file.' >'.$null.' 2>'.$null);
- break;
- }
- if (is_file($file)) {
- if ($dimx && $dimy)
- self::thumb($file,$dimx,$dimy,FALSE);
- elseif (PHP_SAPI!='cli' && !headers_sent()) {
- header(self::HTTP_Content.': image/png');
- header(self::HTTP_Powered.': '.self::TEXT_AppName.' '.
- '('.self::TEXT_AppURL.')');
- echo self::getfile($file);
- }
- unlink($file);
- }
- if ($die)
- die;
- }
- /**
- Class initializer
- @public
- **/
- static function onload() {
- if (!extension_loaded('gd')) {
- // GD extension required
- trigger_error(sprintf(self::TEXT_PHPExt,'gd'));
- }
- if (!isset(self::$vars['EXTERNAL']))
- self::$vars['EXTERNAL']=self::$vars['ROOT'];
- if (!isset(self::$vars['FONTS']))
- self::$vars['FONTS']=self::$vars['ROOT'];
- if (!isset(self::$vars['BGCOLOR']))
- self::$vars['BGCOLOR']=self::GFX_BGColor;
- if (!isset(self::$vars['FGTRANS']))
- self::$vars['FGTRANS']=self::GFX_Transparency;
- if (!isset(self::$vars['IBLOCKS']))
- self::$vars['IBLOCKS']=self::GFX_IdBlocks;
- if (!isset(self::$vars['IPIXELS']))
- self::$vars['IPIXELS']=self::GFX_IdPixels;
- }
- }