xref: /imagick/imagick_class.c (revision 03480460)
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", &amplitude, &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", &degrees) == 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, &param, &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, &param, &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", &param, &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", &param) == 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, &param) == 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, &param) == 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", &param) == 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", &param, &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", &param) == 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", &param, &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", &param, &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", &param, &degrees) == 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", &param) == 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", &param) == 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", &param) == 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