diff options
author | Nils Schwabe | 2014-06-04 14:27:03 +0200 |
---|---|---|
committer | Nils Schwabe | 2014-06-04 14:27:03 +0200 |
commit | 155cf6aeea9ba7ecbc39face6442d3ce1b03ad8e (patch) | |
tree | 1dcc8354eaf6ce216461fc434d9c1a6a67559914 /management-interface/lib/image.php | |
parent | Improve login (diff) | |
download | masterserver-155cf6aeea9ba7ecbc39face6442d3ce1b03ad8e.tar.gz masterserver-155cf6aeea9ba7ecbc39face6442d3ce1b03ad8e.tar.xz masterserver-155cf6aeea9ba7ecbc39face6442d3ce1b03ad8e.zip |
Add webinterface with functionallity
Diffstat (limited to 'management-interface/lib/image.php')
-rw-r--r-- | management-interface/lib/image.php | 571 |
1 files changed, 571 insertions, 0 deletions
diff --git a/management-interface/lib/image.php b/management-interface/lib/image.php new file mode 100644 index 0000000..c328f83 --- /dev/null +++ b/management-interface/lib/image.php @@ -0,0 +1,571 @@ +<?php + +/* + Copyright (c) 2009-2014 F3::Factory/Bong Cosca, All rights reserved. + + This file is part of the Fat-Free Framework (http://fatfree.sf.net). + + THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF + ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + + Please see the license.txt file for more information. +*/ + +//! Image manipulation tools +class Image { + + //@{ Messages + const + E_Color='Invalid color specified: %s', + E_Font='CAPTCHA font not found', + E_Length='Invalid CAPTCHA length: %s'; + //@} + + //@{ Positional cues + const + POS_Left=1, + POS_Center=2, + POS_Right=4, + POS_Top=8, + POS_Middle=16, + POS_Bottom=32; + //@} + + protected + //! Source filename + $file, + //! Image resource + $data, + //! Enable/disable history + $flag=FALSE, + //! Filter count + $count=0; + + /** + * Convert RGB hex triad to array + * @return array|FALSE + * @param $color int + **/ + function rgb($color) { + $hex=str_pad($hex=dechex($color),$color<4096?3:6,'0',STR_PAD_LEFT); + if (($len=strlen($hex))>6) + user_error(sprintf(self::E_Color,'0x'.$hex)); + $color=str_split($hex,$len/3); + foreach ($color as &$hue) { + $hue=hexdec(str_repeat($hue,6/$len)); + unset($hue); + } + return $color; + } + + /** + * Invert image + * @return object + **/ + function invert() { + imagefilter($this->data,IMG_FILTER_NEGATE); + return $this->save(); + } + + /** + * Adjust brightness (range:-255 to 255) + * @return object + * @param $level int + **/ + function brightness($level) { + imagefilter($this->data,IMG_FILTER_BRIGHTNESS,$level); + return $this->save(); + } + + /** + * Adjust contrast (range:-100 to 100) + * @return object + * @param $level int + **/ + function contrast($level) { + imagefilter($this->data,IMG_FILTER_CONTRAST,$level); + return $this->save(); + } + + /** + * Convert to grayscale + * @return object + **/ + function grayscale() { + imagefilter($this->data,IMG_FILTER_GRAYSCALE); + return $this->save(); + } + + /** + * Adjust smoothness + * @return object + * @param $level int + **/ + function smooth($level) { + imagefilter($this->data,IMG_FILTER_SMOOTH,$level); + return $this->save(); + } + + /** + * Emboss the image + * @return object + **/ + function emboss() { + imagefilter($this->data,IMG_FILTER_EMBOSS); + return $this->save(); + } + + /** + * Apply sepia effect + * @return object + **/ + function sepia() { + imagefilter($this->data,IMG_FILTER_GRAYSCALE); + imagefilter($this->data,IMG_FILTER_COLORIZE,90,60,45); + return $this->save(); + } + + /** + * Pixelate the image + * @return object + * @param $size int + **/ + function pixelate($size) { + imagefilter($this->data,IMG_FILTER_PIXELATE,$size,TRUE); + return $this->save(); + } + + /** + * Blur the image using Gaussian filter + * @return object + * @param $selective bool + **/ + function blur($selective=FALSE) { + imagefilter($this->data, + $selective?IMG_FILTER_SELECTIVE_BLUR:IMG_FILTER_GAUSSIAN_BLUR); + return $this->save(); + } + + /** + * Apply sketch effect + * @return object + **/ + function sketch() { + imagefilter($this->data,IMG_FILTER_MEAN_REMOVAL); + return $this->save(); + } + + /** + * Flip on horizontal axis + * @return object + **/ + function hflip() { + $tmp=imagecreatetruecolor( + $width=$this->width(),$height=$this->height()); + imagesavealpha($tmp,TRUE); + imagefill($tmp,0,0,IMG_COLOR_TRANSPARENT); + imagecopyresampled($tmp,$this->data, + 0,0,$width-1,0,$width,$height,-$width,$height); + imagedestroy($this->data); + $this->data=$tmp; + return $this->save(); + } + + /** + * Flip on vertical axis + * @return object + **/ + function vflip() { + $tmp=imagecreatetruecolor( + $width=$this->width(),$height=$this->height()); + imagesavealpha($tmp,TRUE); + imagefill($tmp,0,0,IMG_COLOR_TRANSPARENT); + imagecopyresampled($tmp,$this->data, + 0,0,0,$height-1,$width,$height,$width,-$height); + imagedestroy($this->data); + $this->data=$tmp; + return $this->save(); + } + + /** + * Crop the image + * @return object + * @param $x1 int + * @param $y1 int + * @param $x2 int + * @param $y2 int + **/ + function crop($x1,$y1,$x2,$y2) { + $tmp=imagecreatetruecolor($width=$x2-$x1+1,$height=$y2-$y1+1); + imagesavealpha($tmp,TRUE); + imagefill($tmp,0,0,IMG_COLOR_TRANSPARENT); + imagecopyresampled($tmp,$this->data, + 0,0,$x1,$y1,$width,$height,$width,$height); + imagedestroy($this->data); + $this->data=$tmp; + return $this->save(); + } + + /** + * Resize image (Maintain aspect ratio); Crop relative to center + * if flag is enabled; Enlargement allowed if flag is enabled + * @return object + * @param $width int + * @param $height int + * @param $crop bool + * @param $enlarge bool + **/ + function resize($width,$height,$crop=TRUE,$enlarge=TRUE) { + // Adjust dimensions; retain aspect ratio + $ratio=($origw=imagesx($this->data))/($origh=imagesy($this->data)); + if (!$crop) + if ($width/$ratio<=$height) + $height=$width/$ratio; + else + $width=$height*$ratio; + if (!$enlarge) { + $width=min($origw,$width); + $height=min($origh,$height); + } + // Create blank image + $tmp=imagecreatetruecolor($width,$height); + imagesavealpha($tmp,TRUE); + imagefill($tmp,0,0,IMG_COLOR_TRANSPARENT); + // Resize + if ($crop) { + if ($width/$ratio<=$height) { + $cropw=$origh*$width/$height; + imagecopyresampled($tmp,$this->data, + 0,0,($origw-$cropw)/2,0,$width,$height,$cropw,$origh); + } + else { + $croph=$origw*$height/$width; + imagecopyresampled($tmp,$this->data, + 0,0,0,($origh-$croph)/2,$width,$height,$origw,$croph); + } + } + else + imagecopyresampled($tmp,$this->data, + 0,0,0,0,$width,$height,$origw,$origh); + imagedestroy($this->data); + $this->data=$tmp; + return $this->save(); + } + + /** + * Rotate image + * @return object + * @param $angle int + **/ + function rotate($angle) { + $this->data=imagerotate($this->data,$angle, + imagecolorallocatealpha($this->data,0,0,0,127)); + imagesavealpha($this->data,TRUE); + return $this->save(); + } + + /** + * Apply an image overlay + * @return object + * @param $img object + * @param $align int + **/ + function overlay(Image $img,$align=NULL) { + if (is_null($align)) + $align=self::POS_Right|self::POS_Bottom; + $ovr=imagecreatefromstring($img->dump()); + imagesavealpha($ovr,TRUE); + $imgw=$this->width(); + $imgh=$this->height(); + $ovrw=imagesx($ovr); + $ovrh=imagesy($ovr); + if ($align & self::POS_Left) + $posx=0; + if ($align & self::POS_Center) + $posx=($imgw-$ovrw)/2; + if ($align & self::POS_Right) + $posx=$imgw-$ovrw; + if ($align & self::POS_Top) + $posy=0; + if ($align & self::POS_Middle) + $posy=($imgh-$ovrh)/2; + if ($align & self::POS_Bottom) + $posy=$imgh-$ovrh; + if (empty($posx)) + $posx=0; + if (empty($posy)) + $posy=0; + imagecopy($this->data,$ovr,$posx,$posy,0,0,$ovrw,$ovrh); + return $this->save(); + } + + /** + * Generate identicon + * @return object + * @param $str string + * @param $size int + * @param $blocks int + **/ + function identicon($str,$size=64,$blocks=4) { + $sprites=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) + ); + $hash=sha1($str); + $this->data=imagecreatetruecolor($size,$size); + list($r,$g,$b)=$this->rgb(hexdec(substr($hash,-3))); + $fg=imagecolorallocate($this->data,$r,$g,$b); + imagefill($this->data,0,0,IMG_COLOR_TRANSPARENT); + $ctr=count($sprites); + $dim=$blocks*floor($size/$blocks)*2/$blocks; + for ($j=0,$y=ceil($blocks/2);$j<$y;$j++) + for ($i=$j,$x=$blocks-1-$j;$i<$x;$i++) { + $sprite=imagecreatetruecolor($dim,$dim); + imagefill($sprite,0,0,IMG_COLOR_TRANSPARENT); + if ($block=$sprites[ + hexdec($hash[($j*$blocks+$i)*2])%$ctr]) { + for ($k=0,$pts=count($block);$k<$pts;$k++) + $block[$k]*=$dim; + imagefilledpolygon($sprite,$block,$pts/2,$fg); + } + $sprite=imagerotate($sprite, + 90*(hexdec($hash[($j*$blocks+$i)*2+1])%4), + imagecolorallocatealpha($sprite,0,0,0,127)); + for ($k=0;$k<4;$k++) { + imagecopyresampled($this->data,$sprite, + $i*$dim/2,$j*$dim/2,0,0,$dim/2,$dim/2,$dim,$dim); + $this->data=imagerotate($this->data,90, + imagecolorallocatealpha($this->data,0,0,0,127)); + } + imagedestroy($sprite); + } + imagesavealpha($this->data,TRUE); + return $this->save(); + } + + /** + * Generate CAPTCHA image + * @return object|FALSE + * @param $font string + * @param $size int + * @param $len int + * @param $key string + * @param $path string + * @param $fg int + * @param $bg int + **/ + function captcha($font,$size=24,$len=5, + $key=NULL,$path='',$fg=0xFFFFFF,$bg=0x000000) { + if ((!$ssl=extension_loaded('openssl')) && ($len<4 || $len>13)) { + user_error(sprintf(self::E_Length,$len)); + return FALSE; + } + $fw=Base::instance(); + foreach ($fw->split($path?:$fw->get('UI').';./') as $dir) + if (is_file($path=$dir.$font)) { + $seed=strtoupper(substr( + $ssl?bin2hex(openssl_random_pseudo_bytes($len)):uniqid(), + -$len)); + $block=$size*3; + $tmp=array(); + for ($i=0,$width=0,$height=0;$i<$len;$i++) { + // Process at 2x magnification + $box=imagettfbbox($size*2,0,$path,$seed[$i]); + $w=$box[2]-$box[0]; + $h=$box[1]-$box[5]; + $char=imagecreatetruecolor($block,$block); + imagefill($char,0,0,$bg); + imagettftext($char,$size*2,0, + ($block-$w)/2,$block-($block-$h)/2, + $fg,$path,$seed[$i]); + $char=imagerotate($char,mt_rand(-30,30), + imagecolorallocatealpha($char,0,0,0,127)); + // Reduce to normal size + $tmp[$i]=imagecreatetruecolor( + ($w=imagesx($char))/2,($h=imagesy($char))/2); + imagefill($tmp[$i],0,0,IMG_COLOR_TRANSPARENT); + imagecopyresampled($tmp[$i],$char,0,0,0,0,$w/2,$h/2,$w,$h); + imagedestroy($char); + $width+=$i+1<$len?$block/2:$w/2; + $height=max($height,$h/2); + } + $this->data=imagecreatetruecolor($width,$height); + imagefill($this->data,0,0,IMG_COLOR_TRANSPARENT); + for ($i=0;$i<$len;$i++) { + imagecopy($this->data,$tmp[$i], + $i*$block/2,($height-imagesy($tmp[$i]))/2,0,0, + imagesx($tmp[$i]),imagesy($tmp[$i])); + imagedestroy($tmp[$i]); + } + imagesavealpha($this->data,TRUE); + if ($key) + $fw->set($key,$seed); + return $this->save(); + } + user_error(self::E_Font); + return FALSE; + } + + /** + * Return image width + * @return int + **/ + function width() { + return imagesx($this->data); + } + + /** + * Return image height + * @return int + **/ + function height() { + return imagesy($this->data); + } + + /** + * Send image to HTTP client + * @return NULL + **/ + function render() { + $args=func_get_args(); + $format=$args?array_shift($args):'png'; + if (PHP_SAPI!='cli') { + header('Content-Type: image/'.$format); + header('X-Powered-By: '.Base::instance()->get('PACKAGE')); + } + call_user_func_array('image'.$format, + array_merge(array($this->data),$args)); + } + + /** + * Return image as a string + * @return string + **/ + function dump() { + $args=func_get_args(); + $format=$args?array_shift($args):'png'; + ob_start(); + call_user_func_array('image'.$format, + array_merge(array($this->data),$args)); + return ob_get_clean(); + } + + /** + * Save current state + * @return object + **/ + function save() { + $fw=Base::instance(); + if ($this->flag) { + if (!is_dir($dir=$fw->get('TEMP'))) + mkdir($dir,Base::MODE,TRUE); + $this->count++; + $fw->write($dir.'/'. + $fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. + $fw->hash($this->file).'-'.$this->count.'.png', + $this->dump()); + } + return $this; + } + + /** + * Revert to specified state + * @return object + * @param $state int + **/ + function restore($state=1) { + $fw=Base::instance(); + if ($this->flag && is_file($file=($path=$fw->get('TEMP'). + $fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. + $fw->hash($this->file).'-').$state.'.png')) { + if (is_resource($this->data)) + imagedestroy($this->data); + $this->data=imagecreatefromstring($fw->read($file)); + imagesavealpha($this->data,TRUE); + foreach (glob($path.'*.png',GLOB_NOSORT) as $match) + if (preg_match('/-(\d+)\.png/',$match,$parts) && + $parts[1]>$state) + @unlink($match); + $this->count=$state; + } + return $this; + } + + /** + * Undo most recently applied filter + * @return object + **/ + function undo() { + if ($this->flag) { + if ($this->count) + $this->count--; + return $this->restore($this->count); + } + return $this; + } + + /** + * Load string + * @return object + * @param $str string + **/ + function load($str) { + $this->data=imagecreatefromstring($str); + imagesavealpha($this->data,TRUE); + $this->save(); + return $this; + } + + /** + * Instantiate image + * @param $file string + * @param $flag bool + * @param $path string + **/ + function __construct($file=NULL,$flag=FALSE,$path='') { + $this->flag=$flag; + if ($file) { + $fw=Base::instance(); + // Create image from file + $this->file=$file; + foreach ($fw->split($path?:$fw->get('UI').';./') as $dir) + if (is_file($dir.$file)) + return $this->load($fw->read($dir.$file)); + } + } + + /** + * Wrap-up + * @return NULL + **/ + function __destruct() { + if (is_resource($this->data)) { + imagedestroy($this->data); + $fw=Base::instance(); + $path=$fw->get('TEMP'). + $fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. + $fw->hash($this->file); + if ($glob=@glob($path.'*.png',GLOB_NOSORT)) + foreach ($glob as $match) + if (preg_match('/-(\d+)\.png/',$match)) + @unlink($match); + } + } + +} |