blob: 1577887c2cb23288d658126b6fb4d886b67d20e6 [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
Дмитрийb23b8fc2014-10-20 00:36:55 +04001204 // We can preserve transparency for PNG images
1205 if ($this->image_type === 3)
1206 {
1207 imagealphablending($src_img, FALSE);
1208 imagesavealpha($src_img, TRUE);
1209 }
1210
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001211 // Output the image
Alex Bilbied261b1e2012-06-02 11:12:16 +01001212 if ($this->dynamic_output === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001213 {
1214 $this->image_display_gd($src_img);
1215 }
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001216 elseif ( ! $this->image_save_gd($src_img)) // ... or save it
Derek Allard2067d1a2008-11-13 22:59:24 +00001217 {
Andrey Andreeva92b9032011-12-24 19:05:58 +02001218 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +00001219 }
1220
1221 imagedestroy($src_img);
1222 imagedestroy($wm_img);
1223
1224 return TRUE;
1225 }
1226
1227 // --------------------------------------------------------------------
1228
1229 /**
1230 * Watermark - Text Version
1231 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001232 * @return bool
1233 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001234 public function text_watermark()
Derek Allard2067d1a2008-11-13 22:59:24 +00001235 {
1236 if ( ! ($src_img = $this->image_create_gd()))
1237 {
1238 return FALSE;
1239 }
1240
Alex Bilbied261b1e2012-06-02 11:12:16 +01001241 if ($this->wm_use_truetype === TRUE && ! file_exists($this->wm_font_path))
Derek Allard2067d1a2008-11-13 22:59:24 +00001242 {
1243 $this->set_error('imglib_missing_font');
1244 return FALSE;
1245 }
1246
Andrey Andreev8e70b792012-01-12 20:19:24 +02001247 // Fetch source image properties
Derek Allard2067d1a2008-11-13 22:59:24 +00001248 $this->get_image_properties();
1249
Derek Allard2067d1a2008-11-13 22:59:24 +00001250 // Reverse the vertical offset
1251 // When the image is positioned at the bottom
1252 // we don't want the vertical offset to push it
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001253 // further down. We want the reverse, so we'll
Andrey Andreev8e70b792012-01-12 20:19:24 +02001254 // invert the offset. Note: The horizontal
Derek Allard2067d1a2008-11-13 22:59:24 +00001255 // offset flips itself automatically
1256
Alex Bilbied261b1e2012-06-02 11:12:16 +01001257 if ($this->wm_vrt_alignment === 'B')
Andrey Andreeve52fc262014-02-11 13:27:01 +02001258 {
Derek Allard2067d1a2008-11-13 22:59:24 +00001259 $this->wm_vrt_offset = $this->wm_vrt_offset * -1;
Andrey Andreeve52fc262014-02-11 13:27:01 +02001260 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001261
Alex Bilbied261b1e2012-06-02 11:12:16 +01001262 if ($this->wm_hor_alignment === 'R')
Andrey Andreeve52fc262014-02-11 13:27:01 +02001263 {
Derek Allard2067d1a2008-11-13 22:59:24 +00001264 $this->wm_hor_offset = $this->wm_hor_offset * -1;
Andrey Andreeve52fc262014-02-11 13:27:01 +02001265 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001266
1267 // Set font width and height
1268 // These are calculated differently depending on
1269 // whether we are using the true type font or not
Alex Bilbied261b1e2012-06-02 11:12:16 +01001270 if ($this->wm_use_truetype === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001271 {
Andrey Andreeve52fc262014-02-11 13:27:01 +02001272 if (empty($this->wm_font_size))
Andrey Andreeva92b9032011-12-24 19:05:58 +02001273 {
1274 $this->wm_font_size = 17;
1275 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001276
Andrey Andreeve52fc262014-02-11 13:27:01 +02001277 if (function_exists('imagettfbbox'))
1278 {
1279 $temp = imagettfbbox($this->wm_font_size, 0, $this->wm_font_path, $this->wm_text);
1280 $temp = $temp[2] - $temp[0];
1281
1282 $fontwidth = $temp / strlen($this->wm_text);
1283 }
1284 else
1285 {
1286 $fontwidth = $this->wm_font_size - ($this->wm_font_size / 4);
1287 }
1288
Derek Allard2067d1a2008-11-13 22:59:24 +00001289 $fontheight = $this->wm_font_size;
1290 $this->wm_vrt_offset += $this->wm_font_size;
1291 }
1292 else
1293 {
Derek Jones4b9c6292011-07-01 17:40:48 -05001294 $fontwidth = imagefontwidth($this->wm_font_size);
Derek Allard2067d1a2008-11-13 22:59:24 +00001295 $fontheight = imagefontheight($this->wm_font_size);
1296 }
1297
1298 // Set base X and Y axis values
1299 $x_axis = $this->wm_hor_offset + $this->wm_padding;
1300 $y_axis = $this->wm_vrt_offset + $this->wm_padding;
1301
Alex Bilbied261b1e2012-06-02 11:12:16 +01001302 if ($this->wm_use_drop_shadow === FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001303 $this->wm_shadow_distance = 0;
1304
Andrey Andreev7a7ad782012-11-12 17:21:01 +02001305 $this->wm_vrt_alignment = strtoupper($this->wm_vrt_alignment[0]);
1306 $this->wm_hor_alignment = strtoupper($this->wm_hor_alignment[0]);
Derek Allard2067d1a2008-11-13 22:59:24 +00001307
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001308 // Set verticle alignment
1309 if ($this->wm_vrt_alignment === 'M')
Derek Allard2067d1a2008-11-13 22:59:24 +00001310 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001311 $y_axis += ($this->orig_height / 2) + ($fontheight / 2);
1312 }
1313 elseif ($this->wm_vrt_alignment === 'B')
1314 {
1315 $y_axis += $this->orig_height - $fontheight - $this->wm_shadow_distance - ($fontheight / 2);
Derek Allard2067d1a2008-11-13 22:59:24 +00001316 }
1317
1318 $x_shad = $x_axis + $this->wm_shadow_distance;
1319 $y_shad = $y_axis + $this->wm_shadow_distance;
1320
Andrey Andreev64dbdfb2011-12-30 14:14:07 +02001321 if ($this->wm_use_drop_shadow)
Derek Allard2067d1a2008-11-13 22:59:24 +00001322 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001323 // Set horizontal alignment
1324 if ($this->wm_hor_alignment === 'R')
1325 {
1326 $x_shad += $this->orig_width - ($fontwidth * strlen($this->wm_text));
1327 $x_axis += $this->orig_width - ($fontwidth * strlen($this->wm_text));
1328 }
1329 elseif ($this->wm_hor_alignment === 'C')
1330 {
1331 $x_shad += floor(($this->orig_width - ($fontwidth * strlen($this->wm_text))) / 2);
1332 $x_axis += floor(($this->orig_width - ($fontwidth * strlen($this->wm_text))) / 2);
1333 }
1334
Andrey Andreev8323ae62011-12-31 18:39:10 +02001335 /* Set RGB values for text and shadow
1336 *
1337 * First character is #, so we don't really need it.
1338 * Get the rest of the string and split it into 2-length
1339 * hex values:
1340 */
1341 $txt_color = str_split(substr($this->wm_font_color, 1, 6), 2);
Andrey Andreev64dbdfb2011-12-30 14:14:07 +02001342 $txt_color = imagecolorclosest($src_img, hexdec($txt_color[0]), hexdec($txt_color[1]), hexdec($txt_color[2]));
Andrey Andreev8323ae62011-12-31 18:39:10 +02001343 $drp_color = str_split(substr($this->wm_shadow_color, 1, 6), 2);
Ronald Beilsma8f80bc42012-01-12 16:41:49 +01001344 $drp_color = imagecolorclosest($src_img, hexdec($drp_color[0]), hexdec($drp_color[1]), hexdec($drp_color[2]));
Andrey Andreev64dbdfb2011-12-30 14:14:07 +02001345
Andrey Andreev8e70b792012-01-12 20:19:24 +02001346 // Add the text to the source image
Andrey Andreev64dbdfb2011-12-30 14:14:07 +02001347 if ($this->wm_use_truetype)
1348 {
1349 imagettftext($src_img, $this->wm_font_size, 0, $x_shad, $y_shad, $drp_color, $this->wm_font_path, $this->wm_text);
1350 imagettftext($src_img, $this->wm_font_size, 0, $x_axis, $y_axis, $txt_color, $this->wm_font_path, $this->wm_text);
1351 }
1352 else
1353 {
1354 imagestring($src_img, $this->wm_font_size, $x_shad, $y_shad, $this->wm_text, $drp_color);
1355 imagestring($src_img, $this->wm_font_size, $x_axis, $y_axis, $this->wm_text, $txt_color);
1356 }
Andrey Andreev99ae2262012-10-05 15:14:30 +03001357
1358 // We can preserve transparency for PNG images
1359 if ($this->image_type === 3)
1360 {
1361 imagealphablending($src_img, FALSE);
1362 imagesavealpha($src_img, TRUE);
1363 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001364 }
1365
Andrey Andreev8e70b792012-01-12 20:19:24 +02001366 // Output the final image
Alex Bilbied261b1e2012-06-02 11:12:16 +01001367 if ($this->dynamic_output === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001368 {
1369 $this->image_display_gd($src_img);
1370 }
1371 else
1372 {
1373 $this->image_save_gd($src_img);
1374 }
1375
1376 imagedestroy($src_img);
1377
1378 return TRUE;
1379 }
1380
1381 // --------------------------------------------------------------------
1382
1383 /**
1384 * Create Image - GD
1385 *
1386 * This simply creates an image resource handle
1387 * based on the type of image being processed
1388 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001389 * @param string
Timothy Warrenb82bc3a2012-04-27 09:12:58 -04001390 * @param string
Derek Allard2067d1a2008-11-13 22:59:24 +00001391 * @return resource
1392 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001393 public function image_create_gd($path = '', $image_type = '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001394 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001395 if ($path === '')
Andrey Andreeve52fc262014-02-11 13:27:01 +02001396 {
Derek Allard2067d1a2008-11-13 22:59:24 +00001397 $path = $this->full_src_path;
Andrey Andreeve52fc262014-02-11 13:27:01 +02001398 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001399
Alex Bilbied261b1e2012-06-02 11:12:16 +01001400 if ($image_type === '')
Andrey Andreeve52fc262014-02-11 13:27:01 +02001401 {
Derek Allard2067d1a2008-11-13 22:59:24 +00001402 $image_type = $this->image_type;
Andrey Andreeve52fc262014-02-11 13:27:01 +02001403 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001404
Derek Allard2067d1a2008-11-13 22:59:24 +00001405 switch ($image_type)
1406 {
Andrey Andreeve52fc262014-02-11 13:27:01 +02001407 case 1 :
1408 if ( ! function_exists('imagecreatefromgif'))
1409 {
1410 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_gif_not_supported'));
1411 return FALSE;
1412 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001413
Andrey Andreeve52fc262014-02-11 13:27:01 +02001414 return imagecreatefromgif($path);
Derek Allard2067d1a2008-11-13 22:59:24 +00001415 case 2 :
Andrey Andreeve52fc262014-02-11 13:27:01 +02001416 if ( ! function_exists('imagecreatefromjpeg'))
1417 {
1418 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_jpg_not_supported'));
1419 return FALSE;
1420 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001421
Andrey Andreeve52fc262014-02-11 13:27:01 +02001422 return imagecreatefromjpeg($path);
Derek Allard2067d1a2008-11-13 22:59:24 +00001423 case 3 :
Andrey Andreeve52fc262014-02-11 13:27:01 +02001424 if ( ! function_exists('imagecreatefrompng'))
1425 {
1426 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_png_not_supported'));
1427 return FALSE;
1428 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001429
Andrey Andreeve52fc262014-02-11 13:27:01 +02001430 return imagecreatefrompng($path);
1431 default:
1432 $this->set_error(array('imglib_unsupported_imagecreate'));
1433 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +00001434 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001435 }
1436
1437 // --------------------------------------------------------------------
1438
1439 /**
1440 * Write image file to disk - GD
1441 *
1442 * Takes an image resource as input and writes the file
1443 * to the specified destination
1444 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001445 * @param resource
1446 * @return bool
1447 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001448 public function image_save_gd($resource)
Derek Allard2067d1a2008-11-13 22:59:24 +00001449 {
1450 switch ($this->image_type)
1451 {
Andrey Andreev56454792012-05-17 14:32:19 +03001452 case 1:
1453 if ( ! function_exists('imagegif'))
1454 {
1455 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_gif_not_supported'));
1456 return FALSE;
1457 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001458
Andrey Andreev56454792012-05-17 14:32:19 +03001459 if ( ! @imagegif($resource, $this->full_dst_path))
1460 {
1461 $this->set_error('imglib_save_failed');
1462 return FALSE;
1463 }
1464 break;
1465 case 2:
1466 if ( ! function_exists('imagejpeg'))
1467 {
1468 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_jpg_not_supported'));
1469 return FALSE;
1470 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001471
Andrey Andreev56454792012-05-17 14:32:19 +03001472 if ( ! @imagejpeg($resource, $this->full_dst_path, $this->quality))
1473 {
1474 $this->set_error('imglib_save_failed');
1475 return FALSE;
1476 }
1477 break;
1478 case 3:
1479 if ( ! function_exists('imagepng'))
1480 {
1481 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_png_not_supported'));
1482 return FALSE;
1483 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001484
Andrey Andreev56454792012-05-17 14:32:19 +03001485 if ( ! @imagepng($resource, $this->full_dst_path))
1486 {
1487 $this->set_error('imglib_save_failed');
1488 return FALSE;
1489 }
1490 break;
1491 default:
1492 $this->set_error(array('imglib_unsupported_imagecreate'));
1493 return FALSE;
1494 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001495 }
1496
1497 return TRUE;
1498 }
1499
1500 // --------------------------------------------------------------------
1501
1502 /**
1503 * Dynamically outputs an image
1504 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001505 * @param resource
1506 * @return void
1507 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001508 public function image_display_gd($resource)
Derek Allard2067d1a2008-11-13 22:59:24 +00001509 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001510 header('Content-Disposition: filename='.$this->source_image.';');
1511 header('Content-Type: '.$this->mime_type);
Derek Allard2067d1a2008-11-13 22:59:24 +00001512 header('Content-Transfer-Encoding: binary');
1513 header('Last-Modified: '.gmdate('D, d M Y H:i:s', time()).' GMT');
1514
1515 switch ($this->image_type)
1516 {
Andrey Andreev56454792012-05-17 14:32:19 +03001517 case 1 : imagegif($resource);
Derek Allard2067d1a2008-11-13 22:59:24 +00001518 break;
Ted Wood9cc707b2013-01-08 19:41:45 -08001519 case 2 : imagejpeg($resource, NULL, $this->quality);
Derek Allard2067d1a2008-11-13 22:59:24 +00001520 break;
Andrey Andreev56454792012-05-17 14:32:19 +03001521 case 3 : imagepng($resource);
Derek Allard2067d1a2008-11-13 22:59:24 +00001522 break;
Andrey Andreev56454792012-05-17 14:32:19 +03001523 default: echo 'Unable to display the image';
Derek Allard2067d1a2008-11-13 22:59:24 +00001524 break;
1525 }
1526 }
1527
1528 // --------------------------------------------------------------------
1529
1530 /**
1531 * Re-proportion Image Width/Height
1532 *
1533 * When creating thumbs, the desired width/height
1534 * can end up warping the image due to an incorrect
1535 * ratio between the full-sized image and the thumb.
1536 *
1537 * This function lets us re-proportion the width/height
1538 * if users choose to maintain the aspect ratio when resizing.
1539 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001540 * @return void
1541 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001542 public function image_reproportion()
Derek Allard2067d1a2008-11-13 22:59:24 +00001543 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001544 if (($this->width === 0 && $this->height === 0) OR $this->orig_width === 0 OR $this->orig_height === 0
Andrey Andreev7a7ad782012-11-12 17:21:01 +02001545 OR ( ! ctype_digit((string) $this->width) && ! ctype_digit((string) $this->height))
1546 OR ! ctype_digit((string) $this->orig_width) OR ! ctype_digit((string) $this->orig_height))
Derek Allard2067d1a2008-11-13 22:59:24 +00001547 {
Andrey Andreev8e70b792012-01-12 20:19:24 +02001548 return;
Derek Allard2067d1a2008-11-13 22:59:24 +00001549 }
1550
Andrey Andreev7a7ad782012-11-12 17:21:01 +02001551 // Sanitize
Andrey Andreev8e70b792012-01-12 20:19:24 +02001552 $this->width = (int) $this->width;
1553 $this->height = (int) $this->height;
1554
1555 if ($this->master_dim !== 'width' && $this->master_dim !== 'height')
Derek Allard2067d1a2008-11-13 22:59:24 +00001556 {
Andrey Andreev8e70b792012-01-12 20:19:24 +02001557 if ($this->width > 0 && $this->height > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001558 {
Andrey Andreev8e70b792012-01-12 20:19:24 +02001559 $this->master_dim = ((($this->orig_height/$this->orig_width) - ($this->height/$this->width)) < 0)
1560 ? 'width' : 'height';
Derek Allard2067d1a2008-11-13 22:59:24 +00001561 }
1562 else
1563 {
Andrey Andreev8e70b792012-01-12 20:19:24 +02001564 $this->master_dim = ($this->height === 0) ? 'width' : 'height';
Derek Allard2067d1a2008-11-13 22:59:24 +00001565 }
1566 }
Andrey Andreev8e70b792012-01-12 20:19:24 +02001567 elseif (($this->master_dim === 'width' && $this->width === 0)
1568 OR ($this->master_dim === 'height' && $this->height === 0))
1569 {
1570 return;
1571 }
1572
1573 if ($this->master_dim === 'width')
1574 {
1575 $this->height = (int) ceil($this->width*$this->orig_height/$this->orig_width);
1576 }
1577 else
1578 {
1579 $this->width = (int) ceil($this->orig_width*$this->height/$this->orig_height);
1580 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001581 }
1582
1583 // --------------------------------------------------------------------
1584
1585 /**
1586 * Get image properties
1587 *
1588 * A helper function that gets info about the file
1589 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001590 * @param string
Timothy Warrenb82bc3a2012-04-27 09:12:58 -04001591 * @param bool
Derek Allard2067d1a2008-11-13 22:59:24 +00001592 * @return mixed
1593 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001594 public function get_image_properties($path = '', $return = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001595 {
1596 // For now we require GD but we should
1597 // find a way to determine this using IM or NetPBM
1598
Alex Bilbied261b1e2012-06-02 11:12:16 +01001599 if ($path === '')
Andrey Andreev8e70b792012-01-12 20:19:24 +02001600 {
Derek Allard2067d1a2008-11-13 22:59:24 +00001601 $path = $this->full_src_path;
Andrey Andreev8e70b792012-01-12 20:19:24 +02001602 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001603
1604 if ( ! file_exists($path))
1605 {
1606 $this->set_error('imglib_invalid_path');
1607 return FALSE;
1608 }
1609
Phil Sturgeon901998a2011-08-26 10:03:33 +01001610 $vals = getimagesize($path);
Derek Allard2067d1a2008-11-13 22:59:24 +00001611 $types = array(1 => 'gif', 2 => 'jpeg', 3 => 'png');
Andrey Andreeva92b9032011-12-24 19:05:58 +02001612 $mime = (isset($types[$vals[2]])) ? 'image/'.$types[$vals[2]] : 'image/jpg';
Derek Allard2067d1a2008-11-13 22:59:24 +00001613
Alex Bilbied261b1e2012-06-02 11:12:16 +01001614 if ($return === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001615 {
Andrey Andreeva92b9032011-12-24 19:05:58 +02001616 return array(
1617 'width' => $vals[0],
1618 'height' => $vals[1],
1619 'image_type' => $vals[2],
1620 'size_str' => $vals[3],
1621 'mime_type' => $mime
1622 );
Derek Allard2067d1a2008-11-13 22:59:24 +00001623 }
1624
Andrey Andreeva92b9032011-12-24 19:05:58 +02001625 $this->orig_width = $vals[0];
1626 $this->orig_height = $vals[1];
1627 $this->image_type = $vals[2];
1628 $this->size_str = $vals[3];
Derek Allard2067d1a2008-11-13 22:59:24 +00001629 $this->mime_type = $mime;
1630
1631 return TRUE;
1632 }
1633
1634 // --------------------------------------------------------------------
1635
1636 /**
1637 * Size calculator
1638 *
1639 * This function takes a known width x height and
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001640 * recalculates it to a new size. Only one
Derek Allard2067d1a2008-11-13 22:59:24 +00001641 * new variable needs to be known
1642 *
1643 * $props = array(
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001644 * 'width' => $width,
1645 * 'height' => $height,
1646 * 'new_width' => 40,
1647 * 'new_height' => ''
1648 * );
Derek Allard2067d1a2008-11-13 22:59:24 +00001649 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001650 * @param array
1651 * @return array
1652 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001653 public function size_calculator($vals)
Derek Allard2067d1a2008-11-13 22:59:24 +00001654 {
1655 if ( ! is_array($vals))
1656 {
1657 return;
1658 }
1659
1660 $allowed = array('new_width', 'new_height', 'width', 'height');
1661
1662 foreach ($allowed as $item)
1663 {
Andrey Andreev56454792012-05-17 14:32:19 +03001664 if (empty($vals[$item]))
1665 {
Derek Allard2067d1a2008-11-13 22:59:24 +00001666 $vals[$item] = 0;
Andrey Andreev56454792012-05-17 14:32:19 +03001667 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001668 }
1669
Alex Bilbied261b1e2012-06-02 11:12:16 +01001670 if ($vals['width'] === 0 OR $vals['height'] === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001671 {
1672 return $vals;
1673 }
1674
Alex Bilbied261b1e2012-06-02 11:12:16 +01001675 if ($vals['new_width'] === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001676 {
1677 $vals['new_width'] = ceil($vals['width']*$vals['new_height']/$vals['height']);
1678 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001679 elseif ($vals['new_height'] === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001680 {
1681 $vals['new_height'] = ceil($vals['new_width']*$vals['height']/$vals['width']);
1682 }
1683
1684 return $vals;
1685 }
1686
1687 // --------------------------------------------------------------------
1688
1689 /**
1690 * Explode source_image
1691 *
1692 * This is a helper function that extracts the extension
Derek Jones4b9c6292011-07-01 17:40:48 -05001693 * from the source_image. This function lets us deal with
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001694 * source_images with multiple periods, like: my.cool.jpg
Derek Allard2067d1a2008-11-13 22:59:24 +00001695 * It returns an associative array with two elements:
Derek Jones4b9c6292011-07-01 17:40:48 -05001696 * $array['ext'] = '.jpg';
Derek Allard2067d1a2008-11-13 22:59:24 +00001697 * $array['name'] = 'my.cool';
1698 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001699 * @param array
1700 * @return array
1701 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001702 public function explode_name($source_image)
Derek Allard2067d1a2008-11-13 22:59:24 +00001703 {
Derek Jones08cae632009-02-10 20:03:29 +00001704 $ext = strrchr($source_image, '.');
1705 $name = ($ext === FALSE) ? $source_image : substr($source_image, 0, -strlen($ext));
Barry Mienydd671972010-10-04 16:33:58 +02001706
Derek Jones08cae632009-02-10 20:03:29 +00001707 return array('ext' => $ext, 'name' => $name);
Derek Allard2067d1a2008-11-13 22:59:24 +00001708 }
1709
1710 // --------------------------------------------------------------------
1711
1712 /**
1713 * Is GD Installed?
1714 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001715 * @return bool
1716 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001717 public function gd_loaded()
Derek Allard2067d1a2008-11-13 22:59:24 +00001718 {
1719 if ( ! extension_loaded('gd'))
1720 {
Andrey Andreeva92b9032011-12-24 19:05:58 +02001721 /* As it is stated in the PHP manual, dl() is not always available
1722 * and even if so - it could generate an E_WARNING message on failure
1723 */
Andrey Andreev8e70b792012-01-12 20:19:24 +02001724 return (function_exists('dl') && @dl('gd.so'));
Derek Allard2067d1a2008-11-13 22:59:24 +00001725 }
1726
1727 return TRUE;
1728 }
1729
1730 // --------------------------------------------------------------------
1731
1732 /**
1733 * Get GD version
1734 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001735 * @return mixed
1736 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001737 public function gd_version()
Derek Allard2067d1a2008-11-13 22:59:24 +00001738 {
1739 if (function_exists('gd_info'))
1740 {
1741 $gd_version = @gd_info();
Andrey Andreev8e70b792012-01-12 20:19:24 +02001742 return preg_replace('/\D/', '', $gd_version['GD Version']);
Derek Allard2067d1a2008-11-13 22:59:24 +00001743 }
1744
1745 return FALSE;
1746 }
1747
1748 // --------------------------------------------------------------------
1749
1750 /**
1751 * Set error message
1752 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001753 * @param string
1754 * @return void
1755 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001756 public function set_error($msg)
Derek Allard2067d1a2008-11-13 22:59:24 +00001757 {
1758 $CI =& get_instance();
1759 $CI->lang->load('imglib');
1760
1761 if (is_array($msg))
1762 {
1763 foreach ($msg as $val)
1764 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001765 $msg = ($CI->lang->line($val) === FALSE) ? $val : $CI->lang->line($val);
Derek Allard2067d1a2008-11-13 22:59:24 +00001766 $this->error_msg[] = $msg;
1767 log_message('error', $msg);
1768 }
1769 }
1770 else
1771 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001772 $msg = ($CI->lang->line($msg) === FALSE) ? $msg : $CI->lang->line($msg);
Derek Allard2067d1a2008-11-13 22:59:24 +00001773 $this->error_msg[] = $msg;
1774 log_message('error', $msg);
1775 }
1776 }
1777
1778 // --------------------------------------------------------------------
1779
1780 /**
1781 * Show error messages
1782 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001783 * @param string
Timothy Warrenb82bc3a2012-04-27 09:12:58 -04001784 * @param string
Derek Allard2067d1a2008-11-13 22:59:24 +00001785 * @return string
1786 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001787 public function display_errors($open = '<p>', $close = '</p>')
Derek Allard2067d1a2008-11-13 22:59:24 +00001788 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001789 return (count($this->error_msg) > 0) ? $open.implode($close.$open, $this->error_msg).$close : '';
Derek Allard2067d1a2008-11-13 22:59:24 +00001790 }
1791
1792}
Derek Allard2067d1a2008-11-13 22:59:24 +00001793
1794/* End of file Image_lib.php */
Дмитрийb23b8fc2014-10-20 00:36:55 +04001795/* Location: ./system/libraries/Image_lib.php */