1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 5 / Imagick |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2006-2013 Mikko Koppanen, Scott MacVicar |
6 | ImageMagick (c) ImageMagick Studio LLC |
7 +----------------------------------------------------------------------+
8 | This source file is subject to version 3.01 of the PHP license, |
9 | that is bundled with this package in the file LICENSE, and is |
10 | available through the world-wide-web at the following url: |
11 | http://www.php.net/license/3_01.txt |
12 | If you did not receive a copy of the PHP license and are unable to |
13 | obtain it through the world-wide-web, please send a note to |
14 | license@php.net so we can mail you a copy immediately. |
15 +----------------------------------------------------------------------+
16 | Author: Mikko Kopppanen <mkoppanen@php.net> |
17 | Scott MacVicar <scottmac@php.net> |
18 +----------------------------------------------------------------------+
19 */
20
21 #include "php_imagick.h"
22 #include "php_imagick_defs.h"
23 #include "php_imagick_macros.h"
24 #include "php_imagick_helpers.h"
25 #include "php_imagick_file.h"
26
27
28 #if MagickLibVersion > 0x628
29 /* {{{ proto bool Imagick::pingImageFile(resource filehandle)
30 Query image information without reading the whole image to memory
31 */
PHP_METHOD(Imagick,pingImageFile)32 PHP_METHOD(Imagick, pingImageFile)
33 {
34 char *filename = NULL;
35 IM_LEN_TYPE filename_len;
36 php_imagick_object *intern;
37 zval *zstream;
38 php_stream *stream;
39 zend_bool result;
40
41 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s!", &zstream, &filename, &filename_len) == FAILURE) {
42 return;
43 }
44
45 intern = Z_IMAGICK_P(getThis());
46
47 #if PHP_VERSION_ID >= 70000
48 php_stream_from_zval(stream, zstream);
49 #else
50 php_stream_from_zval(stream, &zstream);
51 #endif
52 result = php_imagick_stream_handler(intern, stream, ImagickPingImageFile TSRMLS_CC);
53
54 if (result == 0) {
55 if (!EG(exception)) {
56 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to ping image from the filehandle" TSRMLS_CC);
57 }
58 return;
59 }
60
61 if (filename) {
62 MagickSetImageFilename(intern->magick_wand, filename);
63 MagickSetLastIterator(intern->magick_wand);
64 }
65 RETURN_TRUE;
66 }
67 /* }}} */
68
69
70 /* {{{ proto bool Imagick::pingImageBlob(string image )
71 Query image information without reading the whole image to memory
72 */
PHP_METHOD(Imagick,pingImageBlob)73 PHP_METHOD(Imagick, pingImageBlob)
74 {
75 char *image_string;
76 IM_LEN_TYPE image_string_len;
77 MagickBooleanType status;
78 php_imagick_object *intern;
79
80 /* Parse parameters given to function */
81 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &image_string, &image_string_len) == FAILURE) {
82 return;
83 }
84
85 if (image_string_len == 0) {
86 php_imagick_throw_exception(IMAGICK_CLASS, "Empty image string passed" TSRMLS_CC);
87 return;
88 }
89
90 intern = Z_IMAGICK_P(getThis());
91 status = MagickPingImageBlob(intern->magick_wand, image_string, image_string_len);
92
93 /* No magick is going to happen */
94 if (status == MagickFalse) {
95 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to ping image blob" TSRMLS_CC);
96 return;
97 }
98
99 RETURN_TRUE;
100 }
101 /* }}} */
102
103 /* {{{ proto bool Imagick::vignetteImage(float blackPoint, float whitePoint, int x, int y )
104 Adds vignette filter to the image
105 */
PHP_METHOD(Imagick,vignetteImage)106 PHP_METHOD(Imagick, vignetteImage)
107 {
108 double black_point, white_point;
109 im_long x, y;
110 php_imagick_object *intern;
111 MagickBooleanType status;
112
113 /* Parse parameters given to function */
114 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddll", &black_point, &white_point, &x, &y) == FAILURE) {
115 return;
116 }
117
118 intern = Z_IMAGICK_P(getThis());
119 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
120 return;
121
122 status = MagickVignetteImage(intern->magick_wand, black_point, white_point, x, y);
123
124 /* No magick is going to happen */
125 if (status == MagickFalse) {
126 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to apply vignette filter" TSRMLS_CC);
127 return;
128 }
129
130 RETURN_TRUE;
131 }
132 /* }}} */
133
134 /* {{{ proto bool Imagick::transposeImage()
135 Creates a vertical mirror image
136 */
PHP_METHOD(Imagick,transposeImage)137 PHP_METHOD(Imagick, transposeImage)
138 {
139 php_imagick_object *intern;
140 MagickBooleanType status;
141
142 if (zend_parse_parameters_none() == FAILURE) {
143 return;
144 }
145
146 intern = Z_IMAGICK_P(getThis());
147 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
148 return;
149
150 status = MagickTransposeImage(intern->magick_wand);
151
152 /* No magick is going to happen */
153 if (status == MagickFalse) {
154 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to transpose image" TSRMLS_CC);
155 return;
156 }
157
158 RETURN_TRUE;
159 }
160 /* }}} */
161
162 /* {{{ proto bool Imagick::transverseImage()
163 Creates a horizontal mirror image
164 */
PHP_METHOD(Imagick,transverseImage)165 PHP_METHOD(Imagick, transverseImage)
166 {
167 php_imagick_object *intern;
168 MagickBooleanType status;
169
170 if (zend_parse_parameters_none() == FAILURE) {
171 return;
172 }
173
174 intern = Z_IMAGICK_P(getThis());
175 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
176 return;
177
178 status = MagickTransverseImage(intern->magick_wand);
179
180 /* No magick is going to happen */
181 if (status == MagickFalse) {
182 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to transverse image" TSRMLS_CC);
183 return;
184 }
185
186 RETURN_TRUE;
187 }
188 /* }}} */
189
190 /* {{{ proto bool Imagick::adaptiveBlurImage(float radius, float sigma[, int channel] )
191 Adds adaptive blur filter to image
192 */
PHP_METHOD(Imagick,adaptiveBlurImage)193 PHP_METHOD(Imagick, adaptiveBlurImage)
194 {
195 double radius, sigma;
196 php_imagick_object *intern;
197 MagickBooleanType status;
198 im_long channel = IM_DEFAULT_CHANNEL;
199
200 /* Parse parameters given to function */
201 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd|l", &radius, &sigma, &channel) == FAILURE) {
202 return;
203 }
204
205 intern = Z_IMAGICK_P(getThis());
206 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
207 return;
208
209 status = MagickAdaptiveBlurImageChannel(intern->magick_wand, channel, radius, sigma);
210
211 /* No magick is going to happen */
212 if (status == MagickFalse) {
213 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to adaptive blur image" TSRMLS_CC);
214 return;
215 }
216
217 RETURN_TRUE;
218 }
219 /* }}} */
220
221 /* {{{ proto bool Imagick::uniqueImageColors()
222 Discards all but one of any pixel color
223 */
PHP_METHOD(Imagick,uniqueImageColors)224 PHP_METHOD(Imagick, uniqueImageColors)
225 {
226 php_imagick_object *intern;
227 MagickBooleanType status;
228
229 if (zend_parse_parameters_none() == FAILURE) {
230 return;
231 }
232
233 intern = Z_IMAGICK_P(getThis());
234 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
235 return;
236
237 status = MagickUniqueImageColors(intern->magick_wand);
238
239 /* No magick is going to happen */
240 if (status == MagickFalse) {
241 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get unique image colors" TSRMLS_CC);
242 return;
243 }
244 RETURN_TRUE;
245 }
246 /* }}} */
247
248 /* {{{ proto bool Imagick::contrastStretchImage(float black_point, float white_point[, int channel])
249 Enhances the contrast of a color image
250 */
PHP_METHOD(Imagick,contrastStretchImage)251 PHP_METHOD(Imagick, contrastStretchImage)
252 {
253 php_imagick_object *intern;
254 double black_point, white_point;
255 MagickBooleanType status;
256 im_long channel = IM_DEFAULT_CHANNEL;
257
258 /* Parse parameters given to function */
259 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd|l", &black_point, &white_point, &channel) == FAILURE) {
260 return;
261 }
262
263 intern = Z_IMAGICK_P(getThis());
264 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
265 return;
266
267 status = MagickContrastStretchImageChannel(intern->magick_wand, channel, black_point, white_point);
268
269 /* No magick is going to happen */
270 if (status == MagickFalse) {
271 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to contrast strech image" TSRMLS_CC);
272 return;
273 }
274
275 RETURN_TRUE;
276 }
277 /* }}} */
278
279 #if !defined(MAGICKCORE_EXCLUDE_DEPRECATED)
280 #if MagickLibVersion < 0x700
281 /* {{{ proto int Imagick::getImageMatte()
282 Returns true if the image has a matte channel otherwise false
283 */
PHP_METHOD(Imagick,getImageMatte)284 PHP_METHOD(Imagick, getImageMatte)
285 {
286 php_imagick_object *intern;
287 MagickBooleanType matte;
288
289 if (zend_parse_parameters_none() == FAILURE) {
290 return;
291 }
292
293 IMAGICK_METHOD_DEPRECATED ("Imagick", "getImageMatte");
294
295 intern = Z_IMAGICK_P(getThis());
296 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
297 return;
298
299 matte = MagickGetImageMatte(intern->magick_wand);
300
301 if (matte == MagickTrue) {
302 RETURN_TRUE;
303 } else {
304 RETURN_FALSE;
305 }
306 }
307 /* }}} */
308 #endif //#if MagickLibVersion < 0x700
309 #endif
310
311 /* {{{ proto bool Imagick::setImageMatte(bool matte)
312 Sets the image matte channel
313 */
PHP_METHOD(Imagick,setImageMatte)314 PHP_METHOD(Imagick, setImageMatte)
315 {
316 php_imagick_object *intern;
317 zend_bool matte;
318 MagickBooleanType status;
319
320 /* Parse parameters given to function */
321 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &matte) == FAILURE) {
322 return;
323 }
324
325 intern = Z_IMAGICK_P(getThis());
326 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
327 return;
328
329 status = MagickSetImageMatte(intern->magick_wand, matte);
330
331 /* No magick is going to happen */
332 if (status == MagickFalse) {
333 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image matte" TSRMLS_CC);
334 return;
335 }
336
337 RETURN_TRUE;
338 }
339 /* }}} */
340
341 /* {{{ proto bool Imagick::adaptiveResizeImage(int width, int height[, bool bestfit[, bool legacy]]])
342 Adaptively resize image with data dependent triangulation
343 If legacy is true, the calculations are done with the small rounding bug that existed in
344 Imagick before 3.4.0. If false, the calculations should produce the same results as
345 ImageMagick CLI does.
346 */
PHP_METHOD(Imagick,adaptiveResizeImage)347 PHP_METHOD(Imagick, adaptiveResizeImage)
348 {
349 php_imagick_object *intern;
350 MagickBooleanType status;
351 im_long width, height, new_width, new_height;
352 zend_bool bestfit = 0;
353 zend_bool legacy = 0;
354
355 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll|bb", &width, &height, &bestfit, &legacy) == FAILURE) {
356 return;
357 }
358
359 intern = Z_IMAGICK_P(getThis());
360 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
361 return;
362
363 if (!php_imagick_thumbnail_dimensions(intern->magick_wand, bestfit, width, height, &new_width, &new_height, legacy)) {
364 php_imagick_throw_exception(IMAGICK_CLASS, "Invalid image geometry" TSRMLS_CC);
365 return;
366 }
367
368 status = MagickAdaptiveResizeImage(intern->magick_wand, new_width, new_height);
369
370 if (status == MagickFalse) {
371 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to adaptive resize image" TSRMLS_CC);
372 return;
373 }
374
375 RETURN_TRUE;
376 }
377 /* }}} */
378 /* {{{ proto bool Imagick::sketchImage(float radius, float sigma, float angle)
379 Simulates a pencil sketch
380 */
PHP_METHOD(Imagick,sketchImage)381 PHP_METHOD(Imagick, sketchImage)
382 {
383 double radius, sigma, angle;
384 MagickBooleanType status;
385 php_imagick_object *intern;
386
387 /* Parse parameters given to function */
388 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd", &radius, &sigma, &angle) == FAILURE) {
389 return;
390 }
391
392 intern = Z_IMAGICK_P(getThis());
393 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
394 return;
395
396 status = MagickSketchImage(intern->magick_wand, sigma, radius, angle);
397
398 /* No magick is going to happen */
399 if (status == MagickFalse) {
400 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to sketch image" TSRMLS_CC);
401 return;
402 }
403
404 RETURN_TRUE;
405 }
406 /* }}} */
407
408 /* {{{ proto bool Imagick::shadeImage(bool gray, float azimuth, float elevation)
409 Shines a distant light on an image
410 */
PHP_METHOD(Imagick,shadeImage)411 PHP_METHOD(Imagick, shadeImage)
412 {
413 php_imagick_object *intern;
414 MagickBooleanType status;
415 double azimuth, elevation;
416 zend_bool gray;
417
418 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "bdd", &gray, &azimuth, &elevation) == FAILURE) {
419 return;
420 }
421
422 intern = Z_IMAGICK_P(getThis());
423 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
424 return;
425
426 status = MagickShadeImage(intern->magick_wand, gray, azimuth, elevation);
427
428 /* No magick is going to happen */
429 if (status == MagickFalse) {
430 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to shade image" TSRMLS_CC);
431 return;
432 }
433
434 RETURN_TRUE;
435 }
436 /* }}} */
437
438 /* {{{ proto int Imagick::getSizeOffset()
439 Returns the size offset associated with the Imagick object
440 */
PHP_METHOD(Imagick,getSizeOffset)441 PHP_METHOD(Imagick, getSizeOffset)
442 {
443 php_imagick_object *intern;
444 ssize_t offset;
445 MagickBooleanType status;
446
447 if (zend_parse_parameters_none() == FAILURE) {
448 return;
449 }
450
451 intern = Z_IMAGICK_P(getThis());
452 status = MagickGetSizeOffset(intern->magick_wand, &offset);
453
454 if (status == MagickFalse) {
455 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get size offset" TSRMLS_CC);
456 return;
457 }
458
459 RETVAL_LONG(offset);
460 }
461 /* }}} */
462
463 /* {{{ proto bool Imagick::setSizeOffset(int columns, int rows, int offset)
464 Sets the size and offset of the Imagick object
465 */
PHP_METHOD(Imagick,setSizeOffset)466 PHP_METHOD(Imagick, setSizeOffset)
467 {
468 php_imagick_object *intern;
469 im_long columns, rows, offset;
470 MagickBooleanType status;
471
472 /* Parse parameters given to function */
473 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &columns, &rows, &offset) == FAILURE) {
474 return;
475 }
476
477 intern = Z_IMAGICK_P(getThis());
478 status = MagickSetSizeOffset(intern->magick_wand, columns, rows, offset);
479
480 /* No magick is going to happen */
481 if (status == MagickFalse) {
482 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set size offset" TSRMLS_CC);
483 return;
484 }
485 RETURN_TRUE;
486 }
487 /* }}} */
488
489 /* {{{ proto bool Imagick::adaptiveSharpenImage(float radius, float sigma[, int channel])
490 Adaptively sharpen image with data dependent triangulation
491 */
PHP_METHOD(Imagick,adaptiveSharpenImage)492 PHP_METHOD(Imagick, adaptiveSharpenImage)
493 {
494 php_imagick_object *intern;
495 MagickBooleanType status;
496 double radius, sigma;
497 im_long channel = IM_DEFAULT_CHANNEL;
498
499 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd|l", &radius, &sigma, &channel) == FAILURE) {
500 return;
501 }
502
503 intern = Z_IMAGICK_P(getThis());
504 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
505 return;
506
507 status = MagickAdaptiveSharpenImageChannel(intern->magick_wand, channel, radius, sigma);
508
509 if (status == MagickFalse) {
510 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to adaptive sharpen image" TSRMLS_CC);
511 return;
512 }
513
514 RETURN_TRUE;
515 }
516 /* }}} */
517
518
519 /* {{{ proto bool Imagick::randomThresholdImage(float low, float high[, int channel])
520 Changes the value of individual pixels
521 */
PHP_METHOD(Imagick,randomThresholdImage)522 PHP_METHOD(Imagick, randomThresholdImage)
523 {
524 php_imagick_object *intern;
525 double low, high;
526 MagickBooleanType status;
527 im_long channel = IM_DEFAULT_CHANNEL;
528
529 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd|l", &low, &high, &channel) == FAILURE) {
530 return;
531 }
532
533 intern = Z_IMAGICK_P(getThis());
534 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
535 return;
536
537 status = MagickRandomThresholdImageChannel(intern->magick_wand, channel, low, high);
538
539 /* No magick is going to happen */
540 if (status == MagickFalse) {
541 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to random threshold image" TSRMLS_CC);
542 return;
543 }
544
545 RETURN_TRUE;
546 }
547 /* }}} */
548
549 /* {{{ proto string Imagick::roundCornersImage(float x_rounding, float y_rounding[, float stroke_width = 10[, float displace = 5[, float size_correction = -6]]] )
550 Rounds image corners
551 */
552 #if MagickLibVersion < 0x700
PHP_METHOD(Imagick,roundCornersImage)553 PHP_METHOD(Imagick, roundCornersImage)
554 {
555 char *old_locale;
556 double x_rounding, y_rounding;
557 DrawingWand *draw;
558 MagickWand *mask_image;
559 PixelWand *color;
560 php_imagick_object *intern;
561 long image_width, image_height;
562 MagickBooleanType status;
563 double stroke_width = 10, displace = 5, correction = -6;
564
565 /* Parse parameters given to function */
566 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd|ddd", &x_rounding, &y_rounding, &stroke_width, &displace, &correction) == FAILURE) {
567 return;
568 }
569
570 intern = Z_IMAGICK_P(getThis());
571
572 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
573 return;
574
575 image_width = MagickGetImageWidth(intern->magick_wand);
576 image_height = MagickGetImageHeight(intern->magick_wand);
577
578 if (!image_width || !image_height) {
579 php_imagick_throw_exception(IMAGICK_CLASS, "Unable to round corners on empty image" TSRMLS_CC);
580 return;
581 }
582
583 status = MagickSetImageMatte(intern->magick_wand, MagickTrue);
584
585 if (status == MagickFalse) {
586 php_imagick_throw_exception(IMAGICK_CLASS, "Unable to set image matte" TSRMLS_CC);
587 return;
588 }
589
590 /* Here we go.. */
591 color = NewPixelWand();
592 if (!color) {
593 php_imagick_throw_exception (IMAGICK_CLASS, "Failed to allocate PixelWand structure" TSRMLS_CC);
594 return;
595 }
596
597 draw = NewDrawingWand();
598 if (!draw) {
599 DestroyPixelWand (color);
600 php_imagick_throw_exception (IMAGICK_CLASS, "Failed to allocate DrawingWand structure" TSRMLS_CC);
601 return;
602 }
603
604 mask_image = NewMagickWand();
605 if (!mask_image) {
606 DestroyPixelWand (color);
607 DestroyDrawingWand (draw);
608 php_imagick_throw_exception (IMAGICK_CLASS, "Failed to allocate MagickWand structure" TSRMLS_CC);
609 return;
610 }
611
612
613 #define exit_cleanup() \
614 if (color != NULL) color = DestroyPixelWand(color); \
615 if (draw != NULL) draw = DestroyDrawingWand(draw); \
616 if (mask_image != NULL) mask_image = DestroyMagickWand(mask_image);
617
618 status = PixelSetColor(color, "transparent");
619
620 if (status == MagickFalse) {
621 exit_cleanup();
622 php_imagick_throw_exception(IMAGICK_CLASS, "Unable to set pixel color" TSRMLS_CC);
623 return;
624 }
625
626 status = MagickNewImage(mask_image, image_width, image_height, color);
627
628 if (status == MagickFalse) {
629 exit_cleanup();
630 php_imagick_throw_exception(IMAGICK_CLASS, "Unable to allocate mask image" TSRMLS_CC);
631 return;
632 }
633
634 MagickSetImageBackgroundColor(mask_image, color);
635 status = PixelSetColor(color, "white");
636
637 if (status == MagickFalse) {
638 exit_cleanup();
639 php_imagick_throw_exception(IMAGICK_CLASS, "Unable to set pixel color" TSRMLS_CC);
640 return;
641 }
642
643 DrawSetFillColor(draw, color);
644 status = PixelSetColor(color, "black");
645
646 if (status == MagickFalse) {
647 exit_cleanup();
648 php_imagick_throw_exception(IMAGICK_CLASS, "Unable to set pixel color" TSRMLS_CC);
649 return;
650 }
651
652 DrawSetStrokeColor(draw, color);
653 DrawSetStrokeWidth(draw, stroke_width);
654 DrawRoundRectangle(draw, displace, displace, image_width + correction, image_height + correction, x_rounding, y_rounding);
655
656 old_locale = php_imagick_set_locale (TSRMLS_C);
657
658 status = MagickDrawImage(mask_image, draw);
659
660 php_imagick_restore_locale (old_locale);
661
662 if (old_locale)
663 efree (old_locale);
664
665 if (status == MagickFalse) {
666 exit_cleanup();
667 php_imagick_throw_exception(IMAGICK_CLASS, "Unable to draw on image" TSRMLS_CC);
668 return;
669 }
670
671 status = MagickCompositeImage(intern->magick_wand, mask_image, DstInCompositeOp, 0, 0);
672
673 if (status == MagickFalse) {
674 exit_cleanup();
675 php_imagick_throw_exception(IMAGICK_CLASS, "Unable to composite image" TSRMLS_CC);
676 return;
677 }
678
679 exit_cleanup();
680 RETURN_TRUE;
681 #undef exit_cleanup
682 }
683 /* }}} */
684 #endif
685
686 /* {{{ proto int Imagick::getIteratorIndex()
687 Returns the index of the current active image
688 */
PHP_METHOD(Imagick,getIteratorIndex)689 PHP_METHOD(Imagick, getIteratorIndex)
690 {
691 MagickBooleanType status;
692 php_imagick_object *intern;
693
694 if (zend_parse_parameters_none() == FAILURE) {
695 return;
696 }
697
698 intern = Z_IMAGICK_P(getThis());
699
700 status = MagickGetIteratorIndex(intern->magick_wand);
701 ZVAL_LONG(return_value, (long)status);
702 return;
703 }
704 /* }}} */
705
706 /* {{{ proto bool Imagick::setIteratorIndex(int index)
707 Sets the index of the Imagick object
708 */
PHP_METHOD(Imagick,setIteratorIndex)709 PHP_METHOD(Imagick, setIteratorIndex)
710 {
711 const im_long index;
712 MagickBooleanType status;
713 php_imagick_object *intern;
714
715 /* Parse parameters given to function */
716 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) {
717 return;
718 }
719
720 intern = Z_IMAGICK_P(getThis());
721 status = MagickSetIteratorIndex(intern->magick_wand, index);
722
723 /* No magick is going to happen */
724 if (status == MagickFalse) {
725 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set iterator index" TSRMLS_CC);
726 return;
727 }
728
729 intern->next_out_of_bound = 0;
730 RETURN_TRUE;
731 }
732 /* }}} */
733
734 #if MagickLibVersion < 0x700
735 /* {{{ proto Imagick Imagick::transformImage(string crop, string geometry )
736 Comfortability method for crop and resize
737 */
PHP_METHOD(Imagick,transformImage)738 PHP_METHOD(Imagick, transformImage)
739 {
740 char *crop, *geometry;
741 IM_LEN_TYPE crop_len, geometry_len;
742 MagickWand *transformed;
743 php_imagick_object *intern, *intern_return;
744
745 /* Parse parameters given to function */
746 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &crop, &crop_len, &geometry, &geometry_len) == FAILURE) {
747 return;
748 }
749
750 intern = Z_IMAGICK_P(getThis());
751 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
752 return;
753
754 transformed = MagickTransformImage(intern->magick_wand, crop, geometry);
755
756 if (!transformed) {
757 php_imagick_convert_imagick_exception(intern->magick_wand, "Transforming image failed" TSRMLS_CC);
758 return;
759 }
760
761 object_init_ex(return_value, php_imagick_sc_entry);
762 intern_return = Z_IMAGICK_P(return_value);
763
764 php_imagick_replace_magickwand(intern_return, transformed);
765 return;
766 }
767 #endif //#if MagickLibVersion < 0x700
768
769 /* }}} */
770 #endif
771
772 #if MagickLibVersion > 0x630
773 #if MagickLibVersion < 0x700
774 /* {{{ proto bool Imagick::setImageOpacity(float opacity)
775 Sets the image to the specified opacity level
776 */
PHP_METHOD(Imagick,setImageOpacity)777 PHP_METHOD(Imagick, setImageOpacity)
778 {
779 double opacity;
780 MagickBooleanType status;
781 php_imagick_object *intern;
782
783 /* Parse parameters given to function */
784 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &opacity) == FAILURE) {
785 return;
786 }
787
788 intern = Z_IMAGICK_P(getThis());
789 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
790 return;
791
792 status = MagickSetImageOpacity(intern->magick_wand, opacity);
793
794 /* No magick is going to happen */
795 if (status == MagickFalse) {
796 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image opacity" TSRMLS_CC);
797 return;
798 }
799
800 RETURN_TRUE;
801 }
802 /* }}} */
803 #endif
804
805
806
807 #if MagickLibVersion >= 0x700
808 /* {{{ proto bool Imagick::setImageAlpha(float alpha)
809 Sets the image to the specified alpha level
810 */
PHP_METHOD(Imagick,setImageAlpha)811 PHP_METHOD(Imagick, setImageAlpha)
812 {
813 double alpha;
814 MagickBooleanType status;
815 php_imagick_object *intern;
816
817 /* Parse parameters given to function */
818 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &alpha) == FAILURE) {
819 return;
820 }
821
822 intern = Z_IMAGICK_P(getThis());
823 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
824 return;
825
826 status = MagickSetImageAlpha(intern->magick_wand, alpha);
827
828 /* No magick is going to happen */
829 if (status == MagickFalse) {
830 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image alpha" TSRMLS_CC);
831 return;
832 }
833
834 RETURN_TRUE;
835 }
836 /* }}} */
837 #endif
838
839
840
841 #if MagickLibVersion < 0x700
842 /* {{{ proto bool Imagick::orderedPosterizeImage(string threshold_map[, int CHANNEL])
843 Performs an ordered dither
844 */
PHP_METHOD(Imagick,orderedPosterizeImage)845 PHP_METHOD(Imagick, orderedPosterizeImage)
846 {
847 char *map;
848 IM_LEN_TYPE map_len;
849 MagickBooleanType status;
850 php_imagick_object *intern;
851 im_long channel = IM_DEFAULT_CHANNEL;
852
853 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &map, &map_len, &channel) == FAILURE) {
854 return;
855 }
856
857 intern = Z_IMAGICK_P(getThis());
858 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
859 return;
860
861 status = MagickOrderedPosterizeImageChannel(intern->magick_wand, channel, map);
862
863 if (status == MagickFalse) {
864 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to posterize image" TSRMLS_CC);
865 return;
866 }
867
868 RETURN_TRUE;
869 }
870 /* }}} */
871 #endif //#if MagickLibVersion < 0x700
872 #endif //#if MagickLibVersion > 0x630
873
874 #if MagickLibVersion > 0x631
875 /* {{{ proto bool Imagick::polaroidImage(ImagickDraw properties, double angle )
876 Simulates a Polaroid picture
877 */
PHP_METHOD(Imagick,polaroidImage)878 PHP_METHOD(Imagick, polaroidImage)
879 {
880 zval *objvar;
881 php_imagick_object *intern;
882 MagickBooleanType status;
883 php_imagickdraw_object *internd;
884 double angle;
885
886 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Od", &objvar, php_imagickdraw_sc_entry, &angle) == FAILURE) {
887 return;
888 }
889
890 intern = Z_IMAGICK_P(getThis());
891 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
892 return;
893
894 internd = Z_IMAGICKDRAW_P(objvar);
895 #if MagickLibVersion >= 0x700
896 {
897 PixelInterpolateMethod method = BilinearInterpolatePixel;
898 char *caption = "TODO FIXME";
899 status = MagickPolaroidImage(intern->magick_wand,internd->drawing_wand,caption,angle,method);
900 }
901 #else
902 status = MagickPolaroidImage(intern->magick_wand, internd->drawing_wand, angle);
903 #endif
904
905
906
907
908 /* No magick is going to happen */
909 if (status == MagickFalse) {
910 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to polaroid image" TSRMLS_CC);
911 return;
912 }
913
914 RETURN_TRUE;
915 }
916 /* }}} */
917
918 /* {{{ proto string Imagick::getImageProperty(string name )
919 Eeturns a value associated with the specified property
920 */
PHP_METHOD(Imagick,getImageProperty)921 PHP_METHOD(Imagick, getImageProperty)
922 {
923 php_imagick_object *intern;
924 char *name, *value;
925 IM_LEN_TYPE name_len;
926
927 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
928 return;
929 }
930
931 intern = Z_IMAGICK_P(getThis());
932 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
933 return;
934
935 value = MagickGetImageProperty(intern->magick_wand, name);
936
937 if (value) {
938 IM_ZVAL_STRING(return_value, (char *)value);
939 IMAGICK_FREE_MAGICK_MEMORY(value);
940 return;
941 }
942 RETURN_FALSE;
943 }
944 /* }}} */
945
946 /* {{{ proto bool Imagick::setImageProperty(string name, string value )
947 returns a value associated with the specified property
948 */
PHP_METHOD(Imagick,setImageProperty)949 PHP_METHOD(Imagick, setImageProperty)
950 {
951 php_imagick_object *intern;
952 char *name, *value;
953 IM_LEN_TYPE name_len, value_len;
954 MagickBooleanType status;
955
956 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &value, &value_len) == FAILURE) {
957 return;
958 }
959
960 intern = Z_IMAGICK_P(getThis());
961
962 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
963 return;
964 status = MagickSetImageProperty(intern->magick_wand, name, value);
965
966 /* No magick is going to happen */
967 if (status == MagickFalse) {
968 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image property" TSRMLS_CC);
969 return;
970 }
971
972 RETURN_TRUE;
973 }
974 /* }}} */
975
976 /* {{{ proto bool Imagick::deleteImageProperty(string name)
977 Deletes an image property.
978 */
PHP_METHOD(Imagick,deleteImageProperty)979 PHP_METHOD(Imagick, deleteImageProperty)
980 {
981 php_imagick_object *intern;
982 char *name;
983 IM_LEN_TYPE name_len;
984 MagickBooleanType status;
985
986 Image *image;
987
988 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
989 return;
990 }
991
992 intern = Z_IMAGICK_P(getThis());
993
994 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
995 return;
996
997 image = GetImageFromMagickWand(intern->magick_wand);
998 status = DeleteImageProperty(image, name);
999
1000 if (status == MagickFalse) {
1001 RETURN_FALSE;
1002 }
1003
1004 RETURN_TRUE;
1005 }
1006 /* }}} */
1007
1008
1009 /* {{{ proto bool Imagick::identifyFormat(string embedText)
1010 Replaces any embedded formatting characters with the appropriate image property and returns the interpreted text. See http://www.imagemagick.org/script/escape.php for escape sequences.
1011 */
PHP_METHOD(Imagick,identifyFormat)1012 PHP_METHOD(Imagick, identifyFormat)
1013 {
1014 php_imagick_object *intern;
1015 char *embedText;
1016 IM_LEN_TYPE embedText_len;
1017 char *result;
1018
1019 ImageInfo *image_info;
1020 Image *image;
1021
1022 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &embedText, &embedText_len) == FAILURE) {
1023 return;
1024 }
1025
1026 intern = Z_IMAGICK_P(getThis());
1027
1028 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0) {
1029 return;
1030 }
1031
1032 image_info = AcquireImageInfo();
1033 image = GetImageFromMagickWand(intern->magick_wand);
1034
1035 #if MagickLibVersion >= 0x700
1036 {
1037 //TODO - handle exception info.
1038 ExceptionInfo *exception = NULL;
1039 result = InterpretImageProperties(image_info, image, embedText, exception);
1040 }
1041 #else
1042 result = InterpretImageProperties(image_info, image, embedText);
1043 #endif
1044 image_info = DestroyImageInfo(image_info);
1045
1046 if (result) {
1047 #if PHP_VERSION_ID >= 70000
1048 RETVAL_STRING(result);
1049 #else
1050 RETVAL_STRING(result, 1);
1051 #endif
1052 IMAGICK_FREE_MAGICK_MEMORY(result);
1053
1054 return;
1055 }
1056
1057 RETURN_FALSE;
1058 }
1059 /* }}} */
1060
1061 /* {{{ proto int Imagick::getImageInterpolateMethod()
1062 Returns the interpolation method for the sepcified image.
1063 */
PHP_METHOD(Imagick,getImageInterpolateMethod)1064 PHP_METHOD(Imagick, getImageInterpolateMethod)
1065 {
1066 php_imagick_object *intern;
1067 long interpolate;
1068
1069 if (zend_parse_parameters_none() == FAILURE) {
1070 return;
1071 }
1072
1073 intern = Z_IMAGICK_P(getThis());
1074 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
1075 return;
1076
1077 interpolate = MagickGetImageInterpolateMethod(intern->magick_wand);
1078 RETVAL_LONG(interpolate);
1079 }
1080 /* }}} */
1081
1082 #if IM_HAVE_IMAGICK_SETIMAGEINTERPOLATEMETHOD
1083 /* {{{ proto bool Imagick::setImageInterpolateMethod(int method)
1084 Sets the image interpolate pixel method.
1085 */
PHP_METHOD(Imagick,setImageInterpolateMethod)1086 PHP_METHOD(Imagick, setImageInterpolateMethod)
1087 {
1088 php_imagick_object *intern;
1089 im_long interpolate;
1090 MagickBooleanType status;
1091
1092 /* Parse parameters given to function */
1093 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &interpolate) == FAILURE) {
1094 return;
1095 }
1096
1097 intern = Z_IMAGICK_P(getThis());
1098 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
1099 return;
1100
1101 status = MagickSetImageInterpolateMethod(intern->magick_wand, interpolate);
1102
1103 /* No magick is going to happen */
1104 if (status == MagickFalse) {
1105 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set the image interpolate method" TSRMLS_CC);
1106 return;
1107 }
1108 RETURN_TRUE;
1109 }
1110 /* }}} */
1111 #endif // #if IM_HAVE_IMAGICK_SETIMAGEINTERPOLATEMETHOD
1112
1113 /* {{{ proto bool Imagick::linearStretchImage(float blackPoint, float whitePoint)
1114 Stretches with saturation the image intensity.
1115 */
PHP_METHOD(Imagick,linearStretchImage)1116 PHP_METHOD(Imagick, linearStretchImage)
1117 {
1118 php_imagick_object *intern;
1119 double blackPoint, whitePoint;
1120 MagickBooleanType status;
1121
1122 /* Parse parameters given to function */
1123 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &blackPoint, &whitePoint) == FAILURE) {
1124 return;
1125 }
1126
1127 intern = Z_IMAGICK_P(getThis());
1128 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
1129 return;
1130
1131 status = MagickLinearStretchImage(intern->magick_wand, blackPoint, whitePoint);
1132
1133 /* No magick is going to happen */
1134 if (status == MagickFalse) {
1135 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to linear strech image" TSRMLS_CC);
1136 return;
1137 }
1138 RETURN_TRUE;
1139 }
1140 /* }}} */
1141
1142 /* {{{ proto int Imagick::getImageLength()
1143 returns the image length in bytes
1144 */
PHP_METHOD(Imagick,getImageLength)1145 PHP_METHOD(Imagick, getImageLength)
1146 {
1147 php_imagick_object *intern;
1148 MagickSizeType length;
1149 MagickBooleanType status;
1150
1151 if (zend_parse_parameters_none() == FAILURE) {
1152 return;
1153 }
1154
1155 intern = Z_IMAGICK_P(getThis());
1156 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
1157 return;
1158
1159 status = MagickGetImageLength(intern->magick_wand, &length);
1160
1161 if (status == MagickFalse) {
1162 php_imagick_throw_exception(IMAGICK_CLASS, "Unable to acquire image length" TSRMLS_CC);
1163 return;
1164 }
1165
1166 RETVAL_LONG(length);
1167 }
1168 /* }}} */
1169
1170 /* {{{ proto bool Imagick::extentImage(int width, int height, int x, int y )
1171 Sets the image size
1172 */
PHP_METHOD(Imagick,extentImage)1173 PHP_METHOD(Imagick, extentImage)
1174 {
1175 php_imagick_object *intern;
1176 MagickBooleanType status;
1177 im_long width, height, x, y;
1178
1179 /* Parse parameters given to function */
1180 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llll", &width, &height, &x, &y) == FAILURE)
1181 {
1182 return;
1183 }
1184
1185 intern = Z_IMAGICK_P(getThis());
1186 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
1187 return;
1188
1189 status = MagickExtentImage(intern->magick_wand, width, height, x, y);
1190
1191 if (status == MagickFalse) {
1192 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to extent image" TSRMLS_CC);
1193 return;
1194 }
1195
1196 RETURN_TRUE;
1197 }
1198 /* }}} */
1199 #endif
1200
1201 #if MagickLibVersion > 0x633
1202 /* {{{ proto Imagick Imagick::getImageOrientation(void)
1203 Gets the image orientation
1204 */
PHP_METHOD(Imagick,getImageOrientation)1205 PHP_METHOD(Imagick, getImageOrientation)
1206 {
1207 php_imagick_object *intern;
1208
1209 if (zend_parse_parameters_none() == FAILURE) {
1210 return;
1211 }
1212
1213 intern = Z_IMAGICK_P(getThis());
1214 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
1215 return;
1216
1217 RETVAL_LONG(MagickGetImageOrientation(intern->magick_wand));
1218 }
1219 /* }}} */
1220
1221 /* {{{ proto Imagick Imagick::setImageOrientation(int orientation)
1222 Sets the image orientation
1223 */
PHP_METHOD(Imagick,setImageOrientation)1224 PHP_METHOD(Imagick, setImageOrientation)
1225 {
1226 php_imagick_object *intern;
1227 im_long orientation;
1228 MagickBooleanType status;
1229
1230 /* Parse parameters given to function */
1231 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &orientation) == FAILURE) {
1232 return;
1233 }
1234
1235 intern = Z_IMAGICK_P(getThis());
1236 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
1237 return;
1238
1239 status = MagickSetImageOrientation(intern->magick_wand, orientation);
1240
1241 /* No magick is going to happen */
1242 if (status == MagickFalse) {
1243 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image orientation" TSRMLS_CC);
1244 return;
1245 }
1246
1247 RETURN_TRUE;
1248 }
1249 /* }}} */
1250 #endif
1251
1252 #if !defined(MAGICKCORE_EXCLUDE_DEPRECATED)
1253 #if MagickLibVersion > 0x634
1254 #if MagickLibVersion < 0x700
1255 /* {{{ proto Imagick Imagick::paintFloodfillImage(mixed fill, float fuzz, mixed bordercolor, int x, int y[, int channel])
1256 Sets the image orientation
1257 */
PHP_METHOD(Imagick,paintFloodfillImage)1258 PHP_METHOD(Imagick, paintFloodfillImage)
1259 {
1260 php_imagick_object *intern;
1261 zval *fill_param, *border_param;
1262 im_long x, y, channel = DefaultChannels;
1263 double fuzz;
1264 MagickBooleanType status;
1265 PixelWand *fill_wand, *border_wand = NULL;
1266 zend_bool fill_allocated = 0, border_allocated = 0;
1267
1268 IMAGICK_METHOD_DEPRECATED ("Imagick", "paintFloodfillImage");
1269
1270 /* Parse parameters given to function */
1271 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zdzll|l", &fill_param, &fuzz, &border_param, &x, &y, &channel) == FAILURE) {
1272 return;
1273 }
1274
1275 intern = Z_IMAGICK_P(getThis());
1276 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
1277 return;
1278
1279 fill_wand = php_imagick_zval_to_pixelwand (fill_param, IMAGICK_CLASS, &fill_allocated TSRMLS_CC);
1280 if (!fill_wand)
1281 return;
1282
1283 if (Z_TYPE_P(border_param) == IS_NULL) {
1284 status = MagickPaintFloodfillImage(intern->magick_wand, channel, fill_wand, fuzz, NULL, x, y);
1285 } else {
1286 border_wand = php_imagick_zval_to_pixelwand (border_param, IMAGICK_CLASS, &border_allocated TSRMLS_CC);
1287 if (!border_wand) {
1288 if (fill_allocated)
1289 DestroyPixelWand (fill_wand);
1290 return;
1291 }
1292 status = MagickPaintFloodfillImage(intern->magick_wand, channel, fill_wand, fuzz, border_wand, x, y);
1293 }
1294
1295 if (fill_allocated)
1296 DestroyPixelWand (fill_wand);
1297
1298 if (border_wand)
1299 DestroyPixelWand (border_wand);
1300
1301 /* No magick is going to happen */
1302 if (status == MagickFalse) {
1303 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to paint floodfill image" TSRMLS_CC);
1304 return;
1305 }
1306 RETURN_TRUE;
1307 }
1308 /* }}} */
1309 #endif // #if MagickLibVersion < 0x700
1310 #endif
1311 #endif
1312
1313 #if MagickLibVersion > 0x635
1314 /* {{{ proto Imagick Imagick::clutImage(Imagick lookup[, int channel] )
1315 Replaces colors in the image from a color lookup table
1316 */
PHP_METHOD(Imagick,clutImage)1317 PHP_METHOD(Imagick, clutImage)
1318 {
1319 zval *objvar;
1320 php_imagick_object *intern, *lookup;
1321 MagickBooleanType status;
1322 im_long channel = IM_DEFAULT_CHANNEL;
1323
1324 /* Parse parameters given to function */
1325 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|l", &objvar, php_imagick_sc_entry, &channel) == FAILURE) {
1326 return;
1327 }
1328
1329 intern = Z_IMAGICK_P(getThis());
1330 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
1331 return;
1332
1333 lookup = Z_IMAGICK_P(objvar);
1334 if (php_imagick_ensure_not_empty (lookup->magick_wand) == 0)
1335 return;
1336
1337 status = MagickClutImageChannel(intern->magick_wand, channel, lookup->magick_wand);
1338
1339 /* No magick is going to happen */
1340 if (status == MagickFalse) {
1341 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to replace colors in the image from a color lookup table" TSRMLS_CC);
1342 return;
1343 }
1344
1345 RETURN_TRUE;
1346 }
1347 /* }}} */
1348
1349 /* {{{ proto Imagick Imagick::getImageProperties([string pattern, bool values] )
1350 Returns all the property names that match the specified pattern
1351 */
PHP_METHOD(Imagick,getImageProperties)1352 PHP_METHOD(Imagick, getImageProperties)
1353 {
1354 zend_bool values = 1;
1355 char *pattern = "*", **properties, *property;
1356 IM_LEN_TYPE pattern_len;
1357 unsigned long i;
1358 size_t properties_count;
1359 php_imagick_object *intern;
1360
1361 /* Parse parameters given to function */
1362 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sb", &pattern, &pattern_len, &values) == FAILURE) {
1363 return;
1364 }
1365
1366 intern = Z_IMAGICK_P(getThis());
1367 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
1368 return;
1369
1370 properties = MagickGetImageProperties(intern->magick_wand, pattern, &properties_count);
1371
1372 if (!properties) {
1373 php_imagick_throw_exception(IMAGICK_CLASS, "Unable to get image properties" TSRMLS_CC);
1374 return;
1375 }
1376
1377 array_init(return_value);
1378
1379 if (values) {
1380
1381 for (i = 0; i < properties_count; i++) {
1382 property = MagickGetImageProperty(intern->magick_wand, properties[i]);
1383 IM_add_assoc_string(return_value, properties[i], property);
1384 IMAGICK_FREE_MAGICK_MEMORY(property);
1385 }
1386
1387 } else {
1388
1389 for (i = 0; i < properties_count; i++) {
1390 IM_add_next_index_string(return_value, properties[i]);
1391 }
1392 }
1393
1394 IMAGICK_FREE_MAGICK_MEMORY(properties);
1395 return;
1396 }
1397 /* }}} */
1398
1399 /* {{{ proto Imagick Imagick::getImageProfiles([string pattern, bool values] )
1400 Returns all the profile names that match the specified pattern
1401 */
PHP_METHOD(Imagick,getImageProfiles)1402 PHP_METHOD(Imagick, getImageProfiles)
1403 {
1404 zend_bool values = 1;
1405 char *pattern = "*", **profiles, *profile;
1406 IM_LEN_TYPE pattern_len;
1407 unsigned long i;
1408 php_imagick_object *intern;
1409 size_t length, profiles_count;
1410
1411 /* Parse parameters given to function */
1412 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sb", &pattern, &pattern_len, &values) == FAILURE) {
1413 return;
1414 }
1415
1416 intern = Z_IMAGICK_P(getThis());
1417 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
1418 return;
1419
1420 profiles = MagickGetImageProfiles(intern->magick_wand, pattern, &profiles_count);
1421
1422 if (!profiles) {
1423 php_imagick_throw_exception(IMAGICK_CLASS, "Unable to get image profiles" TSRMLS_CC);
1424 return;
1425 }
1426
1427 array_init(return_value);
1428
1429 if (values) {
1430
1431 for (i = 0; i < profiles_count; i++) {
1432
1433 profile = (char *)MagickGetImageProfile(intern->magick_wand, profiles[i], &length);
1434 #if PHP_VERSION_ID >= 70000
1435 add_assoc_stringl(return_value, profiles[i], profile, length);
1436 #else
1437 add_assoc_stringl(return_value, profiles[i], profile, length, 1);
1438 #endif
1439 IMAGICK_FREE_MAGICK_MEMORY(profile);
1440 }
1441
1442 } else {
1443
1444 for (i = 0; i < profiles_count; i++) {
1445 IM_add_next_index_string(return_value, profiles[i]);
1446 }
1447 }
1448
1449 IMAGICK_FREE_MAGICK_MEMORY(profiles);
1450 return;
1451 }
1452 /* }}} */
1453 #endif
1454
1455 #if MagickLibVersion > 0x635
1456 /* {{{ proto Imagick Imagick::distortImage(int distortMethod, array arguments, bool bestfit )
1457 Distorts an image using various distortion methods
1458 */
PHP_METHOD(Imagick,distortImage)1459 PHP_METHOD(Imagick, distortImage)
1460 {
1461 php_imagick_object *intern;
1462 double *arguments;
1463 im_long distort_method, elements;
1464 zend_bool bestfit;
1465 zval *arg_array;
1466 MagickBooleanType status;
1467
1468 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lab", &distort_method, &arg_array, &bestfit) == FAILURE) {
1469 return;
1470 }
1471
1472 intern = Z_IMAGICK_P(getThis());
1473 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
1474 return;
1475
1476 arguments = php_imagick_zval_to_double_array(arg_array, &elements TSRMLS_CC);
1477
1478 if (!arguments) {
1479 php_imagick_throw_exception (IMAGICK_CLASS, "Can't read argument array" TSRMLS_CC);
1480 return;
1481 }
1482
1483 status = MagickDistortImage(intern->magick_wand, distort_method, elements, arguments, bestfit);
1484 efree(arguments);
1485
1486 /* No magick is going to happen */
1487 if (status == MagickFalse) {
1488 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to distort the image" TSRMLS_CC);
1489 return;
1490 }
1491
1492 RETURN_TRUE;
1493 }
1494 /* }}} */
1495
1496 /* {{{ proto bool Imagick::writeImageFile(resource $handle[, string $format])
1497 Writes image to an open filehandle. Optional parameter format defines the format the file
1498 is stored with
1499 */
PHP_METHOD(Imagick,writeImageFile)1500 PHP_METHOD(Imagick, writeImageFile)
1501 {
1502 php_imagick_object *intern;
1503 zval *zstream;
1504 php_stream *stream;
1505 zend_bool result;
1506 char *format = NULL;
1507 IM_LEN_TYPE format_len;
1508 char *orig_name = NULL, *buffer;
1509
1510 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s!", &zstream, &format, &format_len) == FAILURE) {
1511 return;
1512 }
1513
1514 intern = Z_IMAGICK_P(getThis());
1515 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
1516 return;
1517
1518 // Get the current name
1519 if (format) {
1520 orig_name = MagickGetImageFilename (intern->magick_wand);
1521
1522 spprintf (&buffer, 0, "%s:", format);
1523 MagickSetImageFilename (intern->magick_wand, buffer);
1524 efree (buffer);
1525 }
1526
1527 #if PHP_VERSION_ID >= 70000
1528 php_stream_from_zval(stream, zstream);
1529 #else
1530 php_stream_from_zval(stream, &zstream);
1531 #endif
1532 result = php_imagick_stream_handler(intern, stream, ImagickWriteImageFile TSRMLS_CC);
1533
1534 /* Restore the original name after write */
1535 if (orig_name) {
1536 MagickSetImageFilename (intern->magick_wand, orig_name);
1537 MagickRelinquishMemory (orig_name);
1538 }
1539
1540 if (result == 0) {
1541 /* php_stream_cast returns warning on some streams but still does not return FAILURE */
1542 if (!EG(exception)) {
1543 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to write image to the filehandle" TSRMLS_CC);
1544 return;
1545 }
1546 return;
1547 }
1548 RETURN_TRUE;
1549 }
1550 /* }}} */
1551
1552 /* {{{ proto bool Imagick::writeImagesFile(resource $handle[, string $format])
1553 Writes images to an open filehandle
1554 */
PHP_METHOD(Imagick,writeImagesFile)1555 PHP_METHOD(Imagick, writeImagesFile)
1556 {
1557 php_imagick_object *intern;
1558 zval *zstream;
1559 php_stream *stream;
1560 zend_bool result;
1561 char *format = NULL;
1562 IM_LEN_TYPE format_len;
1563 char *orig_name = NULL, *buffer;
1564
1565 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s!", &zstream, &format, &format_len) == FAILURE) {
1566 return;
1567 }
1568
1569 intern = Z_IMAGICK_P(getThis());
1570 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
1571 return;
1572
1573 // Get the current name
1574 if (format) {
1575 orig_name = MagickGetImageFilename (intern->magick_wand);
1576
1577 spprintf (&buffer, 0, "%s:", format);
1578 MagickSetImageFilename (intern->magick_wand, buffer);
1579 efree (buffer);
1580 }
1581
1582 #if PHP_VERSION_ID >= 70000
1583 php_stream_from_zval(stream, zstream);
1584 #else
1585 php_stream_from_zval(stream, &zstream);
1586 #endif
1587 result = php_imagick_stream_handler(intern, stream, ImagickWriteImagesFile TSRMLS_CC);
1588
1589 /* Restore the original name after write */
1590 if (orig_name) {
1591 MagickSetImageFilename (intern->magick_wand, orig_name);
1592 MagickRelinquishMemory (orig_name);
1593 }
1594
1595 if (result == 0) {
1596 if (!EG(exception)) {
1597 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to write images to the filehandle" TSRMLS_CC);
1598 return;
1599 }
1600 return;
1601 }
1602 RETURN_TRUE;
1603 }
1604 /* }}} */
1605
1606 /* {{{ proto bool Imagick::resetImagePage(string page)
1607 Resets the page canvas and position
1608 */
PHP_METHOD(Imagick,resetImagePage)1609 PHP_METHOD(Imagick, resetImagePage)
1610 {
1611 php_imagick_object *intern;
1612 MagickBooleanType status;
1613 char *page;
1614 IM_LEN_TYPE page_len;
1615
1616 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &page, &page_len) == FAILURE) {
1617 return;
1618 }
1619
1620 intern = Z_IMAGICK_P(getThis());
1621 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
1622 return;
1623
1624 status = MagickResetImagePage(intern->magick_wand, page);
1625
1626 if (status == MagickFalse) {
1627 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to reset image page" TSRMLS_CC);
1628 return;
1629 }
1630
1631 RETURN_TRUE;
1632 }
1633 /* }}} */
1634
1635
1636 /* {{{ proto Imagick Imagick::getImageClipMask()
1637 Gets image clip mask
1638 */
1639 #if MagickLibVersion < 0x700
PHP_METHOD(Imagick,getImageClipMask)1640 PHP_METHOD(Imagick, getImageClipMask)
1641 {
1642 MagickWand *tmp_wand;
1643 php_imagick_object *intern;
1644 php_imagick_object *intern_return;
1645
1646 if (zend_parse_parameters_none() == FAILURE) {
1647 return;
1648 }
1649
1650 intern = Z_IMAGICK_P(getThis());
1651 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
1652 return;
1653
1654 tmp_wand = MagickGetImageClipMask(intern->magick_wand);
1655
1656 /* No magick is going to happen */
1657 if (!tmp_wand) {
1658 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get image clip mask" TSRMLS_CC);
1659 return;
1660 }
1661
1662 object_init_ex(return_value, php_imagick_sc_entry);
1663 intern_return = Z_IMAGICK_P(return_value);
1664
1665 php_imagick_replace_magickwand(intern_return, tmp_wand);
1666 return;
1667 }
1668 #endif
1669 /* }}} */
1670
1671 /* {{{ proto bool Imagick::setImageClipMask(Imagick clip_mask)
1672 Sets the image clip mask
1673 */
1674 #if MagickLibVersion < 0x700
PHP_METHOD(Imagick,setImageClipMask)1675 PHP_METHOD(Imagick, setImageClipMask)
1676 {
1677 php_imagick_object *intern;
1678 php_imagick_object *clip_mask;
1679 MagickBooleanType status;
1680 zval *objvar;
1681
1682 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &objvar, php_imagick_sc_entry) == FAILURE) {
1683 return;
1684 }
1685
1686 intern = Z_IMAGICK_P(getThis());
1687 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
1688 return;
1689
1690 clip_mask = Z_IMAGICK_P(objvar);
1691 if (php_imagick_ensure_not_empty (clip_mask->magick_wand) == 0)
1692 return;
1693
1694 status = MagickSetImageClipMask(intern->magick_wand, clip_mask->magick_wand);
1695
1696 if (status == MagickFalse) {
1697 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image clip mask" TSRMLS_CC);
1698 return;
1699 }
1700 RETURN_TRUE;
1701 }
1702 #endif
1703 /* }}} */
1704
1705 /* {{{ proto bool Imagick::animateImages(string server_name)
1706 Animates an image or image sequence
1707 */
PHP_METHOD(Imagick,animateImages)1708 PHP_METHOD(Imagick, animateImages)
1709 {
1710 php_imagick_object *intern;
1711 MagickBooleanType status;
1712 char *server_name;
1713 IM_LEN_TYPE server_name_len;
1714
1715 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &server_name, &server_name_len) == FAILURE) {
1716 return;
1717 }
1718
1719 intern = Z_IMAGICK_P(getThis());
1720 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
1721 return;
1722
1723 /* TODO: should this call be there? Not sure */
1724 (void)MagickSetFirstIterator(intern->magick_wand);
1725 status = MagickAnimateImages(intern->magick_wand, server_name);
1726
1727 if (status == MagickFalse) {
1728 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to animate images" TSRMLS_CC);
1729 return;
1730 }
1731 RETURN_TRUE;
1732 }
1733 /* }}} */
1734
1735 #if !defined(MAGICKCORE_EXCLUDE_DEPRECATED)
1736 #if MagickLibVersion < 0x700
1737 /* {{{ proto bool Imagick::recolorImage(array matrix)
1738 Translate, scale, shear, or rotate image colors
1739 */
PHP_METHOD(Imagick,recolorImage)1740 PHP_METHOD(Imagick, recolorImage)
1741 {
1742 php_imagick_object *intern;
1743 MagickBooleanType status;
1744 im_long num_elements;
1745 zval *matrix;
1746 double *array;
1747 unsigned long order;
1748
1749 IMAGICK_METHOD_DEPRECATED ("Imagick", "recolorImage");
1750
1751 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &matrix) == FAILURE) {
1752 return;
1753 }
1754
1755 intern = Z_IMAGICK_P(getThis());
1756 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
1757 return;
1758
1759 array = php_imagick_zval_to_double_array(matrix, &num_elements TSRMLS_CC);
1760
1761 if (!array) {
1762 php_imagick_throw_exception (IMAGICK_CLASS, "The map contains disallowed characters" TSRMLS_CC);
1763 return;
1764 }
1765
1766 order = (unsigned long)sqrt(num_elements);
1767
1768 if ((order * order) != num_elements) {
1769 efree(array);
1770 php_imagick_throw_exception(IMAGICK_CLASS, "The color matrix must contain a square number of elements" TSRMLS_CC);
1771 return;
1772 }
1773
1774 status = MagickRecolorImage(intern->magick_wand, order, array);
1775 efree(array);
1776
1777 if (status == MagickFalse) {
1778 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to recolor image" TSRMLS_CC);
1779 return;
1780 }
1781
1782 RETURN_TRUE;
1783 }
1784 /* }}} */
1785 #endif
1786 #endif
1787 #endif
1788
1789 #if MagickLibVersion > 0x636
PHP_METHOD(Imagick,setFont)1790 PHP_METHOD(Imagick, setFont)
1791 {
1792 php_imagick_object *intern;
1793 char *font, *absolute;
1794 IM_LEN_TYPE font_len;
1795 MagickBooleanType status;
1796 php_imagick_rw_result_t rc;
1797
1798 /* Parse parameters given to function */
1799 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &font, &font_len) == FAILURE) {
1800 return;
1801 }
1802
1803 /* Check that no empty string is passed */
1804 if (font_len == 0) {
1805 php_imagick_throw_exception(IMAGICK_CLASS, "Can not set empty font" TSRMLS_CC);
1806 return;
1807 }
1808
1809 intern = Z_IMAGICK_P(getThis());
1810
1811 /* And if it wasn't */
1812 if (!php_imagick_check_font(font, font_len TSRMLS_CC)) {
1813
1814 if (!(absolute = expand_filepath(font, NULL TSRMLS_CC))) {
1815 php_imagick_throw_exception(IMAGICK_CLASS, "Unable to set font" TSRMLS_CC);
1816 return;
1817 }
1818
1819 if ((rc = php_imagick_file_access_check (absolute TSRMLS_CC)) != IMAGICK_RW_OK) {
1820 php_imagick_rw_fail_to_exception (intern->magick_wand, rc, absolute TSRMLS_CC);
1821 efree(absolute);
1822 return;
1823 }
1824 status = MagickSetFont(intern->magick_wand, absolute);
1825 efree(absolute);
1826 } else {
1827 status = MagickSetFont(intern->magick_wand, font);
1828 }
1829
1830 /* No magick is going to happen */
1831 if (status == MagickFalse) {
1832 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set font" TSRMLS_CC);
1833 return;
1834 }
1835
1836 RETURN_TRUE;
1837 }
1838
PHP_METHOD(Imagick,getFont)1839 PHP_METHOD(Imagick, getFont)
1840 {
1841 char *font;
1842 php_imagick_object *intern;
1843
1844 if (zend_parse_parameters_none() == FAILURE) {
1845 return;
1846 }
1847
1848 intern = Z_IMAGICK_P(getThis());
1849 font = MagickGetFont(intern->magick_wand);
1850
1851 if (font) {
1852 IM_ZVAL_STRING(return_value, font);
1853 IMAGICK_FREE_MAGICK_MEMORY(font);
1854 return;
1855 }
1856 RETURN_FALSE;
1857 }
1858
PHP_METHOD(Imagick,setPointSize)1859 PHP_METHOD(Imagick, setPointSize)
1860 {
1861 php_imagick_object *intern;
1862 double point_size;
1863 MagickBooleanType status;
1864
1865 /* Parse parameters given to function */
1866 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &point_size) == FAILURE) {
1867 return;
1868 }
1869
1870 intern = Z_IMAGICK_P(getThis());
1871 status = MagickSetPointsize(intern->magick_wand, point_size);
1872
1873 /* No magick is going to happen */
1874 if (status == MagickFalse) {
1875 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set point size" TSRMLS_CC);
1876 return;
1877 }
1878
1879 RETURN_TRUE;
1880 }
1881
PHP_METHOD(Imagick,getPointSize)1882 PHP_METHOD(Imagick, getPointSize)
1883 {
1884 php_imagick_object *intern;
1885
1886 if (zend_parse_parameters_none() == FAILURE) {
1887 return;
1888 }
1889
1890 intern = Z_IMAGICK_P(getThis());
1891 RETVAL_DOUBLE(MagickGetPointsize(intern->magick_wand));
1892 }
1893
PHP_METHOD(Imagick,mergeImageLayers)1894 PHP_METHOD(Imagick, mergeImageLayers)
1895 {
1896 php_imagick_object *intern, *intern_return;
1897 im_long layer_method;
1898 MagickWand *merged;
1899
1900 /* Parse parameters given to function */
1901 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &layer_method) == FAILURE) {
1902 return;
1903 }
1904
1905 intern = Z_IMAGICK_P(getThis());
1906 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
1907 return;
1908
1909 /* TODO: SHOULD THIS BE HERE?
1910 Reset the iterator */
1911 (void)MagickSetFirstIterator(intern->magick_wand);
1912
1913 merged = MagickMergeImageLayers(intern->magick_wand, layer_method);
1914
1915 /* No magick is going to happen */
1916 if (!merged) {
1917 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to merge image layers" TSRMLS_CC);
1918 return;
1919 }
1920
1921 object_init_ex(return_value, php_imagick_sc_entry);
1922 intern_return = Z_IMAGICK_P(return_value);
1923
1924 php_imagick_replace_magickwand(intern_return, merged);
1925 return;
1926 }
1927 #endif
1928
1929 #if MagickLibVersion > 0x637
1930 /* {{{ proto bool Imagick::floodfillPaintImage(mixed fill, float fuzz, mixed bordercolor, int x, int y, bool invert[, int CHANNEL])
1931 Changes the color value of any pixel that matches target
1932 */
PHP_METHOD(Imagick,floodfillPaintImage)1933 PHP_METHOD(Imagick, floodfillPaintImage)
1934 {
1935 php_imagick_object *intern;
1936 MagickBooleanType status;
1937 zval *fill_param, *border_param;
1938 im_long x, y, channel = IM_DEFAULT_CHANNEL;
1939 zend_bool invert;
1940 double fuzz;
1941 PixelWand *fill_wand, *border_wand;
1942 zend_bool fill_allocated = 0, border_allocated = 0;
1943
1944 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zdzllb|l",
1945 &fill_param, &fuzz, &border_param, &x, &y, &invert, &channel) == FAILURE) {
1946 return;
1947 }
1948
1949 intern = Z_IMAGICK_P(getThis());
1950 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
1951 return;
1952
1953 fill_wand = php_imagick_zval_to_pixelwand (fill_param, IMAGICK_CLASS, &fill_allocated TSRMLS_CC);
1954 if (!fill_wand)
1955 return;
1956
1957 border_wand = php_imagick_zval_to_pixelwand (border_param, IMAGICK_CLASS, &border_allocated TSRMLS_CC);
1958 if (!border_wand) {
1959 if (fill_allocated)
1960 fill_wand = DestroyPixelWand (fill_wand);
1961
1962 return;
1963 }
1964
1965 #if MagickLibVersion >= 0x700
1966 status = MagickFloodfillPaintImageChannel(intern->magick_wand, channel, fill_wand, fuzz, border_wand, x, y, invert);
1967 #else
1968 status = MagickFloodfillPaintImage(intern->magick_wand, channel, fill_wand, fuzz, border_wand, x, y, invert);
1969 #endif
1970
1971 if (fill_allocated)
1972 fill_wand = DestroyPixelWand (fill_wand);
1973
1974 if (border_allocated)
1975 border_wand = DestroyPixelWand (border_wand);
1976
1977 if (status == MagickFalse) {
1978 php_imagick_convert_imagick_exception (intern->magick_wand, "Unable to floodfill paint image" TSRMLS_CC);
1979 return;
1980 }
1981
1982 RETURN_TRUE;
1983 }
1984 /* }}} */
1985
1986 /* {{{ proto bool Imagick::opaquePaintImage(mixed target, mixed fill, float fuzz, bool invert[, int CHANNEL])
1987 Changes any pixel that matches color with the color defined by fill.
1988 */
PHP_METHOD(Imagick,opaquePaintImage)1989 PHP_METHOD(Imagick, opaquePaintImage)
1990 {
1991 php_imagick_object *intern;
1992 MagickBooleanType status;
1993 zval *fill_param, *target_param;
1994 zend_bool invert;
1995 double fuzz;
1996 im_long channel = IM_DEFAULT_CHANNEL;
1997 PixelWand *fill_wand, *target_wand;
1998 zend_bool fill_allocated = 0, target_allocated = 0;
1999
2000 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zzdb|l", &fill_param, &target_param, &fuzz, &invert, &channel) == FAILURE) {
2001 return;
2002 }
2003
2004 intern = Z_IMAGICK_P(getThis());
2005 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
2006 return;
2007
2008 fill_wand = php_imagick_zval_to_pixelwand (fill_param, IMAGICK_CLASS, &fill_allocated TSRMLS_CC);
2009 if (!fill_wand)
2010 return;
2011
2012 target_wand = php_imagick_zval_to_pixelwand (target_param, IMAGICK_CLASS, &target_allocated TSRMLS_CC);
2013 if (!target_wand) {
2014 if (fill_allocated)
2015 DestroyPixelWand (fill_wand);
2016 return;
2017 }
2018
2019 status = MagickOpaquePaintImageChannel(intern->magick_wand, channel, fill_wand, target_wand, fuzz, invert);
2020
2021 if (fill_allocated)
2022 DestroyPixelWand (fill_wand);
2023
2024 if (target_allocated)
2025 DestroyPixelWand (target_wand);
2026
2027 if (status == MagickFalse) {
2028 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to opaque paint image" TSRMLS_CC);
2029 return;
2030 }
2031
2032 RETURN_TRUE;
2033 }
2034 /* }}} */
2035
2036 /* {{{ proto bool Imagick::transparentPaintImage(mixed target, float alpha, float fuzz, bool invert)
2037 Changes any pixel that matches color with the color defined by fill
2038 */
PHP_METHOD(Imagick,transparentPaintImage)2039 PHP_METHOD(Imagick, transparentPaintImage)
2040 {
2041 php_imagick_object *intern;
2042 MagickBooleanType status;
2043 zval *target_param;
2044 zend_bool invert;
2045 double fuzz, alpha;
2046 PixelWand *target_wand;
2047 zend_bool target_allocated;
2048
2049 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zddb", &target_param, &alpha, &fuzz, &invert) == FAILURE) {
2050 return;
2051 }
2052
2053 intern = Z_IMAGICK_P(getThis());
2054 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
2055 return;
2056
2057 target_wand = php_imagick_zval_to_pixelwand (target_param, IMAGICK_CLASS, &target_allocated TSRMLS_CC);
2058 if (!target_wand)
2059 return;
2060
2061 status = MagickTransparentPaintImage(intern->magick_wand, target_wand, alpha, fuzz, invert);
2062
2063 if (target_allocated)
2064 target_wand = DestroyPixelWand (target_wand);
2065
2066 if (status == MagickFalse) {
2067 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to paint transparent image" TSRMLS_CC);
2068 return;
2069 }
2070
2071 RETURN_TRUE;
2072 }
2073 /* }}} */
2074
2075 /* {{{ proto Imagick Imagick::setImageAlphaChannel(int ALPHACHANNEL )
2076 Activates, deactivates, resets, or sets the alpha channel
2077 */
PHP_METHOD(Imagick,setImageAlphaChannel)2078 PHP_METHOD(Imagick, setImageAlphaChannel)
2079 {
2080 php_imagick_object *intern;
2081 im_long alpha_channel;
2082 MagickBooleanType status;
2083
2084 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &alpha_channel) == FAILURE) {
2085 return;
2086 }
2087
2088 intern = Z_IMAGICK_P(getThis());
2089 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
2090 return;
2091
2092 status = MagickSetImageAlphaChannel(intern->magick_wand, alpha_channel);
2093
2094 if (status == MagickFalse) {
2095 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image alpha channel" TSRMLS_CC);
2096 return;
2097 }
2098 RETURN_TRUE;
2099 }
2100 #endif
2101
2102 #if MagickLibVersion > 0x638
2103 /* {{{ proto Imagick Imagick::liquidRescaleImage(int cols, int rows, float delta_x, float rigidity )
2104 Rescales image with seam carving
2105 */
PHP_METHOD(Imagick,liquidRescaleImage)2106 PHP_METHOD(Imagick, liquidRescaleImage)
2107 {
2108 php_imagick_object *intern;
2109 im_long cols, rows;
2110 double delta_x, rigidity;
2111 MagickBooleanType status;
2112
2113 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lldd", &cols, &rows, &delta_x, &rigidity) == FAILURE) {
2114 return;
2115 }
2116
2117 intern = Z_IMAGICK_P(getThis());
2118 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
2119 return;
2120
2121 status = MagickLiquidRescaleImage(intern->magick_wand, cols, rows, delta_x, rigidity);
2122
2123 if (status == MagickFalse) {
2124 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to liquid rescale image" TSRMLS_CC);
2125 return;
2126 }
2127
2128 RETURN_TRUE;
2129 }
2130 /* }}} */
2131
2132 /* {{{ proto bool Imagick::decipherImage(string passphrase)
2133 Converts cipher pixels to plain pixels
2134 */
PHP_METHOD(Imagick,decipherImage)2135 PHP_METHOD(Imagick, decipherImage)
2136 {
2137 php_imagick_object *intern;
2138 MagickBooleanType status;
2139 char *passphrase;
2140 IM_LEN_TYPE passphrase_len;
2141
2142 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &passphrase, &passphrase_len) == FAILURE) {
2143 return;
2144 }
2145
2146 intern = Z_IMAGICK_P(getThis());
2147 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
2148 return;
2149
2150 status = MagickDecipherImage(intern->magick_wand, passphrase);
2151
2152 if (status == MagickFalse) {
2153 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to decipher image" TSRMLS_CC);
2154 return;
2155 }
2156 RETURN_TRUE;
2157 }
2158 /* }}} */
2159
2160 /* {{{ proto bool Imagick::encipherImage(string passphrase)
2161 Converts plain pixels to cipher pixels
2162 */
PHP_METHOD(Imagick,encipherImage)2163 PHP_METHOD(Imagick, encipherImage)
2164 {
2165 php_imagick_object *intern;
2166 MagickBooleanType status;
2167 char *passphrase;
2168 IM_LEN_TYPE passphrase_len;
2169
2170 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &passphrase, &passphrase_len) == FAILURE) {
2171 return;
2172 }
2173
2174 intern = Z_IMAGICK_P(getThis());
2175 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
2176 return;
2177
2178 status = MagickEncipherImage(intern->magick_wand, passphrase);
2179
2180 if (status == MagickFalse) {
2181 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to encipher image" TSRMLS_CC);
2182 return;
2183 }
2184 RETURN_TRUE;
2185 }
2186 /* }}} */
2187 #endif
2188
2189 #if MagickLibVersion > 0x639
2190 /* {{ proto bool Imagick::setGravity(int GRAVITY)
2191 Sets the gravity value
2192 */
PHP_METHOD(Imagick,setGravity)2193 PHP_METHOD(Imagick, setGravity)
2194 {
2195 php_imagick_object *intern;
2196 im_long gravity;
2197
2198 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &gravity) == FAILURE) {
2199 return;
2200 }
2201
2202 intern = Z_IMAGICK_P(getThis());
2203
2204 if (MagickSetGravity(intern->magick_wand, gravity) == MagickFalse) {
2205 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set gravity" TSRMLS_CC);
2206 return;
2207 }
2208
2209 RETURN_TRUE;
2210 }
2211 /* }}} */
2212
2213 /* {{ proto int Imagick::getGravity()
2214 Gets the gravity value
2215 */
PHP_METHOD(Imagick,getGravity)2216 PHP_METHOD(Imagick, getGravity)
2217 {
2218 php_imagick_object *intern;
2219
2220 if (zend_parse_parameters_none() == FAILURE) {
2221 return;
2222 }
2223
2224 intern = Z_IMAGICK_P(getThis());
2225
2226 RETVAL_LONG(MagickGetGravity(intern->magick_wand));
2227 }
2228 /* }}} */
2229
2230 /* {{ proto Imagick Imagick::getImageChannelRange(int CHANNEL)
2231 Gets the image channel's range
2232 */
PHP_METHOD(Imagick,getImageChannelRange)2233 PHP_METHOD(Imagick, getImageChannelRange)
2234 {
2235 php_imagick_object *intern;
2236 im_long channel;
2237 double maxima, minima;
2238
2239 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &channel) == FAILURE) {
2240 return;
2241 }
2242
2243 intern = Z_IMAGICK_P(getThis());
2244
2245 if (MagickGetImageChannelRange(intern->magick_wand, channel, &minima, &maxima) == MagickFalse) {
2246 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get channel range" TSRMLS_CC);
2247 return;
2248 }
2249
2250 array_init(return_value);
2251
2252 add_assoc_double(return_value, "minima", minima);
2253 add_assoc_double(return_value, "maxima", maxima);
2254
2255 return;
2256 }
2257 /* }}} */
2258
2259 /* {{{ proto int Imagick::getImageAlphaChannel()
2260 Gets the image alpha channel value
2261 */
PHP_METHOD(Imagick,getImageAlphaChannel)2262 PHP_METHOD(Imagick, getImageAlphaChannel)
2263 {
2264 php_imagick_object *intern;
2265
2266 if (zend_parse_parameters_none() == FAILURE) {
2267 return;
2268 }
2269
2270 intern = Z_IMAGICK_P(getThis());
2271 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
2272 return;
2273
2274 RETVAL_LONG(MagickGetImageAlphaChannel(intern->magick_wand));
2275 }
2276 /* }}} */
2277 #endif
2278
2279 #if MagickLibVersion > 0x642
2280 /* {{{ proto float Imagick::getImageChannelDistortions(Imagick reference, int METRICTYPE[, int CHANNEL])
2281 Compares one or more image channels of an image to a reconstructed image and returns the specified distortion metrics
2282 */
PHP_METHOD(Imagick,getImageChannelDistortions)2283 PHP_METHOD(Imagick, getImageChannelDistortions)
2284 {
2285 php_imagick_object *intern;
2286 php_imagick_object *intern_reference;
2287 zval *reference_param;
2288 double distortion;
2289 im_long metric, channel = DefaultChannels;
2290 MagickBooleanType status;
2291
2292 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol|l", &reference_param, php_imagick_sc_entry, &metric, &channel) == FAILURE) {
2293 return;
2294 }
2295
2296 intern = Z_IMAGICK_P(getThis());
2297 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
2298 return;
2299
2300 intern_reference = Z_IMAGICK_P(reference_param);
2301 if (php_imagick_ensure_not_empty (intern_reference->magick_wand) == 0)
2302 return;
2303
2304 status = MagickGetImageChannelDistortion(intern->magick_wand, intern_reference->magick_wand, channel, metric, &distortion);
2305
2306 if (status == MagickFalse) {
2307 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get image channel distortion metrics" TSRMLS_CC);
2308 return;
2309 }
2310
2311 RETVAL_DOUBLE(distortion);
2312 }
2313 /* }}} */
2314 #endif
2315
2316 #if MagickLibVersion > 0x643
2317 /* {{{ proto int Imagick::getImageGravity()
2318 Gets the image gravity
2319 */
PHP_METHOD(Imagick,getImageGravity)2320 PHP_METHOD(Imagick, getImageGravity)
2321 {
2322 php_imagick_object *intern;
2323
2324 if (zend_parse_parameters_none() == FAILURE) {
2325 return;
2326 }
2327
2328 intern = Z_IMAGICK_P(getThis());
2329 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
2330 return;
2331
2332 RETVAL_LONG(MagickGetImageGravity(intern->magick_wand));
2333 }
2334 /* }}} */
2335
2336 /* {{{ proto bool Imagick::setImageGravity(int GRAVITY)
2337 Sets the image gravity
2338 */
PHP_METHOD(Imagick,setImageGravity)2339 PHP_METHOD(Imagick, setImageGravity)
2340 {
2341 php_imagick_object *intern;
2342 MagickBooleanType status;
2343 im_long gravity;
2344
2345 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &gravity) == FAILURE) {
2346 return;
2347 }
2348
2349 intern = Z_IMAGICK_P(getThis());
2350 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
2351 return;
2352
2353 status = MagickSetImageGravity(intern->magick_wand, gravity);
2354
2355 if (status == MagickFalse) {
2356 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image gravity" TSRMLS_CC);
2357 return;
2358 }
2359
2360 RETURN_TRUE;
2361 }
2362 /* }}} */
2363 #endif
2364
2365 #if MagickLibVersion > 0x645
2366 /* {{ proto Imagick Imagick::importImagePixels(int x, int y, int width, int height, string map, int STORAGE, array pixels)
2367 Accepts pixel data and stores it in the image at the location you specify
2368 */
PHP_METHOD(Imagick,importImagePixels)2369 PHP_METHOD(Imagick, importImagePixels)
2370 {
2371 double *double_array;
2372 im_long *long_array;
2373 unsigned char *char_array;
2374
2375 php_imagick_object *intern;
2376 MagickBooleanType status;
2377
2378 im_long storage, num_elements;
2379 im_long x, y, width, height;
2380 IM_LEN_TYPE map_len;
2381 char *map;
2382 zval *pixels;
2383 HashTable *array;
2384
2385 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llllsla", &x, &y, &width, &height, &map, &map_len, &storage, &pixels) == FAILURE) {
2386 return;
2387 }
2388
2389 intern = Z_IMAGICK_P(getThis());
2390 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
2391 return;
2392
2393 if (x < 0 || y < 0) {
2394 php_imagick_throw_exception (IMAGICK_CLASS, "The coordinates must be non-negative" TSRMLS_CC);
2395 return;
2396 }
2397
2398 if (width <= 0 || height <= 0) {
2399 php_imagick_throw_exception(IMAGICK_CLASS, "The width and height must be greater than zero" TSRMLS_CC);
2400 return;
2401 }
2402
2403 array = Z_ARRVAL_P(pixels);
2404
2405 if (zend_hash_num_elements(array) != ((width * height) * map_len)) {
2406 php_imagick_throw_exception(IMAGICK_CLASS, "The map contains incorrect number of elements" TSRMLS_CC);
2407 return;
2408 } else {
2409 if (!php_imagick_validate_map(map TSRMLS_CC)) {
2410 php_imagick_throw_exception(IMAGICK_CLASS, "The map contains disallowed characters" TSRMLS_CC);
2411 return;
2412 }
2413 }
2414
2415 switch (storage) {
2416 case FloatPixel:
2417 case DoublePixel:
2418 /* Use doubles */
2419 storage = DoublePixel;
2420 double_array = php_imagick_zval_to_double_array(pixels, &num_elements TSRMLS_CC);
2421 if (!double_array) {
2422 php_imagick_throw_exception(IMAGICK_CLASS, "The map must contain only numeric values" TSRMLS_CC);
2423 return;
2424 }
2425 status = MagickImportImagePixels(intern->magick_wand, x, y, width, height, map, storage, double_array);
2426 efree(double_array);
2427 break;
2428
2429 case ShortPixel:
2430 #if MagickLibVersion < 0x700
2431 case IntegerPixel:
2432 #endif
2433 case LongPixel:
2434 /* Use longs */
2435 storage = LongPixel;
2436 long_array = php_imagick_zval_to_long_array(pixels, &num_elements TSRMLS_CC);
2437 if (!long_array) {
2438 php_imagick_throw_exception(IMAGICK_CLASS, "The map must contain only numeric values" TSRMLS_CC);
2439 return;
2440 }
2441 status = MagickImportImagePixels(intern->magick_wand, x, y, width, height, map, storage, long_array);
2442 efree(long_array);
2443 break;
2444
2445 case CharPixel:
2446 char_array = php_imagick_zval_to_char_array(pixels, &num_elements TSRMLS_CC);
2447 if (!char_array) {
2448 php_imagick_throw_exception(IMAGICK_CLASS, "The character array contains incorrect values" TSRMLS_CC);
2449 return;
2450 }
2451 status = MagickImportImagePixels(intern->magick_wand, x, y, width, height, map, storage, char_array);
2452 efree(char_array);
2453 break;
2454
2455 default:
2456 php_imagick_throw_exception(IMAGICK_CLASS, "Unknown storage format" TSRMLS_CC);
2457 return;
2458 break;
2459 }
2460
2461 if (status == MagickFalse) {
2462 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to import image pixels" TSRMLS_CC);
2463 return;
2464 }
2465 RETURN_TRUE;
2466 }
2467 /* }}} */
2468
PHP_METHOD(Imagick,deskewImage)2469 PHP_METHOD(Imagick, deskewImage)
2470 {
2471 php_imagick_object *intern;
2472 MagickBooleanType status;
2473 double threshold;
2474
2475 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &threshold) == FAILURE) {
2476 return;
2477 }
2478
2479 intern = Z_IMAGICK_P(getThis());
2480 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
2481 return;
2482
2483 status = MagickDeskewImage(intern->magick_wand, threshold);
2484 if (status == MagickFalse) {
2485 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to deskew image" TSRMLS_CC);
2486 return;
2487 }
2488 RETURN_TRUE;
2489 }
2490
2491
2492 #if PHP_IMAGICK_HAVE_HOUGHLINE
2493 /* {{{ proto bool Imagick::houghLineImage(int width, int height, float threshold)
2494 Draw hough lines for the image
2495
2496 */
PHP_METHOD(Imagick,houghLineImage)2497 PHP_METHOD(Imagick, houghLineImage)
2498 {
2499 php_imagick_object *intern;
2500 MagickBooleanType status;
2501 double threshold;
2502 im_long width, height;
2503
2504 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lld", &width, &height, &threshold) == FAILURE) {
2505 return;
2506 }
2507
2508 intern = Z_IMAGICK_P(getThis());
2509 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
2510 return;
2511
2512 status = MagickHoughLineImage(intern->magick_wand, width, height, threshold);
2513 if (status == MagickFalse) {
2514 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to Hough line image" TSRMLS_CC);
2515 return;
2516 }
2517 RETURN_TRUE;
2518 }
2519 /* }}} */
2520 #endif
2521
PHP_METHOD(Imagick,segmentImage)2522 PHP_METHOD(Imagick, segmentImage)
2523 {
2524 php_imagick_object *intern;
2525 MagickBooleanType status;
2526 im_long colorspace;
2527 zend_bool verbose = 0;
2528 double cluster_threshold, smooth_threshold;
2529
2530 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ldd|b", &colorspace, &cluster_threshold, &smooth_threshold, &verbose) == FAILURE) {
2531 return;
2532 }
2533
2534 intern = Z_IMAGICK_P(getThis());
2535 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
2536 return;
2537
2538 status = MagickSegmentImage(intern->magick_wand, colorspace, verbose, cluster_threshold, smooth_threshold);
2539
2540 if (status == MagickFalse) {
2541 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to segment image" TSRMLS_CC);
2542 return;
2543 }
2544 RETURN_TRUE;
2545 }
2546
PHP_METHOD(Imagick,sparseColorImage)2547 PHP_METHOD(Imagick, sparseColorImage)
2548 {
2549 php_imagick_object *intern;
2550 MagickBooleanType status;
2551 im_long num_elements, sparse_method, channel = IM_DEFAULT_CHANNEL;
2552 zval *arguments;
2553 double *double_array;
2554
2555 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "la|l", &sparse_method, &arguments, &channel) == FAILURE) {
2556 return;
2557 }
2558
2559 intern = Z_IMAGICK_P(getThis());
2560 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
2561 return;
2562
2563 double_array = php_imagick_zval_to_double_array(arguments, &num_elements TSRMLS_CC);
2564
2565 if (!double_array) {
2566 php_imagick_throw_exception(IMAGICK_CLASS, "The map must contain only numeric values" TSRMLS_CC);
2567 return;
2568 }
2569
2570 #if MagickLibVersion >= 0x700
2571 status = MagickSparseColorImageChannel(intern->magick_wand, channel, sparse_method, num_elements, double_array);
2572 #else
2573 status = MagickSparseColorImage(intern->magick_wand, channel, sparse_method, num_elements, double_array);
2574 #endif
2575
2576 efree(double_array);
2577
2578 if (status == MagickFalse) {
2579 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to sparse color image" TSRMLS_CC);
2580 return;
2581 }
2582 RETURN_TRUE;
2583 }
2584
2585 /* {{{ proto bool Imagick::remapImage(Imagick remap, int DITHERMETHOD)
2586 replaces the colors of an image with the closest color from a reference image
2587 */
PHP_METHOD(Imagick,remapImage)2588 PHP_METHOD(Imagick, remapImage)
2589 {
2590 php_imagick_object *intern;
2591 php_imagick_object *intern_remap;
2592 MagickBooleanType status;
2593 im_long dither_method;
2594 zval *remap_param;
2595
2596 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol", &remap_param, php_imagick_sc_entry, &dither_method) == FAILURE) {
2597 return;
2598 }
2599
2600 intern = Z_IMAGICK_P(getThis());
2601 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
2602 return;
2603
2604 intern_remap = Z_IMAGICK_P(remap_param);
2605 if (php_imagick_ensure_not_empty (intern_remap->magick_wand) == 0)
2606 return;
2607
2608 status = MagickRemapImage(intern->magick_wand, intern_remap->magick_wand, dither_method);
2609
2610 if (status == MagickFalse) {
2611 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to remap image" TSRMLS_CC);
2612 return;
2613 }
2614
2615 RETURN_TRUE;
2616 }
2617 /* }}} */
2618 #endif
2619
2620 #if MagickLibVersion > 0x646
2621 /* {{{ proto bool Imagick::exportImagePixels(int x, int y, int width, int height, string map, INT STORAGE)
2622
2623 The types for the PixelStorage types are:
2624
2625 CharPixel - unsigned 1 byte integer
2626 DoublePixel - 8 byte floating point
2627 FloatPixel - 4 byte floating point
2628 IntegerPixel - Removed in IM7 unsigned 4 byte integer
2629 LongPixel - unsigned 4 byte integer
2630 QuantumPixel - Quantum, use the defined type from the IM headers.
2631 ShortPixel - unsigned 2 byte integer
2632
2633
2634 */
PHP_METHOD(Imagick,exportImagePixels)2635 PHP_METHOD(Imagick, exportImagePixels)
2636 {
2637 php_imagick_object *intern;
2638 MagickBooleanType status;
2639 im_long x, y, width, height, storage;
2640 char *map;
2641 int map_size, i = 0;
2642 IM_LEN_TYPE map_len;
2643 double *double_array;
2644 float *float_array;
2645 unsigned char *char_array;
2646 unsigned short *short_array;
2647 unsigned int *long_array; // The long pixel type is implemented in ImageMagick as 'unsigned int'
2648 Quantum *quantum_array;
2649 #if MagickLibVersion >= 0x700
2650 unsigned long long int *longlong_array;
2651 #endif
2652
2653 #if INT_MAX != 0x7FFFFFFF
2654 #error "INT_MAX is not 0x7FFFFFFF, the code below assumes it is, as does the ImageMagick code"
2655 // If this happens, you will need to figure out how to make long_array be an array of
2656 // 4 byte unsigned ints
2657 #endif
2658
2659
2660 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llllsl", &x, &y, &width, &height, &map, &map_len, &storage) == FAILURE) {
2661 return;
2662 }
2663
2664 if ((x < 0) || (y < 0)) {
2665 php_imagick_throw_exception(IMAGICK_CLASS, "The coordinates must be non-negative" TSRMLS_CC);
2666 return;
2667 }
2668
2669 if (width <= 0 || height <= 0) {
2670 php_imagick_throw_exception(IMAGICK_CLASS, "The width and height must be greater than zero" TSRMLS_CC);
2671 return;
2672 }
2673
2674 if (!php_imagick_validate_map(map TSRMLS_CC)) {
2675 php_imagick_throw_exception(IMAGICK_CLASS, "The map contains disallowed characters" TSRMLS_CC);
2676 return;
2677 }
2678
2679 intern = Z_IMAGICK_P(getThis());
2680 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
2681 return;
2682
2683 map_size = (map_len * width * height);
2684
2685 switch (storage) {
2686 case FloatPixel:
2687 float_array = emalloc(map_size * sizeof(float));
2688 status = MagickExportImagePixels(intern->magick_wand, x, y, width, height, map, FloatPixel, (void *)float_array);
2689
2690 if (status != MagickFalse) {
2691 array_init(return_value);
2692 for (i = 0; i < map_size; i++) {
2693 add_next_index_double(return_value, float_array[i]);
2694 }
2695 efree(float_array);
2696 return;
2697 }
2698 break;
2699
2700 case DoublePixel:
2701 double_array = emalloc(map_size * sizeof(double));
2702 status = MagickExportImagePixels(intern->magick_wand, x, y, width, height, map, DoublePixel, (void *)double_array);
2703
2704 if (status != MagickFalse) {
2705 array_init(return_value);
2706 for (i = 0; i < map_size; i++) {
2707 add_next_index_double(return_value, double_array[i]);
2708 }
2709 efree(double_array);
2710 return;
2711 }
2712 break;
2713
2714 case ShortPixel:
2715 short_array = emalloc(map_size * sizeof(unsigned short));
2716 status = MagickExportImagePixels(intern->magick_wand, x, y, width, height, map, ShortPixel, (void *)short_array);
2717
2718 if (status != MagickFalse) {
2719 array_init(return_value);
2720 for (i = 0; i < map_size; i++) {
2721 add_next_index_long(return_value, short_array[i]);
2722 }
2723 efree(short_array);
2724 return;
2725 }
2726 break;
2727
2728 #if MagickLibVersion >= 0x700
2729 case LongLongPixel:
2730 longlong_array = emalloc(map_size * sizeof(unsigned long long int));
2731 status = MagickExportImagePixels(intern->magick_wand, x, y, width, height, map, LongLongPixel, (void *)longlong_array);
2732
2733 if (status != MagickFalse) {
2734 array_init(return_value);
2735 for (i = 0; i < map_size; i++) {
2736 //TODO - think about this.
2737 // on 32bit platforms this will be truncating data
2738 // on 64bit platforms where sizeof(longlong) > 64bits, it will be truncating
2739 // on 64bit platforms where sizeof(longlong) = 64bits, PHP will be
2740 // converting values close to 64bit to be floats...
2741 add_next_index_long(return_value, longlong_array[i]);
2742 }
2743 efree(longlong_array);
2744 return;
2745 }
2746 break;
2747 #endif
2748
2749 #if MagickLibVersion < 0x700
2750 case IntegerPixel:
2751 #endif
2752 case LongPixel:
2753 long_array = emalloc(map_size * sizeof(unsigned int));
2754 status = MagickExportImagePixels(intern->magick_wand, x, y, width, height, map, LongPixel, (void *)long_array);
2755
2756 if (status != MagickFalse) {
2757 array_init(return_value);
2758 for (i = 0; i < map_size; i++) {
2759 add_next_index_long(return_value, long_array[i]);
2760 }
2761 efree(long_array);
2762 return;
2763 }
2764 break;
2765
2766 case CharPixel:
2767 char_array = emalloc(map_size * sizeof(char));
2768 status = MagickExportImagePixels(intern->magick_wand, x, y, width, height, map, CharPixel, (void *)char_array);
2769
2770 if (status != MagickFalse) {
2771 array_init(return_value);
2772 for (i = 0; i < map_size; i++) {
2773 add_next_index_long(return_value, (int)char_array[i]);
2774 }
2775 efree(char_array);
2776 return;
2777 }
2778 break;
2779
2780 case QuantumPixel:
2781 quantum_array = emalloc(map_size * sizeof(Quantum));
2782 status = MagickExportImagePixels(intern->magick_wand, x, y, width, height, map, QuantumPixel, (void *)quantum_array);
2783
2784 if (status != MagickFalse) {
2785 array_init(return_value);
2786 for (i = 0; i < map_size; i++) {
2787 #if MAGICKCORE_HDRI_ENABLE
2788 add_next_index_double(return_value, quantum_array[i]);
2789 #else
2790 add_next_index_long(return_value, quantum_array[i]);
2791 #endif
2792 }
2793 efree(quantum_array);
2794 return;
2795 }
2796 break;
2797
2798 default:
2799 php_imagick_throw_exception(IMAGICK_CLASS, "Unknown pixel type " TSRMLS_CC);
2800 return;
2801 break;
2802 }
2803
2804 if (status == MagickFalse) {
2805 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to export image pixels" TSRMLS_CC);
2806 return;
2807 }
2808 return;
2809 }
2810 /* }}} */
2811 #endif
2812
2813 #if MagickLibVersion > 0x648
2814 /* {{{ proto array Imagick::getImageChannelKurtosis([int CHANNEL])
2815 Gets the kurtosis and skewness of one or more image channels
2816 */
PHP_METHOD(Imagick,getImageChannelKurtosis)2817 PHP_METHOD(Imagick, getImageChannelKurtosis)
2818 {
2819 php_imagick_object *intern;
2820 MagickBooleanType status;
2821 double kurtosis, skewness;
2822 im_long channel = DefaultChannels;
2823
2824 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &channel) == FAILURE) {
2825 return;
2826 }
2827
2828 intern = Z_IMAGICK_P(getThis());
2829 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
2830 return;
2831
2832 status = MagickGetImageChannelKurtosis(intern->magick_wand, channel, &kurtosis, &skewness);
2833
2834 if (status == MagickFalse) {
2835 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get image channel kurtosis" TSRMLS_CC);
2836 return;
2837 }
2838
2839 array_init(return_value);
2840 add_assoc_double(return_value, "kurtosis", kurtosis);
2841 add_assoc_double(return_value, "skewness", skewness);
2842 return;
2843 }
2844 /* }}} */
2845
2846 /* {{{ proto bool Imagick::functionImage(int FUNCTION, array arguments[, int CHANNEL])
2847 Applies an arithmetic, relational, or logical expression to an image
2848 */
PHP_METHOD(Imagick,functionImage)2849 PHP_METHOD(Imagick, functionImage)
2850 {
2851 php_imagick_object *intern;
2852 MagickBooleanType status;
2853 zval *arguments;
2854 im_long func, num_elements, channel = IM_DEFAULT_CHANNEL;
2855 double *array;
2856
2857 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "la|l", &func, &arguments, &channel) == FAILURE) {
2858 return;
2859 }
2860
2861 intern = Z_IMAGICK_P(getThis());
2862 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
2863 return;
2864
2865 array = php_imagick_zval_to_double_array(arguments, &num_elements TSRMLS_CC);
2866
2867 if (!array) {
2868 php_imagick_throw_exception(IMAGICK_CLASS, "The arguments array contains disallowed characters or is empty." TSRMLS_CC);
2869 return;
2870 }
2871
2872 status = MagickFunctionImageChannel(intern->magick_wand, channel, func, num_elements, array);
2873 efree(array);
2874
2875 if (status == MagickFalse) {
2876 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to execute function on the image" TSRMLS_CC);
2877 return;
2878 }
2879
2880 RETURN_TRUE;
2881 }
2882 /* }}} */
2883 #endif
2884
2885 #if MagickLibVersion > 0x651
2886 /* {{{ proto boolean Imagick::transformImageColorspace(int COLORSPACE)
2887 Transform image colorspace
2888 */
PHP_METHOD(Imagick,transformImageColorspace)2889 PHP_METHOD(Imagick, transformImageColorspace)
2890 {
2891 php_imagick_object *intern;
2892 im_long colorspace;
2893 MagickBooleanType status;
2894
2895 /* Parse parameters given to function */
2896 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &colorspace) == FAILURE) {
2897 return;
2898 }
2899
2900 intern = Z_IMAGICK_P(getThis());
2901 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
2902 return;
2903
2904 status = MagickTransformImageColorspace(intern->magick_wand, colorspace);
2905
2906 /* No magick is going to happen */
2907 if (status == MagickFalse) {
2908 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to transform image colorspace" TSRMLS_CC);
2909 return;
2910 }
2911 RETURN_TRUE;
2912 }
2913 /* }}} */
2914 #endif
2915
2916 #if MagickLibVersion > 0x652
2917 /* {{{ proto boolean Imagick::haldClutImage(Imagick hald[, int CHANNEL])
2918 Replaces colors in the image from a Hald color lookup table
2919 */
PHP_METHOD(Imagick,haldClutImage)2920 PHP_METHOD(Imagick, haldClutImage)
2921 {
2922 zval *objvar;
2923 MagickBooleanType status;
2924 php_imagick_object *intern, *hald;
2925 im_long channel = IM_DEFAULT_CHANNEL;
2926
2927 /* Parse parameters given to function */
2928 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|l", &objvar, php_imagick_sc_entry, &channel) == FAILURE) {
2929 return;
2930 }
2931
2932 intern = Z_IMAGICK_P(getThis());
2933 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
2934 return;
2935
2936 hald = Z_IMAGICK_P(objvar);
2937 if (php_imagick_ensure_not_empty (hald->magick_wand) == 0)
2938 return;
2939
2940 status = MagickHaldClutImageChannel(intern->magick_wand, channel, hald->magick_wand);
2941
2942 /* No magick is going to happen */
2943 if (status == MagickFalse) {
2944 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to hald clut image" TSRMLS_CC);
2945 return;
2946 }
2947 RETURN_TRUE;
2948 }
2949 /* }}} */
2950 #endif
2951
2952 #if MagickLibVersion > 0x655
2953 /* {{{ proto boolean Imagick::autoLevelImage([int CHANNEL])
2954 Adjusts the levels of a particular image channel by scaling the minimum and maximum values to the full quantum range.
2955 */
PHP_METHOD(Imagick,autoLevelImage)2956 PHP_METHOD(Imagick, autoLevelImage)
2957 {
2958 php_imagick_object *intern;
2959 MagickBooleanType status;
2960 im_long channel = IM_DEFAULT_CHANNEL;
2961
2962 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &channel) == FAILURE) {
2963 return;
2964 }
2965
2966 intern = Z_IMAGICK_P(getThis());
2967 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
2968 return;
2969
2970 status = MagickAutoLevelImageChannel(intern->magick_wand, channel);
2971 if (status == MagickFalse) {
2972 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to autolevel image" TSRMLS_CC);
2973 return;
2974 }
2975 RETURN_TRUE;
2976 }
2977 /* }}} */
2978
2979 /* {{{ proto boolean Imagick::blueShiftImage([float $factor = 1.5])
2980 Mutes the colors of the image to simulate a scene at nighttime in the moonlight.
2981 */
PHP_METHOD(Imagick,blueShiftImage)2982 PHP_METHOD(Imagick, blueShiftImage)
2983 {
2984 php_imagick_object *intern;
2985 MagickBooleanType status;
2986 double factor = 1.5;
2987
2988 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|d", &factor) == FAILURE) {
2989 return;
2990 }
2991
2992 intern = Z_IMAGICK_P(getThis());
2993 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
2994 return;
2995
2996 status = MagickBlueShiftImage(intern->magick_wand, factor);
2997 if (status == MagickFalse) {
2998 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to blue shift image" TSRMLS_CC);
2999 return;
3000 }
3001 RETURN_TRUE;
3002 }
3003 /* }}} */
3004 #endif
3005
3006 #if MagickLibVersion > 0x656
PHP_METHOD(Imagick,setImageArtifact)3007 PHP_METHOD(Imagick, setImageArtifact)
3008 {
3009 php_imagick_object *intern;
3010 MagickBooleanType status;
3011 char *artifact, *value;
3012 IM_LEN_TYPE artifact_len, value_len;
3013
3014 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &artifact, &artifact_len, &value, &value_len) == FAILURE) {
3015 return;
3016 }
3017
3018 intern = Z_IMAGICK_P(getThis());
3019 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
3020 return;
3021
3022 status = MagickSetImageArtifact(intern->magick_wand, artifact, value);
3023 if (status == MagickFalse) {
3024 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image artifact" TSRMLS_CC);
3025 return;
3026 }
3027 RETURN_TRUE;
3028 }
3029
3030
PHP_METHOD(Imagick,getImageArtifact)3031 PHP_METHOD(Imagick, getImageArtifact)
3032 {
3033 php_imagick_object *intern;
3034 char *artifact, *value;
3035 IM_LEN_TYPE artifact_len;
3036
3037 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &artifact, &artifact_len) == FAILURE) {
3038 return;
3039 }
3040
3041 intern = Z_IMAGICK_P(getThis());
3042 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
3043 return;
3044
3045 value = MagickGetImageArtifact(intern->magick_wand, artifact);
3046
3047 if (!value) {
3048 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get image artifact" TSRMLS_CC);
3049 return;
3050 }
3051 #if PHP_VERSION_ID >= 70000
3052 RETVAL_STRING(value);
3053 #else
3054 RETVAL_STRING(value, 1);
3055 #endif
3056 IMAGICK_FREE_MAGICK_MEMORY(value);
3057 return;
3058 }
3059
3060 /* {{{ proto boolean Imagick::deleteImageArtifact(string $artifact)
3061 Delete image artifact
3062 */
PHP_METHOD(Imagick,deleteImageArtifact)3063 PHP_METHOD(Imagick, deleteImageArtifact)
3064 {
3065 php_imagick_object *intern;
3066 MagickBooleanType status;
3067 char *artifact;
3068 IM_LEN_TYPE artifact_len;
3069
3070 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &artifact, &artifact_len) == FAILURE) {
3071 return;
3072 }
3073
3074 intern = Z_IMAGICK_P(getThis());
3075 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
3076 return;
3077
3078 status = MagickDeleteImageArtifact(intern->magick_wand, artifact);
3079
3080 if (status == MagickFalse) {
3081 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to delete image artifact" TSRMLS_CC);
3082 return;
3083 }
3084
3085 RETURN_TRUE;
3086 }
3087 /* }}} */
3088
3089 /* {{{ proto integer Imagick::getColorspace()
3090 Get the object colorspace property
3091 */
PHP_METHOD(Imagick,getColorspace)3092 PHP_METHOD(Imagick, getColorspace)
3093 {
3094 php_imagick_object *intern;
3095
3096 if (zend_parse_parameters_none() == FAILURE) {
3097 return;
3098 }
3099
3100 intern = Z_IMAGICK_P(getThis());
3101 RETURN_LONG(MagickGetColorspace(intern->magick_wand));
3102 }
3103 /* }}} */
3104
3105 /* {{{ proto boolean Imagick::setColorspace([int COLORSPACE])
3106 Set the object colorspace property
3107 */
PHP_METHOD(Imagick,setColorspace)3108 PHP_METHOD(Imagick, setColorspace)
3109 {
3110 php_imagick_object *intern;
3111 im_long colorspace;
3112 MagickBooleanType status;
3113
3114 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &colorspace) == FAILURE) {
3115 return;
3116 }
3117
3118 intern = Z_IMAGICK_P(getThis());
3119 status = MagickSetColorspace(intern->magick_wand, colorspace);
3120
3121 RETURN_BOOL(status == MagickTrue);
3122 }
3123 /* }}} */
3124
3125 /* {{{ proto boolean Imagick::clampImage([int CHANNEL])
3126 Restricts the color range from 0 to the quantum depth.
3127 */
PHP_METHOD(Imagick,clampImage)3128 PHP_METHOD(Imagick, clampImage)
3129 {
3130 php_imagick_object *intern;
3131 im_long channel = IM_DEFAULT_CHANNEL;
3132 MagickBooleanType status;
3133
3134 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &channel) == FAILURE) {
3135 return;
3136 }
3137
3138 intern = Z_IMAGICK_P(getThis());
3139 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
3140 return;
3141
3142 status = MagickClampImageChannel(intern->magick_wand, channel);
3143
3144 if (status == MagickFalse) {
3145 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to clamp image" TSRMLS_CC);
3146 return;
3147 }
3148
3149 RETURN_TRUE;
3150 }
3151 /* }}} */
3152 #endif
3153
3154 #if MagickLibVersion > 0x667
3155 /* {{{ proto Imagick Imagick::smushImages(boolean stack, int offset)
3156 Takes all images from the current image pointer to the end of the image list and smushs
3157 them to each other top-to-bottom if the stack parameter is true, otherwise left-to-right.
3158 */
PHP_METHOD(Imagick,smushImages)3159 PHP_METHOD(Imagick, smushImages)
3160 {
3161 php_imagick_object *intern, *intern_return;
3162 zend_bool stack;
3163 long offset;
3164 MagickWand *retwand;
3165
3166 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "bl", &stack, &offset) == FAILURE) {
3167 return;
3168 }
3169
3170 intern = Z_IMAGICK_P(getThis());
3171 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
3172 return;
3173
3174 retwand = MagickSmushImages(intern->magick_wand, (stack ? MagickTrue : MagickFalse), offset);
3175
3176 if (!retwand) {
3177 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to smush images" TSRMLS_CC);
3178 return;
3179 }
3180
3181 object_init_ex(return_value, php_imagick_sc_entry);
3182 intern_return = Z_IMAGICK_P(return_value);
3183 php_imagick_replace_magickwand(intern_return, retwand);
3184 return;
3185 }
3186 /* }}} */
3187 #endif
3188
3189 /* {{{ proto Imagick Imagick::__construct([mixed files] )
3190 The Imagick constructor
3191 */
3192 #if PHP_VERSION_ID >= 70000
PHP_METHOD(Imagick,__construct)3193 PHP_METHOD(Imagick, __construct)
3194 {
3195 php_imagick_object *intern;
3196 zval *files = NULL;
3197
3198 zval *pzval;
3199 php_imagick_rw_result_t rc;
3200
3201 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z!/", &files) == FAILURE) {
3202 return;
3203 }
3204
3205 /* No files given.. or null passed */
3206 if (!files) {
3207 return;
3208 }
3209 intern = Z_IMAGICK_P(getThis());
3210
3211 if (Z_TYPE_P (files) == IS_LONG || Z_TYPE_P (files) == IS_DOUBLE) {
3212 convert_to_string (files);
3213 }
3214
3215 /* A single file was given */
3216 if (Z_TYPE_P(files) == IS_STRING) {
3217 struct php_imagick_file_t file = {0};
3218
3219 if (!php_imagick_file_init(&file, Z_STRVAL_P(files), Z_STRLEN_P(files) TSRMLS_CC)) {
3220 php_imagick_throw_exception(IMAGICK_CLASS, "Invalid filename provided" TSRMLS_CC);
3221 return;
3222 }
3223 rc = php_imagick_read_file(intern, &file, ImagickReadImage TSRMLS_CC);
3224 php_imagick_file_deinit(&file);
3225
3226 if (rc != IMAGICK_RW_OK) {
3227 php_imagick_rw_fail_to_exception (intern->magick_wand, rc, Z_STRVAL_P(files) TSRMLS_CC);
3228 return;
3229 }
3230 }
3231
3232 /* an array of filenames was given */
3233 else
3234 if (Z_TYPE_P(files) == IS_ARRAY) {
3235 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(files), pzval) {
3236 struct php_imagick_file_t file = {0};
3237 ZVAL_DEREF(pzval);
3238
3239 if (!php_imagick_file_init(&file, Z_STRVAL_P(pzval), Z_STRLEN_P(pzval) TSRMLS_CC)) {
3240 php_imagick_throw_exception(IMAGICK_CLASS, "Invalid filename provided" TSRMLS_CC);
3241 return;
3242 }
3243
3244 rc = php_imagick_read_file(intern, &file, ImagickReadImage TSRMLS_CC);
3245 php_imagick_file_deinit(&file);
3246
3247 if (rc != IMAGICK_RW_OK) {
3248 php_imagick_rw_fail_to_exception (intern->magick_wand, rc, Z_STRVAL_P(pzval) TSRMLS_CC);
3249 return;
3250 }
3251 } ZEND_HASH_FOREACH_END();
3252 }
3253 if (Z_TYPE_P(files) == IS_FALSE || Z_TYPE_P(files) == IS_TRUE) {
3254 php_imagick_throw_exception(IMAGICK_CLASS, "Constructor shouldn't be called with a boolean as the filename");
3255 }
3256
3257 RETURN_TRUE;
3258 }
3259 #else
PHP_METHOD(Imagick,__construct)3260 PHP_METHOD(Imagick, __construct)
3261 {
3262 php_imagick_object *intern;
3263 zval *files = NULL;
3264 HashPosition pos;
3265 php_imagick_rw_result_t rc;
3266
3267 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z!/", &files) == FAILURE) {
3268 return;
3269 }
3270
3271 /* No files given.. or null passed */
3272 if (!files) {
3273 return;
3274 }
3275 intern = Z_IMAGICK_P(getThis());
3276
3277 if (Z_TYPE_P (files) == IS_LONG || Z_TYPE_P (files) == IS_DOUBLE) {
3278 convert_to_string (files);
3279 }
3280
3281 /* A single file was given */
3282 if (Z_TYPE_P(files) == IS_STRING) {
3283 struct php_imagick_file_t file = {0};
3284
3285 if (!php_imagick_file_init(&file, Z_STRVAL_P(files), Z_STRLEN_P(files) TSRMLS_CC)) {
3286 php_imagick_throw_exception(IMAGICK_CLASS, "Invalid filename provided" TSRMLS_CC);
3287 return;
3288 }
3289 rc = php_imagick_read_file(intern, &file, ImagickReadImage TSRMLS_CC);
3290 php_imagick_file_deinit(&file);
3291
3292 if (rc != IMAGICK_RW_OK) {
3293 php_imagick_rw_fail_to_exception (intern->magick_wand, rc, Z_STRVAL_P(files) TSRMLS_CC);
3294 return;
3295 }
3296 }
3297
3298 /* an array of filenames was given */
3299 else
3300 if (Z_TYPE_P(files) == IS_ARRAY) {
3301 for(zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(files), &pos);
3302 zend_hash_has_more_elements_ex(Z_ARRVAL_P(files), &pos) == SUCCESS;
3303 zend_hash_move_forward_ex(Z_ARRVAL_P(files), &pos)) {
3304
3305 struct php_imagick_file_t file = {0};
3306 zval **ppzval;
3307
3308 if (zend_hash_get_current_data_ex(Z_ARRVAL_P(files), (void**)&ppzval, &pos) == FAILURE) {
3309 continue;
3310 }
3311
3312 if (!php_imagick_file_init(&file, Z_STRVAL_PP(ppzval), Z_STRLEN_PP(ppzval) TSRMLS_CC)) {
3313 php_imagick_throw_exception(IMAGICK_CLASS, "Invalid filename provided" TSRMLS_CC);
3314 return;
3315 }
3316
3317 rc = php_imagick_read_file(intern, &file, ImagickReadImage TSRMLS_CC);
3318 php_imagick_file_deinit(&file);
3319
3320 if (rc != IMAGICK_RW_OK) {
3321 php_imagick_rw_fail_to_exception (intern->magick_wand, rc, Z_STRVAL_PP(ppzval) TSRMLS_CC);
3322 return;
3323 }
3324 }
3325 }
3326
3327 if (Z_TYPE_P(files) == IS_BOOL) {
3328 php_imagick_throw_exception(IMAGICK_CLASS, "Constructor shouldn't be called with a boolean as the filename" TSRMLS_CC);
3329 }
3330
3331 RETURN_TRUE;
3332 }
3333 #endif
3334 /* }}} */
3335
3336 /* {{{ proto string Imagick::__toString()
3337 Returns the current image as string
3338 */
PHP_METHOD(Imagick,__toString)3339 PHP_METHOD(Imagick, __toString)
3340 {
3341 php_imagick_object *intern;
3342 unsigned char *image;
3343 char *buffer;
3344 size_t image_size;
3345
3346 if (zend_parse_parameters_none() == FAILURE) {
3347 return;
3348 }
3349
3350 intern = Z_IMAGICK_P(getThis());
3351
3352 if (MagickGetNumberImages(intern->magick_wand) == 0) {
3353 IM_ZVAL_STRING(return_value, "");
3354 return;
3355 }
3356
3357 buffer = MagickGetImageFormat(intern->magick_wand);
3358
3359 if (!buffer) {
3360 IM_ZVAL_STRING(return_value, "");
3361 return;
3362 } else {
3363 IMAGICK_FREE_MAGICK_MEMORY(buffer);
3364 }
3365
3366 image = MagickGetImageBlob(intern->magick_wand, &image_size);
3367 IM_ZVAL_STRINGL(return_value, (char *)image, image_size);
3368 IMAGICK_FREE_MAGICK_MEMORY(image);
3369 return;
3370 }
3371 /* }}} */
3372
3373 /* {{{ proto string Imagick::count()
3374 Returns the number of images
3375 */
PHP_METHOD(Imagick,count)3376 PHP_METHOD(Imagick, count)
3377 {
3378 php_imagick_object *intern;
3379 im_long mode = 0;
3380
3381 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &mode) == FAILURE) {
3382 return;
3383 }
3384
3385 intern = Z_IMAGICK_P(getThis());
3386 RETVAL_LONG (MagickGetNumberImages(intern->magick_wand));
3387 }
3388 /* }}} */
3389
3390 /* {{{ proto array Imagick::queryFormats([string pattern] )
3391 Returns formats supported by ImageMagick
3392 */
PHP_METHOD(Imagick,queryFormats)3393 PHP_METHOD(Imagick, queryFormats)
3394 {
3395 char **supported_formats;
3396 unsigned long i;
3397 char *pattern = "*";
3398 IM_LEN_TYPE pattern_len = 1;
3399 size_t num_formats = 0;
3400
3401 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &pattern, &pattern_len) == FAILURE) {
3402 return;
3403 }
3404
3405 supported_formats = (char **) MagickQueryFormats(pattern, &num_formats);
3406 array_init(return_value);
3407
3408 for (i = 0 ; i < num_formats ; i++) {
3409 IM_add_next_index_string(return_value, supported_formats[i]);
3410 IMAGICK_FREE_MAGICK_MEMORY(supported_formats[i]);
3411 }
3412
3413 IMAGICK_FREE_MAGICK_MEMORY(supported_formats);
3414 return;
3415 }
3416 /* }}} */
3417
3418 /* {{{ proto array Imagick::queryFonts([string pattern] )
3419 Returns fonts supported by ImageMagick
3420 */
PHP_METHOD(Imagick,queryFonts)3421 PHP_METHOD(Imagick, queryFonts)
3422 {
3423 char **fonts;
3424 unsigned long i;
3425 char *pattern = "*";
3426 IM_LEN_TYPE pattern_len = 1;
3427 size_t num_fonts;
3428
3429 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &pattern, &pattern_len) == FAILURE) {
3430 return;
3431 }
3432
3433 fonts = (char **) MagickQueryFonts(pattern, &num_fonts);
3434 array_init(return_value);
3435
3436 for (i = 0 ; i < num_fonts ; i++) {
3437 IM_add_next_index_string(return_value, fonts[i]);
3438 IMAGICK_FREE_MAGICK_MEMORY(fonts[i]);
3439 }
3440
3441 IMAGICK_FREE_MAGICK_MEMORY(fonts);
3442 return;
3443 }
3444 /* }}} */
3445
3446 /* {{{ proto array Imagick::queryFontMetrics(ImagickDraw draw, string text[, bool multiline] )
3447 Returns a 13 element array representing the font metrics
3448 */
PHP_METHOD(Imagick,queryFontMetrics)3449 PHP_METHOD(Imagick, queryFontMetrics)
3450 {
3451 zval *objvar, *multiline;
3452 zend_bool remove_canvas, query_multiline;
3453 php_imagick_object *intern;
3454 php_imagickdraw_object *internd;
3455 char *text;
3456 IM_LEN_TYPE text_len;
3457 double *metrics;
3458
3459 multiline = NULL;
3460 remove_canvas = 0;
3461 query_multiline = 0;
3462
3463 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|z!", &objvar, php_imagickdraw_sc_entry, &text, &text_len, &multiline) == FAILURE) {
3464 return;
3465 }
3466
3467 /* No parameter passed, this means we should autodetect */
3468 if (!multiline) {
3469 if (strchr (text, '\n') != NULL) {
3470 query_multiline = 1;
3471 }
3472 } else {
3473 convert_to_boolean(multiline);
3474 #if PHP_VERSION_ID >= 70000
3475 if (Z_TYPE_P(multiline) == IS_TRUE) {
3476 query_multiline = 1;
3477 }
3478 #else
3479 query_multiline = Z_BVAL_P(multiline);
3480 #endif
3481 }
3482
3483 /* fetch the objects */
3484 intern = Z_IMAGICK_P(getThis());
3485 internd = Z_IMAGICKDRAW_P(objvar);
3486
3487 /* If wand is empty, create a 1x1 pixel image to use as a temporary canvas */
3488 if (MagickGetNumberImages(intern->magick_wand) < 1) {
3489 PixelWand *pixel_wand;
3490 MagickBooleanType status;
3491
3492 /* Empty bg color */
3493 pixel_wand = NewPixelWand();
3494
3495 if (!pixel_wand) {
3496 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to allocate background color for the temporary canvas" TSRMLS_CC);
3497 return;
3498 }
3499
3500 /* 1x1 should be enough to get the metrics */
3501 status = MagickNewImage(intern->magick_wand, 1, 1, pixel_wand);
3502 pixel_wand = DestroyPixelWand(pixel_wand);
3503
3504 if (status == MagickFalse) {
3505 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to allocate temporary canvas" TSRMLS_CC);
3506 return;
3507 }
3508 remove_canvas = 1;
3509 }
3510
3511 /* Multiline testing */
3512 if (query_multiline) {
3513 metrics = MagickQueryMultilineFontMetrics(intern->magick_wand, internd->drawing_wand, text);
3514 } else {
3515 metrics = MagickQueryFontMetrics(intern->magick_wand, internd->drawing_wand, text);
3516 }
3517
3518 /* Remove the image from the stack*/
3519 if (remove_canvas) {
3520 MagickRemoveImage(intern->magick_wand);
3521 }
3522
3523 if (!metrics) {
3524 php_imagick_convert_imagick_exception(intern->magick_wand, "Failed to query the font metrics" TSRMLS_CC);
3525 return;
3526 } else {
3527 zval *pbounding;
3528 #if PHP_VERSION_ID >= 70000
3529 zval bounding;
3530 pbounding = &bounding;
3531 #else
3532 MAKE_STD_ZVAL(pbounding)
3533 #endif
3534
3535 array_init(return_value);
3536 add_assoc_double(return_value, "characterWidth", metrics[0]);
3537 add_assoc_double(return_value, "characterHeight", metrics[1]);
3538 add_assoc_double(return_value, "ascender", metrics[2]);
3539 add_assoc_double(return_value, "descender", metrics[3]);
3540 add_assoc_double(return_value, "textWidth", metrics[4]);
3541 add_assoc_double(return_value, "textHeight", metrics[5]);
3542 add_assoc_double(return_value, "maxHorizontalAdvance", metrics[6]);
3543
3544 array_init(pbounding);
3545 add_assoc_double(pbounding, "x1", metrics[7]);
3546 add_assoc_double(pbounding, "y1", metrics[8]);
3547 add_assoc_double(pbounding, "x2", metrics[9]);
3548 add_assoc_double(pbounding, "y2", metrics[10]);
3549 add_assoc_zval(return_value, "boundingBox", pbounding);
3550 add_assoc_double(return_value, "originX", metrics[11]);
3551 add_assoc_double(return_value, "originY", metrics[12]);
3552
3553 IMAGICK_FREE_MAGICK_MEMORY(metrics);
3554 return;
3555 }
3556 }
3557 /* }}} */
3558
3559 /* {{{ proto bool Imagick::valid()
3560 Checks if the current item is valid
3561 */
PHP_METHOD(Imagick,valid)3562 PHP_METHOD(Imagick, valid)
3563 {
3564 php_imagick_object *intern;
3565
3566 if (zend_parse_parameters_none() == FAILURE) {
3567 return;
3568 }
3569
3570 intern = Z_IMAGICK_P(getThis());
3571
3572 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
3573 return;
3574
3575 if (intern->next_out_of_bound) {
3576 RETURN_FALSE;
3577 }
3578 RETURN_TRUE;
3579 }
3580 /* }}} */
3581
3582 /* {{{ proto Imagick Imagick::current()
3583 Returns reference to the current imagick object with image pointer at the correct sequence.
3584 */
PHP_METHOD(Imagick,current)3585 PHP_METHOD(Imagick, current)
3586 {
3587 if (zend_parse_parameters_none() == FAILURE) {
3588 return;
3589 }
3590
3591 RETURN_ZVAL(getThis(), 1, 0);
3592 }
3593 /* }}} */
3594
3595 /* {{{ proto bool Imagick::readImage(string filename)
3596 Reads image from filename
3597 */
PHP_METHOD(Imagick,readImage)3598 PHP_METHOD(Imagick, readImage)
3599 {
3600 char *filename;
3601 IM_LEN_TYPE filename_len;
3602 php_imagick_object *intern;
3603 struct php_imagick_file_t file = {0};
3604 php_imagick_rw_result_t rc;
3605
3606 /* Parse parameters given to function */
3607 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
3608 return;
3609 }
3610
3611 intern = Z_IMAGICK_P(getThis());
3612
3613 if (!php_imagick_file_init(&file, filename, filename_len TSRMLS_CC)) {
3614 php_imagick_throw_exception(IMAGICK_CLASS, "Invalid filename provided" TSRMLS_CC);
3615 return;
3616 }
3617
3618 rc = php_imagick_read_file(intern, &file, ImagickReadImage TSRMLS_CC);
3619 php_imagick_file_deinit(&file);
3620
3621 if (rc != IMAGICK_RW_OK) {
3622 php_imagick_rw_fail_to_exception (intern->magick_wand, rc, filename TSRMLS_CC);
3623 return;
3624 }
3625
3626 RETURN_TRUE;
3627 }
3628 /* }}} */
3629
3630 /* {{{ proto bool Imagick::readImages(array files )
3631 Reads image from an array of filenames
3632 */
3633 #if PHP_VERSION_ID >= 70000
PHP_METHOD(Imagick,readImages)3634 PHP_METHOD(Imagick, readImages)
3635 {
3636
3637 zval *value;
3638 zval *files;
3639 php_imagick_object *intern;
3640 php_imagick_rw_result_t rc;
3641
3642 /* Parse parameters given to function */
3643 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &files) == FAILURE) {
3644 return;
3645 }
3646
3647 intern = Z_IMAGICK_P(getThis());
3648 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(files), value) {
3649 struct php_imagick_file_t file = {0};
3650 ZVAL_DEREF(value);
3651
3652 if (!php_imagick_file_init(&file, Z_STRVAL_P(value), Z_STRLEN_P(value) TSRMLS_CC)) {
3653 php_imagick_throw_exception(IMAGICK_CLASS, "Invalid filename provided" TSRMLS_CC);
3654 return;
3655 }
3656
3657 rc = php_imagick_read_file(intern, &file, ImagickReadImage TSRMLS_CC);
3658 php_imagick_file_deinit(&file);
3659
3660 if (rc != IMAGICK_RW_OK) {
3661 php_imagick_rw_fail_to_exception (intern->magick_wand, rc, Z_STRVAL_P(value) TSRMLS_CC);
3662 return;
3663 }
3664 } ZEND_HASH_FOREACH_END();
3665 RETURN_TRUE;
3666 }
3667 #else
PHP_METHOD(Imagick,readImages)3668 PHP_METHOD(Imagick, readImages)
3669 {
3670 zval *files;
3671 php_imagick_object *intern;
3672 HashPosition pos;
3673 php_imagick_rw_result_t rc;
3674
3675 /* Parse parameters given to function */
3676 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &files) == FAILURE) {
3677 return;
3678 }
3679
3680 intern = Z_IMAGICK_P(getThis());
3681
3682 for(zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(files), &pos);
3683 zend_hash_has_more_elements_ex(Z_ARRVAL_P(files), &pos) == SUCCESS;
3684 zend_hash_move_forward_ex(Z_ARRVAL_P(files), &pos)) {
3685
3686 struct php_imagick_file_t file = {0};
3687 zval **ppzval;
3688
3689 if (zend_hash_get_current_data_ex(Z_ARRVAL_P(files), (void**)&ppzval, &pos) == FAILURE) {
3690 continue;
3691 }
3692
3693 if (!php_imagick_file_init(&file, Z_STRVAL_PP(ppzval), Z_STRLEN_PP(ppzval) TSRMLS_CC)) {
3694 php_imagick_throw_exception(IMAGICK_CLASS, "Invalid filename provided" TSRMLS_CC);
3695 return;
3696 }
3697
3698 rc = php_imagick_read_file(intern, &file, ImagickReadImage TSRMLS_CC);
3699 php_imagick_file_deinit(&file);
3700
3701 if (rc != IMAGICK_RW_OK) {
3702 php_imagick_rw_fail_to_exception (intern->magick_wand, rc, Z_STRVAL_PP(ppzval) TSRMLS_CC);
3703 return;
3704 }
3705 }
3706 RETURN_TRUE;
3707 }
3708 #endif
3709
3710
3711 /* {{{ proto bool Imagick::pingImage(string filename )
3712 This method can be used to query image width, height, size, and format without reading the whole image in to memory.
3713 */
PHP_METHOD(Imagick,pingImage)3714 PHP_METHOD(Imagick, pingImage)
3715 {
3716 char *filename;
3717 IM_LEN_TYPE filename_len;
3718 php_imagick_object *intern;
3719 struct php_imagick_file_t file = {0};
3720 php_imagick_rw_result_t rc;
3721
3722 /* Parse parameters given to function */
3723 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
3724 return;
3725 }
3726
3727 intern = Z_IMAGICK_P(getThis());
3728
3729 if (!php_imagick_file_init(&file, filename, filename_len TSRMLS_CC)) {
3730 php_imagick_throw_exception(IMAGICK_CLASS, "Invalid filename provided" TSRMLS_CC);
3731 return;
3732 }
3733 rc = php_imagick_read_file(intern, &file, ImagickPingImage TSRMLS_CC);
3734 php_imagick_file_deinit(&file);
3735
3736 if (rc != IMAGICK_RW_OK) {
3737 php_imagick_rw_fail_to_exception (intern->magick_wand, rc, filename TSRMLS_CC);
3738 return;
3739 }
3740 RETURN_TRUE;
3741 }
3742 /* }}} */
3743
3744 /* {{{ proto bool Imagick::readImageFile(resource filehandle[, string filename])
3745 Reads image from open filehandle
3746 */
PHP_METHOD(Imagick,readImageFile)3747 PHP_METHOD(Imagick, readImageFile)
3748 {
3749 char *filename = NULL;
3750 IM_LEN_TYPE filename_len;
3751 php_imagick_object *intern;
3752 zval *zstream;
3753 zend_bool result;
3754 php_stream *stream;
3755
3756 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s!", &zstream, &filename, &filename_len) == FAILURE) {
3757 return;
3758 }
3759
3760 intern = Z_IMAGICK_P(getThis());
3761
3762 #if PHP_VERSION_ID >= 70000
3763 php_stream_from_zval(stream, zstream);
3764 #else
3765 php_stream_from_zval(stream, &zstream);
3766 #endif
3767 result = php_imagick_stream_handler(intern, stream, ImagickReadImageFile TSRMLS_CC);
3768
3769 if (result == 0) {
3770 if (!EG(exception)) {
3771 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to read image from the filehandle" TSRMLS_CC);
3772 return;
3773 }
3774 return;
3775 }
3776
3777 if (filename) {
3778 MagickSetImageFilename(intern->magick_wand, filename);
3779 MagickSetLastIterator(intern->magick_wand);
3780 }
3781
3782 RETURN_TRUE;
3783 }
3784 /* }}} */
3785
3786 /* {{{ proto bool Imagick::displayImage(string serverName )
3787 Displays an image
3788 */
PHP_METHOD(Imagick,displayImage)3789 PHP_METHOD(Imagick, displayImage)
3790 {
3791 php_imagick_object *intern;
3792 MagickBooleanType status;
3793 char *server_name;
3794 IM_LEN_TYPE server_name_len;
3795
3796 /* Parse parameters given to function */
3797 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &server_name, &server_name_len) == FAILURE) {
3798 return;
3799 }
3800
3801 intern = Z_IMAGICK_P(getThis());
3802 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
3803 return;
3804
3805 status = MagickDisplayImage(intern->magick_wand, server_name);
3806
3807 /* No magick is going to happen */
3808 if (status == MagickFalse) {
3809 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to display image" TSRMLS_CC);
3810 return;
3811 }
3812
3813 RETURN_TRUE;
3814 }
3815 /* }}} */
3816
3817 /* {{{ proto bool Imagick::displayImages(string serverName )
3818 displays an image or image sequence
3819 */
PHP_METHOD(Imagick,displayImages)3820 PHP_METHOD(Imagick, displayImages)
3821 {
3822 php_imagick_object *intern;
3823 MagickBooleanType status;
3824 char *server_name;
3825 IM_LEN_TYPE server_name_len;
3826
3827 /* Parse parameters given to function */
3828 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &server_name, &server_name_len) == FAILURE) {
3829 return;
3830 }
3831
3832 intern = Z_IMAGICK_P(getThis());
3833 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
3834 return;
3835
3836 status = MagickDisplayImages(intern->magick_wand, server_name);
3837
3838 /* No magick is going to happen */
3839 if (status == MagickFalse) {
3840 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to display images" TSRMLS_CC);
3841 return;
3842 }
3843
3844 RETURN_TRUE;
3845 }
3846 /* }}} */
3847
3848 /* {{{ proto bool Imagick::readBlob(string image )
3849 Reads image from a binary string
3850 */
PHP_METHOD(Imagick,readImageBlob)3851 PHP_METHOD(Imagick, readImageBlob)
3852 {
3853 char *image_string;
3854 char *filename = NULL;
3855 long filename_len;
3856 IM_LEN_TYPE image_string_len;
3857 MagickBooleanType status;
3858 php_imagick_object *intern;
3859
3860 /* Parse parameters given to function */
3861 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!", &image_string, &image_string_len, &filename, &filename_len) == FAILURE) {
3862 return;
3863 }
3864
3865 if (!image_string_len) {
3866 php_imagick_throw_exception(IMAGICK_CLASS, "Zero size image string passed" TSRMLS_CC);
3867 return;
3868 }
3869
3870 intern = Z_IMAGICK_P(getThis());
3871 status = MagickReadImageBlob(intern->magick_wand, image_string, image_string_len);
3872
3873 /* No magick is going to happen */
3874 if (status == MagickFalse) {
3875 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to read image blob" TSRMLS_CC);
3876 return;
3877 }
3878
3879 /* Even if filename is null we need to give a name here. Otherwise segfaults will happen */
3880 MagickSetImageFilename(intern->magick_wand, filename);
3881 MagickSetLastIterator(intern->magick_wand);
3882 RETURN_TRUE;
3883 }
3884 /* }}} */
3885
3886 /* {{{ proto bool Imagick::blurImage(float radius, float sigma[, int channel ] )
3887 Adds blur filter to image. Optional third parameter to blur a specific channel.
3888 */
PHP_METHOD(Imagick,blurImage)3889 PHP_METHOD(Imagick, blurImage)
3890 {
3891 double radius, sigma;
3892 php_imagick_object *intern;
3893 MagickBooleanType status;
3894 /* Initialize channel type to all channels*/
3895 im_long channel = IM_DEFAULT_CHANNEL;
3896
3897 /* Parse parameters given to function */
3898 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd|l", &radius, &sigma, &channel) == FAILURE) {
3899 return;
3900 }
3901
3902 intern = Z_IMAGICK_P(getThis());
3903 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
3904 return;
3905
3906 status = MagickBlurImageChannel(intern->magick_wand, channel, radius, sigma);
3907
3908 /* No magick is going to happen */
3909 if (status == MagickFalse) {
3910 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to blur image" TSRMLS_CC);
3911 return;
3912 }
3913
3914 RETURN_TRUE;
3915 }
3916 /* }}} */
3917
3918 /* {{{ proto bool Imagick::waveImage(float amplitude, float length )
3919 Adds wave filter to the image.
3920 */
PHP_METHOD(Imagick,waveImage)3921 PHP_METHOD(Imagick, waveImage)
3922 {
3923 double amplitude, wave_length;
3924 php_imagick_object *intern;
3925 MagickBooleanType status;
3926
3927 /* Parse parameters given to function */
3928 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &litude, &wave_length) == FAILURE) {
3929 return;
3930 }
3931
3932 intern = Z_IMAGICK_P(getThis());
3933 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
3934 return;
3935
3936 #if MagickLibVersion >= 0x700
3937 {
3938 //TODO allow PixelInterpolateMethod be set
3939 PixelInterpolateMethod method = BilinearInterpolatePixel;
3940 status = MagickWaveImage(intern->magick_wand, amplitude, wave_length, method);
3941 }
3942 #else
3943 status = MagickWaveImage(intern->magick_wand, amplitude, wave_length);
3944 #endif
3945
3946 /* No magick is going to happen */
3947 if (status == MagickFalse) {
3948 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to wave image" TSRMLS_CC);
3949 return;
3950 }
3951
3952 RETURN_TRUE;
3953 }
3954 /* }}} */
3955
3956 /* {{{ proto bool Imagick::clear()
3957 Clears all resources associated to Imagick object
3958 */
PHP_METHOD(Imagick,clear)3959 PHP_METHOD(Imagick, clear)
3960 {
3961 php_imagick_object *intern;
3962
3963 if (zend_parse_parameters_none() == FAILURE) {
3964 return;
3965 }
3966
3967 intern = Z_IMAGICK_P(getThis());
3968
3969 if (!intern->magick_wand) {
3970 RETURN_FALSE;
3971 }
3972
3973 ClearMagickWand(intern->magick_wand);
3974 RETURN_TRUE;
3975 }
3976 /* }}} */
3977
3978 /* {{{ proto bool Imagick::scaleImage(int width, int height[, bool bestfit = false[, bool legacy]] )
3979 Scales the size of an image to the given dimensions. Passing zero as either of
3980 the arguments will preserve dimension while scaling.
3981 If legacy is true, the calculations are done with the small rounding bug that existed in
3982 Imagick before 3.4.0. If false, the calculations should produce the same results as
3983 ImageMagick CLI does.
3984 */
PHP_METHOD(Imagick,scaleImage)3985 PHP_METHOD(Imagick, scaleImage)
3986 {
3987 im_long width, height, new_width, new_height;
3988 php_imagick_object *intern;
3989 MagickBooleanType status;
3990 zend_bool bestfit = 0;
3991 zend_bool legacy = 0;
3992
3993 /* Parse parameters given to function */
3994 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll|bb", &width, &height, &bestfit, &legacy) == FAILURE) {
3995 return;
3996 }
3997
3998 intern = Z_IMAGICK_P(getThis());
3999 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4000 return;
4001
4002 if (!php_imagick_thumbnail_dimensions(intern->magick_wand, bestfit, width, height, &new_width, &new_height, legacy)) {
4003 php_imagick_throw_exception(IMAGICK_CLASS, "Invalid image geometry" TSRMLS_CC);
4004 return;
4005 }
4006
4007 status = MagickScaleImage(intern->magick_wand, new_width, new_height);
4008
4009 /* No magick is going to happen */
4010 if (status == MagickFalse) {
4011 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to scale image" TSRMLS_CC);
4012 return;
4013 }
4014
4015 RETURN_TRUE;
4016 }
4017 /* }}} */
4018
4019 /* {{{ proto bool Imagick::cropImage(int width, height, int x, int y )
4020 Extracts a region of the image.
4021 */
PHP_METHOD(Imagick,cropImage)4022 PHP_METHOD(Imagick, cropImage)
4023 {
4024 im_long width, height, x, y;
4025 php_imagick_object *intern;
4026 MagickBooleanType status;
4027
4028 /* Parse parameters given to function */
4029 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llll", &width, &height, &x, &y) == FAILURE) {
4030 return;
4031 }
4032
4033 intern = Z_IMAGICK_P(getThis());
4034 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4035 return;
4036
4037 status = MagickCropImage(intern->magick_wand, width, height, x, y);
4038
4039 /* No magick is going to happen */
4040 if (status == MagickFalse) {
4041 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to crop image" TSRMLS_CC);
4042 return;
4043 }
4044
4045 RETURN_TRUE;
4046 }
4047 /* }}} */
4048
4049 /* {{{ proto bool Imagick::spreadImage(float radius )
4050 Special effects method that randomly displaces each pixel in a block defined by the radius parameter.
4051 */
PHP_METHOD(Imagick,spreadImage)4052 PHP_METHOD(Imagick, spreadImage)
4053 {
4054 double radius;
4055 php_imagick_object *intern;
4056 MagickBooleanType status;
4057
4058 /* Parse parameters given to function */
4059 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &radius) == FAILURE) {
4060 return;
4061 }
4062
4063 intern = Z_IMAGICK_P(getThis());
4064 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4065 return;
4066
4067 #if MagickLibVersion >= 0x700
4068 {
4069 //TODO allow PixelInterpolateMethod be set
4070 PixelInterpolateMethod method = BilinearInterpolatePixel;
4071 status = MagickSpreadImage(intern->magick_wand, radius, method);
4072 }
4073 #else
4074 status = MagickSpreadImage(intern->magick_wand, radius);
4075 #endif
4076
4077 /* No magick is going to happen */
4078 if (status == MagickFalse) {
4079 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to spread image" TSRMLS_CC);
4080 return;
4081 }
4082
4083 RETURN_TRUE;
4084 }
4085 /* }}} */
4086
4087 /* {{{ proto bool Imagick::swirlImage(float degrees )
4088 Swirls the pixels about the center of the image, where degrees indicates the sweep of the arc through which each pixel is moved. You get a more dramatic effect as the degrees move from 1 to 360.
4089 */
PHP_METHOD(Imagick,swirlImage)4090 PHP_METHOD(Imagick, swirlImage)
4091 {
4092 double degrees;
4093 php_imagick_object *intern;
4094 MagickBooleanType status;
4095
4096 /* Parse parameters given to function */
4097 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", °rees) == FAILURE) {
4098 return;
4099 }
4100
4101 intern = Z_IMAGICK_P(getThis());
4102 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4103 return;
4104
4105 #if MagickLibVersion >= 0x700
4106 {
4107 //TODO allow PixelInterpolateMethod be set
4108 PixelInterpolateMethod method = BilinearInterpolatePixel;
4109 status = MagickSwirlImage(intern->magick_wand, degrees, method);
4110 }
4111 #else
4112 status = MagickSwirlImage(intern->magick_wand, degrees);
4113 #endif
4114
4115 /* No magick is going to happen */
4116 if (status == MagickFalse) {
4117 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to swirl image" TSRMLS_CC);
4118 return;
4119 }
4120
4121 RETURN_TRUE;
4122 }
4123 /* }}} */
4124
4125 /* {{{ proto bool Imagick::stripImage()
4126 Strips an image of all profiles and comments.
4127 */
PHP_METHOD(Imagick,stripImage)4128 PHP_METHOD(Imagick, stripImage)
4129 {
4130 php_imagick_object *intern;
4131 MagickBooleanType status;
4132
4133 if (zend_parse_parameters_none() == FAILURE) {
4134 return;
4135 }
4136
4137 intern = Z_IMAGICK_P(getThis());
4138 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4139 return;
4140
4141 status = MagickStripImage(intern->magick_wand);
4142
4143 /* No magick is going to happen */
4144 if (status == MagickFalse) {
4145 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to strip image" TSRMLS_CC);
4146 return;
4147 }
4148
4149 RETURN_TRUE;
4150 }
4151 /* }}} */
4152
4153 /* {{{ proto bool Imagick::trimImage(double fuzz)
4154 Remove edges that are the background color from the image.
4155 */
PHP_METHOD(Imagick,trimImage)4156 PHP_METHOD(Imagick, trimImage)
4157 {
4158 double fuzz;
4159 php_imagick_object *intern;
4160 MagickBooleanType status;
4161
4162 /* Parse parameters given to function */
4163 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &fuzz) == FAILURE) {
4164 return;
4165 }
4166
4167 intern = Z_IMAGICK_P(getThis());
4168 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4169 return;
4170
4171 status = MagickTrimImage(intern->magick_wand, fuzz);
4172
4173 /* No magick is going to happen */
4174 if (status == MagickFalse) {
4175 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to trim image" TSRMLS_CC);
4176 return;
4177 }
4178
4179 RETURN_TRUE;
4180 }
4181 /* }}} */
4182
4183 /* {{{ proto bool Imagick::chopImage(int width, int height, int x, int y)
4184 Removes a region of an image and collapses the image to occupy the removed portion
4185 */
PHP_METHOD(Imagick,chopImage)4186 PHP_METHOD(Imagick, chopImage)
4187 {
4188 php_imagick_object *intern;
4189 im_long width, height, x, y;
4190 MagickBooleanType status;
4191
4192 /* Parse parameters given to function */
4193 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llll", &width, &height, &x, &y) == FAILURE) {
4194 return;
4195 }
4196
4197 intern = Z_IMAGICK_P(getThis());
4198 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4199 return;
4200
4201 status = MagickChopImage(intern->magick_wand, width, height, x, y);
4202
4203 /* No magick is going to happen */
4204 if (status == MagickFalse) {
4205 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to chop image" TSRMLS_CC);
4206 return;
4207 }
4208
4209 RETURN_TRUE;
4210
4211 }
4212 /* }}} */
4213
4214 /* {{{ proto bool Imagick::clipImage()
4215 Clips along the first path from the 8BIM profile, if present.
4216 */
PHP_METHOD(Imagick,clipImage)4217 PHP_METHOD(Imagick, clipImage)
4218 {
4219 php_imagick_object *intern;
4220 MagickBooleanType status;
4221
4222 if (zend_parse_parameters_none() == FAILURE) {
4223 return;
4224 }
4225
4226 intern = Z_IMAGICK_P(getThis());
4227
4228 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4229 return;
4230 status = MagickClipImage(intern->magick_wand);
4231
4232 /* No magick is going to happen */
4233 if (status == MagickFalse) {
4234 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to clip image" TSRMLS_CC);
4235 return;
4236 }
4237 RETURN_TRUE;
4238 }
4239 /* }}} */
4240
4241 /* {{{ proto bool Imagick::clipPathImage(string pathname, bool inside)
4242 Clips along the named paths from the 8BIM profile, if present. Later operations take effect inside the path. Id may be a number if preceded with #, to work on a numbered path, e.g., "#1" to use the first path.
4243 */
PHP_METHOD(Imagick,clipPathImage)4244 PHP_METHOD(Imagick, clipPathImage)
4245 {
4246 php_imagick_object *intern;
4247 char *clip_path;
4248 IM_LEN_TYPE clip_path_len;
4249 zend_bool inside;
4250 MagickBooleanType status;
4251
4252 /* Parse parameters given to function */
4253 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sb", &clip_path, &clip_path_len, &inside) == FAILURE) {
4254 return;
4255 }
4256
4257 intern = Z_IMAGICK_P(getThis());
4258 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4259 return;
4260 #if MagickLibVersion > 0x636
4261 status = MagickClipImagePath(intern->magick_wand, clip_path, inside);
4262 #else
4263 status = MagickClipPathImage(intern->magick_wand, clip_path, inside);
4264 #endif
4265
4266 /* No magick is going to happen */
4267 if (status == MagickFalse) {
4268 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to clip path image" TSRMLS_CC);
4269 return;
4270 }
4271
4272 RETURN_TRUE;
4273
4274 }
4275 /* }}} */
4276
4277 /* {{{ proto Imagick Imagick::coalesceImages()
4278 Composites a set of images while respecting any page offsets and disposal methods. GIF, MIFF, and MNG animation sequences typically start with an image background and each subsequent image varies in size and offset. returns a new sequence where each image in the sequence is the same size as the first and composited with the next image in the sequence.
4279 */
PHP_METHOD(Imagick,coalesceImages)4280 PHP_METHOD(Imagick, coalesceImages)
4281 {
4282 MagickWand *tmp_wand;
4283 php_imagick_object *intern, *intern_return;
4284
4285 if (zend_parse_parameters_none() == FAILURE) {
4286 return;
4287 }
4288
4289 intern = Z_IMAGICK_P(getThis());
4290 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4291 return;
4292
4293 tmp_wand = MagickCoalesceImages(intern->magick_wand);
4294
4295 if (tmp_wand == NULL) {
4296 php_imagick_convert_imagick_exception(intern->magick_wand, "Coalesce image failed" TSRMLS_CC);
4297 return;
4298 }
4299
4300 object_init_ex(return_value, php_imagick_sc_entry);
4301 intern_return = Z_IMAGICK_P(return_value);
4302 php_imagick_replace_magickwand(intern_return, tmp_wand);
4303 return;
4304
4305 }
4306 /* }}} */
4307
4308 #if !defined(MAGICKCORE_EXCLUDE_DEPRECATED)
4309 #if MagickLibVersion < 0x700
4310 /* {{{ proto bool Imagick::colorFloodfillImage(ImagickPixel fill, double fuzz, ImagickPixel bordercolor, int x, int y)
4311 Changes the color value of any pixel that matches target and is an immediate neighbor.
4312 */
PHP_METHOD(Imagick,colorFloodfillImage)4313 PHP_METHOD(Imagick, colorFloodfillImage)
4314 {
4315 php_imagick_object *intern;
4316 zval *fill_param, *border_param;
4317 im_long x, y;
4318 double fuzz;
4319 MagickBooleanType status;
4320 PixelWand *fill_wand, *border_wand;
4321 zend_bool fill_allocated = 0, border_allocated = 0;
4322
4323 IMAGICK_METHOD_DEPRECATED("Imagick", "colorFloodFillImage");
4324
4325 /* Parse parameters given to function */
4326 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zdzll", &fill_param, &fuzz, &border_param, &x, &y) == FAILURE) {
4327 return;
4328 }
4329
4330 intern = Z_IMAGICK_P(getThis());
4331
4332 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4333 return;
4334
4335 fill_wand = php_imagick_zval_to_pixelwand (fill_param, IMAGICK_CLASS, &fill_allocated TSRMLS_CC);
4336 if (!fill_wand)
4337 return;
4338
4339 border_wand = php_imagick_zval_to_pixelwand (border_param, IMAGICK_CLASS, &border_allocated TSRMLS_CC);
4340 if (!border_wand) {
4341 if (fill_allocated)
4342 fill_wand = DestroyPixelWand (fill_wand);
4343 return;
4344 }
4345
4346 status = MagickColorFloodfillImage(intern->magick_wand, fill_wand, fuzz, border_wand, x, y);
4347
4348 if (fill_allocated)
4349 fill_wand = DestroyPixelWand (fill_wand);
4350
4351 if (border_allocated)
4352 border_wand = DestroyPixelWand (border_wand);
4353
4354 /* No magick is going to happen */
4355 if (status == MagickFalse) {
4356 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to color floodfill image" TSRMLS_CC);
4357 return;
4358 }
4359 RETURN_TRUE;
4360 }
4361 /* }}} */
4362 #endif // #if MagickLibVersion < 0x700
4363 #endif
4364
4365 /* {{{ proto Imagick Imagick::combineImages()
4366 Combines one or more images into a single image. The grayscale value of the pixels of each image in the sequence is assigned in order to the specified channels of the combined image. The typical ordering would be image 1 => Red, 2 => Green, 3 => Blue, etc.
4367 */
PHP_METHOD(Imagick,combineImages)4368 PHP_METHOD(Imagick, combineImages)
4369 {
4370 MagickWand *tmp_wand;
4371 php_imagick_object *intern, *intern_return;
4372
4373 // TODO - this is actuall ColorspaceType
4374 // https://imagemagick.org/api/magick-image.php#MagickCombineImages
4375 im_long channel_type;
4376
4377 /* Parse parameters given to function */
4378 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &channel_type) == FAILURE) {
4379 return;
4380 }
4381
4382 intern = Z_IMAGICK_P(getThis());
4383
4384 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4385 return;
4386 tmp_wand = MagickCombineImages(intern->magick_wand, channel_type);
4387
4388 if (tmp_wand == NULL) {
4389 php_imagick_convert_imagick_exception(intern->magick_wand, "Combine images failed" TSRMLS_CC);
4390 return;
4391 }
4392
4393 object_init_ex(return_value, php_imagick_sc_entry);
4394 intern_return = Z_IMAGICK_P(return_value);
4395 php_imagick_replace_magickwand(intern_return, tmp_wand);
4396
4397 return;
4398 }
4399 /* }}} */
4400
4401 /* {{{ proto Imagick Imagick::setImage(Imagick replace )
4402 Replaces the current sequence
4403 */
PHP_METHOD(Imagick,setImage)4404 PHP_METHOD(Imagick, setImage)
4405 {
4406 zval *objvar;
4407 MagickBooleanType status;
4408 php_imagick_object *intern, *replace;
4409
4410 /* Parse parameters given to function */
4411 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &objvar, php_imagick_sc_entry) == FAILURE) {
4412 return;
4413 }
4414
4415 intern = Z_IMAGICK_P(getThis());
4416 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4417 return;
4418
4419 replace = Z_IMAGICK_P(objvar);
4420 if (php_imagick_ensure_not_empty (replace->magick_wand) == 0)
4421 return;
4422
4423 status = MagickSetImage(intern->magick_wand, replace->magick_wand);
4424
4425 /* No magick is going to happen */
4426 if (status == MagickFalse) {
4427 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set the image" TSRMLS_CC);
4428 return;
4429 }
4430 RETURN_TRUE;
4431
4432 }
4433 /* }}} */
4434
4435 /* {{{ proto Imagick Imagick::getImage()
4436 Returns a new Imagick object with the current image sequence.
4437 */
PHP_METHOD(Imagick,getImage)4438 PHP_METHOD(Imagick, getImage)
4439 {
4440 MagickWand *tmp_wand;
4441 php_imagick_object *intern, *intern_return;
4442
4443 if (zend_parse_parameters_none() == FAILURE) {
4444 return;
4445 }
4446
4447 intern = Z_IMAGICK_P(getThis());
4448 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4449 return;
4450
4451 tmp_wand = MagickGetImage(intern->magick_wand);
4452
4453 if (tmp_wand == NULL) {
4454 php_imagick_convert_imagick_exception(intern->magick_wand, "Get image failed" TSRMLS_CC);
4455 return;
4456 }
4457
4458 object_init_ex(return_value, php_imagick_sc_entry);
4459 intern_return = Z_IMAGICK_P(return_value);
4460 php_imagick_replace_magickwand(intern_return, tmp_wand);
4461
4462 return;
4463 }
4464 /* }}} */
4465
4466 /* {{{ proto bool Imagick::addImage(Imagick source )
4467 Adds new image to Imagick object from the current position of the source object.
4468 */
PHP_METHOD(Imagick,addImage)4469 PHP_METHOD(Imagick, addImage)
4470 {
4471 php_imagick_object *intern, *intern_add;
4472 zval *add_obj;
4473 MagickBooleanType status;
4474
4475 /* Parse parameters given to function */
4476 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &add_obj, php_imagick_sc_entry) == FAILURE) {
4477 return;
4478 }
4479
4480 intern = Z_IMAGICK_P(getThis());
4481 intern_add = Z_IMAGICK_P(add_obj);
4482
4483 if (php_imagick_ensure_not_empty (intern_add->magick_wand) == 0)
4484 return;
4485
4486 status = MagickAddImage(intern->magick_wand, intern_add->magick_wand);
4487
4488 /* No magick is going to happen */
4489 if (status == MagickFalse) {
4490 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to add image" TSRMLS_CC);
4491 return;
4492 }
4493
4494 MagickSetLastIterator(intern->magick_wand);
4495 RETURN_TRUE;
4496 }
4497 /* }}} */
4498
4499 /* {{{ proto bool Imagick::newImage(int cols, int rows, ImagickPixel background[, string format] )
4500 Creates a new image and associates ImagickPixel value as background color
4501 */
PHP_METHOD(Imagick,newImage)4502 PHP_METHOD(Imagick, newImage)
4503 {
4504 php_imagick_object *intern;
4505 zval *param;
4506 MagickBooleanType status;
4507 im_long columns, rows;
4508 char *format = NULL;
4509 IM_LEN_TYPE format_len = 0;
4510 PixelWand *color_wand;
4511 zend_bool allocated;
4512
4513 /* Parse parameters given to function */
4514 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llz|s", &columns, &rows, ¶m, &format, &format_len) == FAILURE) {
4515 return;
4516 }
4517
4518 intern = Z_IMAGICK_P(getThis());
4519
4520 color_wand = php_imagick_zval_to_pixelwand (param, IMAGICK_CLASS, &allocated TSRMLS_CC);
4521 if (!color_wand)
4522 return;
4523
4524 status = MagickNewImage(intern->magick_wand, columns, rows, color_wand);
4525
4526 if (allocated)
4527 color_wand = DestroyPixelWand (color_wand);
4528
4529 /* No magick is going to happen */
4530 if (status == MagickFalse) {
4531 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to create new image" TSRMLS_CC);
4532 return;
4533 }
4534
4535 /* If the optional fourth parameter was given
4536 set the image format here */
4537 if (format != NULL && format_len > 0) {
4538
4539 status = MagickSetImageFormat(intern->magick_wand, format);
4540
4541 /* No magick is going to happen */
4542 if (status == MagickFalse) {
4543 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set the image format" TSRMLS_CC);
4544 return;
4545 }
4546 }
4547
4548 MagickSetLastIterator(intern->magick_wand);
4549 RETURN_TRUE;
4550 }
4551 /* }}} */
4552
4553 /* {{{ proto bool Imagick::newPseudoImage(int cols, int rows, string pseudoString )
4554 Creates a new image using pseudo format
4555 */
PHP_METHOD(Imagick,newPseudoImage)4556 PHP_METHOD(Imagick, newPseudoImage)
4557 {
4558 php_imagick_object *intern;
4559 MagickBooleanType status;
4560 im_long columns, rows;
4561 char *pseudo_string;
4562 IM_LEN_TYPE pseudo_string_len;
4563 struct php_imagick_file_t file = {0};
4564 php_imagick_rw_result_t rc;
4565
4566 /* Parse parameters given to function */
4567 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lls", &columns, &rows, &pseudo_string, &pseudo_string_len) == FAILURE) {
4568 return;
4569 }
4570
4571 if (IMAGICK_G(allow_zero_dimension_images) == 0) {
4572 if (columns == 0) {
4573 php_error(
4574 E_DEPRECATED,
4575 "Creating images with zero columns is deprecated. If you think you need to " \
4576 "do this, please open an issue at https://phpimagick.com/issues"
4577 );
4578 }
4579 if (rows == 0) {
4580 php_error(
4581 E_DEPRECATED,
4582 "Creating images with zero rows is deprecated. If you think you need to " \
4583 "do this, please open an issue at https://phpimagick.com/issues"
4584 );
4585 }
4586 }
4587
4588 /* Allow only pseudo formats in this method */
4589 if (strchr (pseudo_string, ':') == NULL) {
4590 php_imagick_throw_exception(IMAGICK_CLASS, "Invalid pseudo format string" TSRMLS_CC);
4591 return;
4592 }
4593
4594 intern = Z_IMAGICK_P(getThis());
4595
4596 /* Pseudo image needs a size set manually */
4597 status = MagickSetSize(intern->magick_wand, columns, rows);
4598
4599 /* No magick is going to happen */
4600 if (status == MagickFalse) {
4601 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to create new pseudo image" TSRMLS_CC);
4602 return;
4603 }
4604
4605 if (!php_imagick_file_init(&file, pseudo_string, pseudo_string_len TSRMLS_CC)) {
4606 php_imagick_throw_exception(IMAGICK_CLASS, "Invalid filename provided" TSRMLS_CC);
4607 return;
4608 }
4609 rc = php_imagick_read_file(intern, &file, ImagickReadImage TSRMLS_CC);
4610 php_imagick_file_deinit(&file);
4611
4612 if (rc != IMAGICK_RW_OK) {
4613 php_imagick_rw_fail_to_exception (intern->magick_wand, rc, pseudo_string TSRMLS_CC);
4614 return;
4615 }
4616 RETURN_TRUE;
4617 }
4618 /* }}} */
4619
4620 /* {{{ proto bool Imagick::getImageTotalInkDensity()
4621 Gets the image total ink density.
4622 */
PHP_METHOD(Imagick,getImageTotalInkDensity)4623 PHP_METHOD(Imagick, getImageTotalInkDensity)
4624 {
4625 php_imagick_object *intern;
4626 double ink_density;
4627
4628 if (zend_parse_parameters_none() == FAILURE) {
4629 return;
4630 }
4631
4632 intern = Z_IMAGICK_P(getThis());
4633 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4634 return;
4635
4636 ink_density = MagickGetImageTotalInkDensity(intern->magick_wand);
4637 RETVAL_DOUBLE(ink_density);
4638 }
4639 /* }}} */
4640
4641 /* {{{ proto bool Imagick::implodeImage(float radius )
4642 Creates a new image that is a copy of an existing one with the image pixels "implode" by the specified percentage. It allocates the memory necessary for the new Image structure and returns a pointer to the new image.
4643 */
PHP_METHOD(Imagick,implodeImage)4644 PHP_METHOD(Imagick, implodeImage)
4645 {
4646 php_imagick_object *intern;
4647 double radius;
4648 MagickBooleanType status;
4649
4650 /* Parse parameters given to function */
4651 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &radius) == FAILURE) {
4652 return;
4653 }
4654
4655 intern = Z_IMAGICK_P(getThis());
4656 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4657 return;
4658
4659 #if MagickLibVersion >= 0x700
4660 {
4661 //TODO allow PixelInterpolateMethod be set
4662 PixelInterpolateMethod method = BilinearInterpolatePixel;
4663 status = MagickImplodeImage(intern->magick_wand, radius, method);
4664 }
4665 #else
4666 status = MagickImplodeImage(intern->magick_wand, radius);
4667 #endif
4668
4669 /* No magick is going to happen */
4670 if (status == MagickFalse) {
4671 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to implode image" TSRMLS_CC);
4672 return;
4673 }
4674 RETURN_TRUE;
4675 }
4676 /* }}} */
4677
4678 #if MagickLibVersion >= 0x658
4679 //Only stable as of 658
4680 //http://upstream-tracker.org/compat_reports/imagemagick/6.5.7.7_to_6.5.7.8/abi_compat_report.html
4681
4682 /* {{{ proto bool Imagick::inverseFourierTransformImage(Imagick complement, bool magnitude)
4683 */
PHP_METHOD(Imagick,inverseFourierTransformImage)4684 PHP_METHOD(Imagick, inverseFourierTransformImage)
4685 {
4686 php_imagick_object *intern, *intern_complement;
4687 zval *complement_obj;
4688 zend_bool magnitude;
4689 MagickBooleanType status;
4690
4691 /* Parse parameters given to function */
4692 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ob", &complement_obj, php_imagick_sc_entry, &magnitude) == FAILURE) {
4693 return;
4694 }
4695
4696 intern = Z_IMAGICK_P(getThis());
4697 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4698 return;
4699
4700 intern_complement = Z_IMAGICK_P(complement_obj);
4701 status = MagickInverseFourierTransformImage(intern->magick_wand, intern_complement->magick_wand, magnitude);
4702
4703 /* No magick is going to happen */
4704 if (status == MagickFalse) {
4705 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to inversefouriertransformimage image" TSRMLS_CC);
4706 return;
4707 }
4708 RETURN_TRUE;
4709 }
4710 /* }}} */
4711 #endif
4712
4713 /* {{{ proto bool Imagick::levelImage(float blackPoint, float gamma, float whitePoint[, int channel] )
4714 Adjusts the levels of an image by scaling the colors falling between specified white and black points to the full available quantum range. The parameters provided represent the black, mid, and white points. The black point specifies the darkest color in the image. Colors darker than the black point are set to zero. Mid point specifies a gamma correction to apply to the image. White point specifies the lightest color in the image. Colors brighter than the white point are set to the maximum quantum value.
4715 */
PHP_METHOD(Imagick,levelImage)4716 PHP_METHOD(Imagick, levelImage)
4717 {
4718 php_imagick_object *intern;
4719 double black_point, gamma, white_point;
4720 MagickBooleanType status;
4721 im_long channel = IM_DEFAULT_CHANNEL;
4722
4723 /* Parse parameters given to function */
4724 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd|l", &black_point, &gamma, &white_point, &channel) == FAILURE) {
4725 return;
4726 }
4727
4728 intern = Z_IMAGICK_P(getThis());
4729 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4730 return;
4731
4732 status = MagickLevelImageChannel(intern->magick_wand, channel, black_point, gamma, white_point);
4733
4734 /* No magick is going to happen */
4735 if (status == MagickFalse) {
4736 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to level image" TSRMLS_CC);
4737 return;
4738 }
4739 RETURN_TRUE;
4740 }
4741 /* }}} */
4742
4743 /* {{{ proto bool Imagick::magnifyImage()
4744 Is a convenience method that scales an image proportionally to twice its original size.
4745 */
PHP_METHOD(Imagick,magnifyImage)4746 PHP_METHOD(Imagick, magnifyImage)
4747 {
4748 php_imagick_object *intern;
4749 MagickBooleanType status;
4750
4751 if (zend_parse_parameters_none() == FAILURE) {
4752 return;
4753 }
4754
4755 intern = Z_IMAGICK_P(getThis());
4756 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4757 return;
4758
4759 status = MagickMagnifyImage(intern->magick_wand);
4760
4761 /* No magick is going to happen */
4762 if (status == MagickFalse) {
4763 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to magnify image" TSRMLS_CC);
4764 return;
4765 }
4766 RETURN_TRUE;
4767 }
4768 /* }}} */
4769
4770 #if !defined(MAGICKCORE_EXCLUDE_DEPRECATED)
4771 #if MagickLibVersion < 0x700
4772 /* {{{ proto bool Imagick::cycleColormapImage(Imagick map, bool dither)
4773 Replaces the colors of an image with the closest color from a reference image.
4774 */
PHP_METHOD(Imagick,mapImage)4775 PHP_METHOD(Imagick, mapImage)
4776 {
4777 php_imagick_object *intern, *intern_map;
4778 zval *map_obj;
4779 zend_bool dither;
4780 MagickBooleanType status;
4781
4782 IMAGICK_METHOD_DEPRECATED ("Imagick", "mapImage");
4783
4784 /* Parse parameters given to function */
4785 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ob", &map_obj, php_imagick_sc_entry, &dither) == FAILURE) {
4786 return;
4787 }
4788
4789 intern = Z_IMAGICK_P(getThis());
4790 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4791 return;
4792
4793 intern_map = Z_IMAGICK_P(map_obj);
4794 status = MagickMapImage(intern->magick_wand, intern_map->magick_wand, dither);
4795
4796 /* No magick is going to happen */
4797 if (status == MagickFalse) {
4798 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to map image" TSRMLS_CC);
4799 return;
4800 }
4801 RETURN_TRUE;
4802 }
4803 /* }}} */
4804 #endif // #if MagickLibVersion < 0x700
4805
4806 #if MagickLibVersion < 0x700
4807 /* {{{ proto bool Imagick::matteFloodfillImage(float alpha,float fuzz,ImagickPixel bordercolor, int x, int y)
4808 Changes the transparency value of any pixel that matches target and is an immediate neighbor
4809 */
PHP_METHOD(Imagick,matteFloodfillImage)4810 PHP_METHOD(Imagick, matteFloodfillImage)
4811 {
4812 php_imagick_object *intern;
4813 zval *param;
4814 im_long x, y;
4815 double alpha, fuzz;
4816 MagickBooleanType status;
4817 PixelWand *color_wand;
4818 zend_bool allocated;
4819
4820 IMAGICK_METHOD_DEPRECATED("Imagick", "matteFloodfillImage");
4821
4822 /* Parse parameters given to function */
4823 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddzll", &alpha, &fuzz, ¶m, &x, &y) == FAILURE) {
4824 return;
4825 }
4826
4827 intern = Z_IMAGICK_P(getThis());
4828 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4829 return;
4830
4831 color_wand = php_imagick_zval_to_pixelwand (param, IMAGICK_CLASS, &allocated TSRMLS_CC);
4832 if (!color_wand)
4833 return;
4834
4835 status = MagickMatteFloodfillImage(intern->magick_wand, alpha, fuzz, color_wand, x, y);
4836
4837 if (allocated)
4838 color_wand = DestroyPixelWand (color_wand);
4839
4840 /* No magick is going to happen */
4841 if (status == MagickFalse) {
4842 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to matte floodfill image" TSRMLS_CC);
4843 return;
4844 }
4845 RETURN_TRUE;
4846 }
4847 /* }}} */
4848 #endif // #if MagickLibVersion < 0x700
4849 #endif
4850
4851 #if MagickLibVersion < 0x700
4852 #if !defined(MAGICKCORE_EXCLUDE_DEPRECATED)
4853 /* {{{ proto bool Imagick::medianFilterImage(float radius)
4854 Applies a digital filter that improves the quality of a noisy image. Each pixel is replaced by the median in a set of neighboring pixels as defined by radius.
4855 */
PHP_METHOD(Imagick,medianFilterImage)4856 PHP_METHOD(Imagick, medianFilterImage)
4857 {
4858 php_imagick_object *intern;
4859 double radius;
4860 MagickBooleanType status;
4861
4862 IMAGICK_METHOD_DEPRECATED ("Imagick", "medianFilterImage");
4863
4864 /* Parse parameters given to function */
4865 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &radius) == FAILURE) {
4866 return;
4867 }
4868
4869 intern = Z_IMAGICK_P(getThis());
4870 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4871 return;
4872
4873 status = MagickMedianFilterImage(intern->magick_wand, radius);
4874
4875 /* No magick is going to happen */
4876 if (status == MagickFalse) {
4877 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to median filter image" TSRMLS_CC);
4878 return;
4879 }
4880 RETURN_TRUE;
4881 }
4882 /* }}} */
4883 #endif
4884 #endif
4885
4886 /* {{{ proto bool Imagick::negateImage(bool gray[, int channel] )
4887 Negates the colors in the reference image. The Grayscale option means that only grayscale values within the image are negated.
4888 */
PHP_METHOD(Imagick,negateImage)4889 PHP_METHOD(Imagick, negateImage)
4890 {
4891 php_imagick_object *intern;
4892 zend_bool gray;
4893 MagickBooleanType status;
4894 im_long channel = IM_DEFAULT_CHANNEL;
4895
4896 /* Parse parameters given to function */
4897 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b|l", &gray, &channel) == FAILURE) {
4898 return;
4899 }
4900
4901 intern = Z_IMAGICK_P(getThis());
4902 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4903 return;
4904
4905 status = MagickNegateImageChannel(intern->magick_wand, channel, gray);
4906
4907 /* No magick is going to happen */
4908 if (status == MagickFalse) {
4909 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to negate image" TSRMLS_CC);
4910 return;
4911 }
4912 RETURN_TRUE;
4913 }
4914 /* }}} */
4915
4916 #if !defined(MAGICKCORE_EXCLUDE_DEPRECATED)
4917 #if MagickLibVersion < 0x700
4918 /* {{{ proto bool Imagick::paintOpaqueImage(ImagickPixel target, ImagickPixel fill, float fuzz[, int channel])
4919 Changes any pixel that matches color with the color defined by fill. Channel argument is supported in ImageMagick 6.2.8+.
4920 */
PHP_METHOD(Imagick,paintOpaqueImage)4921 PHP_METHOD(Imagick, paintOpaqueImage)
4922 {
4923 php_imagick_object *intern;
4924 zval *target_param, *fill_param;
4925 double fuzz;
4926 MagickBooleanType status;
4927 im_long channel = DefaultChannels;
4928 PixelWand *target_wand, *fill_wand;
4929 zend_bool target_allocated = 0, fill_allocated = 0;
4930
4931 IMAGICK_METHOD_DEPRECATED ("Imagick", "paintOpaqueImage");
4932
4933 /* Parse parameters given to function */
4934 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zzd|l", &target_param, &fill_param, &fuzz, &channel) == FAILURE) {
4935 return;
4936 }
4937
4938 intern = Z_IMAGICK_P(getThis());
4939
4940 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4941 return;
4942
4943 target_wand = php_imagick_zval_to_pixelwand (target_param, IMAGICK_CLASS, &target_allocated TSRMLS_CC);
4944 if (!target_wand)
4945 return;
4946
4947 fill_wand = php_imagick_zval_to_pixelwand (fill_param, IMAGICK_CLASS, &fill_allocated TSRMLS_CC);
4948 if (!fill_wand) {
4949 if (target_allocated)
4950 target_wand = DestroyPixelWand (target_wand);
4951 return;
4952 }
4953
4954 #if MagickLibVersion > 0x628
4955 status = MagickPaintOpaqueImageChannel(intern->magick_wand, channel, target_wand, fill_wand, fuzz);
4956 #else
4957 status = MagickPaintOpaqueImage(intern->magick_wand, target_wand, fill_wand, fuzz);
4958 #endif
4959
4960 if (fill_allocated)
4961 fill_wand = DestroyPixelWand (fill_wand);
4962
4963 if (target_allocated)
4964 target_wand = DestroyPixelWand (target_wand);
4965
4966 /* No magick is going to happen */
4967 if (status == MagickFalse) {
4968 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable paint opaque image" TSRMLS_CC);
4969 return;
4970 }
4971 RETURN_TRUE;
4972 }
4973 /* }}} */
4974 #endif // #if MagickLibVersion < 0x700
4975 #endif
4976
4977 #if MagickLibVersion > 0x628
4978 /* {{{ proto Imagick Imagick::optimizeImageLayers()
4979 Compares each image the GIF disposed forms of the previous image in the sequence. From this it attempts to select the smallest cropped image to replace each frame, while preserving the results of the animation.
4980 */
PHP_METHOD(Imagick,optimizeImageLayers)4981 PHP_METHOD(Imagick, optimizeImageLayers)
4982 {
4983 MagickWand *tmp_wand;
4984 php_imagick_object *intern, *intern_return;
4985
4986 if (zend_parse_parameters_none() == FAILURE) {
4987 return;
4988 }
4989
4990 intern = Z_IMAGICK_P(getThis());
4991 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
4992 return;
4993
4994 tmp_wand = MagickOptimizeImageLayers(intern->magick_wand);
4995
4996 if (tmp_wand == NULL) {
4997 php_imagick_convert_imagick_exception(intern->magick_wand, "Optimize image layers failed" TSRMLS_CC);
4998 return;
4999 }
5000
5001 object_init_ex(return_value, php_imagick_sc_entry);
5002 intern_return = Z_IMAGICK_P(return_value);
5003 php_imagick_replace_magickwand(intern_return, tmp_wand);
5004
5005 return;
5006 }
5007 /* }}} */
5008
5009 #if !defined(MAGICKCORE_EXCLUDE_DEPRECATED)
5010 #if MagickLibVersion < 0x700
5011 /* {{{ proto bool Imagick::paintTransparentImage(ImagickPixel target, float alpha, float fuzz)
5012 Changes any pixel that matches color with the color defined by fill.
5013 */
PHP_METHOD(Imagick,paintTransparentImage)5014 PHP_METHOD(Imagick, paintTransparentImage)
5015 {
5016 php_imagick_object *intern;
5017 zval *param;
5018 double alpha, fuzz;
5019 MagickBooleanType status;
5020 PixelWand *color_wand;
5021 zend_bool allocated;
5022
5023 IMAGICK_METHOD_DEPRECATED ("Imagick", "paintTransparentImage");
5024
5025 /* Parse parameters given to function */
5026 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zdd", ¶m, &alpha, &fuzz) == FAILURE) {
5027 return;
5028 }
5029
5030 intern = Z_IMAGICK_P(getThis());
5031 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5032 return;
5033
5034 color_wand = php_imagick_zval_to_pixelwand (param, IMAGICK_CLASS, &allocated TSRMLS_CC);
5035 if (!color_wand)
5036 return;
5037
5038 status = MagickPaintTransparentImage(intern->magick_wand, color_wand, alpha, fuzz);
5039
5040 if (allocated)
5041 color_wand = DestroyPixelWand (color_wand);
5042
5043 /* No magick is going to happen */
5044 if (status == MagickFalse) {
5045 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to paint transparent image" TSRMLS_CC);
5046 return;
5047 }
5048 RETURN_TRUE;
5049 }
5050 /* }}} */
5051 #endif // #if MagickLibVersion < 0x700
5052 #endif
5053 #endif
5054
5055 /* {{{ proto Imagick Imagick::previewImages(int preview )
5056 Tiles 9 thumbnails of the specified image with an image processing operation applied at varying strengths.
5057 This is helpful to quickly pin-point an appropriate parameter for an image processing operation.
5058 */
PHP_METHOD(Imagick,previewImages)5059 PHP_METHOD(Imagick, previewImages)
5060 {
5061 php_imagick_object *intern, *intern_return;
5062 im_long preview;
5063 MagickWand *tmp_wand;
5064
5065 /* Parse parameters given to function */
5066 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &preview) == FAILURE) {
5067 return;
5068 }
5069
5070 intern = Z_IMAGICK_P(getThis());
5071 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5072 return;
5073
5074 tmp_wand = MagickPreviewImages(intern->magick_wand, preview);
5075
5076 if (tmp_wand == NULL) {
5077 php_imagick_convert_imagick_exception(intern->magick_wand, "Preview images failed" TSRMLS_CC);
5078 return;
5079 }
5080
5081 object_init_ex(return_value, php_imagick_sc_entry);
5082 intern_return = Z_IMAGICK_P(return_value);
5083 php_imagick_replace_magickwand(intern_return, tmp_wand);
5084 return;
5085 }
5086 /* }}} */
5087
5088 /* {{{ proto bool Imagick::profileImage(string name,string profile)
5089 Adds or removes a ICC, IPTC, or generic profile from an image. If the profile is NULL, it is removed from the image otherwise added. Use a name of '*' and a profile of NULL to remove all profiles from the image.
5090 */
PHP_METHOD(Imagick,profileImage)5091 PHP_METHOD(Imagick, profileImage)
5092 {
5093 php_imagick_object *intern;
5094 char *name, *profile;
5095 IM_LEN_TYPE name_len, profile_len;
5096 MagickBooleanType status;
5097
5098 /* Parse parameters given to function */
5099 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &profile, &profile_len) == FAILURE) {
5100 return;
5101 }
5102
5103 intern = Z_IMAGICK_P(getThis());
5104 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5105 return;
5106
5107 status = MagickProfileImage(intern->magick_wand, name, profile, profile_len);
5108
5109 /* No magick is going to happen */
5110 if (status == MagickFalse) {
5111 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to profile image" TSRMLS_CC);
5112 return;
5113 }
5114 RETURN_TRUE;
5115 }
5116 /* }}} */
5117
5118 /* {{{ proto bool Imagick::quantizeImage(int numberColors, int colorspace, int treedepth, bool dither,
5119 bool measureError)
5120 Analyzes the colors within a reference image
5121 */
PHP_METHOD(Imagick,quantizeImage)5122 PHP_METHOD(Imagick, quantizeImage)
5123 {
5124 php_imagick_object *intern;
5125 long number_colors, colorspace, tree_depth;
5126 zend_bool dither, measure_error;
5127 MagickBooleanType status;
5128
5129 /* Parse parameters given to function */
5130 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lllbb", &number_colors, &colorspace, &tree_depth, &dither, &measure_error) == FAILURE) {
5131 return;
5132 }
5133
5134 intern = Z_IMAGICK_P(getThis());
5135 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5136 return;
5137
5138 status = MagickQuantizeImage(intern->magick_wand, number_colors, colorspace, tree_depth, dither, measure_error);
5139
5140 /* No magick is going to happen */
5141 if (status == MagickFalse) {
5142 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to quantize image" TSRMLS_CC);
5143 return;
5144 }
5145 RETURN_TRUE;
5146 }
5147 /* }}} */
5148
5149 /* {{{ proto bool Imagick::quantizeImages(int number_colors, int colorspace, int treedepth, bool dither,
5150 bool measure_error)
5151 Analyzes the colors within a sequence of images
5152 */
PHP_METHOD(Imagick,quantizeImages)5153 PHP_METHOD(Imagick, quantizeImages)
5154 {
5155 php_imagick_object *intern;
5156 im_long number_colors, colorspace, tree_depth;
5157 zend_bool dither, measure_error;
5158 MagickBooleanType status;
5159
5160 /* Parse parameters given to function */
5161 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lllbb", &number_colors, &colorspace, &tree_depth, &dither, &measure_error) == FAILURE) {
5162 return;
5163 }
5164
5165 intern = Z_IMAGICK_P(getThis());
5166 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5167 return;
5168
5169 status = MagickQuantizeImages(intern->magick_wand, number_colors, colorspace, tree_depth, dither, measure_error);
5170
5171 /* No magick is going to happen */
5172 if (status == MagickFalse) {
5173 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to quantize images" TSRMLS_CC);
5174 return;
5175 }
5176 RETURN_TRUE;
5177 }
5178 /* }}} */
5179
5180 #if !defined(MAGICKCORE_EXCLUDE_DEPRECATED)
5181 #if MagickLibVersion < 0x700
5182 /* {{{ proto bool Imagick::reduceNoiseImage(float radius)
5183 Smooths the contours of an image
5184 */
PHP_METHOD(Imagick,reduceNoiseImage)5185 PHP_METHOD(Imagick, reduceNoiseImage)
5186 {
5187 php_imagick_object *intern;
5188 double radius;
5189 MagickBooleanType status;
5190
5191 IMAGICK_METHOD_DEPRECATED ("Imagick", "reduceNoiseImage");
5192
5193 /* Parse parameters given to function */
5194 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &radius) == FAILURE) {
5195 return;
5196 }
5197
5198 intern = Z_IMAGICK_P(getThis());
5199 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5200 return;
5201
5202 status = MagickReduceNoiseImage(intern->magick_wand, radius);
5203
5204 /* No magick is going to happen */
5205 if (status == MagickFalse) {
5206 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to reduce image noise" TSRMLS_CC);
5207 return;
5208 }
5209 RETURN_TRUE;
5210 }
5211 /* }}} */
5212 #endif
5213 #endif
5214
5215 /* {{{ proto string Imagick::removeImageProfile(string name)
5216 Removes the named image profile and returns it
5217 */
PHP_METHOD(Imagick,removeImageProfile)5218 PHP_METHOD(Imagick, removeImageProfile)
5219 {
5220 php_imagick_object *intern;
5221 char *name;
5222 unsigned char *profile;
5223 IM_LEN_TYPE name_len;
5224 #if MagickLibVersion < 0x628
5225 long profile_len;
5226 #else
5227 size_t profile_len;
5228 #endif
5229
5230 /* Parse parameters given to function */
5231 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
5232 return;
5233 }
5234
5235 intern = Z_IMAGICK_P(getThis());
5236 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5237 return;
5238
5239 profile = MagickRemoveImageProfile(intern->magick_wand, name, &profile_len);
5240
5241 if (!profile) {
5242 php_imagick_throw_exception(IMAGICK_CLASS, "The image profile does not exist" TSRMLS_CC);
5243 return;
5244 }
5245
5246 IM_ZVAL_STRING(return_value, (char *)profile);
5247 IMAGICK_FREE_MAGICK_MEMORY(profile);
5248 return;
5249 }
5250 /* }}} */
5251
5252 /* {{{ proto bool Imagick::separateImageChannel(int channel)
5253 Separates a channel from the image
5254 */
PHP_METHOD(Imagick,separateImageChannel)5255 PHP_METHOD(Imagick, separateImageChannel)
5256 {
5257 php_imagick_object *intern;
5258 im_long channel;
5259 MagickBooleanType status;
5260
5261 /* Parse parameters given to function */
5262 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &channel) == FAILURE) {
5263 return;
5264 }
5265
5266 intern = Z_IMAGICK_P(getThis());
5267 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5268 return;
5269
5270 #if MagickLibVersion >= 0x700
5271 status = MagickSeparateImage(intern->magick_wand, channel);
5272 #else
5273 status = MagickSeparateImageChannel(intern->magick_wand, channel);
5274 #endif
5275
5276 /* No magick is going to happen */
5277 if (status == MagickFalse) {
5278 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to separate image channel" TSRMLS_CC);
5279 return;
5280 }
5281 RETURN_TRUE;
5282 }
5283 /* }}} */
5284
5285 /* {{{ proto bool Imagick::sepiaToneImage(float threshold)
5286 Applies a special effect to the image
5287 */
PHP_METHOD(Imagick,sepiaToneImage)5288 PHP_METHOD(Imagick, sepiaToneImage)
5289 {
5290 php_imagick_object *intern;
5291 double threshold;
5292 double c_opacity;
5293 MagickBooleanType status;
5294
5295 /* Parse parameters given to function */
5296 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &threshold) == FAILURE) {
5297 return;
5298 }
5299
5300 c_opacity = (threshold * QuantumRange) / 100;
5301
5302 intern = Z_IMAGICK_P(getThis());
5303 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5304 return;
5305
5306 status = MagickSepiaToneImage(intern->magick_wand, c_opacity);
5307
5308 /* No magick is going to happen */
5309 if (status == MagickFalse) {
5310 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to sepia tone image" TSRMLS_CC);
5311 return;
5312 }
5313 RETURN_TRUE;
5314 }
5315 /* }}} */
5316
5317 #if MagickLibVersion < 0x700
5318 /* {{{ proto bool Imagick::setImageBias(float bias)
5319 Sets the image bias
5320 */
5321 static
s_set_image_bias(INTERNAL_FUNCTION_PARAMETERS,zend_bool use_quantum)5322 void s_set_image_bias(INTERNAL_FUNCTION_PARAMETERS, zend_bool use_quantum)
5323 {
5324 php_imagick_object *intern;
5325 double bias;
5326 MagickBooleanType status;
5327
5328 /* Parse parameters given to function */
5329 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &bias) == FAILURE) {
5330 return;
5331 }
5332
5333 intern = Z_IMAGICK_P(getThis());
5334 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5335 return;
5336
5337 if (use_quantum) {
5338 bias *= QuantumRange;
5339 }
5340
5341 status = MagickSetImageBias(intern->magick_wand, bias);
5342
5343 /* No magick is going to happen */
5344 if (status == MagickFalse) {
5345 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image bias" TSRMLS_CC);
5346 return;
5347 }
5348 RETURN_TRUE;
5349 }
5350 /* }}} */
5351 #endif // #if MagickLibVersion < 0x700
5352
5353
5354 /* {{{ proto bool Imagick::setImageBiasQuantum(float bias)
5355 Sets the image bias. Bias should be scaled with 0 = no adjustment, 1 = quantum value
5356 */
5357 #if MagickLibVersion < 0x700
PHP_METHOD(Imagick,setImageBiasQuantum)5358 PHP_METHOD(Imagick, setImageBiasQuantum)
5359 {
5360 s_set_image_bias (INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
5361 }
5362 #endif
5363 /* }}} */
5364
5365
5366 /* {{{ proto bool Imagick::setImageBias(float bias)
5367 Sets the image bias. Bias should be scaled with 0 = no adjustment, 2^^x = adjust black to white
5368 where x = the quantum depth ImageMagick was compiled with
5369 */
5370 #if MagickLibVersion < 0x700
PHP_METHOD(Imagick,setImageBias)5371 PHP_METHOD(Imagick, setImageBias)
5372 {
5373 s_set_image_bias (INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
5374 }
5375 #endif
5376 /* }}} */
5377
5378
5379
5380 /* {{{ proto bool Imagick::setImageBluePrimary(float x,float y)
5381 For IM7 the prototype is
5382 proto bool Imagick::setImageBluePrimary(float x, float y, float z)
5383
5384 Sets the image chromaticity blue primary point
5385 */
PHP_METHOD(Imagick,setImageBluePrimary)5386 PHP_METHOD(Imagick, setImageBluePrimary)
5387 {
5388 php_imagick_object *intern;
5389 double x, y;
5390 #if MagickLibVersion >= 0x700
5391 double z;
5392 #endif
5393 MagickBooleanType status;
5394
5395 /* Parse parameters given to function */
5396 #if MagickLibVersion >= 0x700
5397 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd", &x, &y, &z) == FAILURE) {
5398 #else
5399 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &x, &y) == FAILURE) {
5400 #endif
5401 return;
5402 }
5403
5404 intern = Z_IMAGICK_P(getThis());
5405 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5406 return;
5407
5408 #if MagickLibVersion >= 0x700
5409 status = MagickSetImageBluePrimary(intern->magick_wand, x, y, z);
5410 #else
5411 status = MagickSetImageBluePrimary(intern->magick_wand, x, y);
5412 #endif
5413
5414 /* No magick is going to happen */
5415 if (status == MagickFalse) {
5416 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image blue primary" TSRMLS_CC);
5417 return;
5418 }
5419 RETURN_TRUE;
5420 }
5421 /* }}} */
5422
5423 /* {{{ proto bool Imagick::setImageBorderColor(ImagickPixel border)
5424 Sets the image border color
5425 */
5426 PHP_METHOD(Imagick, setImageBorderColor)
5427 {
5428 zval *param;
5429 php_imagick_object *intern;
5430 MagickBooleanType status;
5431 PixelWand *color_wand;
5432 zend_bool allocated;
5433
5434 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶m) == FAILURE) {
5435 return;
5436 }
5437
5438 intern = Z_IMAGICK_P(getThis());
5439
5440 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5441 return;
5442
5443 color_wand = php_imagick_zval_to_pixelwand (param, IMAGICK_CLASS, &allocated TSRMLS_CC);
5444 if (!color_wand)
5445 return;
5446
5447 status = MagickSetImageBorderColor(intern->magick_wand, color_wand);
5448
5449 if (allocated)
5450 color_wand = DestroyPixelWand (color_wand);
5451
5452 /* No magick is going to happen */
5453 if (status == MagickFalse) {
5454 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image border color" TSRMLS_CC);
5455 return;
5456 }
5457 RETURN_TRUE;
5458 }
5459 /* }}} */
5460
5461 /* {{{ proto bool Imagick::setImageChannelDepth(int channel, int depth)
5462 Sets the depth of a particular image channel
5463 */
5464 PHP_METHOD(Imagick, setImageChannelDepth)
5465 {
5466 php_imagick_object *intern;
5467 im_long channel_type, depth;
5468 MagickBooleanType status;
5469
5470 /* Parse parameters given to function */
5471 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &channel_type, &depth) == FAILURE) {
5472 return;
5473 }
5474
5475 intern = Z_IMAGICK_P(getThis());
5476 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5477 return;
5478
5479 status = MagickSetImageChannelDepth(intern->magick_wand, channel_type, depth);
5480
5481 /* No magick is going to happen */
5482 if (status == MagickFalse) {
5483 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image channel depth" TSRMLS_CC);
5484 return;
5485 }
5486 RETURN_TRUE;
5487 }
5488 /* }}} */
5489
5490 /* {{{ proto bool Imagick::setImageColormapColor(int index, ImagickPixel color)
5491 Sets the color of the specified colormap index
5492 */
5493 PHP_METHOD(Imagick, setImageColormapColor)
5494 {
5495 php_imagick_object *intern;
5496 zval *param;
5497 long index;
5498 MagickBooleanType status;
5499 PixelWand *color_wand;
5500 zend_bool allocated;
5501
5502 /* Parse parameters given to function */
5503 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz", &index, ¶m) == FAILURE) {
5504 return;
5505 }
5506
5507 intern = Z_IMAGICK_P(getThis());
5508 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5509 return;
5510
5511 color_wand = php_imagick_zval_to_pixelwand (param, IMAGICK_CLASS, &allocated TSRMLS_CC);
5512 if (!color_wand)
5513 return;
5514
5515 status = MagickSetImageColormapColor(intern->magick_wand, index, color_wand);
5516
5517 if (allocated)
5518 color_wand = DestroyPixelWand (color_wand);
5519
5520 /* No magick is going to happen */
5521 if (status == MagickFalse) {
5522 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image color map color" TSRMLS_CC);
5523 return;
5524 }
5525 RETURN_TRUE;
5526
5527 }
5528 /* }}} */
5529
5530 /* {{{ proto bool Imagick::setImageColorspace(int colorspace)
5531 Sets the image colorspace
5532 */
5533 PHP_METHOD(Imagick, setImageColorspace)
5534 {
5535 php_imagick_object *intern;
5536 im_long colorspace;
5537 MagickBooleanType status;
5538
5539 /* Parse parameters given to function */
5540 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &colorspace) == FAILURE) {
5541 return;
5542 }
5543
5544 intern = Z_IMAGICK_P(getThis());
5545 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5546 return;
5547
5548 status = MagickSetImageColorspace(intern->magick_wand, colorspace);
5549
5550 /* No magick is going to happen */
5551 if (status == MagickFalse) {
5552 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image colorspace" TSRMLS_CC);
5553 return;
5554 }
5555 RETURN_TRUE;
5556 }
5557 /* }}} */
5558
5559 /* {{{ proto bool Imagick::setImageDispose(int dispose)
5560 Sets the image disposal method
5561 */
5562 PHP_METHOD(Imagick, setImageDispose)
5563 {
5564 php_imagick_object *intern;
5565 im_long dispose;
5566 MagickBooleanType status;
5567
5568 /* Parse parameters given to function */
5569 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &dispose) == FAILURE) {
5570 return;
5571 }
5572
5573 intern = Z_IMAGICK_P(getThis());
5574 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5575 return;
5576
5577 status = MagickSetImageDispose(intern->magick_wand, dispose);
5578
5579 /* No magick is going to happen */
5580 if (status == MagickFalse) {
5581 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image dispose" TSRMLS_CC);
5582 return;
5583 }
5584 RETURN_TRUE;
5585 }
5586 /* }}} */
5587
5588 /* {{{ proto bool Imagick::setImageExtent(int columns, int rows)
5589 Sets the image size
5590 */
5591 PHP_METHOD(Imagick, setImageExtent)
5592 {
5593 php_imagick_object *intern;
5594 im_long rows, columns;
5595 MagickBooleanType status;
5596
5597 /* Parse parameters given to function */
5598 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &rows, &columns) == FAILURE) {
5599 return;
5600 }
5601
5602 intern = Z_IMAGICK_P(getThis());
5603 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5604 return;
5605
5606 status = MagickSetImageExtent(intern->magick_wand, rows, columns);
5607
5608 /* No magick is going to happen */
5609 if (status == MagickFalse) {
5610 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image extent" TSRMLS_CC);
5611 return;
5612 }
5613 RETURN_TRUE;
5614 }
5615 /* }}} */
5616
5617 /* {{{ proto bool Imagick::setImageGreenPrimary(float x, float y)
5618 For IM7 the prototype is
5619 proto bool Imagick::setImageGreenPrimary(float x, float y, float z)
5620 Sets the image chromaticity green primary point
5621 */
5622 PHP_METHOD(Imagick, setImageGreenPrimary)
5623 {
5624 php_imagick_object *intern;
5625 double x, y;
5626 #if MagickLibVersion >= 0x700
5627 double z;
5628 #endif
5629 MagickBooleanType status;
5630
5631
5632 /* Parse parameters given to function */
5633 #if MagickLibVersion >= 0x700
5634 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd", &x, &y, &z) == FAILURE) {
5635 #else
5636 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &x, &y) == FAILURE) {
5637 #endif
5638 return;
5639 }
5640
5641 intern = Z_IMAGICK_P(getThis());
5642 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5643 return;
5644
5645 #if MagickLibVersion >= 0x700
5646 status = MagickSetImageGreenPrimary(intern->magick_wand, x, y, z);
5647 #else
5648 status = MagickSetImageGreenPrimary(intern->magick_wand, x, y);
5649 #endif
5650
5651 /* No magick is going to happen */
5652 if (status == MagickFalse) {
5653 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image green primary" TSRMLS_CC);
5654 return;
5655 }
5656 RETURN_TRUE;
5657 }
5658 /* }}} */
5659
5660 /* {{{ proto bool Imagick::setImageInterlaceScheme(int interlace_scheme)
5661 Sets the image interlace scheme
5662 */
5663 PHP_METHOD(Imagick, setImageInterlaceScheme)
5664 {
5665 php_imagick_object *intern;
5666 im_long interlace;
5667 MagickBooleanType status;
5668
5669 /* Parse parameters given to function */
5670 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &interlace) == FAILURE) {
5671 return;
5672 }
5673
5674 intern = Z_IMAGICK_P(getThis());
5675 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5676 return;
5677
5678 status = MagickSetImageInterlaceScheme(intern->magick_wand, interlace);
5679
5680 /* No magick is going to happen */
5681 if (status == MagickFalse) {
5682 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image interlace scheme" TSRMLS_CC);
5683 return;
5684 }
5685 RETURN_TRUE;
5686 }
5687 /* }}} */
5688
5689 /* {{{ proto bool Imagick::setImageProfile(string name, string profile)
5690 Adds a named profile to the Imagick object
5691 */
5692 PHP_METHOD(Imagick, setImageProfile)
5693 {
5694 php_imagick_object *intern;
5695 char *name, *profile;
5696 IM_LEN_TYPE profile_len, name_len;
5697 MagickBooleanType status;
5698
5699 /* Parse parameters given to function */
5700 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &profile, &profile_len) == FAILURE) {
5701 return;
5702 }
5703
5704 intern = Z_IMAGICK_P(getThis());
5705 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5706 return;
5707
5708 status = MagickSetImageProfile(intern->magick_wand, name, profile, profile_len);
5709
5710 /* No magick is going to happen */
5711 if (status == MagickFalse) {
5712 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image profile" TSRMLS_CC);
5713 return;
5714 }
5715 RETURN_TRUE;
5716 }
5717 /* }}} */
5718
5719 /* {{{ proto bool Imagick::setImageRedPrimary(float x,float y)
5720 For IM7 the prototype is
5721 proto bool Imagick::setImageRedPrimary(float x, float y, float z)
5722
5723 Sets the image chromaticity red primary point.
5724 */
5725 PHP_METHOD(Imagick, setImageRedPrimary)
5726 {
5727 php_imagick_object *intern;
5728 double x, y;
5729 #if MagickLibVersion >= 0x700
5730 double z;
5731 #endif
5732 MagickBooleanType status;
5733
5734 /* Parse parameters given to function */
5735 #if MagickLibVersion >= 0x700
5736 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd", &x, &y, &z) == FAILURE) {
5737 #else
5738 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &x, &y) == FAILURE) {
5739 #endif
5740 return;
5741 }
5742
5743 intern = Z_IMAGICK_P(getThis());
5744 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5745 return;
5746
5747 #if MagickLibVersion >= 0x700
5748 status = MagickSetImageRedPrimary(intern->magick_wand, x, y, z);
5749 #else
5750 status = MagickSetImageRedPrimary(intern->magick_wand, x, y);
5751 #endif
5752
5753 /* No magick is going to happen */
5754 if (status == MagickFalse) {
5755 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image red primary" TSRMLS_CC);
5756 return;
5757 }
5758 RETURN_TRUE;
5759 }
5760 /* }}} */
5761
5762 /* {{{ proto bool Imagick::setImageRenderingIntent(int rendering_intent)
5763 Sets the image rendering intent.
5764 */
5765 PHP_METHOD(Imagick, setImageRenderingIntent)
5766 {
5767 php_imagick_object *intern;
5768 im_long rendering_intent;
5769 MagickBooleanType status;
5770
5771 /* Parse parameters given to function */
5772 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &rendering_intent) == FAILURE) {
5773 return;
5774 }
5775
5776 intern = Z_IMAGICK_P(getThis());
5777 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5778 return;
5779
5780 status = MagickSetImageRenderingIntent(intern->magick_wand, rendering_intent);
5781
5782 /* No magick is going to happen */
5783 if (status == MagickFalse) {
5784 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image rendering intent" TSRMLS_CC);
5785 return;
5786 }
5787 RETURN_TRUE;
5788 }
5789 /* }}} */
5790
5791 /* {{{ proto bool Imagick::setImageVirtualPixelMethod(int method)
5792 Sets the image virtual pixel method.
5793 */
5794 PHP_METHOD(Imagick, setImageVirtualPixelMethod)
5795 {
5796 php_imagick_object *intern;
5797 im_long virtual_pixel;
5798
5799 /* Parse parameters given to function */
5800 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &virtual_pixel) == FAILURE) {
5801 return;
5802 }
5803
5804 intern = Z_IMAGICK_P(getThis());
5805 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5806 return;
5807
5808 MagickSetImageVirtualPixelMethod(intern->magick_wand, virtual_pixel);
5809 RETURN_TRUE;
5810 }
5811 /* }}} */
5812
5813 /* {{{ proto bool Imagick::setImageWhitePoint(float x, float y)
5814
5815 For IM7 the prototype is
5816 proto bool Imagick::setImageWhitePoint(float x, float y, float z)
5817
5818 Sets the image chromaticity white point.
5819 */
5820 PHP_METHOD(Imagick, setImageWhitePoint)
5821 {
5822 php_imagick_object *intern;
5823 double x, y;
5824 #if MagickLibVersion >= 0x700
5825 double z;
5826 #endif
5827 MagickBooleanType status;
5828
5829 /* Parse parameters given to function */
5830 #if MagickLibVersion >= 0x700
5831 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd", &x, &y, &z) == FAILURE) {
5832 #else
5833 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &x, &y) == FAILURE) {
5834 #endif
5835 return;
5836 }
5837
5838 intern = Z_IMAGICK_P(getThis());
5839 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5840 return;
5841
5842 #if MagickLibVersion >= 0x700
5843 status = MagickSetImageWhitePoint(intern->magick_wand, x, y, z);
5844 #else
5845 status = MagickSetImageWhitePoint(intern->magick_wand, x, y);
5846 #endif
5847
5848 /* No magick is going to happen */
5849 if (status == MagickFalse) {
5850 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image white point" TSRMLS_CC);
5851 return;
5852 }
5853 RETURN_TRUE;
5854 }
5855 /* }}} */
5856
5857 /* {{{ proto bool Imagick::sigmoidalContrastImage(bool sharpen, float contrast, float midpoint[, int channel])
5858 Adjusts the contrast of an image with a non-linear sigmoidal contrast algorithm. Increase the contrast of the image using a sigmoidal transfer function without saturating highlights or shadows. Contrast indicates how much to increase the contrast (0 is none; 3 is typical; 20 is pushing it); mid-point indicates where midtones fall in the resultant image (0 is white; 50 is middle-gray; 100 is black). Set sharpen to true to increase the image contrast otherwise the contrast is reduced.
5859 */
5860 PHP_METHOD(Imagick, sigmoidalContrastImage)
5861 {
5862 php_imagick_object *intern;
5863 zend_bool sharpen;
5864 double contrast, midpoint;
5865 MagickBooleanType status;
5866 im_long channel = IM_DEFAULT_CHANNEL;
5867
5868 /* Parse parameters given to function */
5869 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "bdd|l", &sharpen, &contrast, &midpoint, &channel) == FAILURE) {
5870 return;
5871 }
5872
5873 intern = Z_IMAGICK_P(getThis());
5874 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5875 return;
5876
5877 status = MagickSigmoidalContrastImageChannel(intern->magick_wand, channel, sharpen, contrast, midpoint);
5878
5879 /* No magick is going to happen */
5880 if (status == MagickFalse) {
5881 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to sigmoidal contrast image" TSRMLS_CC);
5882 return;
5883 }
5884 RETURN_TRUE;
5885 }
5886 /* }}} */
5887
5888 /* {{{ proto bool Imagick::stereoImage(Imagick offset_wand)
5889 Composites two images and produces a single image that is the composite of a left and right image of a stereo pair
5890 */
5891 PHP_METHOD(Imagick, stereoImage)
5892 {
5893 MagickWand *tmp_wand;
5894 zval *magick_object;
5895 php_imagick_object *intern, *intern_second, *intern_return;
5896
5897 /* Parse parameters given to function */
5898 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &magick_object, php_imagick_sc_entry) == FAILURE) {
5899 return;
5900 }
5901
5902 intern = Z_IMAGICK_P(getThis());
5903 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5904 return;
5905
5906 intern_second = Z_IMAGICK_P(magick_object);
5907 if (php_imagick_ensure_not_empty (intern_second->magick_wand) == 0)
5908 return;
5909
5910 tmp_wand = MagickStereoImage(intern->magick_wand, intern_second->magick_wand);
5911
5912 if (tmp_wand == NULL) {
5913 php_imagick_convert_imagick_exception(intern->magick_wand, "Stereo image failed" TSRMLS_CC);
5914 return;
5915 }
5916
5917 object_init_ex(return_value, php_imagick_sc_entry);
5918 intern_return = Z_IMAGICK_P(return_value);
5919 php_imagick_replace_magickwand(intern_return, tmp_wand);
5920
5921 return;
5922 }
5923 /* }}} */
5924
5925 /* {{{ proto Imagick Imagick::textureImage(Imagick texture_wand)
5926 Repeatedly tiles the texture image across and down the image canvas.
5927 */
5928 PHP_METHOD(Imagick, textureImage)
5929 {
5930 MagickWand *tmp_wand;
5931 zval *magick_object;
5932 php_imagick_object *intern, *intern_second, *intern_return;
5933
5934 /* Parse parameters given to function */
5935 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &magick_object, php_imagick_sc_entry) == FAILURE) {
5936 return;
5937 }
5938
5939 intern = Z_IMAGICK_P(getThis());
5940 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5941 return;
5942
5943 intern_second = Z_IMAGICK_P(magick_object);
5944 if (php_imagick_ensure_not_empty (intern_second->magick_wand) == 0)
5945 return;
5946
5947 tmp_wand = MagickTextureImage(intern->magick_wand, intern_second->magick_wand);
5948
5949 if (!tmp_wand) {
5950 php_imagick_convert_imagick_exception(intern->magick_wand, "Texture image failed" TSRMLS_CC);
5951 return;
5952 }
5953
5954 object_init_ex(return_value, php_imagick_sc_entry);
5955 intern_return = Z_IMAGICK_P(return_value);
5956 php_imagick_replace_magickwand(intern_return, tmp_wand);
5957
5958 return;
5959 }
5960 /* }}} */
5961
5962 /* {{{ proto bool Imagick::tintImage(ImagickPixel tint, ImagickPixel opacity, bool legacy = false)
5963 Applies a color vector to each pixel in the image. The 'opacity' color is a per channel
5964 strength factor for how strongly the color should be applied. If legacy is true, the behaviour
5965 of this function is incorrect, but consistent with how it behaved before Imagick version 3.4.0
5966 */
5967 PHP_METHOD(Imagick, tintImage)
5968 {
5969 php_imagick_object *intern;
5970 zval *tint_param, *opacity_param;
5971 MagickBooleanType status;
5972 PixelWand *tint_wand, *opacity_wand;
5973 zend_bool tint_allocated, opacity_allocated;
5974 zend_bool legacy = 0;
5975
5976 /* Parse parameters given to function */
5977 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|b", &tint_param, &opacity_param, &legacy) == FAILURE) {
5978 return;
5979 }
5980
5981 intern = Z_IMAGICK_P(getThis());
5982 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
5983 return;
5984
5985 tint_wand = php_imagick_zval_to_pixelwand (tint_param, IMAGICK_CLASS, &tint_allocated TSRMLS_CC);
5986 if (!tint_wand)
5987 return;
5988
5989 if (legacy) {
5990 opacity_wand = php_imagick_zval_to_opacity(opacity_param, IMAGICK_CLASS, &opacity_allocated TSRMLS_CC);
5991 }
5992 else {
5993 opacity_wand = php_imagick_zval_to_pixelwand(opacity_param, IMAGICK_CLASS, &opacity_allocated TSRMLS_CC);
5994 }
5995
5996
5997 if (!opacity_wand) {
5998 if (tint_allocated)
5999 tint_wand = DestroyPixelWand (tint_wand);
6000 return;
6001 }
6002
6003 status = MagickTintImage(intern->magick_wand, tint_wand, opacity_wand);
6004
6005 if (tint_allocated)
6006 tint_wand = DestroyPixelWand (tint_wand);
6007
6008 if (opacity_allocated)
6009 opacity_wand = DestroyPixelWand (opacity_wand);
6010
6011 /* No magick is going to happen */
6012 if (status == MagickFalse) {
6013 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable tint image" TSRMLS_CC);
6014 return;
6015 }
6016 RETURN_TRUE;
6017 }
6018 /* }}} */
6019
6020 /* {{{ proto bool Imagick::unsharpMaskImage(float radius, float sigma, float amount, float threshold[, int channel])
6021 Sharpens an image. We convolve the image with a Gaussian operator of the given radius and standard deviation (sigma). For reasonable results, radius should be larger than sigma. Use a radius of 0 and Imagick::UnsharpMaskImage() selects a suitable radius for you.
6022 */
6023 PHP_METHOD(Imagick, unsharpMaskImage)
6024 {
6025 php_imagick_object *intern;
6026 double radius, sigma, amount, threshold;
6027 MagickBooleanType status;
6028 im_long channel = IM_DEFAULT_CHANNEL;
6029
6030 /* Parse parameters given to function */
6031 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dddd|l", &radius, &sigma, &amount, &threshold, &channel) == FAILURE) {
6032 return;
6033 }
6034
6035 intern = Z_IMAGICK_P(getThis());
6036 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6037 return;
6038
6039 status = MagickUnsharpMaskImageChannel(intern->magick_wand, channel, radius, sigma, amount, threshold);
6040
6041 /* No magick is going to happen */
6042 if (status == MagickFalse) {
6043 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to unsharp mask image" TSRMLS_CC);
6044 return;
6045 }
6046 RETURN_TRUE;
6047 }
6048 /* }}} */
6049
6050
6051
6052
6053 #if MagickLibVersion >= 0x700
6054
6055 /* {{{ proto bool Imagick::convolveImage(array kernel[, int channel])
6056 Applies a custom convolution kernel to the image.
6057 */
6058 PHP_METHOD(Imagick, convolveImage)
6059 {
6060 zval *objvar;
6061 php_imagick_object *intern;
6062 php_imagickkernel_object *kernel;
6063 MagickBooleanType status;
6064 im_long channel = IM_DEFAULT_CHANNEL;
6065
6066 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|l", &objvar, php_imagickkernel_sc_entry, &channel) == FAILURE) {
6067 return;
6068 }
6069
6070 intern = Z_IMAGICK_P(getThis());
6071 kernel = Z_IMAGICKKERNEL_P(objvar);
6072
6073 IMAGICK_KERNEL_NOT_NULL_EMPTY(kernel);
6074 status = MagickConvolveImageChannel(intern->magick_wand, channel, kernel->kernel_info);
6075
6076 // No magick is going to happen
6077 if (status == MagickFalse) {
6078 php_imagick_convert_imagick_exception(intern->magick_wand, "Failed to filter image" TSRMLS_CC);
6079 return;
6080 }
6081
6082 RETURN_TRUE;
6083 }
6084
6085 #else
6086
6087 /* {{{ proto bool Imagick::convolveImage(array kernel[, int channel])
6088 Applies a custom convolution kernel to the image.
6089 */
6090 PHP_METHOD(Imagick, convolveImage)
6091 {
6092 php_imagick_object *intern;
6093 MagickBooleanType status;
6094 zval *kernel_array;
6095 double *kernel;
6096 im_long channel = DefaultChannels;
6097 unsigned long order = 0;
6098 im_long num_elements = 0;
6099
6100 /* Parse parameters given to function */
6101 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &kernel_array, &channel) == FAILURE) {
6102 return;
6103 }
6104
6105 intern = Z_IMAGICK_P(getThis());
6106 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6107 return;
6108
6109 kernel = php_imagick_zval_to_double_array(kernel_array, &num_elements TSRMLS_CC);
6110
6111 if (!kernel) {
6112 php_imagick_throw_exception(IMAGICK_CLASS, "Unable to read matrix array" TSRMLS_CC);
6113 return;
6114 }
6115
6116 order = (unsigned long) sqrt(num_elements);
6117 status = MagickConvolveImageChannel(intern->magick_wand, channel, order, kernel);
6118 efree(kernel);
6119
6120 /* No magick is going to happen */
6121 if (status == MagickFalse) {
6122 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to convolve image" TSRMLS_CC);
6123 return;
6124 }
6125
6126 RETURN_TRUE;
6127 }
6128 /* }}} */
6129 #endif
6130
6131 /* {{{ proto bool Imagick::cycleColormapImage(int displace)
6132 Displaces an image's colormap by a given number of positions. If you cycle the colormap a number of times you can produce a psychodelic effect.
6133 */
6134 PHP_METHOD(Imagick, cycleColormapImage)
6135 {
6136 php_imagick_object *intern;
6137 im_long displace;
6138 MagickBooleanType status;
6139
6140 /* Parse parameters given to function */
6141 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &displace) == FAILURE) {
6142 return;
6143 }
6144
6145 intern = Z_IMAGICK_P(getThis());
6146 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6147 return;
6148
6149 status = MagickCycleColormapImage(intern->magick_wand, displace);
6150
6151 /* No magick is going to happen */
6152 if (status == MagickFalse) {
6153 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to cycle image colormap" TSRMLS_CC);
6154 return;
6155 }
6156
6157 RETURN_TRUE;
6158 }
6159 /* }}} */
6160
6161 /* {{{ proto Imagick Imagick::deconstructImages()
6162 Compares each image with the next in a sequence and returns the maximum bounding region of any pixel differences it discovers.
6163 */
6164 PHP_METHOD(Imagick, deconstructImages)
6165 {
6166 MagickWand *tmp_wand;
6167 php_imagick_object *intern, *intern_return;
6168
6169 if (zend_parse_parameters_none() == FAILURE) {
6170 return;
6171 }
6172
6173 intern = Z_IMAGICK_P(getThis());
6174 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6175 return;
6176
6177 tmp_wand = MagickDeconstructImages(intern->magick_wand);
6178
6179 if (tmp_wand == NULL) {
6180 php_imagick_convert_imagick_exception(intern->magick_wand, "Deconstruct image failed" TSRMLS_CC);
6181 return;
6182 }
6183
6184 object_init_ex(return_value, php_imagick_sc_entry);
6185 intern_return = Z_IMAGICK_P(return_value);
6186 php_imagick_replace_magickwand(intern_return, tmp_wand);
6187
6188 return;
6189 }
6190 /* }}} */
6191
6192 /* {{{ proto Imagick Imagick::getImageRegion(int width, int height, int x, int y)
6193 Extracts a region of the image and returns it as a new image.
6194 */
6195 PHP_METHOD(Imagick, getImageRegion)
6196 {
6197 MagickWand *tmp_wand;
6198 php_imagick_object *intern, *intern_return;
6199 im_long width, height, x, y;
6200
6201 /* Parse parameters given to function */
6202 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llll", &width, &height, &x, &y) == FAILURE) {
6203 return;
6204 }
6205
6206 intern = Z_IMAGICK_P(getThis());
6207 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6208 return;
6209
6210 tmp_wand = MagickGetImageRegion(intern->magick_wand, width, height, x, y);
6211
6212 if (tmp_wand == NULL) {
6213 php_imagick_convert_imagick_exception(intern->magick_wand, "Get image region failed" TSRMLS_CC);
6214 return;
6215 }
6216
6217 object_init_ex(return_value, php_imagick_sc_entry);
6218 intern_return = Z_IMAGICK_P(return_value);
6219 php_imagick_replace_magickwand(intern_return, tmp_wand);
6220
6221 return;
6222
6223 }
6224 /* }}} */
6225
6226 /* {{{ proto bool Imagick::despeckleImage()
6227 Reduces the speckle noise in an image while perserving the edges of the original image.
6228 */
6229 PHP_METHOD(Imagick, despeckleImage)
6230 {
6231 php_imagick_object *intern;
6232 MagickBooleanType status;
6233
6234 if (zend_parse_parameters_none() == FAILURE) {
6235 return;
6236 }
6237
6238 intern = Z_IMAGICK_P(getThis());
6239 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6240 return;
6241
6242 status = MagickDespeckleImage(intern->magick_wand);
6243
6244 /* No magick is going to happen */
6245 if (status == MagickFalse) {
6246 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to despeckle image" TSRMLS_CC);
6247 return;
6248 }
6249
6250 RETURN_TRUE;
6251 }
6252 /* }}} */
6253
6254 /* {{{ proto bool Imagick::edgeImage(float radius)
6255 Enhance edges within the image with a convolution filter of the given radius. Use a radius of 0 and Edge() selects a suitable radius for you.
6256 */
6257 PHP_METHOD(Imagick, edgeImage)
6258 {
6259 php_imagick_object *intern;
6260 double radius;
6261 MagickBooleanType status;
6262
6263 /* Parse parameters given to function */
6264 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &radius) == FAILURE) {
6265 return;
6266 }
6267
6268 intern = Z_IMAGICK_P(getThis());
6269 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6270 return;
6271
6272 status = MagickEdgeImage(intern->magick_wand, radius);
6273
6274 /* No magick is going to happen */
6275 if (status == MagickFalse) {
6276 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to edge image" TSRMLS_CC);
6277 return;
6278 }
6279
6280 RETURN_TRUE;
6281
6282 }
6283 /* }}} */
6284
6285 /* {{{ proto bool Imagick::embossImage(float radius, float sigma)
6286 Returns a grayscale image with a three-dimensional effect. We convolve the image with a Gaussian operator of the given radius and standard deviation (sigma). For reasonable results, radius should be larger than sigma. Use a radius of 0 and it will choose a suitable radius for you.
6287 */
6288 PHP_METHOD(Imagick, embossImage)
6289 {
6290 php_imagick_object *intern;
6291 double radius, sigma;
6292 MagickBooleanType status;
6293
6294 /* Parse parameters given to function */
6295 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &radius, &sigma) == FAILURE) {
6296 return;
6297 }
6298
6299 intern = Z_IMAGICK_P(getThis());
6300 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6301 return;
6302
6303 status = MagickEmbossImage(intern->magick_wand, radius, sigma);
6304
6305 /* No magick is going to happen */
6306 if (status == MagickFalse) {
6307 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to emboss image" TSRMLS_CC);
6308 return;
6309 }
6310
6311 RETURN_TRUE;
6312 }
6313 /* }}} */
6314
6315 /* {{{ proto bool Imagick::enhanceImage()
6316 Applies a digital filter that improves the quality of a noisy image.
6317 */
6318 PHP_METHOD(Imagick, enhanceImage)
6319 {
6320 php_imagick_object *intern;
6321 MagickBooleanType status;
6322
6323 if (zend_parse_parameters_none() == FAILURE) {
6324 return;
6325 }
6326
6327 intern = Z_IMAGICK_P(getThis());
6328 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6329 return;
6330
6331 status = MagickEnhanceImage(intern->magick_wand);
6332
6333 /* No magick is going to happen */
6334 if (status == MagickFalse) {
6335 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to enchance image" TSRMLS_CC);
6336 return;
6337 }
6338
6339 RETURN_TRUE;
6340 }
6341 /* }}} */
6342
6343 /* {{{ proto bool Imagick::equalizeImage()
6344 Equalizes the image histogram.
6345 */
6346 PHP_METHOD(Imagick, equalizeImage)
6347 {
6348 php_imagick_object *intern;
6349 MagickBooleanType status;
6350
6351 if (zend_parse_parameters_none() == FAILURE) {
6352 return;
6353 }
6354
6355 intern = Z_IMAGICK_P(getThis());
6356 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6357 return;
6358
6359 status = MagickEqualizeImage(intern->magick_wand);
6360
6361 /* No magick is going to happen */
6362 if (status == MagickFalse) {
6363 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to equalize image" TSRMLS_CC);
6364 return;
6365 }
6366
6367 RETURN_TRUE;
6368 }
6369 /* }}} */
6370
6371 /* {{{ proto bool Imagick::evaluateImage(int op, float constant[, int channel])
6372 Applys an arithmetic, relational, or logical expression to an image. Use these operators to lighten or darken an image, to increase or decrease contrast in an image, or to produce the "negative" of an image.
6373 */
6374 PHP_METHOD(Imagick, evaluateImage)
6375 {
6376 php_imagick_object *intern;
6377 im_long evaluate_operator;
6378 double constant;
6379 MagickBooleanType status;
6380 im_long channel = IM_DEFAULT_CHANNEL;
6381
6382 /* Parse parameters given to function */
6383 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ld|l", &evaluate_operator, &constant, &channel) == FAILURE) {
6384 return;
6385 }
6386
6387 intern = Z_IMAGICK_P(getThis());
6388 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6389 return;
6390
6391 status = MagickEvaluateImageChannel(intern->magick_wand, channel, evaluate_operator, constant);
6392
6393 /* No magick is going to happen */
6394 if (status == MagickFalse) {
6395 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to evaluate image" TSRMLS_CC);
6396 return;
6397 }
6398
6399 RETURN_TRUE;
6400 }
6401 /* }}} */
6402
6403
6404 #if MagickLibVersion >= 0x687
6405 /* {{{ proto bool Imagick::evaluateImages(int EVALUATE_CONSTANT)
6406 Merge multiple images of the same size together with the selected operator.
6407 http://www.imagemagick.org/Usage/layers/#evaluate-sequence
6408 */
6409 PHP_METHOD(Imagick, evaluateImages)
6410 {
6411 php_imagick_object *intern, *intern_return;
6412 im_long evaluate_operator;
6413 MagickBooleanType status;
6414 MagickWand *evaluated_wand;
6415
6416 /* Parse parameters given to function */
6417 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &evaluate_operator) == FAILURE) {
6418 return;
6419 }
6420
6421 intern = Z_IMAGICK_P(getThis());
6422 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6423 return;
6424
6425 // MagickEvaluateImages appears to crash if index is not zero.
6426 #if MagickLibVersion > 0x628
6427 /* Get the current iterator position */
6428 status = MagickSetIteratorIndex(intern->magick_wand, 0);
6429 #else
6430 status = MagickSetImageIndex(intern->magick_wand, 0);
6431 #endif
6432
6433 /* No magick is going to happen */
6434 if (status == MagickFalse) {
6435 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set iterator index" TSRMLS_CC);
6436 return;
6437 }
6438
6439 evaluated_wand = MagickEvaluateImages(intern->magick_wand, evaluate_operator);
6440
6441 object_init_ex(return_value, php_imagick_sc_entry);
6442 intern_return = Z_IMAGICK_P(return_value);
6443 php_imagick_replace_magickwand(intern_return, evaluated_wand);
6444 return;
6445 }
6446 /* }}} */
6447 #endif //MagickLibVersion >= 0x687
6448
6449 #if MagickLibVersion > 0x655
6450
6451 /* {{{ proto bool Imagick::forwardfouriertransformimage(bool magnitude)
6452 //http://www.fftw.org/
6453 yum install fftw-devel fftw
6454 ./configure --enable-hdri
6455 */
6456 PHP_METHOD(Imagick, forwardFourierTransformImage)
6457 {
6458 php_imagick_object *intern;
6459 zend_bool magnitude;
6460 MagickBooleanType status;
6461
6462 /* Parse parameters given to function */
6463 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &magnitude) == FAILURE) {
6464 return;
6465 }
6466
6467 intern = Z_IMAGICK_P(getThis());
6468 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6469 return;
6470
6471 status = MagickForwardFourierTransformImage(intern->magick_wand, magnitude);
6472
6473 /* No magick is going to happen */
6474 if (status == MagickFalse) {
6475 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to forwardfouriertransformimage image" TSRMLS_CC);
6476 return;
6477 }
6478 RETURN_TRUE;
6479 }
6480 /* }}} */
6481
6482 #endif
6483
6484
6485 /* {{{ proto array Imagick::getImageGeometry()
6486 Returns the width and height as an associative array.
6487 */
6488 PHP_METHOD(Imagick, getImageGeometry)
6489 {
6490 long width,height;
6491 php_imagick_object *intern;
6492
6493 if (zend_parse_parameters_none() == FAILURE) {
6494 return;
6495 }
6496
6497 intern = Z_IMAGICK_P(getThis());
6498
6499 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6500 return;
6501
6502 width = MagickGetImageWidth(intern->magick_wand);
6503 height = MagickGetImageHeight(intern->magick_wand);
6504
6505 array_init(return_value);
6506 add_assoc_long(return_value, "width", width);
6507 add_assoc_long(return_value, "height", height);
6508
6509 return;
6510 }
6511 /* }}} */
6512
6513 #if MagickLibVersion < 0x700
6514 #if !defined(MAGICKCORE_EXCLUDE_DEPRECATED)
6515 /* {{{ proto ImagickPixel Imagick::getImageAttribute(string key )
6516 Returns a named attribute
6517 */
6518 PHP_METHOD(Imagick, getImageAttribute)
6519 {
6520 php_imagick_object *intern;
6521 char *key, *attribute;
6522 IM_LEN_TYPE key_len;
6523
6524 IMAGICK_METHOD_DEPRECATED("Imagick", "getImageAttribute");
6525
6526 /* Parse parameters given to function */
6527 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) {
6528 return;
6529 }
6530
6531 intern = Z_IMAGICK_P(getThis());
6532 attribute = MagickGetImageAttribute(intern->magick_wand, key);
6533
6534 if (!attribute) {
6535 RETURN_FALSE;
6536 }
6537
6538 IM_ZVAL_STRING(return_value, attribute);
6539 IMAGICK_FREE_MAGICK_MEMORY(attribute);
6540
6541 return;
6542 }
6543 /* }}} */
6544 #endif
6545 #endif
6546
6547 /* {{{ proto ImagickPixel Imagick::getImageBackgroundColor()
6548 Returns the image background color.
6549 */
6550 PHP_METHOD(Imagick, getImageBackgroundColor)
6551 {
6552 php_imagick_object *intern;
6553 php_imagickpixel_object *internp;
6554 MagickBooleanType status;
6555 PixelWand *tmp_wand;
6556
6557 if (zend_parse_parameters_none() == FAILURE) {
6558 return;
6559 }
6560
6561 intern = Z_IMAGICK_P(getThis());
6562 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6563 return;
6564
6565 tmp_wand = NewPixelWand();
6566 status = MagickGetImageBackgroundColor(intern->magick_wand, tmp_wand);
6567
6568 if (tmp_wand == (PixelWand *)NULL) {
6569 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get image background color" TSRMLS_CC);
6570 return;
6571 }
6572
6573 if (status == MagickFalse) {
6574 tmp_wand = DestroyPixelWand(tmp_wand);
6575 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get image background color" TSRMLS_CC);
6576 return;
6577 }
6578
6579 object_init_ex(return_value, php_imagickpixel_sc_entry);
6580 internp = Z_IMAGICKPIXEL_P(return_value);
6581 php_imagick_replace_pixelwand(internp, tmp_wand);
6582
6583 return;
6584 }
6585 /* }}} */
6586
6587 /* {{{ proto array Imagick::getImageBluePrimary()
6588 Returns the chromaticy green primary point. IM6: Returns an array with the keys "x" and "y".
6589 IM7: Returns an array with the keys "x", "y" and "z".
6590 */
6591 PHP_METHOD(Imagick, getImageBluePrimary)
6592 {
6593 php_imagick_object *intern;
6594 MagickBooleanType status;
6595 double x, y;
6596 #if MagickLibVersion >= 0x700
6597 double z;
6598 #endif
6599
6600 if (zend_parse_parameters_none() == FAILURE) {
6601 return;
6602 }
6603
6604 intern = Z_IMAGICK_P(getThis());
6605 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6606 return;
6607
6608 #if MagickLibVersion >= 0x700
6609 status = MagickGetImageBluePrimary(intern->magick_wand, &x, &y, &z);
6610 #else
6611 status = MagickGetImageBluePrimary(intern->magick_wand, &x, &y);
6612 #endif
6613
6614 if (status == MagickFalse) {
6615 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get image blue primary" TSRMLS_CC);
6616 return;
6617 }
6618
6619 array_init(return_value);
6620 add_assoc_double(return_value, "x", x);
6621 add_assoc_double(return_value, "y", y);
6622 #if MagickLibVersion >= 0x700
6623 add_assoc_double(return_value, "z", z);
6624 #endif
6625
6626 return;
6627 }
6628 /* }}} */
6629
6630 /* {{{ proto ImagickPixel Imagick::getImageBorderColor()
6631 Returns the image border color.
6632 */
6633 PHP_METHOD(Imagick, getImageBorderColor)
6634 {
6635 php_imagick_object *intern;
6636 php_imagickpixel_object *internp;
6637 MagickBooleanType status;
6638 PixelWand *tmp_wand;
6639
6640 if (zend_parse_parameters_none() == FAILURE) {
6641 return;
6642 }
6643
6644 intern = Z_IMAGICK_P(getThis());
6645 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6646 return;
6647
6648 tmp_wand = NewPixelWand();
6649 status = MagickGetImageBorderColor(intern->magick_wand, tmp_wand);
6650
6651 if (tmp_wand == (PixelWand *)NULL) {
6652 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get image border color" TSRMLS_CC);
6653 return;
6654 }
6655
6656 if (status == MagickFalse) {
6657 tmp_wand = DestroyPixelWand(tmp_wand);
6658 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get image border color" TSRMLS_CC);
6659 return;
6660 }
6661
6662 object_init_ex(return_value, php_imagickpixel_sc_entry);
6663 internp = Z_IMAGICKPIXEL_P(return_value);
6664 php_imagick_replace_pixelwand(internp, tmp_wand);
6665
6666 return;
6667 }
6668 /* }}} */
6669
6670 /* {{{ proto int Imagick::getImageChannelDepth()
6671 Gets the depth for a particular image channel.
6672 */
6673 PHP_METHOD(Imagick, getImageChannelDepth)
6674 {
6675 php_imagick_object *intern;
6676 im_long channel_type, channel_depth;
6677
6678 /* Parse parameters given to function */
6679 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &channel_type) == FAILURE) {
6680 return;
6681 }
6682
6683 intern = Z_IMAGICK_P(getThis());
6684 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6685 return;
6686
6687 channel_depth = MagickGetImageChannelDepth(intern->magick_wand, channel_type);
6688 RETVAL_LONG(channel_depth);
6689 }
6690 /* }}} */
6691
6692 /* {{{ proto float Imagick::getImageChannelDistortion(Imagick reference, int channel, int metric)
6693 Compares one or more image channels of an image to a reconstructed image and returns the specified distortion metric.
6694 */
6695 PHP_METHOD(Imagick, getImageChannelDistortion)
6696 {
6697 zval *objvar;
6698 php_imagick_object *intern, *intern_second;
6699 im_long channel_type, metric_type;
6700 double distortion;
6701 MagickBooleanType status;
6702
6703 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Oll", &objvar, php_imagick_sc_entry, &channel_type, &metric_type) == FAILURE) {
6704 return;
6705 }
6706
6707 intern = Z_IMAGICK_P(getThis());
6708 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6709 return;
6710
6711 intern_second = Z_IMAGICK_P(objvar);
6712 if (php_imagick_ensure_not_empty (intern_second->magick_wand) == 0)
6713 return;
6714
6715 status = MagickGetImageChannelDistortion(intern->magick_wand, intern_second->magick_wand, channel_type, metric_type, &distortion);
6716
6717 if (status == MagickFalse) {
6718 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get image channel distortion" TSRMLS_CC);
6719 return;
6720 }
6721
6722 RETVAL_DOUBLE(distortion);
6723
6724 }
6725 /* }}} */
6726
6727 #if !defined(MAGICKCORE_EXCLUDE_DEPRECATED)
6728 #if MagickLibVersion < 0x700
6729 /* {{{ proto array Imagick::getImageChannelExtrema(int channel)
6730 Gets the extrema for one or more image channels. Return value is an associative array with the keys "minima" and "maxima".
6731 */
6732 PHP_METHOD(Imagick, getImageChannelExtrema)
6733 {
6734 php_imagick_object *intern;
6735 im_long channel_type;
6736 size_t minima, maxima;
6737 MagickBooleanType status;
6738
6739 IMAGICK_METHOD_DEPRECATED ("Imagick", "getImageChannelExtrema");
6740
6741 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &channel_type) == FAILURE) {
6742 return;
6743 }
6744
6745 intern = Z_IMAGICK_P(getThis());
6746 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6747 return;
6748
6749 status = MagickGetImageChannelExtrema(intern->magick_wand, channel_type, &minima, &maxima);
6750
6751 if (status == MagickFalse) {
6752 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get image channel extrema" TSRMLS_CC);
6753 return;
6754 }
6755
6756 array_init(return_value);
6757 add_assoc_long(return_value, "minima", minima);
6758 add_assoc_long(return_value, "maxima", maxima);
6759
6760 return;
6761 }
6762 /* }}} */
6763 #endif //#if MagickLibVersion < 0x700
6764 #endif
6765
6766 /* {{{ proto array Imagick::getImageChannelMean(int channel)
6767 Gets the mean and standard deviation of one or more image channels. Return value is an associative array with the keys "mean" and "standardDeviation".
6768 */
6769 PHP_METHOD(Imagick, getImageChannelMean)
6770 {
6771 php_imagick_object *intern;
6772 im_long channel_type;
6773 double mean, standard_deviation;
6774 MagickBooleanType status;
6775
6776 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &channel_type) == FAILURE) {
6777 return;
6778 }
6779
6780 intern = Z_IMAGICK_P(getThis());
6781 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6782 return;
6783
6784 status = MagickGetImageChannelMean(intern->magick_wand, channel_type, &mean, &standard_deviation);
6785
6786 if (status == MagickFalse) {
6787 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get image channel mean" TSRMLS_CC);
6788 return;
6789 }
6790
6791 array_init(return_value);
6792 add_assoc_double(return_value, "mean", mean);
6793 add_assoc_double(return_value, "standardDeviation", standard_deviation);
6794
6795 return;
6796 }
6797 /* }}} */
6798
6799 /* {{{ proto array Imagick::getImageChannelStatistics()
6800 Returns statistics for each channel in the image. The statistics incude the channel depth, its minima and maxima, the mean, and the standard deviation. You can access the red channel mean, for example, like this:
6801 */
6802 PHP_METHOD(Imagick, getImageChannelStatistics)
6803 {
6804 #if PHP_VERSION_ID >= 70000
6805 zval tmp;
6806 #else
6807 zval *tmp;
6808 #endif
6809
6810 const long channels[] = {
6811 UndefinedChannel, RedChannel, CyanChannel,
6812 GreenChannel, MagentaChannel, BlueChannel,
6813 YellowChannel, OpacityChannel, BlackChannel,
6814 #if MagickLibVersion < 0x700
6815 MatteChannel
6816 #endif
6817 };
6818 php_imagick_object *intern;
6819 ChannelStatistics *statistics;
6820 unsigned int i;
6821 #if MagickLibVersion < 0x700
6822 unsigned int elements = 10;
6823 #endif // #if MagickLibVersion >= 0x700
6824
6825 if (zend_parse_parameters_none() == FAILURE) {
6826 return;
6827 }
6828
6829 intern = Z_IMAGICK_P(getThis());
6830 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6831 return;
6832
6833 #if MagickLibVersion >= 0x700
6834 statistics = MagickGetImageStatistics(intern->magick_wand);
6835 #else
6836 statistics = MagickGetImageChannelStatistics(intern->magick_wand);
6837 #endif
6838
6839 array_init(return_value);
6840
6841 #if MagickLibVersion >= 0x700
6842 for (i=0; i < sizeof(channels)/sizeof(channels[0]); i++) {
6843 #if PHP_VERSION_ID >= 70000
6844 array_init(&tmp);
6845 add_assoc_double(&tmp, "mean", statistics[i].mean);
6846 add_assoc_double(&tmp, "minima", statistics[i].minima);
6847 add_assoc_double(&tmp, "maxima", statistics[i].maxima);
6848 add_assoc_double(&tmp, "standardDeviation", statistics[i].standard_deviation);
6849 #if MagickLibVersion < 0x635
6850 add_assoc_long(&tmp, "scale", statistics[i].scale);
6851 #endif //0x635
6852 add_assoc_long(&tmp, "depth", statistics[i].depth);
6853 add_index_zval(return_value, i, &tmp);
6854 #else //not ZE3
6855 MAKE_STD_ZVAL(tmp);
6856 array_init(tmp);
6857 add_assoc_double(tmp, "mean", statistics[i].mean);
6858 add_assoc_double(tmp, "minima", statistics[i].minima);
6859 add_assoc_double(tmp, "maxima", statistics[i].maxima);
6860 add_assoc_double(tmp, "standardDeviation", statistics[i].standard_deviation);
6861 #if MagickLibVersion < 0x635
6862 add_assoc_long(&tmp, "scale", statistics[i].scale);
6863 #endif //0x635
6864 add_assoc_long(tmp, "depth", statistics[i].depth);
6865 add_index_zval(return_value, channels[i], tmp);
6866 #endif //end ZE3
6867 }
6868 #else //below MagickLibVersion>= 0x700
6869 for (i = 0; i < elements ; i++) {
6870 #if PHP_VERSION_ID >= 70000
6871 array_init(&tmp);
6872 add_assoc_double(&tmp, "mean", statistics[channels[i]].mean);
6873 add_assoc_double(&tmp, "minima", statistics[channels[i]].minima);
6874 add_assoc_double(&tmp, "maxima", statistics[channels[i]].maxima);
6875 add_assoc_double(&tmp, "standardDeviation", statistics[channels[i]].standard_deviation);
6876 #if MagickLibVersion < 0x635
6877 add_assoc_long(&tmp, "scale", statistics[channels[i]].scale);
6878 #endif
6879 add_assoc_long(&tmp, "depth", statistics[channels[i]].depth);
6880 add_index_zval(return_value, channels[i], &tmp);
6881 #else
6882 MAKE_STD_ZVAL(tmp);
6883 array_init(tmp);
6884 add_assoc_double(tmp, "mean", statistics[channels[i]].mean);
6885 add_assoc_double(tmp, "minima", statistics[channels[i]].minima);
6886 add_assoc_double(tmp, "maxima", statistics[channels[i]].maxima);
6887 add_assoc_double(tmp, "standardDeviation", statistics[channels[i]].standard_deviation);
6888 #if MagickLibVersion < 0x635
6889 add_assoc_long(&tmp, "scale", statistics[channels[i]].scale);
6890 #endif
6891 add_assoc_long(tmp, "depth", statistics[channels[i]].depth);
6892 add_index_zval(return_value, channels[i], tmp);
6893 #endif
6894
6895 }
6896 #endif
6897
6898 //etc.
6899 // channel_statistics[i].sum_squared*=area;
6900 // channel_statistics[i].sum_cubed*=area;
6901 // channel_statistics[i].sum_fourth_power*=area;
6902
6903 MagickRelinquishMemory(statistics);
6904 return;
6905 }
6906 /* }}} */
6907
6908 /* {{{ proto ImagickPixel Imagick::getImageColormapColor(int index, ImagickPixel color)
6909 Returns the color of the specified colormap index.
6910 */
6911 PHP_METHOD(Imagick, getImageColormapColor)
6912 {
6913 php_imagick_object *intern;
6914 php_imagickpixel_object *internp;
6915 MagickBooleanType status;
6916 PixelWand *tmp_wand;
6917 im_long index;
6918
6919 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) {
6920 return;
6921 }
6922
6923 intern = Z_IMAGICK_P(getThis());
6924 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6925 return;
6926
6927 tmp_wand = NewPixelWand();
6928 status = MagickGetImageColormapColor(intern->magick_wand, index , tmp_wand);
6929
6930 if (tmp_wand == (PixelWand *)NULL) {
6931 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get image colormap color" TSRMLS_CC);
6932 return;
6933 }
6934
6935 if (status == MagickFalse) {
6936 tmp_wand = DestroyPixelWand(tmp_wand);
6937 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get image colormap color" TSRMLS_CC);
6938 return;
6939 }
6940
6941 object_init_ex(return_value, php_imagickpixel_sc_entry);
6942 internp = Z_IMAGICKPIXEL_P(return_value);
6943 php_imagick_replace_pixelwand(internp, tmp_wand);
6944
6945 return;
6946 }
6947 /* }}} */
6948
6949 /* {{{ proto int Imagick::getImageColorspace()
6950 Gets the image colorspace.
6951 */
6952 PHP_METHOD(Imagick, getImageColorspace)
6953 {
6954 php_imagick_object *intern;
6955 long colorSpace;
6956
6957 if (zend_parse_parameters_none() == FAILURE) {
6958 return;
6959 }
6960
6961 intern = Z_IMAGICK_P(getThis());
6962 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6963 return;
6964
6965 colorSpace = MagickGetImageColorspace(intern->magick_wand);
6966 RETVAL_LONG(colorSpace);
6967 }
6968 /* }}} */
6969
6970 /* {{{ proto int Imagick::getImageCompose()
6971 Returns the composite operator associated with the image.
6972 */
6973 PHP_METHOD(Imagick, getImageCompose)
6974 {
6975 php_imagick_object *intern;
6976 long composite;
6977
6978 if (zend_parse_parameters_none() == FAILURE) {
6979 return;
6980 }
6981
6982 intern = Z_IMAGICK_P(getThis());
6983 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
6984 return;
6985
6986 composite = MagickGetImageCompose(intern->magick_wand);
6987 RETVAL_LONG(composite);
6988 }
6989 /* }}} */
6990
6991 /* {{{ proto int Imagick::getImageDelay()
6992 Gets the image delay.
6993 */
6994 PHP_METHOD(Imagick, getImageDelay)
6995 {
6996 php_imagick_object *intern;
6997 long delay;
6998
6999 if (zend_parse_parameters_none() == FAILURE) {
7000 return;
7001 }
7002
7003 intern = Z_IMAGICK_P(getThis());
7004 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7005 return;
7006
7007 delay = MagickGetImageDelay(intern->magick_wand);
7008 RETVAL_LONG(delay);
7009 }
7010 /* }}} */
7011
7012 /* {{{ proto int Imagick::getImageDepth()
7013 Gets the image depth.
7014 */
7015 PHP_METHOD(Imagick, getImageDepth)
7016 {
7017 php_imagick_object *intern;
7018 long depth;
7019
7020 if (zend_parse_parameters_none() == FAILURE) {
7021 return;
7022 }
7023
7024 intern = Z_IMAGICK_P(getThis());
7025 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7026 return;
7027
7028 depth = MagickGetImageDepth(intern->magick_wand);
7029 RETVAL_LONG(depth);
7030 }
7031 /* }}} */
7032
7033 /* {{{ proto float Imagick::getImageDistortion(MagickWand reference, int metric)
7034 Compares an image to a reconstructed image and returns the specified distortion metric.
7035 */
7036 PHP_METHOD(Imagick, getImageDistortion)
7037 {
7038 zval *objvar;
7039 php_imagick_object *intern, *intern_second;
7040 im_long metric_type;
7041 double distortion;
7042 MagickBooleanType status;
7043
7044 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol", &objvar, php_imagick_sc_entry, &metric_type) == FAILURE) {
7045 return;
7046 }
7047
7048 intern = Z_IMAGICK_P(getThis());
7049 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7050 return;
7051
7052 intern_second = Z_IMAGICK_P(objvar);
7053 if (php_imagick_ensure_not_empty (intern_second->magick_wand) == 0)
7054 return;
7055
7056 status = MagickGetImageDistortion(intern->magick_wand, intern_second->magick_wand, metric_type, &distortion);
7057
7058 if (status == MagickFalse) {
7059 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get image distortion" TSRMLS_CC);
7060 return;
7061 }
7062
7063 RETVAL_DOUBLE(distortion);
7064 }
7065 /* }}} */
7066
7067 #if !defined(MAGICKCORE_EXCLUDE_DEPRECATED)
7068 #if MagickLibVersion < 0x700
7069 /* {{{ proto array Imagick::getImageExtrema()
7070 Gets the extrema for the image. Returns an associative array with the keys "min" and "max".
7071 */
7072 PHP_METHOD(Imagick, getImageExtrema)
7073 {
7074 php_imagick_object *intern;
7075 size_t min, max;
7076 MagickBooleanType status;
7077
7078 IMAGICK_METHOD_DEPRECATED ("Imagick", "getImageExtrema");
7079
7080 if (zend_parse_parameters_none() == FAILURE) {
7081 return;
7082 }
7083
7084 intern = Z_IMAGICK_P(getThis());
7085 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7086 return;
7087
7088 status = MagickGetImageExtrema(intern->magick_wand, &min, &max);
7089
7090 if (status == MagickFalse) {
7091 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get image extrema" TSRMLS_CC);
7092 return;
7093 }
7094
7095 array_init(return_value);
7096 add_assoc_long(return_value, "min", min);
7097 add_assoc_long(return_value, "max", max);
7098
7099 return;
7100 }
7101 /* }}} */
7102 #endif //#if MagickLibVersion < 0x700
7103 #endif
7104
7105 /* {{{ proto long Imagick::getImageDispose()
7106 Gets the image disposal method.
7107 */
7108 PHP_METHOD(Imagick, getImageDispose)
7109 {
7110 php_imagick_object *intern;
7111 long dispose;
7112
7113 if (zend_parse_parameters_none() == FAILURE) {
7114 return;
7115 }
7116
7117 intern = Z_IMAGICK_P(getThis());
7118 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7119 return;
7120
7121 dispose = MagickGetImageDispose(intern->magick_wand);
7122 RETVAL_LONG(dispose);
7123 }
7124 /* }}} */
7125
7126 /* {{{ proto float Imagick::getImageGamma()
7127 Gets the image gamma.
7128 */
7129 PHP_METHOD(Imagick, getImageGamma)
7130 {
7131 php_imagick_object *intern;
7132 double gamma;
7133
7134 if (zend_parse_parameters_none() == FAILURE) {
7135 return;
7136 }
7137
7138 intern = Z_IMAGICK_P(getThis());
7139 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7140 return;
7141
7142 gamma = MagickGetImageGamma(intern->magick_wand);
7143 RETVAL_DOUBLE(gamma);
7144 }
7145 /* }}} */
7146
7147 /* {{{ proto array Imagick::getImageGreenPrimary()
7148 Returns the chromaticy green primary point. IM6: Returns an array with the keys "x" and "y".
7149 IM7: Returns an array with the keys "x", "y" and "z".
7150 */
7151 PHP_METHOD(Imagick, getImageGreenPrimary)
7152 {
7153 php_imagick_object *intern;
7154 double x, y;
7155 #if MagickLibVersion >= 0x700
7156 double z;
7157 #endif
7158 MagickBooleanType status;
7159
7160 if (zend_parse_parameters_none() == FAILURE) {
7161 return;
7162 }
7163
7164 intern = Z_IMAGICK_P(getThis());
7165 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7166 return;
7167
7168 #if MagickLibVersion >= 0x700
7169 status = MagickGetImageGreenPrimary(intern->magick_wand, &x, &y, &z);
7170 #else
7171 status = MagickGetImageGreenPrimary(intern->magick_wand, &x, &y);
7172 #endif
7173
7174 if (status == MagickFalse) {
7175 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get image green primary" TSRMLS_CC);
7176 return;
7177 }
7178
7179 array_init(return_value);
7180 add_assoc_double(return_value, "x", x);
7181 add_assoc_double(return_value, "y", y);
7182 #if MagickLibVersion >= 0x700
7183 add_assoc_double(return_value, "z", z);
7184 #endif
7185
7186 return;
7187 }
7188 /* }}} */
7189
7190 /* {{{ proto int Imagick::getImageHeight()
7191 Returns the image height.
7192 */
7193 PHP_METHOD(Imagick, getImageHeight)
7194 {
7195 php_imagick_object *intern;
7196 long height;
7197
7198 if (zend_parse_parameters_none() == FAILURE) {
7199 return;
7200 }
7201
7202 intern = Z_IMAGICK_P(getThis());
7203 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7204 return;
7205
7206 height = MagickGetImageHeight(intern->magick_wand);
7207 RETVAL_LONG(height);
7208 }
7209 /* }}} */
7210
7211 /* {{{ proto array Imagick::getImageHistogram()
7212 Returns the image histogram as an array of ImagickPixel objects.
7213 */
7214 PHP_METHOD(Imagick, getImageHistogram)
7215 {
7216 php_imagick_object *intern;
7217 php_imagickpixel_object *internp;
7218 PixelWand **wand_array;
7219 size_t colors = 0;
7220 unsigned long i;
7221 #if PHP_VERSION_ID >= 70000
7222 zval tmp_pixelwand;
7223 #else
7224 zval *tmp_pixelwand;
7225 #endif
7226
7227
7228 if (zend_parse_parameters_none() == FAILURE) {
7229 return;
7230 }
7231
7232 intern = Z_IMAGICK_P(getThis());
7233 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7234 return;
7235
7236 wand_array = MagickGetImageHistogram(intern->magick_wand, &colors);
7237 array_init(return_value);
7238
7239 for (i = 0; i < colors; i++) {
7240 if (wand_array[i]) {
7241 #if PHP_VERSION_ID >= 70000
7242 object_init_ex(&tmp_pixelwand, php_imagickpixel_sc_entry);
7243 internp = Z_IMAGICKPIXEL_P(&tmp_pixelwand);
7244 php_imagick_replace_pixelwand(internp, wand_array[i]);
7245 add_next_index_zval(return_value, &tmp_pixelwand);
7246 #else
7247 MAKE_STD_ZVAL(tmp_pixelwand);
7248 object_init_ex(tmp_pixelwand, php_imagickpixel_sc_entry);
7249 internp = (php_imagickpixel_object *)zend_object_store_get_object(tmp_pixelwand TSRMLS_CC);
7250 php_imagick_replace_pixelwand(internp, wand_array[i]);
7251 add_next_index_zval(return_value, tmp_pixelwand);
7252 #endif
7253 }
7254 }
7255
7256 IMAGICK_FREE_MAGICK_MEMORY(wand_array);
7257 return;
7258 }
7259 /* }}} */
7260
7261 /* {{{ proto int Imagick::getImageInterlaceScheme()
7262 Gets the image interlace scheme.
7263 */
7264 PHP_METHOD(Imagick, getImageInterlaceScheme)
7265 {
7266 php_imagick_object *intern;
7267 long interlace;
7268
7269 IMAGICK_METHOD_DEPRECATED ("Imagick", "getImageInterlaceScheme");
7270
7271 if (zend_parse_parameters_none() == FAILURE) {
7272 return;
7273 }
7274
7275 intern = Z_IMAGICK_P(getThis());
7276 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7277 return;
7278
7279 interlace = MagickGetImageInterlaceScheme(intern->magick_wand);
7280 RETVAL_LONG(interlace);
7281 }
7282 /* }}} */
7283
7284 /* {{{ proto int Imagick::getImageIterations()
7285 Gets the image iterations.
7286 */
7287 PHP_METHOD(Imagick, getImageIterations)
7288 {
7289 php_imagick_object *intern;
7290 long iterations;
7291
7292 if (zend_parse_parameters_none() == FAILURE) {
7293 return;
7294 }
7295
7296 intern = Z_IMAGICK_P(getThis());
7297 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7298 return;
7299
7300 iterations = MagickGetImageIterations(intern->magick_wand);
7301 RETVAL_LONG(iterations);
7302 }
7303 /* }}} */
7304
7305 #if MagickLibVersion < 0x700
7306 /* {{{ proto ImagickPixel Imagick::getImageMatteColor()
7307 Returns the image matte color.
7308 */
7309 PHP_METHOD(Imagick, getImageMatteColor)
7310 {
7311 php_imagick_object *intern;
7312 php_imagickpixel_object *internp;
7313 MagickBooleanType status;
7314 PixelWand *tmp_wand;
7315
7316 if (zend_parse_parameters_none() == FAILURE) {
7317 return;
7318 }
7319
7320 intern = Z_IMAGICK_P(getThis());
7321 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7322 return;
7323
7324 tmp_wand = NewPixelWand();
7325 status = MagickGetImageMatteColor(intern->magick_wand, tmp_wand);
7326
7327 if (tmp_wand == (PixelWand *)NULL) {
7328 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get image matte color" TSRMLS_CC);
7329 return;
7330 }
7331
7332 if (status == MagickFalse) {
7333 tmp_wand = DestroyPixelWand(tmp_wand);
7334 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable get image matter color" TSRMLS_CC);
7335 return;
7336 }
7337
7338 object_init_ex(return_value, php_imagickpixel_sc_entry);
7339 internp = Z_IMAGICKPIXEL_P(return_value);
7340 php_imagick_replace_pixelwand(internp, tmp_wand);
7341
7342 return;
7343 }
7344 /* }}} */
7345 #endif //#if MagickLibVersion < 0x700
7346
7347 /* {{{ proto array Imagick::getImagePage()
7348 Returns the page geometry associated with the image in an array with the keys "width", "height", "x", and "y".
7349 */
7350 PHP_METHOD(Imagick, getImagePage)
7351 {
7352 php_imagick_object *intern;
7353 MagickBooleanType status;
7354 size_t width, height;
7355 ssize_t x, y;
7356
7357 if (zend_parse_parameters_none() == FAILURE) {
7358 return;
7359 }
7360
7361 intern = Z_IMAGICK_P(getThis());
7362 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7363 return;
7364
7365 status = MagickGetImagePage(intern->magick_wand, &width, &height, &x, &y);
7366
7367 if (status == MagickFalse) {
7368 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get image page" TSRMLS_CC);
7369 return;
7370 }
7371
7372 array_init(return_value);
7373
7374 add_assoc_long(return_value, "width", width);
7375 add_assoc_long(return_value, "height", height);
7376 add_assoc_long(return_value, "x", x);
7377 add_assoc_long(return_value, "y", y);
7378
7379 return;
7380 }
7381 /* }}} */
7382
7383 /* {{{ proto ImagickPixel Imagick::getImagePixelColor(int x, int y)
7384 Returns the color of the specified pixel.
7385 */
7386 PHP_METHOD(Imagick, getImagePixelColor)
7387 {
7388 php_imagick_object *intern;
7389 php_imagickpixel_object *internp;
7390 MagickBooleanType status;
7391 PixelWand *tmp_wand;
7392 im_long x, y;
7393
7394 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &x, &y) == FAILURE) {
7395 return;
7396 }
7397
7398 intern = Z_IMAGICK_P(getThis());
7399 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7400 return;
7401
7402 tmp_wand = NewPixelWand();
7403
7404 if (!tmp_wand) {
7405 php_imagick_convert_imagick_exception(intern->magick_wand, "Failed to allocate new PixelWand" TSRMLS_CC);
7406 return;
7407 }
7408
7409 status = MagickGetImagePixelColor(intern->magick_wand, x, y , tmp_wand);
7410
7411 if (status == MagickFalse) {
7412 tmp_wand = DestroyPixelWand(tmp_wand);
7413 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable get image pixel color" TSRMLS_CC);
7414 return;
7415 }
7416
7417 object_init_ex(return_value, php_imagickpixel_sc_entry);
7418 internp = Z_IMAGICKPIXEL_P(return_value);
7419 php_imagick_replace_pixelwand(internp, tmp_wand);
7420
7421 return;
7422 }
7423 /* }}} */
7424
7425
7426 #if IM_HAVE_IMAGICK_SETIMAGEPIXELCOLOR
7427 /* {{{ proto void setImagePixelColor(int $x, int $y, ImagickPixel|string $color)
7428 Returns the color of the specified pixel.
7429 */
7430 PHP_METHOD(Imagick, setImagePixelColor)
7431 {
7432 php_imagick_object *intern;
7433 zval *param;
7434 MagickBooleanType status;
7435 im_long x, y;
7436 PixelWand *color_wand;
7437 zend_bool allocated;
7438
7439 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llz", &x, &y, ¶m) == FAILURE) {
7440 return;
7441 }
7442
7443 color_wand = php_imagick_zval_to_pixelwand (param, IMAGICK_CLASS, &allocated TSRMLS_CC);
7444 if (!color_wand)
7445 return;
7446
7447 intern = Z_IMAGICK_P(getThis());
7448 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7449 return;
7450
7451 status = MagickSetImagePixelColor(intern->magick_wand, x, y , color_wand);
7452
7453 if (allocated)
7454 color_wand = DestroyPixelWand (color_wand);
7455
7456 if (status == MagickFalse) {
7457 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image pixel color" TSRMLS_CC);
7458 return;
7459 }
7460
7461 return;
7462 }
7463 /* }}} */
7464 #endif
7465
7466 /* {{{ proto string Imagick::getImageProfile(string name)
7467 Returns the named image profile.
7468 */
7469 PHP_METHOD(Imagick, getImageProfile)
7470 {
7471 php_imagick_object *intern;
7472 char *profile, *name;
7473 IM_LEN_TYPE name_len;
7474 #if MagickLibVersion < 0x628
7475 long length;
7476 #else
7477 size_t length;
7478 #endif
7479
7480 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
7481 return;
7482 }
7483
7484 intern = Z_IMAGICK_P(getThis());
7485 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7486 return;
7487
7488 profile = (char *)MagickGetImageProfile(intern->magick_wand, name, &length);
7489
7490 if (profile) {
7491 IM_ZVAL_STRINGL(return_value, profile, length);
7492 IMAGICK_FREE_MAGICK_MEMORY(profile);
7493 return;
7494 }
7495
7496 php_imagick_throw_exception(IMAGICK_CLASS, "Can not get image profile" TSRMLS_CC);
7497 return;
7498 }
7499 /* }}} */
7500
7501 /* {{{ proto array Imagick::getImageRedPrimary()
7502 Returns the chromaticy red primary point as an array. IM6: with the keys "x" and "y".
7503 IM7: Returns an array with the keys "x", "y" and "z".
7504 */
7505 PHP_METHOD(Imagick, getImageRedPrimary)
7506 {
7507 php_imagick_object *intern;
7508 MagickBooleanType status;
7509 double x, y;
7510 #if MagickLibVersion >= 0x700
7511 double z;
7512 #endif
7513
7514 if (zend_parse_parameters_none() == FAILURE) {
7515 return;
7516 }
7517
7518 intern = Z_IMAGICK_P(getThis());
7519 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7520 return;
7521
7522 #if MagickLibVersion >= 0x700
7523 status = MagickGetImageRedPrimary(intern->magick_wand, &x, &y, &z);
7524 #else
7525 status = MagickGetImageRedPrimary(intern->magick_wand, &x, &y);
7526 #endif
7527
7528 if (status == MagickFalse) {
7529 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get image red primary" TSRMLS_CC);
7530 return;
7531 }
7532
7533 array_init(return_value);
7534 add_assoc_double(return_value, "x", x);
7535 add_assoc_double(return_value, "y", y);
7536 #if MagickLibVersion >= 0x700
7537 add_assoc_double(return_value, "z", z);
7538 #endif
7539
7540 return;
7541 }
7542 /* }}} */
7543
7544 /* {{{ proto int Imagick::getImageRenderingIntent()
7545 Gets the image rendering intent.
7546 */
7547 PHP_METHOD(Imagick, getImageRenderingIntent)
7548 {
7549 php_imagick_object *intern;
7550 long renderingIntent;
7551
7552 if (zend_parse_parameters_none() == FAILURE) {
7553 return;
7554 }
7555
7556 intern = Z_IMAGICK_P(getThis());
7557 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7558 return;
7559
7560 renderingIntent = MagickGetImageRenderingIntent(intern->magick_wand);
7561 RETVAL_LONG(renderingIntent);
7562 }
7563 /* }}} */
7564
7565 /* {{{ proto array Imagick::getImageResolution()
7566 Gets the image X and Y resolution.
7567 */
7568 PHP_METHOD(Imagick, getImageResolution)
7569 {
7570 php_imagick_object *intern;
7571 MagickBooleanType status;
7572 double x, y;
7573
7574 if (zend_parse_parameters_none() == FAILURE) {
7575 return;
7576 }
7577
7578 intern = Z_IMAGICK_P(getThis());
7579 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7580 return;
7581
7582 status = MagickGetImageResolution(intern->magick_wand, &x, &y);
7583
7584 if (status == MagickFalse) {
7585 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get image resolution" TSRMLS_CC);
7586 return;
7587 }
7588
7589 array_init(return_value);
7590 add_assoc_double(return_value, "x", x);
7591 add_assoc_double(return_value, "y", y);
7592
7593 return;
7594 }
7595 /* }}} */
7596
7597 /* {{{ proto int Imagick::getImageScene()
7598 Gets the image scene.
7599 */
7600 PHP_METHOD(Imagick, getImageScene)
7601 {
7602 php_imagick_object *intern;
7603 unsigned long scene;
7604
7605 if (zend_parse_parameters_none() == FAILURE) {
7606 return;
7607 }
7608
7609 intern = Z_IMAGICK_P(getThis());
7610 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7611 return;
7612
7613 scene = MagickGetImageScene(intern->magick_wand);
7614 RETVAL_LONG(scene);
7615 }
7616 /* }}} */
7617
7618 /* {{{ proto string Imagick::getImageSignature()
7619 Generates an SHA-256 message digest for the image pixel stream.
7620 */
7621 PHP_METHOD(Imagick, getImageSignature)
7622 {
7623 php_imagick_object *intern;
7624 char *signature;
7625
7626 if (zend_parse_parameters_none() == FAILURE) {
7627 return;
7628 }
7629
7630 intern = Z_IMAGICK_P(getThis());
7631 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7632 return;
7633
7634 signature = MagickGetImageSignature(intern->magick_wand);
7635 IM_ZVAL_STRING(return_value, signature);
7636 IMAGICK_FREE_MAGICK_MEMORY(signature);
7637 return;
7638 }
7639 /* }}} */
7640
7641 /* {{{ proto int Imagick::getImageTicksPerSecond()
7642 Gets the image ticks-per-second.
7643 */
7644 PHP_METHOD(Imagick, getImageTicksPerSecond)
7645 {
7646 php_imagick_object *intern;
7647 unsigned long ticks;
7648
7649 if (zend_parse_parameters_none() == FAILURE) {
7650 return;
7651 }
7652
7653 intern = Z_IMAGICK_P(getThis());
7654 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7655 return;
7656
7657 ticks = MagickGetImageTicksPerSecond(intern->magick_wand);
7658 RETVAL_LONG(ticks);
7659 }
7660 /* }}} */
7661
7662 /* {{{ proto int Imagick::getImageType()
7663 Gets the potential image type:
7664 */
7665 PHP_METHOD(Imagick, getImageType)
7666 {
7667 php_imagick_object *intern;
7668 long imageType;
7669
7670 if (zend_parse_parameters_none() == FAILURE) {
7671 return;
7672 }
7673
7674 intern = Z_IMAGICK_P(getThis());
7675 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7676 return;
7677
7678 imageType = MagickGetImageType(intern->magick_wand);
7679 RETVAL_LONG(imageType);
7680 }
7681 /* }}} */
7682
7683 /* {{{ proto int Imagick::getImageUnits()
7684 Gets the image units of resolution.
7685 */
7686 PHP_METHOD(Imagick, getImageUnits)
7687 {
7688 php_imagick_object *intern;
7689 long resolutionType;
7690
7691 if (zend_parse_parameters_none() == FAILURE) {
7692 return;
7693 }
7694
7695 intern = Z_IMAGICK_P(getThis());
7696 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7697 return;
7698
7699 resolutionType = MagickGetImageUnits(intern->magick_wand);
7700 RETVAL_LONG(resolutionType);
7701 }
7702 /* }}} */
7703
7704 /* {{{ proto int Imagick::getImageVirtualPixelMethod()
7705 Returns the virtual pixel method for the sepcified image.
7706 */
7707 PHP_METHOD(Imagick, getImageVirtualPixelMethod)
7708 {
7709 php_imagick_object *intern;
7710 long pixelMethod;
7711
7712 if (zend_parse_parameters_none() == FAILURE) {
7713 return;
7714 }
7715
7716 intern = Z_IMAGICK_P(getThis());
7717 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7718 return;
7719
7720 pixelMethod = MagickGetImageVirtualPixelMethod(intern->magick_wand);
7721 RETVAL_LONG(pixelMethod);
7722 }
7723 /* }}} */
7724
7725 /* {{{ proto array Imagick::getImageWhitePoint()
7726 Returns the chromaticy white point as an associative array. IM6: with the keys "x" and "y".
7727 IM7: with the keys "x", "y" and "z".
7728 */
7729 PHP_METHOD(Imagick, getImageWhitePoint)
7730 {
7731 php_imagick_object *intern;
7732 MagickBooleanType status;
7733 double x, y;
7734 #if MagickLibVersion >= 0x700
7735 double z;
7736 #endif
7737
7738 if (zend_parse_parameters_none() == FAILURE) {
7739 return;
7740 }
7741
7742 intern = Z_IMAGICK_P(getThis());
7743 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7744 return;
7745
7746 #if MagickLibVersion >= 0x700
7747 status = MagickGetImageWhitePoint(intern->magick_wand, &x, &y, &z);
7748 #else
7749 status = MagickGetImageWhitePoint(intern->magick_wand, &x, &y);
7750 #endif
7751
7752 if (status == MagickFalse) {
7753 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get image white point" TSRMLS_CC);
7754 return;
7755 }
7756
7757 array_init(return_value);
7758 add_assoc_double(return_value, "x", x);
7759 add_assoc_double(return_value, "y", y);
7760 #if MagickLibVersion >= 0x700
7761 add_assoc_double(return_value, "z", z);
7762 #endif
7763
7764 return;
7765 }
7766 /* }}} */
7767
7768 /* {{{ proto int Imagick::getImageWidth()
7769 Returns the image width.
7770 */
7771 PHP_METHOD(Imagick, getImageWidth)
7772 {
7773 php_imagick_object *intern;
7774 unsigned long width;
7775
7776 if (zend_parse_parameters_none() == FAILURE) {
7777 return;
7778 }
7779
7780 intern = Z_IMAGICK_P(getThis());
7781 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7782 return;
7783
7784 width = MagickGetImageWidth(intern->magick_wand);
7785 RETVAL_LONG(width);
7786 }
7787 /* }}} */
7788
7789 /* {{{ proto int Imagick::getNumberImages()
7790 Returns the number of images associated with Imagick object.
7791 */
7792 PHP_METHOD(Imagick, getNumberImages)
7793 {
7794 php_imagick_object *intern;
7795 unsigned long num_images;
7796
7797 if (zend_parse_parameters_none() == FAILURE) {
7798 return;
7799 }
7800
7801 intern = Z_IMAGICK_P(getThis());
7802
7803 num_images = MagickGetNumberImages(intern->magick_wand);
7804 RETVAL_LONG(num_images);
7805 }
7806 /* }}} */
7807
7808 /*
7809 Resizes an image so that it is 'bestfit' for the bounding box
7810 If the image does not fill the box completely the box is filled with
7811 image's background color. The background color can be set using MagickSetImageBackgroundColor
7812 */
7813 #if MagickLibVersion > 0x631
7814 static
7815 zend_bool s_resize_bounding_box(MagickWand *magick_wand, im_long box_width, im_long box_height, zend_bool fill, zend_bool legacy)
7816 {
7817 im_long new_width, new_height;
7818 im_long extent_x, extent_y;
7819
7820 /* Calculate dimensions */
7821 if (!php_imagick_thumbnail_dimensions(magick_wand, 1, box_width, box_height, &new_width, &new_height, legacy)) {
7822 return 0;
7823 }
7824
7825 /* Resize the image to the new size */
7826 if (MagickThumbnailImage(magick_wand, new_width, new_height) == MagickFalse) {
7827 return 0;
7828 }
7829
7830 /* If user does not want to fill we are all done here */
7831 if (!fill) {
7832 return 1;
7833 }
7834
7835 /* In case user wants to fill use extent for it rather than creating a new canvas */
7836 extent_x = (box_width > new_width) ? ((box_width - new_width) / 2) : 0;
7837 extent_y = (box_height > new_height) ? ((box_height - new_height) / 2) : 0;
7838
7839 if (MagickExtentImage(magick_wand, box_width, box_height, extent_x * -1, extent_y * -1) == MagickFalse) {
7840 return 0;
7841 }
7842 return 1;
7843 }
7844 #endif
7845
7846 /* {{{ proto bool Imagick::thumbnailImage(int columns, int rows[, bool bestfit = false[, bool fill = false[, bool legacy = false]]])
7847 Changes the size of an image to the given dimensions and removes any associated profiles.
7848 If legacy is true, the calculations are done with the small rounding bug that existed in
7849 Imagick before 3.4.0. If false, the calculations should produce the same results as
7850 ImageMagick CLI does.
7851 */
7852 PHP_METHOD(Imagick, thumbnailImage)
7853 {
7854 im_long width = 0, height = 0, new_width, new_height;
7855 php_imagick_object *intern;
7856 zend_bool bestfit = 0, fill = 0;
7857 zend_bool legacy = 0;
7858
7859 #if PHP_VERSION_ID < 80100
7860 // This uses an implicit conversion of null to 0 for longs
7861 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll|bbb", &width, &height, &bestfit, &fill, &legacy) == FAILURE) {
7862 return;
7863 }
7864 #else
7865 // Changing longs to be nullable "l!", means that zpp
7866 // wants to write whether they were null to a variable.
7867 bool width_is_null = 0;
7868 bool height_is_null = 0;
7869
7870 /* Parse parameters given to function */
7871 if (zend_parse_parameters(
7872 ZEND_NUM_ARGS() TSRMLS_CC,
7873 "l!l!|bbb",
7874 &width, &width_is_null,
7875 &height, &height_is_null,
7876 &bestfit, &fill, &legacy) == FAILURE) {
7877 return;
7878 }
7879 #endif
7880
7881 intern = Z_IMAGICK_P(getThis());
7882 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
7883 return;
7884
7885 if (bestfit && fill) {
7886 #if MagickLibVersion > 0x631
7887 if (!s_resize_bounding_box(intern->magick_wand, width, height, fill, legacy)) {
7888 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to resize and fill image" TSRMLS_CC);
7889 return;
7890 }
7891 #else
7892 php_imagick_throw_exception(IMAGICK_CLASS, "Fill parameter is only supported with ImageMagick 6.3.2+" TSRMLS_CC);
7893 return;
7894 #endif
7895 } else {
7896 if (!php_imagick_thumbnail_dimensions(intern->magick_wand, bestfit, width, height, &new_width, &new_height, legacy)) {
7897 php_imagick_throw_exception(IMAGICK_CLASS, "Invalid image geometry" TSRMLS_CC);
7898 return;
7899 }
7900 /* No magick is going to happen */
7901 if (MagickThumbnailImage(intern->magick_wand, new_width, new_height) == MagickFalse) {
7902 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to thumbnail image" TSRMLS_CC);
7903 return;
7904 }
7905 }
7906 RETURN_TRUE;
7907 }
7908 /* }}} */
7909
7910 /* This is not universally safe to use, but is safe enough for values that will
7911 be encountered for image dimensions.
7912 */
7913 static inline double im_round_helper_class(double value) {
7914 if (value >= 0.0) {
7915 return floor(value + 0.5);
7916 } else {
7917 return ceil(value - 0.5);
7918 }
7919 }
7920
7921 static
7922 void s_calculate_crop(
7923 im_long orig_width, im_long orig_height,
7924 im_long desired_width, im_long desired_height,
7925 im_long *new_width, im_long *new_height,
7926 im_long *offset_x, im_long *offset_y,
7927 zend_bool legacy
7928 ) {
7929 double ratio_x, ratio_y;
7930 long temp_new_width, temp_new_height;
7931
7932 ratio_x = ((double) desired_width / (double) orig_width);
7933 ratio_y = ((double) desired_height / (double) orig_height);
7934
7935 if (ratio_x > ratio_y) {
7936 temp_new_width = desired_width;
7937
7938 if (legacy) {
7939 temp_new_height = (long)(ratio_x * (double)orig_height);
7940 }
7941 else {
7942 temp_new_height = im_round_helper_class(ratio_x * (double)orig_height);
7943 }
7944 } else {
7945 temp_new_height = desired_height;
7946 if (legacy) {
7947 temp_new_width = (long)(ratio_y * (double)orig_width);
7948 }
7949 else {
7950 temp_new_width = im_round_helper_class(ratio_y * (double)orig_width);
7951 }
7952 }
7953
7954 *new_width = temp_new_width;
7955 *new_height = temp_new_height;
7956
7957 *offset_x = (long) ((temp_new_width - desired_width) / 2);
7958 *offset_y = (long) ((temp_new_height - desired_height) / 2);
7959 }
7960
7961
7962 /* {{{ proto array Imagick::calculateCrop(long orig_width, long orig_height, long desired_width, long desired_height[, bool legacy = false])
7963 Calculates the cropping values that will be used by a crop operation.
7964 */
7965 PHP_METHOD(Imagick, calculateCrop)
7966 {
7967 im_long orig_width, orig_height;
7968 im_long desired_width, desired_height;
7969 im_long new_width, new_height;
7970 im_long offset_x, offset_y;
7971 zend_bool legacy = 0;
7972
7973 /* Parse parameters given to function */
7974 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llll|b",
7975 &orig_width, &orig_height, &desired_width, &desired_height, &legacy) == FAILURE) {
7976 return;
7977 }
7978
7979 if (orig_width <= 0 || orig_height <= 0 ||
7980 desired_width <= 0 || desired_height <= 0) {
7981 php_imagick_throw_exception(IMAGICK_CLASS, "All values must be above zero." TSRMLS_CC);
7982 }
7983
7984 s_calculate_crop(
7985 orig_width, orig_height,
7986 desired_width, desired_height,
7987 &new_width, &new_height,
7988 &offset_x, &offset_y,
7989 legacy
7990 );
7991
7992 array_init(return_value);
7993 add_assoc_long(return_value, "width", new_width);
7994 add_assoc_long(return_value, "height", new_height);
7995
7996 add_assoc_long(return_value, "offset_x", offset_x);
7997 add_assoc_long(return_value, "offset_y", offset_y);
7998
7999 return;
8000 }
8001 /* }}} */
8002
8003
8004 static
8005 zend_bool s_crop_thumbnail_image(MagickWand *magick_wand, im_long desired_width, im_long desired_height, zend_bool legacy TSRMLS_DC)
8006 {
8007 im_long offset_x = 0, offset_y = 0, new_width, new_height;
8008 im_long orig_width = (im_long)MagickGetImageWidth(magick_wand);
8009 im_long orig_height = (im_long)MagickGetImageHeight(magick_wand);
8010
8011 /* Already at the size, just strip profiles */
8012 if ((orig_width == desired_width) && (orig_height == desired_height)) {
8013 if (!MagickStripImage(magick_wand)) {
8014 return 0;
8015 }
8016 return 1;
8017 }
8018
8019 s_calculate_crop(
8020 orig_width, orig_height,
8021 desired_width, desired_height,
8022 &new_width, &new_height,
8023 &offset_x, &offset_y,
8024 legacy
8025 );
8026
8027 if (MagickThumbnailImage(magick_wand, new_width, new_height) == MagickFalse) {
8028 return 0;
8029 }
8030
8031 /* all done here */
8032 if ((new_width == desired_width) && (new_height == desired_height)) {
8033 return 1;
8034 }
8035
8036 if (MagickCropImage(magick_wand, desired_width, desired_height, offset_x, offset_y) == MagickFalse) {
8037 return 0;
8038 }
8039
8040 MagickSetImagePage(magick_wand, desired_width, desired_height, 0, 0);
8041 return 1;
8042 }
8043
8044 //
8045 /* {{{ proto bool Imagick::cropthumbnailImage(int columns, int rows[, bool legacy = false] )
8046 Creates a cropped thumbnail at the requested size. If legacy is true, uses the
8047 incorrect behaviour that was present until Imagick 3.4.0. If false it uses the correct
8048 behaviour.
8049 */
8050 PHP_METHOD(Imagick, cropThumbnailImage)
8051 {
8052 im_long crop_width, crop_height;
8053 zend_bool legacy = 0;
8054 php_imagick_object *intern;
8055
8056 /* Parse parameters given to function */
8057 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll|b", &crop_width, &crop_height, &legacy) == FAILURE) {
8058 return;
8059 }
8060
8061 intern = Z_IMAGICK_P(getThis());
8062 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
8063 return;
8064
8065 /* The world collapses.. */
8066 if (!s_crop_thumbnail_image(intern->magick_wand, crop_width, crop_height, legacy TSRMLS_CC)) {
8067 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to crop-thumbnail image" TSRMLS_CC);
8068 return;
8069 }
8070
8071 RETURN_TRUE;
8072 }
8073 /* }}} */
8074
8075 /* {{{ proto bool Imagick::resetIterator();
8076 Resets the iterator. Use it in conjunction with Imagick::nextImage() to iterate over all the images in a wand container.
8077 */
8078 PHP_METHOD(Imagick, resetIterator)
8079 {
8080 php_imagick_object *intern;
8081 intern = Z_IMAGICK_P(getThis());
8082
8083 if (zend_parse_parameters_none() == FAILURE) {
8084 return;
8085 }
8086
8087 /* No magick is going to happen */
8088 if (intern->magick_wand == NULL) {
8089 RETURN_FALSE;
8090 }
8091 intern->next_out_of_bound = 0;
8092 MagickResetIterator(intern->magick_wand);
8093 RETURN_TRUE;
8094 }
8095 /* }}} */
8096
8097 /* {{{ proto bool Imagick::setFirstIterator()
8098 Sets the wand iterator to the first image.
8099 */
8100 PHP_METHOD(Imagick, setFirstIterator)
8101 {
8102 php_imagick_object *intern;
8103 intern = Z_IMAGICK_P(getThis());
8104
8105 if (zend_parse_parameters_none() == FAILURE) {
8106 return;
8107 }
8108
8109 /* No magick is going to happen */
8110 if (intern->magick_wand == NULL) {
8111 RETURN_FALSE;
8112 }
8113 intern->next_out_of_bound = 0;
8114 MagickSetFirstIterator(intern->magick_wand);
8115 RETURN_TRUE;
8116 }
8117 /* }}} */
8118
8119 /* {{{ proto bool Imagick::setLastIterator()
8120 Sets the wand iterator to the last image.
8121 */
8122 PHP_METHOD(Imagick, setLastIterator)
8123 {
8124 php_imagick_object *intern;
8125 intern = Z_IMAGICK_P(getThis());
8126
8127 if (zend_parse_parameters_none() == FAILURE) {
8128 return;
8129 }
8130
8131 /* No magick is going to happen */
8132 if (intern->magick_wand == NULL) {
8133 RETURN_FALSE;
8134 }
8135 intern->next_out_of_bound = 0;
8136 MagickSetLastIterator(intern->magick_wand);
8137 RETURN_TRUE;
8138 }
8139 /* }}} */
8140
8141 /* {{{ proto bool Imagick::previousImage()
8142 Assocates the previous image in an image list with the Imagick object.
8143 */
8144 PHP_METHOD(Imagick, previousImage)
8145 {
8146 php_imagick_object *intern;
8147 MagickBooleanType status;
8148
8149 if (zend_parse_parameters_none() == FAILURE) {
8150 return;
8151 }
8152
8153 intern = Z_IMAGICK_P(getThis());
8154 status = MagickPreviousImage(intern->magick_wand);
8155
8156 /* No magick is going to happen */
8157 if (status == MagickFalse) {
8158 RETURN_FALSE;
8159 }
8160 intern->next_out_of_bound = 0;
8161 RETURN_TRUE;
8162 }
8163 /* }}} */
8164
8165 /* {{{ proto bool Imagick::nextImage()
8166 Associates the next image in the image list with an Imagick object.
8167 */
8168 PHP_METHOD(Imagick, nextImage)
8169 {
8170 php_imagick_object *intern;
8171 MagickBooleanType status;
8172
8173 if (zend_parse_parameters_none() == FAILURE) {
8174 return;
8175 }
8176
8177 intern = Z_IMAGICK_P(getThis());
8178 status = MagickNextImage(intern->magick_wand);
8179
8180 /* No magick is going to happen */
8181 if (status == MagickFalse) {
8182 intern->next_out_of_bound = 1;
8183 RETURN_FALSE;
8184 }
8185
8186 RETURN_TRUE;
8187 }
8188 /* }}} */
8189
8190 /* {{{ proto bool Imagick::hasPreviousImage()
8191 Returns true if the wand has more images when traversing the list in the reverse direction
8192 */
8193 PHP_METHOD(Imagick, hasPreviousImage)
8194 {
8195 php_imagick_object *intern;
8196 MagickBooleanType status;
8197
8198 if (zend_parse_parameters_none() == FAILURE) {
8199 return;
8200 }
8201
8202 intern = Z_IMAGICK_P(getThis());
8203 status = MagickHasPreviousImage(intern->magick_wand);
8204
8205 /* No magick is going to happen */
8206 if (status == MagickFalse) {
8207 RETURN_FALSE;
8208 }
8209
8210 RETURN_TRUE;
8211 }
8212 /* }}} */
8213
8214 /* {{{ proto bool Imagick::hasNextImage()
8215 Returns true if the wand has more images when traversing the list in the forward direction
8216 */
8217 PHP_METHOD(Imagick, hasNextImage)
8218 {
8219 php_imagick_object *intern;
8220 MagickBooleanType status;
8221
8222 if (zend_parse_parameters_none() == FAILURE) {
8223 return;
8224 }
8225
8226 intern = Z_IMAGICK_P(getThis());
8227 status = MagickHasNextImage(intern->magick_wand);
8228
8229 /* No magick is going to happen */
8230 if (status == MagickFalse) {
8231 RETURN_FALSE;
8232 }
8233
8234 RETURN_TRUE;
8235 }
8236 /* }}} */
8237
8238 #if !defined(MAGICKCORE_EXCLUDE_DEPRECATED)
8239 #if MagickLibVersion < 0x700
8240 /* {{{ proto int Imagick::getImageIndex()
8241 Returns the index of the current active image, within the Imagick object.
8242 */
8243 PHP_METHOD(Imagick, getImageIndex)
8244 {
8245 MagickBooleanType status;
8246 php_imagick_object *intern;
8247
8248 #if MagickLibVersion > 0x628
8249 IMAGICK_METHOD_DEPRECATED("Imagick", "getImageindex");
8250 #endif
8251
8252 if (zend_parse_parameters_none() == FAILURE) {
8253 return;
8254 }
8255
8256 intern = Z_IMAGICK_P(getThis());
8257
8258 status = MagickGetImageIndex(intern->magick_wand);
8259 ZVAL_LONG(return_value, (long)status);
8260 return;
8261 }
8262 /* }}} */
8263 #endif // #if MagickLibVersion < 0x700
8264
8265
8266 #if MagickLibVersion < 0x700
8267
8268 /* {{{ proto bool Imagick::setImageIndex(int index)
8269 Returns the index of the current active image, within the Imagick object.
8270 */
8271 PHP_METHOD(Imagick, setImageIndex)
8272 {
8273 im_long index;
8274 MagickBooleanType status;
8275 php_imagick_object *intern;
8276
8277 #if MagickLibVersion > 0x628
8278 IMAGICK_METHOD_DEPRECATED("Imagick", "setImageIndex");
8279 #endif
8280
8281 /* Parse parameters given to function */
8282 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) {
8283 return;
8284 }
8285
8286 intern = Z_IMAGICK_P(getThis());
8287 #if MagickLibVersion > 0x628
8288 /* Get the current iterator position */
8289 status = MagickSetIteratorIndex(intern->magick_wand, index);
8290 #else
8291 status = MagickSetImageIndex(intern->magick_wand, index);
8292 #endif
8293
8294 /* No magick is going to happen */
8295 if (status == MagickFalse) {
8296 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image index" TSRMLS_CC);
8297 return;
8298 }
8299 intern->next_out_of_bound = 0;
8300 RETURN_TRUE;
8301
8302 }
8303 /* }}} */
8304 #endif // #if MagickLibVersion < 0x700
8305 #endif
8306
8307 /* {{{ proto bool Imagick::removeImage()
8308 Removes an image from the image list.
8309 */
8310 PHP_METHOD(Imagick, removeImage)
8311 {
8312 MagickBooleanType status;
8313 php_imagick_object *intern;
8314
8315 if (zend_parse_parameters_none() == FAILURE) {
8316 return;
8317 }
8318
8319 intern = Z_IMAGICK_P(getThis());
8320 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
8321 return;
8322
8323 status = MagickRemoveImage(intern->magick_wand);
8324
8325 /* No magick is going to happen */
8326 if (status == MagickFalse) {
8327 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to remove image" TSRMLS_CC);
8328 return;
8329 }
8330 intern->next_out_of_bound = 0;
8331 MagickSetLastIterator(intern->magick_wand);
8332 RETURN_TRUE;
8333 }
8334 /* }}} */
8335
8336 /* {{{ proto string Imagick::getImageFilename()
8337 Returns the filename of a particular image in a sequence
8338 */
8339 PHP_METHOD(Imagick, getImageFilename)
8340 {
8341 php_imagick_object *intern;
8342 char *filename;
8343
8344 if (zend_parse_parameters_none() == FAILURE) {
8345 return;
8346 }
8347
8348 intern = Z_IMAGICK_P(getThis());
8349 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
8350 return;
8351
8352 filename = MagickGetImageFilename(intern->magick_wand);
8353
8354 if (filename == (char *)NULL) {
8355 return;
8356 }
8357
8358 IM_ZVAL_STRING(return_value, filename);
8359 IMAGICK_FREE_MAGICK_MEMORY(filename);
8360 return;
8361 }
8362 /* }}} */
8363
8364 #if !defined(MAGICKCORE_EXCLUDE_DEPRECATED)
8365 #if MagickLibVersion < 0x700
8366 /* {{{ proto int Imagick::getImageSize()
8367 returns the image length in bytes
8368 */
8369 PHP_METHOD(Imagick, getImageSize)
8370 {
8371 php_imagick_object *intern;
8372
8373 IMAGICK_METHOD_DEPRECATED_USE_INSTEAD("Imagick", "getImageSize", "Imagick", "getImageLength");
8374
8375 intern = Z_IMAGICK_P(getThis());
8376 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
8377 return;
8378
8379 ZVAL_LONG(return_value, (long)MagickGetImageSize(intern->magick_wand));
8380 return;
8381 }
8382 /* }}} */
8383 #endif
8384 #endif
8385
8386 static
8387 zend_bool s_image_has_format (MagickWand *magick_wand)
8388 {
8389 char *buffer;
8390 zend_bool ret;
8391 buffer = MagickGetImageFormat(magick_wand);
8392 ret = buffer && *buffer != '\0';
8393 if (buffer) {
8394 MagickRelinquishMemory (buffer);
8395 }
8396 return ret;
8397 }
8398
8399 /* {{{ proto string Imagick::getImageBlob()
8400 Returns the current image sequence as a string
8401 */
8402 PHP_METHOD(Imagick, getImageBlob)
8403 {
8404 php_imagick_object *intern;
8405 unsigned char *image_contents;
8406 size_t image_size;
8407
8408 if (zend_parse_parameters_none() == FAILURE) {
8409 return;
8410 }
8411
8412 intern = Z_IMAGICK_P(getThis());
8413 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
8414 return;
8415
8416 if (!s_image_has_format (intern->magick_wand)) {
8417 php_imagick_throw_exception(IMAGICK_CLASS, "Image has no format" TSRMLS_CC);
8418 return;
8419 }
8420
8421 image_contents = MagickGetImageBlob(intern->magick_wand, &image_size);
8422 if (!image_contents) {
8423 return;
8424 }
8425
8426 IM_ZVAL_STRINGL(return_value, (char *)image_contents, image_size);
8427 IMAGICK_FREE_MAGICK_MEMORY(image_contents);
8428 return;
8429 }
8430 /* }}} */
8431
8432 /* {{{ proto string Imagick::getImagesBlob()
8433 Returns all image sequences as a string
8434 */
8435 PHP_METHOD(Imagick, getImagesBlob)
8436 {
8437 php_imagick_object *intern;
8438 unsigned char *image_contents;
8439 size_t image_size;
8440 int current;
8441 MagickBooleanType status;
8442
8443 if (zend_parse_parameters_none() == FAILURE) {
8444 return;
8445 }
8446
8447 intern = Z_IMAGICK_P(getThis());
8448 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
8449 return;
8450
8451 #if MagickLibVersion > 0x628
8452 /* Get the current iterator position */
8453 current = MagickGetIteratorIndex(intern->magick_wand);
8454 #else
8455 /* Get the current iterator position */
8456 current = MagickGetImageIndex(intern->magick_wand);
8457 #endif
8458
8459 /* Reset the iterator */
8460 MagickResetIterator(intern->magick_wand);
8461
8462 /* Loop all images to make sure they have a format */
8463 while (MagickNextImage(intern->magick_wand)) {
8464 if (!s_image_has_format (intern->magick_wand)) {
8465 php_imagick_throw_exception(IMAGICK_CLASS, "Image has no format" TSRMLS_CC);
8466 return;
8467 }
8468 }
8469
8470 #if MagickLibVersion > 0x628
8471 /* Get the current iterator position */
8472 status = MagickSetIteratorIndex(intern->magick_wand, current);
8473 #else
8474 /* Get the current iterator position */
8475 status = MagickSetImageIndex(intern->magick_wand, current);
8476 #endif
8477
8478 if (status == MagickFalse) {
8479 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set the iterator index" TSRMLS_CC);
8480 return;
8481 }
8482
8483 image_contents = MagickGetImagesBlob(intern->magick_wand, &image_size);
8484 if (!image_contents) {
8485 return;
8486 }
8487
8488 IM_ZVAL_STRINGL(return_value, (char *)image_contents, image_size);
8489 IMAGICK_FREE_MAGICK_MEMORY(image_contents);
8490 return;
8491 }
8492 /* }}} */
8493
8494 /* {{{ proto string Imagick::getImageFormat()
8495 Returns the format of a particular image in a sequence.
8496 */
8497 PHP_METHOD(Imagick, getImageFormat)
8498 {
8499 php_imagick_object *intern;
8500 char *format;
8501
8502 if (zend_parse_parameters_none() == FAILURE) {
8503 return;
8504 }
8505 intern = Z_IMAGICK_P(getThis());
8506
8507 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
8508 return;
8509 if (!s_image_has_format (intern->magick_wand)) {
8510 php_imagick_throw_exception(IMAGICK_CLASS, "Image has no format" TSRMLS_CC);
8511 return;
8512 }
8513
8514 format = MagickGetImageFormat (intern->magick_wand);
8515 IM_ZVAL_STRING(return_value, format);
8516 IMAGICK_FREE_MAGICK_MEMORY(format);
8517 return;
8518 }
8519 /* }}} */
8520
8521 /* {{{ proto string Imagick::getImageMimeType()
8522 Returns the image mime-type
8523 */
8524 PHP_METHOD(Imagick, getImageMimeType)
8525 {
8526 php_imagick_object *intern;
8527 char *format = NULL, *mime_type = NULL;
8528
8529 if (zend_parse_parameters_none() == FAILURE) {
8530 return;
8531 }
8532
8533 intern = Z_IMAGICK_P(getThis());
8534
8535 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
8536 return;
8537 if (!s_image_has_format (intern->magick_wand)) {
8538 php_imagick_throw_exception(IMAGICK_CLASS, "Image has no format" TSRMLS_CC);
8539 return;
8540 }
8541
8542 format = MagickGetImageFormat (intern->magick_wand);
8543
8544 mime_type = (char *) MagickToMime(format);
8545 IMAGICK_FREE_MAGICK_MEMORY(format);
8546
8547 if (!mime_type) {
8548 php_imagick_throw_exception(IMAGICK_CLASS, "Unable to get image mime-type" TSRMLS_CC);
8549 return;
8550 }
8551
8552 IM_ZVAL_STRING(return_value, mime_type);
8553 IMAGICK_FREE_MAGICK_MEMORY(mime_type);
8554 return;
8555 }
8556 /* }}} */
8557
8558
8559 static
8560 void s_add_assoc_str (zval *array, const char *key, const char *value)
8561 {
8562 //add_assoc_string (array, key, (char *)(value ? value : ""), copy);
8563 IM_add_assoc_string (array, key, (char *)(value ? value : ""));
8564 //TODO - if copy == 0 free the string?
8565 }
8566
8567 static
8568 void s_add_named_strings (zval *array, const char *haystack TSRMLS_DC)
8569 {
8570 unsigned int i, found;
8571 char *last_ptr = NULL, *buffer;
8572 size_t num_keys;
8573
8574 #if PHP_VERSION_ID >= 70000
8575 zend_string *trim;
8576 zend_string *line_string;
8577 #else
8578 char *trim;
8579 #endif
8580
8581 char *line;
8582
8583 const char *str_keys [] = {
8584 "Format: ",
8585 "Units: ",
8586 "Type: ",
8587 "Colorspace: ",
8588 "Filesize: ",
8589 "Compression: "
8590 };
8591
8592 const char *arr_keys [] = {
8593 "format",
8594 "units",
8595 "type",
8596 "colorSpace",
8597 "fileSize",
8598 "compression"
8599 };
8600
8601 found = 0;
8602
8603
8604 buffer = estrdup (haystack);
8605
8606 num_keys = sizeof (str_keys) / sizeof (str_keys[0]);
8607 line = php_strtok_r (buffer, "\r\n", &last_ptr);
8608
8609 while ((found < num_keys) && line) {
8610 // Break the line further into tokens
8611
8612 #if PHP_VERSION_ID >= 70000
8613 line_string = zend_string_init(line, strlen(line), 0);
8614 //str, what, what_len, mode
8615 trim = php_trim(line_string, NULL, 0, 3);
8616 for (i = 0; i < num_keys; i++) {
8617 if (trim->val) {
8618 if (strncmp (trim->val, str_keys [i], strlen (str_keys [i])) == 0) {
8619 // This should be our line
8620 IM_add_assoc_string (array, arr_keys [i], trim->val + strlen (str_keys [i]));
8621 found++;
8622 }
8623 }
8624 }
8625 // zend_string_release(line_string); - 0 in zend_string_init means no need to free?
8626 zend_string_release(trim);
8627 line = php_strtok_r (NULL, "\r\n", &last_ptr);
8628 #else
8629 trim = php_trim(line, strlen(line), NULL, 0, NULL, 3 TSRMLS_CC);
8630 for (i = 0; i < num_keys; i++) {
8631 if (strncmp (trim, str_keys [i], strlen (str_keys [i])) == 0) {
8632 // This should be our line
8633 IM_add_assoc_string (array, arr_keys [i], trim + strlen (str_keys [i]));
8634 found++;
8635 }
8636 }
8637 efree (trim);
8638 line = php_strtok_r (NULL, "\r\n", &last_ptr);
8639 #endif
8640 }
8641 efree (buffer);
8642 }
8643
8644 /* {{{ proto array Imagick::identifyImage([bool appendRawOutput] )
8645 Identifies an image and returns the attributes. Attributes include the image width, height, size, and others.
8646 If true is passed as argument, then the raw output is appended to the array.
8647 */
8648 PHP_METHOD(Imagick, identifyImage)
8649 {
8650 char *format, *identify, *filename, *signature;
8651 php_imagick_object *intern;
8652 zend_bool append_raw_string = 0;
8653 double x, y;
8654
8655 #if PHP_VERSION_ID >= 70000
8656 zval array;
8657 #else
8658 zval *array;
8659 #endif
8660
8661 zval *pArray;
8662
8663 /* Parse parameters given to function */
8664 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &append_raw_string) == FAILURE) {
8665 return;
8666 }
8667
8668 intern = Z_IMAGICK_P(getThis());
8669 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
8670 return;
8671
8672 // This is to parse some string options, ugly hack but easier than using CommandOptionToMNemonic
8673 // or MagickOptionToMnemonic and FormatMagickSize, which have changed names and signatures between
8674 // versions that we support
8675 identify = MagickIdentifyImage (intern->magick_wand);
8676
8677 // Actually generate the array ourselves
8678 array_init(return_value);
8679
8680 // Name of the image
8681 filename = MagickGetImageFilename (intern->magick_wand);
8682 s_add_assoc_str (return_value, "imageName", filename);
8683 IMAGICK_FREE_MAGICK_MEMORY(filename);
8684
8685 format = MagickGetImageFormat (intern->magick_wand);
8686 if (format) {
8687 char *mime_type = MagickToMime(format);
8688 if (mime_type) {
8689 s_add_assoc_str (return_value, "mimetype", mime_type);
8690 IMAGICK_FREE_MAGICK_MEMORY(mime_type);
8691 } else
8692 s_add_assoc_str (return_value, "mimetype", "unknown");
8693
8694 IMAGICK_FREE_MAGICK_MEMORY(format);
8695 }
8696 else
8697 s_add_assoc_str (return_value, "mimetype", "unknown");
8698
8699 s_add_named_strings (return_value, identify TSRMLS_CC);
8700
8701 // Geometry is an associative array
8702
8703 #if PHP_VERSION_ID >= 70000
8704 array_init(&array);
8705 pArray = &array;
8706 #else
8707 MAKE_STD_ZVAL(array);
8708 pArray = array;
8709 #endif
8710
8711 array_init(pArray);
8712
8713 add_assoc_long (pArray, "width", MagickGetImageWidth (intern->magick_wand));
8714 add_assoc_long (pArray, "height", MagickGetImageHeight (intern->magick_wand));
8715 add_assoc_zval (return_value, "geometry", pArray);
8716
8717 if (MagickGetImageResolution(intern->magick_wand, &x, &y) == MagickTrue) {
8718 #if PHP_VERSION_ID >= 70000
8719 zval geometry_array;
8720 array_init(&geometry_array);
8721 add_assoc_double(&geometry_array, "x", x);
8722 add_assoc_double(&geometry_array, "y", y);
8723 add_assoc_zval(return_value, "resolution", &geometry_array);
8724 #else
8725 zval *p_geometry_array;
8726 MAKE_STD_ZVAL(p_geometry_array);
8727 array_init(p_geometry_array);
8728 add_assoc_double(p_geometry_array, "x", x);
8729 add_assoc_double(p_geometry_array, "y", y);
8730 add_assoc_zval(return_value, "resolution", p_geometry_array);
8731 #endif
8732 }
8733
8734 signature = MagickGetImageSignature(intern->magick_wand);
8735 s_add_assoc_str (return_value, "signature", signature);
8736 IMAGICK_FREE_MAGICK_MEMORY(signature);
8737
8738 if (append_raw_string == 1)
8739 IM_add_assoc_string (return_value, "rawOutput", identify);
8740
8741 IMAGICK_FREE_MAGICK_MEMORY(identify);
8742 return;
8743 }
8744 /* }}} */
8745
8746 #undef imagick_option_to_string
8747
8748 /* {{{ proto int Imagick::getImageColors()
8749 Gets the number of unique colors in the image.
8750 */
8751 PHP_METHOD(Imagick, getImageColors)
8752 {
8753 php_imagick_object *intern;
8754
8755 if (zend_parse_parameters_none() == FAILURE) {
8756 return;
8757 }
8758
8759 intern = Z_IMAGICK_P(getThis());
8760 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
8761 return;
8762
8763 ZVAL_LONG(return_value, (long)MagickGetImageColors(intern->magick_wand));
8764 return;
8765 }
8766 /* }}} */
8767
8768 /* {{{ proto bool Imagick::commentImage(string comment)
8769 Adds a comment to your image.
8770 */
8771 PHP_METHOD(Imagick, commentImage)
8772 {
8773 php_imagick_object *intern;
8774 char *comment;
8775 IM_LEN_TYPE comment_len;
8776 MagickBooleanType status;
8777
8778 /* Parse parameters given to function */
8779 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &comment, &comment_len) == FAILURE) {
8780 return;
8781 }
8782
8783 intern = Z_IMAGICK_P(getThis());
8784
8785 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
8786 return;
8787
8788 status = MagickCommentImage(intern->magick_wand, comment);
8789
8790 /* No magick is going to happen */
8791 if (status == MagickFalse) {
8792 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to comment image" TSRMLS_CC);
8793 return;
8794 }
8795
8796 RETURN_TRUE;
8797 }
8798 /* }}} */
8799
8800 /* {{{ proto bool Imagick::setImageFilename(string filename)
8801 Sets the filename of a particular image in a sequence.
8802 */
8803 PHP_METHOD(Imagick, setImageFilename)
8804 {
8805 php_imagick_object *intern;
8806 char *filename;
8807 IM_LEN_TYPE filename_len;
8808 MagickBooleanType status;
8809
8810 /* Parse parameters given to function */
8811 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
8812 return;
8813 }
8814
8815 intern = Z_IMAGICK_P(getThis());
8816 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
8817 return;
8818
8819 status = MagickSetImageFilename(intern->magick_wand, filename);
8820
8821 /* No magick is going to happen */
8822 if (status == MagickFalse) {
8823 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image filename" TSRMLS_CC);
8824 return;
8825 }
8826
8827 RETURN_TRUE;
8828 }
8829 /* }}} */
8830
8831 #if !defined(MAGICKCORE_EXCLUDE_DEPRECATED)
8832 #if MagickLibVersion < 0x700
8833 /* PS, DEPRECATED please remove: http://www.imagemagick.org/discourse-server/viewtopic.php?f=6&t=8196 */
8834 PHP_METHOD(Imagick, setImageAttribute)
8835 {
8836 php_imagick_object *intern;
8837 char *key, *attribute;
8838 IM_LEN_TYPE key_len, attribute_len;
8839 MagickBooleanType status;
8840
8841 /* Tell user that this method has been deprecated. */
8842 IMAGICK_METHOD_DEPRECATED("Imagick", "setImageAttribute");
8843
8844 /* Parse parameters given to function */
8845 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &key, &key_len, &attribute, &attribute_len) == FAILURE) {
8846 return;
8847 }
8848
8849 intern = Z_IMAGICK_P(getThis());
8850 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
8851 return;
8852
8853 status = MagickSetImageAttribute(intern->magick_wand, key, attribute);
8854
8855 /* No magick is going to happen */
8856 if (status == MagickFalse) {
8857 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image attribute" TSRMLS_CC);
8858 return;
8859 }
8860 RETURN_TRUE;
8861 }
8862 #endif // #if MagickLibVersion < 0x700
8863 #endif
8864
8865 /* {{{ proto bool Imagick::setImageBackgroundColor(ImagickPixel background)
8866 Sets the image background color.
8867 */
8868 PHP_METHOD(Imagick, setImageBackgroundColor)
8869 {
8870 zval *param;
8871 php_imagick_object *intern;
8872 MagickBooleanType status;
8873 PixelWand *color_wand;
8874 zend_bool allocated;
8875
8876 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶m) == FAILURE) {
8877 return;
8878 }
8879
8880 intern = Z_IMAGICK_P(getThis());
8881
8882 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
8883 return;
8884
8885 color_wand = php_imagick_zval_to_pixelwand (param, IMAGICK_CLASS, &allocated TSRMLS_CC);
8886 if (!color_wand)
8887 return;
8888
8889 status = MagickSetImageBackgroundColor(intern->magick_wand, color_wand);
8890
8891 if (allocated)
8892 color_wand = DestroyPixelWand (color_wand);
8893
8894 /* No magick is going to happen */
8895 if (status == MagickFalse) {
8896 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image background color" TSRMLS_CC);
8897 return;
8898 }
8899
8900 RETURN_TRUE;
8901 }
8902 /* }}} */
8903
8904 #if MagickLibVersion >= 0x700
8905 /* {{{ proto int Imagick::setImageChannelMask(int channel)
8906 Sets the image channel mask. Returns the previous set channel mask.
8907 */
8908 PHP_METHOD(Imagick, setImageChannelMask)
8909 {
8910 php_imagick_object *intern;
8911 im_long channel;
8912 ChannelType previous_channel_type;
8913
8914 /* Parse parameters given to function */
8915 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &channel) == FAILURE) {
8916 return;
8917 }
8918
8919 intern = Z_IMAGICK_P(getThis());
8920 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
8921 return;
8922
8923 previous_channel_type = MagickSetImageChannelMask(intern->magick_wand, channel);
8924
8925 RETURN_LONG(previous_channel_type);
8926 }
8927 /* }}} */
8928 #endif
8929
8930
8931 /* {{{ proto bool Imagick::setImageCompose(int compose)
8932 Sets the image composite operator, useful for specifying how to composite the image thumbnail when using the Imagick::montageImage() method.
8933 */
8934 PHP_METHOD(Imagick, setImageCompose)
8935 {
8936 php_imagick_object *intern;
8937 im_long compose;
8938 MagickBooleanType status;
8939
8940 /* Parse parameters given to function */
8941 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &compose) == FAILURE) {
8942 return;
8943 }
8944
8945 intern = Z_IMAGICK_P(getThis());
8946 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
8947 return;
8948
8949 status = MagickSetImageCompose(intern->magick_wand, compose);
8950
8951 /* No magick is going to happen */
8952 if (status == MagickFalse) {
8953 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image composite operator" TSRMLS_CC);
8954 return;
8955 }
8956 RETURN_TRUE;
8957 }
8958 /* }}} */
8959
8960 /* {{{ proto int Imagick::getImageCompression()
8961 Gets the image compression type
8962 */
8963 PHP_METHOD(Imagick, getImageCompression)
8964 {
8965 php_imagick_object *intern;
8966
8967 if (zend_parse_parameters_none() == FAILURE) {
8968 return;
8969 }
8970
8971 intern = Z_IMAGICK_P(getThis());
8972 RETVAL_LONG(MagickGetImageCompression(intern->magick_wand));
8973 }
8974 /* }}} */
8975
8976 /* {{{ proto bool Imagick::setImageCompression(int compression)
8977 Sets the image compression.
8978 */
8979 PHP_METHOD(Imagick, setImageCompression)
8980 {
8981 php_imagick_object *intern;
8982 im_long compression;
8983 MagickBooleanType status;
8984
8985 /* Parse parameters given to function */
8986 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &compression) == FAILURE) {
8987 return;
8988 }
8989
8990 intern = Z_IMAGICK_P(getThis());
8991
8992 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
8993 return;
8994
8995 status = MagickSetImageCompression(intern->magick_wand, compression);
8996
8997 /* No magick is going to happen */
8998 if (status == MagickFalse) {
8999 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image compression" TSRMLS_CC);
9000 return;
9001 }
9002 RETURN_TRUE;
9003 }
9004 /* }}} */
9005
9006 /* {{{ proto bool Imagick::setImageDelay(int delay)
9007 Sets the image delay.
9008 */
9009 PHP_METHOD(Imagick, setImageDelay)
9010 {
9011 php_imagick_object *intern;
9012 im_long delay;
9013 MagickBooleanType status;
9014
9015 /* Parse parameters given to function */
9016 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &delay) == FAILURE) {
9017 return;
9018 }
9019
9020 intern = Z_IMAGICK_P(getThis());
9021 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9022 return;
9023
9024 status = MagickSetImageDelay(intern->magick_wand, delay);
9025
9026 /* No magick is going to happen */
9027 if (status == MagickFalse) {
9028 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image delay" TSRMLS_CC);
9029 return;
9030 }
9031 RETURN_TRUE;
9032 }
9033 /* }}} */
9034
9035 /* {{{ proto bool Imagick::colorizeImage(ImagickPixel colorize, ImagickPixel opacity, bool legacy)
9036 Blends the fill color with each pixel in the image. The 'opacity' color is a
9037 per channel strength factor for how strongly the color should be applied. If
9038 legacy is true, the behaviour of this function is incorrect, but consistent
9039 with how it behaved before Imagick version 3.4.0
9040 */
9041 PHP_METHOD(Imagick, colorizeImage)
9042 {
9043 PixelWand *param_wand = NULL;
9044 php_imagick_object *intern;
9045 zval *color_param, *opacity_param;
9046 MagickBooleanType status;
9047 PixelWand *color_wand, *opacity_wand;
9048 zend_bool color_allocated, opacity_allocated;
9049 zend_bool legacy = 0;
9050
9051 /* Parse parameters given to function */
9052 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|b", &color_param, &opacity_param, &legacy) == FAILURE) {
9053 return;
9054 }
9055
9056 intern = Z_IMAGICK_P(getThis());
9057 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9058 return;
9059
9060 color_wand = php_imagick_zval_to_pixelwand (color_param, IMAGICK_CLASS, &color_allocated TSRMLS_CC);
9061 if (!color_wand)
9062 return;
9063
9064 if (legacy) {
9065 opacity_wand = php_imagick_zval_to_opacity (opacity_param, IMAGICK_CLASS, &opacity_allocated TSRMLS_CC);
9066 }
9067 else {
9068 opacity_wand = php_imagick_zval_to_pixelwand(opacity_param, IMAGICK_CLASS, &opacity_allocated TSRMLS_CC);
9069 }
9070
9071 if (!opacity_wand) {
9072 if (color_allocated)
9073 color_wand = DestroyPixelWand (color_wand);
9074
9075 return;
9076 }
9077
9078 if (legacy) {
9079 /* Colorize wants both wands to be of same instance */
9080 param_wand = php_imagick_clone_pixelwand (color_wand);
9081 if (!param_wand) {
9082 php_imagick_throw_exception (IMAGICK_CLASS, "Failed to allocate" TSRMLS_CC);
9083 return;
9084 }
9085 #if MagickLibVersion < 0x700
9086 PixelSetOpacity(param_wand, PixelGetOpacity(opacity_wand));
9087 #endif
9088 PixelSetAlpha(param_wand, PixelGetAlpha(opacity_wand));
9089 status = MagickColorizeImage(intern->magick_wand, param_wand, param_wand);
9090 param_wand = DestroyPixelWand(param_wand);
9091 } else {
9092 status = MagickColorizeImage(intern->magick_wand, color_wand, opacity_wand);
9093 }
9094
9095 if (color_allocated)
9096 color_wand = DestroyPixelWand (color_wand);
9097
9098 if (opacity_allocated)
9099 opacity_wand = DestroyPixelWand (opacity_wand);
9100
9101 /* No magick is going to happen */
9102 if (status == MagickFalse) {
9103 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to colorize image" TSRMLS_CC);
9104 return;
9105 }
9106 RETURN_TRUE;
9107 }
9108 /* }}} */
9109
9110 /* {{{ proto Imagick Imagick::compareImageChannels(Imagick reference, int channel, int metric)
9111 Compares one or more image channels of an image to a reconstructed image and returns the difference image.
9112 */
9113 PHP_METHOD(Imagick, compareImageChannels)
9114 {
9115 MagickWand *tmp_wand;
9116 zval *objvar;
9117 php_imagick_object *intern, *intern_second, *intern_return;
9118 im_long channel_type, metric_type;
9119 double distortion;
9120 #if PHP_VERSION_ID >= 70000
9121 zval new_wand;
9122 #else
9123 zval *new_wand;
9124 #endif
9125
9126 zval *pNewWand;
9127
9128
9129 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Oll", &objvar, php_imagick_sc_entry, &channel_type, &metric_type) == FAILURE) {
9130 return;
9131 }
9132
9133 intern = Z_IMAGICK_P(getThis());
9134 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9135 return;
9136
9137 intern_second = Z_IMAGICK_P(objvar);
9138 if (php_imagick_ensure_not_empty (intern_second->magick_wand) == 0)
9139 return;
9140
9141 tmp_wand = MagickCompareImageChannels(intern->magick_wand, intern_second->magick_wand, channel_type, metric_type, &distortion);
9142
9143 if (!tmp_wand) {
9144 php_imagick_convert_imagick_exception(intern->magick_wand, "Compare image channels failed" TSRMLS_CC);
9145 return;
9146 }
9147
9148 #if PHP_VERSION_ID >= 70000
9149 pNewWand = &new_wand;
9150 #else
9151 MAKE_STD_ZVAL(new_wand);
9152 pNewWand = new_wand;
9153 #endif
9154 array_init(return_value);
9155
9156 object_init_ex(pNewWand, php_imagick_sc_entry);
9157 intern_return = Z_IMAGICK_P(pNewWand);
9158 php_imagick_replace_magickwand(intern_return, tmp_wand);
9159
9160 add_next_index_zval(return_value, pNewWand);
9161 add_next_index_double(return_value, distortion);
9162
9163 return;
9164 }
9165 /* }}} */
9166 #if MagickLibVersion > 0x628
9167 /* {{{ proto Imagick Imagick::compareImageLayers(int method)
9168 Compares each image with the next in a sequence and returns the maximum bounding region of any pixel differences it discovers.
9169 */
9170 PHP_METHOD(Imagick, compareImageLayers)
9171 {
9172 MagickWand *tmp_wand;
9173 php_imagick_object *intern, *intern_return;
9174 im_long compare_method;
9175
9176 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &compare_method) == FAILURE) {
9177 return;
9178 }
9179
9180 intern = Z_IMAGICK_P(getThis());
9181 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9182 return;
9183
9184 #if MagickLibVersion >= 0x700
9185 tmp_wand = (MagickWand *)MagickCompareImagesLayers(intern->magick_wand, compare_method);
9186 #else
9187 tmp_wand = (MagickWand *)MagickCompareImageLayers(intern->magick_wand, compare_method);
9188 #endif
9189
9190 if (tmp_wand == NULL) {
9191 php_imagick_convert_imagick_exception(intern->magick_wand, "Compare image layers failed" TSRMLS_CC);
9192 return;
9193 }
9194
9195 object_init_ex(return_value, php_imagick_sc_entry);
9196 intern_return = Z_IMAGICK_P(return_value);
9197 php_imagick_replace_magickwand(intern_return, tmp_wand);
9198
9199 return;
9200 }
9201 /* }}} */
9202 #endif
9203
9204 #if MagickLibVersion < 0x700
9205 #if !defined(MAGICKCORE_EXCLUDE_DEPRECATED)
9206 /* {{{ proto Imagick Imagick::flattenImages()
9207 Merges a sequence of images. This is useful for combining Photoshop layers into a single image.
9208 */
9209 PHP_METHOD(Imagick, flattenImages)
9210 {
9211 php_imagick_object *intern, *intern_return;
9212 MagickWand *tmp_wand;
9213
9214 IMAGICK_METHOD_DEPRECATED ("Imagick", "flattenImages");
9215
9216 if (zend_parse_parameters_none() == FAILURE) {
9217 return;
9218 }
9219
9220 intern = Z_IMAGICK_P(getThis());
9221 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9222 return;
9223
9224
9225 /* TODO: SHOULD THIS BE HERE? */
9226 MagickSetFirstIterator(intern->magick_wand);
9227
9228 tmp_wand = MagickFlattenImages(intern->magick_wand);
9229
9230 if (tmp_wand == NULL) {
9231 php_imagick_convert_imagick_exception(intern->magick_wand, "Flatten images failed" TSRMLS_CC);
9232 return;
9233 }
9234
9235 object_init_ex(return_value, php_imagick_sc_entry);
9236 intern_return = Z_IMAGICK_P(return_value);
9237 php_imagick_replace_magickwand(intern_return, tmp_wand);
9238
9239 return;
9240 }
9241 /* }}} */
9242 #endif
9243 #endif
9244
9245 /* {{{ proto bool Imagick::flipImage()
9246 Creates a vertical mirror image by reflecting the pixels around the central x-axis.
9247 */
9248 PHP_METHOD(Imagick, flipImage)
9249 {
9250 php_imagick_object *intern;
9251 MagickBooleanType status;
9252
9253 if (zend_parse_parameters_none() == FAILURE) {
9254 return;
9255 }
9256
9257 intern = Z_IMAGICK_P(getThis());
9258 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9259 return;
9260
9261 status = MagickFlipImage(intern->magick_wand);
9262
9263 /* No magick is going to happen */
9264 if (status == MagickFalse) {
9265 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to flip image" TSRMLS_CC);
9266 return;
9267 }
9268 RETURN_TRUE;
9269 }
9270 /* }}} */
9271
9272 /* {{{ proto bool Imagick::flopImage()
9273 Creates a horizontal mirror image by reflecting the pixels around the central y-axis.
9274 */
9275 PHP_METHOD(Imagick, flopImage)
9276 {
9277 php_imagick_object *intern;
9278 MagickBooleanType status;
9279
9280 if (zend_parse_parameters_none() == FAILURE) {
9281 return;
9282 }
9283
9284 intern = Z_IMAGICK_P(getThis());
9285 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9286 return;
9287
9288 status = MagickFlopImage(intern->magick_wand);
9289
9290 /* No magick is going to happen */
9291 if (status == MagickFalse) {
9292 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to flop image" TSRMLS_CC);
9293 return;
9294 }
9295 RETURN_TRUE;
9296 }
9297 /* }}} */
9298
9299 /* {{{ proto bool Imagick::frameImage(ImagickPixel matte_color, int width, int height, int inner_bevel, int outer_bevel)
9300 Adds a simulated three-dimensional border around the image
9301 */
9302 PHP_METHOD(Imagick, frameImage)
9303 {
9304 zval *param;
9305 php_imagick_object *intern;
9306 MagickBooleanType status;
9307 im_long width, height, inner_bevel, outer_bevel;
9308 PixelWand *color_wand;
9309 zend_bool allocated;
9310
9311 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zllll", ¶m, &width, &height, &inner_bevel, &outer_bevel) == FAILURE) {
9312 return;
9313 }
9314
9315 intern = Z_IMAGICK_P(getThis());
9316
9317 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9318 return;
9319
9320 color_wand = php_imagick_zval_to_pixelwand (param, IMAGICK_CLASS, &allocated TSRMLS_CC);
9321 if (!color_wand)
9322 return;
9323
9324 #if MagickLibVersion >= 0x700
9325 {
9326 //TODO - understand and allow compose to be set.
9327 CompositeOperator compose = AtopCompositeOp;
9328 status = MagickFrameImage(intern->magick_wand, color_wand, width, height, inner_bevel, outer_bevel, compose);
9329 }
9330 #else
9331 status = MagickFrameImage(intern->magick_wand, color_wand, width, height, inner_bevel, outer_bevel);
9332 #endif
9333
9334 if (allocated)
9335 color_wand = DestroyPixelWand (color_wand);
9336
9337 /* No magick is going to happen */
9338 if (status == MagickFalse) {
9339 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to frame image" TSRMLS_CC);
9340 return;
9341 }
9342 RETURN_TRUE;
9343 }
9344 /* }}} */
9345
9346 /* {{{ proto Imagick Imagick::fxImage(string expression[, int channel])
9347 Evaluate expression for each pixel in the image.
9348 */
9349 PHP_METHOD(Imagick, fxImage)
9350 {
9351 MagickWand *tmp_wand;
9352 php_imagick_object *intern, *intern_return;
9353 char *expression;
9354 IM_LEN_TYPE expression_len;
9355 im_long channel = IM_DEFAULT_CHANNEL;
9356
9357 /* Parse parameters given to function */
9358 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &expression, &expression_len, &channel) == FAILURE) {
9359 return;
9360 }
9361
9362 intern = Z_IMAGICK_P(getThis());
9363 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9364 return;
9365
9366 tmp_wand = MagickFxImageChannel(intern->magick_wand, channel, expression);
9367
9368 if (tmp_wand == NULL) {
9369 php_imagick_convert_imagick_exception(intern->magick_wand, "Fx image failed" TSRMLS_CC);
9370 return;
9371 }
9372
9373 object_init_ex(return_value, php_imagick_sc_entry);
9374 intern_return = Z_IMAGICK_P(return_value);
9375 php_imagick_replace_magickwand(intern_return, tmp_wand);
9376
9377 return;
9378 }
9379 /* }}} */
9380
9381 /* {{{ proto bool Imagick::gammaImage(float gamma[, int channel])
9382 Gamma-corrects an image. The same image viewed on different devices will have perceptual differences in the way the image's intensities are represented on the screen. Specify individual gamma levels for the red, green, and blue channels, or adjust all three with the gamma parameter. Values typically range from 0.8 to 2.3.
9383 */
9384 PHP_METHOD(Imagick, gammaImage)
9385 {
9386 php_imagick_object *intern;
9387 MagickBooleanType status;
9388 double gamma;
9389 im_long channel = IM_DEFAULT_CHANNEL;
9390
9391 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d|l", &gamma, &channel) == FAILURE) {
9392 return;
9393 }
9394
9395 intern = Z_IMAGICK_P(getThis());
9396 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9397 return;
9398
9399 status = MagickGammaImageChannel(intern->magick_wand, channel, gamma);
9400
9401 /* No magick is going to happen */
9402 if (status == MagickFalse) {
9403 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to gamma image" TSRMLS_CC);
9404 return;
9405 }
9406
9407 RETURN_TRUE;
9408 }
9409 /* }}} */
9410
9411 /* {{{ proto bool Imagick::gaussianBlurImage(float radius, float sigma[, int channel])
9412 Blurs an image. We convolve the image with a Gaussian operator of the given radius and standard deviation (sigma). For reasonable results, the radius should be larger than sigma. Use a radius of 0 and selects a suitable radius for you.
9413 */
9414 PHP_METHOD(Imagick, gaussianBlurImage)
9415 {
9416 php_imagick_object *intern;
9417 MagickBooleanType status;
9418 double radius, sigma;
9419 im_long channel = IM_DEFAULT_CHANNEL;
9420
9421 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd|l", &radius, &sigma, &channel) == FAILURE) {
9422 return;
9423 }
9424
9425 intern = Z_IMAGICK_P(getThis());
9426 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9427 return;
9428
9429 status = MagickGaussianBlurImageChannel(intern->magick_wand, channel, radius, sigma);
9430
9431 /* No magick is going to happen */
9432 if (status == MagickFalse) {
9433 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to gaussian blur image" TSRMLS_CC);
9434 return;
9435 }
9436
9437 RETURN_TRUE;
9438 }
9439 /* }}} */
9440
9441 /* {{{ proto Imagick Imagick::compareImageChannels(int metric, int distortion)
9442 Compares one or more images and returns the difference image.
9443 */
9444 PHP_METHOD(Imagick, compareImages)
9445 {
9446 MagickWand *tmp_wand;
9447 zval *objvar;
9448 php_imagick_object *intern, *intern_second, *intern_return;
9449 im_long metric_type;
9450 double distortion;
9451 #if PHP_VERSION_ID >= 70000
9452 zval new_wand;
9453 #else
9454 zval *new_wand;
9455 #endif
9456
9457 zval *pNewWand;
9458
9459 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol", &objvar, php_imagick_sc_entry, &metric_type) == FAILURE) {
9460 return;
9461 }
9462
9463 intern = Z_IMAGICK_P(getThis());
9464 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9465 return;
9466
9467 intern_second = Z_IMAGICK_P(objvar);
9468 if (php_imagick_ensure_not_empty (intern_second->magick_wand) == 0)
9469 return;
9470
9471 #if PHP_VERSION_ID >= 70000
9472 pNewWand = &new_wand;
9473 #else
9474 MAKE_STD_ZVAL(new_wand);
9475 pNewWand = new_wand;
9476 #endif
9477 array_init(return_value);
9478
9479 tmp_wand = MagickCompareImages(intern->magick_wand, intern_second->magick_wand, metric_type, &distortion);
9480
9481 if (!tmp_wand) {
9482 php_imagick_convert_imagick_exception(intern->magick_wand, "Compare images failed" TSRMLS_CC);
9483 return;
9484 }
9485
9486 object_init_ex(pNewWand, php_imagick_sc_entry);
9487 intern_return = Z_IMAGICK_P(pNewWand);
9488 php_imagick_replace_magickwand(intern_return, tmp_wand);
9489
9490 add_next_index_zval(return_value, pNewWand);
9491 add_next_index_double(return_value, distortion);
9492
9493 return;
9494 }
9495 /* }}} */
9496
9497 /* {{{ proto bool Imagick::contrastImage(bool sharpen)
9498 Enhances the intensity differences between the lighter and darker elements of the image. Set sharpen to a value other than 0 to increase the image contrast otherwise the contrast is reduced.
9499 */
9500 PHP_METHOD(Imagick, contrastImage)
9501 {
9502 php_imagick_object *intern;
9503 MagickBooleanType status;
9504 zend_bool contrast;
9505
9506 /* Parse parameters given to function */
9507 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &contrast) == FAILURE) {
9508 return;
9509 }
9510
9511 intern = Z_IMAGICK_P(getThis());
9512 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9513 return;
9514
9515 status = MagickContrastImage(intern->magick_wand, contrast);
9516
9517 /* No magick is going to happen */
9518 if (status == MagickFalse) {
9519 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to contrast image" TSRMLS_CC);
9520 return;
9521 }
9522 RETURN_TRUE;
9523 }
9524 /* }}} */
9525
9526 /* {{{ proto bool Imagick::setImageDepth(int depth)
9527 Sets the image depth.
9528 */
9529 PHP_METHOD(Imagick, setImageDepth)
9530 {
9531 php_imagick_object *intern;
9532 im_long depth;
9533 MagickBooleanType status;
9534
9535 /* Parse parameters given to function */
9536 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &depth) == FAILURE) {
9537 return;
9538 }
9539
9540 intern = Z_IMAGICK_P(getThis());
9541 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9542 return;
9543
9544 status = MagickSetImageDepth(intern->magick_wand, depth);
9545
9546 /* No magick is going to happen */
9547 if (status == MagickFalse) {
9548 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image depth" TSRMLS_CC);
9549 return;
9550 }
9551 RETURN_TRUE;
9552 }
9553 /* }}} */
9554
9555 /* {{{ proto bool Imagick::setImageGamma(float gamma)
9556 Sets the image gamma.
9557 */
9558 PHP_METHOD(Imagick, setImageGamma)
9559 {
9560 php_imagick_object *intern;
9561 double gamma;
9562 MagickBooleanType status;
9563
9564 /* Parse parameters given to function */
9565 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &gamma) == FAILURE) {
9566 return;
9567 }
9568
9569 intern = Z_IMAGICK_P(getThis());
9570 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9571 return;
9572
9573 status = MagickSetImageGamma(intern->magick_wand, gamma);
9574
9575 /* No magick is going to happen */
9576 if (status == MagickFalse) {
9577 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image gamma" TSRMLS_CC);
9578 return;
9579 }
9580 RETURN_TRUE;
9581 }
9582 /* }}} */
9583
9584 /* {{{ proto bool Imagick::setImageIterations(int iterations)
9585 Sets the image iterations.
9586 */
9587 PHP_METHOD(Imagick, setImageIterations)
9588 {
9589 php_imagick_object *intern;
9590 im_long iterations;
9591 MagickBooleanType status;
9592
9593 /* Parse parameters given to function */
9594 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &iterations) == FAILURE) {
9595 return;
9596 }
9597
9598 intern = Z_IMAGICK_P(getThis());
9599 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9600 return;
9601
9602 status = MagickSetImageIterations(intern->magick_wand, iterations);
9603
9604 /* No magick is going to happen */
9605 if (status == MagickFalse) {
9606 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image iterations" TSRMLS_CC);
9607 return;
9608 }
9609 RETURN_TRUE;
9610 }
9611 /* }}} */
9612
9613 #if MagickLibVersion < 0x700
9614 /* {{{ proto bool Imagick::setImageMatteColor(ImagickPixel matte)
9615 Sets the image matte color.
9616 */
9617 PHP_METHOD(Imagick, setImageMatteColor)
9618 {
9619 zval *param;
9620 php_imagick_object *intern;
9621 MagickBooleanType status;
9622 PixelWand *color_wand;
9623 zend_bool allocated;
9624
9625 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶m) == FAILURE) {
9626 return;
9627 }
9628
9629 intern = Z_IMAGICK_P(getThis());
9630
9631 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9632 return;
9633
9634 color_wand = php_imagick_zval_to_pixelwand (param, IMAGICK_CLASS, &allocated TSRMLS_CC);
9635 if (!color_wand)
9636 return;
9637
9638 status = MagickSetImageMatteColor(intern->magick_wand, color_wand);
9639
9640 if (allocated)
9641 color_wand = DestroyPixelWand (color_wand);
9642
9643 /* No magick is going to happen */
9644 if (status == MagickFalse) {
9645 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image matte color" TSRMLS_CC);
9646 return;
9647 }
9648
9649 RETURN_TRUE;
9650 }
9651 /* }}} */
9652 #endif //#if MagickLibVersion < 0x700
9653
9654 /* {{{ proto bool Imagick::setImagePage(int width, int height, int x, int y)
9655 Sets the page geometry of the image.
9656 */
9657 PHP_METHOD(Imagick, setImagePage)
9658 {
9659 php_imagick_object *intern;
9660 im_long width, height, x, y;
9661 MagickBooleanType status;
9662
9663 /* Parse parameters given to function */
9664 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llll", &width, &height, &x, &y) == FAILURE) {
9665 return;
9666 }
9667
9668 intern = Z_IMAGICK_P(getThis());
9669 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9670 return;
9671
9672 status = MagickSetImagePage(intern->magick_wand, width, height, x, y);
9673
9674 /* No magick is going to happen */
9675 if (status == MagickFalse) {
9676 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image page" TSRMLS_CC);
9677 return;
9678 }
9679 RETURN_TRUE;
9680 }
9681 /* }}} */
9682
9683 /* {{{ proto bool Imagick::setImageResolution(float x_resolution,const float y_resolution)
9684 Sets the image resolution.
9685 */
9686 PHP_METHOD(Imagick, setImageResolution)
9687 {
9688 php_imagick_object *intern;
9689 double x_res, y_res;
9690 MagickBooleanType status;
9691
9692 /* Parse parameters given to function */
9693 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &x_res, &y_res) == FAILURE) {
9694 return;
9695 }
9696
9697 intern = Z_IMAGICK_P(getThis());
9698 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9699 return;
9700
9701 status = MagickSetImageResolution(intern->magick_wand, x_res, y_res);
9702
9703 /* No magick is going to happen */
9704 if (status == MagickFalse) {
9705 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image resolution" TSRMLS_CC);
9706 return;
9707 }
9708 RETURN_TRUE;
9709 }
9710 /* }}} */
9711
9712 /* {{{ proto bool Imagick::setImageScene(int scene)
9713 Sets the image scene.
9714 */
9715 PHP_METHOD(Imagick, setImageScene)
9716 {
9717 php_imagick_object *intern;
9718 im_long scene;
9719 MagickBooleanType status;
9720
9721 /* Parse parameters given to function */
9722 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &scene) == FAILURE) {
9723 return;
9724 }
9725
9726 intern = Z_IMAGICK_P(getThis());
9727 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9728 return;
9729
9730 status = MagickSetImageScene(intern->magick_wand, scene);
9731
9732 /* No magick is going to happen */
9733 if (status == MagickFalse) {
9734 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image scene" TSRMLS_CC);
9735 return;
9736 }
9737 RETURN_TRUE;
9738 }
9739 /* }}} */
9740
9741 /* {{{ proto bool Imagick::setImageTicksPerSecond(int ticks_per-second)
9742 Sets the image ticks-per-second.
9743 */
9744 PHP_METHOD(Imagick, setImageTicksPerSecond)
9745 {
9746 php_imagick_object *intern;
9747 im_long ticks_per_second;
9748 MagickBooleanType status;
9749
9750 /* Parse parameters given to function */
9751 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &ticks_per_second) == FAILURE) {
9752 return;
9753 }
9754
9755 intern = Z_IMAGICK_P(getThis());
9756 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9757 return;
9758
9759 status = MagickSetImageTicksPerSecond(intern->magick_wand, ticks_per_second);
9760
9761 /* No magick is going to happen */
9762 if (status == MagickFalse) {
9763 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image ticks per second" TSRMLS_CC);
9764 return;
9765 }
9766 RETURN_TRUE;
9767 }
9768 /* }}} */
9769
9770 /* {{{ proto bool Imagick::setImageType(int image_type)
9771 Sets the image type.
9772 */
9773 PHP_METHOD(Imagick, setImageType)
9774 {
9775 php_imagick_object *intern;
9776 im_long image_type;
9777 MagickBooleanType status;
9778
9779 /* Parse parameters given to function */
9780 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &image_type) == FAILURE) {
9781 return;
9782 }
9783
9784 intern = Z_IMAGICK_P(getThis());
9785 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9786 return;
9787
9788 status = MagickSetImageType(intern->magick_wand, image_type);
9789
9790 /* No magick is going to happen */
9791 if (status == MagickFalse) {
9792 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image type" TSRMLS_CC);
9793 return;
9794 }
9795 RETURN_TRUE;
9796 }
9797 /* }}} */
9798
9799 /* {{{ proto bool Imagick::setImageUnits(int units)
9800 Sets the image units of resolution.
9801 */
9802 PHP_METHOD(Imagick, setImageUnits)
9803 {
9804 php_imagick_object *intern;
9805 im_long units;
9806 MagickBooleanType status;
9807
9808 /* Parse parameters given to function */
9809 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &units) == FAILURE) {
9810 return;
9811 }
9812
9813 intern = Z_IMAGICK_P(getThis());
9814
9815 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9816 return;
9817
9818 status = MagickSetImageUnits(intern->magick_wand, units);
9819
9820 /* No magick is going to happen */
9821 if (status == MagickFalse) {
9822 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image units" TSRMLS_CC);
9823 return;
9824 }
9825 RETURN_TRUE;
9826 }
9827 /* }}} */
9828
9829 /* {{{ proto bool Imagick::setImageFormat(string format)
9830 Sets the format of a particular image in a sequence.
9831 */
9832 PHP_METHOD(Imagick, setImageFormat)
9833 {
9834 char *format;
9835 IM_LEN_TYPE format_len;
9836 MagickBooleanType status;
9837 php_imagick_object *intern;
9838
9839 /* Parse parameters given to function */
9840 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &format, &format_len) == FAILURE) {
9841 return;
9842 }
9843
9844 intern = Z_IMAGICK_P(getThis());
9845 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9846 return;
9847
9848 status = MagickSetImageFormat(intern->magick_wand, format);
9849
9850 /* No magick is going to happen */
9851 if (status == MagickFalse) {
9852 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image format" TSRMLS_CC);
9853 return;
9854 }
9855
9856 RETURN_TRUE;
9857 }
9858 /* }}} */
9859
9860 /* {{{ proto bool Imagick::charcoalImage(float radius, float sigma)
9861 Simulates a charcoal drawing.
9862 */
9863 PHP_METHOD(Imagick, charcoalImage)
9864 {
9865 double sigma, radius;
9866 MagickBooleanType status;
9867 php_imagick_object *intern;
9868
9869 /* Parse parameters given to function */
9870 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &radius, &sigma) == FAILURE) {
9871 return;
9872 }
9873
9874 intern = Z_IMAGICK_P(getThis());
9875 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9876 return;
9877
9878 status = MagickCharcoalImage(intern->magick_wand, sigma, radius);
9879
9880 /* No magick is going to happen */
9881 if (status == MagickFalse) {
9882 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to charcoal image" TSRMLS_CC);
9883 return;
9884 }
9885 RETURN_TRUE;
9886 }
9887 /* }}} */
9888
9889 /* {{{ proto bool Imagick::oilPaintImage(float radius)
9890 Applies a special effect filter that simulates an oil painting. Each pixel is replaced by the most frequent color occurring in a circular region defined by radius.
9891 */
9892 PHP_METHOD(Imagick, oilPaintImage)
9893 {
9894 double radius;
9895 MagickBooleanType status;
9896 php_imagick_object *intern;
9897 #if MagickLibVersion >= 0x700
9898 float sigma = 1.0;
9899 //TODO - allow sigma to be set.
9900 #endif // #if MagickLibVersion >= 0x700
9901
9902 /* Parse parameters given to function */
9903 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &radius) == FAILURE) {
9904 return;
9905 }
9906
9907 intern = Z_IMAGICK_P(getThis());
9908 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9909 return;
9910
9911 #if MagickLibVersion >= 0x700
9912 status = MagickOilPaintImage(intern->magick_wand, radius, sigma);
9913 #else
9914 status = MagickOilPaintImage(intern->magick_wand, radius);
9915 #endif
9916
9917 /* No magick is going to happen */
9918 if (status == MagickFalse)
9919 {
9920 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to oilpaint image" TSRMLS_CC);
9921 return;
9922 }
9923 RETURN_TRUE;
9924 }
9925 /* }}} */
9926
9927 /* {{{ proto bool Imagick::normalizeImage([int channel])
9928 Enhances the contrast of a color image by adjusting the pixels color to span the entire range of colors available, Channel parameter is ignored in ImageMagick below 6.2.8
9929 */
9930 PHP_METHOD(Imagick, normalizeImage)
9931 {
9932 MagickBooleanType status;
9933 php_imagick_object *intern;
9934 im_long channel = IM_DEFAULT_CHANNEL;
9935
9936 /* Parse parameters given to function */
9937 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &channel) == FAILURE) {
9938 return;
9939 }
9940
9941 intern = Z_IMAGICK_P(getThis());
9942 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9943 return;
9944
9945 #if MagickLibVersion > 0x628
9946 status = MagickNormalizeImageChannel(intern->magick_wand, channel);
9947 #else
9948 status = MagickNormalizeImage(intern->magick_wand);
9949 #endif
9950 /* No magick is going to happen */
9951 if (status == MagickFalse) {
9952 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to normalize image" TSRMLS_CC);
9953 return;
9954 }
9955 RETURN_TRUE;
9956 }
9957 /* }}} */
9958
9959 /* {{{ proto bool Imagick::labelImage(string label)
9960 Adds a label to your image.
9961 */
9962 PHP_METHOD(Imagick, labelImage)
9963 {
9964 char *label;
9965 IM_LEN_TYPE label_len;
9966 MagickBooleanType status;
9967 php_imagick_object *intern;
9968
9969 /* Parse parameters given to function */
9970 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &label, &label_len) == FAILURE) {
9971 return;
9972 }
9973
9974 intern = Z_IMAGICK_P(getThis());
9975
9976 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
9977 return;
9978 status = MagickLabelImage(intern->magick_wand, label);
9979
9980 /* No magick is going to happen */
9981 if (status == MagickFalse) {
9982 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to label image" TSRMLS_CC);
9983 return;
9984 }
9985
9986 RETURN_TRUE;
9987 }
9988 /* }}} */
9989
9990 /* {{{ proto bool Imagick::writeImage(string filename)
9991 Writes an image to the specified filename
9992 */
9993 PHP_METHOD(Imagick, writeImage)
9994 {
9995 char *filename = NULL;
9996 IM_LEN_TYPE filename_len = 0;
9997 zend_bool free_filename = 0;
9998 php_imagick_object *intern;
9999 struct php_imagick_file_t file = {0};
10000 php_imagick_rw_result_t rc;
10001
10002 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!", &filename, &filename_len) == FAILURE) {
10003 return;
10004 }
10005
10006 intern = Z_IMAGICK_P(getThis());
10007 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10008 return;
10009
10010 if (!filename) {
10011 filename = MagickGetImageFilename(intern->magick_wand);
10012
10013 if (!filename) {
10014 php_imagick_throw_exception(IMAGICK_CLASS, "No image filename specified" TSRMLS_CC);
10015 return;
10016 }
10017 filename_len = strlen(filename);
10018 free_filename = 1;
10019 }
10020
10021 if (!filename_len) {
10022 php_imagick_throw_exception(IMAGICK_CLASS, "Can not use empty string as a filename" TSRMLS_CC);
10023 return;
10024 }
10025
10026 if (!php_imagick_file_init(&file, filename, filename_len TSRMLS_CC)) {
10027 php_imagick_throw_exception(IMAGICK_CLASS, "Invalid filename provided" TSRMLS_CC);
10028 return;
10029 }
10030 rc = php_imagick_write_file(intern, &file, ImagickWriteImage, 0 TSRMLS_CC);
10031 php_imagick_file_deinit(&file);
10032
10033 if (rc != IMAGICK_RW_OK) {
10034 php_imagick_rw_fail_to_exception (intern->magick_wand, rc, filename TSRMLS_CC);
10035 if (free_filename) {
10036 IMAGICK_FREE_MAGICK_MEMORY(filename);
10037 }
10038 return;
10039 }
10040
10041 if (free_filename) {
10042 IMAGICK_FREE_MAGICK_MEMORY(filename);
10043 }
10044 RETURN_TRUE;
10045 }
10046 /* }}} */
10047
10048 /* {{{ proto bool Imagick::writeImages(string filename, bool adjoin)
10049 Writes an image or image sequence.
10050 */
10051 PHP_METHOD(Imagick, writeImages)
10052 {
10053 char *filename;
10054 zend_bool adjoin;
10055 IM_LEN_TYPE filename_len;
10056 php_imagick_object *intern;
10057 struct php_imagick_file_t file = {0};
10058 php_imagick_rw_result_t rc;
10059
10060 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sb", &filename, &filename_len, &adjoin) == FAILURE) {
10061 return;
10062 }
10063
10064 intern = Z_IMAGICK_P(getThis());
10065 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10066 return;
10067
10068 if (!filename_len) {
10069 php_imagick_convert_imagick_exception(intern->magick_wand, "Can not use empty string as a filename" TSRMLS_CC);
10070 return;
10071 }
10072
10073 if (!php_imagick_file_init(&file, filename, filename_len TSRMLS_CC)) {
10074 php_imagick_throw_exception(IMAGICK_CLASS, "Invalid filename provided" TSRMLS_CC);
10075 return;
10076 }
10077 rc = php_imagick_write_file(intern, &file, ImagickWriteImages, adjoin TSRMLS_CC);
10078 php_imagick_file_deinit(&file);
10079
10080 if (rc != IMAGICK_RW_OK) {
10081 php_imagick_rw_fail_to_exception (intern->magick_wand, rc, filename TSRMLS_CC);
10082 return;
10083 }
10084 RETURN_TRUE;
10085
10086 }
10087 /* }}} */
10088
10089 /* {{{ proto bool Imagick::drawImage(ImagickDraw drawing_wand)
10090 Renders the ImagickDrawing object on the current image.
10091 */
10092 PHP_METHOD(Imagick, drawImage)
10093 {
10094 zval *objvar;
10095 php_imagick_object *intern;
10096 MagickBooleanType status;
10097 php_imagickdraw_object *internd;
10098 char *old_locale;
10099
10100 intern = Z_IMAGICK_P(getThis());
10101
10102 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10103 return;
10104
10105 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &objvar, php_imagickdraw_sc_entry) == FAILURE) {
10106 return;
10107 }
10108
10109 internd = Z_IMAGICKDRAW_P(objvar);
10110
10111 old_locale = php_imagick_set_locale (TSRMLS_C);
10112
10113 status = MagickDrawImage(intern->magick_wand, internd->drawing_wand);
10114
10115 php_imagick_restore_locale (old_locale);
10116
10117 if (old_locale)
10118 efree (old_locale);
10119
10120 /* No magick is going to happen */
10121 if (status == MagickFalse) {
10122 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to draw image" TSRMLS_CC);
10123 return;
10124 }
10125
10126 RETURN_TRUE;
10127 }
10128 /* }}} */
10129
10130 /* {{{ proto bool Imagick::annotateImage(ImagickDraw drawing_wand, float x, float y, float angle, string text)
10131 Annotates an image with text.
10132 */
10133 PHP_METHOD(Imagick, annotateImage)
10134 {
10135 php_imagick_object *intern;
10136 MagickBooleanType status;
10137 php_imagickdraw_object *internd;
10138 double x, y, angle;
10139 char *text;
10140 IM_LEN_TYPE text_len;
10141 zval *objvar;
10142 #if MagickLibVersion < 0x632
10143 char *font;
10144 #endif
10145
10146 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Oddds", &objvar, php_imagickdraw_sc_entry, &x, &y, &angle, &text, &text_len) == FAILURE) {
10147 return;
10148 }
10149
10150 intern = Z_IMAGICK_P(getThis());
10151 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10152 return;
10153
10154 internd = Z_IMAGICKDRAW_P(objvar);
10155
10156 #if MagickLibVersion < 0x632
10157 font = DrawGetFont(internd->drawing_wand);
10158
10159 /* Fixes PECL Bug #11328 */
10160 if (!font) {
10161 php_imagick_throw_exception(IMAGICK_CLASS, "Font needs to be set before annotating an image" TSRMLS_CC);
10162 return;
10163 }
10164 #endif
10165
10166 status = MagickAnnotateImage(intern->magick_wand, internd->drawing_wand, x, y, angle, text);
10167
10168 /* No magick is going to happen */
10169 if (status == MagickFalse) {
10170 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to annotate image" TSRMLS_CC);
10171 return;
10172 }
10173
10174 RETURN_TRUE;
10175 }
10176 /* }}} */
10177
10178 /* {{{ proto bool Imagick::getImageCompressionQuality(int quality)
10179 Gets the image compression quality
10180 */
10181 PHP_METHOD(Imagick, getImageCompressionQuality)
10182 {
10183 php_imagick_object *intern;
10184
10185 if (zend_parse_parameters_none() == FAILURE) {
10186 return;
10187 }
10188
10189 intern = Z_IMAGICK_P(getThis());
10190 RETVAL_LONG(MagickGetImageCompressionQuality(intern->magick_wand));
10191 }
10192 /* }}} */
10193
10194 /* {{{ proto bool Imagick::setImageCompressionQuality(int quality)
10195 Sets the image compression quality
10196 */
10197 PHP_METHOD(Imagick, setImageCompressionQuality)
10198 {
10199 im_long quality;
10200 php_imagick_object *intern;
10201 MagickBooleanType status;
10202
10203 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &quality) == FAILURE) {
10204 return;
10205 }
10206
10207 intern = Z_IMAGICK_P(getThis());
10208 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10209 return;
10210
10211 status = MagickSetImageCompressionQuality(intern->magick_wand, quality);
10212
10213 /* No magick is going to happen */
10214 if (status == MagickFalse) {
10215 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set image compression quality" TSRMLS_CC);
10216 return;
10217 }
10218
10219 RETURN_TRUE;
10220 }
10221 /* }}} */
10222
10223
10224 /* {{{ proto bool Imagick::compositeImage(Imagick composite_wand, int compose, int x, int y[, int channel] )
10225 Composite one image onto another at the specified offset. Channel parameter is ignored in ImageMagick below 6.2.8
10226 */
10227 PHP_METHOD(Imagick, compositeImage)
10228 {
10229 zval *objvar;
10230 php_imagick_object *intern;
10231 php_imagick_object *intern_second;
10232 im_long x, y;
10233 im_long composite_id = 0;
10234 im_long channel = IM_DEFAULT_CHANNEL;
10235
10236 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Olll|l", &objvar, php_imagick_sc_entry, &composite_id, &x, &y, &channel) == FAILURE) {
10237 return;
10238 }
10239
10240 intern = Z_IMAGICK_P(getThis());
10241 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10242 return;
10243
10244 intern_second = Z_IMAGICK_P(objvar);
10245 if (php_imagick_ensure_not_empty (intern_second->magick_wand) == 0)
10246 return;
10247
10248 #if MagickLibVersion > 0x628
10249 MagickCompositeImageChannel(intern->magick_wand, channel, intern_second->magick_wand, composite_id, x, y);
10250 #else
10251 MagickCompositeImage(intern->magick_wand, intern_second->magick_wand, composite_id, x, y);
10252 #endif
10253
10254 RETURN_TRUE;
10255 }
10256 /* }}} */
10257
10258 /* {{{ proto bool Imagick::modulateImage(float brightness, float saturation, float hue)
10259 Lets you control the brightness, saturation, and hue of an image. Hue is the percentage of absolute rotation from the current position. For example 50 results in a counter-clockwise rotation of 90 degrees, 150 results in a clockwise rotation of 90 degrees, with 0 and 200 both resulting in a rotation of 180 degrees.
10260 */
10261 PHP_METHOD(Imagick, modulateImage)
10262 {
10263 php_imagick_object *intern;
10264 MagickBooleanType status;
10265 double brightness, saturation, hue;
10266
10267 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd", &brightness, &saturation, &hue) == FAILURE) {
10268 return;
10269 }
10270
10271 intern = Z_IMAGICK_P(getThis());
10272 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10273 return;
10274
10275 status = MagickModulateImage(intern->magick_wand, brightness, saturation, hue);
10276
10277 if (status == MagickFalse) {
10278 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to modulate image" TSRMLS_CC);
10279 return;
10280 }
10281
10282 RETURN_TRUE;
10283 }
10284 /* }}} */
10285
10286 /* {{{ proto bool Imagick::addNoiseImage(int noise_type[, int channel])
10287 Adds random noise to the image. Channel parameter is ignored in ImageMagick below 6.2.8
10288 */
10289 PHP_METHOD(Imagick, addNoiseImage)
10290 {
10291 php_imagick_object *intern;
10292 MagickBooleanType status;
10293 im_long noise;
10294 im_long channel = IM_DEFAULT_CHANNEL;
10295
10296 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &noise, &channel) == FAILURE) {
10297 return;
10298 }
10299
10300 intern = Z_IMAGICK_P(getThis());
10301
10302 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10303 return;
10304
10305 #if MagickLibVersion > 0x628
10306 status = MagickAddNoiseImageChannel(intern->magick_wand, channel, noise);
10307 #else
10308 status = MagickAddNoiseImage(intern->magick_wand, noise);
10309 #endif
10310
10311 if (status == MagickFalse) {
10312 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to add image noise" TSRMLS_CC);
10313 return;
10314 }
10315
10316 RETURN_TRUE;
10317 }
10318 /* }}} */
10319
10320 /* {{{ proto Imagick Imagick::montageImage(ImagickDraw drawing_wand, string tile_geometry, string thumbnail_geometry, int mode, string frame)
10321 Creates a composite image by combining several separate images. The images are tiled on the composite image with the name of the image optionally appearing just below the individual tile.
10322 */
10323
10324 PHP_METHOD(Imagick, montageImage)
10325 {
10326 MagickWand *tmp_wand;
10327 zval *objvar;
10328 php_imagick_object *intern, *intern_return;
10329 php_imagickdraw_object *internd;
10330 char *tile_geometry, *thumbnail_geometry, *frame;
10331 IM_LEN_TYPE tile_geometry_len, thumbnail_geometry_len, frame_len;
10332 im_long montage_mode = 0;
10333
10334 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ossls", &objvar, php_imagickdraw_sc_entry,
10335 &tile_geometry, &tile_geometry_len,
10336 &thumbnail_geometry, &thumbnail_geometry_len,
10337 &montage_mode,
10338 &frame, &frame_len) == FAILURE)
10339 {
10340 return;
10341 }
10342
10343 intern = Z_IMAGICK_P(getThis());
10344
10345 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10346 return;
10347 internd = Z_IMAGICKDRAW_P(objvar);
10348
10349 tmp_wand = MagickMontageImage(intern->magick_wand, internd->drawing_wand, tile_geometry, thumbnail_geometry, montage_mode, frame);
10350
10351 if (tmp_wand == NULL) {
10352 php_imagick_convert_imagick_exception(intern->magick_wand, "Montage image failed" TSRMLS_CC);
10353 return;
10354 }
10355
10356 object_init_ex(return_value, php_imagick_sc_entry);
10357 intern_return = Z_IMAGICK_P(return_value);
10358 php_imagick_replace_magickwand(intern_return, tmp_wand);
10359
10360 return;
10361 }
10362 /* }}} */
10363
10364 /* {{{ proto bool Imagick::affineTransformImage(ImagickDraw drawing_wand)
10365 Transforms an image as dictated by the affine matrix of the drawing wand.
10366 */
10367 PHP_METHOD(Imagick, affineTransformImage)
10368 {
10369 zval *objvar;
10370 php_imagick_object *intern;
10371 php_imagickdraw_object *internd;
10372 MagickBooleanType status;
10373
10374 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &objvar, php_imagickdraw_sc_entry) == FAILURE) {
10375 return;
10376 }
10377
10378 intern = Z_IMAGICK_P(getThis());
10379 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10380 return;
10381
10382 internd = Z_IMAGICKDRAW_P(objvar);
10383 status = MagickAffineTransformImage(intern->magick_wand, internd->drawing_wand);
10384
10385 /* No magick is going to happen */
10386 if (status == MagickFalse) {
10387 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to affine transform image" TSRMLS_CC);
10388 return;
10389 }
10390
10391 RETURN_TRUE;
10392 }
10393 /* }}} */
10394
10395 #if MagickLibVersion < 0x700
10396 #if !defined(MAGICKCORE_EXCLUDE_DEPRECATED)
10397 /* {{{ proto Imagick Imagick::averageImages()
10398 Average a set of images.
10399 */
10400 PHP_METHOD(Imagick, averageImages)
10401 {
10402 MagickWand *tmp_wand;
10403 php_imagick_object *intern, *intern_return;
10404
10405 IMAGICK_METHOD_DEPRECATED ("Imagick", "averageImages");
10406
10407 if (zend_parse_parameters_none() == FAILURE) {
10408 return;
10409 }
10410
10411 intern = Z_IMAGICK_P(getThis());
10412 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10413 return;
10414
10415 tmp_wand = MagickAverageImages(intern->magick_wand);
10416
10417 if (tmp_wand == NULL) {
10418 php_imagick_convert_imagick_exception(intern->magick_wand, "Averaging images failed" TSRMLS_CC);
10419 return;
10420 }
10421
10422 object_init_ex(return_value, php_imagick_sc_entry);
10423 intern_return = Z_IMAGICK_P(return_value);
10424 php_imagick_replace_magickwand(intern_return, tmp_wand);
10425 return;
10426 }
10427 /* }}} */
10428 #endif
10429 #endif
10430
10431 /* {{{ proto bool Imagick::borderImage(ImagickPixel bordercolor, int width, int height)
10432 Surrounds the image with a border of the color defined by the bordercolor pixel wand.
10433 */
10434 PHP_METHOD(Imagick, borderImage)
10435 {
10436 zval *param;
10437 php_imagick_object *intern;
10438 MagickBooleanType status;
10439 im_long width, height;
10440 PixelWand *color_wand;
10441 zend_bool allocated;
10442
10443 #if MagickLibVersion >= 0x700
10444 //TODO - understand and allow compose to be set.
10445 CompositeOperator compose = AtopCompositeOp;
10446 #endif // #if MagickLibVersion >= 0x700
10447
10448 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zll", ¶m, &width, &height) == FAILURE) {
10449 return;
10450 }
10451
10452 intern = Z_IMAGICK_P(getThis());
10453
10454 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10455 return;
10456
10457 color_wand = php_imagick_zval_to_pixelwand (param, IMAGICK_CLASS, &allocated TSRMLS_CC);
10458 if (!color_wand)
10459 return;
10460
10461 #if MagickLibVersion >= 0x700
10462 status = MagickBorderImage(intern->magick_wand, color_wand, width, height, compose);
10463 #else
10464 status = MagickBorderImage(intern->magick_wand, color_wand, width, height);
10465 #endif
10466
10467 if (allocated)
10468 color_wand = DestroyPixelWand (color_wand);
10469
10470 /* No magick is going to happen */
10471 if (status == MagickFalse) {
10472 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to border image" TSRMLS_CC);
10473 return;
10474 }
10475
10476 RETURN_TRUE;
10477 }
10478 /* }}} */
10479
10480 /* {{{ proto bool Imagick::thresholdImage(float threshold[, int channel] )
10481 Changes the value of individual pixels based on the intensity of each pixel compared to threshold. The result is a high-contrast, two color image.
10482 */
10483 PHP_METHOD(Imagick, thresholdImage)
10484 {
10485 php_imagick_object *intern;
10486 double threshold;
10487 MagickBooleanType status;
10488 im_long channel = DefaultChannels;
10489
10490 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d|l", &threshold, &channel) == FAILURE) {
10491 return;
10492 }
10493
10494 intern = Z_IMAGICK_P(getThis());
10495
10496 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10497 return;
10498
10499 status = MagickThresholdImageChannel(intern->magick_wand, channel, threshold);
10500
10501 /* No magick is going to happen */
10502 if (status == MagickFalse) {
10503 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to threshold image" TSRMLS_CC);
10504 return;
10505 }
10506
10507 RETURN_TRUE;
10508 }
10509 /* }}} */
10510
10511 /* {{{ proto bool Imagick::adaptiveThresholdImage(int width, int height, int offset)
10512 Selects an individual threshold for each pixel based on the range of intensity values in its local neighborhood. This allows for thresholding of an image whose global intensity histogram doesn't contain distinctive peaks.
10513 */
10514 PHP_METHOD(Imagick, adaptiveThresholdImage)
10515 {
10516 php_imagick_object *intern;
10517 im_long width, height, offset;
10518 MagickBooleanType status;
10519
10520 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &width, &height, &offset) == FAILURE) {
10521 return;
10522 }
10523
10524 intern = Z_IMAGICK_P(getThis());
10525 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10526 return;
10527
10528 status = MagickAdaptiveThresholdImage(intern->magick_wand, width, height, offset);
10529
10530 /* No magick is going to happen */
10531 if (status == MagickFalse) {
10532 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to adaptive threshold image" TSRMLS_CC);
10533 return;
10534 }
10535
10536 RETURN_TRUE;
10537 }
10538 /* }}} */
10539
10540 /* {{{ proto bool Imagick::sharpenImage(float radius, float sigma[, int channel])
10541 Sharpens an image. We convolve the image with a Gaussian operator of the given radius and standard deviation (sigma). For reasonable results, the radius should be larger than sigma. Use a radius of 0 and selects a suitable radius for you.
10542 */
10543 PHP_METHOD(Imagick, sharpenImage)
10544 {
10545 double sigma, radius;
10546 MagickBooleanType status;
10547 php_imagick_object *intern;
10548 im_long channel = IM_DEFAULT_CHANNEL;
10549
10550 /* Parse parameters given to function */
10551 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd|l", &radius, &sigma, &channel) == FAILURE) {
10552 return;
10553 }
10554
10555 intern = Z_IMAGICK_P(getThis());
10556 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10557 return;
10558
10559 status = MagickSharpenImageChannel(intern->magick_wand, channel, radius, sigma);
10560
10561 /* No magick is going to happen */
10562 if (status == MagickFalse) {
10563 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to sharpen image" TSRMLS_CC);
10564 return;
10565 }
10566 RETURN_TRUE;
10567 }
10568 /* }}} */
10569
10570 /* {{{ proto bool Imagick::shaveImage(int columns, int rows)
10571 Shaves pixels from the image edges. It allocates the memory necessary for the new Image structure and returns a pointer to the new image.
10572 */
10573 PHP_METHOD(Imagick, shaveImage)
10574 {
10575 php_imagick_object *intern;
10576 im_long columns, rows;
10577 MagickBooleanType status;
10578
10579 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &columns, &rows) == FAILURE) {
10580 return;
10581 }
10582
10583 intern = Z_IMAGICK_P(getThis());
10584 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10585 return;
10586
10587 status = MagickShaveImage(intern->magick_wand, columns, rows);
10588
10589 /* No magick is going to happen */
10590 if (status == MagickFalse) {
10591 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to shave image" TSRMLS_CC);
10592 return;
10593 }
10594
10595 RETURN_TRUE;
10596 }
10597 /* }}} */
10598
10599 /* {{{ proto bool Imagick::shearImage(ImagickPixel background, float x_shear, float y_shear)
10600 Slides one edge of an image along the X or Y axis
10601 */
10602 PHP_METHOD(Imagick, shearImage)
10603 {
10604 zval *param;
10605 php_imagick_object *intern;
10606 double x_shear, y_shear;
10607 MagickBooleanType status;
10608 PixelWand *color_wand;
10609 zend_bool allocated;
10610
10611 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zdd", ¶m, &x_shear, &y_shear) == FAILURE) {
10612 return;
10613 }
10614
10615 intern = Z_IMAGICK_P(getThis());
10616 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10617 return;
10618
10619 color_wand = php_imagick_zval_to_pixelwand (param, IMAGICK_CLASS, &allocated TSRMLS_CC);
10620 if (!color_wand)
10621 return;
10622
10623 status = MagickShearImage(intern->magick_wand, color_wand, x_shear, y_shear);
10624
10625 if (allocated)
10626 color_wand = DestroyPixelWand (color_wand);
10627
10628 /* No magick is going to happen */
10629 if (status == MagickFalse) {
10630 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to shear image" TSRMLS_CC);
10631 return;
10632 }
10633
10634 RETURN_TRUE;
10635 }
10636 /* }}} */
10637
10638 /* {{{ proto bool Imagick::spliceImage(int width, int height, int x, int y)
10639 Splices a solid color into the image.
10640 */
10641 PHP_METHOD(Imagick, spliceImage)
10642 {
10643 im_long width, height, x, y;
10644 php_imagick_object *intern;
10645 MagickBooleanType status;
10646
10647 /* Parse parameters given to function */
10648 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llll", &width, &height, &x, &y) == FAILURE) {
10649 return;
10650 }
10651
10652 intern = Z_IMAGICK_P(getThis());
10653 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10654 return;
10655
10656 status = MagickSpliceImage(intern->magick_wand, width, height, x, y);
10657
10658 /* No magick is going to happen */
10659 if (status == MagickFalse) {
10660 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to splice image" TSRMLS_CC);
10661 return;
10662 }
10663
10664 RETURN_TRUE;
10665 }
10666 /* }}} */
10667
10668 /* {{{ proto Imagick Imagick::steganoImage(Imagick watermark_wand, int offset)
10669 Hides a digital watermark within the image. Recover the hidden watermark later to prove that the authenticity of an image. Offset defines the start position within the image to hide the watermark.
10670 */
10671 PHP_METHOD(Imagick, steganoImage)
10672 {
10673 zval *objvar;
10674 php_imagick_object *intern, *intern_second, *intern_return;
10675 im_long offset;
10676 MagickWand *tmp_wand;
10677
10678 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol", &objvar, php_imagick_sc_entry, &offset) == FAILURE) {
10679 return;
10680 }
10681
10682 intern = Z_IMAGICK_P(getThis());
10683 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10684 return;
10685
10686 intern_second = Z_IMAGICK_P(objvar);
10687 if (php_imagick_ensure_not_empty (intern_second->magick_wand) == 0)
10688 return;
10689
10690 tmp_wand = MagickSteganoImage(intern->magick_wand, intern_second->magick_wand, offset);
10691
10692 if (!tmp_wand) {
10693 php_imagick_convert_imagick_exception(intern->magick_wand, "Stegano image failed" TSRMLS_CC);
10694 return;
10695 }
10696
10697 object_init_ex(return_value, php_imagick_sc_entry);
10698 intern_return = Z_IMAGICK_P(return_value);
10699 php_imagick_replace_magickwand(intern_return, tmp_wand);
10700 return;
10701 }
10702 /* }}} */
10703
10704 /* {{{ proto Imagick Imagick::clone()
10705 Makes an exact copy of the Imagick object.
10706 */
10707 PHP_METHOD(Imagick, clone)
10708 {
10709 php_imagick_object *intern, *intern_return;
10710 MagickWand *tmp_wand;
10711
10712 if (zend_parse_parameters_none() == FAILURE) {
10713 return;
10714 }
10715
10716 IMAGICK_METHOD_DEPRECATED("Imagick", "clone");
10717 intern = Z_IMAGICK_P(getThis());
10718 tmp_wand = CloneMagickWand(intern->magick_wand);
10719
10720 if (tmp_wand == NULL) {
10721 php_imagick_convert_imagick_exception(intern->magick_wand, "Cloning Imagick object failed" TSRMLS_CC);
10722 return;
10723 }
10724
10725 object_init_ex(return_value, php_imagick_sc_entry);
10726 intern_return = Z_IMAGICK_P(return_value);
10727 php_imagick_replace_magickwand(intern_return, tmp_wand);
10728 return;
10729 }
10730 /* }}} */
10731
10732 /* {{{ proto bool Imagick::rotateImage(ImagickPixel background, float degrees)
10733 Rotates an image the specified number of degrees. Empty triangles left over from rotating the image are filled with the background color.
10734 */
10735 PHP_METHOD(Imagick, rotateImage)
10736 {
10737 zval *param;
10738 php_imagick_object *intern;
10739 double degrees;
10740 MagickBooleanType status;
10741 PixelWand *color_wand;
10742 zend_bool allocated;
10743
10744 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zd", ¶m, °rees) == FAILURE) {
10745 return;
10746 }
10747
10748 intern = Z_IMAGICK_P(getThis());
10749 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10750 return;
10751
10752 color_wand = php_imagick_zval_to_pixelwand (param, IMAGICK_CLASS, &allocated TSRMLS_CC);
10753 if (!color_wand)
10754 return;
10755
10756 status = MagickRotateImage(intern->magick_wand, color_wand, degrees);
10757
10758 if (allocated)
10759 color_wand = DestroyPixelWand (color_wand);
10760
10761 /* No magick is going to happen */
10762 if (status == MagickFalse) {
10763 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to rotate image" TSRMLS_CC);
10764 return;
10765 }
10766
10767 RETURN_TRUE;
10768 }
10769 /* }}} */
10770
10771 /* {{{ proto bool Imagick::sampleImage(int columns, int rows)
10772 Scales an image to the desired dimensions with pixel sampling. Unlike other scaling methods, this method does not introduce any additional color into the scaled image.
10773 */
10774 PHP_METHOD(Imagick, sampleImage)
10775 {
10776 php_imagick_object *intern;
10777 im_long columns, rows;
10778 MagickBooleanType status;
10779
10780 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &columns, &rows) == FAILURE) {
10781 return;
10782 }
10783
10784 intern = Z_IMAGICK_P(getThis());
10785 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10786 return;
10787
10788 status = MagickSampleImage(intern->magick_wand, columns, rows);
10789
10790 /* No magick is going to happen */
10791 if (status == MagickFalse) {
10792 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to sample image" TSRMLS_CC);
10793 return;
10794 }
10795
10796 RETURN_TRUE;
10797 }
10798 /* }}} */
10799
10800 /* {{{ proto bool Imagick::solarizeImage(float threshold)
10801 Applies a special effect to the image, similar to the effect achieved in a photo darkroom by selectively exposing areas of photo sensitive paper to light. Threshold ranges from 0 to QuantumRange and is a measure of the extent of the solarization.
10802 */
10803 PHP_METHOD(Imagick, solarizeImage)
10804 {
10805 php_imagick_object *intern;
10806 MagickBooleanType status;
10807 im_long threshold;
10808
10809 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &threshold) == FAILURE) {
10810 return;
10811 }
10812
10813 intern = Z_IMAGICK_P(getThis());
10814 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10815 return;
10816
10817 status = MagickSolarizeImage(intern->magick_wand, threshold);
10818
10819 /* No magick is going to happen */
10820 if (status == MagickFalse)
10821 {
10822 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to solarize image" TSRMLS_CC);
10823 return;
10824 }
10825
10826 RETURN_TRUE;
10827 }
10828 /* }}} */
10829
10830 /* {{{ proto bool Imagick::shadowImage(float opacity, float sigma, int x, int y)
10831 Simulates an image shadow.
10832 */
10833 PHP_METHOD(Imagick, shadowImage)
10834 {
10835 php_imagick_object *intern;
10836 MagickBooleanType status;
10837 double opacity, sigma;
10838 long x, y;
10839
10840 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddll", &opacity, &sigma, &x, &y) == FAILURE) {
10841 return;
10842 }
10843
10844 intern = Z_IMAGICK_P(getThis());
10845 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10846 return;
10847
10848 status = MagickShadowImage(intern->magick_wand, opacity, sigma, x, y);
10849
10850 /* No magick is going to happen */
10851 if (status == MagickFalse) {
10852 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to shadow image" TSRMLS_CC);
10853 return;
10854 }
10855
10856 RETURN_TRUE;
10857 }
10858 /* }}} */
10859
10860 /* {{{ proto bool Imagick::motionBlurImage(float radius, float sigma, float angle[, int CHANNEL])
10861 Simulates motion blur. We convolve the image with a Gaussian operator of the given radius and standard deviation (sigma). For reasonable results, radius should be larger than sigma. Use a radius of 0 and MotionBlurImage() selects a suitable radius for you. Angle gives the angle of the blurring motion.
10862 */
10863 PHP_METHOD(Imagick, motionBlurImage)
10864 {
10865 php_imagick_object *intern;
10866 MagickBooleanType status;
10867 double radius, sigma, angle;
10868 im_long channel = IM_DEFAULT_CHANNEL;
10869
10870 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd|l", &radius, &sigma, &angle, &channel) == FAILURE) {
10871 return;
10872 }
10873
10874 intern = Z_IMAGICK_P(getThis());
10875 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10876 return;
10877
10878 #if MagickLibVersion > 0x643
10879 status = MagickMotionBlurImageChannel(intern->magick_wand, channel, radius, sigma, angle);
10880 #else
10881 status = MagickMotionBlurImage(intern->magick_wand, radius, sigma, angle);
10882 #endif
10883
10884 /* No magick is going to happen */
10885 if (status == MagickFalse) {
10886 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to motion blur image" TSRMLS_CC);
10887 return;
10888 }
10889
10890 RETURN_TRUE;
10891
10892
10893 }
10894 /* }}} */
10895
10896 #if MagickLibVersion < 0x700
10897 #if !defined(MAGICKCORE_EXCLUDE_DEPRECATED)
10898 /* {{{ proto Imagick Imagick::mosaicImages()
10899 Inlays an image sequence to form a single coherent picture. It returns a wand with each image in the sequence composited at the location defined by the page offset of the image.
10900 */
10901 PHP_METHOD(Imagick, mosaicImages)
10902 {
10903 MagickWand *tmp_wand = NULL;
10904 php_imagick_object *intern, *intern_return;
10905
10906 IMAGICK_METHOD_DEPRECATED ("Imagick", "mosaicImages");
10907
10908 if (zend_parse_parameters_none() == FAILURE) {
10909 return;
10910 }
10911
10912 intern = Z_IMAGICK_P(getThis());
10913 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10914 return;
10915
10916 /* TODO: should this be here? */
10917 MagickSetFirstIterator(intern->magick_wand);
10918 tmp_wand = MagickMosaicImages(intern->magick_wand);
10919
10920 if (!tmp_wand) {
10921 php_imagick_convert_imagick_exception(intern->magick_wand, "Mosaic image failed" TSRMLS_CC);
10922 return;
10923 }
10924
10925 object_init_ex(return_value, php_imagick_sc_entry);
10926 intern_return = Z_IMAGICK_P(return_value);
10927 php_imagick_replace_magickwand(intern_return, tmp_wand);
10928
10929 return;
10930
10931 }
10932 /* }}} */
10933 #endif
10934 #endif
10935 /* {{{ proto Imagick Imagick::morphImages(int number_frames)
10936 Method morphs a set of images. Both the image pixels and size are linearly interpolated to give the appearance of a meta-morphosis from one image to the next.
10937 */
10938 PHP_METHOD(Imagick, morphImages)
10939 {
10940 MagickWand *tmp_wand;
10941 php_imagick_object *intern, *intern_return;
10942 im_long frames;
10943
10944 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &frames) == FAILURE) {
10945 return;
10946 }
10947
10948 intern = Z_IMAGICK_P(getThis());
10949 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10950 return;
10951
10952 tmp_wand = MagickMorphImages(intern->magick_wand, frames);
10953
10954 if (!tmp_wand) {
10955 php_imagick_convert_imagick_exception(intern->magick_wand, "Morphing images failed" TSRMLS_CC);
10956 return;
10957 }
10958
10959 object_init_ex(return_value, php_imagick_sc_entry);
10960 intern_return = Z_IMAGICK_P(return_value);
10961 php_imagick_replace_magickwand(intern_return, tmp_wand);
10962
10963 return;
10964
10965 }
10966 /* }}} */
10967
10968 /* {{{ proto bool Imagick::minifyImage()
10969 Is a convenience method that scales an image proportionally to one-half its original size
10970 */
10971 PHP_METHOD(Imagick, minifyImage)
10972 {
10973 php_imagick_object *intern;
10974 MagickBooleanType status;
10975
10976 if (zend_parse_parameters_none() == FAILURE) {
10977 return;
10978 }
10979
10980 intern = Z_IMAGICK_P(getThis());
10981 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
10982 return;
10983
10984 status = MagickMinifyImage(intern->magick_wand);
10985
10986 /* No magick is going to happen */
10987 if (status == MagickFalse) {
10988 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to minify image" TSRMLS_CC);
10989 return;
10990 }
10991
10992 RETURN_TRUE;
10993
10994 }
10995 /* }}} */
10996
10997 /* {{{ proto bool Imagick::posterizeImage(int levels, bool dither)
10998 Reduces the image to a limited number of color level.
10999 */
11000 PHP_METHOD(Imagick, posterizeImage)
11001 {
11002 php_imagick_object *intern;
11003 MagickBooleanType status;
11004 im_long levels;
11005 zend_bool dither;
11006
11007 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lb", &levels, &dither) == FAILURE) {
11008 return;
11009 }
11010
11011 intern = Z_IMAGICK_P(getThis());
11012 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
11013 return;
11014
11015 status = MagickPosterizeImage(intern->magick_wand, levels, dither);
11016
11017 /* No magick is going to happen */
11018 if (status == MagickFalse) {
11019 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to posterize image" TSRMLS_CC);
11020 return;
11021 }
11022
11023 RETURN_TRUE;
11024
11025 }
11026 /* }}} */
11027
11028 #if !defined(MAGICKCORE_EXCLUDE_DEPRECATED)
11029 #if MagickLibVersion < 0x700
11030 /* {{{ proto bool Imagick::radialBlurImage(float angle[, int channel])
11031 Radial blurs an image.
11032 */
11033 PHP_METHOD(Imagick, radialBlurImage)
11034 {
11035 php_imagick_object *intern;
11036 MagickBooleanType status;
11037 double angle;
11038 im_long channel = DefaultChannels;
11039
11040 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d|l", &angle, &channel) == FAILURE) {
11041 return;
11042 }
11043
11044 intern = Z_IMAGICK_P(getThis());
11045 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
11046 return;
11047
11048 status = MagickRadialBlurImageChannel(intern->magick_wand, channel, angle);
11049
11050 /* No magick is going to happen */
11051 if (status == MagickFalse) {
11052 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to radial blur image" TSRMLS_CC);
11053 return;
11054 }
11055
11056 RETURN_TRUE;
11057 }
11058 /* }}} */
11059 #endif
11060 #endif
11061
11062 /* {{{ proto bool Imagick::raiseImage(int width, int height, int x, int y, bool raise)
11063 Creates a simulated three-dimensional button-like effect by lightening and darkening the edges of the image. Members width and height of raise_info define the width of the vertical and horizontal edge of the effect.
11064 */
11065 PHP_METHOD(Imagick, raiseImage)
11066 {
11067 php_imagick_object *intern;
11068 MagickBooleanType status;
11069 im_long width, height, x, y;
11070 zend_bool raise;
11071
11072 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llllb", &width, &height, &x, &y, &raise) == FAILURE) {
11073 return;
11074 }
11075
11076 intern = Z_IMAGICK_P(getThis());
11077 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
11078 return;
11079
11080 status = MagickRaiseImage(intern->magick_wand, width, height, x, y, raise);
11081
11082 /* No magick is going to happen */
11083 if (status == MagickFalse) {
11084 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to raise image" TSRMLS_CC);
11085 return;
11086 }
11087
11088 RETURN_TRUE;
11089 }
11090 /* }}} */
11091
11092 /* {{{ proto bool Imagick::blackThresholdImage(ImagickPixel threshold)
11093 Is like MagickThresholdImage() but forces all pixels below the threshold into black while leaving all pixels above the threshold unchanged.
11094 */
11095 PHP_METHOD(Imagick, blackThresholdImage)
11096 {
11097 php_imagick_object *intern;
11098 zval *param;
11099 MagickBooleanType status;
11100 PixelWand *color_wand;
11101 zend_bool allocated;
11102
11103 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶m) == FAILURE) {
11104 return;
11105 }
11106
11107 intern = Z_IMAGICK_P(getThis());
11108 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
11109 return;
11110
11111 color_wand = php_imagick_zval_to_pixelwand (param, IMAGICK_CLASS, &allocated TSRMLS_CC);
11112 if (!color_wand)
11113 return;
11114
11115 status = MagickBlackThresholdImage(intern->magick_wand, color_wand);
11116
11117 if (allocated)
11118 color_wand = DestroyPixelWand (color_wand);
11119
11120 /* No magick is going to happen */
11121 if (status == MagickFalse) {
11122 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to black threshold image" TSRMLS_CC);
11123 return;
11124 }
11125
11126 RETURN_TRUE;
11127 }
11128 /* }}} */
11129
11130 /* {{{ proto bool Imagick::resampleImage(float x_resolution, float y_resolution, int filter, float blur)
11131 Resample image to desired resolution.
11132 */
11133 PHP_METHOD(Imagick, resampleImage)
11134 {
11135 double xRes, yRes, blur;
11136 im_long filter = 0;
11137 php_imagick_object *intern;
11138 MagickBooleanType status;
11139
11140 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddld", &xRes, &yRes, &filter, &blur) == FAILURE) {
11141 return;
11142 }
11143
11144 intern = Z_IMAGICK_P(getThis());
11145 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
11146 return;
11147
11148 #if MagickLibVersion >= 0x700
11149 //TODO - allow filter to be set.
11150 //TODO - figure out what to do about blur.
11151 status = MagickResampleImage(intern->magick_wand, xRes, yRes, LanczosFilter);
11152 #else
11153 status = MagickResampleImage(intern->magick_wand, xRes, yRes, filter, blur);
11154 #endif
11155
11156 /* No magick is going to happen */
11157 if (status == MagickFalse) {
11158 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to resample image" TSRMLS_CC);
11159 return;
11160 }
11161
11162 RETURN_TRUE;
11163 }
11164 /* }}} */
11165
11166 /* {{{ proto bool Imagick::resizeImage(int width, int height, int filter, float blur[, bool bestfit = false[, bool legacy]])
11167 Scales an image to the desired dimensions with one of these filters:
11168 If legacy is true, the calculations are done with the small rounding bug that existed in
11169 Imagick before 3.4.0. If false, the calculations should produce the same results as
11170 ImageMagick CLI does.
11171 */
11172 PHP_METHOD(Imagick, resizeImage)
11173 {
11174 double blur;
11175 im_long width, height, new_width, new_height, filter = 0;
11176 php_imagick_object *intern;
11177 MagickBooleanType status;
11178 zend_bool bestfit = 0;
11179 zend_bool legacy = 0;
11180
11181 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llld|bb", &width, &height, &filter, &blur, &bestfit, &legacy) == FAILURE) {
11182 return;
11183 }
11184
11185 intern = Z_IMAGICK_P(getThis());
11186 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
11187 return;
11188
11189 if (!php_imagick_thumbnail_dimensions(intern->magick_wand, bestfit, width, height, &new_width, &new_height, legacy)) {
11190 php_imagick_throw_exception(IMAGICK_CLASS, "Invalid image geometry" TSRMLS_CC);
11191 return;
11192 }
11193
11194 #if MagickLibVersion >= 0x700
11195 //TODO - remove blur from params
11196 status = MagickResizeImage(intern->magick_wand, new_width, new_height, filter);
11197 #else
11198 status = MagickResizeImage(intern->magick_wand, new_width, new_height, filter, blur);
11199 #endif
11200
11201 /* No magick is going to happen */
11202 if (status == MagickFalse) {
11203 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to resize image" TSRMLS_CC);
11204 return;
11205 }
11206
11207 RETURN_TRUE;
11208 }
11209 /* }}} */
11210
11211 /* {{{ proto bool Imagick::rollImage(int x, int y)
11212 Offsets an image as defined by x and y.
11213 */
11214 PHP_METHOD(Imagick, rollImage)
11215 {
11216 im_long x, y;
11217 php_imagick_object *intern;
11218 MagickBooleanType status;
11219
11220 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &x, &y) == FAILURE) {
11221 return;
11222 }
11223
11224 intern = Z_IMAGICK_P(getThis());
11225 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
11226 return;
11227 status = MagickRollImage(intern->magick_wand, x, y);
11228
11229 /* No magick is going to happen */
11230 if (status == MagickFalse) {
11231 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to roll image" TSRMLS_CC);
11232 return;
11233 }
11234
11235 RETURN_TRUE;
11236 }
11237 /* }}} */
11238
11239 /* {{{ proto Imagick Imagick::appendImages(bool stack)
11240 Append a set of images.
11241 */
11242 PHP_METHOD(Imagick, appendImages)
11243 {
11244 php_imagick_object *intern, *intern_return;
11245 MagickWand *tmp_wand;
11246 zend_bool stack;
11247
11248 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &stack) == FAILURE) {
11249 return;
11250 }
11251
11252 intern = Z_IMAGICK_P(getThis());
11253
11254 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
11255 return;
11256 tmp_wand = MagickAppendImages(intern->magick_wand, stack);
11257
11258 if (!tmp_wand) {
11259 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to append images" TSRMLS_CC);
11260 return;
11261 }
11262
11263 object_init_ex(return_value, php_imagick_sc_entry);
11264 intern_return = Z_IMAGICK_P(return_value);
11265 php_imagick_replace_magickwand(intern_return, tmp_wand);
11266 return;
11267 }
11268 /* }}} */
11269
11270 /* {{{ proto bool Imagick::whiteThresholdImage(ImagickPixel threshold)
11271 Is like ThresholdImage() but force all pixels above the threshold into white while leaving all pixels below the threshold unchanged.
11272 */
11273 PHP_METHOD(Imagick, whiteThresholdImage)
11274 {
11275 php_imagick_object *intern;
11276 zval *param;
11277 MagickBooleanType status;
11278 PixelWand *color_wand;
11279 zend_bool allocated;
11280
11281 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶m) == FAILURE) {
11282 return;
11283 }
11284
11285 intern = Z_IMAGICK_P(getThis());
11286 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
11287 return;
11288
11289 color_wand = php_imagick_zval_to_pixelwand (param, IMAGICK_CLASS, &allocated TSRMLS_CC);
11290 if (!color_wand)
11291 return;
11292
11293 status = MagickWhiteThresholdImage(intern->magick_wand, color_wand);
11294
11295 if (allocated)
11296 color_wand = DestroyPixelWand (color_wand);
11297
11298 /* No magick is going to happen */
11299 if (status == MagickFalse) {
11300 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to white threshold image" TSRMLS_CC);
11301 return;
11302 }
11303
11304 RETURN_TRUE;
11305 }
11306 /* }}} */
11307
11308 /* {{{ proto ImagickPixelIterator Imagick::getPixelIterator()
11309 Returns a MagickPixelIterator.
11310 */
11311 PHP_METHOD(Imagick, getPixelIterator)
11312 {
11313 PixelIterator *pixel_it;
11314 php_imagick_object *intern;
11315
11316 if (zend_parse_parameters_none() == FAILURE) {
11317 return;
11318 }
11319
11320 intern = Z_IMAGICK_P(getThis());
11321
11322 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
11323 return;
11324
11325 pixel_it = NewPixelIterator(intern->magick_wand);
11326
11327 if (!pixel_it) {
11328 php_imagick_throw_exception (IMAGICKPIXELITERATOR_CLASS, "Can not allocate ImagickPixelIterator" TSRMLS_CC);
11329 return;
11330 }
11331
11332 php_imagick_pixel_iterator_new (pixel_it, return_value TSRMLS_CC);
11333 return;
11334 }
11335 /* }}} */
11336
11337 /* {{{ proto ImagickPixelIterator Imagick::getPixelRegionIterator(long x, long y, long columns, long rows)
11338 Returns a subset of pixels in a MagickPixelIterator object.
11339 */
11340 PHP_METHOD(Imagick, getPixelRegionIterator)
11341 {
11342 PixelIterator *pixel_it;
11343 php_imagick_object *intern;
11344 im_long x, y, columns, rows;
11345
11346 /* Parse parameters given to function */
11347 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llll", &x, &y, &columns, &rows) == FAILURE) {
11348 return;
11349 }
11350
11351 intern = Z_IMAGICK_P(getThis());
11352
11353 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
11354 return;
11355
11356 pixel_it = NewPixelRegionIterator(intern->magick_wand, x, y, columns, rows);
11357
11358 if (!pixel_it) {
11359 php_imagick_throw_exception (IMAGICKPIXELITERATOR_CLASS, "Can not allocate ImagickPixelIterator" TSRMLS_CC);
11360 return;
11361 }
11362
11363 php_imagick_pixel_iterator_new (pixel_it, return_value TSRMLS_CC);
11364 return;
11365 }
11366 /* }}} */
11367
11368 /* {{{ proto int Imagick::getCompression()
11369 Gets the wand compression type.
11370 */
11371 PHP_METHOD(Imagick, getCompression)
11372 {
11373 php_imagick_object *intern;
11374
11375 if (zend_parse_parameters_none() == FAILURE) {
11376 return;
11377 }
11378
11379 intern = Z_IMAGICK_P(getThis());
11380 RETVAL_LONG(MagickGetCompression(intern->magick_wand));
11381 }
11382 /* }}} */
11383
11384 /* {{{ proto int Imagick::getCompressionQuality()
11385 Gets the wand compression quality.
11386 */
11387 PHP_METHOD(Imagick, getCompressionQuality)
11388 {
11389 php_imagick_object *intern;
11390
11391 if (zend_parse_parameters_none() == FAILURE) {
11392 return;
11393 }
11394
11395 intern = Z_IMAGICK_P(getThis());
11396 RETVAL_LONG(MagickGetCompressionQuality(intern->magick_wand));
11397 }
11398 /* }}} */
11399
11400 /* {{{ proto string Imagick::getCopyright()
11401 Returns the ImageMagick API copyright as a string constant.
11402 */
11403 PHP_METHOD(Imagick, getCopyright)
11404 {
11405 char *copyright;
11406
11407 if (zend_parse_parameters_none() == FAILURE) {
11408 return;
11409 }
11410
11411 copyright = (char *)MagickGetCopyright();
11412 IM_ZVAL_STRING(return_value, copyright);
11413 return;
11414 }
11415 /* }}} */
11416
11417
11418 /* {{{ proto string Imagick::getConfigureOptions()
11419 Returns any ImageMagick configure options that match the specified pattern (e.g. "*" for all). Options include NAME, VERSION, LIB_VERSION, etc.
11420 */
11421 PHP_METHOD(Imagick, getConfigureOptions)
11422 {
11423 size_t number_options;
11424
11425 char *pattern = "*";
11426 IM_LEN_TYPE pattern_len;
11427 char **result;
11428 char *option_value;
11429 unsigned int i;
11430
11431 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &pattern, &pattern_len) == FAILURE) {
11432 return;
11433 }
11434
11435 result = MagickQueryConfigureOptions(pattern, &number_options);
11436
11437 array_init(return_value);
11438
11439 for (i=0; i<number_options; i++) {
11440 option_value = MagickQueryConfigureOption(result[i]);
11441 IM_add_assoc_string(return_value, result[i], option_value);
11442 }
11443 }
11444 /* }}} */
11445
11446 #if MagickLibVersion > 0x660
11447 /* {{{ proto string Imagick::getFeatures()
11448 GetFeatures() returns the ImageMagick features that have been compiled into the runtime.
11449 */
11450 PHP_METHOD(Imagick, getFeatures)
11451 {
11452 const char *features;
11453
11454 if (zend_parse_parameters_none() == FAILURE) {
11455 return;
11456 }
11457
11458 features = GetMagickFeatures();
11459
11460 IM_ZVAL_STRING(return_value, features);
11461 }
11462 /* }}} */
11463 #endif
11464
11465
11466
11467 /* {{{ proto string Imagick::getFilename()
11468 Returns the filename associated with an image sequence.
11469 */
11470 PHP_METHOD(Imagick, getFilename)
11471 {
11472 php_imagick_object *intern;
11473 char *filename;
11474
11475 if (zend_parse_parameters_none() == FAILURE) {
11476 return;
11477 }
11478
11479 intern = Z_IMAGICK_P(getThis());
11480 filename = (char *)MagickGetFilename(intern->magick_wand);
11481
11482 if (filename) {
11483 IM_ZVAL_STRING(return_value, filename);
11484 IMAGICK_FREE_MAGICK_MEMORY(filename);
11485 }
11486 return;
11487 }
11488 /* }}} */
11489
11490 /* {{{ proto string Imagick::getFormat()
11491 Returns the format of the Imagick object.
11492 */
11493 PHP_METHOD(Imagick, getFormat)
11494 {
11495 php_imagick_object *intern;
11496 char *format;
11497
11498 if (zend_parse_parameters_none() == FAILURE) {
11499 return;
11500 }
11501
11502 intern = Z_IMAGICK_P(getThis());
11503 format = (char *)MagickGetFormat(intern->magick_wand);
11504
11505 if (format) {
11506 IM_ZVAL_STRING(return_value, format);
11507 IMAGICK_FREE_MAGICK_MEMORY(format);
11508 }
11509 return;
11510 }
11511 /* }}} */
11512
11513 /* {{{ proto string Imagick::getHomeURL()
11514 Returns the ImageMagick home URL.
11515 */
11516 PHP_METHOD(Imagick, getHomeURL)
11517 {
11518 char *home_url;
11519
11520 if (zend_parse_parameters_none() == FAILURE) {
11521 return;
11522 }
11523
11524 home_url = (char *)MagickGetHomeURL();
11525 if (home_url) {
11526 IM_ZVAL_STRING(return_value, home_url);
11527 IMAGICK_FREE_MAGICK_MEMORY(home_url);
11528 }
11529 return;
11530 }
11531 /* }}} */
11532
11533 /* {{{ proto int Imagick::getInterlaceScheme()
11534 Gets the wand interlace scheme.
11535 */
11536 PHP_METHOD(Imagick, getInterlaceScheme)
11537 {
11538 php_imagick_object *intern;
11539
11540 if (zend_parse_parameters_none() == FAILURE) {
11541 return;
11542 }
11543
11544 intern = Z_IMAGICK_P(getThis());
11545 RETVAL_LONG(MagickGetInterlaceScheme(intern->magick_wand));
11546 }
11547 /* }}} */
11548
11549 /* {{{ proto string Imagick::getOption(string key)
11550 Returns a value associated with a wand and the specified key. Use MagickRelinquishMemory() to free the value when you are finished with it.
11551 */
11552 PHP_METHOD(Imagick, getOption)
11553 {
11554 php_imagick_object *intern;
11555 char *key, *value;
11556 IM_LEN_TYPE key_len;
11557
11558 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) {
11559 return;
11560 }
11561
11562 intern = Z_IMAGICK_P(getThis());
11563
11564 value = MagickGetOption(intern->magick_wand, key);
11565
11566 if (value) {
11567 IM_ZVAL_STRING(return_value, value);
11568 IMAGICK_FREE_MAGICK_MEMORY(value);
11569 }
11570 return;
11571 }
11572 /* }}} */
11573
11574 /* {{{ proto string Imagick::getPackageName()
11575 Returns the ImageMagick package name as a string constant.
11576 */
11577 PHP_METHOD(Imagick, getPackageName)
11578 {
11579 char *package_name;
11580
11581 if (zend_parse_parameters_none() == FAILURE) {
11582 return;
11583 }
11584
11585 package_name = (char *)MagickGetPackageName();
11586 IM_ZVAL_STRING(return_value, package_name);
11587 return;
11588 }
11589 /* }}} */
11590
11591 /* {{{ proto array Imagick::getPage()
11592 Returns the page geometry associated with the Imagick object in an associative array with the keys "width", "height", "x", and "y".
11593 */
11594 PHP_METHOD(Imagick, getPage)
11595 {
11596 php_imagick_object *intern;
11597 MagickBooleanType status;
11598 size_t width, height;
11599 ssize_t x, y;
11600
11601 if (zend_parse_parameters_none() == FAILURE) {
11602 return;
11603 }
11604
11605 intern = Z_IMAGICK_P(getThis());
11606 status = MagickGetPage(intern->magick_wand, &width, &height, &x, &y);
11607
11608 if (status == MagickFalse) {
11609 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get page" TSRMLS_CC);
11610 return;
11611 }
11612
11613 array_init(return_value);
11614 add_assoc_long(return_value, "width", width);
11615 add_assoc_long(return_value, "height", height);
11616 add_assoc_long(return_value, "x", x);
11617 add_assoc_long(return_value, "y", y);
11618
11619 return;
11620 }
11621 /* }}} */
11622
11623 /* {{{ proto int Imagick::getHDRIEnabled()
11624 Returns true if Imagick was compiled against a HDRI verison of ImageMagick.
11625 */
11626 PHP_METHOD(Imagick, getHdriEnabled)
11627 {
11628 if (zend_parse_parameters_none() == FAILURE) {
11629 return;
11630 }
11631
11632 #if MAGICKCORE_HDRI_ENABLE
11633 RETURN_TRUE;
11634 #else
11635 RETURN_FALSE;
11636 #endif
11637 return;
11638 }
11639 /* }}} */
11640
11641
11642 /* {{{ proto int Imagick::getQuantum()
11643 Returns the ImageMagick quantum range as an integer.
11644 */
11645 PHP_METHOD(Imagick, getQuantum)
11646 {
11647 size_t range;
11648
11649 if (zend_parse_parameters_none() == FAILURE) {
11650 return;
11651 }
11652
11653 MagickGetQuantumRange(&range);
11654 ZVAL_LONG(return_value, range);
11655
11656 //#ifdef MAGICKCORE_HDRI_ENABLE
11657 // RETVAL_DOUBLE(color_value);
11658 //#else
11659 // RETVAL_LONG(color_value);
11660 //#endif
11661 return;
11662 }
11663 /* }}} */
11664
11665
11666 /* {{{ proto array Imagick::getQuantumDepth()
11667 Returns the ImageMagick quantum depth as a string constant.
11668 */
11669 PHP_METHOD(Imagick, getQuantumDepth)
11670 {
11671 const char *quantum_depth;
11672 size_t depth;
11673
11674 if (zend_parse_parameters_none() == FAILURE) {
11675 return;
11676 }
11677
11678 quantum_depth = MagickGetQuantumDepth(&depth);
11679
11680 array_init(return_value);
11681 add_assoc_long(return_value, "quantumDepthLong", depth);
11682 IM_add_assoc_string(return_value, "quantumDepthString", (char *)quantum_depth);
11683
11684 return;
11685 }
11686 /* }}} */
11687
11688 /* {{{ proto array Imagick::getQuantumRange()
11689 Returns the ImageMagick quantum range as a string constant.
11690 */
11691 PHP_METHOD(Imagick, getQuantumRange)
11692 {
11693 const char *quantum_range;
11694 size_t range;
11695
11696 if (zend_parse_parameters_none() == FAILURE) {
11697 return;
11698 }
11699
11700 quantum_range = MagickGetQuantumRange(&range);
11701 array_init(return_value);
11702
11703 add_assoc_long(return_value, "quantumRangeLong", range);
11704 IM_add_assoc_string(return_value, "quantumRangeString", (char *)quantum_range);
11705 return;
11706 }
11707 /* }}} */
11708
11709 /* {{{ proto string Imagick::getReleaseDate()
11710 Returns the ImageMagick release date as a string constant.
11711 */
11712 PHP_METHOD(Imagick, getReleaseDate)
11713 {
11714 char *release_date;
11715
11716 if (zend_parse_parameters_none() == FAILURE) {
11717 return;
11718 }
11719
11720 release_date = (char *)MagickGetReleaseDate();
11721 IM_ZVAL_STRING(return_value, release_date);
11722 return;
11723 }
11724 /* }}} */
11725
11726 /* {{{ proto int Imagick::getResource(int type)
11727 Returns the specified resource in megabytes.
11728 */
11729 PHP_METHOD(Imagick, getResource)
11730 {
11731 im_long resource_type;
11732
11733 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &resource_type) == FAILURE) {
11734 return;
11735 }
11736
11737 RETVAL_LONG(MagickGetResource(resource_type));
11738 }
11739 /* }}} */
11740
11741 /* {{{ proto Imagick Imagick::getResourceLimit(int type)
11742 Returns the specified resource limit in megabytes.
11743 */
11744 PHP_METHOD(Imagick, getResourceLimit)
11745 {
11746 im_long resource_type;
11747
11748 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &resource_type) == FAILURE) {
11749 return;
11750 }
11751
11752 RETVAL_DOUBLE(MagickGetResourceLimit(resource_type));
11753 }
11754 /* }}} */
11755
11756 /* {{{ proto array Imagick::getSamplingFactors()
11757 Gets the horizontal and vertical sampling factor.
11758 */
11759 PHP_METHOD(Imagick, getSamplingFactors)
11760 {
11761 php_imagick_object *intern;
11762 double *sampling_factors;
11763 unsigned long i;
11764 size_t number_factors = 0;
11765
11766 if (zend_parse_parameters_none() == FAILURE) {
11767 return;
11768 }
11769
11770 intern = Z_IMAGICK_P(getThis());
11771
11772 sampling_factors = (double *)MagickGetSamplingFactors(intern->magick_wand, &number_factors);
11773
11774 array_init(return_value);
11775
11776 for (i = 0 ; i < number_factors; i++) {
11777 add_next_index_double(return_value, sampling_factors[i]);
11778 }
11779
11780 MagickRelinquishMemory(sampling_factors);
11781
11782 return;
11783 }
11784 /* }}} */
11785
11786 /* {{{ proto array Imagick::getSize()
11787 Returns the size associated with the Imagick object as an array with the keys "columns" and "rows".
11788 */
11789 PHP_METHOD(Imagick, getSize)
11790 {
11791 php_imagick_object *intern;
11792 size_t columns, rows;
11793 MagickBooleanType status;
11794
11795 if (zend_parse_parameters_none() == FAILURE) {
11796 return;
11797 }
11798
11799 intern = Z_IMAGICK_P(getThis());
11800 status = MagickGetSize(intern->magick_wand, &columns, &rows);
11801
11802 if (status == MagickFalse) {
11803 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get size" TSRMLS_CC);
11804 return;
11805 }
11806
11807 array_init(return_value);
11808 add_assoc_long(return_value, "columns", columns);
11809 add_assoc_long(return_value, "rows", rows);
11810
11811 return;
11812 }
11813 /* }}} */
11814
11815 /* {{{ proto array Imagick::getVersion()
11816 Returns the ImageMagick API version as a string constant and as a number.
11817 */
11818 PHP_METHOD(Imagick, getVersion)
11819 {
11820 char *version_string;
11821 size_t version_number;
11822
11823 if (zend_parse_parameters_none() == FAILURE) {
11824 return;
11825 }
11826
11827 version_string = (char *)MagickGetVersion(&version_number);
11828 array_init(return_value);
11829
11830 add_assoc_long(return_value, "versionNumber", (long) version_number);
11831 IM_add_assoc_string(return_value, "versionString", version_string);
11832 return;
11833 }
11834 /* }}} */
11835
11836 /* {{{ proto bool Imagick::setBackgroundColor(ImagickPixel background)
11837 Sets the wand background color.
11838 */
11839 PHP_METHOD(Imagick, setBackgroundColor)
11840 {
11841 zval *param;
11842 php_imagick_object *intern;
11843 MagickBooleanType status;
11844 PixelWand *background_wand;
11845 zend_bool allocated = 0;
11846
11847 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶m) == FAILURE) {
11848 return;
11849 }
11850
11851 intern = Z_IMAGICK_P(getThis());
11852
11853 background_wand = php_imagick_zval_to_pixelwand (param, IMAGICK_CLASS, &allocated TSRMLS_CC);
11854 if (!background_wand)
11855 return;
11856
11857 status = MagickSetBackgroundColor(intern->magick_wand, background_wand);
11858
11859 if (allocated)
11860 background_wand = DestroyPixelWand (background_wand);
11861
11862 /* No magick is going to happen */
11863 if (status == MagickFalse) {
11864 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set background color" TSRMLS_CC);
11865 return;
11866 }
11867
11868 RETURN_TRUE;
11869 }
11870 /* }}} */
11871
11872 /* {{{ proto bool Imagick::setCompression(COMPRESSIONTYPE compression)
11873 Sets the wand compression type.
11874 */
11875 PHP_METHOD(Imagick, setCompression)
11876 {
11877 php_imagick_object *intern;
11878 im_long compression;
11879 MagickBooleanType status;
11880
11881 /* Parse parameters given to function */
11882 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &compression) == FAILURE) {
11883 return;
11884 }
11885
11886 intern = Z_IMAGICK_P(getThis());
11887 status = MagickSetCompression(intern->magick_wand, compression);
11888
11889 /* No magick is going to happen */
11890 if (status == MagickFalse) {
11891 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set compression" TSRMLS_CC);
11892 return;
11893 }
11894 RETURN_TRUE;
11895 }
11896 /* }}} */
11897
11898 /* {{{ proto bool Imagick::setCompressionQuality(int quality)
11899 Sets the wand compression quality.
11900 */
11901 PHP_METHOD(Imagick, setCompressionQuality)
11902 {
11903 php_imagick_object *intern;
11904 im_long quality;
11905 MagickBooleanType status;
11906
11907 /* Parse parameters given to function */
11908 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &quality) == FAILURE) {
11909 return;
11910 }
11911
11912 intern = Z_IMAGICK_P(getThis());
11913 status = MagickSetCompressionQuality(intern->magick_wand, quality);
11914
11915 /* No magick is going to happen */
11916 if (status == MagickFalse) {
11917 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set compression quality" TSRMLS_CC);
11918 return;
11919 }
11920 RETURN_TRUE;
11921 }
11922 /* }}} */
11923
11924 /* {{{ proto bool Imagick::setFilename(string filename)
11925 Sets the filename before you read or write an image file.
11926 */
11927 PHP_METHOD(Imagick, setFilename)
11928 {
11929 php_imagick_object *intern;
11930 char *filename;
11931 IM_LEN_TYPE filename_len;
11932 MagickBooleanType status;
11933
11934 /* Parse parameters given to function */
11935 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
11936 return;
11937 }
11938
11939 intern = Z_IMAGICK_P(getThis());
11940 status = MagickSetFilename(intern->magick_wand, filename);
11941
11942 /* No magick is going to happen */
11943 if (status == MagickFalse) {
11944 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set filename" TSRMLS_CC);
11945 return;
11946 }
11947
11948 RETURN_TRUE;
11949 }
11950 /* }}} */
11951
11952 /* {{{ proto bool Imagick::setFormat(string format)
11953 Sets the format of the Imagick object.
11954 */
11955 PHP_METHOD(Imagick, setFormat)
11956 {
11957 php_imagick_object *intern;
11958 char *format;
11959 IM_LEN_TYPE format_len;
11960 MagickBooleanType status;
11961
11962 /* Parse parameters given to function */
11963 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &format, &format_len) == FAILURE) {
11964 return;
11965 }
11966
11967 intern = Z_IMAGICK_P(getThis());
11968 status = MagickSetFormat(intern->magick_wand, format);
11969
11970 /* No magick is going to happen */
11971 if (status == MagickFalse) {
11972 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set format" TSRMLS_CC);
11973 return;
11974 }
11975
11976 RETURN_TRUE;
11977 }
11978 /* }}} */
11979
11980 /* {{{ proto bool Imagick::setInterlaceScheme(INTERLACETYPE interlace_scheme)
11981 Sets the image compression.
11982 */
11983 PHP_METHOD(Imagick, setInterlaceScheme)
11984 {
11985 php_imagick_object *intern;
11986 im_long schema;
11987 MagickBooleanType status;
11988
11989 /* Parse parameters given to function */
11990 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &schema) == FAILURE) {
11991 return;
11992 }
11993
11994 intern = Z_IMAGICK_P(getThis());
11995 status = MagickSetInterlaceScheme(intern->magick_wand, schema);
11996
11997 /* No magick is going to happen */
11998 if (status == MagickFalse) {
11999 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set interlace scheme" TSRMLS_CC);
12000 return;
12001 }
12002 RETURN_TRUE;
12003 }
12004 /* }}} */
12005
12006 /* {{{ proto bool Imagick::setOption(string key, string value)
12007 Associates one or options with the wand (.e.g MagickSetOption(wand,"jpeg:perserve","yes")).
12008 */
12009 PHP_METHOD(Imagick, setOption)
12010 {
12011 php_imagick_object *intern;
12012 MagickBooleanType status;
12013 char *key, *value;
12014 IM_LEN_TYPE key_len, value_len;
12015
12016 /* Parse parameters given to function */
12017 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &key, &key_len, &value, &value_len) == FAILURE) {
12018 return;
12019 }
12020
12021 intern = Z_IMAGICK_P(getThis());
12022 status = MagickSetOption(intern->magick_wand, key, value);
12023
12024 /* No magick is going to happen */
12025 if (status == MagickFalse) {
12026 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set option" TSRMLS_CC);
12027 return;
12028 }
12029 RETURN_TRUE;
12030 }
12031 /* }}} */
12032
12033 /* {{{ proto bool Imagick::setPage(int width, int height, int x, int y)
12034 Sets the page geometry of the Imagick object.
12035 */
12036 PHP_METHOD(Imagick, setPage)
12037 {
12038 php_imagick_object *intern;
12039 MagickBooleanType status;
12040 im_long width, height, x, y;
12041
12042 /* Parse parameters given to function */
12043 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llll", &width, &height, &x, &y) == FAILURE) {
12044 return;
12045 }
12046
12047 intern = Z_IMAGICK_P(getThis());
12048 status = MagickSetPage(intern->magick_wand, width, height, x, y);
12049
12050 /* No magick is going to happen */
12051 if (status == MagickFalse) {
12052 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set page" TSRMLS_CC);
12053 return;
12054 }
12055 RETURN_TRUE;
12056 }
12057 /* }}} */
12058
12059 PHP_METHOD(Imagick, setImageProgressMonitor)
12060 {
12061 char *filename;
12062 IM_LEN_TYPE filename_len;
12063 php_imagick_object *intern;
12064 php_imagick_rw_result_t rc;
12065
12066 if (!IMAGICK_G(progress_monitor)) {
12067 php_imagick_throw_exception(IMAGICK_CLASS, "Progress monitoring is disabled in ini-settings" TSRMLS_CC);
12068 return;
12069 }
12070
12071 /* Parse parameters given to function */
12072 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
12073 return;
12074 }
12075
12076 intern = Z_IMAGICK_P(getThis());
12077
12078 if ((rc = php_imagick_file_access_check (filename TSRMLS_CC)) != IMAGICK_RW_OK) {
12079 php_imagick_rw_fail_to_exception (intern->magick_wand, rc, filename TSRMLS_CC);
12080 return;
12081 }
12082
12083 if (intern->progress_monitor_name) {
12084 efree(intern->progress_monitor_name);
12085 }
12086
12087 intern->progress_monitor_name = estrdup(filename);
12088 MagickSetImageProgressMonitor(intern->magick_wand, php_imagick_progress_monitor, intern);
12089 RETURN_TRUE;
12090 }
12091
12092 /* {{{ proto bool Imagick::setProgressMonitor(callable callback)
12093 Set a callback that will be called during the processing of the Imagick image.
12094 */
12095 #if MagickLibVersion > 0x653
12096 PHP_METHOD(Imagick, setProgressMonitor)
12097 {
12098 zval *user_callback;
12099
12100 php_imagick_object *intern;
12101 php_imagick_callback *callback;
12102
12103 /* Parse parameters given to function */
12104 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &user_callback) == FAILURE) {
12105 RETURN_FALSE;
12106 }
12107
12108 // Check whether the callback is valid now, rather than failing later
12109 if (!user_callback || !zend_is_callable(user_callback, 0, NULL TSRMLS_CC)) {
12110 php_imagick_throw_exception(IMAGICK_CLASS, "First argument to setProgressMonitor is expected to be a valid callback" TSRMLS_CC);
12111 RETURN_FALSE;
12112 }
12113
12114 callback = (php_imagick_callback *) emalloc(sizeof(php_imagick_callback));
12115
12116 TSRMLS_SET_CTX(callback->thread_ctx);
12117 //We can't free the previous callback as we can't guarantee that
12118 //ImageMagick won't use it at some point. There is no 'unbind' function
12119 //for previously set 'MagickSetImageProgressMonitor'
12120 callback->previous_callback = IMAGICK_G(progress_callback);
12121
12122 //Add a ref and store the user's callback
12123 #if PHP_VERSION_ID >= 70000
12124 Z_TRY_ADDREF_P(user_callback);
12125 ZVAL_COPY_VALUE(&callback->user_callback, user_callback);
12126 #else
12127 Z_ADDREF_P(user_callback);
12128 callback->user_callback = user_callback;
12129 #endif
12130
12131 //The callback is now valid, store it in the global
12132 IMAGICK_G(progress_callback) = callback;
12133 intern = Z_IMAGICK_P(getThis());
12134
12135 MagickSetImageProgressMonitor(intern->magick_wand, php_imagick_progress_monitor_callable, callback);
12136 RETURN_TRUE;
12137 }
12138 #endif
12139
12140 /* {{{ proto bool Imagick::setResourceLimit(RESOURCETYPE type, int limit)
12141 Sets the limit for a particular resource in megabytes.
12142 */
12143 PHP_METHOD(Imagick, setResourceLimit)
12144 {
12145 MagickBooleanType status;
12146 im_long type;
12147 double limit;
12148
12149 /* Parse parameters given to function */
12150 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ld", &type, &limit) == FAILURE) {
12151 return;
12152 }
12153
12154 status = MagickSetResourceLimit(type, (MagickSizeType)limit);
12155
12156 /* No magick is going to happen */
12157 if (status == MagickFalse) {
12158 php_imagick_throw_exception(IMAGICK_CLASS, "Unable to set resource limit" TSRMLS_CC);
12159 return;
12160 }
12161 RETURN_TRUE;
12162 }
12163 /* }}} */
12164
12165 /* {{{ proto bool Imagick::setResolution(float x_resolution, float y_resolution)
12166 Sets the image resolution.
12167 */
12168 PHP_METHOD(Imagick, setResolution)
12169 {
12170 php_imagick_object *intern;
12171 MagickBooleanType status;
12172 double x_resolution, y_resolution;
12173
12174 /* Parse parameters given to function */
12175 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &x_resolution, &y_resolution) == FAILURE) {
12176 return;
12177 }
12178
12179 intern = Z_IMAGICK_P(getThis());
12180 status = MagickSetResolution(intern->magick_wand, x_resolution, y_resolution);
12181
12182 /* No magick is going to happen */
12183 if (status == MagickFalse) {
12184 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set resolution" TSRMLS_CC);
12185 return;
12186 }
12187 RETURN_TRUE;
12188 }
12189 /* }}} */
12190
12191 /* {{{ proto bool Imagick::setSamplingFactors(array factors)
12192 Sets the image sampling factors.
12193 */
12194 PHP_METHOD(Imagick, setSamplingFactors)
12195 {
12196 php_imagick_object *intern;
12197 MagickBooleanType status;
12198 zval *factors;
12199 double *double_array;
12200 im_long elements = 0;
12201
12202 /* Parse parameters given to function */
12203 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &factors) == FAILURE) {
12204 return;
12205 }
12206
12207 double_array = php_imagick_zval_to_double_array(factors, &elements TSRMLS_CC);
12208
12209 if (!double_array) {
12210 php_imagick_throw_exception(IMAGICK_CLASS, "Can't read array" TSRMLS_CC);
12211 return;
12212 }
12213
12214 intern = Z_IMAGICK_P(getThis());
12215
12216 status = MagickSetSamplingFactors(intern->magick_wand, elements, double_array);
12217 efree(double_array);
12218
12219 /* No magick is going to happen */
12220 if (status == MagickFalse) {
12221 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set sampling factors" TSRMLS_CC);
12222 return;
12223 }
12224 RETURN_TRUE;
12225 }
12226 /* }}} */
12227
12228 /* {{{ proto bool Imagick::setSize(int columns, int rows)
12229 Sets the size of the Imagick object. Set it before you read a raw image format such as RGB, GRAY, or CMYK.
12230 */
12231 PHP_METHOD(Imagick, setSize)
12232 {
12233 php_imagick_object *intern;
12234 im_long columns, rows;
12235 MagickBooleanType status;
12236
12237 /* Parse parameters given to function */
12238 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &columns, &rows) == FAILURE) {
12239 return;
12240 }
12241
12242 intern = Z_IMAGICK_P(getThis());
12243 status = MagickSetSize(intern->magick_wand, columns, rows);
12244
12245 /* No magick is going to happen */
12246 if (status == MagickFalse) {
12247 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set size" TSRMLS_CC);
12248 return;
12249 }
12250 RETURN_TRUE;
12251 }
12252 /* }}} */
12253
12254 /* {{{ proto bool Imagick::setType(IMAGETYPE image_type)
12255 Sets the image type attribute.
12256 */
12257 PHP_METHOD(Imagick, setType)
12258 {
12259 php_imagick_object *intern;
12260 im_long type;
12261 MagickBooleanType status;
12262
12263 /* Parse parameters given to function */
12264 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &type) == FAILURE) {
12265 return;
12266 }
12267
12268 intern = Z_IMAGICK_P(getThis());
12269 status = MagickSetType(intern->magick_wand, type);
12270
12271 /* No magick is going to happen */
12272 if (status == MagickFalse) {
12273 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to set type" TSRMLS_CC);
12274 return;
12275 }
12276 RETURN_TRUE;
12277 }
12278 /* }}} */
12279
12280 #if MagickLibVersion >= 0x659
12281 /* {{{ proto bool Imagick::brightnessContrastImage(float brigthness, float contrast[, int channel])
12282 Change the brightness and/or contrast of an image. It converts the brightness and contrast parameters into slope and intercept and calls a polynomical function to apply to the image.
12283 */
12284 PHP_METHOD(Imagick, brightnessContrastImage)
12285 {
12286 php_imagick_object *intern;
12287 double brightness, contrast;
12288 MagickBooleanType status;
12289 im_long channel = IM_DEFAULT_CHANNEL;
12290
12291 /* Parse parameters given to function */
12292 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd|l", &brightness, &contrast, &channel) == FAILURE) {
12293 return;
12294 }
12295
12296 intern = Z_IMAGICK_P(getThis());
12297 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
12298 return;
12299
12300 status = MagickBrightnessContrastImageChannel(intern->magick_wand, channel, brightness, contrast);
12301
12302 /* No magick is going to happen */
12303 if (status == MagickFalse) {
12304 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to brightnesscontrastimage" TSRMLS_CC);
12305 return;
12306 }
12307
12308 RETURN_TRUE;
12309 }
12310 /* }}} */
12311 #endif
12312
12313
12314 #if MagickLibVersion > 0x661
12315
12316 static KernelInfo *php_imagick_getKernelInfo(const double *color_matrix, const size_t order)
12317 {
12318 KernelInfo *kernel_info;
12319
12320 #if MagickLibVersion >= 0x700
12321 ExceptionInfo *ex_info = NULL;
12322 //TODO - inspect exception info
12323 kernel_info=AcquireKernelInfo(NULL, ex_info);
12324 #else
12325 kernel_info=AcquireKernelInfo(NULL);
12326 #endif
12327 if (kernel_info == (KernelInfo *) NULL) {
12328 return NULL;
12329 }
12330
12331 kernel_info->width = order;
12332 kernel_info->height = order;
12333 #if MagickLibVersion >= 0x700
12334 {
12335 unsigned int i;
12336 kernel_info->values = (MagickRealType *)AcquireAlignedMemory(order, order*sizeof(MagickRealType));
12337 for (i=0 ; i<order*order ; i++) {
12338 kernel_info->values[i] = color_matrix[i];
12339 }
12340 }
12341 #else
12342 kernel_info->values = (double *)AcquireAlignedMemory(order, order*sizeof(double));
12343 memcpy(kernel_info->values, color_matrix, order * order * sizeof(double));
12344 #endif
12345
12346 return kernel_info;
12347 }
12348
12349
12350 /* {{{ proto bool Imagick::colorMatrixImage(array kernel)
12351 apply color transformation to an image. The method permits saturation changes, hue rotation, luminance to alpha, and various other effects. Although variable-sized transformation matrices can be used, typically one uses a 5x5 matrix for an RGBA image and a 6x6 for CMYKA (or RGBA with offsets). The matrix is similar to those used by Adobe Flash except offsets are in column 6 rather than 5 (in support of CMYKA images) and offsets are normalized (divide Flash offset by 255).
12352 */
12353 PHP_METHOD(Imagick, colorMatrixImage)
12354 {
12355 php_imagick_object *intern;
12356 MagickBooleanType status;
12357 zval *color_matrix_array;
12358 double *colors;
12359 size_t order = 0;
12360 im_long num_elements = 0;
12361 KernelInfo *kernel_color_matrix;
12362
12363 /* Parse parameters given to function */
12364 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &color_matrix_array) == FAILURE) {
12365 return;
12366 }
12367
12368 intern = Z_IMAGICK_P(getThis());
12369 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
12370 return;
12371
12372 colors = php_imagick_zval_to_double_array(color_matrix_array, &num_elements TSRMLS_CC);
12373
12374 if (!colors) {
12375 php_imagick_throw_exception(IMAGICK_CLASS, "Unable to read color matrix array" TSRMLS_CC);
12376 return;
12377 }
12378
12379 if (num_elements == 25) {
12380 order = 5;
12381 }
12382 else if (num_elements == 36) {
12383 order = 6;
12384 }
12385 else {
12386 efree(colors);
12387 php_imagick_throw_exception(IMAGICK_CLASS, "Color matrix array must be 5x5 or 6x6" TSRMLS_CC);
12388 return;
12389 }
12390
12391 kernel_color_matrix = php_imagick_getKernelInfo(colors, order);
12392
12393 //TODO - add check that matrix is 5x5 or 6x6?
12394 status = MagickColorMatrixImage(intern->magick_wand, kernel_color_matrix);
12395
12396 //Free the memory
12397 #if MagickLibVersion >= 0x700
12398 kernel_color_matrix->values = (MagickRealType *) NULL;
12399 #else
12400 kernel_color_matrix->values = (double *) NULL;
12401 #endif
12402 kernel_color_matrix = DestroyKernelInfo(kernel_color_matrix);
12403 efree(colors);
12404
12405
12406 /* No magick is going to happen */
12407 if (status == MagickFalse) {
12408 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to colormatriximage" TSRMLS_CC);
12409 return;
12410 }
12411
12412 RETURN_TRUE;
12413 }
12414 /* }}} */
12415 #endif
12416
12417 /* {{{ proto bool Imagick::selectiveBlurImage(float radius, float sigma, float threshold[, int channel])
12418 Selectively blur an image within a contrast threshold. It is similar to the unsharpen mask that sharpens everything with contrast above a certain threshold.
12419 */
12420 PHP_METHOD(Imagick, selectiveBlurImage)
12421 {
12422 php_imagick_object *intern;
12423 double brightness, contrast, threshold;
12424 MagickBooleanType status;
12425 im_long channel = IM_DEFAULT_CHANNEL;
12426
12427 /* Parse parameters given to function */
12428 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd|l", &brightness, &contrast, &threshold, &channel) == FAILURE) {
12429 return;
12430 }
12431
12432 intern = Z_IMAGICK_P(getThis());
12433 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
12434 return;
12435
12436 status = MagickSelectiveBlurImageChannel(intern->magick_wand, channel, brightness, contrast, threshold);
12437
12438 /* No magick is going to happen */
12439 if (status == MagickFalse) {
12440 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to selectiveblurimage" TSRMLS_CC);
12441 return;
12442 }
12443
12444 RETURN_TRUE;
12445 }
12446 /* }}} */
12447
12448
12449
12450 #if MagickLibVersion >= 0x689
12451 /* {{{ proto bool Imagick::rotationalblurimage(float angle[, int channel])
12452 Rotational blurs an image.
12453 */
12454 PHP_METHOD(Imagick, rotationalBlurImage)
12455 {
12456 php_imagick_object *intern;
12457 MagickBooleanType status;
12458 double angle;
12459 im_long channel = IM_DEFAULT_CHANNEL;
12460
12461 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d|l", &angle, &channel) == FAILURE) {
12462 return;
12463 }
12464
12465 intern = Z_IMAGICK_P(getThis());
12466 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
12467 return;
12468
12469 status = MagickRotationalBlurImageChannel(intern->magick_wand, channel, angle);
12470
12471 /* No magick is going to happen */
12472 if (status == MagickFalse) {
12473 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to rotational blur image" TSRMLS_CC);
12474 return;
12475 }
12476
12477 RETURN_TRUE;
12478 }
12479 /* }}} */
12480 #endif
12481
12482 #if MagickLibVersion >= 0x683
12483
12484 //Technically, this version is available in 0x682. However there was an incompatible
12485 //change to the methods signature in a bug release. So only expose it for stable
12486 //versions.
12487 //
12488 //6.8.2.8 - MagickStatisticImage ( MagickWand* p1, enum ChannelType const p2, enum StatisticType const p3, size_t const p4, size_t const p5 ) (6)
12489 //6.8.2.9 - MagickStatisticImage ( MagickWand* p1, enum StatisticType const p2, size_t const p3, size_t const p4 )
12490
12491
12492 /* {{{ proto bool Imagick::statisticImage(int type, int width, int height[, int channel] )
12493 Replace each pixel with corresponding statistic from the neighborhood of the specified width and height.
12494 */
12495 PHP_METHOD(Imagick, statisticImage)
12496 {
12497 php_imagick_object *intern;
12498 MagickBooleanType status;
12499 im_long type;
12500 im_long width, height;
12501 im_long channel = IM_DEFAULT_CHANNEL;
12502
12503 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll|l", &type, &width, &height, &channel) == FAILURE) {
12504 return;
12505 }
12506
12507 intern = Z_IMAGICK_P(getThis());
12508 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
12509 return;
12510
12511 status = MagickStatisticImageChannel(intern->magick_wand, channel, type, width, height);
12512
12513 /* No magick is going to happen */
12514 if (status == MagickFalse) {
12515 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to statisticImage" TSRMLS_CC);
12516 return;
12517 }
12518
12519 RETURN_TRUE;
12520 }
12521 /* }}} */
12522
12523 #endif
12524
12525 #if MagickLibVersion >= 0x652
12526 /* {{{ proto Imagick Imagick::subimageMatch(Imagick subimage[, array &$bestMatch[, float &similarity[, float similarity_threshold = 0[, int metric = ]]]])
12527 Searches for a subimage in the current image and returns a similarity image such that an exact match location is completely white and if none of the pixels match, black, otherwise some gray level in-between.
12528 You can also pass in the optional parameters bestMatch and similarity. After calling the function similarity will be
12529 set to the 'score' of the similarity between the subimage and the matching position in the larger image, bestMatch will
12530 contain an associative array with elements x, y, width, height that describe the matching region.
12531 */
12532 PHP_METHOD(Imagick, subimageMatch)
12533 {
12534 php_imagick_object *intern;
12535 RectangleInfo best_match_offset;
12536 double similarity;
12537 double similarity_threshold = 0.0;
12538
12539 zval *reference_obj;
12540 php_imagick_object *reference_intern;
12541 php_imagick_object *intern_return;
12542 zval *z_similarity = NULL;
12543 zval *z_best_match_offset = NULL;
12544
12545 //http://devzone.zend.com/317/extension-writing-part-ii-parameters-arrays-and-zvals/
12546 MagickWand *new_wand;
12547
12548
12549 #if MagickLibVersion >= 0x700
12550 im_long metric = RootMeanSquaredErrorMetric;
12551 #else
12552 im_long metric = 0;
12553 #endif
12554
12555 #if PHP_VERSION_ID >= 70000
12556 char *param_string = "O|z/z/dl";
12557 #else
12558 char *param_string = "O|zzdl";
12559
12560 #endif
12561
12562 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, param_string, &reference_obj, php_imagick_sc_entry, &z_best_match_offset, &z_similarity, &similarity_threshold, &metric) == FAILURE) {
12563 return;
12564 }
12565 reference_intern = Z_IMAGICK_P(reference_obj);
12566
12567 intern = Z_IMAGICK_P(getThis());
12568 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
12569 return;
12570
12571 #if MagickLibVersion >= 0x700
12572 new_wand = MagickSimilarityImage(intern->magick_wand, reference_intern->magick_wand,
12573 metric, similarity_threshold,
12574 &best_match_offset, &similarity);
12575 #else
12576 new_wand = MagickSimilarityImage(intern->magick_wand, reference_intern->magick_wand, &best_match_offset, &similarity);
12577 #endif
12578
12579 if (new_wand == NULL) {
12580 php_imagick_convert_imagick_exception(intern->magick_wand, "subimagematch failed" TSRMLS_CC);
12581 return;
12582 }
12583
12584 if (z_similarity) {
12585 ZVAL_DOUBLE(z_similarity, similarity);
12586 }
12587
12588 if (z_best_match_offset) {
12589 array_init(z_best_match_offset);
12590 add_assoc_long(z_best_match_offset, "x", best_match_offset.x);
12591 add_assoc_long(z_best_match_offset, "y", best_match_offset.y);
12592 add_assoc_long(z_best_match_offset, "width", best_match_offset.width);
12593 add_assoc_long(z_best_match_offset, "height", best_match_offset.height);
12594 }
12595
12596 object_init_ex(return_value, php_imagick_sc_entry);
12597 intern_return = Z_IMAGICK_P(return_value);
12598 php_imagick_replace_magickwand(intern_return, new_wand);
12599
12600 return;
12601 }
12602 /* }}} */
12603 #endif
12604
12605
12606 /* {{{ proto bool Imagick::setRegistry(string key, string value)
12607 Sets the ImageMagick registry entry named key to value. This is most
12608 useful for setting "temporary-path" which controls where ImageMagick
12609 creates temporary images e.g. while processing PDFs.
12610 */
12611 PHP_METHOD(Imagick, setRegistry)
12612 {
12613 MagickBooleanType status;
12614 char *key, *value;
12615 IM_LEN_TYPE key_len, value_len;
12616
12617 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &key, &key_len, &value, &value_len) == FAILURE) {
12618 return;
12619 }
12620
12621 status = SetImageRegistry(StringRegistryType, key, value, NULL);
12622
12623 /* No magick is going to happen */
12624 if (status == MagickFalse) {
12625 RETURN_FALSE;
12626 }
12627
12628 RETURN_TRUE;
12629 }
12630 /* }}} */
12631
12632
12633 /* {{{ proto string|false Imagick::getRegistry(string key)
12634 Get the StringRegistry entry for the named key or false if not set.
12635 */
12636 PHP_METHOD(Imagick, getRegistry)
12637 {
12638 char *key, *value;
12639 IM_LEN_TYPE key_len;
12640 ExceptionInfo *ex_info;
12641
12642 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) {
12643 return;
12644 }
12645
12646 ex_info = AcquireExceptionInfo();
12647
12648 value = GetImageRegistry(StringRegistryType, key, ex_info);
12649
12650 if (ex_info->severity != 0) {
12651 zend_throw_exception_ex(php_imagick_exception_class_entry, 1 TSRMLS_CC, "Imagick::getRegistry exception (%s) ", ex_info->reason);
12652 ex_info = DestroyExceptionInfo(ex_info);
12653 return;
12654 }
12655
12656 ex_info = DestroyExceptionInfo(ex_info);
12657
12658 if (value != NULL) {
12659 IM_ZVAL_STRING(return_value, value);
12660 IMAGICK_FREE_MAGICK_MEMORY(value);
12661 return;
12662 }
12663
12664 RETURN_FALSE;
12665 }
12666 /* }}} */
12667
12668
12669 /* {{{ proto array Imagick::listRegistry()
12670 List all the registry settings calls GetImageRegistry. returns an array of all the key/value pairs in the registry
12671 */
12672 PHP_METHOD(Imagick, listRegistry)
12673 {
12674 char *registry = NULL;
12675 char *value = NULL;
12676
12677 if (zend_parse_parameters_none() == FAILURE) {
12678 return;
12679 }
12680
12681 array_init(return_value);
12682
12683 ResetImageRegistryIterator();
12684 while ((registry = GetNextImageRegistry())) {
12685 value = GetImageRegistry(StringRegistryType, registry, NULL);
12686 //should this be add_assoc_string(return_value, estrdup(registry), value, 1);
12687 IM_add_assoc_string(return_value, registry, value);
12688 IMAGICK_FREE_MAGICK_MEMORY(value);
12689 }
12690
12691 return;
12692 }
12693 /* }}} */
12694
12695 #if MagickLibVersion >= 0x680
12696 /* {{{ proto bool Imagick::morphology(int morphologyMethod, int iterations, kernel, [int CHANNEL] )
12697 Applies a user supplied kernel to the image according to the given morphology method.
12698 iterations - A value of -1 means loop until no change found. How this is applied may depend on the morphology method. Typically this is a value of 1.
12699 */
12700 PHP_METHOD(Imagick, morphology)
12701 {
12702 zval *objvar;
12703 php_imagick_object *intern;
12704 php_imagickkernel_object *kernel;
12705 im_long morphologyMethod, iterations;
12706 MagickBooleanType status;
12707 im_long channel = IM_DEFAULT_CHANNEL;
12708
12709 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llO|l", &morphologyMethod, &iterations, &objvar, php_imagickkernel_sc_entry, &channel) == FAILURE) {
12710 return;
12711 }
12712
12713 intern = Z_IMAGICK_P(getThis());
12714 kernel = Z_IMAGICKKERNEL_P(objvar);
12715 IMAGICK_KERNEL_NOT_NULL_EMPTY(kernel);
12716
12717 status = MagickMorphologyImageChannel(
12718 intern->magick_wand,
12719 channel,
12720 morphologyMethod,
12721 iterations,
12722 kernel->kernel_info
12723 );
12724
12725 // No magick is going to happen
12726 if (status == MagickFalse) {
12727 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to morphology image" TSRMLS_CC);
12728 return;
12729 }
12730
12731 RETURN_TRUE;
12732 }
12733 /* }}} */
12734 #endif //#if MagickLibVersion >= 0x680
12735
12736 #ifdef IMAGICK_WITH_KERNEL
12737 #if MagickLibVersion < 0x700
12738 /* {{{ proto bool Imagick::filter(ImagickKernel kernel, [int CHANNEL] )
12739 Applies a custom convolution kernel to the image.
12740 */
12741 PHP_METHOD(Imagick, filter)
12742 {
12743 zval *objvar;
12744 php_imagick_object *intern;
12745 php_imagickkernel_object *kernel;
12746 MagickBooleanType status;
12747 ChannelType channel = UndefinedChannel;
12748
12749 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|l", &objvar, php_imagickkernel_sc_entry, &channel) == FAILURE) {
12750 return;
12751 }
12752
12753 intern = Z_IMAGICK_P(getThis());
12754 kernel = Z_IMAGICKKERNEL_P(objvar);
12755
12756 if ((kernel->kernel_info->width % 2) != 1) {
12757 php_imagick_convert_imagick_exception(intern->magick_wand, "Only odd-sized, square kernels can be applied as a filter." TSRMLS_CC);
12758 return;
12759 }
12760
12761 if (kernel->kernel_info->width != kernel->kernel_info->height) {
12762 php_imagick_convert_imagick_exception(intern->magick_wand, "Only odd-sized, square kernels can be applied as a filter." TSRMLS_CC);
12763 return;
12764 }
12765
12766 if (channel == 0) {
12767 status = MagickFilterImage(intern->magick_wand, kernel->kernel_info);
12768 }
12769 else {
12770 status = MagickFilterImageChannel(intern->magick_wand, channel, kernel->kernel_info);
12771 }
12772
12773 // No magick is going to happen
12774 if (status == MagickFalse) {
12775 php_imagick_convert_imagick_exception(intern->magick_wand, "Failed to filter image" TSRMLS_CC);
12776 return;
12777 }
12778
12779 RETURN_TRUE;
12780 }
12781 /* }}} */
12782 #endif //#if MagickLibVersion < 0x700
12783 #endif // #ifdef IMAGICK_WITH_KERNEL
12784
12785 /* {{{ proto int Imagick::setAntiAlias(bool antialias)
12786 Set whether antialiasing should be used for operations. On by default.
12787 */
12788 PHP_METHOD(Imagick, setAntialias)
12789 {
12790 php_imagick_object *intern;
12791 zend_bool antialias;
12792 MagickBooleanType status;
12793
12794 /* Parse parameters given to function */
12795 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &antialias) == FAILURE) {
12796 return;
12797 }
12798
12799 intern = Z_IMAGICK_P(getThis());
12800 status = MagickSetAntialias(intern->magick_wand, antialias);
12801
12802 if (status == MagickFalse) {
12803 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to setAntiAlias" TSRMLS_CC);
12804 return;
12805 }
12806
12807 RETURN_TRUE;
12808 }
12809 /* }}} */
12810
12811 /* {{{ proto bool Imagick::getAntiAlias()
12812 get whether antialiasing would be used for operations.
12813 */
12814 PHP_METHOD(Imagick, getAntialias)
12815 {
12816 php_imagick_object *intern;
12817 MagickBooleanType antialias;
12818
12819 if (zend_parse_parameters_none() == FAILURE) {
12820 return;
12821 }
12822
12823 intern = Z_IMAGICK_P(getThis());
12824 antialias = MagickGetAntialias(intern->magick_wand);
12825
12826 if (antialias == MagickTrue) {
12827 RETURN_TRUE;
12828 } else {
12829 RETURN_FALSE;
12830 }
12831 }
12832 /* }}} */
12833
12834 #if MagickLibVersion > 0x676
12835 /* {{{ proto bool Imagick::colorDecisionListImage(string color_correction_collection)
12836 Set whether antialiasing should be used for operations. On by default.
12837 */
12838 PHP_METHOD(Imagick, colorDecisionListImage)
12839 {
12840 php_imagick_object *intern;
12841 MagickBooleanType status;
12842
12843 char *color_correction_collection;
12844 IM_LEN_TYPE ccc_len;
12845
12846 /* Parse parameters given to function */
12847 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &color_correction_collection, &ccc_len) == FAILURE) {
12848 return;
12849 }
12850
12851 intern = Z_IMAGICK_P(getThis());
12852 status = MagickColorDecisionListImage(intern->magick_wand, color_correction_collection);
12853
12854 if (status == MagickFalse) {
12855 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to colorDecisionListImage" TSRMLS_CC);
12856 return;
12857 }
12858
12859 RETURN_TRUE;
12860 }
12861 /* }}} */
12862 #endif
12863
12864 #if MagickLibVersion >= 0x687
12865 /* {{{ proto Imagick Imagick::optimizeimagetransparency()
12866 Takes a frame optimized GIF animation, and compares the overlayed pixels against the disposal image resulting fr
12867 */
12868 PHP_METHOD(Imagick, optimizeImageTransparency)
12869 {
12870 php_imagick_object *intern;
12871 MagickBooleanType status;
12872
12873 if (zend_parse_parameters_none() == FAILURE) {
12874 return;
12875 }
12876
12877 intern = Z_IMAGICK_P(getThis());
12878 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
12879 return;
12880
12881 status = MagickOptimizeImageTransparency(intern->magick_wand);
12882
12883 /* No magick is going to happen */
12884 if (status == MagickFalse) {
12885 php_imagick_convert_imagick_exception(intern->magick_wand, "Optimize image transparency failed" TSRMLS_CC);
12886 return;
12887 }
12888
12889 RETURN_TRUE;
12890 }
12891 /* }}} */
12892 #endif
12893
12894 #if MagickLibVersion >= 0x660
12895 /* {{{ proto bool Imagick::autoGammaImage([int channel = CHANNEL_ALL])
12896 Extracts the 'mean' from the image and adjust the image to try make set its gamma appropriately.
12897 */
12898 PHP_METHOD(Imagick, autoGammaImage)
12899 {
12900 php_imagick_object *intern;
12901 MagickBooleanType status;
12902 im_long channel = IM_DEFAULT_CHANNEL;
12903
12904 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &channel) == FAILURE) {
12905 return;
12906 }
12907
12908 intern = Z_IMAGICK_P(getThis());
12909 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
12910 return;
12911
12912 status = MagickAutoGammaImageChannel(intern->magick_wand, channel);
12913
12914 /* No magick is going to happen */
12915 if (status == MagickFalse) {
12916 php_imagick_convert_imagick_exception(intern->magick_wand, "autoGammaImage" TSRMLS_CC);
12917 return;
12918 }
12919
12920 RETURN_TRUE;
12921 }
12922 /* }}} */
12923 #endif //#if MagickLibVersion >= 0x660
12924
12925 #if MagickLibVersion >= 0x692
12926 /* {{{ proto bool Imagick::autoOrient()
12927 Adjusts an image so that its orientation is suitable $ for viewing (i.e. top-left orientation).
12928 */
12929 PHP_METHOD(Imagick, autoOrient)
12930 {
12931 php_imagick_object *intern;
12932 MagickBooleanType status;
12933
12934 if (zend_parse_parameters_none() == FAILURE) {
12935 return;
12936 }
12937
12938 intern = Z_IMAGICK_P(getThis());
12939 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
12940 return;
12941
12942 status = MagickAutoOrientImage(intern->magick_wand);
12943
12944 /* No magick is going to happen */
12945 if (status == MagickFalse) {
12946 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable autoOrient image" TSRMLS_CC);
12947 return;
12948 }
12949
12950 RETURN_TRUE;
12951 }
12952 /* }}} */
12953 #endif // #if MagickLibVersion >= 0x692
12954
12955 #if MagickLibVersion >= 0x692
12956 /* {{{ proto bool Imagick::compositeImageGravity(Imagick $image, int COMPOSITE_CONSTANT, int GRAVITY_CONSTANT)
12957 Composite one image onto another using the specified gravity.
12958 */
12959 PHP_METHOD(Imagick, compositeImageGravity)
12960 {
12961 zval *objvar;
12962 php_imagick_object *intern, *image_to_composite;
12963 MagickBooleanType status;
12964 im_long composite, gravity;
12965
12966 /* Parse parameters given to function */
12967 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Oll", &objvar, php_imagick_sc_entry, &composite, &gravity) == FAILURE) {
12968 return;
12969 }
12970
12971 intern = Z_IMAGICK_P(getThis());
12972 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
12973 return;
12974
12975 image_to_composite = Z_IMAGICK_P(objvar);
12976 if (php_imagick_ensure_not_empty (image_to_composite->magick_wand) == 0)
12977 return;
12978
12979 status = MagickCompositeImageGravity(intern->magick_wand, image_to_composite->magick_wand, composite, gravity);
12980
12981 /* No magick is going to happen */
12982 if (status == MagickFalse) {
12983 php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to compositeImageGravity" TSRMLS_CC);
12984 return;
12985 }
12986
12987 RETURN_TRUE;
12988 }
12989 /* }}} */
12990 #endif
12991
12992 #if MagickLibVersion >= 0x693
12993 /* {{{ proto bool Imagick::localContrastImage(float radius, float strength)
12994 Attempts to increase the appearance of large-scale light-dark transitions.
12995 Local contrast enhancement works similarly to sharpening with an unsharp mask,
12996 however the mask is instead created using an image with a greater blur distance.
12997 */
12998 PHP_METHOD(Imagick, localContrastImage)
12999 {
13000 php_imagick_object *intern;
13001 MagickBooleanType status;
13002 double radius, strength;
13003
13004 /* Parse parameters given to function */
13005 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &radius, &strength) == FAILURE) {
13006 return;
13007 }
13008
13009 intern = Z_IMAGICK_P(getThis());
13010 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
13011 return;
13012
13013 status = MagickLocalContrastImage(intern->magick_wand, radius, strength);
13014
13015 /* No magick is going to happen */
13016 if (status == MagickFalse) {
13017 php_imagick_convert_imagick_exception(intern->magick_wand, "Failed to localContrastImage" TSRMLS_CC);
13018 return;
13019 }
13020
13021 RETURN_TRUE;
13022 }
13023 /* }}} */
13024 #endif // #if MagickLibVersion >= 0x693
13025
13026
13027 #if MagickLibVersion >= 0x700
13028 /* {{{ proto int Imagick::identifyImageType()
13029 Identifies the potential image type, returns one of the Imagick::IMGTYPE_* constants
13030 */
13031 PHP_METHOD(Imagick, identifyImageType)
13032 {
13033 php_imagick_object *intern;
13034 long imageType;
13035
13036 if (zend_parse_parameters_none() == FAILURE) {
13037 return;
13038 }
13039
13040 intern = Z_IMAGICK_P(getThis());
13041 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
13042 return;
13043
13044 imageType = MagickIdentifyImageType(intern->magick_wand);
13045
13046 RETVAL_LONG(imageType);
13047 }
13048 /* }}} */
13049 #endif // #if MagickLibVersion >= 0x700
13050
13051
13052 #if IM_HAVE_IMAGICK_GETSETIMAGEMASK
13053 /* {{{ proto Imagick Imagick::getImageMask()
13054 returns one of the Imagick::PIXELMASK_* constants
13055 */
13056 PHP_METHOD(Imagick, getImageMask)
13057 {
13058 php_imagick_object *intern;
13059 php_imagick_object *intern_return;
13060 im_long pixelmask_type;
13061 MagickWand *tmp_wand;
13062
13063 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &pixelmask_type) == FAILURE) {
13064 return;
13065 }
13066
13067 intern = Z_IMAGICK_P(getThis());
13068 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
13069 return;
13070
13071 tmp_wand = MagickGetImageMask(intern->magick_wand, pixelmask_type);
13072
13073 /* No magick is going to happen */
13074 if (!tmp_wand) {
13075 RETURN_NULL();
13076
13077 // php_imagick_convert_imagick_exception(intern->magick_wand, "Unable to get image clip mask" TSRMLS_CC);
13078 // return;
13079 }
13080
13081 object_init_ex(return_value, php_imagick_sc_entry);
13082 intern_return = Z_IMAGICK_P(return_value);
13083
13084 php_imagick_replace_magickwand(intern_return, tmp_wand);
13085 return;
13086 }
13087 /* }}} */
13088
13089 /* {{{ proto void Imagick::setImageMask(Imagick $clip_mask, int $pixelmask_type)
13090 returns one of the Imagick::PIXELMASK_* constants
13091 */
13092 PHP_METHOD(Imagick, setImageMask)
13093 {
13094 php_imagick_object *intern;
13095 php_imagick_object *clip_mask;
13096 zval *objvar;
13097 im_long pixelmask_type;
13098
13099 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol", &objvar, php_imagick_sc_entry, &pixelmask_type) == FAILURE) {
13100 return;
13101 }
13102
13103 intern = Z_IMAGICK_P(getThis());
13104 if (php_imagick_ensure_not_empty (intern->magick_wand) == 0)
13105 return;
13106
13107 clip_mask = Z_IMAGICK_P(objvar);
13108 if (php_imagick_ensure_not_empty (clip_mask->magick_wand) == 0)
13109 return;
13110
13111 MagickSetImageMask(
13112 intern->magick_wand,
13113 pixelmask_type,
13114 clip_mask->magick_wand
13115 );
13116
13117 // TODO - check that
13118 // wand->exception
13119 // You want ei->severity. ei->error_number
13120 // the Go Imagick library does something like:
13121 //return &MagickWandException{ExceptionType(C.int(et)), C.GoString(csdescription)}
13122
13123 RETURN_TRUE;
13124 }
13125 /* }}} */
13126 #endif // IM_HAVE_IMAGICK_GETSETIMAGEMASK
13127
13128 /* end of Imagick */
13129