blob: 9ad0dd5b624956b9510e097ce4e96fa8ab70e102 [file] [log] [blame]
Andrey Andreevc5536aa2012-11-01 17:33:58 +02001<?php
Derek Allard2067d1a2008-11-13 22:59:24 +00002/**
3 * CodeIgniter
4 *
Andrey Andreevfe9309d2015-01-09 17:48:58 +02005 * An open source application development framework for PHP
Derek Allard2067d1a2008-11-13 22:59:24 +00006 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +02007 * This content is released under the MIT License (MIT)
Eric Barnesb1673362011-12-05 22:05:38 -05008 *
Andrey Andreevfe9309d2015-01-09 17:48:58 +02009 * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
Eric Barnesb1673362011-12-05 22:05:38 -050010 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020011 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
Derek Jonesf4a4bd82011-10-20 12:18:42 -050017 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020018 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 * THE SOFTWARE.
28 *
29 * @package CodeIgniter
30 * @author EllisLab Dev Team
darwinel871754a2014-02-11 17:34:57 +010031 * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
Andrey Andreevfe9309d2015-01-09 17:48:58 +020032 * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020033 * @license http://opensource.org/licenses/MIT MIT License
34 * @link http://codeigniter.com
35 * @since Version 1.0.0
Derek Allard2067d1a2008-11-13 22:59:24 +000036 * @filesource
37 */
Andrey Andreevc5536aa2012-11-01 17:33:58 +020038defined('BASEPATH') OR exit('No direct script access allowed');
Derek Allard2067d1a2008-11-13 22:59:24 +000039
Derek Allard2067d1a2008-11-13 22:59:24 +000040/**
41 * Image Manipulation class
42 *
43 * @package CodeIgniter
44 * @subpackage Libraries
45 * @category Image_lib
Derek Jonesf4a4bd82011-10-20 12:18:42 -050046 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +000047 * @link http://codeigniter.com/user_guide/libraries/image_lib.html
48 */
49class CI_Image_lib {
50
Timothy Warrenb8e62852012-04-26 18:40:54 -040051 /**
52 * PHP extension/library to use for image manipulation
Andrey Andreev56454792012-05-17 14:32:19 +030053 * Can be: imagemagick, netpbm, gd, gd2
Timothy Warrenb8e62852012-04-26 18:40:54 -040054 *
55 * @var string
56 */
57 public $image_library = 'gd2';
Andrey Andreev56454792012-05-17 14:32:19 +030058
Timothy Warrenb8e62852012-04-26 18:40:54 -040059 /**
60 * Path to the graphic library (if applicable)
61 *
62 * @var string
63 */
Andrey Andreev3a459572011-12-21 11:23:11 +020064 public $library_path = '';
Andrey Andreev56454792012-05-17 14:32:19 +030065
Timothy Warrenb8e62852012-04-26 18:40:54 -040066 /**
67 * Whether to send to browser or write to disk
68 *
69 * @var bool
70 */
71 public $dynamic_output = FALSE;
Andrey Andreev56454792012-05-17 14:32:19 +030072
Timothy Warrenb8e62852012-04-26 18:40:54 -040073 /**
74 * Path to original image
75 *
76 * @var string
77 */
Andrey Andreev3a459572011-12-21 11:23:11 +020078 public $source_image = '';
Andrey Andreev56454792012-05-17 14:32:19 +030079
Timothy Warrenb8e62852012-04-26 18:40:54 -040080 /**
81 * Path to the modified image
82 *
83 * @var string
84 */
Andrey Andreev56454792012-05-17 14:32:19 +030085 public $new_image = '';
86
Timothy Warrenb8e62852012-04-26 18:40:54 -040087 /**
88 * Image width
89 *
90 * @var int
91 */
Andrey Andreev56454792012-05-17 14:32:19 +030092 public $width = '';
93
Timothy Warrenb8e62852012-04-26 18:40:54 -040094 /**
95 * Image height
96 *
97 * @var int
98 */
Andrey Andreev56454792012-05-17 14:32:19 +030099 public $height = '';
100
Timothy Warrenb8e62852012-04-26 18:40:54 -0400101 /**
102 * Quality percentage of new image
103 *
104 * @var int
105 */
Andrey Andreev56454792012-05-17 14:32:19 +0300106 public $quality = 90;
107
Timothy Warrenb8e62852012-04-26 18:40:54 -0400108 /**
109 * Whether to create a thumbnail
110 *
111 * @var bool
112 */
Andrey Andreev3a459572011-12-21 11:23:11 +0200113 public $create_thumb = FALSE;
Andrey Andreev56454792012-05-17 14:32:19 +0300114
Timothy Warrenb8e62852012-04-26 18:40:54 -0400115 /**
116 * String to add to thumbnail version of image
117 *
118 * @var string
119 */
Andrey Andreev3a459572011-12-21 11:23:11 +0200120 public $thumb_marker = '_thumb';
Andrey Andreev56454792012-05-17 14:32:19 +0300121
Timothy Warrenb8e62852012-04-26 18:40:54 -0400122 /**
123 * Whether to maintain aspect ratio when resizing or use hard values
124 *
125 * @var bool
126 */
127 public $maintain_ratio = TRUE;
Andrey Andreev56454792012-05-17 14:32:19 +0300128
Timothy Warrenb8e62852012-04-26 18:40:54 -0400129 /**
130 * auto, height, or width. Determines what to use as the master dimension
131 *
132 * @var string
133 */
Andrey Andreev56454792012-05-17 14:32:19 +0300134 public $master_dim = 'auto';
135
Timothy Warrenb8e62852012-04-26 18:40:54 -0400136 /**
137 * Angle at to rotate image
138 *
139 * @var string
140 */
Andrey Andreev3a459572011-12-21 11:23:11 +0200141 public $rotation_angle = '';
Andrey Andreev56454792012-05-17 14:32:19 +0300142
Timothy Warrenb8e62852012-04-26 18:40:54 -0400143 /**
144 * X Coordinate for manipulation of the current image
145 *
146 * @var int
147 */
Andrey Andreev56454792012-05-17 14:32:19 +0300148 public $x_axis = '';
149
Timothy Warrenb8e62852012-04-26 18:40:54 -0400150 /**
151 * Y Coordinate for manipulation of the current image
152 *
153 * @var int
154 */
Andrey Andreev56454792012-05-17 14:32:19 +0300155 public $y_axis = '';
Derek Allard2067d1a2008-11-13 22:59:24 +0000156
Timothy Warrenb8e62852012-04-26 18:40:54 -0400157 // --------------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000158 // Watermark Vars
Timothy Warrenb8e62852012-04-26 18:40:54 -0400159 // --------------------------------------------------------------------------
Andrey Andreev56454792012-05-17 14:32:19 +0300160
Timothy Warrenb8e62852012-04-26 18:40:54 -0400161 /**
162 * Watermark text if graphic is not used
163 *
164 * @var string
165 */
166 public $wm_text = '';
Andrey Andreev56454792012-05-17 14:32:19 +0300167
Timothy Warrenb8e62852012-04-26 18:40:54 -0400168 /**
169 * Type of watermarking. Options: text/overlay
170 *
171 * @var string
172 */
173 public $wm_type = 'text';
Andrey Andreev56454792012-05-17 14:32:19 +0300174
Timothy Warrenb8e62852012-04-26 18:40:54 -0400175 /**
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400176 * Default transparency for watermark
Andrey Andreev56454792012-05-17 14:32:19 +0300177 *
Timothy Warrenb8e62852012-04-26 18:40:54 -0400178 * @var int
179 */
Andrey Andreev3a459572011-12-21 11:23:11 +0200180 public $wm_x_transp = 4;
Andrey Andreev56454792012-05-17 14:32:19 +0300181
Timothy Warrenb8e62852012-04-26 18:40:54 -0400182 /**
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400183 * Default transparency for watermark
184 *
Timothy Warrenb8e62852012-04-26 18:40:54 -0400185 * @var int
186 */
Andrey Andreev3a459572011-12-21 11:23:11 +0200187 public $wm_y_transp = 4;
Andrey Andreev56454792012-05-17 14:32:19 +0300188
Timothy Warrenb8e62852012-04-26 18:40:54 -0400189 /**
190 * Watermark image path
Andrey Andreev56454792012-05-17 14:32:19 +0300191 *
Timothy Warrenb8e62852012-04-26 18:40:54 -0400192 * @var string
193 */
Andrey Andreev56454792012-05-17 14:32:19 +0300194 public $wm_overlay_path = '';
195
Timothy Warrenb8e62852012-04-26 18:40:54 -0400196 /**
197 * TT font
198 *
199 * @var string
200 */
201 public $wm_font_path = '';
Andrey Andreev56454792012-05-17 14:32:19 +0300202
Timothy Warrenb8e62852012-04-26 18:40:54 -0400203 /**
204 * Font size (different versions of GD will either use points or pixels)
205 *
206 * @var int
207 */
208 public $wm_font_size = 17;
Andrey Andreev56454792012-05-17 14:32:19 +0300209
Timothy Warrenb8e62852012-04-26 18:40:54 -0400210 /**
211 * Vertical alignment: T M B
212 *
213 * @var string
214 */
215 public $wm_vrt_alignment = 'B';
Andrey Andreev56454792012-05-17 14:32:19 +0300216
Timothy Warrenb8e62852012-04-26 18:40:54 -0400217 /**
218 * Horizontal alignment: L R C
219 *
220 * @var string
221 */
222 public $wm_hor_alignment = 'C';
Andrey Andreev56454792012-05-17 14:32:19 +0300223
Timothy Warrenb8e62852012-04-26 18:40:54 -0400224 /**
225 * Padding around text
226 *
227 * @var int
228 */
229 public $wm_padding = 0;
Andrey Andreev56454792012-05-17 14:32:19 +0300230
Timothy Warrenb8e62852012-04-26 18:40:54 -0400231 /**
232 * Lets you push text to the right
233 *
234 * @var int
235 */
236 public $wm_hor_offset = 0;
Andrey Andreev56454792012-05-17 14:32:19 +0300237
Timothy Warrenb8e62852012-04-26 18:40:54 -0400238 /**
239 * Lets you push text down
240 *
241 * @var int
242 */
243 public $wm_vrt_offset = 0;
Andrey Andreev56454792012-05-17 14:32:19 +0300244
Timothy Warrenb8e62852012-04-26 18:40:54 -0400245 /**
246 * Text color
247 *
248 * @var string
249 */
Andrey Andreev56454792012-05-17 14:32:19 +0300250 protected $wm_font_color = '#ffffff';
251
Timothy Warrenb8e62852012-04-26 18:40:54 -0400252 /**
253 * Dropshadow color
254 *
255 * @var string
256 */
Andrey Andreev56454792012-05-17 14:32:19 +0300257 protected $wm_shadow_color = '';
258
Timothy Warrenb8e62852012-04-26 18:40:54 -0400259 /**
260 * Dropshadow distance
261 *
262 * @var int
263 */
264 public $wm_shadow_distance = 2;
Andrey Andreev56454792012-05-17 14:32:19 +0300265
Timothy Warrenb8e62852012-04-26 18:40:54 -0400266 /**
267 * Image opacity: 1 - 100 Only works with image
268 *
269 * @var int
270 */
Andrey Andreev56454792012-05-17 14:32:19 +0300271 public $wm_opacity = 50;
Derek Allard2067d1a2008-11-13 22:59:24 +0000272
Timothy Warrenb8e62852012-04-26 18:40:54 -0400273 // --------------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000274 // Private Vars
Timothy Warrenb8e62852012-04-26 18:40:54 -0400275 // --------------------------------------------------------------------------
Andrey Andreev56454792012-05-17 14:32:19 +0300276
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400277 /**
278 * Source image folder
279 *
280 * @var string
281 */
Andrey Andreev3a459572011-12-21 11:23:11 +0200282 public $source_folder = '';
Andrey Andreev56454792012-05-17 14:32:19 +0300283
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400284 /**
285 * Destination image folder
286 *
287 * @var string
288 */
Andrey Andreev3a459572011-12-21 11:23:11 +0200289 public $dest_folder = '';
Andrey Andreev56454792012-05-17 14:32:19 +0300290
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400291 /**
292 * Image mime-type
293 *
294 * @var string
295 */
Andrey Andreev56454792012-05-17 14:32:19 +0300296 public $mime_type = '';
297
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400298 /**
Andrey Andreev56454792012-05-17 14:32:19 +0300299 * Original image width
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400300 *
301 * @var int
302 */
Andrey Andreev56454792012-05-17 14:32:19 +0300303 public $orig_width = '';
304
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400305 /**
306 * Original image height
307 *
308 * @var int
309 */
Andrey Andreev3a459572011-12-21 11:23:11 +0200310 public $orig_height = '';
Andrey Andreev56454792012-05-17 14:32:19 +0300311
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400312 /**
313 * Image format
Andrey Andreev56454792012-05-17 14:32:19 +0300314 *
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400315 * @var string
316 */
Andrey Andreev56454792012-05-17 14:32:19 +0300317 public $image_type = '';
318
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400319 /**
320 * Size of current image
321 *
322 * @var string
323 */
Andrey Andreev56454792012-05-17 14:32:19 +0300324 public $size_str = '';
325
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400326 /**
327 * Full path to source image
328 *
329 * @var string
330 */
Andrey Andreev3a459572011-12-21 11:23:11 +0200331 public $full_src_path = '';
Andrey Andreev56454792012-05-17 14:32:19 +0300332
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400333 /**
334 * Full path to destination image
335 *
336 * @var string
337 */
Andrey Andreev3a459572011-12-21 11:23:11 +0200338 public $full_dst_path = '';
Andrey Andreev56454792012-05-17 14:32:19 +0300339
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400340 /**
Andrey Andreev45965742014-08-27 20:40:11 +0300341 * File permissions
342 *
343 * @var int
344 */
345 public $file_permissions = 0644;
346
347 /**
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400348 * Name of function to create image
349 *
350 * @var string
351 */
Andrey Andreev56454792012-05-17 14:32:19 +0300352 public $create_fnc = 'imagecreatetruecolor';
353
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400354 /**
355 * Name of function to copy image
356 *
357 * @var string
358 */
Andrey Andreev56454792012-05-17 14:32:19 +0300359 public $copy_fnc = 'imagecopyresampled';
360
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400361 /**
362 * Error messages
363 *
364 * @var array
365 */
Andrey Andreev56454792012-05-17 14:32:19 +0300366 public $error_msg = array();
367
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400368 /**
369 * Whether to have a drop shadow on watermark
370 *
371 * @var bool
372 */
Andrey Andreev64dbdfb2011-12-30 14:14:07 +0200373 protected $wm_use_drop_shadow = FALSE;
Andrey Andreev56454792012-05-17 14:32:19 +0300374
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400375 /**
376 * Whether to use truetype fonts
377 *
378 * @var bool
379 */
Andrey Andreev3a459572011-12-21 11:23:11 +0200380 public $wm_use_truetype = FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000381
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400382 /**
383 * Initialize Image Library
384 *
385 * @param array $props
Andrey Andreev56454792012-05-17 14:32:19 +0300386 * @return void
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400387 */
Greg Akera9263282010-11-10 15:26:43 -0600388 public function __construct($props = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000389 {
390 if (count($props) > 0)
391 {
392 $this->initialize($props);
393 }
394
Andrey Andreev90726b82015-01-20 12:39:22 +0200395 log_message('info', 'Image Lib Class Initialized');
Derek Allard2067d1a2008-11-13 22:59:24 +0000396 }
397
398 // --------------------------------------------------------------------
399
400 /**
401 * Initialize image properties
402 *
403 * Resets values in case this class is used in a loop
404 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000405 * @return void
406 */
Andrey Andreev4eea9892011-12-19 12:05:41 +0200407 public function clear()
Derek Allard2067d1a2008-11-13 22:59:24 +0000408 {
Sam Doidge5cb5c0a2013-03-13 01:28:06 +0000409 $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 +0000410
411 foreach ($props as $val)
412 {
413 $this->$val = '';
414 }
415
Michael Denniscb07a322011-08-20 23:40:59 -0700416 $this->image_library = 'gd2';
417 $this->dynamic_output = FALSE;
Andrey Andreev56454792012-05-17 14:32:19 +0300418 $this->quality = 90;
Michael Denniscb07a322011-08-20 23:40:59 -0700419 $this->create_thumb = FALSE;
420 $this->thumb_marker = '_thumb';
421 $this->maintain_ratio = TRUE;
422 $this->master_dim = 'auto';
423 $this->wm_type = 'text';
424 $this->wm_x_transp = 4;
425 $this->wm_y_transp = 4;
426 $this->wm_font_size = 17;
427 $this->wm_vrt_alignment = 'B';
428 $this->wm_hor_alignment = 'C';
429 $this->wm_padding = 0;
430 $this->wm_hor_offset = 0;
431 $this->wm_vrt_offset = 0;
432 $this->wm_font_color = '#ffffff';
433 $this->wm_shadow_distance = 2;
434 $this->wm_opacity = 50;
435 $this->create_fnc = 'imagecreatetruecolor';
436 $this->copy_fnc = 'imagecopyresampled';
437 $this->error_msg = array();
438 $this->wm_use_drop_shadow = FALSE;
439 $this->wm_use_truetype = FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000440 }
441
442 // --------------------------------------------------------------------
443
444 /**
445 * initialize image preferences
446 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000447 * @param array
448 * @return bool
449 */
Andrey Andreev4eea9892011-12-19 12:05:41 +0200450 public function initialize($props = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000451 {
Andrey Andreev8e70b792012-01-12 20:19:24 +0200452 // Convert array elements into class variables
Derek Allard2067d1a2008-11-13 22:59:24 +0000453 if (count($props) > 0)
454 {
455 foreach ($props as $key => $val)
456 {
Andrey Andreev64dbdfb2011-12-30 14:14:07 +0200457 if (property_exists($this, $key))
458 {
459 if (in_array($key, array('wm_font_color', 'wm_shadow_color')))
460 {
Andrey Andreev8323ae62011-12-31 18:39:10 +0200461 if (preg_match('/^#?([0-9a-f]{3}|[0-9a-f]{6})$/i', $val, $matches))
Andrey Andreev64dbdfb2011-12-30 14:14:07 +0200462 {
Andrey Andreevcf2ba9e2012-01-01 21:57:13 +0200463 /* $matches[1] contains our hex color value, but it might be
Andrey Andreev8323ae62011-12-31 18:39:10 +0200464 * both in the full 6-length format or the shortened 3-length
465 * value.
Andrey Andreevbb96c8b2011-12-31 18:48:39 +0200466 * We'll later need the full version, so we keep it if it's
Andrey Andreev8323ae62011-12-31 18:39:10 +0200467 * already there and if not - we'll convert to it. We can
468 * access string characters by their index as in an array,
469 * so we'll do that and use concatenation to form the final
470 * value:
471 */
Andrey Andreev665af0c2011-12-30 14:39:29 +0200472 $val = (strlen($matches[1]) === 6)
473 ? '#'.$matches[1]
474 : '#'.$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 +0200475 }
476 else
477 {
478 continue;
479 }
480 }
481
482 $this->$key = $val;
483 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000484 }
485 }
486
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200487 // Is there a source image? If not, there's no reason to continue
Alex Bilbied261b1e2012-06-02 11:12:16 +0100488 if ($this->source_image === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000489 {
490 $this->set_error('imglib_source_image_required');
Eric Barnesb1673362011-12-05 22:05:38 -0500491 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000492 }
493
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200494 /* Is getimagesize() available?
Derek Allard2067d1a2008-11-13 22:59:24 +0000495 *
496 * We use it to determine the image properties (width/height).
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200497 * Note: We need to figure out how to determine image
Derek Allard2067d1a2008-11-13 22:59:24 +0000498 * properties using ImageMagick and NetPBM
Derek Allard2067d1a2008-11-13 22:59:24 +0000499 */
500 if ( ! function_exists('getimagesize'))
501 {
502 $this->set_error('imglib_gd_required_for_props');
503 return FALSE;
504 }
505
506 $this->image_library = strtolower($this->image_library);
507
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200508 /* Set the full server path
Derek Allard2067d1a2008-11-13 22:59:24 +0000509 *
510 * The source image may or may not contain a path.
511 * Either way, we'll try use realpath to generate the
512 * full server path in order to more reliably read it.
Derek Allard2067d1a2008-11-13 22:59:24 +0000513 */
Andrey Andreevea41c8a2014-02-26 18:31:02 +0200514 if (($full_source_path = realpath($this->source_image)) !== FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000515 {
Andrey Andreevea41c8a2014-02-26 18:31:02 +0200516 $full_source_path = str_replace('\\', '/', $full_source_path);
Derek Allard2067d1a2008-11-13 22:59:24 +0000517 }
518 else
519 {
520 $full_source_path = $this->source_image;
521 }
522
523 $x = explode('/', $full_source_path);
524 $this->source_image = end($x);
525 $this->source_folder = str_replace($this->source_image, '', $full_source_path);
526
527 // Set the Image Properties
528 if ( ! $this->get_image_properties($this->source_folder.$this->source_image))
529 {
Eric Barnesb1673362011-12-05 22:05:38 -0500530 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000531 }
532
533 /*
534 * Assign the "new" image name/path
535 *
536 * If the user has set a "new_image" name it means
537 * we are making a copy of the source image. If not
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200538 * it means we are altering the original. We'll
Derek Allard2067d1a2008-11-13 22:59:24 +0000539 * set the destination filename and path accordingly.
Derek Allard2067d1a2008-11-13 22:59:24 +0000540 */
Alex Bilbied261b1e2012-06-02 11:12:16 +0100541 if ($this->new_image === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000542 {
543 $this->dest_image = $this->source_image;
544 $this->dest_folder = $this->source_folder;
545 }
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200546 elseif (strpos($this->new_image, '/') === FALSE)
547 {
548 $this->dest_folder = $this->source_folder;
549 $this->dest_image = $this->new_image;
550 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000551 else
552 {
Andrey Andreev1b815532012-04-03 16:06:03 +0300553 if (strpos($this->new_image, '/') === FALSE && strpos($this->new_image, '\\') === FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000554 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200555 $full_dest_path = str_replace('\\', '/', realpath($this->new_image));
Derek Allard2067d1a2008-11-13 22:59:24 +0000556 }
557 else
558 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200559 $full_dest_path = $this->new_image;
560 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000561
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200562 // Is there a file name?
563 if ( ! preg_match('#\.(jpg|jpeg|gif|png)$#i', $full_dest_path))
564 {
565 $this->dest_folder = $full_dest_path.'/';
566 $this->dest_image = $this->source_image;
567 }
568 else
569 {
570 $x = explode('/', $full_dest_path);
571 $this->dest_image = end($x);
572 $this->dest_folder = str_replace($this->dest_image, '', $full_dest_path);
Derek Allard2067d1a2008-11-13 22:59:24 +0000573 }
574 }
575
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200576 /* Compile the finalized filenames/paths
Derek Allard2067d1a2008-11-13 22:59:24 +0000577 *
578 * We'll create two master strings containing the
579 * full server path to the source image and the
580 * full server path to the destination image.
581 * We'll also split the destination image name
582 * so we can insert the thumbnail marker if needed.
Derek Allard2067d1a2008-11-13 22:59:24 +0000583 */
Alex Bilbied261b1e2012-06-02 11:12:16 +0100584 if ($this->create_thumb === FALSE OR $this->thumb_marker === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000585 {
586 $this->thumb_marker = '';
587 }
588
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200589 $xp = $this->explode_name($this->dest_image);
Derek Allard2067d1a2008-11-13 22:59:24 +0000590
591 $filename = $xp['name'];
592 $file_ext = $xp['ext'];
593
594 $this->full_src_path = $this->source_folder.$this->source_image;
595 $this->full_dst_path = $this->dest_folder.$filename.$this->thumb_marker.$file_ext;
596
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200597 /* Should we maintain image proportions?
Derek Allard2067d1a2008-11-13 22:59:24 +0000598 *
599 * When creating thumbs or copies, the target width/height
600 * might not be in correct proportion with the source
Andrey Andreev8e70b792012-01-12 20:19:24 +0200601 * image's width/height. We'll recalculate it here.
Derek Allard2067d1a2008-11-13 22:59:24 +0000602 */
Alex Bilbied261b1e2012-06-02 11:12:16 +0100603 if ($this->maintain_ratio === TRUE && ($this->width !== 0 OR $this->height !== 0))
Derek Allard2067d1a2008-11-13 22:59:24 +0000604 {
605 $this->image_reproportion();
606 }
607
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200608 /* Was a width and height specified?
Derek Allard2067d1a2008-11-13 22:59:24 +0000609 *
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200610 * If the destination width/height was not submitted we
611 * will use the values from the actual file
Derek Allard2067d1a2008-11-13 22:59:24 +0000612 */
Alex Bilbied261b1e2012-06-02 11:12:16 +0100613 if ($this->width === '')
Andrey Andreev8e70b792012-01-12 20:19:24 +0200614 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000615 $this->width = $this->orig_width;
Andrey Andreev8e70b792012-01-12 20:19:24 +0200616 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000617
Alex Bilbied261b1e2012-06-02 11:12:16 +0100618 if ($this->height === '')
Andrey Andreev8e70b792012-01-12 20:19:24 +0200619 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000620 $this->height = $this->orig_height;
Andrey Andreev8e70b792012-01-12 20:19:24 +0200621 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000622
623 // Set the quality
Andrey Andreev8e70b792012-01-12 20:19:24 +0200624 $this->quality = trim(str_replace('%', '', $this->quality));
Derek Allard2067d1a2008-11-13 22:59:24 +0000625
Andrey Andreev7a7ad782012-11-12 17:21:01 +0200626 if ($this->quality === '' OR $this->quality === 0 OR ! ctype_digit($this->quality))
Andrey Andreev8e70b792012-01-12 20:19:24 +0200627 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000628 $this->quality = 90;
Andrey Andreev8e70b792012-01-12 20:19:24 +0200629 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000630
631 // Set the x/y coordinates
Andrey Andreev5036c9c2012-06-04 15:34:56 +0300632 is_numeric($this->x_axis) OR $this->x_axis = 0;
633 is_numeric($this->y_axis) OR $this->y_axis = 0;
Derek Allard2067d1a2008-11-13 22:59:24 +0000634
635 // Watermark-related Stuff...
Alex Bilbied261b1e2012-06-02 11:12:16 +0100636 if ($this->wm_overlay_path !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000637 {
Andrey Andreev8e70b792012-01-12 20:19:24 +0200638 $this->wm_overlay_path = str_replace('\\', '/', realpath($this->wm_overlay_path));
Derek Allard2067d1a2008-11-13 22:59:24 +0000639 }
640
Alex Bilbied261b1e2012-06-02 11:12:16 +0100641 if ($this->wm_shadow_color !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000642 {
643 $this->wm_use_drop_shadow = TRUE;
644 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100645 elseif ($this->wm_use_drop_shadow === TRUE && $this->wm_shadow_color === '')
Andrey Andreev64dbdfb2011-12-30 14:14:07 +0200646 {
647 $this->wm_use_drop_shadow = FALSE;
648 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000649
Alex Bilbied261b1e2012-06-02 11:12:16 +0100650 if ($this->wm_font_path !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000651 {
652 $this->wm_use_truetype = TRUE;
653 }
654
655 return TRUE;
656 }
657
658 // --------------------------------------------------------------------
659
660 /**
661 * Image Resize
662 *
663 * This is a wrapper function that chooses the proper
664 * resize function based on the protocol specified
665 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000666 * @return bool
667 */
Andrey Andreev4eea9892011-12-19 12:05:41 +0200668 public function resize()
Derek Allard2067d1a2008-11-13 22:59:24 +0000669 {
Andrey Andreev1a9f52c2012-01-07 01:06:34 +0200670 $protocol = ($this->image_library === 'gd2') ? 'image_process_gd' : 'image_process_'.$this->image_library;
Derek Allard2067d1a2008-11-13 22:59:24 +0000671 return $this->$protocol('resize');
672 }
673
674 // --------------------------------------------------------------------
675
676 /**
677 * Image Crop
678 *
679 * This is a wrapper function that chooses the proper
680 * cropping function based on the protocol specified
681 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000682 * @return bool
683 */
Andrey Andreev4eea9892011-12-19 12:05:41 +0200684 public function crop()
Derek Allard2067d1a2008-11-13 22:59:24 +0000685 {
Andrey Andreev5a67e3d2012-01-07 01:21:09 +0200686 $protocol = ($this->image_library === 'gd2') ? 'image_process_gd' : 'image_process_'.$this->image_library;
Derek Allard2067d1a2008-11-13 22:59:24 +0000687 return $this->$protocol('crop');
688 }
689
690 // --------------------------------------------------------------------
691
692 /**
693 * Image Rotate
694 *
695 * This is a wrapper function that chooses the proper
696 * rotation function based on the protocol specified
697 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000698 * @return bool
699 */
Andrey Andreev4eea9892011-12-19 12:05:41 +0200700 public function rotate()
Derek Allard2067d1a2008-11-13 22:59:24 +0000701 {
702 // Allowed rotation values
703 $degs = array(90, 180, 270, 'vrt', 'hor');
704
Alex Bilbied261b1e2012-06-02 11:12:16 +0100705 if ($this->rotation_angle === '' OR ! in_array($this->rotation_angle, $degs))
Derek Allard2067d1a2008-11-13 22:59:24 +0000706 {
707 $this->set_error('imglib_rotation_angle_required');
Eric Barnesb1673362011-12-05 22:05:38 -0500708 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000709 }
710
711 // Reassign the width and height
Alex Bilbied261b1e2012-06-02 11:12:16 +0100712 if ($this->rotation_angle === 90 OR $this->rotation_angle === 270)
Derek Allard2067d1a2008-11-13 22:59:24 +0000713 {
714 $this->width = $this->orig_height;
715 $this->height = $this->orig_width;
716 }
717 else
718 {
719 $this->width = $this->orig_width;
720 $this->height = $this->orig_height;
721 }
722
Derek Allard2067d1a2008-11-13 22:59:24 +0000723 // Choose resizing function
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200724 if ($this->image_library === 'imagemagick' OR $this->image_library === 'netpbm')
Derek Allard2067d1a2008-11-13 22:59:24 +0000725 {
726 $protocol = 'image_process_'.$this->image_library;
Derek Allard2067d1a2008-11-13 22:59:24 +0000727 return $this->$protocol('rotate');
728 }
729
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200730 return ($this->rotation_angle === 'hor' OR $this->rotation_angle === 'vrt')
731 ? $this->image_mirror_gd()
732 : $this->image_rotate_gd();
Derek Allard2067d1a2008-11-13 22:59:24 +0000733 }
734
735 // --------------------------------------------------------------------
736
737 /**
738 * Image Process Using GD/GD2
739 *
740 * This function will resize or crop
741 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000742 * @param string
743 * @return bool
744 */
Andrey Andreev4eea9892011-12-19 12:05:41 +0200745 public function image_process_gd($action = 'resize')
Derek Allard2067d1a2008-11-13 22:59:24 +0000746 {
747 $v2_override = FALSE;
748
749 // If the target width/height match the source, AND if the new file name is not equal to the old file name
750 // 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 +0100751 if ($this->dynamic_output === FALSE && $this->orig_width === $this->width && $this->orig_height === $this->height)
Derek Allard2067d1a2008-11-13 22:59:24 +0000752 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100753 if ($this->source_image !== $this->new_image && @copy($this->full_src_path, $this->full_dst_path))
Derek Allard2067d1a2008-11-13 22:59:24 +0000754 {
Andrey Andreev45965742014-08-27 20:40:11 +0300755 chmod($this->full_dst_path, $this->file_permissions);
Derek Allard2067d1a2008-11-13 22:59:24 +0000756 }
Andrey Andreeva92b9032011-12-24 19:05:58 +0200757
758 return TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000759 }
760
761 // Let's set up our values based on the action
Alex Bilbied261b1e2012-06-02 11:12:16 +0100762 if ($action === 'crop')
Derek Allard2067d1a2008-11-13 22:59:24 +0000763 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200764 // Reassign the source width/height if cropping
Derek Jones4b9c6292011-07-01 17:40:48 -0500765 $this->orig_width = $this->width;
Derek Allard2067d1a2008-11-13 22:59:24 +0000766 $this->orig_height = $this->height;
767
768 // GD 2.0 has a cropping bug so we'll test for it
769 if ($this->gd_version() !== FALSE)
770 {
771 $gd_version = str_replace('0', '', $this->gd_version());
Andrey Andreevd4818b72014-10-23 17:15:32 +0300772 $v2_override = ($gd_version == 2);
Derek Allard2067d1a2008-11-13 22:59:24 +0000773 }
774 }
775 else
776 {
777 // If resizing the x/y axis must be zero
778 $this->x_axis = 0;
779 $this->y_axis = 0;
780 }
781
Derek Jones4b9c6292011-07-01 17:40:48 -0500782 // Create the image handle
Derek Allard2067d1a2008-11-13 22:59:24 +0000783 if ( ! ($src_img = $this->image_create_gd()))
784 {
785 return FALSE;
786 }
787
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200788 /* Create the image
789 *
790 * Old conditional which users report cause problems with shared GD libs who report themselves as "2.0 or greater"
791 * it appears that this is no longer the issue that it was in 2004, so we've removed it, retaining it in the comment
792 * below should that ever prove inaccurate.
793 *
Alex Bilbied261b1e2012-06-02 11:12:16 +0100794 * if ($this->image_library === 'gd2' && function_exists('imagecreatetruecolor') && $v2_override === FALSE)
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200795 */
Andrey Andreev8e70b792012-01-12 20:19:24 +0200796 if ($this->image_library === 'gd2' && function_exists('imagecreatetruecolor'))
Derek Allard2067d1a2008-11-13 22:59:24 +0000797 {
798 $create = 'imagecreatetruecolor';
799 $copy = 'imagecopyresampled';
800 }
801 else
802 {
803 $create = 'imagecreate';
804 $copy = 'imagecopyresized';
805 }
806
807 $dst_img = $create($this->width, $this->height);
Derek Jones595bfd12010-08-20 10:28:22 -0500808
Alex Bilbied261b1e2012-06-02 11:12:16 +0100809 if ($this->image_type === 3) // png we can actually preserve transparency
Derek Jones595bfd12010-08-20 10:28:22 -0500810 {
811 imagealphablending($dst_img, FALSE);
812 imagesavealpha($dst_img, TRUE);
813 }
Barry Mienydd671972010-10-04 16:33:58 +0200814
Derek Allard2067d1a2008-11-13 22:59:24 +0000815 $copy($dst_img, $src_img, 0, 0, $this->x_axis, $this->y_axis, $this->width, $this->height, $this->orig_width, $this->orig_height);
816
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200817 // Show the image
Alex Bilbied261b1e2012-06-02 11:12:16 +0100818 if ($this->dynamic_output === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000819 {
820 $this->image_display_gd($dst_img);
821 }
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200822 elseif ( ! $this->image_save_gd($dst_img)) // Or save it
Derek Allard2067d1a2008-11-13 22:59:24 +0000823 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200824 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000825 }
826
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200827 // Kill the file handles
Derek Allard2067d1a2008-11-13 22:59:24 +0000828 imagedestroy($dst_img);
829 imagedestroy($src_img);
830
Andrey Andreev45965742014-08-27 20:40:11 +0300831 chmod($this->full_dst_path, $this->file_permissions);
Derek Allard2067d1a2008-11-13 22:59:24 +0000832
833 return TRUE;
834 }
835
836 // --------------------------------------------------------------------
837
838 /**
839 * Image Process Using ImageMagick
840 *
841 * This function will resize, crop or rotate
842 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000843 * @param string
844 * @return bool
845 */
Andrey Andreev4eea9892011-12-19 12:05:41 +0200846 public function image_process_imagemagick($action = 'resize')
Derek Allard2067d1a2008-11-13 22:59:24 +0000847 {
Derek Jones4b9c6292011-07-01 17:40:48 -0500848 // Do we have a vaild library path?
Alex Bilbied261b1e2012-06-02 11:12:16 +0100849 if ($this->library_path === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000850 {
851 $this->set_error('imglib_libpath_invalid');
852 return FALSE;
853 }
854
Andrey Andreev8e70b792012-01-12 20:19:24 +0200855 if ( ! preg_match('/convert$/i', $this->library_path))
Derek Allard2067d1a2008-11-13 22:59:24 +0000856 {
Andrey Andreeva92b9032011-12-24 19:05:58 +0200857 $this->library_path = rtrim($this->library_path, '/').'/convert';
Derek Allard2067d1a2008-11-13 22:59:24 +0000858 }
859
860 // Execute the command
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200861 $cmd = $this->library_path.' -quality '.$this->quality;
Derek Allard2067d1a2008-11-13 22:59:24 +0000862
Alex Bilbied261b1e2012-06-02 11:12:16 +0100863 if ($action === 'crop')
Derek Allard2067d1a2008-11-13 22:59:24 +0000864 {
Andrey Andreev8e70b792012-01-12 20:19:24 +0200865 $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 +0000866 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100867 elseif ($action === 'rotate')
Derek Allard2067d1a2008-11-13 22:59:24 +0000868 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200869 $angle = ($this->rotation_angle === 'hor' OR $this->rotation_angle === 'vrt')
870 ? '-flop' : '-rotate '.$this->rotation_angle;
Derek Allard2067d1a2008-11-13 22:59:24 +0000871
Andrey Andreev8e70b792012-01-12 20:19:24 +0200872 $cmd .= ' '.$angle.' "'.$this->full_src_path.'" "'.$this->full_dst_path.'" 2>&1';
Derek Allard2067d1a2008-11-13 22:59:24 +0000873 }
Andrey Andreev8e70b792012-01-12 20:19:24 +0200874 else // Resize
Derek Allard2067d1a2008-11-13 22:59:24 +0000875 {
Omar24063af2012-07-02 13:50:17 -0300876 if($this->maintain_ratio === TRUE)
877 {
878 $cmd .= ' -resize '.$this->width.'x'.$this->height.' "'.$this->full_src_path.'" "'.$this->full_dst_path.'" 2>&1';
879 }
Omarbb531d62012-06-29 10:48:28 -0300880 else
Omar24063af2012-07-02 13:50:17 -0300881 {
882 $cmd .= ' -resize '.$this->width.'x'.$this->height.'\! "'.$this->full_src_path.'" "'.$this->full_dst_path.'" 2>&1';
883 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000884 }
885
886 $retval = 1;
Andrey Andreeve9d2dc82012-11-07 14:23:29 +0200887 // exec() might be disabled
888 if (function_usable('exec'))
889 {
890 @exec($cmd, $output, $retval);
891 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000892
Andrey Andreev8e70b792012-01-12 20:19:24 +0200893 // Did it work?
Derek Allard2067d1a2008-11-13 22:59:24 +0000894 if ($retval > 0)
895 {
896 $this->set_error('imglib_image_process_failed');
897 return FALSE;
898 }
899
Andrey Andreev45965742014-08-27 20:40:11 +0300900 chmod($this->full_dst_path, $this->file_permissions);
Derek Allard2067d1a2008-11-13 22:59:24 +0000901
902 return TRUE;
903 }
904
905 // --------------------------------------------------------------------
906
907 /**
908 * Image Process Using NetPBM
909 *
910 * This function will resize, crop or rotate
911 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000912 * @param string
913 * @return bool
914 */
Andrey Andreev4eea9892011-12-19 12:05:41 +0200915 public function image_process_netpbm($action = 'resize')
Derek Allard2067d1a2008-11-13 22:59:24 +0000916 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100917 if ($this->library_path === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000918 {
919 $this->set_error('imglib_libpath_invalid');
920 return FALSE;
921 }
922
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200923 // Build the resizing command
Derek Allard2067d1a2008-11-13 22:59:24 +0000924 switch ($this->image_type)
925 {
926 case 1 :
Andrey Andreev56454792012-05-17 14:32:19 +0300927 $cmd_in = 'giftopnm';
928 $cmd_out = 'ppmtogif';
Derek Allard2067d1a2008-11-13 22:59:24 +0000929 break;
930 case 2 :
Andrey Andreev56454792012-05-17 14:32:19 +0300931 $cmd_in = 'jpegtopnm';
932 $cmd_out = 'ppmtojpeg';
Derek Allard2067d1a2008-11-13 22:59:24 +0000933 break;
934 case 3 :
Andrey Andreev56454792012-05-17 14:32:19 +0300935 $cmd_in = 'pngtopnm';
936 $cmd_out = 'ppmtopng';
Derek Allard2067d1a2008-11-13 22:59:24 +0000937 break;
938 }
939
Alex Bilbied261b1e2012-06-02 11:12:16 +0100940 if ($action === 'crop')
Derek Allard2067d1a2008-11-13 22:59:24 +0000941 {
942 $cmd_inner = 'pnmcut -left '.$this->x_axis.' -top '.$this->y_axis.' -width '.$this->width.' -height '.$this->height;
943 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100944 elseif ($action === 'rotate')
Derek Allard2067d1a2008-11-13 22:59:24 +0000945 {
946 switch ($this->rotation_angle)
947 {
Andrey Andreev56454792012-05-17 14:32:19 +0300948 case 90: $angle = 'r270';
Derek Allard2067d1a2008-11-13 22:59:24 +0000949 break;
Andrey Andreev56454792012-05-17 14:32:19 +0300950 case 180: $angle = 'r180';
Derek Allard2067d1a2008-11-13 22:59:24 +0000951 break;
Andrey Andreev56454792012-05-17 14:32:19 +0300952 case 270: $angle = 'r90';
Derek Allard2067d1a2008-11-13 22:59:24 +0000953 break;
Andrey Andreev56454792012-05-17 14:32:19 +0300954 case 'vrt': $angle = 'tb';
Derek Allard2067d1a2008-11-13 22:59:24 +0000955 break;
Andrey Andreev56454792012-05-17 14:32:19 +0300956 case 'hor': $angle = 'lr';
Derek Allard2067d1a2008-11-13 22:59:24 +0000957 break;
958 }
959
960 $cmd_inner = 'pnmflip -'.$angle.' ';
961 }
962 else // Resize
963 {
964 $cmd_inner = 'pnmscale -xysize '.$this->width.' '.$this->height;
965 }
966
967 $cmd = $this->library_path.$cmd_in.' '.$this->full_src_path.' | '.$cmd_inner.' | '.$cmd_out.' > '.$this->dest_folder.'netpbm.tmp';
968
969 $retval = 1;
Andrey Andreeve9d2dc82012-11-07 14:23:29 +0200970 // exec() might be disabled
971 if (function_usable('exec'))
972 {
973 @exec($cmd, $output, $retval);
974 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000975
Andrey Andreev8e70b792012-01-12 20:19:24 +0200976 // Did it work?
Derek Allard2067d1a2008-11-13 22:59:24 +0000977 if ($retval > 0)
978 {
979 $this->set_error('imglib_image_process_failed');
980 return FALSE;
981 }
982
983 // With NetPBM we have to create a temporary image.
984 // If you try manipulating the original it fails so
985 // we have to rename the temp file.
Andrey Andreeve9d2dc82012-11-07 14:23:29 +0200986 copy($this->dest_folder.'netpbm.tmp', $this->full_dst_path);
Andrey Andreev2c8baeb2012-01-19 15:45:28 +0200987 unlink($this->dest_folder.'netpbm.tmp');
Andrey Andreev45965742014-08-27 20:40:11 +0300988 chmod($this->full_dst_path, $this->file_permissions);
Derek Allard2067d1a2008-11-13 22:59:24 +0000989
990 return TRUE;
991 }
992
993 // --------------------------------------------------------------------
994
995 /**
996 * Image Rotate Using GD
997 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000998 * @return bool
999 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001000 public function image_rotate_gd()
Derek Allard2067d1a2008-11-13 22:59:24 +00001001 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001002 // Create the image handle
Derek Allard2067d1a2008-11-13 22:59:24 +00001003 if ( ! ($src_img = $this->image_create_gd()))
1004 {
1005 return FALSE;
1006 }
1007
1008 // Set the background color
1009 // This won't work with transparent PNG files so we are
1010 // going to have to figure out how to determine the color
1011 // of the alpha channel in a future release.
1012
1013 $white = imagecolorallocate($src_img, 255, 255, 255);
1014
Andrey Andreev8e70b792012-01-12 20:19:24 +02001015 // Rotate it!
Derek Allard2067d1a2008-11-13 22:59:24 +00001016 $dst_img = imagerotate($src_img, $this->rotation_angle, $white);
1017
Andrey Andreev8e70b792012-01-12 20:19:24 +02001018 // Show the image
Alex Bilbied261b1e2012-06-02 11:12:16 +01001019 if ($this->dynamic_output === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001020 {
1021 $this->image_display_gd($dst_img);
1022 }
Andrey Andreev8e70b792012-01-12 20:19:24 +02001023 elseif ( ! $this->image_save_gd($dst_img)) // ... or save it
Derek Allard2067d1a2008-11-13 22:59:24 +00001024 {
Andrey Andreev8e70b792012-01-12 20:19:24 +02001025 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +00001026 }
1027
Andrey Andreev8e70b792012-01-12 20:19:24 +02001028 // Kill the file handles
Derek Allard2067d1a2008-11-13 22:59:24 +00001029 imagedestroy($dst_img);
1030 imagedestroy($src_img);
1031
Andrey Andreev45965742014-08-27 20:40:11 +03001032 chmod($this->full_dst_path, $this->file_permissions);
Derek Allard2067d1a2008-11-13 22:59:24 +00001033
Pascal Kriete8761ef52011-02-14 13:13:52 -05001034 return TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +00001035 }
1036
1037 // --------------------------------------------------------------------
1038
1039 /**
1040 * Create Mirror Image using GD
1041 *
1042 * This function will flip horizontal or vertical
1043 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001044 * @return bool
1045 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001046 public function image_mirror_gd()
Derek Allard2067d1a2008-11-13 22:59:24 +00001047 {
1048 if ( ! $src_img = $this->image_create_gd())
1049 {
1050 return FALSE;
1051 }
1052
Derek Jones4b9c6292011-07-01 17:40:48 -05001053 $width = $this->orig_width;
Derek Allard2067d1a2008-11-13 22:59:24 +00001054 $height = $this->orig_height;
1055
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001056 if ($this->rotation_angle === 'hor')
Derek Allard2067d1a2008-11-13 22:59:24 +00001057 {
Andrey Andreeva92b9032011-12-24 19:05:58 +02001058 for ($i = 0; $i < $height; $i++, $left = 0, $right = $width-1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001059 {
Derek Allard2067d1a2008-11-13 22:59:24 +00001060 while ($left < $right)
1061 {
1062 $cl = imagecolorat($src_img, $left, $i);
1063 $cr = imagecolorat($src_img, $right, $i);
1064
1065 imagesetpixel($src_img, $left, $i, $cr);
1066 imagesetpixel($src_img, $right, $i, $cl);
1067
1068 $left++;
1069 $right--;
1070 }
1071 }
1072 }
1073 else
1074 {
Andrey Andreeva92b9032011-12-24 19:05:58 +02001075 for ($i = 0; $i < $width; $i++, $top = 0, $bot = $height-1)
Derek Allard2067d1a2008-11-13 22:59:24 +00001076 {
Derek Allard2067d1a2008-11-13 22:59:24 +00001077 while ($top < $bot)
1078 {
1079 $ct = imagecolorat($src_img, $i, $top);
1080 $cb = imagecolorat($src_img, $i, $bot);
1081
1082 imagesetpixel($src_img, $i, $top, $cb);
1083 imagesetpixel($src_img, $i, $bot, $ct);
1084
1085 $top++;
1086 $bot--;
1087 }
1088 }
1089 }
1090
Andrey Andreev8e70b792012-01-12 20:19:24 +02001091 // Show the image
Alex Bilbied261b1e2012-06-02 11:12:16 +01001092 if ($this->dynamic_output === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001093 {
1094 $this->image_display_gd($src_img);
1095 }
Andrey Andreev8e70b792012-01-12 20:19:24 +02001096 elseif ( ! $this->image_save_gd($src_img)) // ... or save it
Derek Allard2067d1a2008-11-13 22:59:24 +00001097 {
Andrey Andreev8e70b792012-01-12 20:19:24 +02001098 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +00001099 }
1100
Andrey Andreev8e70b792012-01-12 20:19:24 +02001101 // Kill the file handles
Derek Allard2067d1a2008-11-13 22:59:24 +00001102 imagedestroy($src_img);
1103
Andrey Andreev45965742014-08-27 20:40:11 +03001104 chmod($this->full_dst_path, $this->file_permissions);
Derek Allard2067d1a2008-11-13 22:59:24 +00001105
1106 return TRUE;
1107 }
1108
1109 // --------------------------------------------------------------------
1110
1111 /**
1112 * Image Watermark
1113 *
1114 * This is a wrapper function that chooses the type
1115 * of watermarking based on the specified preference.
1116 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001117 * @return bool
1118 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001119 public function watermark()
Derek Allard2067d1a2008-11-13 22:59:24 +00001120 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001121 return ($this->wm_type === 'overlay') ? $this->overlay_watermark() : $this->text_watermark();
Derek Allard2067d1a2008-11-13 22:59:24 +00001122 }
1123
1124 // --------------------------------------------------------------------
1125
1126 /**
1127 * Watermark - Graphic Version
1128 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001129 * @return bool
1130 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001131 public function overlay_watermark()
Derek Allard2067d1a2008-11-13 22:59:24 +00001132 {
1133 if ( ! function_exists('imagecolortransparent'))
1134 {
1135 $this->set_error('imglib_gd_required');
1136 return FALSE;
1137 }
1138
Andrey Andreev8e70b792012-01-12 20:19:24 +02001139 // Fetch source image properties
Derek Allard2067d1a2008-11-13 22:59:24 +00001140 $this->get_image_properties();
1141
Andrey Andreev8e70b792012-01-12 20:19:24 +02001142 // Fetch watermark image properties
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001143 $props = $this->get_image_properties($this->wm_overlay_path, TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +00001144 $wm_img_type = $props['image_type'];
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001145 $wm_width = $props['width'];
1146 $wm_height = $props['height'];
Derek Allard2067d1a2008-11-13 22:59:24 +00001147
Andrey Andreev8e70b792012-01-12 20:19:24 +02001148 // Create two image resources
Derek Jones4b9c6292011-07-01 17:40:48 -05001149 $wm_img = $this->image_create_gd($this->wm_overlay_path, $wm_img_type);
Derek Allard2067d1a2008-11-13 22:59:24 +00001150 $src_img = $this->image_create_gd($this->full_src_path);
1151
1152 // Reverse the offset if necessary
1153 // When the image is positioned at the bottom
1154 // we don't want the vertical offset to push it
Andrey Andreev8e70b792012-01-12 20:19:24 +02001155 // further down. We want the reverse, so we'll
1156 // invert the offset. Same with the horizontal
Derek Allard2067d1a2008-11-13 22:59:24 +00001157 // offset when the image is at the right
1158
Andrey Andreev8e70b792012-01-12 20:19:24 +02001159 $this->wm_vrt_alignment = strtoupper($this->wm_vrt_alignment[0]);
1160 $this->wm_hor_alignment = strtoupper($this->wm_hor_alignment[0]);
Derek Allard2067d1a2008-11-13 22:59:24 +00001161
Alex Bilbied261b1e2012-06-02 11:12:16 +01001162 if ($this->wm_vrt_alignment === 'B')
Derek Allard2067d1a2008-11-13 22:59:24 +00001163 $this->wm_vrt_offset = $this->wm_vrt_offset * -1;
1164
Alex Bilbied261b1e2012-06-02 11:12:16 +01001165 if ($this->wm_hor_alignment === 'R')
Derek Allard2067d1a2008-11-13 22:59:24 +00001166 $this->wm_hor_offset = $this->wm_hor_offset * -1;
1167
Andrey Andreev8e70b792012-01-12 20:19:24 +02001168 // Set the base x and y axis values
Derek Allard2067d1a2008-11-13 22:59:24 +00001169 $x_axis = $this->wm_hor_offset + $this->wm_padding;
1170 $y_axis = $this->wm_vrt_offset + $this->wm_padding;
1171
Andrey Andreev8e70b792012-01-12 20:19:24 +02001172 // Set the vertical position
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001173 if ($this->wm_vrt_alignment === 'M')
Derek Allard2067d1a2008-11-13 22:59:24 +00001174 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001175 $y_axis += ($this->orig_height / 2) - ($wm_height / 2);
1176 }
1177 elseif ($this->wm_vrt_alignment === 'B')
1178 {
1179 $y_axis += $this->orig_height - $wm_height;
Derek Allard2067d1a2008-11-13 22:59:24 +00001180 }
1181
Andrey Andreev8e70b792012-01-12 20:19:24 +02001182 // Set the horizontal position
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001183 if ($this->wm_hor_alignment === 'C')
Derek Allard2067d1a2008-11-13 22:59:24 +00001184 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001185 $x_axis += ($this->orig_width / 2) - ($wm_width / 2);
1186 }
1187 elseif ($this->wm_hor_alignment === 'R')
1188 {
1189 $x_axis += $this->orig_width - $wm_width;
Derek Allard2067d1a2008-11-13 22:59:24 +00001190 }
1191
Derek Jones4b9c6292011-07-01 17:40:48 -05001192 // Build the finalized image
Alex Bilbied261b1e2012-06-02 11:12:16 +01001193 if ($wm_img_type === 3 && function_exists('imagealphablending'))
Derek Allard2067d1a2008-11-13 22:59:24 +00001194 {
1195 @imagealphablending($src_img, TRUE);
Barry Mienydd671972010-10-04 16:33:58 +02001196 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001197
1198 // Set RGB values for text and shadow
1199 $rgba = imagecolorat($wm_img, $this->wm_x_transp, $this->wm_y_transp);
1200 $alpha = ($rgba & 0x7F000000) >> 24;
1201
1202 // make a best guess as to whether we're dealing with an image with alpha transparency or no/binary transparency
1203 if ($alpha > 0)
1204 {
1205 // copy the image directly, the image's alpha transparency being the sole determinant of blending
1206 imagecopy($src_img, $wm_img, $x_axis, $y_axis, 0, 0, $wm_width, $wm_height);
1207 }
1208 else
1209 {
1210 // set our RGB value from above to be transparent and merge the images with the specified opacity
1211 imagecolortransparent($wm_img, imagecolorat($wm_img, $this->wm_x_transp, $this->wm_y_transp));
1212 imagecopymerge($src_img, $wm_img, $x_axis, $y_axis, 0, 0, $wm_width, $wm_height, $this->wm_opacity);
1213 }
1214
Andrey Andreevdb037db2015-01-12 13:45:12 +02001215 // We can preserve transparency for PNG images
Дмитрийb23b8fc2014-10-20 00:36:55 +04001216 if ($this->image_type === 3)
1217 {
1218 imagealphablending($src_img, FALSE);
1219 imagesavealpha($src_img, TRUE);
1220 }
1221
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001222 // Output the image
Alex Bilbied261b1e2012-06-02 11:12:16 +01001223 if ($this->dynamic_output === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001224 {
1225 $this->image_display_gd($src_img);
1226 }
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001227 elseif ( ! $this->image_save_gd($src_img)) // ... or save it
Derek Allard2067d1a2008-11-13 22:59:24 +00001228 {
Andrey Andreeva92b9032011-12-24 19:05:58 +02001229 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +00001230 }
1231
1232 imagedestroy($src_img);
1233 imagedestroy($wm_img);
1234
1235 return TRUE;
1236 }
1237
1238 // --------------------------------------------------------------------
1239
1240 /**
1241 * Watermark - Text Version
1242 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001243 * @return bool
1244 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001245 public function text_watermark()
Derek Allard2067d1a2008-11-13 22:59:24 +00001246 {
1247 if ( ! ($src_img = $this->image_create_gd()))
1248 {
1249 return FALSE;
1250 }
1251
Alex Bilbied261b1e2012-06-02 11:12:16 +01001252 if ($this->wm_use_truetype === TRUE && ! file_exists($this->wm_font_path))
Derek Allard2067d1a2008-11-13 22:59:24 +00001253 {
1254 $this->set_error('imglib_missing_font');
1255 return FALSE;
1256 }
1257
Andrey Andreev8e70b792012-01-12 20:19:24 +02001258 // Fetch source image properties
Derek Allard2067d1a2008-11-13 22:59:24 +00001259 $this->get_image_properties();
1260
Derek Allard2067d1a2008-11-13 22:59:24 +00001261 // Reverse the vertical offset
1262 // When the image is positioned at the bottom
1263 // we don't want the vertical offset to push it
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001264 // further down. We want the reverse, so we'll
Andrey Andreev8e70b792012-01-12 20:19:24 +02001265 // invert the offset. Note: The horizontal
Derek Allard2067d1a2008-11-13 22:59:24 +00001266 // offset flips itself automatically
1267
Alex Bilbied261b1e2012-06-02 11:12:16 +01001268 if ($this->wm_vrt_alignment === 'B')
Andrey Andreeve52fc262014-02-11 13:27:01 +02001269 {
Derek Allard2067d1a2008-11-13 22:59:24 +00001270 $this->wm_vrt_offset = $this->wm_vrt_offset * -1;
Andrey Andreeve52fc262014-02-11 13:27:01 +02001271 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001272
Alex Bilbied261b1e2012-06-02 11:12:16 +01001273 if ($this->wm_hor_alignment === 'R')
Andrey Andreeve52fc262014-02-11 13:27:01 +02001274 {
Derek Allard2067d1a2008-11-13 22:59:24 +00001275 $this->wm_hor_offset = $this->wm_hor_offset * -1;
Andrey Andreeve52fc262014-02-11 13:27:01 +02001276 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001277
1278 // Set font width and height
1279 // These are calculated differently depending on
1280 // whether we are using the true type font or not
Alex Bilbied261b1e2012-06-02 11:12:16 +01001281 if ($this->wm_use_truetype === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001282 {
Andrey Andreeve52fc262014-02-11 13:27:01 +02001283 if (empty($this->wm_font_size))
Andrey Andreeva92b9032011-12-24 19:05:58 +02001284 {
1285 $this->wm_font_size = 17;
1286 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001287
Andrey Andreeve52fc262014-02-11 13:27:01 +02001288 if (function_exists('imagettfbbox'))
1289 {
1290 $temp = imagettfbbox($this->wm_font_size, 0, $this->wm_font_path, $this->wm_text);
1291 $temp = $temp[2] - $temp[0];
1292
1293 $fontwidth = $temp / strlen($this->wm_text);
1294 }
1295 else
1296 {
1297 $fontwidth = $this->wm_font_size - ($this->wm_font_size / 4);
1298 }
1299
Derek Allard2067d1a2008-11-13 22:59:24 +00001300 $fontheight = $this->wm_font_size;
1301 $this->wm_vrt_offset += $this->wm_font_size;
1302 }
1303 else
1304 {
Derek Jones4b9c6292011-07-01 17:40:48 -05001305 $fontwidth = imagefontwidth($this->wm_font_size);
Derek Allard2067d1a2008-11-13 22:59:24 +00001306 $fontheight = imagefontheight($this->wm_font_size);
1307 }
1308
1309 // Set base X and Y axis values
1310 $x_axis = $this->wm_hor_offset + $this->wm_padding;
1311 $y_axis = $this->wm_vrt_offset + $this->wm_padding;
1312
Alex Bilbied261b1e2012-06-02 11:12:16 +01001313 if ($this->wm_use_drop_shadow === FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001314 $this->wm_shadow_distance = 0;
1315
Andrey Andreev7a7ad782012-11-12 17:21:01 +02001316 $this->wm_vrt_alignment = strtoupper($this->wm_vrt_alignment[0]);
1317 $this->wm_hor_alignment = strtoupper($this->wm_hor_alignment[0]);
Derek Allard2067d1a2008-11-13 22:59:24 +00001318
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001319 // Set verticle alignment
1320 if ($this->wm_vrt_alignment === 'M')
Derek Allard2067d1a2008-11-13 22:59:24 +00001321 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001322 $y_axis += ($this->orig_height / 2) + ($fontheight / 2);
1323 }
1324 elseif ($this->wm_vrt_alignment === 'B')
1325 {
1326 $y_axis += $this->orig_height - $fontheight - $this->wm_shadow_distance - ($fontheight / 2);
Derek Allard2067d1a2008-11-13 22:59:24 +00001327 }
1328
1329 $x_shad = $x_axis + $this->wm_shadow_distance;
1330 $y_shad = $y_axis + $this->wm_shadow_distance;
1331
Andrey Andreev64dbdfb2011-12-30 14:14:07 +02001332 if ($this->wm_use_drop_shadow)
Derek Allard2067d1a2008-11-13 22:59:24 +00001333 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001334 // Set horizontal alignment
1335 if ($this->wm_hor_alignment === 'R')
1336 {
1337 $x_shad += $this->orig_width - ($fontwidth * strlen($this->wm_text));
1338 $x_axis += $this->orig_width - ($fontwidth * strlen($this->wm_text));
1339 }
1340 elseif ($this->wm_hor_alignment === 'C')
1341 {
1342 $x_shad += floor(($this->orig_width - ($fontwidth * strlen($this->wm_text))) / 2);
1343 $x_axis += floor(($this->orig_width - ($fontwidth * strlen($this->wm_text))) / 2);
1344 }
1345
Andrey Andreev8323ae62011-12-31 18:39:10 +02001346 /* Set RGB values for text and shadow
1347 *
1348 * First character is #, so we don't really need it.
1349 * Get the rest of the string and split it into 2-length
1350 * hex values:
1351 */
1352 $txt_color = str_split(substr($this->wm_font_color, 1, 6), 2);
Andrey Andreev64dbdfb2011-12-30 14:14:07 +02001353 $txt_color = imagecolorclosest($src_img, hexdec($txt_color[0]), hexdec($txt_color[1]), hexdec($txt_color[2]));
Andrey Andreev8323ae62011-12-31 18:39:10 +02001354 $drp_color = str_split(substr($this->wm_shadow_color, 1, 6), 2);
Ronald Beilsma8f80bc42012-01-12 16:41:49 +01001355 $drp_color = imagecolorclosest($src_img, hexdec($drp_color[0]), hexdec($drp_color[1]), hexdec($drp_color[2]));
Andrey Andreev64dbdfb2011-12-30 14:14:07 +02001356
Andrey Andreev8e70b792012-01-12 20:19:24 +02001357 // Add the text to the source image
Andrey Andreev64dbdfb2011-12-30 14:14:07 +02001358 if ($this->wm_use_truetype)
1359 {
1360 imagettftext($src_img, $this->wm_font_size, 0, $x_shad, $y_shad, $drp_color, $this->wm_font_path, $this->wm_text);
1361 imagettftext($src_img, $this->wm_font_size, 0, $x_axis, $y_axis, $txt_color, $this->wm_font_path, $this->wm_text);
1362 }
1363 else
1364 {
1365 imagestring($src_img, $this->wm_font_size, $x_shad, $y_shad, $this->wm_text, $drp_color);
1366 imagestring($src_img, $this->wm_font_size, $x_axis, $y_axis, $this->wm_text, $txt_color);
1367 }
Andrey Andreev99ae2262012-10-05 15:14:30 +03001368
1369 // We can preserve transparency for PNG images
1370 if ($this->image_type === 3)
1371 {
1372 imagealphablending($src_img, FALSE);
1373 imagesavealpha($src_img, TRUE);
1374 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001375 }
1376
Andrey Andreev8e70b792012-01-12 20:19:24 +02001377 // Output the final image
Alex Bilbied261b1e2012-06-02 11:12:16 +01001378 if ($this->dynamic_output === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001379 {
1380 $this->image_display_gd($src_img);
1381 }
1382 else
1383 {
1384 $this->image_save_gd($src_img);
1385 }
1386
1387 imagedestroy($src_img);
1388
1389 return TRUE;
1390 }
1391
1392 // --------------------------------------------------------------------
1393
1394 /**
1395 * Create Image - GD
1396 *
1397 * This simply creates an image resource handle
1398 * based on the type of image being processed
1399 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001400 * @param string
Timothy Warrenb82bc3a2012-04-27 09:12:58 -04001401 * @param string
Derek Allard2067d1a2008-11-13 22:59:24 +00001402 * @return resource
1403 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001404 public function image_create_gd($path = '', $image_type = '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001405 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001406 if ($path === '')
Andrey Andreeve52fc262014-02-11 13:27:01 +02001407 {
Derek Allard2067d1a2008-11-13 22:59:24 +00001408 $path = $this->full_src_path;
Andrey Andreeve52fc262014-02-11 13:27:01 +02001409 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001410
Alex Bilbied261b1e2012-06-02 11:12:16 +01001411 if ($image_type === '')
Andrey Andreeve52fc262014-02-11 13:27:01 +02001412 {
Derek Allard2067d1a2008-11-13 22:59:24 +00001413 $image_type = $this->image_type;
Andrey Andreeve52fc262014-02-11 13:27:01 +02001414 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001415
Derek Allard2067d1a2008-11-13 22:59:24 +00001416 switch ($image_type)
1417 {
Andrey Andreeve52fc262014-02-11 13:27:01 +02001418 case 1 :
1419 if ( ! function_exists('imagecreatefromgif'))
1420 {
1421 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_gif_not_supported'));
1422 return FALSE;
1423 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001424
Andrey Andreeve52fc262014-02-11 13:27:01 +02001425 return imagecreatefromgif($path);
Derek Allard2067d1a2008-11-13 22:59:24 +00001426 case 2 :
Andrey Andreeve52fc262014-02-11 13:27:01 +02001427 if ( ! function_exists('imagecreatefromjpeg'))
1428 {
1429 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_jpg_not_supported'));
1430 return FALSE;
1431 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001432
Andrey Andreeve52fc262014-02-11 13:27:01 +02001433 return imagecreatefromjpeg($path);
Derek Allard2067d1a2008-11-13 22:59:24 +00001434 case 3 :
Andrey Andreeve52fc262014-02-11 13:27:01 +02001435 if ( ! function_exists('imagecreatefrompng'))
1436 {
1437 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_png_not_supported'));
1438 return FALSE;
1439 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001440
Andrey Andreeve52fc262014-02-11 13:27:01 +02001441 return imagecreatefrompng($path);
1442 default:
1443 $this->set_error(array('imglib_unsupported_imagecreate'));
1444 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +00001445 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001446 }
1447
1448 // --------------------------------------------------------------------
1449
1450 /**
1451 * Write image file to disk - GD
1452 *
1453 * Takes an image resource as input and writes the file
1454 * to the specified destination
1455 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001456 * @param resource
1457 * @return bool
1458 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001459 public function image_save_gd($resource)
Derek Allard2067d1a2008-11-13 22:59:24 +00001460 {
1461 switch ($this->image_type)
1462 {
Andrey Andreev56454792012-05-17 14:32:19 +03001463 case 1:
1464 if ( ! function_exists('imagegif'))
1465 {
1466 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_gif_not_supported'));
1467 return FALSE;
1468 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001469
Andrey Andreev56454792012-05-17 14:32:19 +03001470 if ( ! @imagegif($resource, $this->full_dst_path))
1471 {
1472 $this->set_error('imglib_save_failed');
1473 return FALSE;
1474 }
1475 break;
1476 case 2:
1477 if ( ! function_exists('imagejpeg'))
1478 {
1479 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_jpg_not_supported'));
1480 return FALSE;
1481 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001482
Andrey Andreev56454792012-05-17 14:32:19 +03001483 if ( ! @imagejpeg($resource, $this->full_dst_path, $this->quality))
1484 {
1485 $this->set_error('imglib_save_failed');
1486 return FALSE;
1487 }
1488 break;
1489 case 3:
1490 if ( ! function_exists('imagepng'))
1491 {
1492 $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_png_not_supported'));
1493 return FALSE;
1494 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001495
Andrey Andreev56454792012-05-17 14:32:19 +03001496 if ( ! @imagepng($resource, $this->full_dst_path))
1497 {
1498 $this->set_error('imglib_save_failed');
1499 return FALSE;
1500 }
1501 break;
1502 default:
1503 $this->set_error(array('imglib_unsupported_imagecreate'));
1504 return FALSE;
1505 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001506 }
1507
1508 return TRUE;
1509 }
1510
1511 // --------------------------------------------------------------------
1512
1513 /**
1514 * Dynamically outputs an image
1515 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001516 * @param resource
1517 * @return void
1518 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001519 public function image_display_gd($resource)
Derek Allard2067d1a2008-11-13 22:59:24 +00001520 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001521 header('Content-Disposition: filename='.$this->source_image.';');
1522 header('Content-Type: '.$this->mime_type);
Derek Allard2067d1a2008-11-13 22:59:24 +00001523 header('Content-Transfer-Encoding: binary');
1524 header('Last-Modified: '.gmdate('D, d M Y H:i:s', time()).' GMT');
1525
1526 switch ($this->image_type)
1527 {
Andrey Andreev56454792012-05-17 14:32:19 +03001528 case 1 : imagegif($resource);
Derek Allard2067d1a2008-11-13 22:59:24 +00001529 break;
Ted Wood9cc707b2013-01-08 19:41:45 -08001530 case 2 : imagejpeg($resource, NULL, $this->quality);
Derek Allard2067d1a2008-11-13 22:59:24 +00001531 break;
Andrey Andreev56454792012-05-17 14:32:19 +03001532 case 3 : imagepng($resource);
Derek Allard2067d1a2008-11-13 22:59:24 +00001533 break;
Andrey Andreev56454792012-05-17 14:32:19 +03001534 default: echo 'Unable to display the image';
Derek Allard2067d1a2008-11-13 22:59:24 +00001535 break;
1536 }
1537 }
1538
1539 // --------------------------------------------------------------------
1540
1541 /**
1542 * Re-proportion Image Width/Height
1543 *
1544 * When creating thumbs, the desired width/height
1545 * can end up warping the image due to an incorrect
1546 * ratio between the full-sized image and the thumb.
1547 *
1548 * This function lets us re-proportion the width/height
1549 * if users choose to maintain the aspect ratio when resizing.
1550 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001551 * @return void
1552 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001553 public function image_reproportion()
Derek Allard2067d1a2008-11-13 22:59:24 +00001554 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001555 if (($this->width === 0 && $this->height === 0) OR $this->orig_width === 0 OR $this->orig_height === 0
Andrey Andreev7a7ad782012-11-12 17:21:01 +02001556 OR ( ! ctype_digit((string) $this->width) && ! ctype_digit((string) $this->height))
1557 OR ! ctype_digit((string) $this->orig_width) OR ! ctype_digit((string) $this->orig_height))
Derek Allard2067d1a2008-11-13 22:59:24 +00001558 {
Andrey Andreev8e70b792012-01-12 20:19:24 +02001559 return;
Derek Allard2067d1a2008-11-13 22:59:24 +00001560 }
1561
Andrey Andreev7a7ad782012-11-12 17:21:01 +02001562 // Sanitize
Andrey Andreev8e70b792012-01-12 20:19:24 +02001563 $this->width = (int) $this->width;
1564 $this->height = (int) $this->height;
1565
1566 if ($this->master_dim !== 'width' && $this->master_dim !== 'height')
Derek Allard2067d1a2008-11-13 22:59:24 +00001567 {
Andrey Andreev8e70b792012-01-12 20:19:24 +02001568 if ($this->width > 0 && $this->height > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001569 {
Andrey Andreev8e70b792012-01-12 20:19:24 +02001570 $this->master_dim = ((($this->orig_height/$this->orig_width) - ($this->height/$this->width)) < 0)
1571 ? 'width' : 'height';
Derek Allard2067d1a2008-11-13 22:59:24 +00001572 }
1573 else
1574 {
Andrey Andreev8e70b792012-01-12 20:19:24 +02001575 $this->master_dim = ($this->height === 0) ? 'width' : 'height';
Derek Allard2067d1a2008-11-13 22:59:24 +00001576 }
1577 }
Andrey Andreev8e70b792012-01-12 20:19:24 +02001578 elseif (($this->master_dim === 'width' && $this->width === 0)
1579 OR ($this->master_dim === 'height' && $this->height === 0))
1580 {
1581 return;
1582 }
1583
1584 if ($this->master_dim === 'width')
1585 {
1586 $this->height = (int) ceil($this->width*$this->orig_height/$this->orig_width);
1587 }
1588 else
1589 {
1590 $this->width = (int) ceil($this->orig_width*$this->height/$this->orig_height);
1591 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001592 }
1593
1594 // --------------------------------------------------------------------
1595
1596 /**
1597 * Get image properties
1598 *
1599 * A helper function that gets info about the file
1600 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001601 * @param string
Timothy Warrenb82bc3a2012-04-27 09:12:58 -04001602 * @param bool
Derek Allard2067d1a2008-11-13 22:59:24 +00001603 * @return mixed
1604 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001605 public function get_image_properties($path = '', $return = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001606 {
1607 // For now we require GD but we should
1608 // find a way to determine this using IM or NetPBM
1609
Alex Bilbied261b1e2012-06-02 11:12:16 +01001610 if ($path === '')
Andrey Andreev8e70b792012-01-12 20:19:24 +02001611 {
Derek Allard2067d1a2008-11-13 22:59:24 +00001612 $path = $this->full_src_path;
Andrey Andreev8e70b792012-01-12 20:19:24 +02001613 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001614
1615 if ( ! file_exists($path))
1616 {
1617 $this->set_error('imglib_invalid_path');
1618 return FALSE;
1619 }
1620
Phil Sturgeon901998a2011-08-26 10:03:33 +01001621 $vals = getimagesize($path);
Derek Allard2067d1a2008-11-13 22:59:24 +00001622 $types = array(1 => 'gif', 2 => 'jpeg', 3 => 'png');
Andrey Andreeva92b9032011-12-24 19:05:58 +02001623 $mime = (isset($types[$vals[2]])) ? 'image/'.$types[$vals[2]] : 'image/jpg';
Derek Allard2067d1a2008-11-13 22:59:24 +00001624
Alex Bilbied261b1e2012-06-02 11:12:16 +01001625 if ($return === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001626 {
Andrey Andreeva92b9032011-12-24 19:05:58 +02001627 return array(
1628 'width' => $vals[0],
1629 'height' => $vals[1],
1630 'image_type' => $vals[2],
1631 'size_str' => $vals[3],
1632 'mime_type' => $mime
1633 );
Derek Allard2067d1a2008-11-13 22:59:24 +00001634 }
1635
Andrey Andreeva92b9032011-12-24 19:05:58 +02001636 $this->orig_width = $vals[0];
1637 $this->orig_height = $vals[1];
1638 $this->image_type = $vals[2];
1639 $this->size_str = $vals[3];
Derek Allard2067d1a2008-11-13 22:59:24 +00001640 $this->mime_type = $mime;
1641
1642 return TRUE;
1643 }
1644
1645 // --------------------------------------------------------------------
1646
1647 /**
1648 * Size calculator
1649 *
1650 * This function takes a known width x height and
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001651 * recalculates it to a new size. Only one
Derek Allard2067d1a2008-11-13 22:59:24 +00001652 * new variable needs to be known
1653 *
1654 * $props = array(
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001655 * 'width' => $width,
1656 * 'height' => $height,
1657 * 'new_width' => 40,
1658 * 'new_height' => ''
1659 * );
Derek Allard2067d1a2008-11-13 22:59:24 +00001660 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001661 * @param array
1662 * @return array
1663 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001664 public function size_calculator($vals)
Derek Allard2067d1a2008-11-13 22:59:24 +00001665 {
1666 if ( ! is_array($vals))
1667 {
1668 return;
1669 }
1670
1671 $allowed = array('new_width', 'new_height', 'width', 'height');
1672
1673 foreach ($allowed as $item)
1674 {
Andrey Andreev56454792012-05-17 14:32:19 +03001675 if (empty($vals[$item]))
1676 {
Derek Allard2067d1a2008-11-13 22:59:24 +00001677 $vals[$item] = 0;
Andrey Andreev56454792012-05-17 14:32:19 +03001678 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001679 }
1680
Alex Bilbied261b1e2012-06-02 11:12:16 +01001681 if ($vals['width'] === 0 OR $vals['height'] === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001682 {
1683 return $vals;
1684 }
1685
Alex Bilbied261b1e2012-06-02 11:12:16 +01001686 if ($vals['new_width'] === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001687 {
1688 $vals['new_width'] = ceil($vals['width']*$vals['new_height']/$vals['height']);
1689 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001690 elseif ($vals['new_height'] === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001691 {
1692 $vals['new_height'] = ceil($vals['new_width']*$vals['height']/$vals['width']);
1693 }
1694
1695 return $vals;
1696 }
1697
1698 // --------------------------------------------------------------------
1699
1700 /**
1701 * Explode source_image
1702 *
1703 * This is a helper function that extracts the extension
Derek Jones4b9c6292011-07-01 17:40:48 -05001704 * from the source_image. This function lets us deal with
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001705 * source_images with multiple periods, like: my.cool.jpg
Derek Allard2067d1a2008-11-13 22:59:24 +00001706 * It returns an associative array with two elements:
Derek Jones4b9c6292011-07-01 17:40:48 -05001707 * $array['ext'] = '.jpg';
Derek Allard2067d1a2008-11-13 22:59:24 +00001708 * $array['name'] = 'my.cool';
1709 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001710 * @param array
1711 * @return array
1712 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001713 public function explode_name($source_image)
Derek Allard2067d1a2008-11-13 22:59:24 +00001714 {
Derek Jones08cae632009-02-10 20:03:29 +00001715 $ext = strrchr($source_image, '.');
1716 $name = ($ext === FALSE) ? $source_image : substr($source_image, 0, -strlen($ext));
Barry Mienydd671972010-10-04 16:33:58 +02001717
Derek Jones08cae632009-02-10 20:03:29 +00001718 return array('ext' => $ext, 'name' => $name);
Derek Allard2067d1a2008-11-13 22:59:24 +00001719 }
1720
1721 // --------------------------------------------------------------------
1722
1723 /**
1724 * Is GD Installed?
1725 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001726 * @return bool
1727 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001728 public function gd_loaded()
Derek Allard2067d1a2008-11-13 22:59:24 +00001729 {
1730 if ( ! extension_loaded('gd'))
1731 {
Andrey Andreeva92b9032011-12-24 19:05:58 +02001732 /* As it is stated in the PHP manual, dl() is not always available
1733 * and even if so - it could generate an E_WARNING message on failure
1734 */
Andrey Andreev8e70b792012-01-12 20:19:24 +02001735 return (function_exists('dl') && @dl('gd.so'));
Derek Allard2067d1a2008-11-13 22:59:24 +00001736 }
1737
1738 return TRUE;
1739 }
1740
1741 // --------------------------------------------------------------------
1742
1743 /**
1744 * Get GD version
1745 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001746 * @return mixed
1747 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001748 public function gd_version()
Derek Allard2067d1a2008-11-13 22:59:24 +00001749 {
1750 if (function_exists('gd_info'))
1751 {
1752 $gd_version = @gd_info();
Andrey Andreev8e70b792012-01-12 20:19:24 +02001753 return preg_replace('/\D/', '', $gd_version['GD Version']);
Derek Allard2067d1a2008-11-13 22:59:24 +00001754 }
1755
1756 return FALSE;
1757 }
1758
1759 // --------------------------------------------------------------------
1760
1761 /**
1762 * Set error message
1763 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001764 * @param string
1765 * @return void
1766 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001767 public function set_error($msg)
Derek Allard2067d1a2008-11-13 22:59:24 +00001768 {
1769 $CI =& get_instance();
1770 $CI->lang->load('imglib');
1771
1772 if (is_array($msg))
1773 {
1774 foreach ($msg as $val)
1775 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001776 $msg = ($CI->lang->line($val) === FALSE) ? $val : $CI->lang->line($val);
Derek Allard2067d1a2008-11-13 22:59:24 +00001777 $this->error_msg[] = $msg;
1778 log_message('error', $msg);
1779 }
1780 }
1781 else
1782 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001783 $msg = ($CI->lang->line($msg) === FALSE) ? $msg : $CI->lang->line($msg);
Derek Allard2067d1a2008-11-13 22:59:24 +00001784 $this->error_msg[] = $msg;
1785 log_message('error', $msg);
1786 }
1787 }
1788
1789 // --------------------------------------------------------------------
1790
1791 /**
1792 * Show error messages
1793 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001794 * @param string
Timothy Warrenb82bc3a2012-04-27 09:12:58 -04001795 * @param string
Derek Allard2067d1a2008-11-13 22:59:24 +00001796 * @return string
1797 */
Andrey Andreev4eea9892011-12-19 12:05:41 +02001798 public function display_errors($open = '<p>', $close = '</p>')
Derek Allard2067d1a2008-11-13 22:59:24 +00001799 {
Andrey Andreev2c8baeb2012-01-19 15:45:28 +02001800 return (count($this->error_msg) > 0) ? $open.implode($close.$open, $this->error_msg).$close : '';
Derek Allard2067d1a2008-11-13 22:59:24 +00001801 }
1802
1803}
Derek Allard2067d1a2008-11-13 22:59:24 +00001804
1805/* End of file Image_lib.php */
Andrey Andreevdb037db2015-01-12 13:45:12 +02001806/* Location: ./system/libraries/Image_lib.php */