1: <?php
2:
3: 4: 5: 6: 7: 8: 9:
10:
11:
12: define('IMAGICK_REQUIRED_VERSION', '3.0.0');
13: define('IMAGEMAGICK_REQUIRED_VERSION', '6.3.8');
14:
15: $_imagick_version = phpversion('imagick');
16: $_imagick_version_pass = version_compare($_imagick_version, IMAGICK_REQUIRED_VERSION, '>=');
17:
18: $_imagemagick_version = '';
19: $_imagemagick_version_pass = false;
20:
21: $_zp_imagick_present = extension_loaded('imagick') && $_imagick_version_pass;
22:
23: if ($_zp_imagick_present) {
24: @$_imagemagick_version = Imagick::getVersion();
25: preg_match('/\d+(\.\d+)*/', $_imagemagick_version['versionString'], $matches);
26:
27: $_imagemagick_version['versionNumber'] = $matches[0];
28: $_imagemagick_version_pass = version_compare($_imagemagick_version['versionNumber'], IMAGEMAGICK_REQUIRED_VERSION, '>=');
29:
30: $_zp_imagick_present &= $_imagick_version_pass;
31: unset($matches);
32: }
33:
34: $_zp_graphics_optionhandlers += array('lib_Imagick_Options' => new lib_Imagick_Options());
35:
36: 37: 38:
39: class lib_Imagick_Options {
40:
41: public static $ignore_size = 0;
42:
43: function __construct() {
44: setOptionDefault('magick_max_height', self::$ignore_size);
45: setOptionDefault('magick_max_width', self::$ignore_size);
46:
47: if (!sanitize_numeric(getOption('magick_max_height'))) {
48: setOption('magick_max_height', self::$ignore_size);
49: }
50:
51: if (!sanitize_numeric(getOption('magick_max_width'))) {
52: setOption('magick_max_width', self::$ignore_size);
53: }
54: }
55:
56: 57: 58: 59: 60:
61: function getOptionsSupported() {
62: global $_zp_imagick_present, $_zp_graphics_optionhandlers;
63: if ($disabled = $this->canLoadMsg()) {
64: setOption('use_imagick', 0, true);
65: }
66: $imagickOptions = array(
67: gettext('Enable Imagick') => array(
68: 'key' => 'use_imagick',
69: 'type' => OPTION_TYPE_CHECKBOX,
70: 'order' => 0,
71: 'disabled' => $disabled,
72: 'desc' => ($disabled) ? '<p class="notebox">' . $disabled . '</p>' : gettext('Your PHP has support for Imagick. Check this option if you wish to use the Imagick graphics library.')
73: )
74: );
75:
76: if (!$disabled) {
77: $imagickOptions += array(
78: gettext('Max height') => array(
79: 'key' => 'magick_max_height',
80: 'type' => OPTION_TYPE_TEXTBOX,
81: 'order' => 1,
82: 'desc' => sprintf(gettext('The maximum height used by the site for processed images. Set to %d for unconstrained. Default is <strong>%d</strong>'), self::$ignore_size, self::$ignore_size)
83: ),
84: gettext('Max width') => array(
85: 'key' => 'magick_max_width',
86: 'type' => OPTION_TYPE_TEXTBOX,
87: 'order' => 2,
88: 'desc' => sprintf(gettext('The maximum width used by the site for processed images. Set to %d for unconstrained. Default is <strong>%d</strong>.'), self::$ignore_size, self::$ignore_size)
89: )
90: );
91: }
92:
93: return $imagickOptions;
94: }
95:
96: function canLoadMsg() {
97: global $_imagick_version_pass, $_imagemagick_version_pass;
98:
99: if (extension_loaded('imagick')) {
100: if (!$_imagick_version_pass) {
101: return sprintf(gettext('The <strong><em>Imagick</em></strong> library version must be <strong>%s</strong> or later.'), IMAGICK_REQUIRED_VERSION);
102: }
103:
104: if (!$_imagemagick_version_pass) {
105: return sprintf(gettext('The <strong><em>ImageMagick</em></strong> binary version must be <strong>%s</strong> or later.'), IMAGEMAGICK_REQUIRED_VERSION);
106: }
107: } else {
108: return gettext('The <strong><em>Imagick</em></strong> extension is not available.');
109: }
110:
111: return '';
112: }
113:
114: }
115:
116: 117: 118:
119: if ($_zp_imagick_present && (getOption('use_imagick') || !extension_loaded('gd'))) {
120: $_lib_Imagick_info = array();
121: $_lib_Imagick_info['Library'] = 'Imagick';
122: $_lib_Imagick_info['Library_desc'] = sprintf(gettext('PHP Imagick library <em>%s</em>') . '<br /><em>%s</em>', $_imagick_version, $_imagemagick_version['versionString']);
123:
124: $_imagick_format_whitelist = array(
125: 'BMP' => 'jpg', 'BMP2' => 'jpg', 'BMP3' => 'jpg',
126: 'GIF' => 'gif', 'GIF87' => 'gif',
127: 'JPG' => 'jpg', 'JPEG' => 'jpg',
128: 'PNG' => 'png', 'PNG8' => 'png', 'PNG24' => 'png', 'PNG32' => 'png',
129: 'TIFF' => 'jpg', 'TIFF64' => 'jpg'
130: );
131:
132: $_imagick = new Imagick();
133: $_imagick_formats = $_imagick->queryFormats();
134: foreach ($_imagick_formats as $format) {
135: if (array_key_exists($format, $_imagick_format_whitelist)) {
136: $_lib_Imagick_info[$format] = $_imagick_format_whitelist[$format];
137: }
138: }
139: unset($_imagick_format_whitelist);
140: unset($_imagick_formats);
141: unset($_imagick);
142: unset($format);
143:
144: if (DEBUG_IMAGE) {
145: debugLog('Loading ' . $_lib_Imagick_info['Library']);
146: }
147:
148: 149: 150: 151: 152: 153:
154: function zp_imageGet($imgfile) {
155: global $_lib_Imagick_info;
156:
157: if (array_key_exists(strtoupper(getSuffix($imgfile)), $_lib_Imagick_info)) {
158: $image = new Imagick();
159:
160: $maxHeight = getOption('magick_max_height');
161: $maxWidth = getOption('magick_max_width');
162:
163: if ($maxHeight > lib_Imagick_Options::$ignore_size && $maxWidth > lib_Imagick_Options::$ignore_size) {
164: $image->setOption('jpeg:size', $maxWidth . 'x' . $maxHeight);
165: }
166:
167: $image->readImage(filesystemToInternal($imgfile));
168:
169:
170: if ($image->getImageColorspace() == Imagick::COLORSPACE_CMYK) {
171: $image->transformimagecolorspace(Imagick::COLORSPACE_SRGB);
172: }
173:
174: return $image;
175: }
176:
177: return false;
178: }
179:
180: 181: 182: 183: 184: 185: 186: 187: 188:
189: function zp_imageOutput($im, $type, $filename = NULL, $qual = 75) {
190: $interlace = getOption('image_interlace');
191: $qual = max(min($qual, 100), 0);
192:
193: $im->setImageFormat($type);
194:
195: switch ($type) {
196: case 'gif':
197: $im->setImageCompression(Imagick::COMPRESSION_LZW);
198: $im->setImageCompressionQuality($qual);
199:
200: if ($interlace) {
201: $im->setInterlaceScheme(Imagick::INTERLACE_GIF);
202: }
203:
204: break;
205:
206: case 'jpeg':
207: case 'jpg':
208: $im->setImageCompression(Imagick::COMPRESSION_JPEG);
209: $im->setImageCompressionQuality($qual);
210:
211: if ($interlace) {
212: $im->setInterlaceScheme(Imagick::INTERLACE_JPEG);
213: }
214:
215: break;
216:
217: case 'png':
218: $im->setImageCompression(Imagick::COMPRESSION_ZIP);
219: $im->setImageCompressionQuality($qual);
220:
221: if ($interlace) {
222: $im->setInterlaceScheme(Imagick::INTERLACE_PNG);
223: }
224:
225: break;
226: }
227:
228: $im->optimizeImageLayers();
229:
230: if ($filename == NULL) {
231: header('Content-Type: image/' . $type);
232:
233: return print $im->getImagesBlob();
234: }
235:
236: return $im->writeImages(filesystemToInternal($filename), true);
237: }
238:
239: 240: 241: 242: 243: 244: 245:
246: function zp_createImage($w, $h) {
247: $im = new Imagick();
248: $im->newImage($w, $h, 'none');
249: $im->setImageType(Imagick::IMGTYPE_TRUECOLORMATTE);
250:
251: return $im;
252: }
253:
254: 255: 256: 257: 258: 259: 260: 261: 262:
263: function zp_imageFill($image, $x, $y, $color) {
264: $target = $image->getImagePixelColor($x, $y);
265:
266: return $image->floodFillPaintImage($color, 1, $target, $x, $y, false);
267: }
268:
269: 270: 271: 272: 273: 274: 275:
276: function zp_imageColorTransparent($image, $color) {
277: return $image->transparentPaintImage($color, 0.0, 1, false);
278: }
279:
280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292:
293: function zp_copyCanvas($imgCanvas, $img, $dest_x, $dest_y, $src_x, $src_y, $w, $h) {
294: $img->cropImage($w, $h, $src_x, $src_y);
295: $result = true;
296: foreach ($imgCanvas as $frame) {
297: $result &= $frame->compositeImage($img, Imagick::COMPOSITE_OVER, $dest_x, $dest_y);
298: }
299: return $result;
300: }
301:
302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316:
317: function zp_resampleImage($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) {
318: foreach ($src_image->getImageProfiles() as $name => $profile) {
319: $dst_image->profileImage($name, $profile);
320: }
321: $result = true;
322: $src_image = $src_image->coalesceImages();
323: foreach ($src_image as $frame) {
324: $frame->cropImage($src_w, $src_h, $src_x, $src_y);
325: $frame->setImagePage(0, 0, 0, 0);
326: $frame->resizeImage($dst_w, $dst_h, Imagick::FILTER_LANCZOS, 1);
327:
328: $dst_image->setImageDelay($frame->getImageDelay());
329: $result &= $dst_image->compositeImage($frame, Imagick::COMPOSITE_OVER, $dst_x, $dst_y);
330:
331: if ($dst_image->getNumberImages() < $src_image->getNumberImages()) {
332: $result &= $dst_image->addImage(zp_createImage($dst_image->getImageWidth(), $dst_image->getImageHeight()));
333: }
334: if (!$result) {
335: break;
336: }
337: }
338: return $result;
339: }
340:
341: 342: 343: 344: 345: 346: 347: 348: 349:
350: function zp_imageUnsharpMask($img, $amount, $radius, $threshold) {
351: $img->unsharpMaskImage($radius, 0.1, $amount, $threshold);
352:
353: return $img;
354: }
355:
356: 357: 358: 359: 360: 361: 362: 363:
364: function zp_imageResizeAlpha($src, $w, $h) {
365: $src->scaleImage($w, $h);
366:
367: return $src;
368: }
369:
370: 371: 372: 373: 374:
375: function zp_imageCanRotate() {
376: return true;
377: }
378:
379: 380: 381: 382: 383: 384: 385:
386: function zp_rotateImage($im, $rotate) {
387: $im->rotateImage('none', 360 - $rotate);
388: return $im;
389: }
390:
391: 392: 393: 394: 395: 396: 397:
398: function zp_imageDims($filename) {
399: $ping = new Imagick();
400:
401: if ($ping->pingImage(filesystemToInternal($filename))) {
402: return array('width' => $ping->getImageWidth(), 'height' => $ping->getImageHeight());
403: }
404:
405: return false;
406: }
407:
408: 409: 410: 411: 412: 413:
414: function zp_imageIPTC($filename) {
415: $ping = new Imagick();
416:
417: if ($ping->pingImage(filesystemToInternal($filename))) {
418: try {
419: return $ping->getImageProfile('iptc');
420: } catch (ImagickException $e) {
421:
422: }
423: }
424:
425: return false;
426: }
427:
428: 429: 430: 431: 432: 433:
434: function zp_imageWidth($im) {
435: return $im->getImageWidth();
436: }
437:
438: 439: 440: 441: 442: 443:
444: function zp_imageHeight($im) {
445: return $im->getImageHeight();
446: }
447:
448: 449: 450: 451: 452: 453: 454: 455: 456: 457: 458: 459: 460: 461:
462: function zp_imageMerge($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct) {
463: $src_im->cropImage($src_w, $src_h, $src_x, $src_y);
464: $src_im->setImageOpacity($pct / 100);
465:
466: return $dst_im->compositeImage($src_im, Imagick::COMPOSITE_OVER, $dst_x, $dst_y);
467: }
468:
469: 470: 471: 472: 473: 474:
475: function zp_imageGray($image) {
476: $image->setType(Imagick::IMGTYPE_GRAYSCALE);
477: $image->setImageColorspace(Imagick::COLORSPACE_GRAY);
478: $image->setImageProperty('exif:ColorSpace', Imagick::IMGTYPE_GRAYSCALE);
479:
480: return $image;
481: }
482:
483: 484: 485: 486: 487: 488:
489: function zp_imageKill($im) {
490: return $im->destroy();
491: }
492:
493: 494: 495: 496: 497: 498: 499: 500: 501:
502: function zp_colorAllocate($image, $red, $green, $blue) {
503: return new ImagickPixel("rgb($red, $green, $blue)");
504: }
505:
506: 507: 508: 509: 510: 511: 512: 513: 514: 515: 516:
517: function zp_writeString($image, $font, $x, $y, $string, $color) {
518: $font->setStrokeColor($color);
519:
520: return $image->annotateImage($font, $x, $y + $image->getImageHeight() / 2, 0, $string);
521: }
522:
523: 524: 525: 526: 527: 528: 529: 530: 531: 532: 533:
534: function zp_drawRectangle($image, $x1, $y1, $x2, $y2, $color) {
535: return $image->borderImage($color, 1, 1);
536: }
537:
538: 539: 540: 541: 542:
543: function zp_graphicsLibInfo() {
544: global $_lib_Imagick_info;
545:
546: return $_lib_Imagick_info;
547: }
548:
549: 550: 551: 552: 553:
554: function zp_getFonts() {
555: global $_imagick_fontlist;
556:
557: if (!is_array($_imagick_fontlist)) {
558: @$_imagick_fontlist = Imagick::queryFonts();
559: $_imagick_fontlist = array('system' => '') + array_combine($_imagick_fontlist, $_imagick_fontlist);
560:
561: $basefile = SERVERPATH . '/' . USER_PLUGIN_FOLDER . '/imagick_fonts/';
562:
563: if (is_dir($basefile)) {
564: chdir($basefile);
565: $filelist = safe_glob('*.ttf');
566:
567: foreach ($filelist as $file) {
568: $key = filesystemToInternal(str_replace('.ttf', '', $file));
569: $_imagick_fontlist[$key] = getcwd() . '/' . $file;
570: }
571: }
572:
573: chdir(dirname(__FILE__));
574: }
575:
576: return $_imagick_fontlist;
577: }
578:
579: 580: 581: 582: 583: 584:
585: function zp_imageLoadFont($font = NULL, $size = 18) {
586: $draw = new ImagickDraw();
587:
588: if (!empty($font)) {
589: $draw->setFont($font);
590: }
591:
592: $draw->setFontSize($size);
593:
594: return $draw;
595: }
596:
597: 598: 599: 600: 601: 602:
603: function zp_imageFontWidth($font) {
604: $temp = new Imagick();
605: $metrics = $temp->queryFontMetrics($font, "The quick brown fox jumps over the lazy dog");
606: $temp->destroy();
607:
608: return $metrics['characterWidth'];
609: }
610:
611: 612: 613: 614: 615: 616:
617: function zp_imageFontHeight($font) {
618: $temp = new Imagick();
619: $metrics = $temp->queryFontMetrics($font, "The quick brown fox jumps over the lazy dog");
620: $temp->destroy();
621:
622: return $metrics['characterHeight'];
623: }
624:
625: 626: 627: 628: 629: 630:
631: function zp_imageFromString($string) {
632: $im = new Imagick();
633:
634: $maxHeight = getOption('magick_max_height');
635: $maxWidth = getOption('magick_max_width');
636:
637: if ($maxHeight > lib_Imagick_Options::$ignore_size && $maxWidth > lib_Imagick_Options::$ignore_size) {
638: $im->setOption('jpeg:size', $maxWidth . 'x' . $maxHeight);
639: }
640:
641: $im->readImageBlob($string);
642:
643: return $im;
644: }
645:
646: }
647: ?>
648: