1
<?php
2
/**
3
* Image Manipulation Library
4
*
5
* @author Zhou Yuan <yuanzhou19@gmail.com>
6
* @link http://www.infopotato.com/
7
* @link http://codeigniter.com/user_guide/libraries/image_lib.html
8
* @copyright Copyright © 2009-2011 Zhou Yuan
9
* @license http://www.opensource.org/licenses/mit-license.php MIT Licence
10
*/
11
class Image_Library {
12
/**
13
* Sets the image library to be used (Can be: imagemagick, netpbm, gd, gd2)
14
*
15
* Availability: R, C, X, W
16
*
17
* @var string
18
*/
19
public $image_library_to_use = 'gd2';
20
21
/**
22
* Sets the server path to your ImageMagick or NetPBM library.
23
* If you use either of those libraries you must supply the path.
24
*
25
* Availability: R, C, X
26
*
27
* @var string
28
*/
29
public $library_path = '';
30
31
/**
32
* Determines whether the new image file should be written to disk or generated dynamically.
33
* Whether to send to browser or write to disk
34
* Note: If you choose the dynamic setting, only one image can be shown at a time,
35
* and it can't be positioned on the page.
36
* It simply outputs the raw image dynamically to your browser, along with image headers.
37
*
38
* Availability: R, C, X, W
39
*
40
* @var string
41
*/
42
public $dynamic_output = FALSE;
43
44
/**
45
* Sets the source image name/path.
46
* The path must be a relative or absolute server path, not a URL.
47
*
48
* Availability: R, C, X, W
49
*
50
* @var string
51
*/
52
public $source_image = '';
53
54
/**
55
* Sets the destination image name/path. You'll use this preference when creating an image copy.
56
* The path must be a relative or absolute server path, not a URL.
57
*
58
* Availability: R, C, X, W
59
*
60
* @var string
61
*/
62
public $new_image = '';
63
64
/**
65
* Sets the width you would like the image set to.
66
*
67
* Availability: R, C
68
*
69
* @var string
70
*/
71
public $width = '';
72
73
/**
74
* Sets the height you would like the image set to.
75
*
76
* Availability: R, C
77
*
78
* @var string
79
*/
80
public $height = '';
81
82
/**
83
* Sets the quality of the image. The higher the quality the larger the file size.
84
*
85
* Availability: R, C, X, W
86
*
87
* @var string
88
*/
89
public $quality = '90';
90
91
/**
92
* Tells the image processing function to create a thumb.
93
*
94
* Availability: R
95
*
96
* @var boolean
97
*/
98
public $create_thumb = FALSE;
99
100
/**
101
* Specifies the thumbnail indicator. It will be inserted just before the file extension,
102
* so mypic.jpg would become mypic_thumb.jpg
103
*
104
* Availability: R
105
*
106
* @var string
107
*/
108
public $thumb_marker = '_thumb';
109
110
/**
111
* Specifies whether to maintain the original aspect ratio when resizing or use hard values.
112
*
113
* Availability: R, C
114
*
115
* @var boolean
116
*/
117
public $maintain_ratio = TRUE;
118
119
/**
120
* Specifies what to use as the master axis when resizing or creating thumbs.
121
* For example, let's say you want to resize an image to 100 X 75 pixels.
122
* If the source image size does not allow perfect resizing to those dimensions,
123
* this setting determines which axis should be used as the hard value.
124
* "auto" sets the axis automatically based on whether the image is taller then wider, or vice versa.
125
*
126
* auto, height, or width. Determines what to use as the master dimension
127
*
128
* Availability: R
129
*
130
* @var string
131
*/
132
public $master_dim = 'auto';
133
134
/**
135
* Specifies the angle of rotation when rotating images.
136
* Note that PHP rotates counter-clockwise,
137
* so a 90 degree rotation to the right must be specified as 270.
138
*
139
* Availability: X
140
*
141
* @var string
142
*/
143
public $rotation_angle = '';
144
145
/**
146
* Sets the X coordinate in pixels for image cropping.
147
* For example, a setting of 30 will crop an image 30 pixels from the left.
148
*
149
* Availability: C
150
*
151
* @var string
152
*/
153
public $x_axis = '';
154
155
/**
156
* Sets the Y coordinate in pixels for image cropping.
157
* For example, a setting of 30 will crop an image 30 pixels from the top.
158
*
159
* Availability: C
160
*
161
* @var string
162
*/
163
public $y_axis = '';
164
165
// Watermark Vars
166
167
/**
168
* The text you would like shown as the watermark.
169
* Typically this will be a copyright notice.
170
*
171
* @var string
172
*/
173
public $wm_text = '';
174
175
/**
176
* Sets the type of watermarking that should be used.
177
* Options: text/overlay
178
*
179
* @var string
180
*/
181
public $wm_type = 'text';
182
183
/**
184
* If your watermark image is a PNG or GIF image,
185
* you may specify a color on the image to be "transparent".
186
* This setting (along with the next) will allow you to specify that color.
187
* This works by specifying the "X" and "Y" coordinate pixel (measured from the upper left)
188
* within the image that corresponds to a pixel representative of the color you want to be transparent.
189
*
190
* @var integer
191
*/
192
public $wm_x_transp = 4;
193
194
/**
195
* Along with the previous setting, this allows you to specify the coordinate
196
* to a pixel representative of the color you want to be transparent.
197
*
198
* @var integer
199
*/
200
public $wm_y_transp = 4;
201
202
/**
203
* The server path to the image you wish to use as your watermark.
204
* Required only if you are using the overlay method.
205
*
206
* @var string
207
*/
208
public $wm_overlay_path = '';
209
210
/**
211
* The server path to the True Type Font you would like to use.
212
* If you do not use this option, the native GD font will be used.
213
*
214
* @var string
215
*/
216
public $wm_font_path = '';
217
218
/**
219
* The size of the text. Note: If you are not using the True Type option above,
220
* the number is set using a range of 1 - 5.
221
* Otherwise, you can use any valid pixel size for the font you're using.
222
*
223
* @var integer
224
*/
225
public $wm_font_size = 17;
226
227
/**
228
* Sets the vertical alignment for the watermark image.
229
* Vertical alignment: T M B
230
*
231
* @var string
232
*/
233
public $wm_vrt_alignment = 'B';
234
235
/**
236
* Sets the horizontal alignment for the watermark image.
237
* Horizontal alignment: L R C
238
*
239
* @var string
240
*/
241
public $wm_hor_alignment = 'C';
242
243
/**
244
* The amount of padding around text, set in pixels,
245
* that will be applied to the watermark to set it away from the edge of your images.
246
*
247
* @var integer
248
*/
249
public $wm_padding = 0;
250
251
/**
252
* You may specify a horizontal offset (in pixels) to apply to the watermark position.
253
* The offset normally moves the watermark to the right, except if you have your alignment
254
* set to "right" then your offset value will move the watermark toward the left of the image.
255
*
256
* @var integer
257
*/
258
public $wm_hor_offset = 0;
259
260
/**
261
* You may specify a vertical offset (in pixels) to apply to the watermark position.
262
* The offset normally moves the watermark down, except if you have your alignment
263
* set to "bottom" then your offset value will move the watermark toward the top of the image.
264
*
265
* @var integer
266
*/
267
public $wm_vrt_offset = 0;
268
269
/**
270
* The font color, specified in hex.
271
* Note, you must use the full 6 character hex value (ie, 993300),
272
* rather than the three character abbreviated version (ie fff).
273
*
274
* @var string
275
*/
276
public $wm_font_color = '#ffffff';
277
278
/**
279
* The color of the drop shadow, specified in hex.
280
* If you leave this blank a drop shadow will not be used.
281
* Note, you must use the full 6 character hex value (ie, 993300),
282
* rather than the three character abbreviated version (ie fff).
283
*
284
* @var string
285
*/
286
public $wm_shadow_color = '';
287
288
/**
289
* The distance (in pixels) from the font that the drop shadow should appear.
290
*
291
* @var integer
292
*/
293
public $wm_shadow_distance = 2;
294
295
/**
296
* Image opacity. You may specify the opacity (i.e. transparency) of your watermark image.
297
* This allows the watermark to be faint and not completely obscure the details
298
* from the original image behind it. A 50% opacity is typical.
299
* Image opacity: 1 - 100 Only works with image
300
*
301
* @var integer
302
*/
303
public $wm_opacity = 50;
304
305
// Private Vars
306
private $source_folder = '';
307
private $dest_folder = '';
308
private $mime_type = '';
309
private $orig_width = '';
310
private $orig_height = '';
311
private $image_type = '';
312
private $size_str = '';
313
private $full_src_path = '';
314
private $full_dst_path = '';
315
private $create_fnc = 'imagecreatetruecolor';
316
private $copy_fnc = 'imagecopyresampled';
317
private $wm_use_drop_shadow = FALSE;
318
private $wm_use_truetype = FALSE;
319
320
321
/**
322
* All the pre defined error messages
323
*
324
* @var array
325
*/
326
private $_error_messages = array();
327
328
/**
329
* The errors caputered to display
330
*
331
* @var array
332
*/
333
private $_error_msg_to_display= array();
334
335
/**
336
* Constructor
337
*
338
* @param string
339
* @return void
340
*/
341
public function __construct(array $config = NULL) {
342
if (count($config) > 0) {
343
$default_vars = array(
344
'image_library_to_use' => '',
345
'library_path' => '',
346
'dynamic_output' => FALSE,
347
'source_image' => '',
348
'new_image' => '',
349
'width' => '',
350
'height' => '',
351
'quality' => '',
352
'create_thumb' => FALSE,
353
'thumb_marker' => '_thumb',
354
'maintain_ratio' => TRUE,
355
'master_dim' => 'auto',
356
'rotation_angle' => '',
357
'x_axis' => '',
358
'y_axis' => '',
359
'wm_text' => '',
360
'wm_type' => '',
361
'wm_x_transp' => 4,
362
'wm_y_transp' => 4,
363
'wm_overlay_path' => '',
364
'wm_font_path' => '',
365
'wm_font_size' => 17,
366
'wm_vrt_alignment' => 'B',
367
'wm_hor_alignment' => 'C',
368
'wm_padding' => 0,
369
'wm_hor_offset' => 0,
370
'wm_vrt_offset' => 0,
371
'wm_font_color' => '#ffffff',
372
'wm_shadow_color' => '',
373
'wm_shadow_distance' => 2,
374
'wm_opacity' => 50
375
);
376
377
foreach ($default_vars as $key => $val) {
378
if (isset($config[$key])) {
379
$this->$key = $config[$key];
380
}
381
}
382
}
383
384
$lang = array(
385
'en/us' => array(
386
'source_image_required' => "You must specify a source image in your preferences.",
387
'gd_required' => "The GD image library is required for this feature.",
388
'gd_required_for_props' => "Your server must support the GD image library in order to determine the image properties.",
389
'unsupported_imagecreate' => "Your server does not support the GD function required to process this type of image.",
390
'gif_not_supported' => "GIF images are often not supported due to licensing restrictions. You may have to use JPG or PNG images instead.",
391
'jpg_not_supported' => "JPG images are not supported.",
392
'png_not_supported' => "PNG images are not supported.",
393
'jpg_or_png_required' => "The image resize protocol specified in your preferences only works with JPEG or PNG image types.",
394
'copy_error' => "An error was encountered while attempting to replace the file. Please make sure your file directory is writable.",
395
'rotate_unsupported' => "Image rotation does not appear to be supported by your server.",
396
'libpath_invalid' => "The path to your image library is not correct. Please set the correct path in your image preferences.",
397
'image_process_failed' => "Image processing failed. Please verify that your server supports the chosen protocol and that the path to your image library is correct.",
398
'rotation_angle_required' => "An angle of rotation is required to rotate the image.",
399
'writing_failed_gif' => "GIF image.",
400
'invalid_path' => "The path to the image is not correct.",
401
'copy_failed' => "The image copy routine failed.",
402
'missing_font' => "Unable to find a font to use.",
403
'save_failed' => "Unable to save the image. Please make sure the image and file directory are writable."
404
),
405
406
'zh/cn' => array(
407
'source_image_required' => "必须制定图片",
408
'gd_required' => "需要GD类来实现这个功能",
409
'gd_required_for_props' => "为了决定图片属性你的服务器必须支持GD图片库",
410
'unsupported_imagecreate' => "你的服务器不支持GD类的函数来实现此功能",
411
'gif_not_supported' => "GIF images are often not supported due to licensing restrictions. You may have to use JPG or PNG images instead.",
412
'jpg_not_supported' => "不支持JPG格式图片",
413
'png_not_supported' => "不支持PNG格式图片",
414
'jpg_or_png_required' => "The image resize protocol specified in your preferences only works with JPEG or PNG image types.",
415
'copy_error' => "An error was encountered while attempting to replace the file. Please make sure your file directory is writable.",
416
'rotate_unsupported' => "你的服务器不支持图片旋转",
417
'libpath_invalid' => "图片库路径不正确,请检查",
418
'image_process_failed' => "图片处理失败 Please verify that your server supports the chosen protocol and that the path to your image library is correct.",
419
'rotation_angle_required' => "必须制定旋转角度来完成图片旋转",
420
'writing_failed_gif' => "GIF image.",
421
'invalid_path' => "无效的图片路径",
422
'copy_failed' => "复制图片失败",
423
'missing_font' => "找不到能用的字体",
424
'save_failed' => "无法保存图片,请确保图片和文件目录可写"
425
),
426
);
427
428
$this->_error_messages = (isset($config['lang']) && array_key_exists($config['lang'], $lang))
429
? $lang[$config['lang']]
430
: $lang['en/us'];
431
432
433
// Check image preferences
434
$this->_init();
435
}
436
437
438
/**
439
* Check image preferences
440
*
441
* @access private
442
* @param array
443
* @return bool
444
*/
445
private function _init() {
446
// Is there a source image? If not, there's no reason to continue
447
if ($this->source_image == '') {
448
$this->_set_error('source_image_required');
449
return FALSE;
450
}
451
452
// Is getimagesize() Available?
453
// We use it to determine the image properties (width/height).
454
// Note: We need to figure out how to determine image
455
// properties using ImageMagick and NetPBM
456
if ( ! function_exists('getimagesize')) {
457
$this->_set_error('gd_required_for_props');
458
return FALSE;
459
}
460
461
$this->image_library_to_use = strtolower($this->image_library_to_use);
462
463
// Set the full server path
464
// The source image may or may not contain a path.
465
// Either way, we'll try use realpath to generate the
466
// full server path in order to more reliably read it.
467
if (function_exists('realpath') && @realpath($this->source_image) !== FALSE) {
468
$full_source_path = str_replace("\\", "/", realpath($this->source_image));
469
} else {
470
$full_source_path = $this->source_image;
471
}
472
473
$x = explode('/', $full_source_path);
474
$this->source_image = end($x);
475
$this->source_folder = str_replace($this->source_image, '', $full_source_path);
476
477
// Set the Image Properties
478
if ( ! $this->_get_image_properties($this->source_folder.$this->source_image)) {
479
return FALSE;
480
}
481
482
// Assign the "new" image name/path
483
// If the user has set a "new_image" name it means
484
// we are making a copy of the source image. If not
485
// it means we are altering the original.
486
// We'll set the destination filename and path accordingly.
487
if ($this->new_image == '') {
488
$this->dest_image = $this->source_image;
489
$this->dest_folder = $this->source_folder;
490
} else {
491
if (strpos($this->new_image, '/') === FALSE) {
492
$this->dest_folder = $this->source_folder;
493
$this->dest_image = $this->new_image;
494
} else {
495
if (function_exists('realpath') && @realpath($this->new_image) !== FALSE) {
496
$full_dest_path = str_replace("\\", "/", realpath($this->new_image));
497
} else {
498
$full_dest_path = $this->new_image;
499
}
500
501
// Is there a file name?
502
if ( ! preg_match("#\.(jpg|jpeg|gif|png)$#i", $full_dest_path)) {
503
$this->dest_folder = $full_dest_path.'/';
504
$this->dest_image = $this->source_image;
505
} else {
506
$x = explode('/', $full_dest_path);
507
$this->dest_image = end($x);
508
$this->dest_folder = str_replace($this->dest_image, '', $full_dest_path);
509
}
510
}
511
}
512
513
// Compile the finalized filenames/paths
514
// We'll create two master strings containing the
515
// full server path to the source image and the
516
// full server path to the destination image.
517
// We'll also split the destination image name
518
// so we can insert the thumbnail marker if needed.
519
if ($this->create_thumb === FALSE || $this->thumb_marker == '') {
520
$this->thumb_marker = '';
521
}
522
523
$xp = $this->_explode_name($this->dest_image);
524
525
$filename = $xp['name'];
526
$file_ext = $xp['ext'];
527
528
$this->full_src_path = $this->source_folder.$this->source_image;
529
$this->full_dst_path = $this->dest_folder.$filename.$this->thumb_marker.$file_ext;
530
531
// Should we maintain image proportions?
532
// When creating thumbs or copies, the target width/height
533
// might not be in correct proportion with the source
534
// image's width/height. We'll recalculate it here.
535
if ($this->maintain_ratio === TRUE && ($this->width != '' && $this->height != '')) {
536
$this->_image_reproportion();
537
}
538
539
// Was a width and height specified?
540
// If the destination width/height was
541
// not submitted we will use the values
542
// from the actual file
543
if ($this->width == '') {
544
$this->width = $this->orig_width;
545
}
546
547
if ($this->height == '') {
548
$this->height = $this->orig_height;
549
}
550
551
// Set the quality
552
$this->quality = trim(str_replace("%", "", $this->quality));
553
554
if ($this->quality == '' || $this->quality == 0 || ! is_numeric($this->quality)) {
555
$this->quality = 90;
556
}
557
558
// Set the x/y coordinates
559
$this->x_axis = ($this->x_axis == '' || ! is_numeric($this->x_axis)) ? 0 : $this->x_axis;
560
$this->y_axis = ($this->y_axis == '' || ! is_numeric($this->y_axis)) ? 0 : $this->y_axis;
561
562
// Watermark-related Stuff...
563
if ($this->wm_font_color != '') {
564
if (strlen($this->wm_font_color) == 6) {
565
$this->wm_font_color = '#'.$this->wm_font_color;
566
}
567
}
568
569
if ($this->wm_shadow_color != '') {
570
if (strlen($this->wm_shadow_color) == 6) {
571
$this->wm_shadow_color = '#'.$this->wm_shadow_color;
572
}
573
}
574
575
if ($this->wm_overlay_path != '') {
576
$this->wm_overlay_path = str_replace("\\", "/", realpath($this->wm_overlay_path));
577
}
578
579
if ($this->wm_shadow_color != '') {
580
$this->wm_use_drop_shadow = TRUE;
581
}
582
583
if ($this->wm_font_path != '') {
584
$this->wm_use_truetype = TRUE;
585
}
586
587
return TRUE;
588
}
589
590
591
/**
592
* Resets values in case this class is used in a loop
593
*
594
* @access public
595
* @return void
596
*/
597
public function clear() {
598
$props = array('source_folder', 'dest_folder', 'source_image', 'full_src_path', 'full_dst_path', 'new_image', 'image_type', 'size_str', 'quality', 'orig_width', 'orig_height', 'rotation_angle', 'x_axis', 'y_axis', 'create_fnc', 'copy_fnc', 'wm_overlay_path', 'wm_use_truetype', 'dynamic_output', 'wm_font_size', 'wm_text', 'wm_vrt_alignment', 'wm_hor_alignment', 'wm_padding', 'wm_hor_offset', 'wm_vrt_offset', 'wm_font_color', 'wm_use_drop_shadow', 'wm_shadow_color', 'wm_shadow_distance', 'wm_opacity');
599
600
foreach ($props as $val) {
601
$this->$val = '';
602
}
603
604
// special consideration for master_dim
605
$this->master_dim = 'auto';
606
}
607
608
609
/**
610
* Image Resize: R
611
*
612
* This is a wrapper function that chooses the proper
613
* resize function based on the protocol specified
614
*
615
* @access public
616
* @return bool
617
*/
618
public function resize() {
619
$protocol = '_image_process_'.$this->image_library_to_use;
620
621
if (preg_match('/gd2$/i', $protocol)) {
622
$protocol = '_image_process_gd';
623
}
624
625
return $this->$protocol('resize');
626
}
627
628
629
/**
630
* Image Crop: C
631
*
632
* This is a wrapper function that chooses the proper
633
* cropping function based on the protocol specified
634
*
635
* @access public
636
* @return bool
637
*/
638
public function crop() {
639
$protocol = '_image_process_'.$this->image_library_to_use;
640
641
if (preg_match('/gd2$/i', $protocol)) {
642
$protocol = '_image_process_gd';
643
}
644
645
return $this->$protocol('crop');
646
}
647
648
649
/**
650
* Image Rotate: X
651
*
652
* This is a wrapper function that chooses the proper
653
* rotation function based on the protocol specified
654
*
655
* @access public
656
* @return bool
657
*/
658
public function rotate() {
659
// Allowed rotation values
660
$degs = array(90, 180, 270, 'vrt', 'hor');
661
662
if ($this->rotation_angle == '' || ! in_array($this->rotation_angle, $degs)) {
663
$this->_set_error('rotation_angle_required');
664
return FALSE;
665
}
666
667
// Reassign the width and height
668
if ($this->rotation_angle == 90 || $this->rotation_angle == 270) {
669
$this->width = $this->orig_height;
670
$this->height = $this->orig_width;
671
} else {
672
$this->width = $this->orig_width;
673
$this->height = $this->orig_height;
674
}
675
676
677
// Choose resizing function
678
if ($this->image_library_to_use == 'imagemagick' || $this->image_library_to_use == 'netpbm') {
679
$protocol = '_image_process_'.$this->image_library_to_use;
680
681
return $this->$protocol('rotate');
682
}
683
684
if ($this->rotation_angle == 'hor' || $this->rotation_angle == 'vrt') {
685
return $this->_image_mirror_gd();
686
} else {
687
return $this->_image_rotate_gd();
688
}
689
}
690
691
692
/**
693
* Image Process Using GD/GD2
694
*
695
* This function will resize or crop
696
*
697
* @param string
698
* @return bool
699
*/
700
private function _image_process_gd($action = 'resize') {
701
$v2_override = FALSE;
702
703
// If the target width/height match the source, AND if the new file name is not equal to the old file name
704
// we'll simply make a copy of the original with the new name... assuming dynamic rendering is off.
705
if ($this->dynamic_output === FALSE) {
706
if ($this->orig_width == $this->width && $this->orig_height == $this->height) {
707
if ($this->source_image != $this->new_image) {
708
if (@copy($this->full_src_path, $this->full_dst_path)) {
709
@chmod($this->full_dst_path, 0666);
710
}
711
}
712
713
return TRUE;
714
}
715
}
716
717
// Let's set up our values based on the action
718
if ($action == 'crop') {
719
// Reassign the source width/height if cropping
720
$this->orig_width = $this->width;
721
$this->orig_height = $this->height;
722
723
// GD 2.0 has a cropping bug so we'll test for it
724
if ($this->_gd_version() !== FALSE) {
725
$gd_version = str_replace('0', '', $this->_gd_version());
726
$v2_override = ($gd_version == 2) ? TRUE : FALSE;
727
}
728
} else {
729
// If resizing the x/y axis must be zero
730
$this->x_axis = 0;
731
$this->y_axis = 0;
732
}
733
734
// Create the image handle
735
if ( ! ($src_img = $this->_image_create_gd())) {
736
return FALSE;
737
}
738
739
// Create The Image
740
//
741
// old conditional which users report cause problems with shared GD libs who report themselves as "2.0 or greater"
742
// it appears that this is no longer the issue that it was in 2004, so we've removed it, retaining it in the comment
743
// below should that ever prove inaccurate.
744
//
745
// if ($this->image_library_to_use == 'gd2' AND function_exists('imagecreatetruecolor') AND $v2_override == FALSE)
746
if ($this->image_library_to_use == 'gd2' && function_exists('imagecreatetruecolor')) {
747
$create = 'imagecreatetruecolor';
748
$copy = 'imagecopyresampled';
749
} else {
750
$create = 'imagecreate';
751
$copy = 'imagecopyresized';
752
}
753
754
$dst_img = $create($this->width, $this->height);
755
756
// png we can actually preserve transparency
757
if ($this->image_type == 3) {
758
imagealphablending($dst_img, FALSE);
759
imagesavealpha($dst_img, TRUE);
760
}
761
762
$copy($dst_img, $src_img, 0, 0, $this->x_axis, $this->y_axis, $this->width, $this->height, $this->orig_width, $this->orig_height);
763
764
// Show the image
765
if ($this->dynamic_output == TRUE) {
766
$this->_image_display_gd($dst_img);
767
} else {
768
// Or save it
769
if ( ! $this->_image_save_gd($dst_img)) {
770
return FALSE;
771
}
772
}
773
774
// Kill the file handles
775
imagedestroy($dst_img);
776
imagedestroy($src_img);
777
778
// Set the file to 777
779
@chmod($this->full_dst_path, 0666);
780
781
return TRUE;
782
}
783
784
785
/**
786
* Image Process Using ImageMagick
787
*
788
* This function will resize, crop or rotate
789
*
790
* @param string
791
* @return bool
792
*/
793
private function _image_process_imagemagick($action = 'resize') {
794
// Do we have a vaild library path?
795
if ($this->library_path == '') {
796
$this->_set_error('libpath_invalid');
797
return FALSE;
798
}
799
800
if ( ! preg_match("/convert$/i", $this->library_path)) {
801
$this->library_path = rtrim($this->library_path, '/').'/';
802
$this->library_path .= 'convert';
803
}
804
805
// Execute the command
806
$cmd = $this->library_path." -quality ".$this->quality;
807
808
if ($action == 'crop') {
809
$cmd .= " -crop ".$this->width."x".$this->height."+".$this->x_axis."+".$this->y_axis." \"$this->full_src_path\" \"$this->full_dst_path\" 2>&1";
810
} elseif ($action == 'rotate') {
811
switch ($this->rotation_angle) {
812
case 'hor' :
813
$angle = '-flop';
814
break;
815
816
case 'vrt' :
817
$angle = '-flip';
818
break;
819
820
default :
821
$angle = '-rotate '.$this->rotation_angle;
822
break;
823
}
824
825
$cmd .= " ".$angle." \"$this->full_src_path\" \"$this->full_dst_path\" 2>&1";
826
} else {
827
// Resize
828
$cmd .= " -resize ".$this->width."x".$this->height." \"$this->full_src_path\" \"$this->full_dst_path\" 2>&1";
829
}
830
831
$retval = 1;
832
833
@exec($cmd, $output, $retval);
834
835
// Did it work?
836
if ($retval > 0) {
837
$this->_set_error('image_process_failed');
838
return FALSE;
839
}
840
841
// Set the file to 777
842
@chmod($this->full_dst_path, 0666);
843
844
return TRUE;
845
}
846
847
848
/**
849
* Image Process Using NetPBM
850
*
851
* This function will resize, crop or rotate
852
*
853
* @param string
854
* @return bool
855
*/
856
private function _image_process_netpbm($action = 'resize') {
857
if ($this->library_path == '') {
858
$this->_set_error('imglib_libpath_invalid');
859
return FALSE;
860
}
861
862
// Build the resizing command
863
switch ($this->image_type) {
864
case 1 :
865
$cmd_in = 'giftopnm';
866
$cmd_out = 'ppmtogif';
867
break;
868
869
case 2 :
870
$cmd_in = 'jpegtopnm';
871
$cmd_out = 'ppmtojpeg';
872
break;
873
874
case 3 :
875
$cmd_in = 'pngtopnm';
876
$cmd_out = 'ppmtopng';
877
break;
878
}
879
880
if ($action == 'crop') {
881
$cmd_inner = 'pnmcut -left '.$this->x_axis.' -top '.$this->y_axis.' -width '.$this->width.' -height '.$this->height;
882
} elseif ($action == 'rotate') {
883
switch ($this->rotation_angle) {
884
case 90 :
885
$angle = 'r270';
886
break;
887
888
case 180 :
889
$angle = 'r180';
890
break;
891
892
case 270 :
893
$angle = 'r90';
894
break;
895
896
case 'vrt' :
897
$angle = 'tb';
898
break;
899
900
case 'hor' :
901
$angle = 'lr';
902
break;
903
}
904
905
$cmd_inner = 'pnmflip -'.$angle.' ';
906
} else {
907
// Resize
908
$cmd_inner = 'pnmscale -xysize '.$this->width.' '.$this->height;
909
}
910
911
$cmd = $this->library_path.$cmd_in.' '.$this->full_src_path.' | '.$cmd_inner.' | '.$cmd_out.' > '.$this->dest_folder.'netpbm.tmp';
912
913
$retval = 1;
914
915
@exec($cmd, $output, $retval);
916
917
// Did it work?
918
if ($retval > 0) {
919
$this->_set_error('image_process_failed');
920
return FALSE;
921
}
922
923
// With NetPBM we have to create a temporary image.
924
// If you try manipulating the original it fails so
925
// we have to rename the temp file.
926
copy ($this->dest_folder.'netpbm.tmp', $this->full_dst_path);
927
unlink ($this->dest_folder.'netpbm.tmp');
928
@chmod($this->full_dst_path, 0666);
929
930
return TRUE;
931
}
932
933
934
/**
935
* Image Rotate Using GD
936
*
937
* @return bool
938
*/
939
private function _image_rotate_gd() {
940
// Create the image handle
941
if ( ! ($src_img = $this->_image_create_gd())) {
942
return FALSE;
943
}
944
945
// Set the background color
946
// This won't work with transparent PNG files so we are
947
// going to have to figure out how to determine the color
948
// of the alpha channel in a future release.
949
950
$white = imagecolorallocate($src_img, 255, 255, 255);
951
952
// Rotate it!
953
$dst_img = imagerotate($src_img, $this->rotation_angle, $white);
954
955
// Save the Image
956
if ($this->dynamic_output == TRUE) {
957
$this->_image_display_gd($dst_img);
958
} else {
959
// Or save it
960
if ( ! $this->_image_save_gd($dst_img)) {
961
return FALSE;
962
}
963
}
964
965
// Kill the file handles
966
imagedestroy($dst_img);
967
imagedestroy($src_img);
968
969
// Set the file to 777
970
971
@chmod($this->full_dst_path, 0666);
972
973
return TRUE;
974
}
975
976
977
/**
978
* Create Mirror Image using GD
979
*
980
* This function will flip horizontal or vertical
981
*
982
* @return bool
983
*/
984
private function _image_mirror_gd() {
985
if ( ! $src_img = $this->_image_create_gd()) {
986
return FALSE;
987
}
988
989
$width = $this->orig_width;
990
$height = $this->orig_height;
991
992
if ($this->rotation_angle == 'hor') {
993
for ($i = 0; $i < $height; $i++) {
994
$left = 0;
995
$right = $width-1;
996
997
while ($left < $right) {
998
$cl = imagecolorat($src_img, $left, $i);
999
$cr = imagecolorat($src_img, $right, $i);
1000
1001
imagesetpixel($src_img, $left, $i, $cr);
1002
imagesetpixel($src_img, $right, $i, $cl);
1003
1004
$left++;
1005
$right--;
1006
}
1007
}
1008
} else {
1009
for ($i = 0; $i < $width; $i++) {
1010
$top = 0;
1011
$bot = $height-1;
1012
1013
while ($top < $bot) {
1014
$ct = imagecolorat($src_img, $i, $top);
1015
$cb = imagecolorat($src_img, $i, $bot);
1016
1017
imagesetpixel($src_img, $i, $top, $cb);
1018
imagesetpixel($src_img, $i, $bot, $ct);
1019
1020
$top++;
1021
$bot--;
1022
}
1023
}
1024
}
1025
1026
// Show the image
1027
if ($this->dynamic_output == TRUE) {
1028
$this->_image_display_gd($src_img);
1029
} else {
1030
// Or save it
1031
if ( ! $this->_image_save_gd($src_img)) {
1032
return FALSE;
1033
}
1034
}
1035
1036
// Kill the file handles
1037
imagedestroy($src_img);
1038
1039
// Set the file to 777
1040
@chmod($this->full_dst_path, 0666);
1041
1042
return TRUE;
1043
}
1044
1045
1046
/**
1047
* Image Watermark: W
1048
*
1049
* This is a wrapper function that chooses the type
1050
* of watermarking based on the specified preference.
1051
*
1052
* @access public
1053
* @param string
1054
* @return bool
1055
*/
1056
public function watermark() {
1057
if ($this->wm_type == 'overlay') {
1058
return $this->_overlay_watermark();
1059
} else {
1060
return $this->_text_watermark();
1061
}
1062
}
1063
1064
1065
/**
1066
* Watermark - Graphic Version
1067
*
1068
* @return bool
1069
*/
1070
private function _overlay_watermark() {
1071
if ( ! function_exists('imagecolortransparent')) {
1072
$this->_set_error('gd_required');
1073
return FALSE;
1074
}
1075
1076
// Fetch source image properties
1077
$this->_get_image_properties();
1078
1079
// Fetch watermark image properties
1080
$props = $this->_get_image_properties($this->wm_overlay_path, TRUE);
1081
$wm_img_type = $props['image_type'];
1082
$wm_width = $props['width'];
1083
$wm_height = $props['height'];
1084
1085
// Create two image resources
1086
$wm_img = $this->_image_create_gd($this->wm_overlay_path, $wm_img_type);
1087
$src_img = $this->_image_create_gd($this->full_src_path);
1088
1089
// Reverse the offset if necessary
1090
// When the image is positioned at the bottom
1091
// we don't want the vertical offset to push it
1092
// further down. We want the reverse, so we'll
1093
// invert the offset. Same with the horizontal
1094
// offset when the image is at the right
1095
1096
$this->wm_vrt_alignment = strtoupper(substr($this->wm_vrt_alignment, 0, 1));
1097
$this->wm_hor_alignment = strtoupper(substr($this->wm_hor_alignment, 0, 1));
1098
1099
if ($this->wm_vrt_alignment == 'B') {
1100
$this->wm_vrt_offset = $this->wm_vrt_offset * -1;
1101
}
1102
1103
if ($this->wm_hor_alignment == 'R') {
1104
$this->wm_hor_offset = $this->wm_hor_offset * -1;
1105
}
1106
1107
// Set the base x and y axis values
1108
$x_axis = $this->wm_hor_offset + $this->wm_padding;
1109
$y_axis = $this->wm_vrt_offset + $this->wm_padding;
1110
1111
// Set the vertical position
1112
switch ($this->wm_vrt_alignment) {
1113
case 'T':
1114
break;
1115
1116
case 'M':
1117
$y_axis += ($this->orig_height / 2) - ($wm_height / 2);
1118
break;
1119
1120
case 'B':
1121
$y_axis += $this->orig_height - $wm_height;
1122
break;
1123
}
1124
1125
// Set the horizontal position
1126
switch ($this->wm_hor_alignment) {
1127
case 'L':
1128
break;
1129
1130
case 'C':
1131
$x_axis += ($this->orig_width / 2) - ($wm_width / 2);
1132
break;
1133
1134
case 'R':
1135
$x_axis += $this->orig_width - $wm_width;
1136
break;
1137
}
1138
1139
// Build the finalized image
1140
if ($wm_img_type == 3 && function_exists('imagealphablending')) {
1141
@imagealphablending($src_img, TRUE);
1142
}
1143
1144
// Set RGB values for text and shadow
1145
$rgba = imagecolorat($wm_img, $this->wm_x_transp, $this->wm_y_transp);
1146
$alpha = ($rgba & 0x7F000000) >> 24;
1147
1148
// make a best guess as to whether we're dealing with an image with alpha transparency or no/binary transparency
1149
if ($alpha > 0) {
1150
// copy the image directly, the image's alpha transparency being the sole determinant of blending
1151
imagecopy($src_img, $wm_img, $x_axis, $y_axis, 0, 0, $wm_width, $wm_height);
1152
} else {
1153
// set our RGB value from above to be transparent and merge the images with the specified opacity
1154
imagecolortransparent($wm_img, imagecolorat($wm_img, $this->wm_x_transp, $this->wm_y_transp));
1155
imagecopymerge($src_img, $wm_img, $x_axis, $y_axis, 0, 0, $wm_width, $wm_height, $this->wm_opacity);
1156
}
1157
1158
// Output the image
1159
if ($this->dynamic_output == TRUE) {
1160
$this->_image_display_gd($src_img);
1161
} else {
1162
if ( ! $this->_image_save_gd($src_img)) {
1163
return FALSE;
1164
}
1165
}
1166
1167
imagedestroy($src_img);
1168
imagedestroy($wm_img);
1169
1170
return TRUE;
1171
}
1172
1173
1174
/**
1175
* Watermark - Text Version
1176
*
1177
* @return bool
1178
*/
1179
private function _text_watermark() {
1180
if ( ! ($src_img = $this->_image_create_gd())) {
1181
return FALSE;
1182
}
1183
1184
if ($this->wm_use_truetype == TRUE && ! file_exists($this->wm_font_path)) {
1185
$this->_set_error('missing_font');
1186
return FALSE;
1187
}
1188
1189
// Fetch source image properties
1190
$this->_get_image_properties();
1191
1192
// Set RGB values for text and shadow
1193
$this->wm_font_color = str_replace('#', '', $this->wm_font_color);
1194
$this->wm_shadow_color = str_replace('#', '', $this->wm_shadow_color);
1195
1196
$R1 = hexdec(substr($this->wm_font_color, 0, 2));
1197
$G1 = hexdec(substr($this->wm_font_color, 2, 2));
1198
$B1 = hexdec(substr($this->wm_font_color, 4, 2));
1199
1200
$R2 = hexdec(substr($this->wm_shadow_color, 0, 2));
1201
$G2 = hexdec(substr($this->wm_shadow_color, 2, 2));
1202
$B2 = hexdec(substr($this->wm_shadow_color, 4, 2));
1203
1204
$txt_color = imagecolorclosest($src_img, $R1, $G1, $B1);
1205
$drp_color = imagecolorclosest($src_img, $R2, $G2, $B2);
1206
1207
// Reverse the vertical offset
1208
// When the image is positioned at the bottom
1209
// we don't want the vertical offset to push it
1210
// further down. We want the reverse, so we'll
1211
// invert the offset. Note: The horizontal
1212
// offset flips itself automatically
1213
1214
if ($this->wm_vrt_alignment == 'B') {
1215
$this->wm_vrt_offset = $this->wm_vrt_offset * -1;
1216
}
1217
1218
if ($this->wm_hor_alignment == 'R') {
1219
$this->wm_hor_offset = $this->wm_hor_offset * -1;
1220
}
1221
// Set font width and height
1222
// These are calculated differently depending on
1223
// whether we are using the true type font or not
1224
if ($this->wm_use_truetype == TRUE) {
1225
if ($this->wm_font_size == '') {
1226
$this->wm_font_size = '17';
1227
}
1228
$fontwidth = $this->wm_font_size-($this->wm_font_size/4);
1229
$fontheight = $this->wm_font_size;
1230
$this->wm_vrt_offset += $this->wm_font_size;
1231
} else {
1232
$fontwidth = imagefontwidth($this->wm_font_size);
1233
$fontheight = imagefontheight($this->wm_font_size);
1234
}
1235
1236
// Set base X and Y axis values
1237
$x_axis = $this->wm_hor_offset + $this->wm_padding;
1238
$y_axis = $this->wm_vrt_offset + $this->wm_padding;
1239
1240
// Set verticle alignment
1241
if ($this->wm_use_drop_shadow == FALSE) {
1242
$this->wm_shadow_distance = 0;
1243
}
1244
$this->wm_vrt_alignment = strtoupper(substr($this->wm_vrt_alignment, 0, 1));
1245
$this->wm_hor_alignment = strtoupper(substr($this->wm_hor_alignment, 0, 1));
1246
1247
switch ($this->wm_vrt_alignment) {
1248
case "T" :
1249
break;
1250
1251
case "M":
1252
$y_axis += ($this->orig_height/2)+($fontheight/2);
1253
break;
1254
1255
case "B":
1256
$y_axis += ($this->orig_height - $fontheight - $this->wm_shadow_distance - ($fontheight/2));
1257
break;
1258
}
1259
1260
$x_shad = $x_axis + $this->wm_shadow_distance;
1261
$y_shad = $y_axis + $this->wm_shadow_distance;
1262
1263
// Set horizontal alignment
1264
switch ($this->wm_hor_alignment) {
1265
case "L":
1266
break;
1267
1268
case "R":
1269
if ($this->wm_use_drop_shadow) {
1270
$x_shad += ($this->orig_width - $fontwidth*strlen($this->wm_text));
1271
}
1272
$x_axis += ($this->orig_width - $fontwidth*strlen($this->wm_text));
1273
break;
1274
1275
case "C":
1276
if ($this->wm_use_drop_shadow) {
1277
$x_shad += floor(($this->orig_width - $fontwidth*strlen($this->wm_text))/2);
1278
}
1279
$x_axis += floor(($this->orig_width -$fontwidth*strlen($this->wm_text))/2);
1280
break;
1281
}
1282
1283
// Add the text to the source image
1284
if ($this->wm_use_truetype) {
1285
if ($this->wm_use_drop_shadow) {
1286
imagettftext($src_img, $this->wm_font_size, 0, $x_shad, $y_shad, $drp_color, $this->wm_font_path, $this->wm_text);
1287
}
1288
imagettftext($src_img, $this->wm_font_size, 0, $x_axis, $y_axis, $txt_color, $this->wm_font_path, $this->wm_text);
1289
} else {
1290
if ($this->wm_use_drop_shadow) {
1291
imagestring($src_img, $this->wm_font_size, $x_shad, $y_shad, $this->wm_text, $drp_color);
1292
}
1293
imagestring($src_img, $this->wm_font_size, $x_axis, $y_axis, $this->wm_text, $txt_color);
1294
}
1295
1296
// Output the final image
1297
if ($this->dynamic_output == TRUE) {
1298
$this->_image_display_gd($src_img);
1299
} else {
1300
$this->_image_save_gd($src_img);
1301
}
1302
1303
imagedestroy($src_img);
1304
1305
return TRUE;
1306
}
1307
1308
1309
/**
1310
* Create Image - GD
1311
*
1312
* This simply creates an image resource handle
1313
* based on the type of image being processed
1314
*
1315
* @param string
1316
* @return resource
1317
*/
1318
private function _image_create_gd($path = '', $image_type = '') {
1319
if ($path == '') {
1320
$path = $this->full_src_path;
1321
}
1322
1323
if ($image_type == '') {
1324
$image_type = $this->image_type;
1325
}
1326
1327
switch ($image_type) {
1328
case 1 :
1329
if ( ! function_exists('imagecreatefromgif')) {
1330
$this->_set_error(array('unsupported_imagecreate', 'gif_not_supported'));
1331
return FALSE;
1332
}
1333
1334
return imagecreatefromgif($path);
1335
break;
1336
1337
case 2 :
1338
if ( ! function_exists('imagecreatefromjpeg')) {
1339
$this->_set_error(array('unsupported_imagecreate', 'jpg_not_supported'));
1340
return FALSE;
1341
}
1342
1343
return imagecreatefromjpeg($path);
1344
break;
1345
1346
case 3 :
1347
if ( ! function_exists('imagecreatefrompng')) {
1348
$this->_set_error(array('unsupported_imagecreate', 'png_not_supported'));
1349
return FALSE;
1350
}
1351
1352
return imagecreatefrompng($path);
1353
break;
1354
1355
}
1356
1357
$this->_set_error(array('unsupported_imagecreate'));
1358
return FALSE;
1359
}
1360
1361
1362
/**
1363
* Write image file to disk - GD
1364
*
1365
* Takes an image resource as input and writes the file
1366
* to the specified destination
1367
*
1368
* @param resource
1369
* @return bool
1370
*/
1371
private function _image_save_gd($resource) {
1372
switch ($this->image_type) {
1373
case 1 :
1374
if ( ! function_exists('imagegif')) {
1375
$this->_set_error(array('unsupported_imagecreate', 'gif_not_supported'));
1376
return FALSE;
1377
}
1378
1379
if ( ! @imagegif($resource, $this->full_dst_path)) {
1380
$this->_set_error('save_failed');
1381
return FALSE;
1382
}
1383
break;
1384
1385
case 2 :
1386
if ( ! function_exists('imagejpeg')) {
1387
$this->_set_error(array('unsupported_imagecreate', 'jpg_not_supported'));
1388
return FALSE;
1389
}
1390
1391
if ( ! @imagejpeg($resource, $this->full_dst_path, $this->quality)) {
1392
$this->_set_error('save_failed');
1393
return FALSE;
1394
}
1395
break;
1396
1397
case 3 :
1398
if ( ! function_exists('imagepng')) {
1399
$this->_set_error(array('unsupported_imagecreate', 'png_not_supported'));
1400
return FALSE;
1401
}
1402
1403
if ( ! @imagepng($resource, $this->full_dst_path)) {
1404
$this->_set_error('save_failed');
1405
return FALSE;
1406
}
1407
break;
1408
1409
default :
1410
$this->_set_error(array('unsupported_imagecreate'));
1411
return FALSE;
1412
break;
1413
}
1414
1415
return TRUE;
1416
}
1417
1418
1419
/**
1420
* Dynamically outputs an image
1421
*
1422
* @param resource
1423
* @return void
1424
*/
1425
private function _image_display_gd($resource) {
1426
header("Content-Disposition: filename={$this->source_image};");
1427
header("Content-Type: {$this->mime_type}");
1428
header('Content-Transfer-Encoding: binary');
1429
header('Last-Modified: '.gmdate('D, d M Y H:i:s', time()).' GMT');
1430
1431
switch ($this->image_type) {
1432
case 1 :
1433
imagegif($resource);
1434
break;
1435
1436
case 2 :
1437
imagejpeg($resource, '', $this->quality);
1438
break;
1439
1440
case 3 :
1441
imagepng($resource);
1442
break;
1443
1444
default :
1445
echo 'Unable to display the image';
1446
break;
1447
}
1448
}
1449
1450
1451
/**
1452
* Re-proportion Image Width/Height
1453
*
1454
* When creating thumbs, the desired width/height
1455
* can end up warping the image due to an incorrect
1456
* ratio between the full-sized image and the thumb.
1457
*
1458
* This function lets us re-proportion the width/height
1459
* if users choose to maintain the aspect ratio when resizing.
1460
*
1461
* @return void
1462
*/
1463
private function _image_reproportion() {
1464
if ( ! is_numeric($this->width) || ! is_numeric($this->height) || $this->width == 0 || $this->height == 0) {
1465
return;
1466
}
1467
1468
if ( ! is_numeric($this->orig_width) || ! is_numeric($this->orig_height) || $this->orig_width == 0 || $this->orig_height == 0) {
1469
return;
1470
}
1471
1472
$new_width = ceil($this->orig_width*$this->height/$this->orig_height);
1473
$new_height = ceil($this->width*$this->orig_height/$this->orig_width);
1474
1475
$ratio = (($this->orig_height/$this->orig_width) - ($this->height/$this->width));
1476
1477
if ($this->master_dim != 'width' && $this->master_dim != 'height') {
1478
$this->master_dim = ($ratio < 0) ? 'width' : 'height';
1479
}
1480
1481
if (($this->width != $new_width) && ($this->height != $new_height)) {
1482
if ($this->master_dim == 'height') {
1483
$this->width = $new_width;
1484
} else {
1485
$this->height = $new_height;
1486
}
1487
}
1488
}
1489
1490
1491
/**
1492
* Get image properties
1493
*
1494
* A helper function that gets info about the file
1495
*
1496
* @param string
1497
* @return mixed
1498
*/
1499
private function _get_image_properties($path = '', $return = FALSE) {
1500
// For now we require GD but we should
1501
// find a way to determine this using IM or NetPBM
1502
1503
if ($path == '') {
1504
$path = $this->full_src_path;
1505
}
1506
1507
if ( ! file_exists($path)) {
1508
$this->_set_error('invalid_path');
1509
return FALSE;
1510
}
1511
1512
$vals = @getimagesize($path);
1513
1514
$types = array(1 => 'gif', 2 => 'jpeg', 3 => 'png');
1515
1516
$mime = (isset($types[$vals['2']])) ? 'image/'.$types[$vals['2']] : 'image/jpg';
1517
1518
if ($return == TRUE) {
1519
$v['width'] = $vals['0'];
1520
$v['height'] = $vals['1'];
1521
$v['image_type'] = $vals['2'];
1522
$v['size_str'] = $vals['3'];
1523
$v['mime_type'] = $mime;
1524
1525
return $v;
1526
}
1527
1528
$this->orig_width = $vals['0'];
1529
$this->orig_height = $vals['1'];
1530
$this->image_type = $vals['2'];
1531
$this->size_str = $vals['3'];
1532
$this->mime_type = $mime;
1533
1534
return TRUE;
1535
}
1536
1537
1538
/**
1539
* Size calculator
1540
*
1541
* This function takes a known width x height and
1542
* recalculates it to a new size. Only one
1543
* new variable needs to be known
1544
*
1545
* $props = array(
1546
* 'width' => $width,
1547
* 'height' => $height,
1548
* 'new_width' => 40,
1549
* 'new_height' => ''
1550
* );
1551
*
1552
* @param array
1553
* @return array
1554
*/
1555
private function size_calculator($vals) {
1556
if ( ! is_array($vals)) {
1557
return;
1558
}
1559
1560
$allowed = array('new_width', 'new_height', 'width', 'height');
1561
1562
foreach ($allowed as $item) {
1563
if ( ! isset($vals[$item]) || $vals[$item] == '') {
1564
$vals[$item] = 0;
1565
}
1566
}
1567
1568
if ($vals['width'] == 0 || $vals['height'] == 0) {
1569
return $vals;
1570
}
1571
1572
if ($vals['new_width'] == 0) {
1573
$vals['new_width'] = ceil($vals['width']*$vals['new_height']/$vals['height']);
1574
} elseif ($vals['new_height'] == 0) {
1575
$vals['new_height'] = ceil($vals['new_width']*$vals['height']/$vals['width']);
1576
}
1577
1578
return $vals;
1579
}
1580
1581
1582
/**
1583
* Explode source_image
1584
*
1585
* This is a helper function that extracts the extension
1586
* from the source_image. This function lets us deal with
1587
* source_images with multiple periods, like: my.cool.jpg
1588
* It returns an associative array with two elements:
1589
* $array['ext'] = '.jpg';
1590
* $array['name'] = 'my.cool';
1591
*
1592
* @param array
1593
* @return array
1594
*/
1595
private function _explode_name($source_image) {
1596
$ext = strrchr($source_image, '.');
1597
$name = ($ext === FALSE) ? $source_image : substr($source_image, 0, -strlen($ext));
1598
1599
return array('ext' => $ext, 'name' => $name);
1600
}
1601
1602
1603
/**
1604
* Is GD Installed?
1605
*
1606
* @return bool
1607
*/
1608
private function gd_loaded() {
1609
if ( ! extension_loaded('gd')) {
1610
// Note: dl() has been removed from some SAPI's in PHP 5.3.
1611
if ( ! dl('gd.so')) {
1612
return FALSE;
1613
}
1614
}
1615
1616
return TRUE;
1617
}
1618
1619
1620
/**
1621
* Get GD version
1622
*
1623
* @return mixed
1624
*/
1625
private function _gd_version() {
1626
if (function_exists('gd_info')) {
1627
$gd_version = @gd_info();
1628
$gd_version = preg_replace("/\D/", "", $gd_version['GD Version']);
1629
1630
return $gd_version;
1631
}
1632
1633
return FALSE;
1634
}
1635
1636
1637
/**
1638
* Set error message
1639
*
1640
* @param string
1641
* @return void
1642
*/
1643
private function _set_error($msg) {
1644
if (is_array($msg)) {
1645
foreach ($msg as $val) {
1646
$this->_error_msg_to_display[] = isset($this->_error_messages[$val]) ? $this->_error_messages[$val] : $val;
1647
}
1648
} else {
1649
$this->_error_msg_to_display[] = isset($this->_error_messages[$msg]) ? $this->_error_messages[$msg] : $msg;
1650
}
1651
}
1652
1653
1654
/**
1655
* Show error messages
1656
*
1657
* @param string
1658
* @return string
1659
*/
1660
public function display_errors($open = '<p>', $close = '</p>') {
1661
$str = '';
1662
foreach ($this->_error_msg_to_display as $val) {
1663
$str .= $open.$val.$close;
1664
}
1665
1666
return $str;
1667
}
1668
1669
}
1670
1671
/* End of file: ./system/libraries/image/image_library.php */
Page URI: http://www.infopotato.com/index.php/code/library/image/
