blob: ceb31d1f044d0bf41a471a2c80f0c43ad6dc8e47 [file] [log] [blame]
Derek Jones4b9c6292011-07-01 17:40:48 -05001<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
Derek Allard2067d1a2008-11-13 22:59:24 +00002/**
3 * CodeIgniter
4 *
Greg Aker741de1c2010-11-10 14:52:57 -06005 * An open source application development framework for PHP 5.1.6 or newer
Derek Allard2067d1a2008-11-13 22:59:24 +00006 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05007 * NOTICE OF LICENSE
8 *
9 * Licensed under the Open Software License version 3.0
10 *
11 * This source file is subject to the Open Software License (OSL 3.0) that is
12 * bundled with this package in the files license.txt / license.rst. It is
13 * also available through the world wide web at this URL:
14 * http://opensource.org/licenses/OSL-3.0
15 * If you did not receive a copy of the license and are unable to obtain it
16 * through the world wide web, please send an email to
17 * licensing@ellislab.com so we can send you a copy immediately.
18 *
Derek Allard2067d1a2008-11-13 22:59:24 +000019 * @package CodeIgniter
Derek Jonesf4a4bd82011-10-20 12:18:42 -050020 * @author EllisLab Dev Team
21 * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc. (http://ellislab.com/)
22 * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
Derek Allard2067d1a2008-11-13 22:59:24 +000023 * @link http://codeigniter.com
24 * @since Version 1.0
25 * @filesource
26 */
27
28// ------------------------------------------------------------------------
29
30/**
31 * Image Manipulation class
32 *
33 * @package CodeIgniter
34 * @subpackage Libraries
35 * @category Image_lib
Derek Jonesf4a4bd82011-10-20 12:18:42 -050036 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +000037 * @link http://codeigniter.com/user_guide/libraries/image_lib.html
38 */
39class CI_Image_lib {
40
Derek Jones4b9c6292011-07-01 17:40:48 -050041 var $image_library = 'gd2'; // Can be: imagemagick, netpbm, gd, gd2
Derek Allard2067d1a2008-11-13 22:59:24 +000042 var $library_path = '';
43 var $dynamic_output = FALSE; // Whether to send to browser or write to disk
44 var $source_image = '';
45 var $new_image = '';
46 var $width = '';
47 var $height = '';
48 var $quality = '90';
49 var $create_thumb = FALSE;
50 var $thumb_marker = '_thumb';
Barry Mienydd671972010-10-04 16:33:58 +020051 var $maintain_ratio = TRUE; // Whether to maintain aspect ratio when resizing or use hard values
Derek Jones4b9c6292011-07-01 17:40:48 -050052 var $master_dim = 'auto'; // auto, height, or width. Determines what to use as the master dimension
Derek Allard2067d1a2008-11-13 22:59:24 +000053 var $rotation_angle = '';
54 var $x_axis = '';
55 var $y_axis = '';
56
57 // Watermark Vars
58 var $wm_text = ''; // Watermark text if graphic is not used
Derek Jones4b9c6292011-07-01 17:40:48 -050059 var $wm_type = 'text'; // Type of watermarking. Options: text/overlay
Derek Allard2067d1a2008-11-13 22:59:24 +000060 var $wm_x_transp = 4;
61 var $wm_y_transp = 4;
62 var $wm_overlay_path = ''; // Watermark image path
63 var $wm_font_path = ''; // TT font
64 var $wm_font_size = 17; // Font size (different versions of GD will either use points or pixels)
Derek Jones4b9c6292011-07-01 17:40:48 -050065 var $wm_vrt_alignment = 'B'; // Vertical alignment: T M B
Derek Allard2067d1a2008-11-13 22:59:24 +000066 var $wm_hor_alignment = 'C'; // Horizontal alignment: L R C
67 var $wm_padding = 0; // Padding around text
68 var $wm_hor_offset = 0; // Lets you push text to the right
Derek Jones4b9c6292011-07-01 17:40:48 -050069 var $wm_vrt_offset = 0; // Lets you push text down
Derek Allard2067d1a2008-11-13 22:59:24 +000070 var $wm_font_color = '#ffffff'; // Text color
71 var $wm_shadow_color = ''; // Dropshadow color
72 var $wm_shadow_distance = 2; // Dropshadow distance
Derek Jones4b9c6292011-07-01 17:40:48 -050073 var $wm_opacity = 50; // Image opacity: 1 - 100 Only works with image
Derek Allard2067d1a2008-11-13 22:59:24 +000074
75 // Private Vars
76 var $source_folder = '';
77 var $dest_folder = '';
78 var $mime_type = '';
79 var $orig_width = '';
80 var $orig_height = '';
81 var $image_type = '';
82 var $size_str = '';
83 var $full_src_path = '';
84 var $full_dst_path = '';
85 var $create_fnc = 'imagecreatetruecolor';
86 var $copy_fnc = 'imagecopyresampled';
87 var $error_msg = array();
88 var $wm_use_drop_shadow = FALSE;
89 var $wm_use_truetype = FALSE;
90
91 /**
92 * Constructor
93 *
Derek Allard2067d1a2008-11-13 22:59:24 +000094 * @param string
95 * @return void
96 */
Greg Akera9263282010-11-10 15:26:43 -060097 public function __construct($props = array())
Derek Allard2067d1a2008-11-13 22:59:24 +000098 {
99 if (count($props) > 0)
100 {
101 $this->initialize($props);
102 }
103
104 log_message('debug', "Image Lib Class Initialized");
105 }
106
107 // --------------------------------------------------------------------
108
109 /**
110 * Initialize image properties
111 *
112 * Resets values in case this class is used in a loop
113 *
114 * @access public
115 * @return void
116 */
117 function clear()
118 {
Seb Pollardb840a672011-10-22 23:28:21 +0100119 $props = array('source_folder', 'dest_folder', 'source_image', 'full_src_path', 'full_dst_path', 'new_image', 'image_type', 'size_str', 'quality', 'orig_width', 'orig_height', 'rotation_angle', 'x_axis', 'y_axis', 'create_fnc', 'copy_fnc', 'wm_overlay_path', 'wm_use_truetype', 'dynamic_output', 'wm_font_size', 'wm_text', 'wm_vrt_alignment', 'wm_hor_alignment', 'wm_padding', 'wm_hor_offset', 'wm_vrt_offset', 'wm_font_color', 'wm_use_drop_shadow', 'wm_shadow_color', 'wm_shadow_distance', 'wm_opacity', 'width', 'height');
Derek Allard2067d1a2008-11-13 22:59:24 +0000120
121 foreach ($props as $val)
122 {
123 $this->$val = '';
124 }
125
126 // special consideration for master_dim
127 $this->master_dim = 'auto';
Seb Pollardb840a672011-10-22 23:28:21 +0100128
129 // special consideration for create_thumb
130 $this->create_thumb = FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000131 }
132
133 // --------------------------------------------------------------------
134
135 /**
136 * initialize image preferences
137 *
138 * @access public
139 * @param array
140 * @return bool
141 */
142 function initialize($props = array())
143 {
144 /*
145 * Convert array elements into class variables
146 */
147 if (count($props) > 0)
148 {
149 foreach ($props as $key => $val)
150 {
151 $this->$key = $val;
152 }
153 }
154
155 /*
156 * Is there a source image?
157 *
158 * If not, there's no reason to continue
159 *
160 */
161 if ($this->source_image == '')
162 {
163 $this->set_error('imglib_source_image_required');
Derek Jones4b9c6292011-07-01 17:40:48 -0500164 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000165 }
166
167 /*
168 * Is getimagesize() Available?
169 *
170 * We use it to determine the image properties (width/height).
Derek Jones4b9c6292011-07-01 17:40:48 -0500171 * Note: We need to figure out how to determine image
Derek Allard2067d1a2008-11-13 22:59:24 +0000172 * properties using ImageMagick and NetPBM
173 *
174 */
175 if ( ! function_exists('getimagesize'))
176 {
177 $this->set_error('imglib_gd_required_for_props');
178 return FALSE;
179 }
180
181 $this->image_library = strtolower($this->image_library);
182
183 /*
184 * Set the full server path
185 *
186 * The source image may or may not contain a path.
187 * Either way, we'll try use realpath to generate the
188 * full server path in order to more reliably read it.
189 *
190 */
191 if (function_exists('realpath') AND @realpath($this->source_image) !== FALSE)
192 {
193 $full_source_path = str_replace("\\", "/", realpath($this->source_image));
194 }
195 else
196 {
197 $full_source_path = $this->source_image;
198 }
199
200 $x = explode('/', $full_source_path);
201 $this->source_image = end($x);
202 $this->source_folder = str_replace($this->source_image, '', $full_source_path);
203
204 // Set the Image Properties
205 if ( ! $this->get_image_properties($this->source_folder.$this->source_image))
206 {
Derek Jones4b9c6292011-07-01 17:40:48 -0500207 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000208 }
209
210 /*
211 * Assign the "new" image name/path
212 *
213 * If the user has set a "new_image" name it means
214 * we are making a copy of the source image. If not
Derek Jones4b9c6292011-07-01 17:40:48 -0500215 * it means we are altering the original. We'll
Derek Allard2067d1a2008-11-13 22:59:24 +0000216 * set the destination filename and path accordingly.
217 *
218 */
219 if ($this->new_image == '')
220 {
221 $this->dest_image = $this->source_image;
222 $this->dest_folder = $this->source_folder;
223 }
224 else
225 {
226 if (strpos($this->new_image, '/') === FALSE)
227 {
228 $this->dest_folder = $this->source_folder;
229 $this->dest_image = $this->new_image;
230 }
231 else
232 {
233 if (function_exists('realpath') AND @realpath($this->new_image) !== FALSE)
234 {
235 $full_dest_path = str_replace("\\", "/", realpath($this->new_image));
236 }
237 else
238 {
239 $full_dest_path = $this->new_image;
240 }
241
242 // Is there a file name?
243 if ( ! preg_match("#\.(jpg|jpeg|gif|png)$#i", $full_dest_path))
244 {
245 $this->dest_folder = $full_dest_path.'/';
246 $this->dest_image = $this->source_image;
247 }
248 else
249 {
250 $x = explode('/', $full_dest_path);
251 $this->dest_image = end($x);
252 $this->dest_folder = str_replace($this->dest_image, '', $full_dest_path);
253 }
254 }
255 }
256
257 /*
258 * Compile the finalized filenames/paths
259 *
260 * We'll create two master strings containing the
261 * full server path to the source image and the
262 * full server path to the destination image.
263 * We'll also split the destination image name
264 * so we can insert the thumbnail marker if needed.
265 *
266 */
267 if ($this->create_thumb === FALSE OR $this->thumb_marker == '')
268 {
269 $this->thumb_marker = '';
270 }
271
272 $xp = $this->explode_name($this->dest_image);
273
274 $filename = $xp['name'];
275 $file_ext = $xp['ext'];
276
277 $this->full_src_path = $this->source_folder.$this->source_image;
278 $this->full_dst_path = $this->dest_folder.$filename.$this->thumb_marker.$file_ext;
279
280 /*
281 * Should we maintain image proportions?
282 *
283 * When creating thumbs or copies, the target width/height
284 * might not be in correct proportion with the source
Derek Jones4b9c6292011-07-01 17:40:48 -0500285 * image's width/height. We'll recalculate it here.
Derek Allard2067d1a2008-11-13 22:59:24 +0000286 *
287 */
288 if ($this->maintain_ratio === TRUE && ($this->width != '' AND $this->height != ''))
289 {
290 $this->image_reproportion();
291 }
292
293 /*
294 * Was a width and height specified?
295 *
296 * If the destination width/height was
297 * not submitted we will use the values
298 * from the actual file
299 *
300 */
301 if ($this->width == '')
302 $this->width = $this->orig_width;
303
304 if ($this->height == '')
305 $this->height = $this->orig_height;
306
307 // Set the quality
308 $this->quality = trim(str_replace("%", "", $this->quality));
309
310 if ($this->quality == '' OR $this->quality == 0 OR ! is_numeric($this->quality))
311 $this->quality = 90;
312
313 // Set the x/y coordinates
314 $this->x_axis = ($this->x_axis == '' OR ! is_numeric($this->x_axis)) ? 0 : $this->x_axis;
315 $this->y_axis = ($this->y_axis == '' OR ! is_numeric($this->y_axis)) ? 0 : $this->y_axis;
316
317 // Watermark-related Stuff...
318 if ($this->wm_font_color != '')
319 {
320 if (strlen($this->wm_font_color) == 6)
321 {
322 $this->wm_font_color = '#'.$this->wm_font_color;
323 }
324 }
325
326 if ($this->wm_shadow_color != '')
327 {
328 if (strlen($this->wm_shadow_color) == 6)
329 {
330 $this->wm_shadow_color = '#'.$this->wm_shadow_color;
331 }
332 }
333
334 if ($this->wm_overlay_path != '')
335 {
336 $this->wm_overlay_path = str_replace("\\", "/", realpath($this->wm_overlay_path));
337 }
338
339 if ($this->wm_shadow_color != '')
340 {
341 $this->wm_use_drop_shadow = TRUE;
342 }
343
344 if ($this->wm_font_path != '')
345 {
346 $this->wm_use_truetype = TRUE;
347 }
348
349 return TRUE;
350 }
351
352 // --------------------------------------------------------------------
353
354 /**
355 * Image Resize
356 *
357 * This is a wrapper function that chooses the proper
358 * resize function based on the protocol specified
359 *
360 * @access public
361 * @return bool
362 */
363 function resize()
364 {
365 $protocol = 'image_process_'.$this->image_library;
366
Derek Jones1322ec52009-03-11 17:01:14 +0000367 if (preg_match('/gd2$/i', $protocol))
Derek Allard2067d1a2008-11-13 22:59:24 +0000368 {
369 $protocol = 'image_process_gd';
370 }
371
372 return $this->$protocol('resize');
373 }
374
375 // --------------------------------------------------------------------
376
377 /**
378 * Image Crop
379 *
380 * This is a wrapper function that chooses the proper
381 * cropping function based on the protocol specified
382 *
383 * @access public
384 * @return bool
385 */
386 function crop()
387 {
388 $protocol = 'image_process_'.$this->image_library;
389
Derek Jones1322ec52009-03-11 17:01:14 +0000390 if (preg_match('/gd2$/i', $protocol))
Derek Allard2067d1a2008-11-13 22:59:24 +0000391 {
392 $protocol = 'image_process_gd';
393 }
394
395 return $this->$protocol('crop');
396 }
397
398 // --------------------------------------------------------------------
399
400 /**
401 * Image Rotate
402 *
403 * This is a wrapper function that chooses the proper
404 * rotation function based on the protocol specified
405 *
406 * @access public
407 * @return bool
408 */
409 function rotate()
410 {
411 // Allowed rotation values
412 $degs = array(90, 180, 270, 'vrt', 'hor');
413
Derek Allardd9c7f032008-12-01 20:18:00 +0000414 if ($this->rotation_angle == '' OR ! in_array($this->rotation_angle, $degs))
Derek Allard2067d1a2008-11-13 22:59:24 +0000415 {
416 $this->set_error('imglib_rotation_angle_required');
Derek Jones4b9c6292011-07-01 17:40:48 -0500417 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000418 }
419
420 // Reassign the width and height
421 if ($this->rotation_angle == 90 OR $this->rotation_angle == 270)
422 {
423 $this->width = $this->orig_height;
424 $this->height = $this->orig_width;
425 }
426 else
427 {
428 $this->width = $this->orig_width;
429 $this->height = $this->orig_height;
430 }
431
432
433 // Choose resizing function
434 if ($this->image_library == 'imagemagick' OR $this->image_library == 'netpbm')
435 {
436 $protocol = 'image_process_'.$this->image_library;
437
438 return $this->$protocol('rotate');
439 }
440
441 if ($this->rotation_angle == 'hor' OR $this->rotation_angle == 'vrt')
442 {
443 return $this->image_mirror_gd();
444 }
445 else
446 {
447 return $this->image_rotate_gd();
448 }
449 }
450
451 // --------------------------------------------------------------------
452
453 /**
454 * Image Process Using GD/GD2
455 *
456 * This function will resize or crop
457 *
458 * @access public
459 * @param string
460 * @return bool
461 */
462 function image_process_gd($action = 'resize')
463 {
464 $v2_override = FALSE;
465
466 // If the target width/height match the source, AND if the new file name is not equal to the old file name
467 // we'll simply make a copy of the original with the new name... assuming dynamic rendering is off.
468 if ($this->dynamic_output === FALSE)
469 {
470 if ($this->orig_width == $this->width AND $this->orig_height == $this->height)
471 {
Barry Mienydd671972010-10-04 16:33:58 +0200472 if ($this->source_image != $this->new_image)
473 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000474 if (@copy($this->full_src_path, $this->full_dst_path))
475 {
Derek Jones172e1612009-10-13 14:32:48 +0000476 @chmod($this->full_dst_path, FILE_WRITE_MODE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000477 }
478 }
479
480 return TRUE;
481 }
482 }
483
484 // Let's set up our values based on the action
485 if ($action == 'crop')
486 {
Derek Jones4b9c6292011-07-01 17:40:48 -0500487 // Reassign the source width/height if cropping
488 $this->orig_width = $this->width;
Derek Allard2067d1a2008-11-13 22:59:24 +0000489 $this->orig_height = $this->height;
490
491 // GD 2.0 has a cropping bug so we'll test for it
492 if ($this->gd_version() !== FALSE)
493 {
494 $gd_version = str_replace('0', '', $this->gd_version());
495 $v2_override = ($gd_version == 2) ? TRUE : FALSE;
496 }
497 }
498 else
499 {
500 // If resizing the x/y axis must be zero
501 $this->x_axis = 0;
502 $this->y_axis = 0;
503 }
504
Derek Jones4b9c6292011-07-01 17:40:48 -0500505 // Create the image handle
Derek Allard2067d1a2008-11-13 22:59:24 +0000506 if ( ! ($src_img = $this->image_create_gd()))
507 {
508 return FALSE;
509 }
510
Derek Jones4b9c6292011-07-01 17:40:48 -0500511 // Create The Image
Derek Allard2067d1a2008-11-13 22:59:24 +0000512 //
Derek Jones4b9c6292011-07-01 17:40:48 -0500513 // old conditional which users report cause problems with shared GD libs who report themselves as "2.0 or greater"
514 // it appears that this is no longer the issue that it was in 2004, so we've removed it, retaining it in the comment
515 // below should that ever prove inaccurate.
Derek Allard2067d1a2008-11-13 22:59:24 +0000516 //
Derek Jones4b9c6292011-07-01 17:40:48 -0500517 // if ($this->image_library == 'gd2' AND function_exists('imagecreatetruecolor') AND $v2_override == FALSE)
Barry Mienydd671972010-10-04 16:33:58 +0200518 if ($this->image_library == 'gd2' AND function_exists('imagecreatetruecolor'))
Derek Allard2067d1a2008-11-13 22:59:24 +0000519 {
520 $create = 'imagecreatetruecolor';
521 $copy = 'imagecopyresampled';
522 }
523 else
524 {
525 $create = 'imagecreate';
526 $copy = 'imagecopyresized';
527 }
528
529 $dst_img = $create($this->width, $this->height);
Derek Jones595bfd12010-08-20 10:28:22 -0500530
531 if ($this->image_type == 3) // png we can actually preserve transparency
532 {
533 imagealphablending($dst_img, FALSE);
534 imagesavealpha($dst_img, TRUE);
535 }
Barry Mienydd671972010-10-04 16:33:58 +0200536
Derek Allard2067d1a2008-11-13 22:59:24 +0000537 $copy($dst_img, $src_img, 0, 0, $this->x_axis, $this->y_axis, $this->width, $this->height, $this->orig_width, $this->orig_height);
538
Derek Jones4b9c6292011-07-01 17:40:48 -0500539 // Show the image
Derek Allard2067d1a2008-11-13 22:59:24 +0000540 if ($this->dynamic_output == TRUE)
541 {
542 $this->image_display_gd($dst_img);
543 }
544 else
545 {
546 // Or save it
547 if ( ! $this->image_save_gd($dst_img))
548 {
549 return FALSE;
550 }
551 }
552
Derek Jones4b9c6292011-07-01 17:40:48 -0500553 // Kill the file handles
Derek Allard2067d1a2008-11-13 22:59:24 +0000554 imagedestroy($dst_img);
555 imagedestroy($src_img);
556
557 // Set the file to 777
Derek Jones172e1612009-10-13 14:32:48 +0000558 @chmod($this->full_dst_path, FILE_WRITE_MODE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000559
560 return TRUE;
561 }
562
563 // --------------------------------------------------------------------
564
565 /**
566 * Image Process Using ImageMagick
567 *
568 * This function will resize, crop or rotate
569 *
570 * @access public
571 * @param string
572 * @return bool
573 */
574 function image_process_imagemagick($action = 'resize')
575 {
Derek Jones4b9c6292011-07-01 17:40:48 -0500576 // Do we have a vaild library path?
Derek Allard2067d1a2008-11-13 22:59:24 +0000577 if ($this->library_path == '')
578 {
579 $this->set_error('imglib_libpath_invalid');
580 return FALSE;
581 }
582
Derek Jones1322ec52009-03-11 17:01:14 +0000583 if ( ! preg_match("/convert$/i", $this->library_path))
Derek Allard2067d1a2008-11-13 22:59:24 +0000584 {
Derek Jones1322ec52009-03-11 17:01:14 +0000585 $this->library_path = rtrim($this->library_path, '/').'/';
Derek Allard2067d1a2008-11-13 22:59:24 +0000586
587 $this->library_path .= 'convert';
588 }
589
590 // Execute the command
591 $cmd = $this->library_path." -quality ".$this->quality;
592
593 if ($action == 'crop')
594 {
595 $cmd .= " -crop ".$this->width."x".$this->height."+".$this->x_axis."+".$this->y_axis." \"$this->full_src_path\" \"$this->full_dst_path\" 2>&1";
596 }
597 elseif ($action == 'rotate')
598 {
599 switch ($this->rotation_angle)
600 {
Barry Mienydd671972010-10-04 16:33:58 +0200601 case 'hor' : $angle = '-flop';
Derek Allard2067d1a2008-11-13 22:59:24 +0000602 break;
Barry Mienydd671972010-10-04 16:33:58 +0200603 case 'vrt' : $angle = '-flip';
Derek Allard2067d1a2008-11-13 22:59:24 +0000604 break;
605 default : $angle = '-rotate '.$this->rotation_angle;
606 break;
607 }
608
609 $cmd .= " ".$angle." \"$this->full_src_path\" \"$this->full_dst_path\" 2>&1";
610 }
Derek Jones4b9c6292011-07-01 17:40:48 -0500611 else // Resize
Derek Allard2067d1a2008-11-13 22:59:24 +0000612 {
613 $cmd .= " -resize ".$this->width."x".$this->height." \"$this->full_src_path\" \"$this->full_dst_path\" 2>&1";
614 }
615
616 $retval = 1;
617
618 @exec($cmd, $output, $retval);
619
620 // Did it work?
621 if ($retval > 0)
622 {
623 $this->set_error('imglib_image_process_failed');
624 return FALSE;
625 }
626
627 // Set the file to 777
Derek Jones172e1612009-10-13 14:32:48 +0000628 @chmod($this->full_dst_path, FILE_WRITE_MODE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000629
630 return TRUE;
631 }
632
633 // --------------------------------------------------------------------
634
635 /**
636 * Image Process Using NetPBM
637 *
638 * This function will resize, crop or rotate
639 *
640 * @access public
641 * @param string
642 * @return bool
643 */
644 function image_process_netpbm($action = 'resize')
645 {
646 if ($this->library_path == '')
647 {
648 $this->set_error('imglib_libpath_invalid');
649 return FALSE;
650 }
651
Derek Jones4b9c6292011-07-01 17:40:48 -0500652 // Build the resizing command
Derek Allard2067d1a2008-11-13 22:59:24 +0000653 switch ($this->image_type)
654 {
655 case 1 :
656 $cmd_in = 'giftopnm';
657 $cmd_out = 'ppmtogif';
658 break;
659 case 2 :
660 $cmd_in = 'jpegtopnm';
661 $cmd_out = 'ppmtojpeg';
662 break;
663 case 3 :
664 $cmd_in = 'pngtopnm';
665 $cmd_out = 'ppmtopng';
666 break;
667 }
668
669 if ($action == 'crop')
670 {
671 $cmd_inner = 'pnmcut -left '.$this->x_axis.' -top '.$this->y_axis.' -width '.$this->width.' -height '.$this->height;
672 }
673 elseif ($action == 'rotate')
674 {
675 switch ($this->rotation_angle)
676 {
677 case 90 : $angle = 'r270';
678 break;
679 case 180 : $angle = 'r180';
680 break;
Barry Mienydd671972010-10-04 16:33:58 +0200681 case 270 : $angle = 'r90';
Derek Allard2067d1a2008-11-13 22:59:24 +0000682 break;
683 case 'vrt' : $angle = 'tb';
684 break;
685 case 'hor' : $angle = 'lr';
686 break;
687 }
688
689 $cmd_inner = 'pnmflip -'.$angle.' ';
690 }
691 else // Resize
692 {
693 $cmd_inner = 'pnmscale -xysize '.$this->width.' '.$this->height;
694 }
695
696 $cmd = $this->library_path.$cmd_in.' '.$this->full_src_path.' | '.$cmd_inner.' | '.$cmd_out.' > '.$this->dest_folder.'netpbm.tmp';
697
698 $retval = 1;
699
700 @exec($cmd, $output, $retval);
701
Derek Jones4b9c6292011-07-01 17:40:48 -0500702 // Did it work?
Derek Allard2067d1a2008-11-13 22:59:24 +0000703 if ($retval > 0)
704 {
705 $this->set_error('imglib_image_process_failed');
706 return FALSE;
707 }
708
709 // With NetPBM we have to create a temporary image.
710 // If you try manipulating the original it fails so
711 // we have to rename the temp file.
712 copy ($this->dest_folder.'netpbm.tmp', $this->full_dst_path);
713 unlink ($this->dest_folder.'netpbm.tmp');
Derek Jones172e1612009-10-13 14:32:48 +0000714 @chmod($this->full_dst_path, FILE_WRITE_MODE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000715
716 return TRUE;
717 }
718
719 // --------------------------------------------------------------------
720
721 /**
722 * Image Rotate Using GD
723 *
724 * @access public
725 * @return bool
726 */
727 function image_rotate_gd()
728 {
Derek Jones4b9c6292011-07-01 17:40:48 -0500729 // Create the image handle
Derek Allard2067d1a2008-11-13 22:59:24 +0000730 if ( ! ($src_img = $this->image_create_gd()))
731 {
732 return FALSE;
733 }
734
735 // Set the background color
736 // This won't work with transparent PNG files so we are
737 // going to have to figure out how to determine the color
738 // of the alpha channel in a future release.
739
740 $white = imagecolorallocate($src_img, 255, 255, 255);
741
Derek Jones4b9c6292011-07-01 17:40:48 -0500742 // Rotate it!
Derek Allard2067d1a2008-11-13 22:59:24 +0000743 $dst_img = imagerotate($src_img, $this->rotation_angle, $white);
744
Derek Jones4b9c6292011-07-01 17:40:48 -0500745 // Save the Image
Derek Allard2067d1a2008-11-13 22:59:24 +0000746 if ($this->dynamic_output == TRUE)
747 {
748 $this->image_display_gd($dst_img);
749 }
750 else
751 {
752 // Or save it
753 if ( ! $this->image_save_gd($dst_img))
754 {
755 return FALSE;
756 }
757 }
758
Derek Jones4b9c6292011-07-01 17:40:48 -0500759 // Kill the file handles
Derek Allard2067d1a2008-11-13 22:59:24 +0000760 imagedestroy($dst_img);
761 imagedestroy($src_img);
762
763 // Set the file to 777
764
Derek Jones172e1612009-10-13 14:32:48 +0000765 @chmod($this->full_dst_path, FILE_WRITE_MODE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000766
Pascal Kriete8761ef52011-02-14 13:13:52 -0500767 return TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000768 }
769
770 // --------------------------------------------------------------------
771
772 /**
773 * Create Mirror Image using GD
774 *
775 * This function will flip horizontal or vertical
776 *
777 * @access public
778 * @return bool
779 */
780 function image_mirror_gd()
781 {
782 if ( ! $src_img = $this->image_create_gd())
783 {
784 return FALSE;
785 }
786
Derek Jones4b9c6292011-07-01 17:40:48 -0500787 $width = $this->orig_width;
Derek Allard2067d1a2008-11-13 22:59:24 +0000788 $height = $this->orig_height;
789
790 if ($this->rotation_angle == 'hor')
791 {
792 for ($i = 0; $i < $height; $i++)
793 {
Derek Jones4b9c6292011-07-01 17:40:48 -0500794 $left = 0;
Derek Allard2067d1a2008-11-13 22:59:24 +0000795 $right = $width-1;
796
797 while ($left < $right)
798 {
799 $cl = imagecolorat($src_img, $left, $i);
800 $cr = imagecolorat($src_img, $right, $i);
801
802 imagesetpixel($src_img, $left, $i, $cr);
803 imagesetpixel($src_img, $right, $i, $cl);
804
805 $left++;
806 $right--;
807 }
808 }
809 }
810 else
811 {
812 for ($i = 0; $i < $width; $i++)
813 {
814 $top = 0;
815 $bot = $height-1;
816
817 while ($top < $bot)
818 {
819 $ct = imagecolorat($src_img, $i, $top);
820 $cb = imagecolorat($src_img, $i, $bot);
821
822 imagesetpixel($src_img, $i, $top, $cb);
823 imagesetpixel($src_img, $i, $bot, $ct);
824
825 $top++;
826 $bot--;
827 }
828 }
829 }
830
Derek Jones4b9c6292011-07-01 17:40:48 -0500831 // Show the image
Derek Allard2067d1a2008-11-13 22:59:24 +0000832 if ($this->dynamic_output == TRUE)
833 {
834 $this->image_display_gd($src_img);
835 }
836 else
837 {
838 // Or save it
839 if ( ! $this->image_save_gd($src_img))
840 {
841 return FALSE;
842 }
843 }
844
Derek Jones4b9c6292011-07-01 17:40:48 -0500845 // Kill the file handles
Derek Allard2067d1a2008-11-13 22:59:24 +0000846 imagedestroy($src_img);
847
848 // Set the file to 777
Derek Jones172e1612009-10-13 14:32:48 +0000849 @chmod($this->full_dst_path, FILE_WRITE_MODE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000850
851 return TRUE;
852 }
853
854 // --------------------------------------------------------------------
855
856 /**
857 * Image Watermark
858 *
859 * This is a wrapper function that chooses the type
860 * of watermarking based on the specified preference.
861 *
862 * @access public
863 * @param string
864 * @return bool
865 */
866 function watermark()
867 {
868 if ($this->wm_type == 'overlay')
869 {
870 return $this->overlay_watermark();
871 }
872 else
873 {
874 return $this->text_watermark();
875 }
876 }
877
878 // --------------------------------------------------------------------
879
880 /**
881 * Watermark - Graphic Version
882 *
883 * @access public
884 * @return bool
885 */
886 function overlay_watermark()
887 {
888 if ( ! function_exists('imagecolortransparent'))
889 {
890 $this->set_error('imglib_gd_required');
891 return FALSE;
892 }
893
Derek Jones4b9c6292011-07-01 17:40:48 -0500894 // Fetch source image properties
Derek Allard2067d1a2008-11-13 22:59:24 +0000895 $this->get_image_properties();
896
Derek Jones4b9c6292011-07-01 17:40:48 -0500897 // Fetch watermark image properties
Barry Mienydd671972010-10-04 16:33:58 +0200898 $props = $this->get_image_properties($this->wm_overlay_path, TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000899 $wm_img_type = $props['image_type'];
900 $wm_width = $props['width'];
901 $wm_height = $props['height'];
902
Derek Jones4b9c6292011-07-01 17:40:48 -0500903 // Create two image resources
904 $wm_img = $this->image_create_gd($this->wm_overlay_path, $wm_img_type);
Derek Allard2067d1a2008-11-13 22:59:24 +0000905 $src_img = $this->image_create_gd($this->full_src_path);
906
907 // Reverse the offset if necessary
908 // When the image is positioned at the bottom
909 // we don't want the vertical offset to push it
Derek Jones4b9c6292011-07-01 17:40:48 -0500910 // further down. We want the reverse, so we'll
911 // invert the offset. Same with the horizontal
Derek Allard2067d1a2008-11-13 22:59:24 +0000912 // offset when the image is at the right
913
914 $this->wm_vrt_alignment = strtoupper(substr($this->wm_vrt_alignment, 0, 1));
915 $this->wm_hor_alignment = strtoupper(substr($this->wm_hor_alignment, 0, 1));
916
917 if ($this->wm_vrt_alignment == 'B')
918 $this->wm_vrt_offset = $this->wm_vrt_offset * -1;
919
920 if ($this->wm_hor_alignment == 'R')
921 $this->wm_hor_offset = $this->wm_hor_offset * -1;
922
Derek Jones4b9c6292011-07-01 17:40:48 -0500923 // Set the base x and y axis values
Derek Allard2067d1a2008-11-13 22:59:24 +0000924 $x_axis = $this->wm_hor_offset + $this->wm_padding;
925 $y_axis = $this->wm_vrt_offset + $this->wm_padding;
926
Derek Jones4b9c6292011-07-01 17:40:48 -0500927 // Set the vertical position
Derek Allard2067d1a2008-11-13 22:59:24 +0000928 switch ($this->wm_vrt_alignment)
929 {
930 case 'T':
931 break;
932 case 'M': $y_axis += ($this->orig_height / 2) - ($wm_height / 2);
933 break;
934 case 'B': $y_axis += $this->orig_height - $wm_height;
935 break;
936 }
937
Derek Jones4b9c6292011-07-01 17:40:48 -0500938 // Set the horizontal position
Derek Allard2067d1a2008-11-13 22:59:24 +0000939 switch ($this->wm_hor_alignment)
940 {
941 case 'L':
942 break;
943 case 'C': $x_axis += ($this->orig_width / 2) - ($wm_width / 2);
944 break;
945 case 'R': $x_axis += $this->orig_width - $wm_width;
946 break;
947 }
948
Derek Jones4b9c6292011-07-01 17:40:48 -0500949 // Build the finalized image
Derek Allard2067d1a2008-11-13 22:59:24 +0000950 if ($wm_img_type == 3 AND function_exists('imagealphablending'))
951 {
952 @imagealphablending($src_img, TRUE);
Barry Mienydd671972010-10-04 16:33:58 +0200953 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000954
955 // Set RGB values for text and shadow
956 $rgba = imagecolorat($wm_img, $this->wm_x_transp, $this->wm_y_transp);
957 $alpha = ($rgba & 0x7F000000) >> 24;
958
959 // make a best guess as to whether we're dealing with an image with alpha transparency or no/binary transparency
960 if ($alpha > 0)
961 {
962 // copy the image directly, the image's alpha transparency being the sole determinant of blending
963 imagecopy($src_img, $wm_img, $x_axis, $y_axis, 0, 0, $wm_width, $wm_height);
964 }
965 else
966 {
967 // set our RGB value from above to be transparent and merge the images with the specified opacity
968 imagecolortransparent($wm_img, imagecolorat($wm_img, $this->wm_x_transp, $this->wm_y_transp));
969 imagecopymerge($src_img, $wm_img, $x_axis, $y_axis, 0, 0, $wm_width, $wm_height, $this->wm_opacity);
970 }
971
Derek Jones4b9c6292011-07-01 17:40:48 -0500972 // Output the image
Derek Allard2067d1a2008-11-13 22:59:24 +0000973 if ($this->dynamic_output == TRUE)
974 {
975 $this->image_display_gd($src_img);
976 }
977 else
978 {
979 if ( ! $this->image_save_gd($src_img))
980 {
981 return FALSE;
982 }
983 }
984
985 imagedestroy($src_img);
986 imagedestroy($wm_img);
987
988 return TRUE;
989 }
990
991 // --------------------------------------------------------------------
992
993 /**
994 * Watermark - Text Version
995 *
996 * @access public
997 * @return bool
998 */
999 function text_watermark()
1000 {
1001 if ( ! ($src_img = $this->image_create_gd()))
1002 {
1003 return FALSE;
1004 }
1005
1006 if ($this->wm_use_truetype == TRUE AND ! file_exists($this->wm_font_path))
1007 {
1008 $this->set_error('imglib_missing_font');
1009 return FALSE;
1010 }
1011
Derek Jones4b9c6292011-07-01 17:40:48 -05001012 // Fetch source image properties
Derek Allard2067d1a2008-11-13 22:59:24 +00001013 $this->get_image_properties();
1014
1015 // Set RGB values for text and shadow
1016 $this->wm_font_color = str_replace('#', '', $this->wm_font_color);
1017 $this->wm_shadow_color = str_replace('#', '', $this->wm_shadow_color);
1018
1019 $R1 = hexdec(substr($this->wm_font_color, 0, 2));
1020 $G1 = hexdec(substr($this->wm_font_color, 2, 2));
1021 $B1 = hexdec(substr($this->wm_font_color, 4, 2));
1022
1023 $R2 = hexdec(substr($this->wm_shadow_color, 0, 2));
1024 $G2 = hexdec(substr($this->wm_shadow_color, 2, 2));
1025 $B2 = hexdec(substr($this->wm_shadow_color, 4, 2));
1026
1027 $txt_color = imagecolorclosest($src_img, $R1, $G1, $B1);
1028 $drp_color = imagecolorclosest($src_img, $R2, $G2, $B2);
1029
1030 // Reverse the vertical offset
1031 // When the image is positioned at the bottom
1032 // we don't want the vertical offset to push it
Derek Jones4b9c6292011-07-01 17:40:48 -05001033 // further down. We want the reverse, so we'll
1034 // invert the offset. Note: The horizontal
Derek Allard2067d1a2008-11-13 22:59:24 +00001035 // offset flips itself automatically
1036
1037 if ($this->wm_vrt_alignment == 'B')
1038 $this->wm_vrt_offset = $this->wm_vrt_offset * -1;
1039
1040 if ($this->wm_hor_alignment == 'R')
1041 $this->wm_hor_offset = $this->wm_hor_offset * -1;
1042
1043 // Set font width and height
1044 // These are calculated differently depending on
1045 // whether we are using the true type font or not
1046 if ($this->wm_use_truetype == TRUE)
1047 {
1048 if ($this->wm_font_size == '')
1049 $this->wm_font_size = '17';
1050
Derek Jones4b9c6292011-07-01 17:40:48 -05001051 $fontwidth = $this->wm_font_size-($this->wm_font_size/4);
Derek Allard2067d1a2008-11-13 22:59:24 +00001052 $fontheight = $this->wm_font_size;
1053 $this->wm_vrt_offset += $this->wm_font_size;
1054 }
1055 else
1056 {
Derek Jones4b9c6292011-07-01 17:40:48 -05001057 $fontwidth = imagefontwidth($this->wm_font_size);
Derek Allard2067d1a2008-11-13 22:59:24 +00001058 $fontheight = imagefontheight($this->wm_font_size);
1059 }
1060
1061 // Set base X and Y axis values
1062 $x_axis = $this->wm_hor_offset + $this->wm_padding;
1063 $y_axis = $this->wm_vrt_offset + $this->wm_padding;
1064
1065 // Set verticle alignment
1066 if ($this->wm_use_drop_shadow == FALSE)
1067 $this->wm_shadow_distance = 0;
1068
1069 $this->wm_vrt_alignment = strtoupper(substr($this->wm_vrt_alignment, 0, 1));
1070 $this->wm_hor_alignment = strtoupper(substr($this->wm_hor_alignment, 0, 1));
1071
1072 switch ($this->wm_vrt_alignment)
1073 {
1074 case "T" :
1075 break;
1076 case "M": $y_axis += ($this->orig_height/2)+($fontheight/2);
1077 break;
1078 case "B": $y_axis += ($this->orig_height - $fontheight - $this->wm_shadow_distance - ($fontheight/2));
1079 break;
1080 }
1081
1082 $x_shad = $x_axis + $this->wm_shadow_distance;
1083 $y_shad = $y_axis + $this->wm_shadow_distance;
1084
1085 // Set horizontal alignment
1086 switch ($this->wm_hor_alignment)
1087 {
1088 case "L":
1089 break;
1090 case "R":
1091 if ($this->wm_use_drop_shadow)
1092 $x_shad += ($this->orig_width - $fontwidth*strlen($this->wm_text));
1093 $x_axis += ($this->orig_width - $fontwidth*strlen($this->wm_text));
1094 break;
1095 case "C":
1096 if ($this->wm_use_drop_shadow)
1097 $x_shad += floor(($this->orig_width - $fontwidth*strlen($this->wm_text))/2);
Derek Jones4b9c6292011-07-01 17:40:48 -05001098 $x_axis += floor(($this->orig_width -$fontwidth*strlen($this->wm_text))/2);
Derek Allard2067d1a2008-11-13 22:59:24 +00001099 break;
1100 }
1101
Derek Jones4b9c6292011-07-01 17:40:48 -05001102 // Add the text to the source image
Derek Allard2067d1a2008-11-13 22:59:24 +00001103 if ($this->wm_use_truetype)
1104 {
1105 if ($this->wm_use_drop_shadow)
1106 imagettftext($src_img, $this->wm_font_size, 0, $x_shad, $y_shad, $drp_color, $this->wm_font_path, $this->wm_text);
1107 imagettftext($src_img, $this->wm_font_size, 0, $x_axis, $y_axis, $txt_color, $this->wm_font_path, $this->wm_text);
1108 }
1109 else
1110 {
1111 if ($this->wm_use_drop_shadow)
1112 imagestring($src_img, $this->wm_font_size, $x_shad, $y_shad, $this->wm_text, $drp_color);
1113 imagestring($src_img, $this->wm_font_size, $x_axis, $y_axis, $this->wm_text, $txt_color);
1114 }
1115
Derek Jones4b9c6292011-07-01 17:40:48 -05001116 // Output the final image
Derek Allard2067d1a2008-11-13 22:59:24 +00001117 if ($this->dynamic_output == TRUE)
1118 {
1119 $this->image_display_gd($src_img);
1120 }
1121 else
1122 {
1123 $this->image_save_gd($src_img);
1124 }
1125
1126 imagedestroy($src_img);
1127
1128 return TRUE;
1129 }
1130
1131 // --------------------------------------------------------------------
1132
1133 /**
1134 * Create Image - GD
1135 *
1136 * This simply creates an image resource handle
1137 * based on the type of image being processed
1138 *
1139 * @access public
1140 * @param string
1141 * @return resource
1142 */
1143 function image_create_gd($path = '', $image_type = '')
1144 {
1145 if ($path == '')
1146 $path = $this->full_src_path;
1147
1148 if ($image_type == '')
1149 $image_type = $this->image_type;
1150
1151
1152 switch ($image_type)
1153 {
1154 case 1 :
1155 if ( ! function_exists('imagecreatefromgif'))
1156 {
1157 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_gif_not_supported'));
1158 return FALSE;
1159 }
1160
1161 return imagecreatefromgif($path);
1162 break;
1163 case 2 :
1164 if ( ! function_exists('imagecreatefromjpeg'))
1165 {
1166 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_jpg_not_supported'));
1167 return FALSE;
1168 }
1169
1170 return imagecreatefromjpeg($path);
1171 break;
1172 case 3 :
1173 if ( ! function_exists('imagecreatefrompng'))
1174 {
1175 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_png_not_supported'));
1176 return FALSE;
1177 }
1178
1179 return imagecreatefrompng($path);
1180 break;
1181
1182 }
1183
1184 $this->set_error(array('imglib_unsupported_imagecreate'));
1185 return FALSE;
1186 }
1187
1188 // --------------------------------------------------------------------
1189
1190 /**
1191 * Write image file to disk - GD
1192 *
1193 * Takes an image resource as input and writes the file
1194 * to the specified destination
1195 *
1196 * @access public
1197 * @param resource
1198 * @return bool
1199 */
1200 function image_save_gd($resource)
1201 {
1202 switch ($this->image_type)
1203 {
1204 case 1 :
1205 if ( ! function_exists('imagegif'))
1206 {
1207 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_gif_not_supported'));
1208 return FALSE;
1209 }
1210
Derek Jones541ddbd2008-12-09 15:25:31 +00001211 if ( ! @imagegif($resource, $this->full_dst_path))
1212 {
1213 $this->set_error('imglib_save_failed');
1214 return FALSE;
1215 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001216 break;
1217 case 2 :
1218 if ( ! function_exists('imagejpeg'))
1219 {
1220 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_jpg_not_supported'));
1221 return FALSE;
1222 }
1223
Derek Jones541ddbd2008-12-09 15:25:31 +00001224 if ( ! @imagejpeg($resource, $this->full_dst_path, $this->quality))
1225 {
1226 $this->set_error('imglib_save_failed');
1227 return FALSE;
1228 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001229 break;
1230 case 3 :
1231 if ( ! function_exists('imagepng'))
1232 {
1233 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_png_not_supported'));
1234 return FALSE;
1235 }
1236
Derek Jones541ddbd2008-12-09 15:25:31 +00001237 if ( ! @imagepng($resource, $this->full_dst_path))
1238 {
1239 $this->set_error('imglib_save_failed');
1240 return FALSE;
1241 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001242 break;
1243 default :
1244 $this->set_error(array('imglib_unsupported_imagecreate'));
1245 return FALSE;
1246 break;
1247 }
1248
1249 return TRUE;
1250 }
1251
1252 // --------------------------------------------------------------------
1253
1254 /**
1255 * Dynamically outputs an image
1256 *
1257 * @access public
1258 * @param resource
1259 * @return void
1260 */
1261 function image_display_gd($resource)
1262 {
1263 header("Content-Disposition: filename={$this->source_image};");
1264 header("Content-Type: {$this->mime_type}");
1265 header('Content-Transfer-Encoding: binary');
1266 header('Last-Modified: '.gmdate('D, d M Y H:i:s', time()).' GMT');
1267
1268 switch ($this->image_type)
1269 {
Barry Mienydd671972010-10-04 16:33:58 +02001270 case 1 : imagegif($resource);
Derek Allard2067d1a2008-11-13 22:59:24 +00001271 break;
1272 case 2 : imagejpeg($resource, '', $this->quality);
1273 break;
1274 case 3 : imagepng($resource);
1275 break;
1276 default : echo 'Unable to display the image';
1277 break;
1278 }
1279 }
1280
1281 // --------------------------------------------------------------------
1282
1283 /**
1284 * Re-proportion Image Width/Height
1285 *
1286 * When creating thumbs, the desired width/height
1287 * can end up warping the image due to an incorrect
1288 * ratio between the full-sized image and the thumb.
1289 *
1290 * This function lets us re-proportion the width/height
1291 * if users choose to maintain the aspect ratio when resizing.
1292 *
1293 * @access public
1294 * @return void
1295 */
1296 function image_reproportion()
1297 {
1298 if ( ! is_numeric($this->width) OR ! is_numeric($this->height) OR $this->width == 0 OR $this->height == 0)
1299 return;
1300
1301 if ( ! is_numeric($this->orig_width) OR ! is_numeric($this->orig_height) OR $this->orig_width == 0 OR $this->orig_height == 0)
1302 return;
1303
1304 $new_width = ceil($this->orig_width*$this->height/$this->orig_height);
1305 $new_height = ceil($this->width*$this->orig_height/$this->orig_width);
1306
1307 $ratio = (($this->orig_height/$this->orig_width) - ($this->height/$this->width));
1308
1309 if ($this->master_dim != 'width' AND $this->master_dim != 'height')
1310 {
1311 $this->master_dim = ($ratio < 0) ? 'width' : 'height';
1312 }
1313
1314 if (($this->width != $new_width) AND ($this->height != $new_height))
1315 {
1316 if ($this->master_dim == 'height')
1317 {
1318 $this->width = $new_width;
1319 }
1320 else
1321 {
1322 $this->height = $new_height;
1323 }
1324 }
1325 }
1326
1327 // --------------------------------------------------------------------
1328
1329 /**
1330 * Get image properties
1331 *
1332 * A helper function that gets info about the file
1333 *
1334 * @access public
1335 * @param string
1336 * @return mixed
1337 */
1338 function get_image_properties($path = '', $return = FALSE)
1339 {
1340 // For now we require GD but we should
1341 // find a way to determine this using IM or NetPBM
1342
1343 if ($path == '')
1344 $path = $this->full_src_path;
1345
1346 if ( ! file_exists($path))
1347 {
1348 $this->set_error('imglib_invalid_path');
1349 return FALSE;
1350 }
1351
Phil Sturgeon901998a2011-08-26 10:03:33 +01001352 $vals = getimagesize($path);
Derek Allard2067d1a2008-11-13 22:59:24 +00001353
1354 $types = array(1 => 'gif', 2 => 'jpeg', 3 => 'png');
1355
1356 $mime = (isset($types[$vals['2']])) ? 'image/'.$types[$vals['2']] : 'image/jpg';
1357
1358 if ($return == TRUE)
1359 {
1360 $v['width'] = $vals['0'];
1361 $v['height'] = $vals['1'];
1362 $v['image_type'] = $vals['2'];
1363 $v['size_str'] = $vals['3'];
1364 $v['mime_type'] = $mime;
1365
1366 return $v;
1367 }
1368
1369 $this->orig_width = $vals['0'];
1370 $this->orig_height = $vals['1'];
1371 $this->image_type = $vals['2'];
1372 $this->size_str = $vals['3'];
1373 $this->mime_type = $mime;
1374
1375 return TRUE;
1376 }
1377
1378 // --------------------------------------------------------------------
1379
1380 /**
1381 * Size calculator
1382 *
1383 * This function takes a known width x height and
Derek Jones4b9c6292011-07-01 17:40:48 -05001384 * recalculates it to a new size. Only one
Derek Allard2067d1a2008-11-13 22:59:24 +00001385 * new variable needs to be known
1386 *
1387 * $props = array(
Barry Mienydd671972010-10-04 16:33:58 +02001388 * 'width' => $width,
1389 * 'height' => $height,
Derek Allard2067d1a2008-11-13 22:59:24 +00001390 * 'new_width' => 40,
1391 * 'new_height' => ''
Derek Jones4b9c6292011-07-01 17:40:48 -05001392 * );
Derek Allard2067d1a2008-11-13 22:59:24 +00001393 *
1394 * @access public
1395 * @param array
1396 * @return array
1397 */
1398 function size_calculator($vals)
1399 {
1400 if ( ! is_array($vals))
1401 {
1402 return;
1403 }
1404
1405 $allowed = array('new_width', 'new_height', 'width', 'height');
1406
1407 foreach ($allowed as $item)
1408 {
1409 if ( ! isset($vals[$item]) OR $vals[$item] == '')
1410 $vals[$item] = 0;
1411 }
1412
1413 if ($vals['width'] == 0 OR $vals['height'] == 0)
1414 {
1415 return $vals;
1416 }
1417
1418 if ($vals['new_width'] == 0)
1419 {
1420 $vals['new_width'] = ceil($vals['width']*$vals['new_height']/$vals['height']);
1421 }
1422 elseif ($vals['new_height'] == 0)
1423 {
1424 $vals['new_height'] = ceil($vals['new_width']*$vals['height']/$vals['width']);
1425 }
1426
1427 return $vals;
1428 }
1429
1430 // --------------------------------------------------------------------
1431
1432 /**
1433 * Explode source_image
1434 *
1435 * This is a helper function that extracts the extension
Derek Jones4b9c6292011-07-01 17:40:48 -05001436 * from the source_image. This function lets us deal with
1437 * source_images with multiple periods, like: my.cool.jpg
Derek Allard2067d1a2008-11-13 22:59:24 +00001438 * It returns an associative array with two elements:
Derek Jones4b9c6292011-07-01 17:40:48 -05001439 * $array['ext'] = '.jpg';
Derek Allard2067d1a2008-11-13 22:59:24 +00001440 * $array['name'] = 'my.cool';
1441 *
1442 * @access public
1443 * @param array
1444 * @return array
1445 */
1446 function explode_name($source_image)
1447 {
Derek Jones08cae632009-02-10 20:03:29 +00001448 $ext = strrchr($source_image, '.');
1449 $name = ($ext === FALSE) ? $source_image : substr($source_image, 0, -strlen($ext));
Barry Mienydd671972010-10-04 16:33:58 +02001450
Derek Jones08cae632009-02-10 20:03:29 +00001451 return array('ext' => $ext, 'name' => $name);
Derek Allard2067d1a2008-11-13 22:59:24 +00001452 }
1453
1454 // --------------------------------------------------------------------
1455
1456 /**
1457 * Is GD Installed?
1458 *
1459 * @access public
1460 * @return bool
1461 */
1462 function gd_loaded()
1463 {
1464 if ( ! extension_loaded('gd'))
1465 {
1466 if ( ! dl('gd.so'))
1467 {
1468 return FALSE;
1469 }
1470 }
1471
1472 return TRUE;
1473 }
1474
1475 // --------------------------------------------------------------------
1476
1477 /**
1478 * Get GD version
1479 *
1480 * @access public
1481 * @return mixed
1482 */
1483 function gd_version()
1484 {
1485 if (function_exists('gd_info'))
1486 {
1487 $gd_version = @gd_info();
1488 $gd_version = preg_replace("/\D/", "", $gd_version['GD Version']);
1489
1490 return $gd_version;
1491 }
1492
1493 return FALSE;
1494 }
1495
1496 // --------------------------------------------------------------------
1497
1498 /**
1499 * Set error message
1500 *
1501 * @access public
1502 * @param string
1503 * @return void
1504 */
1505 function set_error($msg)
1506 {
1507 $CI =& get_instance();
1508 $CI->lang->load('imglib');
1509
1510 if (is_array($msg))
1511 {
1512 foreach ($msg as $val)
1513 {
1514
1515 $msg = ($CI->lang->line($val) == FALSE) ? $val : $CI->lang->line($val);
1516 $this->error_msg[] = $msg;
1517 log_message('error', $msg);
1518 }
1519 }
1520 else
1521 {
1522 $msg = ($CI->lang->line($msg) == FALSE) ? $msg : $CI->lang->line($msg);
1523 $this->error_msg[] = $msg;
1524 log_message('error', $msg);
1525 }
1526 }
1527
1528 // --------------------------------------------------------------------
1529
1530 /**
1531 * Show error messages
1532 *
1533 * @access public
1534 * @param string
1535 * @return string
1536 */
1537 function display_errors($open = '<p>', $close = '</p>')
1538 {
1539 $str = '';
1540 foreach ($this->error_msg as $val)
1541 {
1542 $str .= $open.$val.$close;
1543 }
1544
1545 return $str;
1546 }
1547
1548}
1549// END Image_lib Class
1550
1551/* End of file Image_lib.php */
Derek Jonesa3ffbbb2008-05-11 18:18:29 +00001552/* Location: ./system/libraries/Image_lib.php */