blob: 39753705b59cb3f69ac7a5a48e8916d13d7f569f [file] [log] [blame]
Andrey Andreevc5536aa2012-11-01 17:33:58 +02001<?php
Derek Allard2067d1a2008-11-13 22:59:24 +00002/**
3 * CodeIgniter
4 *
Phil Sturgeon07c1ac82012-03-09 17:03:37 +00005 * An open source application development framework for PHP 5.2.4 or newer
Derek Allard2067d1a2008-11-13 22:59:24 +00006 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05007 * NOTICE OF LICENSE
Eric Barnesb1673362011-12-05 22:05:38 -05008 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05009 * Licensed under the Open Software License version 3.0
Eric Barnesb1673362011-12-05 22:05:38 -050010 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -050011 * This source file is subject to the Open Software License (OSL 3.0) that is
Andrey Andreeva3d19c42012-01-24 15:29:29 +020012 * bundled with this package in the files license.txt / license.rst. It is
Derek Jonesf4a4bd82011-10-20 12:18:42 -050013 * 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
darwinel871754a2014-02-11 17:34:57 +010021 * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
Derek Jonesf4a4bd82011-10-20 12:18:42 -050022 * @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 */
Andrey Andreevc5536aa2012-11-01 17:33:58 +020027defined('BASEPATH') OR exit('No direct script access allowed');
Derek Allard2067d1a2008-11-13 22:59:24 +000028
Derek Allard2067d1a2008-11-13 22:59:24 +000029/**
30 * Image Manipulation class
31 *
32 * @package CodeIgniter
33 * @subpackage Libraries
34 * @category Image_lib
Derek Jonesf4a4bd82011-10-20 12:18:42 -050035 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +000036 * @link http://codeigniter.com/user_guide/libraries/image_lib.html
37 */
38class CI_Image_lib {
39
Timothy Warrenb8e62852012-04-26 18:40:54 -040040 /**
41 * PHP extension/library to use for image manipulation
Andrey Andreev56454792012-05-17 14:32:19 +030042 * Can be: imagemagick, netpbm, gd, gd2
Timothy Warrenb8e62852012-04-26 18:40:54 -040043 *
44 * @var string
45 */
46 public $image_library = 'gd2';
Andrey Andreev56454792012-05-17 14:32:19 +030047
Timothy Warrenb8e62852012-04-26 18:40:54 -040048 /**
49 * Path to the graphic library (if applicable)
50 *
51 * @var string
52 */
Andrey Andreev3a459572011-12-21 11:23:11 +020053 public $library_path = '';
Andrey Andreev56454792012-05-17 14:32:19 +030054
Timothy Warrenb8e62852012-04-26 18:40:54 -040055 /**
56 * Whether to send to browser or write to disk
57 *
58 * @var bool
59 */
60 public $dynamic_output = FALSE;
Andrey Andreev56454792012-05-17 14:32:19 +030061
Timothy Warrenb8e62852012-04-26 18:40:54 -040062 /**
63 * Path to original image
64 *
65 * @var string
66 */
Andrey Andreev3a459572011-12-21 11:23:11 +020067 public $source_image = '';
Andrey Andreev56454792012-05-17 14:32:19 +030068
Timothy Warrenb8e62852012-04-26 18:40:54 -040069 /**
70 * Path to the modified image
71 *
72 * @var string
73 */
Andrey Andreev56454792012-05-17 14:32:19 +030074 public $new_image = '';
75
Timothy Warrenb8e62852012-04-26 18:40:54 -040076 /**
77 * Image width
78 *
79 * @var int
80 */
Andrey Andreev56454792012-05-17 14:32:19 +030081 public $width = '';
82
Timothy Warrenb8e62852012-04-26 18:40:54 -040083 /**
84 * Image height
85 *
86 * @var int
87 */
Andrey Andreev56454792012-05-17 14:32:19 +030088 public $height = '';
89
Timothy Warrenb8e62852012-04-26 18:40:54 -040090 /**
91 * Quality percentage of new image
92 *
93 * @var int
94 */
Andrey Andreev56454792012-05-17 14:32:19 +030095 public $quality = 90;
96
Timothy Warrenb8e62852012-04-26 18:40:54 -040097 /**
98 * Whether to create a thumbnail
99 *
100 * @var bool
101 */
Andrey Andreev3a459572011-12-21 11:23:11 +0200102 public $create_thumb = FALSE;
Andrey Andreev56454792012-05-17 14:32:19 +0300103
Timothy Warrenb8e62852012-04-26 18:40:54 -0400104 /**
105 * String to add to thumbnail version of image
106 *
107 * @var string
108 */
Andrey Andreev3a459572011-12-21 11:23:11 +0200109 public $thumb_marker = '_thumb';
Andrey Andreev56454792012-05-17 14:32:19 +0300110
Timothy Warrenb8e62852012-04-26 18:40:54 -0400111 /**
112 * Whether to maintain aspect ratio when resizing or use hard values
113 *
114 * @var bool
115 */
116 public $maintain_ratio = TRUE;
Andrey Andreev56454792012-05-17 14:32:19 +0300117
Timothy Warrenb8e62852012-04-26 18:40:54 -0400118 /**
119 * auto, height, or width. Determines what to use as the master dimension
120 *
121 * @var string
122 */
Andrey Andreev56454792012-05-17 14:32:19 +0300123 public $master_dim = 'auto';
124
Timothy Warrenb8e62852012-04-26 18:40:54 -0400125 /**
126 * Angle at to rotate image
127 *
128 * @var string
129 */
Andrey Andreev3a459572011-12-21 11:23:11 +0200130 public $rotation_angle = '';
Andrey Andreev56454792012-05-17 14:32:19 +0300131
Timothy Warrenb8e62852012-04-26 18:40:54 -0400132 /**
133 * X Coordinate for manipulation of the current image
134 *
135 * @var int
136 */
Andrey Andreev56454792012-05-17 14:32:19 +0300137 public $x_axis = '';
138
Timothy Warrenb8e62852012-04-26 18:40:54 -0400139 /**
140 * Y Coordinate for manipulation of the current image
141 *
142 * @var int
143 */
Andrey Andreev56454792012-05-17 14:32:19 +0300144 public $y_axis = '';
Derek Allard2067d1a2008-11-13 22:59:24 +0000145
Timothy Warrenb8e62852012-04-26 18:40:54 -0400146 // --------------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000147 // Watermark Vars
Timothy Warrenb8e62852012-04-26 18:40:54 -0400148 // --------------------------------------------------------------------------
Andrey Andreev56454792012-05-17 14:32:19 +0300149
Timothy Warrenb8e62852012-04-26 18:40:54 -0400150 /**
151 * Watermark text if graphic is not used
152 *
153 * @var string
154 */
155 public $wm_text = '';
Andrey Andreev56454792012-05-17 14:32:19 +0300156
Timothy Warrenb8e62852012-04-26 18:40:54 -0400157 /**
158 * Type of watermarking. Options: text/overlay
159 *
160 * @var string
161 */
162 public $wm_type = 'text';
Andrey Andreev56454792012-05-17 14:32:19 +0300163
Timothy Warrenb8e62852012-04-26 18:40:54 -0400164 /**
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400165 * Default transparency for watermark
Andrey Andreev56454792012-05-17 14:32:19 +0300166 *
Timothy Warrenb8e62852012-04-26 18:40:54 -0400167 * @var int
168 */
Andrey Andreev3a459572011-12-21 11:23:11 +0200169 public $wm_x_transp = 4;
Andrey Andreev56454792012-05-17 14:32:19 +0300170
Timothy Warrenb8e62852012-04-26 18:40:54 -0400171 /**
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400172 * Default transparency for watermark
173 *
Timothy Warrenb8e62852012-04-26 18:40:54 -0400174 * @var int
175 */
Andrey Andreev3a459572011-12-21 11:23:11 +0200176 public $wm_y_transp = 4;
Andrey Andreev56454792012-05-17 14:32:19 +0300177
Timothy Warrenb8e62852012-04-26 18:40:54 -0400178 /**
179 * Watermark image path
Andrey Andreev56454792012-05-17 14:32:19 +0300180 *
Timothy Warrenb8e62852012-04-26 18:40:54 -0400181 * @var string
182 */
Andrey Andreev56454792012-05-17 14:32:19 +0300183 public $wm_overlay_path = '';
184
Timothy Warrenb8e62852012-04-26 18:40:54 -0400185 /**
186 * TT font
187 *
188 * @var string
189 */
190 public $wm_font_path = '';
Andrey Andreev56454792012-05-17 14:32:19 +0300191
Timothy Warrenb8e62852012-04-26 18:40:54 -0400192 /**
193 * Font size (different versions of GD will either use points or pixels)
194 *
195 * @var int
196 */
197 public $wm_font_size = 17;
Andrey Andreev56454792012-05-17 14:32:19 +0300198
Timothy Warrenb8e62852012-04-26 18:40:54 -0400199 /**
200 * Vertical alignment: T M B
201 *
202 * @var string
203 */
204 public $wm_vrt_alignment = 'B';
Andrey Andreev56454792012-05-17 14:32:19 +0300205
Timothy Warrenb8e62852012-04-26 18:40:54 -0400206 /**
207 * Horizontal alignment: L R C
208 *
209 * @var string
210 */
211 public $wm_hor_alignment = 'C';
Andrey Andreev56454792012-05-17 14:32:19 +0300212
Timothy Warrenb8e62852012-04-26 18:40:54 -0400213 /**
214 * Padding around text
215 *
216 * @var int
217 */
218 public $wm_padding = 0;
Andrey Andreev56454792012-05-17 14:32:19 +0300219
Timothy Warrenb8e62852012-04-26 18:40:54 -0400220 /**
221 * Lets you push text to the right
222 *
223 * @var int
224 */
225 public $wm_hor_offset = 0;
Andrey Andreev56454792012-05-17 14:32:19 +0300226
Timothy Warrenb8e62852012-04-26 18:40:54 -0400227 /**
228 * Lets you push text down
229 *
230 * @var int
231 */
232 public $wm_vrt_offset = 0;
Andrey Andreev56454792012-05-17 14:32:19 +0300233
Timothy Warrenb8e62852012-04-26 18:40:54 -0400234 /**
235 * Text color
236 *
237 * @var string
238 */
Andrey Andreev56454792012-05-17 14:32:19 +0300239 protected $wm_font_color = '#ffffff';
240
Timothy Warrenb8e62852012-04-26 18:40:54 -0400241 /**
242 * Dropshadow color
243 *
244 * @var string
245 */
Andrey Andreev56454792012-05-17 14:32:19 +0300246 protected $wm_shadow_color = '';
247
Timothy Warrenb8e62852012-04-26 18:40:54 -0400248 /**
249 * Dropshadow distance
250 *
251 * @var int
252 */
253 public $wm_shadow_distance = 2;
Andrey Andreev56454792012-05-17 14:32:19 +0300254
Timothy Warrenb8e62852012-04-26 18:40:54 -0400255 /**
256 * Image opacity: 1 - 100 Only works with image
257 *
258 * @var int
259 */
Andrey Andreev56454792012-05-17 14:32:19 +0300260 public $wm_opacity = 50;
Derek Allard2067d1a2008-11-13 22:59:24 +0000261
Timothy Warrenb8e62852012-04-26 18:40:54 -0400262 // --------------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000263 // Private Vars
Timothy Warrenb8e62852012-04-26 18:40:54 -0400264 // --------------------------------------------------------------------------
Andrey Andreev56454792012-05-17 14:32:19 +0300265
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400266 /**
267 * Source image folder
268 *
269 * @var string
270 */
Andrey Andreev3a459572011-12-21 11:23:11 +0200271 public $source_folder = '';
Andrey Andreev56454792012-05-17 14:32:19 +0300272
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400273 /**
274 * Destination image folder
275 *
276 * @var string
277 */
Andrey Andreev3a459572011-12-21 11:23:11 +0200278 public $dest_folder = '';
Andrey Andreev56454792012-05-17 14:32:19 +0300279
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400280 /**
281 * Image mime-type
282 *
283 * @var string
284 */
Andrey Andreev56454792012-05-17 14:32:19 +0300285 public $mime_type = '';
286
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400287 /**
Andrey Andreev56454792012-05-17 14:32:19 +0300288 * Original image width
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400289 *
290 * @var int
291 */
Andrey Andreev56454792012-05-17 14:32:19 +0300292 public $orig_width = '';
293
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400294 /**
295 * Original image height
296 *
297 * @var int
298 */
Andrey Andreev3a459572011-12-21 11:23:11 +0200299 public $orig_height = '';
Andrey Andreev56454792012-05-17 14:32:19 +0300300
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400301 /**
302 * Image format
Andrey Andreev56454792012-05-17 14:32:19 +0300303 *
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400304 * @var string
305 */
Andrey Andreev56454792012-05-17 14:32:19 +0300306 public $image_type = '';
307
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400308 /**
309 * Size of current image
310 *
311 * @var string
312 */
Andrey Andreev56454792012-05-17 14:32:19 +0300313 public $size_str = '';
314
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400315 /**
316 * Full path to source image
317 *
318 * @var string
319 */
Andrey Andreev3a459572011-12-21 11:23:11 +0200320 public $full_src_path = '';
Andrey Andreev56454792012-05-17 14:32:19 +0300321
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400322 /**
323 * Full path to destination image
324 *
325 * @var string
326 */
Andrey Andreev3a459572011-12-21 11:23:11 +0200327 public $full_dst_path = '';
Andrey Andreev56454792012-05-17 14:32:19 +0300328
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400329 /**
Andrey Andreev45965742014-08-27 20:40:11 +0300330 * File permissions
331 *
332 * @var int
333 */
334 public $file_permissions = 0644;
335
336 /**
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400337 * Name of function to create image
338 *
339 * @var string
340 */
Andrey Andreev56454792012-05-17 14:32:19 +0300341 public $create_fnc = 'imagecreatetruecolor';
342
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400343 /**
344 * Name of function to copy image
345 *
346 * @var string
347 */
Andrey Andreev56454792012-05-17 14:32:19 +0300348 public $copy_fnc = 'imagecopyresampled';
349
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400350 /**
351 * Error messages
352 *
353 * @var array
354 */
Andrey Andreev56454792012-05-17 14:32:19 +0300355 public $error_msg = array();
356
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400357 /**
358 * Whether to have a drop shadow on watermark
359 *
360 * @var bool
361 */
Andrey Andreev64dbdfb2011-12-30 14:14:07 +0200362 protected $wm_use_drop_shadow = FALSE;
Andrey Andreev56454792012-05-17 14:32:19 +0300363
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400364 /**
365 * Whether to use truetype fonts
366 *
367 * @var bool
368 */
Andrey Andreev3a459572011-12-21 11:23:11 +0200369 public $wm_use_truetype = FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000370
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400371 /**
372 * Initialize Image Library
373 *
374 * @param array $props
Andrey Andreev56454792012-05-17 14:32:19 +0300375 * @return void
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400376 */
Greg Akera9263282010-11-10 15:26:43 -0600377 public function __construct($props = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000378 {
379 if (count($props) > 0)
380 {
381 $this->initialize($props);
382 }
383
Andrey Andreev8e70b792012-01-12 20:19:24 +0200384 log_message('debug', 'Image Lib Class Initialized');
Derek Allard2067d1a2008-11-13 22:59:24 +0000385 }
386
387 // --------------------------------------------------------------------
388
389 /**
390 * Initialize image properties
391 *
392 * Resets values in case this class is used in a loop
393 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000394 * @return void
395 */
Andrey Andreev4eea9892011-12-19 12:05:41 +0200396 public function clear()
Derek Allard2067d1a2008-11-13 22:59:24 +0000397 {
Sam Doidge5cb5c0a2013-03-13 01:28:06 +0000398 $props = array('thumb_marker', 'library_path', 'source_image', 'new_image', 'width', 'height', 'rotation_angle', 'x_axis', 'y_axis', 'wm_text', 'wm_overlay_path', 'wm_font_path', 'wm_shadow_color', 'source_folder', 'dest_folder', 'mime_type', 'orig_width', 'orig_height', 'image_type', 'size_str', 'full_src_path', 'full_dst_path');
Derek Allard2067d1a2008-11-13 22:59:24 +0000399
400 foreach ($props as $val)
401 {
402 $this->$val = '';
403 }
404
Michael Denniscb07a322011-08-20 23:40:59 -0700405 $this->image_library = 'gd2';
406 $this->dynamic_output = FALSE;
Andrey Andreev56454792012-05-17 14:32:19 +0300407 $this->quality = 90;
Michael Denniscb07a322011-08-20 23:40:59 -0700408 $this->create_thumb = FALSE;
409 $this->thumb_marker = '_thumb';
410 $this->maintain_ratio = TRUE;
411 $this->master_dim = 'auto';
412 $this->wm_type = 'text';
413 $this->wm_x_transp = 4;
414 $this->wm_y_transp = 4;
415 $this->wm_font_size = 17;
416 $this->wm_vrt_alignment = 'B';
417 $this->wm_hor_alignment = 'C';
418 $this->wm_padding = 0;
419 $this->wm_hor_offset = 0;
420 $this->wm_vrt_offset = 0;
421 $this->wm_font_color = '#ffffff';
422 $this->wm_shadow_distance = 2;
423 $this->wm_opacity = 50;
424 $this->create_fnc = 'imagecreatetruecolor';
425 $this->copy_fnc = 'imagecopyresampled';
426 $this->error_msg = array();
427 $this->wm_use_drop_shadow = FALSE;
428 $this->wm_use_truetype = FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000429 }
430
431 // --------------------------------------------------------------------
432
433 /**
434 * initialize image preferences
435 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000436 * @param array
437 * @return bool
438 */
Andrey Andreev4eea9892011-12-19 12:05:41 +0200439 public function initialize($props = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000440 {
Andrey Andreev8e70b792012-01-12 20:19:24 +0200441 // Convert array elements into class variables
Derek Allard2067d1a2008-11-13 22:59:24 +0000442 if (count($props) > 0)
443 {
444 foreach ($props as $key => $val)
445 {
Andrey Andreev64dbdfb2011-12-30 14:14:07 +0200446 if (property_exists($this, $key))
447 {
448 if (in_array($key, array('wm_font_color', 'wm_shadow_color')))
449 {
Andrey Andreev8323ae62011-12-31 18:39:10 +0200450 if (preg_match('/^#?([0-9a-f]{3}|[0-9a-f]{6})$/i', $val, $matches))
Andrey Andreev64dbdfb2011-12-30 14:14:07 +0200451 {
Andrey Andreevcf2ba9e2012-01-01 21:57:13 +0200452 /* $matches[1] contains our hex color value, but it might be
Andrey Andreev8323ae62011-12-31 18:39:10 +0200453 * both in the full 6-length format or the shortened 3-length
454 * value.
Andrey Andreevbb96c8b2011-12-31 18:48:39 +0200455 * We'll later need the full version, so we keep it if it's
Andrey Andreev8323ae62011-12-31 18:39:10 +0200456 * already there and if not - we'll convert to it. We can
457 * access string characters by their index as in an array,
458 * so we'll do that and use concatenation to form the final
459 * value:
460 */
Andrey Andreev665af0c2011-12-30 14:39:29 +0200461 $val = (strlen($matches[1]) === 6)
462 ? '#'.$matches[1]
463 : '#'.$matches[1][0].$matches[1][0].$matches[1][1].$matches[1][1].$matches[1][2].$matches[1][2];
Andrey Andreev64dbdfb2011-12-30 14:14:07 +0200464 }
465 else
466 {
467 continue;
468 }
469 }
470
471 $this->$key = $val;
472 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000473 }
474 }
475
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200476 // Is there a source image? If not, there's no reason to continue
Alex Bilbied261b1e2012-06-02 11:12:16 +0100477 if ($this->source_image === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000478 {
479 $this->set_error('imglib_source_image_required');
Eric Barnesb1673362011-12-05 22:05:38 -0500480 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000481 }
482
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200483 /* Is getimagesize() available?
Derek Allard2067d1a2008-11-13 22:59:24 +0000484 *
485 * We use it to determine the image properties (width/height).
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200486 * Note: We need to figure out how to determine image
Derek Allard2067d1a2008-11-13 22:59:24 +0000487 * properties using ImageMagick and NetPBM
Derek Allard2067d1a2008-11-13 22:59:24 +0000488 */
489 if ( ! function_exists('getimagesize'))
490 {
491 $this->set_error('imglib_gd_required_for_props');
492 return FALSE;
493 }
494
495 $this->image_library = strtolower($this->image_library);
496
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200497 /* Set the full server path
Derek Allard2067d1a2008-11-13 22:59:24 +0000498 *
499 * The source image may or may not contain a path.
500 * Either way, we'll try use realpath to generate the
501 * full server path in order to more reliably read it.
Derek Allard2067d1a2008-11-13 22:59:24 +0000502 */
Andrey Andreevea41c8a2014-02-26 18:31:02 +0200503 if (($full_source_path = realpath($this->source_image)) !== FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000504 {
Andrey Andreevea41c8a2014-02-26 18:31:02 +0200505 $full_source_path = str_replace('\\', '/', $full_source_path);
Derek Allard2067d1a2008-11-13 22:59:24 +0000506 }
507 else
508 {
509 $full_source_path = $this->source_image;
510 }
511
512 $x = explode('/', $full_source_path);
513 $this->source_image = end($x);
514 $this->source_folder = str_replace($this->source_image, '', $full_source_path);
515
516 // Set the Image Properties
517 if ( ! $this->get_image_properties($this->source_folder.$this->source_image))
518 {
Eric Barnesb1673362011-12-05 22:05:38 -0500519 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000520 }
521
522 /*
523 * Assign the "new" image name/path
524 *
525 * If the user has set a "new_image" name it means
526 * we are making a copy of the source image. If not
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200527 * it means we are altering the original. We'll
Derek Allard2067d1a2008-11-13 22:59:24 +0000528 * set the destination filename and path accordingly.
Derek Allard2067d1a2008-11-13 22:59:24 +0000529 */
Alex Bilbied261b1e2012-06-02 11:12:16 +0100530 if ($this->new_image === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000531 {
532 $this->dest_image = $this->source_image;
533 $this->dest_folder = $this->source_folder;
534 }
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200535 elseif (strpos($this->new_image, '/') === FALSE)
536 {
537 $this->dest_folder = $this->source_folder;
538 $this->dest_image = $this->new_image;
539 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000540 else
541 {
Andrey Andreev1b815532012-04-03 16:06:03 +0300542 if (strpos($this->new_image, '/') === FALSE && strpos($this->new_image, '\\') === FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000543 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200544 $full_dest_path = str_replace('\\', '/', realpath($this->new_image));
Derek Allard2067d1a2008-11-13 22:59:24 +0000545 }
546 else
547 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200548 $full_dest_path = $this->new_image;
549 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000550
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200551 // Is there a file name?
552 if ( ! preg_match('#\.(jpg|jpeg|gif|png)$#i', $full_dest_path))
553 {
554 $this->dest_folder = $full_dest_path.'/';
555 $this->dest_image = $this->source_image;
556 }
557 else
558 {
559 $x = explode('/', $full_dest_path);
560 $this->dest_image = end($x);
561 $this->dest_folder = str_replace($this->dest_image, '', $full_dest_path);
Derek Allard2067d1a2008-11-13 22:59:24 +0000562 }
563 }
564
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200565 /* Compile the finalized filenames/paths
Derek Allard2067d1a2008-11-13 22:59:24 +0000566 *
567 * We'll create two master strings containing the
568 * full server path to the source image and the
569 * full server path to the destination image.
570 * We'll also split the destination image name
571 * so we can insert the thumbnail marker if needed.
Derek Allard2067d1a2008-11-13 22:59:24 +0000572 */
Alex Bilbied261b1e2012-06-02 11:12:16 +0100573 if ($this->create_thumb === FALSE OR $this->thumb_marker === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000574 {
575 $this->thumb_marker = '';
576 }
577
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200578 $xp = $this->explode_name($this->dest_image);
Derek Allard2067d1a2008-11-13 22:59:24 +0000579
580 $filename = $xp['name'];
581 $file_ext = $xp['ext'];
582
583 $this->full_src_path = $this->source_folder.$this->source_image;
584 $this->full_dst_path = $this->dest_folder.$filename.$this->thumb_marker.$file_ext;
585
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200586 /* Should we maintain image proportions?
Derek Allard2067d1a2008-11-13 22:59:24 +0000587 *
588 * When creating thumbs or copies, the target width/height
589 * might not be in correct proportion with the source
Andrey Andreev8e70b792012-01-12 20:19:24 +0200590 * image's width/height. We'll recalculate it here.
Derek Allard2067d1a2008-11-13 22:59:24 +0000591 */
Alex Bilbied261b1e2012-06-02 11:12:16 +0100592 if ($this->maintain_ratio === TRUE && ($this->width !== 0 OR $this->height !== 0))
Derek Allard2067d1a2008-11-13 22:59:24 +0000593 {
594 $this->image_reproportion();
595 }
596
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200597 /* Was a width and height specified?
Derek Allard2067d1a2008-11-13 22:59:24 +0000598 *
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200599 * If the destination width/height was not submitted we
600 * will use the values from the actual file
Derek Allard2067d1a2008-11-13 22:59:24 +0000601 */
Alex Bilbied261b1e2012-06-02 11:12:16 +0100602 if ($this->width === '')
Andrey Andreev8e70b792012-01-12 20:19:24 +0200603 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000604 $this->width = $this->orig_width;
Andrey Andreev8e70b792012-01-12 20:19:24 +0200605 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000606
Alex Bilbied261b1e2012-06-02 11:12:16 +0100607 if ($this->height === '')
Andrey Andreev8e70b792012-01-12 20:19:24 +0200608 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000609 $this->height = $this->orig_height;
Andrey Andreev8e70b792012-01-12 20:19:24 +0200610 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000611
612 // Set the quality
Andrey Andreev8e70b792012-01-12 20:19:24 +0200613 $this->quality = trim(str_replace('%', '', $this->quality));
Derek Allard2067d1a2008-11-13 22:59:24 +0000614
Andrey Andreev7a7ad782012-11-12 17:21:01 +0200615 if ($this->quality === '' OR $this->quality === 0 OR ! ctype_digit($this->quality))
Andrey Andreev8e70b792012-01-12 20:19:24 +0200616 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000617 $this->quality = 90;
Andrey Andreev8e70b792012-01-12 20:19:24 +0200618 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000619
620 // Set the x/y coordinates
Andrey Andreev5036c9c2012-06-04 15:34:56 +0300621 is_numeric($this->x_axis) OR $this->x_axis = 0;
622 is_numeric($this->y_axis) OR $this->y_axis = 0;
Derek Allard2067d1a2008-11-13 22:59:24 +0000623
624 // Watermark-related Stuff...
Alex Bilbied261b1e2012-06-02 11:12:16 +0100625 if ($this->wm_overlay_path !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000626 {
Andrey Andreev8e70b792012-01-12 20:19:24 +0200627 $this->wm_overlay_path = str_replace('\\', '/', realpath($this->wm_overlay_path));
Derek Allard2067d1a2008-11-13 22:59:24 +0000628 }
629
Alex Bilbied261b1e2012-06-02 11:12:16 +0100630 if ($this->wm_shadow_color !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000631 {
632 $this->wm_use_drop_shadow = TRUE;
633 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100634 elseif ($this->wm_use_drop_shadow === TRUE && $this->wm_shadow_color === '')
Andrey Andreev64dbdfb2011-12-30 14:14:07 +0200635 {
636 $this->wm_use_drop_shadow = FALSE;
637 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000638
Alex Bilbied261b1e2012-06-02 11:12:16 +0100639 if ($this->wm_font_path !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000640 {
641 $this->wm_use_truetype = TRUE;
642 }
643
644 return TRUE;
645 }
646
647 // --------------------------------------------------------------------
648
649 /**
650 * Image Resize
651 *
652 * This is a wrapper function that chooses the proper
653 * resize function based on the protocol specified
654 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000655 * @return bool
656 */
Andrey Andreev4eea9892011-12-19 12:05:41 +0200657 public function resize()
Derek Allard2067d1a2008-11-13 22:59:24 +0000658 {
Andrey Andreev1a9f52c2012-01-07 01:06:34 +0200659 $protocol = ($this->image_library === 'gd2') ? 'image_process_gd' : 'image_process_'.$this->image_library;
Derek Allard2067d1a2008-11-13 22:59:24 +0000660 return $this->$protocol('resize');
661 }
662
663 // --------------------------------------------------------------------
664
665 /**
666 * Image Crop
667 *
668 * This is a wrapper function that chooses the proper
669 * cropping function based on the protocol specified
670 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000671 * @return bool
672 */
Andrey Andreev4eea9892011-12-19 12:05:41 +0200673 public function crop()
Derek Allard2067d1a2008-11-13 22:59:24 +0000674 {
Andrey Andreev5a67e3d2012-01-07 01:21:09 +0200675 $protocol = ($this->image_library === 'gd2') ? 'image_process_gd' : 'image_process_'.$this->image_library;
Derek Allard2067d1a2008-11-13 22:59:24 +0000676 return $this->$protocol('crop');
677 }
678
679 // --------------------------------------------------------------------
680
681 /**
682 * Image Rotate
683 *
684 * This is a wrapper function that chooses the proper
685 * rotation function based on the protocol specified
686 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000687 * @return bool
688 */
Andrey Andreev4eea9892011-12-19 12:05:41 +0200689 public function rotate()
Derek Allard2067d1a2008-11-13 22:59:24 +0000690 {
691 // Allowed rotation values
692 $degs = array(90, 180, 270, 'vrt', 'hor');
693
Alex Bilbied261b1e2012-06-02 11:12:16 +0100694 if ($this->rotation_angle === '' OR ! in_array($this->rotation_angle, $degs))
Derek Allard2067d1a2008-11-13 22:59:24 +0000695 {
696 $this->set_error('imglib_rotation_angle_required');
Eric Barnesb1673362011-12-05 22:05:38 -0500697 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000698 }
699
700 // Reassign the width and height
Alex Bilbied261b1e2012-06-02 11:12:16 +0100701 if ($this->rotation_angle === 90 OR $this->rotation_angle === 270)
Derek Allard2067d1a2008-11-13 22:59:24 +0000702 {
703 $this->width = $this->orig_height;
704 $this->height = $this->orig_width;
705 }
706 else
707 {
708 $this->width = $this->orig_width;
709 $this->height = $this->orig_height;
710 }
711
Derek Allard2067d1a2008-11-13 22:59:24 +0000712 // Choose resizing function
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200713 if ($this->image_library === 'imagemagick' OR $this->image_library === 'netpbm')
Derek Allard2067d1a2008-11-13 22:59:24 +0000714 {
715 $protocol = 'image_process_'.$this->image_library;
Derek Allard2067d1a2008-11-13 22:59:24 +0000716 return $this->$protocol('rotate');
717 }
718
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200719 return ($this->rotation_angle === 'hor' OR $this->rotation_angle === 'vrt')
720 ? $this->image_mirror_gd()
721 : $this->image_rotate_gd();
Derek Allard2067d1a2008-11-13 22:59:24 +0000722 }
723
724 // --------------------------------------------------------------------
725
726 /**
727 * Image Process Using GD/GD2
728 *
729 * This function will resize or crop
730 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000731 * @param string
732 * @return bool
733 */
Andrey Andreev4eea9892011-12-19 12:05:41 +0200734 public function image_process_gd($action = 'resize')
Derek Allard2067d1a2008-11-13 22:59:24 +0000735 {
736 $v2_override = FALSE;
737
738 // If the target width/height match the source, AND if the new file name is not equal to the old file name
739 // we'll simply make a copy of the original with the new name... assuming dynamic rendering is off.
Alex Bilbied261b1e2012-06-02 11:12:16 +0100740 if ($this->dynamic_output === FALSE && $this->orig_width === $this->width && $this->orig_height === $this->height)
Derek Allard2067d1a2008-11-13 22:59:24 +0000741 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100742 if ($this->source_image !== $this->new_image && @copy($this->full_src_path, $this->full_dst_path))
Derek Allard2067d1a2008-11-13 22:59:24 +0000743 {
Andrey Andreev45965742014-08-27 20:40:11 +0300744 chmod($this->full_dst_path, $this->file_permissions);
Derek Allard2067d1a2008-11-13 22:59:24 +0000745 }
Andrey Andreeva92b9032011-12-24 19:05:58 +0200746
747 return TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000748 }
749
750 // Let's set up our values based on the action
Alex Bilbied261b1e2012-06-02 11:12:16 +0100751 if ($action === 'crop')
Derek Allard2067d1a2008-11-13 22:59:24 +0000752 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200753 // Reassign the source width/height if cropping
Derek Jones4b9c6292011-07-01 17:40:48 -0500754 $this->orig_width = $this->width;
Derek Allard2067d1a2008-11-13 22:59:24 +0000755 $this->orig_height = $this->height;
756
757 // GD 2.0 has a cropping bug so we'll test for it
758 if ($this->gd_version() !== FALSE)
759 {
760 $gd_version = str_replace('0', '', $this->gd_version());
Andrey Andreev5036c9c2012-06-04 15:34:56 +0300761 $v2_override = ($gd_version === 2);
Derek Allard2067d1a2008-11-13 22:59:24 +0000762 }
763 }
764 else
765 {
766 // If resizing the x/y axis must be zero
767 $this->x_axis = 0;
768 $this->y_axis = 0;
769 }
770
Derek Jones4b9c6292011-07-01 17:40:48 -0500771 // Create the image handle
Derek Allard2067d1a2008-11-13 22:59:24 +0000772 if ( ! ($src_img = $this->image_create_gd()))
773 {
774 return FALSE;
775 }
776
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200777 /* Create the image
778 *
779 * Old conditional which users report cause problems with shared GD libs who report themselves as "2.0 or greater"
780 * it appears that this is no longer the issue that it was in 2004, so we've removed it, retaining it in the comment
781 * below should that ever prove inaccurate.
782 *
Alex Bilbied261b1e2012-06-02 11:12:16 +0100783 * if ($this->image_library === 'gd2' && function_exists('imagecreatetruecolor') && $v2_override === FALSE)
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200784 */
Andrey Andreev8e70b792012-01-12 20:19:24 +0200785 if ($this->image_library === 'gd2' && function_exists('imagecreatetruecolor'))
Derek Allard2067d1a2008-11-13 22:59:24 +0000786 {
787 $create = 'imagecreatetruecolor';
788 $copy = 'imagecopyresampled';
789 }
790 else
791 {
792 $create = 'imagecreate';
793 $copy = 'imagecopyresized';
794 }
795
796 $dst_img = $create($this->width, $this->height);
Derek Jones595bfd12010-08-20 10:28:22 -0500797
Alex Bilbied261b1e2012-06-02 11:12:16 +0100798 if ($this->image_type === 3) // png we can actually preserve transparency
Derek Jones595bfd12010-08-20 10:28:22 -0500799 {
800 imagealphablending($dst_img, FALSE);
801 imagesavealpha($dst_img, TRUE);
802 }
Barry Mienydd671972010-10-04 16:33:58 +0200803
Derek Allard2067d1a2008-11-13 22:59:24 +0000804 $copy($dst_img, $src_img, 0, 0, $this->x_axis, $this->y_axis, $this->width, $this->height, $this->orig_width, $this->orig_height);
805
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200806 // Show the image
Alex Bilbied261b1e2012-06-02 11:12:16 +0100807 if ($this->dynamic_output === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000808 {
809 $this->image_display_gd($dst_img);
810 }
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200811 elseif ( ! $this->image_save_gd($dst_img)) // Or save it
Derek Allard2067d1a2008-11-13 22:59:24 +0000812 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200813 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000814 }
815
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200816 // Kill the file handles
Derek Allard2067d1a2008-11-13 22:59:24 +0000817 imagedestroy($dst_img);
818 imagedestroy($src_img);
819
Andrey Andreev45965742014-08-27 20:40:11 +0300820 chmod($this->full_dst_path, $this->file_permissions);
Derek Allard2067d1a2008-11-13 22:59:24 +0000821
822 return TRUE;
823 }
824
825 // --------------------------------------------------------------------
826
827 /**
828 * Image Process Using ImageMagick
829 *
830 * This function will resize, crop or rotate
831 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000832 * @param string
833 * @return bool
834 */
Andrey Andreev4eea9892011-12-19 12:05:41 +0200835 public function image_process_imagemagick($action = 'resize')
Derek Allard2067d1a2008-11-13 22:59:24 +0000836 {
Derek Jones4b9c6292011-07-01 17:40:48 -0500837 // Do we have a vaild library path?
Alex Bilbied261b1e2012-06-02 11:12:16 +0100838 if ($this->library_path === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000839 {
840 $this->set_error('imglib_libpath_invalid');
841 return FALSE;
842 }
843
Andrey Andreev8e70b792012-01-12 20:19:24 +0200844 if ( ! preg_match('/convert$/i', $this->library_path))
Derek Allard2067d1a2008-11-13 22:59:24 +0000845 {
Andrey Andreeva92b9032011-12-24 19:05:58 +0200846 $this->library_path = rtrim($this->library_path, '/').'/convert';
Derek Allard2067d1a2008-11-13 22:59:24 +0000847 }
848
849 // Execute the command
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200850 $cmd = $this->library_path.' -quality '.$this->quality;
Derek Allard2067d1a2008-11-13 22:59:24 +0000851
Alex Bilbied261b1e2012-06-02 11:12:16 +0100852 if ($action === 'crop')
Derek Allard2067d1a2008-11-13 22:59:24 +0000853 {
Andrey Andreev8e70b792012-01-12 20:19:24 +0200854 $cmd .= ' -crop '.$this->width.'x'.$this->height.'+'.$this->x_axis.'+'.$this->y_axis.' "'.$this->full_src_path.'" "'.$this->full_dst_path .'" 2>&1';
Derek Allard2067d1a2008-11-13 22:59:24 +0000855 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100856 elseif ($action === 'rotate')
Derek Allard2067d1a2008-11-13 22:59:24 +0000857 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200858 $angle = ($this->rotation_angle === 'hor' OR $this->rotation_angle === 'vrt')
859 ? '-flop' : '-rotate '.$this->rotation_angle;
Derek Allard2067d1a2008-11-13 22:59:24 +0000860
Andrey Andreev8e70b792012-01-12 20:19:24 +0200861 $cmd .= ' '.$angle.' "'.$this->full_src_path.'" "'.$this->full_dst_path.'" 2>&1';
Derek Allard2067d1a2008-11-13 22:59:24 +0000862 }
Andrey Andreev8e70b792012-01-12 20:19:24 +0200863 else // Resize
Derek Allard2067d1a2008-11-13 22:59:24 +0000864 {
Omar24063af2012-07-02 13:50:17 -0300865 if($this->maintain_ratio === TRUE)
866 {
867 $cmd .= ' -resize '.$this->width.'x'.$this->height.' "'.$this->full_src_path.'" "'.$this->full_dst_path.'" 2>&1';
868 }
Omarbb531d62012-06-29 10:48:28 -0300869 else
Omar24063af2012-07-02 13:50:17 -0300870 {
871 $cmd .= ' -resize '.$this->width.'x'.$this->height.'\! "'.$this->full_src_path.'" "'.$this->full_dst_path.'" 2>&1';
872 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000873 }
874
875 $retval = 1;
Andrey Andreeve9d2dc82012-11-07 14:23:29 +0200876 // exec() might be disabled
877 if (function_usable('exec'))
878 {
879 @exec($cmd, $output, $retval);
880 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000881
Andrey Andreev8e70b792012-01-12 20:19:24 +0200882 // Did it work?
Derek Allard2067d1a2008-11-13 22:59:24 +0000883 if ($retval > 0)
884 {
885 $this->set_error('imglib_image_process_failed');
886 return FALSE;
887 }
888
Andrey Andreev45965742014-08-27 20:40:11 +0300889 chmod($this->full_dst_path, $this->file_permissions);
Derek Allard2067d1a2008-11-13 22:59:24 +0000890
891 return TRUE;
892 }
893
894 // --------------------------------------------------------------------
895
896 /**
897 * Image Process Using NetPBM
898 *
899 * This function will resize, crop or rotate
900 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000901 * @param string
902 * @return bool
903 */
Andrey Andreev4eea9892011-12-19 12:05:41 +0200904 public function image_process_netpbm($action = 'resize')
Derek Allard2067d1a2008-11-13 22:59:24 +0000905 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100906 if ($this->library_path === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000907 {
908 $this->set_error('imglib_libpath_invalid');
909 return FALSE;
910 }
911
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200912 // Build the resizing command
Derek Allard2067d1a2008-11-13 22:59:24 +0000913 switch ($this->image_type)
914 {
915 case 1 :
Andrey Andreev56454792012-05-17 14:32:19 +0300916 $cmd_in = 'giftopnm';
917 $cmd_out = 'ppmtogif';
Derek Allard2067d1a2008-11-13 22:59:24 +0000918 break;
919 case 2 :
Andrey Andreev56454792012-05-17 14:32:19 +0300920 $cmd_in = 'jpegtopnm';
921 $cmd_out = 'ppmtojpeg';
Derek Allard2067d1a2008-11-13 22:59:24 +0000922 break;
923 case 3 :
Andrey Andreev56454792012-05-17 14:32:19 +0300924 $cmd_in = 'pngtopnm';
925 $cmd_out = 'ppmtopng';
Derek Allard2067d1a2008-11-13 22:59:24 +0000926 break;
927 }
928
Alex Bilbied261b1e2012-06-02 11:12:16 +0100929 if ($action === 'crop')
Derek Allard2067d1a2008-11-13 22:59:24 +0000930 {
931 $cmd_inner = 'pnmcut -left '.$this->x_axis.' -top '.$this->y_axis.' -width '.$this->width.' -height '.$this->height;
932 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100933 elseif ($action === 'rotate')
Derek Allard2067d1a2008-11-13 22:59:24 +0000934 {
935 switch ($this->rotation_angle)
936 {
Andrey Andreev56454792012-05-17 14:32:19 +0300937 case 90: $angle = 'r270';
Derek Allard2067d1a2008-11-13 22:59:24 +0000938 break;
Andrey Andreev56454792012-05-17 14:32:19 +0300939 case 180: $angle = 'r180';
Derek Allard2067d1a2008-11-13 22:59:24 +0000940 break;
Andrey Andreev56454792012-05-17 14:32:19 +0300941 case 270: $angle = 'r90';
Derek Allard2067d1a2008-11-13 22:59:24 +0000942 break;
Andrey Andreev56454792012-05-17 14:32:19 +0300943 case 'vrt': $angle = 'tb';
Derek Allard2067d1a2008-11-13 22:59:24 +0000944 break;
Andrey Andreev56454792012-05-17 14:32:19 +0300945 case 'hor': $angle = 'lr';
Derek Allard2067d1a2008-11-13 22:59:24 +0000946 break;
947 }
948
949 $cmd_inner = 'pnmflip -'.$angle.' ';
950 }
951 else // Resize
952 {
953 $cmd_inner = 'pnmscale -xysize '.$this->width.' '.$this->height;
954 }
955
956 $cmd = $this->library_path.$cmd_in.' '.$this->full_src_path.' | '.$cmd_inner.' | '.$cmd_out.' > '.$this->dest_folder.'netpbm.tmp';
957
958 $retval = 1;
Andrey Andreeve9d2dc82012-11-07 14:23:29 +0200959 // exec() might be disabled
960 if (function_usable('exec'))
961 {
962 @exec($cmd, $output, $retval);
963 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000964
Andrey Andreev8e70b792012-01-12 20:19:24 +0200965 // Did it work?
Derek Allard2067d1a2008-11-13 22:59:24 +0000966 if ($retval > 0)
967 {
968 $this->set_error('imglib_image_process_failed');
969 return FALSE;
970 }
971
972 // With NetPBM we have to create a temporary image.
973 // If you try manipulating the original it fails so
974 // we have to rename the temp file.
Andrey Andreeve9d2dc82012-11-07 14:23:29 +0200975 copy($this->dest_folder.'netpbm.tmp', $this->full_dst_path);
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200976 unlink($this->dest_folder.'netpbm.tmp');
Andrey Andreev45965742014-08-27 20:40:11 +0300977 chmod($this->full_dst_path, $this->file_permissions);
Derek Allard2067d1a2008-11-13 22:59:24 +0000978
979 return TRUE;
980 }
981
982 // --------------------------------------------------------------------
983
984 /**
985 * Image Rotate Using GD
986 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000987 * @return bool
988 */
Andrey Andreev4eea9892011-12-19 12:05:41 +0200989 public function image_rotate_gd()
Derek Allard2067d1a2008-11-13 22:59:24 +0000990 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200991 // Create the image handle
Derek Allard2067d1a2008-11-13 22:59:24 +0000992 if ( ! ($src_img = $this->image_create_gd()))
993 {
994 return FALSE;
995 }
996
997 // Set the background color
998 // This won't work with transparent PNG files so we are
999 // going to have to figure out how to determine the color
1000 // of the alpha channel in a future release.
1001
1002 $white = imagecolorallocate($src_img, 255, 255, 255);
1003
Andrey Andreev8e70b792012-01-12 20:19:24 +02001004 // Rotate it!
Derek Allard2067d1a2008-11-13 22:59:24 +00001005 $dst_img = imagerotate($src_img, $this->rotation_angle, $white);
1006
Andrey Andreev8e70b792012-01-12 20:19:24 +02001007 // Show the image
Alex Bilbied261b1e2012-06-02 11:12:16 +01001008 if ($this->dynamic_output === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001009 {
1010 $this->image_display_gd($dst_img);
1011 }
Andrey Andreev8e70b792012-01-12 20:19:24 +02001012 elseif ( ! $this->image_save_gd($dst_img)) // ... or save it
Derek Allard2067d1a2008-11-13 22:59:24 +00001013 {
Andrey Andreev8e70b792012-01-12 20:19:24 +02001014 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +00001015 }
1016
Andrey Andreev8e70b792012-01-12 20:19:24 +02001017 // Kill the file handles
Derek Allard2067d1a2008-11-13 22:59:24 +00001018 imagedestroy($dst_img);
1019 imagedestroy($src_img);
1020
Andrey Andreev45965742014-08-27 20:40:11 +03001021 chmod($this->full_dst_path, $this->file_permissions);
Derek Allard2067d1a2008-11-13 22:59:24 +00001022
Pascal Kriete8761ef52011-02-14 13:13:52 -05001023 return TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +00001024 }
1025
1026 // --------------------------------------------------------------------
1027
1028 /**
1029 * Create Mirror Image using GD
1030 *
1031 * This function will flip horizontal or vertical
1032 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001033 * @return bool
1034 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001035 public function image_mirror_gd()
Derek Allard2067d1a2008-11-13 22:59:24 +00001036 {
1037 if ( ! $src_img = $this->image_create_gd())
1038 {
1039 return FALSE;
1040 }
1041
Derek Jones4b9c6292011-07-01 17:40:48 -05001042 $width = $this->orig_width;
Derek Allard2067d1a2008-11-13 22:59:24 +00001043 $height = $this->orig_height;
1044
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001045 if ($this->rotation_angle === 'hor')
Derek Allard2067d1a2008-11-13 22:59:24 +00001046 {
Andrey Andreeva92b9032011-12-24 19:05:58 +02001047 for ($i = 0; $i < $height; $i++, $left = 0, $right = $width-1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001048 {
Derek Allard2067d1a2008-11-13 22:59:24 +00001049 while ($left < $right)
1050 {
1051 $cl = imagecolorat($src_img, $left, $i);
1052 $cr = imagecolorat($src_img, $right, $i);
1053
1054 imagesetpixel($src_img, $left, $i, $cr);
1055 imagesetpixel($src_img, $right, $i, $cl);
1056
1057 $left++;
1058 $right--;
1059 }
1060 }
1061 }
1062 else
1063 {
Andrey Andreeva92b9032011-12-24 19:05:58 +02001064 for ($i = 0; $i < $width; $i++, $top = 0, $bot = $height-1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001065 {
Derek Allard2067d1a2008-11-13 22:59:24 +00001066 while ($top < $bot)
1067 {
1068 $ct = imagecolorat($src_img, $i, $top);
1069 $cb = imagecolorat($src_img, $i, $bot);
1070
1071 imagesetpixel($src_img, $i, $top, $cb);
1072 imagesetpixel($src_img, $i, $bot, $ct);
1073
1074 $top++;
1075 $bot--;
1076 }
1077 }
1078 }
1079
Andrey Andreev8e70b792012-01-12 20:19:24 +02001080 // Show the image
Alex Bilbied261b1e2012-06-02 11:12:16 +01001081 if ($this->dynamic_output === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001082 {
1083 $this->image_display_gd($src_img);
1084 }
Andrey Andreev8e70b792012-01-12 20:19:24 +02001085 elseif ( ! $this->image_save_gd($src_img)) // ... or save it
Derek Allard2067d1a2008-11-13 22:59:24 +00001086 {
Andrey Andreev8e70b792012-01-12 20:19:24 +02001087 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +00001088 }
1089
Andrey Andreev8e70b792012-01-12 20:19:24 +02001090 // Kill the file handles
Derek Allard2067d1a2008-11-13 22:59:24 +00001091 imagedestroy($src_img);
1092
Andrey Andreev45965742014-08-27 20:40:11 +03001093 chmod($this->full_dst_path, $this->file_permissions);
Derek Allard2067d1a2008-11-13 22:59:24 +00001094
1095 return TRUE;
1096 }
1097
1098 // --------------------------------------------------------------------
1099
1100 /**
1101 * Image Watermark
1102 *
1103 * This is a wrapper function that chooses the type
1104 * of watermarking based on the specified preference.
1105 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001106 * @return bool
1107 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001108 public function watermark()
Derek Allard2067d1a2008-11-13 22:59:24 +00001109 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001110 return ($this->wm_type === 'overlay') ? $this->overlay_watermark() : $this->text_watermark();
Derek Allard2067d1a2008-11-13 22:59:24 +00001111 }
1112
1113 // --------------------------------------------------------------------
1114
1115 /**
1116 * Watermark - Graphic Version
1117 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001118 * @return bool
1119 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001120 public function overlay_watermark()
Derek Allard2067d1a2008-11-13 22:59:24 +00001121 {
1122 if ( ! function_exists('imagecolortransparent'))
1123 {
1124 $this->set_error('imglib_gd_required');
1125 return FALSE;
1126 }
1127
Andrey Andreev8e70b792012-01-12 20:19:24 +02001128 // Fetch source image properties
Derek Allard2067d1a2008-11-13 22:59:24 +00001129 $this->get_image_properties();
1130
Andrey Andreev8e70b792012-01-12 20:19:24 +02001131 // Fetch watermark image properties
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001132 $props = $this->get_image_properties($this->wm_overlay_path, TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +00001133 $wm_img_type = $props['image_type'];
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001134 $wm_width = $props['width'];
1135 $wm_height = $props['height'];
Derek Allard2067d1a2008-11-13 22:59:24 +00001136
Andrey Andreev8e70b792012-01-12 20:19:24 +02001137 // Create two image resources
Derek Jones4b9c6292011-07-01 17:40:48 -05001138 $wm_img = $this->image_create_gd($this->wm_overlay_path, $wm_img_type);
Derek Allard2067d1a2008-11-13 22:59:24 +00001139 $src_img = $this->image_create_gd($this->full_src_path);
1140
1141 // Reverse the offset if necessary
1142 // When the image is positioned at the bottom
1143 // we don't want the vertical offset to push it
Andrey Andreev8e70b792012-01-12 20:19:24 +02001144 // further down. We want the reverse, so we'll
1145 // invert the offset. Same with the horizontal
Derek Allard2067d1a2008-11-13 22:59:24 +00001146 // offset when the image is at the right
1147
Andrey Andreev8e70b792012-01-12 20:19:24 +02001148 $this->wm_vrt_alignment = strtoupper($this->wm_vrt_alignment[0]);
1149 $this->wm_hor_alignment = strtoupper($this->wm_hor_alignment[0]);
Derek Allard2067d1a2008-11-13 22:59:24 +00001150
Alex Bilbied261b1e2012-06-02 11:12:16 +01001151 if ($this->wm_vrt_alignment === 'B')
Derek Allard2067d1a2008-11-13 22:59:24 +00001152 $this->wm_vrt_offset = $this->wm_vrt_offset * -1;
1153
Alex Bilbied261b1e2012-06-02 11:12:16 +01001154 if ($this->wm_hor_alignment === 'R')
Derek Allard2067d1a2008-11-13 22:59:24 +00001155 $this->wm_hor_offset = $this->wm_hor_offset * -1;
1156
Andrey Andreev8e70b792012-01-12 20:19:24 +02001157 // Set the base x and y axis values
Derek Allard2067d1a2008-11-13 22:59:24 +00001158 $x_axis = $this->wm_hor_offset + $this->wm_padding;
1159 $y_axis = $this->wm_vrt_offset + $this->wm_padding;
1160
Andrey Andreev8e70b792012-01-12 20:19:24 +02001161 // Set the vertical position
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001162 if ($this->wm_vrt_alignment === 'M')
Derek Allard2067d1a2008-11-13 22:59:24 +00001163 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001164 $y_axis += ($this->orig_height / 2) - ($wm_height / 2);
1165 }
1166 elseif ($this->wm_vrt_alignment === 'B')
1167 {
1168 $y_axis += $this->orig_height - $wm_height;
Derek Allard2067d1a2008-11-13 22:59:24 +00001169 }
1170
Andrey Andreev8e70b792012-01-12 20:19:24 +02001171 // Set the horizontal position
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001172 if ($this->wm_hor_alignment === 'C')
Derek Allard2067d1a2008-11-13 22:59:24 +00001173 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001174 $x_axis += ($this->orig_width / 2) - ($wm_width / 2);
1175 }
1176 elseif ($this->wm_hor_alignment === 'R')
1177 {
1178 $x_axis += $this->orig_width - $wm_width;
Derek Allard2067d1a2008-11-13 22:59:24 +00001179 }
1180
Derek Jones4b9c6292011-07-01 17:40:48 -05001181 // Build the finalized image
Alex Bilbied261b1e2012-06-02 11:12:16 +01001182 if ($wm_img_type === 3 && function_exists('imagealphablending'))
Derek Allard2067d1a2008-11-13 22:59:24 +00001183 {
1184 @imagealphablending($src_img, TRUE);
Barry Mienydd671972010-10-04 16:33:58 +02001185 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001186
1187 // Set RGB values for text and shadow
1188 $rgba = imagecolorat($wm_img, $this->wm_x_transp, $this->wm_y_transp);
1189 $alpha = ($rgba & 0x7F000000) >> 24;
1190
1191 // make a best guess as to whether we're dealing with an image with alpha transparency or no/binary transparency
1192 if ($alpha > 0)
1193 {
1194 // copy the image directly, the image's alpha transparency being the sole determinant of blending
1195 imagecopy($src_img, $wm_img, $x_axis, $y_axis, 0, 0, $wm_width, $wm_height);
1196 }
1197 else
1198 {
1199 // set our RGB value from above to be transparent and merge the images with the specified opacity
1200 imagecolortransparent($wm_img, imagecolorat($wm_img, $this->wm_x_transp, $this->wm_y_transp));
1201 imagecopymerge($src_img, $wm_img, $x_axis, $y_axis, 0, 0, $wm_width, $wm_height, $this->wm_opacity);
1202 }
1203
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001204 // Output the image
Alex Bilbied261b1e2012-06-02 11:12:16 +01001205 if ($this->dynamic_output === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001206 {
1207 $this->image_display_gd($src_img);
1208 }
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001209 elseif ( ! $this->image_save_gd($src_img)) // ... or save it
Derek Allard2067d1a2008-11-13 22:59:24 +00001210 {
Andrey Andreeva92b9032011-12-24 19:05:58 +02001211 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +00001212 }
1213
1214 imagedestroy($src_img);
1215 imagedestroy($wm_img);
1216
1217 return TRUE;
1218 }
1219
1220 // --------------------------------------------------------------------
1221
1222 /**
1223 * Watermark - Text Version
1224 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001225 * @return bool
1226 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001227 public function text_watermark()
Derek Allard2067d1a2008-11-13 22:59:24 +00001228 {
1229 if ( ! ($src_img = $this->image_create_gd()))
1230 {
1231 return FALSE;
1232 }
1233
Alex Bilbied261b1e2012-06-02 11:12:16 +01001234 if ($this->wm_use_truetype === TRUE && ! file_exists($this->wm_font_path))
Derek Allard2067d1a2008-11-13 22:59:24 +00001235 {
1236 $this->set_error('imglib_missing_font');
1237 return FALSE;
1238 }
1239
Andrey Andreev8e70b792012-01-12 20:19:24 +02001240 // Fetch source image properties
Derek Allard2067d1a2008-11-13 22:59:24 +00001241 $this->get_image_properties();
1242
Derek Allard2067d1a2008-11-13 22:59:24 +00001243 // Reverse the vertical offset
1244 // When the image is positioned at the bottom
1245 // we don't want the vertical offset to push it
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001246 // further down. We want the reverse, so we'll
Andrey Andreev8e70b792012-01-12 20:19:24 +02001247 // invert the offset. Note: The horizontal
Derek Allard2067d1a2008-11-13 22:59:24 +00001248 // offset flips itself automatically
1249
Alex Bilbied261b1e2012-06-02 11:12:16 +01001250 if ($this->wm_vrt_alignment === 'B')
Andrey Andreeve52fc262014-02-11 13:27:01 +02001251 {
Derek Allard2067d1a2008-11-13 22:59:24 +00001252 $this->wm_vrt_offset = $this->wm_vrt_offset * -1;
Andrey Andreeve52fc262014-02-11 13:27:01 +02001253 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001254
Alex Bilbied261b1e2012-06-02 11:12:16 +01001255 if ($this->wm_hor_alignment === 'R')
Andrey Andreeve52fc262014-02-11 13:27:01 +02001256 {
Derek Allard2067d1a2008-11-13 22:59:24 +00001257 $this->wm_hor_offset = $this->wm_hor_offset * -1;
Andrey Andreeve52fc262014-02-11 13:27:01 +02001258 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001259
1260 // Set font width and height
1261 // These are calculated differently depending on
1262 // whether we are using the true type font or not
Alex Bilbied261b1e2012-06-02 11:12:16 +01001263 if ($this->wm_use_truetype === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001264 {
Andrey Andreeve52fc262014-02-11 13:27:01 +02001265 if (empty($this->wm_font_size))
Andrey Andreeva92b9032011-12-24 19:05:58 +02001266 {
1267 $this->wm_font_size = 17;
1268 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001269
Andrey Andreeve52fc262014-02-11 13:27:01 +02001270 if (function_exists('imagettfbbox'))
1271 {
1272 $temp = imagettfbbox($this->wm_font_size, 0, $this->wm_font_path, $this->wm_text);
1273 $temp = $temp[2] - $temp[0];
1274
1275 $fontwidth = $temp / strlen($this->wm_text);
1276 }
1277 else
1278 {
1279 $fontwidth = $this->wm_font_size - ($this->wm_font_size / 4);
1280 }
1281
Derek Allard2067d1a2008-11-13 22:59:24 +00001282 $fontheight = $this->wm_font_size;
1283 $this->wm_vrt_offset += $this->wm_font_size;
1284 }
1285 else
1286 {
Derek Jones4b9c6292011-07-01 17:40:48 -05001287 $fontwidth = imagefontwidth($this->wm_font_size);
Derek Allard2067d1a2008-11-13 22:59:24 +00001288 $fontheight = imagefontheight($this->wm_font_size);
1289 }
1290
1291 // Set base X and Y axis values
1292 $x_axis = $this->wm_hor_offset + $this->wm_padding;
1293 $y_axis = $this->wm_vrt_offset + $this->wm_padding;
1294
Alex Bilbied261b1e2012-06-02 11:12:16 +01001295 if ($this->wm_use_drop_shadow === FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001296 $this->wm_shadow_distance = 0;
1297
Andrey Andreev7a7ad782012-11-12 17:21:01 +02001298 $this->wm_vrt_alignment = strtoupper($this->wm_vrt_alignment[0]);
1299 $this->wm_hor_alignment = strtoupper($this->wm_hor_alignment[0]);
Derek Allard2067d1a2008-11-13 22:59:24 +00001300
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001301 // Set verticle alignment
1302 if ($this->wm_vrt_alignment === 'M')
Derek Allard2067d1a2008-11-13 22:59:24 +00001303 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001304 $y_axis += ($this->orig_height / 2) + ($fontheight / 2);
1305 }
1306 elseif ($this->wm_vrt_alignment === 'B')
1307 {
1308 $y_axis += $this->orig_height - $fontheight - $this->wm_shadow_distance - ($fontheight / 2);
Derek Allard2067d1a2008-11-13 22:59:24 +00001309 }
1310
1311 $x_shad = $x_axis + $this->wm_shadow_distance;
1312 $y_shad = $y_axis + $this->wm_shadow_distance;
1313
Andrey Andreev64dbdfb2011-12-30 14:14:07 +02001314 if ($this->wm_use_drop_shadow)
Derek Allard2067d1a2008-11-13 22:59:24 +00001315 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001316 // Set horizontal alignment
1317 if ($this->wm_hor_alignment === 'R')
1318 {
1319 $x_shad += $this->orig_width - ($fontwidth * strlen($this->wm_text));
1320 $x_axis += $this->orig_width - ($fontwidth * strlen($this->wm_text));
1321 }
1322 elseif ($this->wm_hor_alignment === 'C')
1323 {
1324 $x_shad += floor(($this->orig_width - ($fontwidth * strlen($this->wm_text))) / 2);
1325 $x_axis += floor(($this->orig_width - ($fontwidth * strlen($this->wm_text))) / 2);
1326 }
1327
Andrey Andreev8323ae62011-12-31 18:39:10 +02001328 /* Set RGB values for text and shadow
1329 *
1330 * First character is #, so we don't really need it.
1331 * Get the rest of the string and split it into 2-length
1332 * hex values:
1333 */
1334 $txt_color = str_split(substr($this->wm_font_color, 1, 6), 2);
Andrey Andreev64dbdfb2011-12-30 14:14:07 +02001335 $txt_color = imagecolorclosest($src_img, hexdec($txt_color[0]), hexdec($txt_color[1]), hexdec($txt_color[2]));
Andrey Andreev8323ae62011-12-31 18:39:10 +02001336 $drp_color = str_split(substr($this->wm_shadow_color, 1, 6), 2);
Ronald Beilsma8f80bc42012-01-12 16:41:49 +01001337 $drp_color = imagecolorclosest($src_img, hexdec($drp_color[0]), hexdec($drp_color[1]), hexdec($drp_color[2]));
Andrey Andreev64dbdfb2011-12-30 14:14:07 +02001338
Andrey Andreev8e70b792012-01-12 20:19:24 +02001339 // Add the text to the source image
Andrey Andreev64dbdfb2011-12-30 14:14:07 +02001340 if ($this->wm_use_truetype)
1341 {
1342 imagettftext($src_img, $this->wm_font_size, 0, $x_shad, $y_shad, $drp_color, $this->wm_font_path, $this->wm_text);
1343 imagettftext($src_img, $this->wm_font_size, 0, $x_axis, $y_axis, $txt_color, $this->wm_font_path, $this->wm_text);
1344 }
1345 else
1346 {
1347 imagestring($src_img, $this->wm_font_size, $x_shad, $y_shad, $this->wm_text, $drp_color);
1348 imagestring($src_img, $this->wm_font_size, $x_axis, $y_axis, $this->wm_text, $txt_color);
1349 }
Andrey Andreev99ae2262012-10-05 15:14:30 +03001350
1351 // We can preserve transparency for PNG images
1352 if ($this->image_type === 3)
1353 {
1354 imagealphablending($src_img, FALSE);
1355 imagesavealpha($src_img, TRUE);
1356 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001357 }
1358
Andrey Andreev8e70b792012-01-12 20:19:24 +02001359 // Output the final image
Alex Bilbied261b1e2012-06-02 11:12:16 +01001360 if ($this->dynamic_output === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001361 {
1362 $this->image_display_gd($src_img);
1363 }
1364 else
1365 {
1366 $this->image_save_gd($src_img);
1367 }
1368
1369 imagedestroy($src_img);
1370
1371 return TRUE;
1372 }
1373
1374 // --------------------------------------------------------------------
1375
1376 /**
1377 * Create Image - GD
1378 *
1379 * This simply creates an image resource handle
1380 * based on the type of image being processed
1381 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001382 * @param string
Timothy Warrenb82bc3a2012-04-27 09:12:58 -04001383 * @param string
Derek Allard2067d1a2008-11-13 22:59:24 +00001384 * @return resource
1385 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001386 public function image_create_gd($path = '', $image_type = '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001387 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001388 if ($path === '')
Andrey Andreeve52fc262014-02-11 13:27:01 +02001389 {
Derek Allard2067d1a2008-11-13 22:59:24 +00001390 $path = $this->full_src_path;
Andrey Andreeve52fc262014-02-11 13:27:01 +02001391 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001392
Alex Bilbied261b1e2012-06-02 11:12:16 +01001393 if ($image_type === '')
Andrey Andreeve52fc262014-02-11 13:27:01 +02001394 {
Derek Allard2067d1a2008-11-13 22:59:24 +00001395 $image_type = $this->image_type;
Andrey Andreeve52fc262014-02-11 13:27:01 +02001396 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001397
Derek Allard2067d1a2008-11-13 22:59:24 +00001398 switch ($image_type)
1399 {
Andrey Andreeve52fc262014-02-11 13:27:01 +02001400 case 1 :
1401 if ( ! function_exists('imagecreatefromgif'))
1402 {
1403 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_gif_not_supported'));
1404 return FALSE;
1405 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001406
Andrey Andreeve52fc262014-02-11 13:27:01 +02001407 return imagecreatefromgif($path);
Derek Allard2067d1a2008-11-13 22:59:24 +00001408 case 2 :
Andrey Andreeve52fc262014-02-11 13:27:01 +02001409 if ( ! function_exists('imagecreatefromjpeg'))
1410 {
1411 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_jpg_not_supported'));
1412 return FALSE;
1413 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001414
Andrey Andreeve52fc262014-02-11 13:27:01 +02001415 return imagecreatefromjpeg($path);
Derek Allard2067d1a2008-11-13 22:59:24 +00001416 case 3 :
Andrey Andreeve52fc262014-02-11 13:27:01 +02001417 if ( ! function_exists('imagecreatefrompng'))
1418 {
1419 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_png_not_supported'));
1420 return FALSE;
1421 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001422
Andrey Andreeve52fc262014-02-11 13:27:01 +02001423 return imagecreatefrompng($path);
1424 default:
1425 $this->set_error(array('imglib_unsupported_imagecreate'));
1426 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +00001427 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001428 }
1429
1430 // --------------------------------------------------------------------
1431
1432 /**
1433 * Write image file to disk - GD
1434 *
1435 * Takes an image resource as input and writes the file
1436 * to the specified destination
1437 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001438 * @param resource
1439 * @return bool
1440 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001441 public function image_save_gd($resource)
Derek Allard2067d1a2008-11-13 22:59:24 +00001442 {
1443 switch ($this->image_type)
1444 {
Andrey Andreev56454792012-05-17 14:32:19 +03001445 case 1:
1446 if ( ! function_exists('imagegif'))
1447 {
1448 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_gif_not_supported'));
1449 return FALSE;
1450 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001451
Andrey Andreev56454792012-05-17 14:32:19 +03001452 if ( ! @imagegif($resource, $this->full_dst_path))
1453 {
1454 $this->set_error('imglib_save_failed');
1455 return FALSE;
1456 }
1457 break;
1458 case 2:
1459 if ( ! function_exists('imagejpeg'))
1460 {
1461 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_jpg_not_supported'));
1462 return FALSE;
1463 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001464
Andrey Andreev56454792012-05-17 14:32:19 +03001465 if ( ! @imagejpeg($resource, $this->full_dst_path, $this->quality))
1466 {
1467 $this->set_error('imglib_save_failed');
1468 return FALSE;
1469 }
1470 break;
1471 case 3:
1472 if ( ! function_exists('imagepng'))
1473 {
1474 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_png_not_supported'));
1475 return FALSE;
1476 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001477
Andrey Andreev56454792012-05-17 14:32:19 +03001478 if ( ! @imagepng($resource, $this->full_dst_path))
1479 {
1480 $this->set_error('imglib_save_failed');
1481 return FALSE;
1482 }
1483 break;
1484 default:
1485 $this->set_error(array('imglib_unsupported_imagecreate'));
1486 return FALSE;
1487 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001488 }
1489
1490 return TRUE;
1491 }
1492
1493 // --------------------------------------------------------------------
1494
1495 /**
1496 * Dynamically outputs an image
1497 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001498 * @param resource
1499 * @return void
1500 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001501 public function image_display_gd($resource)
Derek Allard2067d1a2008-11-13 22:59:24 +00001502 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001503 header('Content-Disposition: filename='.$this->source_image.';');
1504 header('Content-Type: '.$this->mime_type);
Derek Allard2067d1a2008-11-13 22:59:24 +00001505 header('Content-Transfer-Encoding: binary');
1506 header('Last-Modified: '.gmdate('D, d M Y H:i:s', time()).' GMT');
1507
1508 switch ($this->image_type)
1509 {
Andrey Andreev56454792012-05-17 14:32:19 +03001510 case 1 : imagegif($resource);
Derek Allard2067d1a2008-11-13 22:59:24 +00001511 break;
Ted Wood9cc707b2013-01-08 19:41:45 -08001512 case 2 : imagejpeg($resource, NULL, $this->quality);
Derek Allard2067d1a2008-11-13 22:59:24 +00001513 break;
Andrey Andreev56454792012-05-17 14:32:19 +03001514 case 3 : imagepng($resource);
Derek Allard2067d1a2008-11-13 22:59:24 +00001515 break;
Andrey Andreev56454792012-05-17 14:32:19 +03001516 default: echo 'Unable to display the image';
Derek Allard2067d1a2008-11-13 22:59:24 +00001517 break;
1518 }
1519 }
1520
1521 // --------------------------------------------------------------------
1522
1523 /**
1524 * Re-proportion Image Width/Height
1525 *
1526 * When creating thumbs, the desired width/height
1527 * can end up warping the image due to an incorrect
1528 * ratio between the full-sized image and the thumb.
1529 *
1530 * This function lets us re-proportion the width/height
1531 * if users choose to maintain the aspect ratio when resizing.
1532 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001533 * @return void
1534 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001535 public function image_reproportion()
Derek Allard2067d1a2008-11-13 22:59:24 +00001536 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001537 if (($this->width === 0 && $this->height === 0) OR $this->orig_width === 0 OR $this->orig_height === 0
Andrey Andreev7a7ad782012-11-12 17:21:01 +02001538 OR ( ! ctype_digit((string) $this->width) && ! ctype_digit((string) $this->height))
1539 OR ! ctype_digit((string) $this->orig_width) OR ! ctype_digit((string) $this->orig_height))
Derek Allard2067d1a2008-11-13 22:59:24 +00001540 {
Andrey Andreev8e70b792012-01-12 20:19:24 +02001541 return;
Derek Allard2067d1a2008-11-13 22:59:24 +00001542 }
1543
Andrey Andreev7a7ad782012-11-12 17:21:01 +02001544 // Sanitize
Andrey Andreev8e70b792012-01-12 20:19:24 +02001545 $this->width = (int) $this->width;
1546 $this->height = (int) $this->height;
1547
1548 if ($this->master_dim !== 'width' && $this->master_dim !== 'height')
Derek Allard2067d1a2008-11-13 22:59:24 +00001549 {
Andrey Andreev8e70b792012-01-12 20:19:24 +02001550 if ($this->width > 0 && $this->height > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001551 {
Andrey Andreev8e70b792012-01-12 20:19:24 +02001552 $this->master_dim = ((($this->orig_height/$this->orig_width) - ($this->height/$this->width)) < 0)
1553 ? 'width' : 'height';
Derek Allard2067d1a2008-11-13 22:59:24 +00001554 }
1555 else
1556 {
Andrey Andreev8e70b792012-01-12 20:19:24 +02001557 $this->master_dim = ($this->height === 0) ? 'width' : 'height';
Derek Allard2067d1a2008-11-13 22:59:24 +00001558 }
1559 }
Andrey Andreev8e70b792012-01-12 20:19:24 +02001560 elseif (($this->master_dim === 'width' && $this->width === 0)
1561 OR ($this->master_dim === 'height' && $this->height === 0))
1562 {
1563 return;
1564 }
1565
1566 if ($this->master_dim === 'width')
1567 {
1568 $this->height = (int) ceil($this->width*$this->orig_height/$this->orig_width);
1569 }
1570 else
1571 {
1572 $this->width = (int) ceil($this->orig_width*$this->height/$this->orig_height);
1573 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001574 }
1575
1576 // --------------------------------------------------------------------
1577
1578 /**
1579 * Get image properties
1580 *
1581 * A helper function that gets info about the file
1582 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001583 * @param string
Timothy Warrenb82bc3a2012-04-27 09:12:58 -04001584 * @param bool
Derek Allard2067d1a2008-11-13 22:59:24 +00001585 * @return mixed
1586 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001587 public function get_image_properties($path = '', $return = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001588 {
1589 // For now we require GD but we should
1590 // find a way to determine this using IM or NetPBM
1591
Alex Bilbied261b1e2012-06-02 11:12:16 +01001592 if ($path === '')
Andrey Andreev8e70b792012-01-12 20:19:24 +02001593 {
Derek Allard2067d1a2008-11-13 22:59:24 +00001594 $path = $this->full_src_path;
Andrey Andreev8e70b792012-01-12 20:19:24 +02001595 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001596
1597 if ( ! file_exists($path))
1598 {
1599 $this->set_error('imglib_invalid_path');
1600 return FALSE;
1601 }
1602
Phil Sturgeon901998a2011-08-26 10:03:33 +01001603 $vals = getimagesize($path);
Derek Allard2067d1a2008-11-13 22:59:24 +00001604 $types = array(1 => 'gif', 2 => 'jpeg', 3 => 'png');
Andrey Andreeva92b9032011-12-24 19:05:58 +02001605 $mime = (isset($types[$vals[2]])) ? 'image/'.$types[$vals[2]] : 'image/jpg';
Derek Allard2067d1a2008-11-13 22:59:24 +00001606
Alex Bilbied261b1e2012-06-02 11:12:16 +01001607 if ($return === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001608 {
Andrey Andreeva92b9032011-12-24 19:05:58 +02001609 return array(
1610 'width' => $vals[0],
1611 'height' => $vals[1],
1612 'image_type' => $vals[2],
1613 'size_str' => $vals[3],
1614 'mime_type' => $mime
1615 );
Derek Allard2067d1a2008-11-13 22:59:24 +00001616 }
1617
Andrey Andreeva92b9032011-12-24 19:05:58 +02001618 $this->orig_width = $vals[0];
1619 $this->orig_height = $vals[1];
1620 $this->image_type = $vals[2];
1621 $this->size_str = $vals[3];
Derek Allard2067d1a2008-11-13 22:59:24 +00001622 $this->mime_type = $mime;
1623
1624 return TRUE;
1625 }
1626
1627 // --------------------------------------------------------------------
1628
1629 /**
1630 * Size calculator
1631 *
1632 * This function takes a known width x height and
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001633 * recalculates it to a new size. Only one
Derek Allard2067d1a2008-11-13 22:59:24 +00001634 * new variable needs to be known
1635 *
1636 * $props = array(
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001637 * 'width' => $width,
1638 * 'height' => $height,
1639 * 'new_width' => 40,
1640 * 'new_height' => ''
1641 * );
Derek Allard2067d1a2008-11-13 22:59:24 +00001642 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001643 * @param array
1644 * @return array
1645 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001646 public function size_calculator($vals)
Derek Allard2067d1a2008-11-13 22:59:24 +00001647 {
1648 if ( ! is_array($vals))
1649 {
1650 return;
1651 }
1652
1653 $allowed = array('new_width', 'new_height', 'width', 'height');
1654
1655 foreach ($allowed as $item)
1656 {
Andrey Andreev56454792012-05-17 14:32:19 +03001657 if (empty($vals[$item]))
1658 {
Derek Allard2067d1a2008-11-13 22:59:24 +00001659 $vals[$item] = 0;
Andrey Andreev56454792012-05-17 14:32:19 +03001660 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001661 }
1662
Alex Bilbied261b1e2012-06-02 11:12:16 +01001663 if ($vals['width'] === 0 OR $vals['height'] === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001664 {
1665 return $vals;
1666 }
1667
Alex Bilbied261b1e2012-06-02 11:12:16 +01001668 if ($vals['new_width'] === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001669 {
1670 $vals['new_width'] = ceil($vals['width']*$vals['new_height']/$vals['height']);
1671 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001672 elseif ($vals['new_height'] === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001673 {
1674 $vals['new_height'] = ceil($vals['new_width']*$vals['height']/$vals['width']);
1675 }
1676
1677 return $vals;
1678 }
1679
1680 // --------------------------------------------------------------------
1681
1682 /**
1683 * Explode source_image
1684 *
1685 * This is a helper function that extracts the extension
Derek Jones4b9c6292011-07-01 17:40:48 -05001686 * from the source_image. This function lets us deal with
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001687 * source_images with multiple periods, like: my.cool.jpg
Derek Allard2067d1a2008-11-13 22:59:24 +00001688 * It returns an associative array with two elements:
Derek Jones4b9c6292011-07-01 17:40:48 -05001689 * $array['ext'] = '.jpg';
Derek Allard2067d1a2008-11-13 22:59:24 +00001690 * $array['name'] = 'my.cool';
1691 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001692 * @param array
1693 * @return array
1694 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001695 public function explode_name($source_image)
Derek Allard2067d1a2008-11-13 22:59:24 +00001696 {
Derek Jones08cae632009-02-10 20:03:29 +00001697 $ext = strrchr($source_image, '.');
1698 $name = ($ext === FALSE) ? $source_image : substr($source_image, 0, -strlen($ext));
Barry Mienydd671972010-10-04 16:33:58 +02001699
Derek Jones08cae632009-02-10 20:03:29 +00001700 return array('ext' => $ext, 'name' => $name);
Derek Allard2067d1a2008-11-13 22:59:24 +00001701 }
1702
1703 // --------------------------------------------------------------------
1704
1705 /**
1706 * Is GD Installed?
1707 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001708 * @return bool
1709 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001710 public function gd_loaded()
Derek Allard2067d1a2008-11-13 22:59:24 +00001711 {
1712 if ( ! extension_loaded('gd'))
1713 {
Andrey Andreeva92b9032011-12-24 19:05:58 +02001714 /* As it is stated in the PHP manual, dl() is not always available
1715 * and even if so - it could generate an E_WARNING message on failure
1716 */
Andrey Andreev8e70b792012-01-12 20:19:24 +02001717 return (function_exists('dl') && @dl('gd.so'));
Derek Allard2067d1a2008-11-13 22:59:24 +00001718 }
1719
1720 return TRUE;
1721 }
1722
1723 // --------------------------------------------------------------------
1724
1725 /**
1726 * Get GD version
1727 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001728 * @return mixed
1729 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001730 public function gd_version()
Derek Allard2067d1a2008-11-13 22:59:24 +00001731 {
1732 if (function_exists('gd_info'))
1733 {
1734 $gd_version = @gd_info();
Andrey Andreev8e70b792012-01-12 20:19:24 +02001735 return preg_replace('/\D/', '', $gd_version['GD Version']);
Derek Allard2067d1a2008-11-13 22:59:24 +00001736 }
1737
1738 return FALSE;
1739 }
1740
1741 // --------------------------------------------------------------------
1742
1743 /**
1744 * Set error message
1745 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001746 * @param string
1747 * @return void
1748 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001749 public function set_error($msg)
Derek Allard2067d1a2008-11-13 22:59:24 +00001750 {
1751 $CI =& get_instance();
1752 $CI->lang->load('imglib');
1753
1754 if (is_array($msg))
1755 {
1756 foreach ($msg as $val)
1757 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001758 $msg = ($CI->lang->line($val) === FALSE) ? $val : $CI->lang->line($val);
Derek Allard2067d1a2008-11-13 22:59:24 +00001759 $this->error_msg[] = $msg;
1760 log_message('error', $msg);
1761 }
1762 }
1763 else
1764 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001765 $msg = ($CI->lang->line($msg) === FALSE) ? $msg : $CI->lang->line($msg);
Derek Allard2067d1a2008-11-13 22:59:24 +00001766 $this->error_msg[] = $msg;
1767 log_message('error', $msg);
1768 }
1769 }
1770
1771 // --------------------------------------------------------------------
1772
1773 /**
1774 * Show error messages
1775 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001776 * @param string
Timothy Warrenb82bc3a2012-04-27 09:12:58 -04001777 * @param string
Derek Allard2067d1a2008-11-13 22:59:24 +00001778 * @return string
1779 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001780 public function display_errors($open = '<p>', $close = '</p>')
Derek Allard2067d1a2008-11-13 22:59:24 +00001781 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001782 return (count($this->error_msg) > 0) ? $open.implode($close.$open, $this->error_msg).$close : '';
Derek Allard2067d1a2008-11-13 22:59:24 +00001783 }
1784
1785}
Derek Allard2067d1a2008-11-13 22:59:24 +00001786
1787/* End of file Image_lib.php */
Sam Doidge7ee20342013-03-13 04:43:55 +00001788/* Location: ./system/libraries/Image_lib.php */