├── LICENSE ├── README.md └── image_moo.php /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Mat-Moo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | image_moo 2 | ========= 3 | 4 | image_moo (PHP Image manipulation class) 5 | 6 | http://www.matmoo.com/digital-dribble/codeigniter/image_moo/ -------------------------------------------------------------------------------- /image_moo.php: -------------------------------------------------------------------------------- 1 | image_moo->load("file")->resize(64,40)->save("thumb")->resize(640,480)->save("medium"); 23 | * if ($this->image_moo->errors) print $this->image_moo->display_errors(); 24 | * 25 | * COLOURS! 26 | * Any function that can take a colour as a parameter can take "#RGB", "#RRGGBB" or an array(R,G,B) 27 | * 28 | * image manipulation functions 29 | * ----------------------------------------------------------------------------- 30 | * load($x) - Loads an image file specified by $x - JPG, PNG, GIF, WEBP supported 31 | * load_temp() - Takes a cropped/altered image and makes it the main image to work with. 32 | * save($x) - Saved the manipulated image (if applicable) to file $x - JPG, PNG, GIF, WEBP supported 33 | * get_data_stream($filename="") - Return the image as a stream so that it can be sent as source data to the output 34 | * save_pa($prepend="", $append="", $overwrite=FALSE) - Saves using the original image name but with prepend and append text, e.g. load('moo.jpg')->save_pa('pre_','_app') would save as filename pre_moo_app.jpg 35 | * save_dynamic($filename="") - Saves as a stream output, use filename to return png/jpg/gif/webp etc., default is jpeg 36 | * resize($x,$y=FALSE,$pad=FALSE) - Proportionally resize original image using the bounds $x and $y (if y is false x size is used), if padding is set return image is as defined centralised using BG colour 37 | * resize_crop($x,$y) - Proportionally resize original image using the bounds $x and $y but cropped to fill dimensions 38 | * stretch($x,$y) - Take the original image and stretch it to fill new dimensions $x $y 39 | * crop($x1,$y1,$x2,$y2) - Crop the original image using Top left, $x1,$y1 to bottom right $x2,y2. New image size =$x2-x1 x $y2-y1 40 | * rotate($angle) - Rotates the work image by X degrees, normally 90,180,270 can be any angle.Excess filled with background colour 41 | * load_watermark($filename, $transparent_x=0, $transparent_y=0) - Loads the specified file as the watermark file, if using PNG32/24 use x,y to specify direct positions of colour to use as index 42 | * make_watermark_text($text, $fontfile, $size=16, $colour="#ffffff", $angle=0) - Creates a text watermark 43 | * watermark($position, $offset=8, $abs=FALSE) - Use the loaded watermark, or created text to place a watermark. $position works like NUM PAD key layout, e.g. 7=Top left, 3=Bottom right $offset is the padding/indentation, if $abs is true then use $positiona and $offset as direct values to watermark placement 44 | * border($width,$colour="#000") - Draw a border around the output image X pixels wide in colour specified 45 | * border_3d($width,$rot=0,$opacity=30) - Draw a 3d border (opaque) around the current image $width wise in 0-3 rot positions, $opacity allows you to change how much it effects the picture 46 | * filter($function, $arg1=NULL, $arg2=NULL, $arg3=NULL, $arg4=NULL) -Runs the standard imagefilter GD2 command, see http://www.php.net/manual/en/function.imagefilter.php for details 47 | * round($radius,$invert=FALSE,$corners(array[top left, top right, bottom right, bottom left of true or False)="") default is all on and normal rounding 48 | * shadow($size=4, $direction=3, $colour="#444") - Size in pixels, note that the image will increase by this size, so resize(400,400)->shadoe(4) will give an image 404 pixels in size, Direction works on teh keypad basis like the watermark, so 3 is bottom right, $color if the colour of the shadow. 49 | * ----------------------------------------------------------------------------- 50 | * image helper functions 51 | * ignore_jpeg_warnings - Sets the gd.jpeg_ignore_warning to help load images that may otherwise not work 52 | * allow_scale_up($onoff = FALSE) - When using resize, setting this to tru will allow small images to increase in size, otherwise they do not get resized 53 | * real_filesize() - returns the filesize of the image in bytes etc. 54 | * display_errors($open = '

', $close = '

') - Display errors as Ci standard style 55 | * set_jpeg_quality($x) - quality to write jpeg/webp files in for save, default 75 (1-100) 56 | * set_watermark_transparency($x) - the opacity of the watermark 1-100, 1-just about see, 100=solid 57 | * check_gd() - Run to see if you server can use this library 58 | * clear_temp() - Call to clear the temp changes using the master image again 59 | * clear() - Clears all images in memory 60 | * ----------------------------------------------------------------------------- 61 | * 62 | * KNOWN BUGS 63 | * make_watermark_text does not deal with rotation angle correctly, box is cropped 64 | * 65 | * TO DO 66 | * 67 | * THANKS 68 | * Matjaž for poiting out the save_pa bug (should of tested it!) 69 | * Cahva for posting yet another bug in the save_pa (Man I can be silly sometimes!) 70 | * Cole spotting the resize flaw and providing a fix 71 | * Nuno Mira for suggesting the new width/new size on teh ci forums 72 | * HugoSolar for transparent rotate 73 | * EbbenF/Locally.com for webp support 74 | * 75 | */ 76 | 77 | class Image_moo 78 | { 79 | // image vars 80 | private $main_image = ""; 81 | private $watermark_image; 82 | private $temp_image; 83 | private $jpeg_quality = 75; 84 | private $background_colour = "#ffffff"; 85 | private $watermark_method; 86 | private $jpeg_ignore_warnings = FALSE; // set to true or call ignore_jpeg_warnings() 87 | private $can_stretch = FALSE; // when a resizing an image too small, allow it to be stretched larger 88 | 89 | // other 90 | private $filename = ""; 91 | 92 | // watermark stuff, opacity 93 | private $watermark_transparency = 50; 94 | 95 | // reported errors 96 | public $errors = FALSE; 97 | private $error_msg = array(); 98 | 99 | // image info 100 | public $width = 0; 101 | public $height = 0; 102 | public $new_width = 0; 103 | public $new_height = 0; 104 | 105 | function __construct() 106 | //---------------------------------------------------------------------------------------------------------- 107 | // create stuff here as needed 108 | //---------------------------------------------------------------------------------------------------------- 109 | { 110 | // log_message('debug', "Image Moo Class Initialized"); 111 | if ($this->jpeg_ignore_warnings) $this->ignore_jpeg_warnings(); 112 | if ($this->can_stretch) $this->can_stretch(TRUE); 113 | } 114 | 115 | public function ignore_jpeg_warnings($onoff = TRUE) 116 | //---------------------------------------------------------------------------------------------------------- 117 | // having loaded lots of jpegs I quite often get corrupt ones, this setting relaxs GD a bit 118 | // requires 5.1.3 php 119 | //---------------------------------------------------------------------------------------------------------- 120 | { 121 | ini_set('gd.jpeg_ignore_warning', $onoff == TRUE); 122 | return $this; 123 | } 124 | 125 | public function allow_scale_up($onoff = FALSE) 126 | //---------------------------------------------------------------------------------------------------------- 127 | // If you want to stretch or crop images that are smaller than the target size, call this with TRUE to scale 128 | // up 129 | //---------------------------------------------------------------------------------------------------------- 130 | { 131 | $this->can_stretch = $onoff; 132 | return $this; 133 | } 134 | 135 | private function _clear_errors() 136 | //---------------------------------------------------------------------------------------------------------- 137 | // load a resource 138 | //---------------------------------------------------------------------------------------------------------- 139 | { 140 | $this->error_msg = array(); 141 | } 142 | 143 | private function set_error($msg) 144 | //---------------------------------------------------------------------------------------------------------- 145 | // Set an error message 146 | //---------------------------------------------------------------------------------------------------------- 147 | { 148 | $this->errors = TRUE; 149 | $this->error_msg[] = $msg; 150 | } 151 | 152 | public function display_errors($open = '

', $close = '

') 153 | //---------------------------------------------------------------------------------------------------------- 154 | // returns the errors formatted as needed, same as CI doed 155 | //---------------------------------------------------------------------------------------------------------- 156 | { 157 | $str = ''; 158 | foreach ($this->error_msg as $val) 159 | { 160 | $str .= $open.$val.$close; 161 | } 162 | return $str; 163 | } 164 | 165 | public function check_gd() 166 | //---------------------------------------------------------------------------------------------------------- 167 | // verification util to see if you can use image_moo 168 | //---------------------------------------------------------------------------------------------------------- 169 | { 170 | // is gd loaded? 171 | if ( ! extension_loaded('gd')) 172 | { 173 | if ( ! dl('gd.so')) 174 | { 175 | $this->set_error('GD library does not appear to be loaded'); 176 | return FALSE; 177 | } 178 | } 179 | 180 | // check version 181 | if (function_exists('gd_info')) 182 | { 183 | $gdarray = @gd_info(); 184 | $versiontxt = preg_replace('/[A-Z,\ ()\[\]]/i', '', $gdarray['GD Version']); 185 | $versionparts=explode('.',$versiontxt); 186 | // looking for a version 2 187 | if ($versionparts[0]=="2") 188 | { 189 | return TRUE; 190 | } 191 | else 192 | { 193 | $this->set_error('Requires GD2, this reported as '.$versiontxt); 194 | return FALSE; 195 | } 196 | } 197 | else 198 | { 199 | // should this be a warning? 200 | $this->set_error('Could not verify GD version'); 201 | return FALSE; 202 | } 203 | } 204 | 205 | //---------------------------------------------------------------------------------------------------------- 206 | // checks that we have an GD image loaded 207 | //--- 208 | 209 | private function is_gd_image( $image ) { 210 | 211 | return ( (is_resource($image) && get_resource_type( $image ) === 'gd') || (is_object( $image ) && $image instanceof GdImage) ); 212 | } 213 | 214 | private function _check_image() 215 | //---------------------------------------------------------------------------------------------------------- 216 | // checks that we have an image loaded 217 | //---------------------------------------------------------------------------------------------------------- 218 | { 219 | // generic check 220 | if (!$this->is_gd_image($this->main_image)) 221 | { 222 | $this->set_error("No main image loaded!"); 223 | return FALSE; 224 | } 225 | else 226 | { 227 | return TRUE; 228 | } 229 | } 230 | 231 | function get_data_stream($filename="") 232 | //---------------------------------------------------------------------------------------------------------- 233 | // Saves image as a datastream for inline inclustion 234 | // writes as a temp image 235 | // you can not chain this one! 236 | //---------------------------------------------------------------------------------------------------------- 237 | { 238 | // validate we loaded a main image 239 | if (!$this->_check_image()) return $this; 240 | 241 | // if no operations, copy it for temp save 242 | $this->_copy_to_temp_if_needed(); 243 | 244 | // ok, lets go! 245 | if ($filename=="") $filename=rand(1000,999999).".jpg"; // send as jpeg 246 | $ext = strtoupper(pathinfo($filename, PATHINFO_EXTENSION)); 247 | 248 | // start new buffer 249 | ob_start(); 250 | 251 | switch ($ext) 252 | { 253 | case "GIF" : 254 | imagegif($this->temp_image); 255 | break; 256 | case "JPG" : 257 | case "JPEG" : 258 | imagejpeg($this->temp_image); 259 | break; 260 | case "PNG" : 261 | imagepng($this->temp_image); 262 | break; 263 | case "WEBP": 264 | imagewebp($this->temp_image); 265 | break; 266 | default: 267 | $this->set_error('Extension not recognised! Must be jpg/png/gif'); 268 | return FALSE; 269 | break; 270 | } 271 | 272 | // get the buffer 273 | $contents = ob_get_contents(); 274 | 275 | // remove buffer 276 | ob_end_clean(); 277 | 278 | // return teh buffer (allows user to encode it) 279 | return $contents; 280 | } 281 | 282 | function save_dynamic($filename="") 283 | //---------------------------------------------------------------------------------------------------------- 284 | // Saves the temp image as a dynamic image 285 | // e.g. direct output to the browser 286 | //---------------------------------------------------------------------------------------------------------- 287 | { 288 | // validate we loaded a main image 289 | if (!$this->_check_image()) return $this; 290 | 291 | // if no operations, copy it for temp save 292 | $this->_copy_to_temp_if_needed(); 293 | 294 | // ok, lets go! 295 | if ($filename=="") $filename=rand(1000,999999).".jpg"; // send as jpeg 296 | $ext = strtoupper(pathinfo($filename, PATHINFO_EXTENSION)); 297 | header("Content-disposition: filename=$filename;"); 298 | header('Content-transfer-Encoding: binary'); 299 | header('Last-modified: '.gmdate('D, d M Y H:i:s')); 300 | switch ($ext) 301 | { 302 | case "GIF" : 303 | header("Content-type: image/gif"); 304 | imagegif($this->temp_image); 305 | return $this; 306 | break; 307 | case "JPG" : 308 | case "JPEG" : 309 | header("Content-type: image/jpeg"); 310 | imagejpeg($this->temp_image, NULL, $this->jpeg_quality); 311 | return $this; 312 | break; 313 | case "PNG" : 314 | header("Content-type: image/png"); 315 | imagepng($this->temp_image); 316 | return $this; 317 | break; 318 | case "WEBP": 319 | header("Content-type: image/webp"); 320 | imagewebp($this->temp_image, NULL, $this->jpeg_quality); 321 | return $this; 322 | break; 323 | } 324 | $this->set_error('Unable to save, extension not GIF/JPEG/JPG/PNG'); 325 | return $this; 326 | } 327 | 328 | function save_pa($prepend="", $append="", $overwrite=FALSE) 329 | //---------------------------------------------------------------------------------------------------------- 330 | // Saves the temp image as the filename specified, 331 | // overwrite = true of false 332 | //---------------------------------------------------------------------------------------------------------- 333 | { 334 | // validate we loaded a main image 335 | if (!$this->_check_image()) return $this; 336 | 337 | // get current file parts 338 | $parts=pathinfo($this->filename); 339 | 340 | // save 341 | $this->save($parts["dirname"].'/'.$prepend.$parts['filename'].$append.'.'.$parts["extension"], $overwrite); 342 | 343 | return $this; 344 | } 345 | 346 | function save($filename,$overwrite=FALSE) 347 | //---------------------------------------------------------------------------------------------------------- 348 | // Saves the temp image as the filename specified, 349 | // overwrite = true of false 350 | //---------------------------------------------------------------------------------------------------------- 351 | { 352 | // validate we loaded a main image 353 | if (!$this->_check_image()) return $this; 354 | 355 | // if no operations, copy it for temp save 356 | $this->_copy_to_temp_if_needed(); 357 | 358 | // check if it already exists 359 | if (!$overwrite) 360 | { 361 | // don't overwrite, so check for file 362 | if (file_exists($filename)) 363 | { 364 | $this->set_error('File exists, overwrite is FALSE, could not save over file '.$filename); 365 | return $this; 366 | } 367 | } 368 | 369 | // find out the type of file to save 370 | $ext = strtoupper(pathinfo($filename, PATHINFO_EXTENSION)); 371 | switch ($ext) 372 | { 373 | case "GIF" : 374 | imagegif($this->temp_image, $filename); 375 | return $this; 376 | break; 377 | case "JPG" : 378 | case "JPEG" : 379 | imagejpeg($this->temp_image, $filename, $this->jpeg_quality); 380 | return $this; 381 | break; 382 | case "PNG" : 383 | imagepng($this->temp_image, $filename); 384 | return $this; 385 | break; 386 | case "WEBP" : 387 | imagewebp($this->temp_image, $filename, $this->jpeg_quality); 388 | return $this; 389 | break; 390 | } 391 | 392 | // invalid filetype?! 393 | $this->set_error('Do no know what '.$ext.' filetype is in filename '.$filename); 394 | return $this; 395 | } 396 | 397 | private function _load_image($filename) 398 | //---------------------------------------------------------------------------------------------------------- 399 | // private function to load a resource 400 | //---------------------------------------------------------------------------------------------------------- 401 | { 402 | // check the request file can be located 403 | if (!file_exists($filename)) 404 | { 405 | $this->set_error('Could not locate file '.$filename); 406 | return FALSE; 407 | } 408 | 409 | // get image info about this file 410 | $image_info=getimagesize($filename); 411 | 412 | // load file depending on mimetype 413 | try 414 | { 415 | switch ($image_info["mime"]) 416 | { 417 | case "image/gif" : 418 | return @imagecreatefromgif($filename); 419 | break; 420 | case "image/jpeg" : 421 | return @imagecreatefromjpeg($filename); 422 | break; 423 | case "image/png" : 424 | return @imagecreatefrompng($filename); 425 | break; 426 | case "image/webp" : 427 | return @imagecreatefromwebp($filename); 428 | break; 429 | } 430 | } 431 | catch (Exception $e) 432 | { 433 | $this->set_error('Exception loading '.$filename.' - '.$e->getMessage()); 434 | } 435 | 436 | // invalid filetype?! 437 | $this->set_error('Unable to load '.$filename.' filetype '.$image_info["mime"].'not recognised'); 438 | return FALSE; 439 | } 440 | 441 | public function load_temp() 442 | //---------------------------------------------------------------------------------------------------------- 443 | // Take the temp image and make it the main image 444 | //---------------------------------------------------------------------------------------------------------- 445 | { 446 | // validate we loaded a main image 447 | if (!$this->_check_image()) return $this; 448 | 449 | if (!$this->is_gd_image($this->temp_image)) 450 | { 451 | $this->set_error("No temp image created!"); 452 | return FALSE; 453 | } 454 | 455 | // make main the temp 456 | $this->main_image = $this->temp_image; 457 | 458 | // clear temp 459 | $this->clear_temp(); 460 | 461 | // reset sizes 462 | $this->_set_new_size(); 463 | 464 | // return the object 465 | return $this; 466 | } 467 | 468 | public function load($filename) 469 | //---------------------------------------------------------------------------------------------------------- 470 | // Load an image, public function 471 | //---------------------------------------------------------------------------------------------------------- 472 | { 473 | // new image, reset error messages 474 | $this->_clear_errors(); 475 | 476 | // remove temporary image stored 477 | $this->clear_temp(); 478 | 479 | // save filename 480 | $this->filename=$filename; 481 | 482 | // reset width and height 483 | $this->width = 0; 484 | $this->height = 0; 485 | 486 | // load it 487 | $this->main_image = $this->_load_image($filename); 488 | 489 | // no error, then get the dminesions set 490 | if ($this->main_image <> FALSE) 491 | { 492 | $this->new_width = $this->width = imageSX($this->main_image); 493 | $this->new_height = $this->height = imageSY($this->main_image); 494 | $this->_set_new_size(); 495 | } 496 | 497 | // return the object 498 | return $this; 499 | } 500 | 501 | public function load_watermark($filename, $transparent_x=NULL, $transparent_y=NULL) 502 | //---------------------------------------------------------------------------------------------------------- 503 | // Load an image, public function 504 | //---------------------------------------------------------------------------------------------------------- 505 | { 506 | if($this->is_gd_image($this->watermark_image)) imagedestroy($this->watermark_image); 507 | $this->watermark_image = $this->_load_image($filename); 508 | 509 | if($this->is_gd_image($this->watermark_image)) 510 | { 511 | $this->watermark_method = 1; 512 | if(($transparent_x <> NULL) AND ($transparent_y <> NULL)) 513 | { 514 | // get the top left corner colour allocation 515 | $tpcolour = imagecolorat($this->watermark_image, $transparent_x, $transparent_y); 516 | 517 | // set this as the transparent colour 518 | imagecolortransparent($this->watermark_image, $tpcolour); 519 | 520 | // $set diff method 521 | $this->watermark_method = 2; 522 | } 523 | } 524 | 525 | // return this object 526 | return $this; 527 | } 528 | 529 | public function real_filesize() 530 | //---------------------------------------------------------------------------------------------------------- 531 | // Returns the actual filesize of the original image 532 | //---------------------------------------------------------------------------------------------------------- 533 | { 534 | // filename? 535 | if ($this->filename == "") 536 | { 537 | $this->set_error('Unable to get filesize, no filename!'); 538 | return "-"; 539 | } 540 | if (!file_exists($this->filename)) 541 | { 542 | $this->set_error('Unable to get filesize, file does not exist!'); 543 | return "-"; 544 | } 545 | 546 | // set the units (found on filesize.php) 547 | $size = filesize($this->filename); 548 | 549 | // set the units 550 | $units = array(' B', ' KB', ' MB', ' GB', ' TB'); 551 | for ($i = 0; $size >= 1024 && $i < 4; $i++) $size /= 1024; 552 | 553 | // return the closest 554 | return round($size, 2).$units[$i]; 555 | } 556 | 557 | public function set_watermark_transparency($transparency=50) 558 | //---------------------------------------------------------------------------------------------------------- 559 | // Sets the quality that jpeg will be saved at 560 | //---------------------------------------------------------------------------------------------------------- 561 | { 562 | $this->watermark_transparency = $transparency; 563 | return $this; 564 | } 565 | 566 | public function set_background_colour($colour="#ffffff") 567 | //---------------------------------------------------------------------------------------------------------- 568 | // Sets teh background colour to use on rotation and padding for resize 569 | //---------------------------------------------------------------------------------------------------------- 570 | { 571 | $this->background_colour = $this->_html2rgb($colour); 572 | return $this; 573 | } 574 | 575 | public function set_jpeg_quality($quality=75) 576 | //---------------------------------------------------------------------------------------------------------- 577 | // Sets the quality that jpeg will be saved at 578 | //---------------------------------------------------------------------------------------------------------- 579 | { 580 | $this->jpeg_quality = $quality; 581 | return $this; 582 | } 583 | 584 | private function _copy_to_temp_if_needed() 585 | //---------------------------------------------------------------------------------------------------------- 586 | // If temp image is empty, e.g. not resized or done anything then just copy main image 587 | //---------------------------------------------------------------------------------------------------------- 588 | { 589 | if (!$this->is_gd_image($this->temp_image)) 590 | { 591 | // create a temp based on new dimensions 592 | $this->temp_image = imagecreatetruecolor($this->width, $this->height); 593 | 594 | // check it 595 | if(!$this->is_gd_image($this->temp_image)) 596 | { 597 | $this->set_error('Unable to create temp image sized '.$this->width.' x '.$this->height); 598 | return FALSE; 599 | } 600 | 601 | // copy image to temp workspace 602 | imagecopy($this->temp_image, $this->main_image, 0, 0, 0, 0, $this->width, $this->height); 603 | $this->_set_new_size(); 604 | } 605 | } 606 | 607 | public function clear() 608 | //---------------------------------------------------------------------------------------------------------- 609 | // clear everything! 610 | //---------------------------------------------------------------------------------------------------------- 611 | { 612 | if($this->is_gd_image($this->main_image)) imagedestroy($this->main_image); 613 | if($this->is_gd_image($this->watermark_image)) imagedestroy($this->watermark_image); 614 | if($this->is_gd_image($this->temp_image)) imagedestroy($this->temp_image); 615 | return $this; 616 | } 617 | 618 | public function clear_temp() 619 | //---------------------------------------------------------------------------------------------------------- 620 | // you may want to revert back to teh original image to work on, e.g. watermark, this clears temp 621 | //---------------------------------------------------------------------------------------------------------- 622 | { 623 | if($this->is_gd_image($this->temp_image)) imagedestroy($this->temp_image); 624 | return $this; 625 | } 626 | 627 | public function resize_crop($mw,$mh) 628 | //---------------------------------------------------------------------------------------------------------- 629 | // take main image and resize to tempimage using EXACT boundaries mw,mh (max width and max height) 630 | // this is proportional and crops the image centrally to fit 631 | //---------------------------------------------------------------------------------------------------------- 632 | { 633 | if (!$this->_check_image()) return $this; 634 | 635 | // clear temp image 636 | $this->clear_temp(); 637 | 638 | if( $this->width > $mw || $this->height > $mh || $this->can_stretch) 639 | // create a temp based on new dimensions 640 | $this->temp_image = imagecreatetruecolor($mw, $mh); 641 | else 642 | return $this; 643 | 644 | // check it 645 | if(!$this->is_gd_image($this->temp_image)) 646 | { 647 | $this->set_error('Unable to create temp image sized '.$mw.' x '.$mh); 648 | return $this; 649 | } 650 | 651 | // work out best positions for copy 652 | $wx=$this->width / $mw; 653 | $wy=$this->height / $mh; 654 | 655 | if ($wx >= $wy) 656 | { 657 | // use full height 658 | $sy = 0; 659 | $sy2 = $this->height; 660 | 661 | // calcs 662 | $calc_width = $mw * $wy; 663 | $sx = ($this->width - $calc_width) / 2; 664 | $sx2 = $calc_width; 665 | } 666 | else 667 | { 668 | // use full width 669 | $sx = 0; 670 | $sx2 = $this->width; 671 | 672 | // calcs 673 | $calc_height = $mh * $wx; 674 | $sy = ($this->height - $calc_height) / 2; 675 | $sy2 = $calc_height; 676 | } 677 | 678 | //image transparency preserved 679 | imagealphablending( $this->temp_image, false ); 680 | imagesavealpha( $this->temp_image, true ); 681 | 682 | // copy section 683 | imagecopyresampled($this->temp_image, $this->main_image, 0, 0, $sx, $sy, $mw, $mh, $sx2, $sy2); 684 | 685 | // set sizes 686 | $this->_set_new_size(); 687 | 688 | // return self 689 | return $this; 690 | } 691 | 692 | public function resize($mw, $mh=FALSE, $pad=FALSE) 693 | //---------------------------------------------------------------------------------------------------------- 694 | // take main image and resize to tempimage using boundaries mw,mh (max width or max height) 695 | // this is proportional, pad to true will set it in the middle of area size 696 | //---------------------------------------------------------------------------------------------------------- 697 | { 698 | // no image - fail! 699 | if (!$this->_check_image()) return $this; 700 | 701 | // set mh if not set 702 | if ($mh == FALSE) $mh = $mw; 703 | 704 | // calc new dimensions 705 | if( $this->width > $mw || $this->height > $mh || $this->can_stretch) 706 | { 707 | if( ($this->width / $this->height) > ($mw / $mh) ) { 708 | $tnw = $mw; 709 | $tnh = $tnw * $this->height / $this->width; 710 | } else { 711 | $tnh = $mh; 712 | $tnw = $tnh * $this->width / $this->height; 713 | } 714 | } 715 | else 716 | { 717 | $tnw = $this->width; 718 | $tnh = $this->height; 719 | } 720 | // clear temp image 721 | $this->clear_temp(); 722 | 723 | // create a temp based on new dimensions 724 | if ($pad) 725 | { 726 | $tx = $mw; 727 | $ty = $mh; 728 | $px = ($mw - $tnw) / 2; 729 | $py = ($mh - $tnh) / 2; 730 | } 731 | else 732 | { 733 | $tx = $tnw; 734 | $ty = $tnh; 735 | $px = 0; 736 | $py = 0; 737 | } 738 | 739 | $this->temp_image = imagecreatetruecolor($tx,$ty); 740 | 741 | // check it 742 | if(!$this->is_gd_image($this->temp_image)) 743 | { 744 | $this->set_error('Unable to create temp image sized '.$tx.' x '.$ty); 745 | return $this; 746 | } 747 | 748 | 749 | /* hmm what was I doing here?! 750 | imagealphablending($this->main_image, true); 751 | $a = imagecolortransparent($this->temp_image, imagecolorallocatealpha($this->temp_image, 0, 0, 0, 127)); 752 | imagefilledrectangle($this->temp_image, 0, 0, $tx, $ty, $a); 753 | imagesavealpha($this->temp_image, true); 754 | */ 755 | 756 | $col = $this->_html2rgb($this->background_colour); 757 | $bg = imagecolorallocate($this->temp_image, $col[0], $col[1], $col[2]); 758 | imagefilledrectangle($this->temp_image, 0, 0, $tx, $ty, $bg); 759 | 760 | // if padding, fill background 761 | if ($pad) 762 | { 763 | $col = $this->_html2rgb($this->background_colour); 764 | $bg = imagecolorallocate($this->temp_image, $col[0], $col[1], $col[2]); 765 | imagefilledrectangle($this->temp_image, 0, 0, $tx, $ty, $bg); 766 | /* TO DO 767 | imagealphablending($this->temp_image, false); 768 | imagesavealpha($this->temp_image, true); 769 | $color = imagecolorallocatealpha($this->temp_image, 0, 0, 0, 127); 770 | imagefilledrectangle($this->temp_image, 0, 0, $this->width, $this->height, $color); 771 | */ 772 | } 773 | 774 | // copy resized 775 | imagecopyresampled($this->temp_image, $this->main_image, $px, $py, 0, 0, $tnw, $tnh, $this->width, $this->height); 776 | 777 | // set sizes 778 | $this->_set_new_size(); 779 | 780 | // return self 781 | return $this; 782 | } 783 | 784 | public function stretch($mw,$mh) 785 | //---------------------------------------------------------------------------------------------------------- 786 | // take main image and resize to tempimage using boundaries mw,mh (max width or max height) 787 | // does not retain proportions 788 | //---------------------------------------------------------------------------------------------------------- 789 | { 790 | if (!$this->_check_image()) return $this; 791 | 792 | // clear temp image 793 | $this->clear_temp(); 794 | 795 | // create a temp based on new dimensions 796 | $this->temp_image = imagecreatetruecolor($mw, $mh); 797 | 798 | // check it 799 | if(!$this->is_gd_image($this->temp_image)) 800 | { 801 | $this->set_error('Unable to create temp image sized '.$mh.' x '.$mw); 802 | return $this; 803 | } 804 | 805 | // copy resized (stethced, proportions not kept); 806 | imagecopyresampled($this->temp_image, $this->main_image, 0, 0, 0, 0, $mw, $mh, $this->width, $this->height); 807 | 808 | // set sizes 809 | $this->_set_new_size(); 810 | 811 | // return self 812 | return $this; 813 | } 814 | 815 | public function crop($x1, $y1, $x2, $y2) 816 | //---------------------------------------------------------------------------------------------------------- 817 | // crop the main image to temp image using coords 818 | //---------------------------------------------------------------------------------------------------------- 819 | { 820 | if (!$this->_check_image()) return $this; 821 | 822 | // clear temp image 823 | $this->clear_temp(); 824 | 825 | // check dimensions 826 | if ($x1 < 0 || $y1 < 0 || $x2 - $x1 > $this->width || $y2 - $y1 > $this->height) 827 | { 828 | $this->set_error('Invalid crop dimensions, either - passed or width/heigh too large '.$x1.'/'.$y1.' x '.$x2.'/'.$y2); 829 | return $this; 830 | } 831 | 832 | // create a temp based on new dimensions 833 | $this->temp_image = imagecreatetruecolor($x2-$x1, $y2-$y1); 834 | 835 | // check it 836 | if(!$this->is_gd_image($this->temp_image)) 837 | { 838 | $this->set_error('Unable to create temp image sized '.($x2-$x1).' x '.($y2-$y1)); 839 | return $this; 840 | } 841 | 842 | // copy cropped portion 843 | imagecopy($this->temp_image, $this->main_image, 0, 0, $x1, $y1, $x2 - $x1, $y2 - $y1); 844 | 845 | // set sizes 846 | $this->_set_new_size(); 847 | 848 | // return self 849 | return $this; 850 | } 851 | 852 | private function _html2rgb($colour) 853 | //---------------------------------------------------------------------------------------------------------- 854 | // convert #aa0011 to a php colour array 855 | //---------------------------------------------------------------------------------------------------------- 856 | { 857 | if (is_array($colour)) 858 | { 859 | if (count($colour)==3) return $colour; // rgb sent as an array so use it 860 | $this->set_error('Colour error, array sent not 3 elements, expected array(r,g,b)'); 861 | return false; 862 | } 863 | if ($colour[0] == '#') 864 | $colour = substr($colour, 1); 865 | 866 | if (strlen($colour) == 6) 867 | { 868 | list($r, $g, $b) = array($colour[0].$colour[1], 869 | $colour[2].$colour[3], 870 | $colour[4].$colour[5]); 871 | } 872 | elseif (strlen($colour) == 3) 873 | { 874 | list($r, $g, $b) = array($colour[0].$colour[0], $colour[1].$colour[1], $colour[2].$colour[2]); 875 | } 876 | else 877 | { 878 | $this->set_error('Colour error, value sent not #RRGGBB or RRGGBB, and not array(r,g,b)'); 879 | return false; 880 | } 881 | 882 | $r = hexdec($r); $g = hexdec($g); $b = hexdec($b); 883 | 884 | return array($r, $g, $b); 885 | } 886 | 887 | public function rotate($angle) 888 | //---------------------------------------------------------------------------------------------------------- 889 | // rotate an image bu 0 / 90 / 180 / 270 degrees 890 | //---------------------------------------------------------------------------------------------------------- 891 | { 892 | // validate we loaded a main image 893 | if (!$this->_check_image()) return $this; 894 | 895 | // if no operations, copy it for temp save 896 | $this->_copy_to_temp_if_needed(); 897 | 898 | // set the colour 899 | $col = $this->_html2rgb($this->background_colour); 900 | $bg = imagecolorallocatealpha($this->temp_image, 0, 0, 0, 127); 901 | 902 | // rotate as needed 903 | $this->temp_image = imagerotate($this->temp_image, $angle, $bg); 904 | imagealphablending($this->temp_image, false); 905 | imagesavealpha($this->temp_image, true); 906 | 907 | // set sizes 908 | $this->_set_new_size(); 909 | 910 | // return self 911 | return $this; 912 | } 913 | 914 | public function make_watermark_text($text, $fontfile, $size=16, $colour="#ffffff", $angle=0) 915 | //---------------------------------------------------------------------------------------------------------- 916 | // create an image from text that can be applied as a watermark 917 | // text is the text to write, $fontile is a ttf file that will be used $size=font size, $colour is the colour of text 918 | //---------------------------------------------------------------------------------------------------------- 919 | { 920 | // check font file can be found 921 | if (!file_exists($fontfile)) 922 | { 923 | $this->set_error('Could not locate font file "'.$fontfile.'"'); 924 | return $this; 925 | } 926 | 927 | // validate we loaded a main image 928 | if (!$this->_check_image()) 929 | { 930 | $remove = TRUE; 931 | // no image loaded so make temp image to use 932 | $this->main_image = imagecreatetruecolor(1000,1000); 933 | } 934 | else 935 | { 936 | $remove = FALSE; 937 | } 938 | 939 | // work out text dimensions 940 | $bbox = imageftbbox($size, $angle, $fontfile, $text); 941 | $bw = abs($bbox[4] - $bbox[0]) + 1; 942 | $bh = abs($bbox[1] - $bbox[5]) + 1; 943 | $bl = $bbox[1]; 944 | 945 | // use this to create watermark image 946 | if($this->is_gd_image($this->watermark_image)) imagedestroy($this->watermark_image); 947 | $this->watermark_image = imagecreatetruecolor($bw, $bh); 948 | 949 | // set colours 950 | $col = $this->_html2rgb($colour); 951 | $font_col = imagecolorallocate($this->watermark_image, $col[0], $col[1], $col[2]); 952 | $bg_col = imagecolorallocate($this->watermark_image, 127, 128, 126); 953 | 954 | // set method to use 955 | $this->watermark_method = 2; 956 | 957 | // create bg 958 | imagecolortransparent($this->watermark_image, $bg_col); 959 | imagefilledrectangle($this->watermark_image, 0,0, $bw, $bh, $bg_col); 960 | 961 | // write text to watermark 962 | imagefttext($this->watermark_image, $size, $angle, 0, $bh-$bl, $font_col, $fontfile, $text); 963 | 964 | if ($remove) imagedestroy($this->main_image); 965 | return $this; 966 | } 967 | 968 | public function watermark($position, $offset=8, $abs=FALSE) 969 | //---------------------------------------------------------------------------------------------------------- 970 | // add a watermark to the image 971 | // position works like a keypad e.g. 972 | // 7 8 9 973 | // 4 5 6 974 | // 1 2 3 975 | // offset moves image inwards by x pixels 976 | // if abs is set then $position, $offset = direct placement coords 977 | //---------------------------------------------------------------------------------------------------------- 978 | { 979 | // validate we loaded a main image 980 | if (!$this->_check_image()) return $this; 981 | 982 | // validate we have a watermark 983 | if(!$this->is_gd_image($this->watermark_image)) 984 | { 985 | $this->set_error("Can't watermark image, no watermark loaded/created"); 986 | return $this; 987 | } 988 | 989 | // if no operations, copy it for temp save 990 | $this->_copy_to_temp_if_needed(); 991 | 992 | // get watermark width 993 | $wm_w = imageSX($this->watermark_image); 994 | $wm_h = imageSY($this->watermark_image); 995 | 996 | // get temp widths 997 | $temp_w = imageSX($this->temp_image); 998 | $temp_h = imageSY($this->temp_image); 999 | 1000 | // check watermark will fit! 1001 | if ($wm_w > $temp_w || $wm_h > $temp_h) 1002 | { 1003 | $this->set_error("Watermark is larger than image. WM: $wm_w x $wm_h Temp image: $temp_w x $temp_h"); 1004 | return $this; 1005 | } 1006 | 1007 | if ($abs) 1008 | { 1009 | // direct placement 1010 | $dest_x = $position; 1011 | $dest_y = $offset; 1012 | } 1013 | else 1014 | { 1015 | // do X position 1016 | switch ($position) 1017 | { 1018 | // x left 1019 | case "7": 1020 | case "4": 1021 | case "1": 1022 | $dest_x = $offset; 1023 | break; 1024 | // x middle 1025 | case "8": 1026 | case "5": 1027 | case "2": 1028 | $dest_x = ($temp_w - $wm_w) /2 ; 1029 | break; 1030 | // x right 1031 | case "9": 1032 | case "6": 1033 | case "3": 1034 | $dest_x = $temp_w - $offset - $wm_w; 1035 | break; 1036 | default: 1037 | $dest_x = $offset; 1038 | $this->set_error("Watermark position $position not in valid range 7,8,9 - 4,5,6 - 1,2,3"); 1039 | } 1040 | // do y position 1041 | switch ($position) 1042 | { 1043 | // y top 1044 | case "7": 1045 | case "8": 1046 | case "9": 1047 | $dest_y = $offset; 1048 | break; 1049 | // y middle 1050 | case "4": 1051 | case "5": 1052 | case "6": 1053 | $dest_y = ($temp_h - $wm_h) /2 ; 1054 | break; 1055 | // y bottom 1056 | case "1": 1057 | case "2": 1058 | case "3": 1059 | $dest_y = $temp_h - $offset - $wm_h; 1060 | break; 1061 | default: 1062 | $dest_y = $offset; 1063 | $this->set_error("Watermark position $position not in valid range 7,8,9 - 4,5,6 - 1,2,3"); 1064 | } 1065 | 1066 | } 1067 | 1068 | // copy over temp image to desired location 1069 | if ($this->watermark_method == 1) 1070 | { 1071 | // use back methods to do this, taken from php help files 1072 | //$this->imagecopymerge_alpha($this->temp_image, $this->watermark_image, $dest_x, $dest_y, 0, 0, $wm_w, $wm_h, $this->watermark_transparency); 1073 | 1074 | $opacity=$this->watermark_transparency; 1075 | 1076 | // creating a cut resource 1077 | $cut = imagecreatetruecolor($wm_w, $wm_h); 1078 | 1079 | // copying that section of the background to the cut 1080 | imagecopy($cut, $this->temp_image, 0, 0, $dest_x, $dest_y, $wm_w, $wm_h); 1081 | 1082 | // inverting the opacity 1083 | $opacity = 100 - $opacity; 1084 | 1085 | // placing the watermark now 1086 | imagecopy($cut, $this->watermark_image, 0, 0, 0, 0, $wm_w, $wm_h); 1087 | imagecopymerge($this->temp_image, $cut, $dest_x, $dest_y, 0, 0, $wm_w, $wm_h, $opacity); 1088 | 1089 | } 1090 | else 1091 | { 1092 | // use normal with selected transparency colour 1093 | imagecopymerge($this->temp_image, $this->watermark_image, $dest_x, $dest_y, 0, 0, $wm_w, $wm_h, $this->watermark_transparency); 1094 | } 1095 | 1096 | return $this; 1097 | } 1098 | 1099 | public function border($width=5,$colour="#000") 1100 | //---------------------------------------------------------------------------------------------------------- 1101 | // add a solidborder frame, coloured $colour to the image 1102 | //---------------------------------------------------------------------------------------------------------- 1103 | { 1104 | // validate we loaded a main image 1105 | if (!$this->_check_image()) return $this; 1106 | 1107 | // if no operations, copy it for temp save 1108 | $this->_copy_to_temp_if_needed(); 1109 | 1110 | // get colour set for temp image 1111 | $col = $this->_html2rgb($colour); 1112 | $border_col = imagecolorallocate($this->temp_image, $col[0], $col[1], $col[2]); 1113 | 1114 | // get temp widths 1115 | $temp_w = imageSX($this->temp_image); 1116 | $temp_h = imageSY($this->temp_image); 1117 | 1118 | // do border 1119 | for($x=0;$x<$width;$x++) 1120 | { 1121 | imagerectangle($this->temp_image, $x, $x, $temp_w-$x-1, $temp_h-$x-1, $border_col); 1122 | } 1123 | 1124 | // return object 1125 | return $this; 1126 | } 1127 | 1128 | public function border_3d($width=5,$rot=0,$opacity=30) 1129 | //---------------------------------------------------------------------------------------------------------- 1130 | // overlay a black white border to make it look 3d 1131 | //---------------------------------------------------------------------------------------------------------- 1132 | { 1133 | // validate we loaded a main image 1134 | if (!$this->_check_image()) return $this; 1135 | 1136 | // if no operations, copy it for temp save 1137 | $this->_copy_to_temp_if_needed(); 1138 | 1139 | // create temp canvas to merge 1140 | $border_image = imagecreatetruecolor($this->new_width, $this->new_height); 1141 | 1142 | // create colours 1143 | $black = imagecolorallocate($border_image, 0, 0, 0); 1144 | $white = imagecolorallocate($border_image, 255, 255, 255); 1145 | switch ($rot) 1146 | { 1147 | case 1 : 1148 | $cols=array($white,$black,$white,$black); 1149 | break; 1150 | case 2 : 1151 | $cols=array($black,$black,$white,$white); 1152 | break; 1153 | case 3 : 1154 | $cols=array($black,$white,$black,$white); 1155 | break; 1156 | default : 1157 | $cols=array($white,$white,$black,$black); 1158 | } 1159 | $bg_col = imagecolorallocate($border_image, 127, 128, 126); 1160 | 1161 | // create bg 1162 | imagecolortransparent($border_image, $bg_col); 1163 | imagefilledrectangle($border_image, 0,0, $this->new_width, $this->new_height, $bg_col); 1164 | 1165 | // do border 1166 | for($x=0;$x<$width;$x++) 1167 | { 1168 | // top 1169 | imageline($border_image, $x, $x, $this->new_width-$x-1, $x, $cols[0]); 1170 | // left 1171 | imageline($border_image, $x, $x, $x, $this->new_width-$x-1, $cols[1]); 1172 | // bottom 1173 | imageline($border_image, $x, $this->new_height-$x-1, $this->new_width-1-$x, $this->new_height-$x-1, $cols[3]); 1174 | // right 1175 | imageline($border_image, $this->new_width-$x-1, $x, $this->new_width-$x-1, $this->new_height-$x-1, $cols[2]); 1176 | } 1177 | 1178 | // merg with temp image 1179 | imagecopymerge($this->temp_image, $border_image, 0, 0, 0, 0, $this->new_width, $this->new_height, $opacity); 1180 | 1181 | // clean up 1182 | imagedestroy($border_image); 1183 | 1184 | // return object 1185 | return $this; 1186 | } 1187 | 1188 | public function shadow($size=4, $direction=3, $colour="#444") 1189 | //---------------------------------------------------------------------------------------------------------- 1190 | // add a shadow to an image, this will INCREASE the size of the image 1191 | //---------------------------------------------------------------------------------------------------------- 1192 | { 1193 | // validate we loaded a main image 1194 | if (!$this->_check_image()) return $this; 1195 | 1196 | // if no operations, copy it for temp save 1197 | $this->_copy_to_temp_if_needed(); 1198 | 1199 | // get the current size 1200 | $sx = imagesx($this->temp_image); 1201 | $sy = imagesy($this->temp_image); 1202 | 1203 | // new image 1204 | $bu_image = imagecreatetruecolor($sx, $sy); 1205 | 1206 | // check it 1207 | if(!$this->is_gd_image($bu_image)) 1208 | { 1209 | $this->set_error('Unable to create shadow temp image sized '.$this->width.' x '.$this->height); 1210 | return FALSE; 1211 | } 1212 | 1213 | // copy the current image to memory 1214 | imagecopy($bu_image, $this->temp_image, 0, 0, 0, 0, $sx, $sy); 1215 | 1216 | imagedestroy($this->temp_image); 1217 | $this->temp_image = imagecreatetruecolor($sx+$size, $sy+$size); 1218 | 1219 | // fill background colour 1220 | $col = $this->_html2rgb($this->background_colour); 1221 | $bg = imagecolorallocate($this->temp_image, $col[0], $col[1], $col[2]); 1222 | imagefilledrectangle($this->temp_image, 0, 0, $sx+$size, $sy+$size, $bg); 1223 | 1224 | // work out position 1225 | // do X position 1226 | switch ($direction) 1227 | { 1228 | // x left 1229 | case "7": 1230 | case "4": 1231 | case "1": 1232 | $sh_x = 0; 1233 | $pic_x = $size; 1234 | break; 1235 | // x middle 1236 | case "8": 1237 | case "5": 1238 | case "2": 1239 | $sh_x = $size / 2; 1240 | $pic_x = $size / 2; 1241 | break; 1242 | // x right 1243 | case "9": 1244 | case "6": 1245 | case "3": 1246 | $sh_x = $size; 1247 | $pic_x = 0; 1248 | break; 1249 | default: 1250 | $sh_x = $size; 1251 | $pic_x = 0; 1252 | $this->set_error("Shadow position $position not in valid range 7,8,9 - 4,5,6 - 1,2,3"); 1253 | } 1254 | // do y position 1255 | switch ($direction) 1256 | { 1257 | // y top 1258 | case "7": 1259 | case "8": 1260 | case "9": 1261 | $sh_y = 0; 1262 | $pic_y = $size; 1263 | break; 1264 | // y middle 1265 | case "4": 1266 | case "5": 1267 | case "6": 1268 | $sh_y = $size / 2; 1269 | $pic_y = $size / 2; 1270 | break; 1271 | // y bottom 1272 | case "1": 1273 | case "2": 1274 | case "3": 1275 | $sh_y = $size; 1276 | $pic_y = 0; 1277 | break; 1278 | default: 1279 | $sh_y = $size; 1280 | $pic_y = 0; 1281 | $this->set_error("Shadow position $position not in valid range 7,8,9 - 4,5,6 - 1,2,3"); 1282 | } 1283 | 1284 | // create the shadow 1285 | $shadowcolour = $this->_html2rgb($colour); 1286 | $shadow = imagecolorallocate($this->temp_image, $shadowcolour[0], $shadowcolour[1], $shadowcolour[2]); 1287 | imagefilledrectangle($this->temp_image, $sh_x, $sh_y, $sh_x+$sx-1, $sh_y+$sy-1, $shadow); 1288 | 1289 | // copy current image to correct location 1290 | imagecopy($this->temp_image, $bu_image, $pic_x, $pic_y, 0, 0, $sx, $sy); 1291 | 1292 | // clean up and desstroy temp image 1293 | imagedestroy($bu_image); 1294 | 1295 | // set sizes 1296 | $this->_set_new_size(); 1297 | 1298 | // return self 1299 | return $this; 1300 | } 1301 | 1302 | public function filter($function, $arg1=NULL, $arg2=NULL, $arg3=NULL, $arg4=NULL) 1303 | //---------------------------------------------------------------------------------------------------------- 1304 | // allows you to use the inbulit gd2 image filters 1305 | //---------------------------------------------------------------------------------------------------------- 1306 | { 1307 | // validate we loaded a main image 1308 | if (!$this->_check_image()) return $this; 1309 | 1310 | // if no operations, copy it for temp save 1311 | $this->_copy_to_temp_if_needed(); 1312 | 1313 | if (!imagefilter($this->temp_image, $function, $arg1, $arg2, $arg3, $arg4)) 1314 | { 1315 | $this->set_error("Filter $function failed"); 1316 | } 1317 | 1318 | // set sizes 1319 | $this->_set_new_size(); 1320 | 1321 | // return self 1322 | return $this; 1323 | } 1324 | 1325 | public function round($radius=5,$invert=False,$corners="") 1326 | //---------------------------------------------------------------------------------------------------------- 1327 | // adds rounded corners to the output 1328 | // using a quarter and rotating as you can end up with odd roudning if you draw a whole and use parts 1329 | //---------------------------------------------------------------------------------------------------------- 1330 | { 1331 | // validate we loaded a main image 1332 | if (!$this->_check_image()) return $this; 1333 | 1334 | // if no operations, copy it for temp save 1335 | $this->_copy_to_temp_if_needed(); 1336 | 1337 | // check input 1338 | if ($corners=="") $corners=array(True,True,True,True); 1339 | if (!is_array($corners) || count($corners)<>4) 1340 | { 1341 | $this->set_error("Round failed, expected an array of 4 items round(radius,tl,tr,br,bl)"); 1342 | return $this; 1343 | } 1344 | 1345 | // create corner 1346 | $corner = imagecreatetruecolor($radius, $radius); 1347 | 1348 | // turn on aa make it nicer 1349 | imageantialias($corner, true); 1350 | $col = $this->_html2rgb($this->background_colour); 1351 | 1352 | // use bg col for corners 1353 | $bg = imagecolorallocate($corner, $col[0], $col[1], $col[2]); 1354 | 1355 | // create our transparent colour 1356 | $xparent = imagecolorallocate($corner, 127, 128, 126); 1357 | imagecolortransparent($corner, $xparent); 1358 | if ($invert) 1359 | { 1360 | // fill and clear bits 1361 | imagefilledrectangle($corner, 0, 0, $radius, $radius, $xparent); 1362 | imagefilledellipse($corner, 0, 0, ($radius * 2)-1, ($radius * 2)-1, $bg); 1363 | } 1364 | else 1365 | { 1366 | // fill and clear bits 1367 | imagefilledrectangle($corner, 0, 0, $radius, $radius, $bg); 1368 | imagefilledellipse($corner, $radius, $radius, ($radius * 2) , ($radius * 2) , $xparent); 1369 | } 1370 | 1371 | // get temp widths 1372 | $temp_w = imageSX($this->temp_image); 1373 | $temp_h = imageSY($this->temp_image); 1374 | 1375 | // do corners 1376 | if ($corners[0]) imagecopymerge($this->temp_image, $corner, 0, 0, 0, 0, $radius, $radius, 100); 1377 | $corner = imagerotate($corner, 270, 0); 1378 | if ($corners[1]) imagecopymerge($this->temp_image, $corner, $temp_w-$radius, 0, 0, 0, $radius, $radius, 100); 1379 | $corner = imagerotate($corner, 270, 0); 1380 | if ($corners[2]) imagecopymerge($this->temp_image, $corner, $temp_w-$radius, $temp_h-$radius, 0, 0, $radius, $radius, 100); 1381 | $corner = imagerotate($corner, 270, 0); 1382 | if ($corners[3]) imagecopymerge($this->temp_image, $corner, 0, $temp_h-$radius, 0, 0, $radius, $radius, 100); 1383 | 1384 | // set sizes 1385 | $this->_set_new_size(); 1386 | 1387 | // return self 1388 | return $this; 1389 | } 1390 | 1391 | private function _set_new_size() 1392 | //---------------------------------------------------------------------------------------------------------- 1393 | // Updates the new_widht and height sizes 1394 | //---------------------------------------------------------------------------------------------------------- 1395 | { 1396 | // just in case 1397 | if ( ! $this->_check_image()) 1398 | { 1399 | $this->new_height = 0; 1400 | $this->new_width = 0; 1401 | return; 1402 | } 1403 | 1404 | // is there a temp image? 1405 | if ( ! $this->is_gd_image($this->temp_image)) 1406 | { 1407 | $this->new_height = $this->height; 1408 | $this->new_width = $this->width; 1409 | return; 1410 | } 1411 | 1412 | // set new sizes 1413 | $this->new_height = imagesy($this->temp_image); 1414 | $this->new_width = imagesx($this->temp_image); 1415 | } 1416 | 1417 | } 1418 | /* End of file image_moo.php */ 1419 | /* Location: /application/libraries/image_moo.php */ 1420 | --------------------------------------------------------------------------------