diff --git a/ext/config.m4 b/ext/config.m4 index 0fa0f4bae1e..97488a483e5 100644 --- a/ext/config.m4 +++ b/ext/config.m4 @@ -340,7 +340,13 @@ mvc/model/query/scanner.c \ mvc/view/engine/volt/parser.c \ mvc/view/engine/volt/scanner.c \ annotations/parser.c \ -annotations/scanner.c" +annotations/scanner.c \ +image.c \ +image/adapter.c \ +image/adapterinterface.c \ +image/exception.c \ +image/adapter/gd.c \ +image/adapter/imagick.c" PHP_NEW_EXTENSION(phalcon, $phalcon_sources, $ext_shared) PHP_ADD_EXTENSION_DEP([phalcon], [spl]) diff --git a/ext/image.c b/ext/image.c new file mode 100644 index 00000000000..5d9878928c3 --- /dev/null +++ b/ext/image.c @@ -0,0 +1,72 @@ + +/* + +------------------------------------------------------------------------+ + | Phalcon Framework | + +------------------------------------------------------------------------+ + | Copyright (c) 2011-2013 Phalcon Team (http://www.phalconphp.com) | + +------------------------------------------------------------------------+ + | This source file is subject to the New BSD License that is bundled | + | with this package in the file docs/LICENSE.txt. | + | | + | If you did not receive a copy of the license and are unable to | + | obtain it through the world-wide-web, please send an email | + | to license@phalconphp.com so we can send you a copy immediately. | + +------------------------------------------------------------------------+ + | Authors: Andres Gutierrez | + | Eduar Carvajal | + +------------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_phalcon.h" +#include "phalcon.h" + +#include "Zend/zend_operators.h" +#include "Zend/zend_exceptions.h" +#include "Zend/zend_interfaces.h" + +#include "kernel/main.h" +#include "kernel/memory.h" + +/** + * Phalcon\Image + * + * Image manipulation support. Allows images to be resized, cropped, etc. + * + * + * $image = new Phalcon\Image\Adapter\GD("upload/test.jpg"); + * $image->resize(200, 200); + * $$image->save(); + * + */ + + +/** + * Phalcon\Image initializer + */ +PHALCON_INIT_CLASS(Phalcon_Image){ + + PHALCON_REGISTER_CLASS(Phalcon, Image, image, NULL, ZEND_ACC_EXPLICIT_ABSTRACT_CLASS); + + // Resizing constraints + zend_declare_class_constant_long(phalcon_image_ce, SL("NONE"), 1 TSRMLS_CC); + zend_declare_class_constant_long(phalcon_image_ce, SL("WIDTH"), 2 TSRMLS_CC); + zend_declare_class_constant_long(phalcon_image_ce, SL("HEIGHT"), 3 TSRMLS_CC); + zend_declare_class_constant_long(phalcon_image_ce, SL("AUTO"), 4 TSRMLS_CC); + zend_declare_class_constant_long(phalcon_image_ce, SL("INVERSE"), 5 TSRMLS_CC); + zend_declare_class_constant_long(phalcon_image_ce, SL("PRECISE"), 6 TSRMLS_CC); + + // Flipping directions + zend_declare_class_constant_long(phalcon_image_ce, SL("HORIZONTAL"), 11 TSRMLS_CC); + zend_declare_class_constant_long(phalcon_image_ce, SL("VERTICAL"), 12 TSRMLS_CC); + + // Driver: GD, ImageMagick, etc + zend_declare_class_constant_long(phalcon_image_ce, SL("GD"), 21 TSRMLS_CC); + zend_declare_class_constant_long(phalcon_image_ce, SL("IMAGICK"), 22 TSRMLS_CC); + + return SUCCESS; +} \ No newline at end of file diff --git a/ext/image.h b/ext/image.h new file mode 100644 index 00000000000..efa2e83db00 --- /dev/null +++ b/ext/image.h @@ -0,0 +1,22 @@ + +/* + +------------------------------------------------------------------------+ + | Phalcon Framework | + +------------------------------------------------------------------------+ + | Copyright (c) 2011-2013 Phalcon Team (http://www.phalconphp.com) | + +------------------------------------------------------------------------+ + | This source file is subject to the New BSD License that is bundled | + | with this package in the file docs/LICENSE.txt. | + | | + | If you did not receive a copy of the license and are unable to | + | obtain it through the world-wide-web, please send an email | + | to license@phalconphp.com so we can send you a copy immediately. | + +------------------------------------------------------------------------+ + | Authors: Andres Gutierrez | + | Eduar Carvajal | + +------------------------------------------------------------------------+ +*/ + +extern zend_class_entry *phalcon_image_ce; + +PHALCON_INIT_CLASS(Phalcon_Image); \ No newline at end of file diff --git a/ext/image/adapter.c b/ext/image/adapter.c new file mode 100644 index 00000000000..748b27b9e3d --- /dev/null +++ b/ext/image/adapter.c @@ -0,0 +1,922 @@ +/* + +------------------------------------------------------------------------+ + | Phalcon Framework | + +------------------------------------------------------------------------+ + | Copyright (c) 2011-2013 Phalcon Team (http://www.phalconphp.com) | + +------------------------------------------------------------------------+ + | This source file is subject to the New BSD License that is bundled | + | with this package in the file docs/LICENSE.txt. | + | | + | If you did not receive a copy of the license and are unable to | + | obtain it through the world-wide-web, please send an email | + | to license@phalconphp.com so we can send you a copy immediately. | + +------------------------------------------------------------------------+ + | Authors: Andres Gutierrez | + | Eduar Carvajal | + +------------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_phalcon.h" +#include "phalcon.h" + +#include "Zend/zend_operators.h" +#include "Zend/zend_exceptions.h" +#include "Zend/zend_interfaces.h" + +#include "kernel/main.h" +#include "kernel/memory.h" +#include "kernel/exception.h" +#include "kernel/object.h" +#include "kernel/fcall.h" +#include "kernel/string.h" +#include "kernel/concat.h" +#include "kernel/operators.h" + +/** + * Phalcon\Image\Adapter + * + * Base class for Phalcon\Image adapters + */ + + +/** + * Phalcon\Image\Adapter initializer + */ +PHALCON_INIT_CLASS(Phalcon_Image_Adapter){ + + PHALCON_REGISTER_CLASS(Phalcon\\Image, Adapter, image_adapter, phalcon_image_adapter_method_entry, ZEND_ACC_EXPLICIT_ABSTRACT_CLASS); + + zend_declare_property_null(phalcon_image_adapter_ce, SL("_image"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_image_adapter_ce, SL("_checked"), ZEND_ACC_PROTECTED|ZEND_ACC_STATIC TSRMLS_CC); + zend_declare_property_null(phalcon_image_adapter_ce, SL("_file"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_image_adapter_ce, SL("_realpath"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_image_adapter_ce, SL("_imageinfo"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_image_adapter_ce, SL("_width"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_image_adapter_ce, SL("_height"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_image_adapter_ce, SL("_type"), ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_null(phalcon_image_adapter_ce, SL("_mime"), ZEND_ACC_PROTECTED TSRMLS_CC); + + return SUCCESS; +} + +/** + * Phalcon\Image constructor + */ +PHP_METHOD(Phalcon_Image_Adapter, __construct){ + + zval *file, *realpath, *imageinfo, *width, *height, *type, *mime, *exception_message; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 1, 0, &file); + + if (Z_TYPE_P(file) != IS_STRING) { + PHALCON_THROW_EXCEPTION_STR(phalcon_image_exception_ce, "file parameter should be a string"); + return; + } + + phalcon_update_property_this(this_ptr, SL("_file"), file TSRMLS_CC); + + PHALCON_INIT_VAR(realpath); + phalcon_call_func_p1(realpath, "realpath", file); + phalcon_update_property_this(this_ptr, SL("_realpath"), realpath TSRMLS_CC); + + PHALCON_INIT_VAR(imageinfo); + phalcon_call_func_p1(imageinfo, "getimagesize", realpath); + + if (Z_TYPE_P(imageinfo) != IS_ARRAY) { + PHALCON_INIT_VAR(exception_message); + PHALCON_CONCAT_SVS(exception_message, "Can't open image file at '", realpath, "'"); + PHALCON_THROW_EXCEPTION_ZVAL(phalcon_image_exception_ce, exception_message); + return; + } + + if (phalcon_array_isset_long(imageinfo, 0)) { + PHALCON_OBS_VAR(width); + phalcon_array_fetch_long(&width, imageinfo, 0, PH_NOISY); + phalcon_update_property_this(this_ptr, SL("_width"), width TSRMLS_CC); + } + + if (phalcon_array_isset_long(imageinfo, 1)) { + PHALCON_OBS_VAR(height); + phalcon_array_fetch_long(&height, imageinfo, 1, PH_NOISY); + phalcon_update_property_this(this_ptr, SL("_height"), height TSRMLS_CC); + } + + if (phalcon_array_isset_long(imageinfo, 2)) { + PHALCON_OBS_VAR(type); + phalcon_array_fetch_long(&type, imageinfo, 2, PH_NOISY); + phalcon_update_property_this(this_ptr, SL("_type"), type TSRMLS_CC); + } + + if (phalcon_array_isset_string(imageinfo, SS("mime"))) { + PHALCON_OBS_VAR(mime); + phalcon_array_fetch_string(&mime, imageinfo, SL("mime"), PH_NOISY); + phalcon_update_property_this(this_ptr, SL("_mime"), mime TSRMLS_CC); + } + + phalcon_update_property_this(this_ptr, SL("_imageinfo"), imageinfo TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Returns the real path of the image file + * + * @return string + */ +PHP_METHOD(Phalcon_Image_Adapter, getRealPath){ + + + RETURN_MEMBER(this_ptr, "_realpath"); +} + +/** + * Returns the width of images + * + * @return int + */ +PHP_METHOD(Phalcon_Image_Adapter, getWidth){ + + + RETURN_MEMBER(this_ptr, "_width"); +} + +/** + * Returns the height of images + * + * @return int + */ +PHP_METHOD(Phalcon_Image_Adapter, getHeight){ + + + RETURN_MEMBER(this_ptr, "_height"); +} + +/** + * Returns the type of images + * + * @return int + */ +PHP_METHOD(Phalcon_Image_Adapter, getType){ + + + RETURN_MEMBER(this_ptr, "_type"); +} + +/** + * Returns the mime of images + * + * @return string + */ +PHP_METHOD(Phalcon_Image_Adapter, getMime){ + + + RETURN_MEMBER(this_ptr, "_mime"); +} + +/** + * Returns the image of images + * + * @return resource + */ +PHP_METHOD(Phalcon_Image_Adapter, getImage){ + + + RETURN_MEMBER(this_ptr, "_image"); +} + +/** + * Resize the image to the given size. Either the width or the height can + * be omitted and the image will be resized proportionally. + * + * @param int $width new width + * @param int $height new height + * @param int $master master dimension + * @return Phalcon\Image\Adapter + */ +PHP_METHOD(Phalcon_Image_Adapter, resize){ + + zval *width = NULL, *height = NULL, *master = NULL; + zval *image_width, *image_height; + int tmp_image_width, tmp_image_height, tmp_width, tmp_height; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 0, 3, &width, &height, &master); + + if (!width) { + PHALCON_INIT_VAR(width); + } else { + PHALCON_SEPARATE_PARAM(width); + } + + if (!height) { + PHALCON_INIT_VAR(height); + } else { + PHALCON_SEPARATE_PARAM(height); + } + + if (!master) { + PHALCON_INIT_VAR(master); + ZVAL_LONG(master, 4); + } else { + PHALCON_SEPARATE_PARAM(master); + } + + PHALCON_OBS_VAR(image_width); + phalcon_read_property_this(&image_width, this_ptr, SL("_width"), PH_NOISY_CC); + + PHALCON_OBS_VAR(image_height); + phalcon_read_property_this(&image_height, this_ptr, SL("_height"), PH_NOISY_CC); + + tmp_image_width = phalcon_get_intval(image_width); + tmp_image_height = phalcon_get_intval(image_height); + + if (Z_TYPE_P(master) != IS_LONG) { + convert_to_long(master); + } + + if (Z_LVAL_P(master) == 2 && Z_TYPE_P(width) == IS_LONG) { + ZVAL_LONG(master, 4); + } else if (Z_LVAL_P(master) == 3 && Z_TYPE_P(height) == IS_LONG) { + ZVAL_LONG(master, 4); + } + + if (Z_TYPE_P(width) != IS_LONG) { + if (Z_LVAL_P(master) == 1) { + tmp_width = tmp_image_width; + } else { + ZVAL_LONG(master, 3); + } + } else { + tmp_width = Z_LVAL_P(width); + } + + if (Z_TYPE_P(height) != IS_LONG) { + if (Z_LVAL_P(master) == 1) { + tmp_height = tmp_image_height; + } else { + ZVAL_LONG(master, 2); + } + } else { + tmp_height = Z_LVAL_P(height); + } + + switch (Z_LVAL_P(master)) { + case 4: // AUTO + { + if ( (tmp_image_width / tmp_width) > (tmp_image_height / tmp_height)) { + ZVAL_LONG(master, 2); + } else { + ZVAL_LONG(master, 3); + } + break; + } + case 5: // INVERSE + { + if ( (tmp_image_width / tmp_width) > (tmp_image_height / tmp_height)) { + ZVAL_LONG(master, 3); + } else { + ZVAL_LONG(master, 2); + } + break; + } + + } + + switch (Z_LVAL_P(master)) { + case 2: // WIDTH + { + tmp_height = (int)((tmp_image_height * tmp_width / tmp_image_width) + 0.5); + break; + } + case 3: // HEIGHT + { + tmp_width = (int)((tmp_image_width * tmp_height / tmp_image_height) + 0.5); + break; + } + case 6: //PRECISE + { + if ((tmp_width / tmp_height) > (tmp_image_width / tmp_image_height)) { + tmp_height = (int)((tmp_image_height * tmp_width / tmp_image_width) + 0.5); + } else { + tmp_width = (int)((tmp_image_width * tmp_height / tmp_image_height) + 0.5); + } + break; + } + + } + + if (tmp_width <= 0) { + tmp_width = 1; + } + + if (tmp_height <= 0) { + tmp_height = 1; + } + + PHALCON_INIT_NVAR(width); + ZVAL_LONG(width, tmp_width); + + PHALCON_INIT_NVAR(height); + ZVAL_LONG(height, tmp_height); + + phalcon_call_method_p2_noret(this_ptr, "_resize", width, height); + + RETURN_THIS(); +} + +/** + * Crop an image to the given size. Either the width or the height can be + * omitted and the current width or height will be used. + * + * @param int $width new width + * @param int $height new height + * @param int $offset_x offset from the left + * @param int $offset_y offset from the top + * @return Phalcon\Image\Adapter + */ +PHP_METHOD(Phalcon_Image_Adapter, crop){ + + zval *width, *height, *offset_x = NULL, *offset_y = NULL; + zval *image_width, *image_height; + int tmp_max_width, tmp_max_height, tmp_width, tmp_height, tmp_image_width, tmp_image_height, tmp_offset_x, tmp_offset_y; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 2, 2, &width, &height, &offset_x, &offset_y); + + PHALCON_SEPARATE_PARAM(width); + PHALCON_SEPARATE_PARAM(height); + + if (Z_TYPE_P(width) != IS_LONG) { + convert_to_long(width); + } + + if (Z_TYPE_P(height) != IS_LONG) { + convert_to_long(height); + } + + PHALCON_OBS_VAR(image_width); + phalcon_read_property_this(&image_width, this_ptr, SL("_width"), PH_NOISY_CC); + + PHALCON_OBS_VAR(image_height); + phalcon_read_property_this(&image_height, this_ptr, SL("_height"), PH_NOISY_CC); + + tmp_width = phalcon_get_intval(width); + tmp_height = phalcon_get_intval(height); + tmp_image_width = phalcon_get_intval(image_width); + tmp_image_height = phalcon_get_intval(image_height); + + if (tmp_width > tmp_image_width) { + tmp_width = tmp_image_width; + } + + if (tmp_height > tmp_image_height) { + tmp_height = tmp_image_height; + } + + if (!offset_x) { + tmp_offset_x = (int)(((tmp_image_width - tmp_width) / 2) + 0.5); + } else { + PHALCON_SEPARATE_PARAM(offset_x); + + if (zend_is_true(offset_x)) { + tmp_offset_x = tmp_image_width - tmp_width; + } else if (Z_TYPE_P(offset_x) != IS_LONG) { + tmp_offset_x = (int)(((tmp_image_width - tmp_width) / 2) + 0.5); + } else if (Z_LVAL_P(offset_x) < 0) { + tmp_offset_x = (int)(tmp_image_width - tmp_width + Z_LVAL_P(offset_x) + 0.5); + } else { + tmp_offset_x = Z_LVAL_P(offset_x); + } + } + + if (!offset_y) { + tmp_offset_y = (int)(((tmp_image_height - tmp_height) / 2) + 0.5); + } else { + PHALCON_SEPARATE_PARAM(offset_y); + + if (zend_is_true(offset_y)) { + tmp_offset_y = tmp_image_height - tmp_height; + } else if (Z_TYPE_P(offset_y) != IS_LONG) { + tmp_offset_y = (int)(((tmp_image_height - tmp_height) / 2) + 0.5); + } else if (Z_LVAL_P(offset_y) < 0) { + tmp_offset_y = tmp_image_height - tmp_height + Z_LVAL_P(offset_y); + } else { + tmp_offset_y = Z_LVAL_P(offset_y); + } + } + + tmp_max_width = tmp_image_width - tmp_offset_x; + tmp_max_height = tmp_image_height - tmp_offset_y; + + if (tmp_width > tmp_max_width) { + tmp_width = tmp_max_width; + } + + if (tmp_height > tmp_max_height) { + tmp_height = tmp_max_height; + } + + PHALCON_INIT_NVAR(width); + ZVAL_LONG(width, tmp_width); + + PHALCON_INIT_NVAR(height); + ZVAL_LONG(height, tmp_height); + + PHALCON_INIT_NVAR(offset_x); + ZVAL_LONG(offset_x, tmp_offset_x); + + PHALCON_INIT_NVAR(offset_y); + ZVAL_LONG(offset_y, tmp_offset_y); + + phalcon_call_method_p4_noret(this_ptr, "_crop", width, height, offset_x, offset_y); + + RETURN_THIS(); +} + +/** + * Rotate the image by a given amount. + * + * @param int $degrees degrees to rotate: -360-360 + * @return Phalcon\Image\Adapter + */ +PHP_METHOD(Phalcon_Image_Adapter, rotate){ + + zval *degrees; + int tmp_degrees; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 1, 0, °rees); + + PHALCON_SEPARATE_PARAM(degrees); + + if (Z_TYPE_P(degrees) != IS_LONG) { + convert_to_long(degrees); + } + + tmp_degrees = Z_LVAL_P(degrees); + + if (tmp_degrees > 180) { + do { + tmp_degrees -= 360; + } while (tmp_degrees > 180); + } else if (tmp_degrees < -180) { + do { + tmp_degrees += 360; + } while (tmp_degrees < -180); + } + + PHALCON_INIT_VAR(degrees); + ZVAL_LONG(degrees, tmp_degrees); + + phalcon_call_method_p1_noret(this_ptr, "_rotate", degrees); + + RETURN_THIS(); +} + +/** + * Flip the image along the horizontal or vertical axis. + * + * @param $int $direction direction: Image::HORIZONTAL, Image::VERTICAL + * @return Phalcon\Image\Adapter + */ +PHP_METHOD(Phalcon_Image_Adapter, flip){ + + zval *direction; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 1, 0, &direction); + + PHALCON_SEPARATE_PARAM(direction); + + if (Z_TYPE_P(direction) != IS_LONG) { + convert_to_long(direction); + } + + if (Z_LVAL_P(direction) != 11) { + ZVAL_LONG(direction, 12); + } + + phalcon_call_method_p1_noret(this_ptr, "_flip", direction); + + RETURN_THIS(); +} + +/** + * Sharpen the image by a given amount. + * + * @param int $amount amount to sharpen: 1-100 + * @return Phalcon\Image\Adapter + */ +PHP_METHOD(Phalcon_Image_Adapter, sharpen){ + + zval *amount; + int a; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 1, 0, &amount); + + PHALCON_SEPARATE_PARAM(amount); + + if (Z_TYPE_P(amount) != IS_LONG) { + convert_to_long(amount); + } + + if (Z_LVAL_P(amount) > 100) { + ZVAL_LONG(amount, 100); + } else if (Z_LVAL_P(amount) < 1) { + ZVAL_LONG(amount, 1); + } + + phalcon_call_method_p1_noret(this_ptr, "_sharpen", amount); + + RETURN_THIS(); +} + +/** + * Add a reflection to an image. The most opaque part of the reflection + * will be equal to the opacity setting and fade out to full transparent. + * Alpha transparency is preserved. + * + * @param int $height reflection height + * @param int $opacity reflection opacity: 0-100 + * @param boolean $fade_in TRUE to fade in, FALSE to fade out + * @return Phalcon\Image\Adapter + */ +PHP_METHOD(Phalcon_Image_Adapter, reflection){ + + zval *height = NULL, *opacity = NULL, *fade_in = NULL; + zval *image_height; + int tmp_image_height; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 0, 3, &height, &opacity, &fade_in); + + PHALCON_OBS_VAR(image_height); + phalcon_read_property_this(&image_height, this_ptr, SL("_height"), PH_NOISY_CC); + + tmp_image_height = phalcon_get_intval(image_height); + + if (!height) { + PHALCON_INIT_NVAR(height); + ZVAL_LONG(height, tmp_image_height); + } else if (Z_TYPE_P(height) != IS_LONG || Z_LVAL_P(height) > tmp_image_height) { + PHALCON_SEPARATE_PARAM(height); + + PHALCON_INIT_NVAR(height); + ZVAL_LONG(height, tmp_image_height); + } + + if (!opacity) { + PHALCON_INIT_NVAR(opacity); + ZVAL_LONG(opacity, 100); + } else { + PHALCON_SEPARATE_PARAM(opacity); + + if (Z_TYPE_P(opacity) != IS_LONG || Z_LVAL_P(opacity) > 100) { + PHALCON_INIT_NVAR(opacity); + ZVAL_LONG(opacity, 100); + } else if (Z_LVAL_P(opacity) < 0) { + ZVAL_LONG(opacity, 0); + } + } + + if (!fade_in) { + PHALCON_INIT_NVAR(fade_in); + ZVAL_LONG(fade_in, 0); + } + + phalcon_call_method_p3_noret(this_ptr, "_reflection", height, opacity, fade_in); + + RETURN_THIS(); +} + +/** + * Add a watermark to an image with a specified opacity. Alpha transparency + * will be preserved. + * + * @param Phalcon\Image\Adapter $watermark watermark Image instance + * @param int $offset_x offset from the left + * @param int $offset_y offset from the top + * @param int $opacity opacity of watermark: 1-100 + * @return Phalcon\Image\Adapter + */ +PHP_METHOD(Phalcon_Image_Adapter, watermark){ + + zval *watermark, *offset_x = NULL, *offset_y = NULL, *opacity = NULL; + zval *image_width, *image_height, *watermark_width, *watermark_height; + int tmp_image_width, tmp_image_height, tmp_watermark_width, tmp_watermark_height, tmp_offset_x, tmp_offset_y, tmp_opacity; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 1, 3, &watermark, &offset_x, &offset_y, &opacity); + + + + PHALCON_OBS_VAR(image_width); + phalcon_read_property_this(&image_width, this_ptr, SL("_width"), PH_NOISY_CC); + + PHALCON_OBS_VAR(image_height); + phalcon_read_property_this(&image_height, this_ptr, SL("_height"), PH_NOISY_CC); + + PHALCON_OBS_VAR(watermark_width); + phalcon_read_property_this(&watermark_width, watermark, SL("_width"), PH_NOISY_CC); + + PHALCON_OBS_VAR(watermark_height); + phalcon_read_property_this(&watermark_height, watermark, SL("_height"), PH_NOISY_CC); + + tmp_image_width = phalcon_get_intval(image_width); + tmp_image_height = phalcon_get_intval(image_height); + tmp_watermark_width = phalcon_get_intval(watermark_width); + tmp_watermark_height = phalcon_get_intval(watermark_height); + + if (!offset_x) { + tmp_offset_x = (int)(((tmp_image_width - tmp_watermark_width) / 2) + 0.5); + } else { + PHALCON_SEPARATE_PARAM(offset_x); + if (zend_is_true(offset_x)) { + tmp_offset_x = (int)(tmp_image_width - tmp_watermark_width); + } else if (Z_TYPE_P(offset_x) == IS_LONG ) { + tmp_offset_x = phalcon_get_intval(offset_x); + if (tmp_offset_x < 0) { + tmp_offset_x = (int)(tmp_image_width - tmp_watermark_width + tmp_offset_x + 0.5); + } + } else { + tmp_offset_x = (int)(((tmp_image_width - tmp_watermark_width) / 2) + 0.5); + } + } + + PHALCON_INIT_NVAR(offset_x); + ZVAL_LONG(offset_x, tmp_offset_x); + + if (!offset_y) { + tmp_offset_y = (int)(((tmp_image_height - tmp_watermark_height) / 2) + 0.5); + } else { + PHALCON_SEPARATE_PARAM(offset_y); + if (zend_is_true(offset_y)) { + tmp_offset_y = (int)(tmp_image_height - tmp_watermark_height); + } else if (Z_TYPE_P(offset_y) == IS_LONG ) { + tmp_offset_y = phalcon_get_intval(offset_y); + if (tmp_offset_y < 0) { + tmp_offset_y = (int)(tmp_image_height - tmp_watermark_height + tmp_offset_y + 0.5); + } + } else { + tmp_offset_y = (int)(((tmp_image_height - tmp_watermark_height) / 2) + 0.5); + } + } + + PHALCON_INIT_NVAR(offset_y); + ZVAL_LONG(offset_y, tmp_offset_y); + + if (!opacity) { + tmp_opacity = 100; + } else { + PHALCON_SEPARATE_PARAM(opacity); + + tmp_opacity = phalcon_get_intval(opacity); + + if (tmp_opacity < 1) { + tmp_opacity = 1; + } else if (tmp_opacity > 100) { + tmp_opacity = 100; + } + } + + PHALCON_INIT_NVAR(opacity); + ZVAL_LONG(opacity, tmp_opacity); + + phalcon_call_method_p4_noret(this_ptr, "_watermark", watermark, offset_x, offset_y, opacity); + + RETURN_THIS(); +} + +/** + * Set the background color of an image. This is only useful for images + * with alpha transparency. + * + * @param string $color hexadecimal color value + * @param int $opacity background opacity: 0-100 + * @return Phalcon\Image\Adapter + */ +PHP_METHOD(Phalcon_Image_Adapter, background){ + + zval *color, *opacity = NULL; + zval *tmp = NULL, *tmp_color = NULL, *r = NULL, *g = NULL, *b = NULL; + zval *pattern, *replacement; + int i; + char *c; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 1, 1, &color, &opacity); + + if (Z_TYPE_P(color) != IS_STRING) { + PHALCON_THROW_EXCEPTION_STR(phalcon_image_exception_ce, "color must be an string"); + return; + } + + c = Z_STRVAL_P(color); + + if (c[0] == '#') { + PHALCON_INIT_NVAR(tmp_color); + phalcon_substr(tmp_color, color, 1, 0); + } else { + PHALCON_CPY_WRT(tmp_color, color); + } + + if (Z_STRLEN_P(tmp_color) == 3) { + PHALCON_INIT_VAR(pattern); + ZVAL_STRING(pattern, "#.#", 1); + + PHALCON_INIT_VAR(replacement); + ZVAL_STRING(replacement, "$0$0", 1); + + PHALCON_INIT_NVAR(tmp); + phalcon_call_func_p3(tmp, "preg_replace", pattern, replacement, tmp_color); + + PHALCON_CPY_WRT(tmp_color, tmp); + } + + if (Z_STRLEN_P(tmp_color) >= 6) { + + PHALCON_INIT_NVAR(tmp); + phalcon_substr(tmp, tmp_color, 0, 2); + + PHALCON_INIT_NVAR(r); + phalcon_call_func_p1(r, "hexdec", tmp); + + PHALCON_INIT_NVAR(tmp); + phalcon_substr(tmp, tmp_color, 2, 2); + + PHALCON_INIT_NVAR(g); + phalcon_call_func_p1(g, "hexdec", tmp); + + PHALCON_INIT_NVAR(tmp); + phalcon_substr(tmp, tmp_color, 4, 2); + + PHALCON_INIT_NVAR(b); + phalcon_call_func_p1(b, "hexdec", tmp); + } else { + PHALCON_THROW_EXCEPTION_STR(phalcon_image_exception_ce, "color is not valid"); + return; + } + + if (!opacity) { + PHALCON_INIT_NVAR(opacity); + ZVAL_LONG(opacity, 100); + } else { + PHALCON_SEPARATE_PARAM(opacity); + + i = phalcon_get_intval(opacity); + + if (i < 1) { + PHALCON_INIT_NVAR(opacity); + ZVAL_LONG(opacity, 1); + } else if (i > 100) { + PHALCON_INIT_NVAR(opacity); + ZVAL_LONG(opacity, 100); + } + } + + phalcon_call_method_p4_noret(this_ptr, "_background", r, g, b, opacity); + + RETURN_THIS(); +} + +/** + * Save the image. If the filename is omitted, the original image will + * be overwritten. + * + * @param string $file new image path + * @param int $quality quality of image: 1-100 + * @return Phalcon\Image\Adapter + */ +PHP_METHOD(Phalcon_Image_Adapter, save){ + + zval *file = NULL, *quality = NULL, *exception_message; + zval *ret, *dir, *constant; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 0, 2, &file, &quality); + + if (!file) { + PHALCON_OBS_VAR(file); + phalcon_read_property_this(&file, this_ptr, SL("_realpath"), PH_NOISY_CC); + } + + if (!quality) { + PHALCON_INIT_VAR(quality); + ZVAL_LONG(quality, 100); + } else if (Z_TYPE_P(quality) != IS_LONG) { + PHALCON_SEPARATE_PARAM(quality); + + PHALCON_INIT_NVAR(quality); + ZVAL_LONG(quality, 100); + } + + PHALCON_INIT_VAR(ret); + phalcon_call_func_p1(ret, "is_file", file); + + if (zend_is_true(ret)) { + phalcon_call_func_p1(ret, "is_writable", file); + if (!zend_is_true(ret)) { + PHALCON_INIT_VAR(exception_message); + PHALCON_CONCAT_SVS(exception_message, "File must be writable: '", file, "'"); + PHALCON_THROW_EXCEPTION_ZVAL(phalcon_image_exception_ce, exception_message); + return; + } + } else { + PHALCON_INIT_VAR(constant); + if (zend_get_constant(SL("PATHINFO_DIRNAME"), constant TSRMLS_CC) == FAILURE) { + RETURN_MM(); + } + + PHALCON_INIT_NVAR(ret); + phalcon_call_func_p2(ret, "pathinfo", file, constant); + + PHALCON_INIT_VAR(dir); + phalcon_call_func_p1(dir, "realpath", ret); + + PHALCON_INIT_NVAR(ret); + phalcon_call_func_p1(ret, "is_dir", dir); + + if (!zend_is_true(ret)) { + PHALCON_INIT_VAR(exception_message); + PHALCON_CONCAT_SVS(exception_message, "Directory must be writable: '", dir, "'"); + PHALCON_THROW_EXCEPTION_ZVAL(phalcon_image_exception_ce, exception_message); + return; + } else { + PHALCON_INIT_NVAR(ret); + phalcon_call_func_p1(ret, "is_writable", dir); + if (!zend_is_true(ret)) { + PHALCON_INIT_VAR(exception_message); + PHALCON_CONCAT_SVS(exception_message, "Directory must be writable: '", dir, "'"); + PHALCON_THROW_EXCEPTION_ZVAL(phalcon_image_exception_ce, exception_message); + return; + } + } + + } + + if (Z_LVAL_P(quality) > 100) { + ZVAL_LONG(quality, 100); + } else if (Z_LVAL_P(quality) < 1) { + ZVAL_LONG(quality, 1); + } + + phalcon_call_method_p2_noret(this_ptr, "_save", file, quality); + + RETURN_THIS(); +} + +/** + * Render the image and return the binary string. + * + * @param string $ext image type to return: png, jpg, gif, etc + * @param int $quality quality of image: 1-100 + * @return Phalcon\Image\Adapter + */ +PHP_METHOD(Phalcon_Image_Adapter, render){ + + zval *ext = NULL, *quality = NULL, *type, *include_dot, *exception_message; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 0, 2, &ext, &quality); + + if (!ext) { + PHALCON_INIT_VAR(include_dot); + ZVAL_BOOL(include_dot, 0); + + PHALCON_OBS_VAR(type); + phalcon_read_property_this(&type, this_ptr, SL("_type"), PH_NOISY_CC); + + PHALCON_INIT_VAR(ext); + phalcon_call_func_p2(ext, "image_type_to_extension", type, include_dot); + } + + if (!quality) { + PHALCON_INIT_VAR(quality); + ZVAL_LONG(quality, 100); + } else if (Z_TYPE_P(quality) != IS_LONG) { + PHALCON_INIT_NVAR(quality); + ZVAL_LONG(quality, 100); + } + + phalcon_call_method_p2(return_value, this_ptr, "_render", ext, quality); + + RETURN_MM(); +} diff --git a/ext/image/adapter.h b/ext/image/adapter.h new file mode 100644 index 00000000000..7338ab32da5 --- /dev/null +++ b/ext/image/adapter.h @@ -0,0 +1,119 @@ + +/* + +------------------------------------------------------------------------+ + | Phalcon Framework | + +------------------------------------------------------------------------+ + | Copyright (c) 2011-2013 Phalcon Team (http://www.phalconphp.com) | + +------------------------------------------------------------------------+ + | This source file is subject to the New BSD License that is bundled | + | with this package in the file docs/LICENSE.txt. | + | | + | If you did not receive a copy of the license and are unable to | + | obtain it through the world-wide-web, please send an email | + | to license@phalconphp.com so we can send you a copy immediately. | + +------------------------------------------------------------------------+ + | Authors: Andres Gutierrez | + | Eduar Carvajal | + +------------------------------------------------------------------------+ +*/ + +extern zend_class_entry *phalcon_image_adapter_ce; + +PHALCON_INIT_CLASS(Phalcon_Image_Adapter); + +PHP_METHOD(Phalcon_Image_Adapter, __construct); +PHP_METHOD(Phalcon_Image_Adapter, getRealPath); +PHP_METHOD(Phalcon_Image_Adapter, getWidth); +PHP_METHOD(Phalcon_Image_Adapter, getHeight); +PHP_METHOD(Phalcon_Image_Adapter, getType); +PHP_METHOD(Phalcon_Image_Adapter, getMime); +PHP_METHOD(Phalcon_Image_Adapter, getImage); +PHP_METHOD(Phalcon_Image_Adapter, resize); +PHP_METHOD(Phalcon_Image_Adapter, crop); +PHP_METHOD(Phalcon_Image_Adapter, rotate); +PHP_METHOD(Phalcon_Image_Adapter, flip); +PHP_METHOD(Phalcon_Image_Adapter, sharpen); +PHP_METHOD(Phalcon_Image_Adapter, reflection); +PHP_METHOD(Phalcon_Image_Adapter, watermark); +PHP_METHOD(Phalcon_Image_Adapter, background); +PHP_METHOD(Phalcon_Image_Adapter, save); +PHP_METHOD(Phalcon_Image_Adapter, render); + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter___construct, 0, 0, 1) + ZEND_ARG_INFO(0, file) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_resize, 0, 0, 0) + ZEND_ARG_INFO(0, width) + ZEND_ARG_INFO(0, height) + ZEND_ARG_INFO(0, master) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_crop, 0, 0, 2) + ZEND_ARG_INFO(0, width) + ZEND_ARG_INFO(0, height) + ZEND_ARG_INFO(0, offset_x) + ZEND_ARG_INFO(0, offset_y) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_rotate, 0, 0, 1) + ZEND_ARG_INFO(0, degrees) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_flip, 0, 0, 1) + ZEND_ARG_INFO(0, direction) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_sharpen, 0, 0, 1) + ZEND_ARG_INFO(0, amount) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_reflection, 0, 0, 0) + ZEND_ARG_INFO(0, height) + ZEND_ARG_INFO(0, opacity) + ZEND_ARG_INFO(0, fade_in) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_watermark, 0, 0, 1) + ZEND_ARG_INFO(0, watermark) + ZEND_ARG_INFO(0, offset_x) + ZEND_ARG_INFO(0, offset_y) + ZEND_ARG_INFO(0, opacity) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_background, 0, 0, 1) + ZEND_ARG_INFO(0, color) + ZEND_ARG_INFO(0, quality) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_save, 0, 0, 0) + ZEND_ARG_INFO(0, file) + ZEND_ARG_INFO(0, quality) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_render, 0, 0, 0) + ZEND_ARG_INFO(0, ext) + ZEND_ARG_INFO(0, quality) +ZEND_END_ARG_INFO() + +PHALCON_INIT_FUNCS(phalcon_image_adapter_method_entry){ + PHP_ME(Phalcon_Image_Adapter, __construct, arginfo_phalcon_image_adapter___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) + PHP_ME(Phalcon_Image_Adapter, getRealPath, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Image_Adapter, getWidth, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Image_Adapter, getHeight, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Image_Adapter, getType, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Image_Adapter, getMime, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Image_Adapter, getImage, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Image_Adapter, resize, arginfo_phalcon_image_adapter_resize, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Image_Adapter, crop, arginfo_phalcon_image_adapter_crop, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Image_Adapter, rotate, arginfo_phalcon_image_adapter_rotate, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Image_Adapter, flip, arginfo_phalcon_image_adapter_flip, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Image_Adapter, sharpen, arginfo_phalcon_image_adapter_sharpen, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Image_Adapter, reflection, arginfo_phalcon_image_adapter_reflection, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Image_Adapter, watermark, arginfo_phalcon_image_adapter_watermark, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Image_Adapter, background, arginfo_phalcon_image_adapter_background, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Image_Adapter, save, arginfo_phalcon_image_adapter_save, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Image_Adapter, render, arginfo_phalcon_image_adapter_render, ZEND_ACC_PUBLIC) + PHP_FE_END +}; + diff --git a/ext/image/adapter/gd.c b/ext/image/adapter/gd.c new file mode 100644 index 00000000000..291a6f90ee6 --- /dev/null +++ b/ext/image/adapter/gd.c @@ -0,0 +1,1098 @@ + +/* + +------------------------------------------------------------------------+ + | Phalcon Framework | + +------------------------------------------------------------------------+ + | Copyright (c) 2011-2013 Phalcon Team (http://www.phalconphp.com) | + +------------------------------------------------------------------------+ + | This source file is subject to the New BSD License that is bundled | + | with this package in the file docs/LICENSE.txt. | + | | + | If you did not receive a copy of the license and are unable to | + | obtain it through the world-wide-web, please send an email | + | to license@phalconphp.com so we can send you a copy immediately. | + +------------------------------------------------------------------------+ + | Authors: Andres Gutierrez | + | Eduar Carvajal | + +------------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_phalcon.h" +#include "phalcon.h" + +#include "Zend/zend_operators.h" +#include "Zend/zend_exceptions.h" +#include "Zend/zend_interfaces.h" + +#include "kernel/main.h" +#include "kernel/memory.h" + +#include "kernel/array.h" +#include "kernel/string.h" +#include "kernel/concat.h" +#include "kernel/operators.h" +#include "kernel/exception.h" +#include "kernel/fcall.h" +#include "kernel/concat.h" +#include "kernel/object.h" +#include "kernel/output.h" + +/** + * Phalcon\Image\\Adapter\GD + * + * Image manipulation support. Allows images to be resized, cropped, etc. + * + * + * $image = new Phalcon\Image\Adapter\GD("upload/test.jpg"); + * $image->resize(200, 200); + * $image->save(); + * + */ + + +/** + * Phalcon\Image\Adapter\GD initializer + */ +PHALCON_INIT_CLASS(Phalcon_Image_Adapter_GD){ + + PHALCON_REGISTER_CLASS_EX(Phalcon\\Image\\Adapter, GD, image_adapter_gd, "phalcon\\image\\adapter", phalcon_image_adapter_gd_method_entry, 0); + + zend_class_implements(phalcon_image_adapter_gd_ce TSRMLS_CC, 1, phalcon_image_adapterinterface_ce); + + return SUCCESS; +} + +/** + * Checks if GD is enabled + * + * @return boolean + */ +PHP_METHOD(Phalcon_Image_Adapter_GD, check){ + + zval *func_name, *ret = NULL, *gd_info = NULL, *gd_version = NULL, *version, *exception_message; + zval *op, *pattern = NULL, *matches = NULL; + + PHALCON_MM_GROW(); + + PHALCON_INIT_VAR(func_name); + ZVAL_STRING(func_name, "gd_info", 1); + + PHALCON_INIT_NVAR(ret); + phalcon_call_func_p1(ret, "function_exists", func_name); + + if (!zend_is_true(ret)) { + PHALCON_THROW_EXCEPTION_STR(phalcon_image_exception_ce, "GD is either not installed or not enabled, check your configuration"); + return; + } + + PHALCON_INIT_NVAR(gd_version); + if (zend_get_constant(SL("GD_VERSION"), gd_version TSRMLS_CC) == FAILURE) { + + if (!gd_info) { + PHALCON_INIT_NVAR(gd_info); + phalcon_call_func(gd_info, "gd_info"); + } + + PHALCON_INIT_NVAR(pattern); + ZVAL_STRING(pattern, "#\\d+\\.\\d+(?:\\.\\d+)?#", 1); + + if (phalcon_array_isset_string(gd_info, SS("GD Version"))) { + PHALCON_OBS_NVAR(gd_version); + phalcon_array_fetch_string(&gd_version, gd_info, SL("GD Version"), PH_NOISY); + + PHALCON_INIT_NVAR(matches); + + PHALCON_INIT_NVAR(ret); + phalcon_preg_match(ret, pattern, gd_version, matches TSRMLS_CC); + + if (zend_is_true(ret)) { + if (phalcon_array_isset_long(matches, 0)) { + PHALCON_OBS_NVAR(gd_version); + phalcon_array_fetch_long(&gd_version, matches, 0, PH_NOISY); + } else { + PHALCON_INIT_NVAR(gd_version); + ZVAL_STRING(gd_version, "", 1); + } + } else { + PHALCON_INIT_NVAR(gd_version); + ZVAL_STRING(gd_version, "", 1); + } + } + } + + PHALCON_INIT_VAR(version); + ZVAL_STRING(version, "2.0.1", 1); + + PHALCON_INIT_VAR(op); + ZVAL_STRING(op, ">=", 1); + + PHALCON_INIT_NVAR(ret); + phalcon_call_func_p3(ret, "version_compare", gd_version, version, op); + + if (!zend_is_true(ret)) { + PHALCON_INIT_VAR(exception_message); + PHALCON_CONCAT_SVSVS(exception_message, "Image_GD requires GD version '", version ,"' or greater, you have '", gd_version, ","); + PHALCON_THROW_EXCEPTION_ZVAL(phalcon_image_exception_ce, exception_message); + return; + } + + phalcon_update_static_property(SL("phalcon\\image\\adapter\\gd"), SL("_checked"), ret TSRMLS_CC); + + ZVAL_BOOL(return_value, 1); + + RETURN_MM(); +} + +/** + * Phalcon\Image\GD constructor + * + * @param string $file + */ +PHP_METHOD(Phalcon_Image_Adapter_GD, __construct){ + + zval *file, *exception_message; + zval *checked = NULL, *realpath = NULL, *type = NULL, *mime = NULL, *image = NULL; + zval *ret, *saveflag; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 1, 0, &file); + + if (Z_TYPE_P(file) != IS_STRING) { + PHALCON_THROW_EXCEPTION_STR(phalcon_image_exception_ce, "file didn't return a valid string"); + return; + } + + PHALCON_OBS_VAR(checked); + phalcon_read_static_property(&checked, SL("phalcon\\image\\adapter\\gd"), SL("_checked") TSRMLS_CC); + + if (!zend_is_true(checked)) { + phalcon_call_static_noret("phalcon\\image\\adapter\\gd", "check"); + } + + phalcon_call_parent_p1_noret(this_ptr, phalcon_image_adapter_gd_ce, "__construct", file); + + PHALCON_OBS_VAR(realpath); + phalcon_read_property_this(&realpath, this_ptr, SL("_realpath"), PH_NOISY_CC); + + PHALCON_OBS_VAR(type); + phalcon_read_property_this(&type, this_ptr, SL("_type"), PH_NOISY_CC); + + PHALCON_OBS_VAR(mime); + phalcon_read_property_this(&mime, this_ptr, SL("_mime"), PH_NOISY_CC); + + switch (Z_LVAL_P(type)) { + case 1: // GIF + { + PHALCON_INIT_VAR(image); + phalcon_call_func_p1(image, "imagecreatefromgif", realpath); + break; + } + case 2: // JPEG + { + PHALCON_INIT_VAR(image); + phalcon_call_func_p1(image, "imagecreatefromjpeg", realpath); + break; + } + case 3: // PNG + { + PHALCON_INIT_VAR(image); + phalcon_call_func_p1(image, "imagecreatefrompng", realpath); + break; + } + default: + { + PHALCON_INIT_VAR(exception_message); + PHALCON_CONCAT_SVS(exception_message, "Installed GD does not support '", mime, "' images"); + PHALCON_THROW_EXCEPTION_ZVAL(phalcon_image_exception_ce, exception_message); + return; + } + } + + if (Z_TYPE_P(image) != IS_RESOURCE) { + PHALCON_INIT_VAR(exception_message); + PHALCON_CONCAT_SVS(exception_message, "Create image from file '", realpath, "' failure "); + PHALCON_THROW_EXCEPTION_ZVAL(phalcon_image_exception_ce, exception_message); + return; + } + + PHALCON_INIT_VAR(saveflag); + ZVAL_BOOL(saveflag, 1); + + phalcon_call_func_p2_noret("imagesavealpha", image, saveflag); + + phalcon_update_property_this(this_ptr, SL("_image"), image TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Execute a resize. + * + * @param int $width + * @param int $height + */ +PHP_METHOD(Phalcon_Image_Adapter_GD, _resize) { + + zval *width = NULL, *height = NULL, *ori_width, *ori_height, *pre_width, *pre_height, *reduction_width, *reduction_height; + zval *image = NULL, *tmp_image = NULL, *ret = NULL, *dst; + int tmp_width, tmp_height, tmp_pre_width, tmp_pre_height, tmp_reduction_width, tmp_reduction_height; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 2, 0, &width, &height); + + PHALCON_OBS_VAR(ori_width); + phalcon_read_property_this(&ori_width, this_ptr, SL("_width"), PH_NOISY_CC); + + PHALCON_OBS_VAR(ori_height); + phalcon_read_property_this(&ori_height, this_ptr, SL("_height"), PH_NOISY_CC); + + tmp_width = phalcon_get_intval(width); + tmp_height = phalcon_get_intval(height); + + tmp_pre_width = phalcon_get_intval(ori_width); + tmp_pre_height = phalcon_get_intval(ori_height); + + PHALCON_INIT_VAR(pre_width); + ZVAL_LONG(pre_width, tmp_pre_width); + + PHALCON_INIT_VAR(pre_height); + ZVAL_LONG(pre_height, tmp_pre_height); + + PHALCON_OBS_VAR(image); + phalcon_read_property_this(&image, this_ptr, SL("_image"), PH_NOISY_CC); + + PHALCON_INIT_VAR(dst); + ZVAL_LONG(dst, 0); + + if (tmp_width > (tmp_pre_width / 2) && tmp_height > (tmp_pre_height / 2)) { + tmp_reduction_width = (int)(tmp_width*1.1 + 0.5); + + PHALCON_INIT_VAR(reduction_width); + ZVAL_LONG(reduction_width, tmp_reduction_width); + + tmp_reduction_height = (int)(tmp_height*1.1 + 0.5); + + PHALCON_INIT_VAR(reduction_height); + ZVAL_LONG(reduction_height, tmp_reduction_height); + + while ((tmp_pre_width / 2 > tmp_reduction_width) && (tmp_pre_height / 2 > tmp_reduction_height)) { + tmp_pre_width = (int)(tmp_pre_width/2); + tmp_pre_height = (int)(tmp_pre_height/2); + } + + PHALCON_INIT_NVAR(pre_width); + ZVAL_LONG(pre_width, tmp_pre_width); + + PHALCON_INIT_NVAR(pre_height); + ZVAL_LONG(pre_height, tmp_pre_height); + + PHALCON_INIT_VAR(tmp_image); + + phalcon_call_method_p2(tmp_image, this_ptr, "_create", pre_width, pre_height); + + PHALCON_INIT_NVAR(ret); + PHALCON_CALL_FUNCTION(ret, "imagecopyresized", 10, tmp_image, image, dst, dst, dst, dst, pre_width, pre_height, ori_width, ori_height); + + if (zend_is_true(ret)) { + phalcon_call_func_p1_noret("imagedestroy", image); + PHALCON_CPY_WRT(image, tmp_image); + } + } + + PHALCON_INIT_NVAR(tmp_image); + phalcon_call_method_p2(tmp_image, this_ptr, "_create", width, height); + + PHALCON_INIT_NVAR(ret); + PHALCON_CALL_FUNCTION(ret, "imagecopyresampled", 10, tmp_image, image, dst, dst, dst, dst, width, height, pre_width, pre_height); + + if (zend_is_true(ret)) { + phalcon_call_func_p1_noret("imagedestroy", image); + phalcon_update_property_this(this_ptr, SL("_image"), tmp_image TSRMLS_CC); + + phalcon_update_property_this(this_ptr, SL("_width"), width TSRMLS_CC); + phalcon_update_property_this(this_ptr, SL("_height"), height TSRMLS_CC); + } + + PHALCON_MM_RESTORE(); +} + +/** + * Execute a crop. + * + * @param int $width + * @param int $height + * @param int $offset_x + * @param int $offset_y + */ +PHP_METHOD(Phalcon_Image_Adapter_GD, _crop) { + zval *width, *height, *offset_x, *offset_y; + zval *image, *tmp_image = NULL, *dst, *ret = NULL; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 4, 0, &width, &height, &offset_x, &offset_y); + + PHALCON_OBS_VAR(image); + phalcon_read_property_this(&image, this_ptr, SL("_image"), PH_NOISY_CC); + + PHALCON_INIT_NVAR(tmp_image); + phalcon_call_method_p2(tmp_image, this_ptr, "_create", width, height); + + PHALCON_INIT_VAR(dst); + ZVAL_LONG(dst, 0); + + PHALCON_INIT_NVAR(ret); + PHALCON_CALL_FUNCTION(ret, "imagecopyresampled", 10, tmp_image, image, dst, dst, offset_x, offset_y, width, height, width, height); + + if (zend_is_true(ret)) { + phalcon_call_func_p1_noret("imagedestroy", image); + phalcon_update_property_this(this_ptr, SL("_image"), tmp_image TSRMLS_CC); + + phalcon_update_property_this(this_ptr, SL("_width"), width TSRMLS_CC); + phalcon_update_property_this(this_ptr, SL("_height"), height TSRMLS_CC); + } + + PHALCON_MM_RESTORE(); +} + +/** + * Execute a rotation. + * + * @param int $degrees + */ +PHP_METHOD(Phalcon_Image_Adapter_GD, _rotate) { + + zval *degrees; + zval *bundled = NULL, *image = NULL, *tmp_image, *color, *alpha, *transparent, *ignore_transparent, *saveflag, *ret; + zval *w, *h, *dst, *pct; + int tmp_degrees; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 1, 0, °rees); + + PHALCON_SEPARATE_PARAM(degrees); + + PHALCON_INIT_VAR(color); + ZVAL_LONG(color, 0); + + PHALCON_INIT_VAR(alpha); + ZVAL_LONG(alpha, 127); + + PHALCON_OBS_VAR(image); + phalcon_read_property_this(&image, this_ptr, SL("_image"), PH_NOISY_CC); + + PHALCON_INIT_VAR(transparent); + phalcon_call_func_p5(transparent, "imagecolorallocatealpha", image, color, color, color, alpha); + + tmp_degrees = phalcon_get_intval(degrees); + + PHALCON_INIT_NVAR(degrees); + ZVAL_LONG(degrees, 360 - tmp_degrees); + + PHALCON_INIT_VAR(ignore_transparent); + ZVAL_LONG(ignore_transparent, 1); + + PHALCON_INIT_VAR(tmp_image); + phalcon_call_func_p4(tmp_image, "imagerotate", image, degrees, transparent, ignore_transparent); + + PHALCON_INIT_VAR(saveflag); + ZVAL_BOOL(saveflag, 1); + + phalcon_call_func_p2_noret("imagesavealpha", tmp_image, saveflag); + + PHALCON_INIT_VAR(w); + phalcon_call_func_p1(w, "imagesx", tmp_image); + + PHALCON_INIT_VAR(h); + phalcon_call_func_p1(h, "imagesy", tmp_image); + + phalcon_call_func_p1_noret("imagedestroy", image); + phalcon_update_property_this(this_ptr, SL("_image"), tmp_image TSRMLS_CC); + + phalcon_update_property_this(this_ptr, SL("_width"), w TSRMLS_CC); + phalcon_update_property_this(this_ptr, SL("_height"), h TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Execute a flip. + * + * @param int $direction + */ +PHP_METHOD(Phalcon_Image_Adapter_GD, _flip) { + + zval *direction; + zval *image = NULL, *flipped_image, *width, *height, *dst_x = NULL, *dst_y = NULL, *src_x = NULL, *src_y = NULL, *src_width = NULL, *src_height = NULL; + int w, h, x, y; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 1, 0, &direction); + + PHALCON_OBS_VAR(width); + phalcon_read_property_this(&width, this_ptr, SL("_width"), PH_NOISY_CC); + + PHALCON_OBS_VAR(height); + phalcon_read_property_this(&height, this_ptr, SL("_height"), PH_NOISY_CC); + + PHALCON_OBS_VAR(image); + phalcon_read_property_this(&image, this_ptr, SL("_image"), PH_NOISY_CC); + + PHALCON_INIT_VAR(flipped_image); + phalcon_call_method_p2(flipped_image, this_ptr, "_create", width, height); + + w = Z_LVAL_P(width); + h = Z_LVAL_P(height); + + if (Z_LVAL_P(direction) == 11) { + + PHALCON_INIT_NVAR(dst_y); + ZVAL_LONG(dst_y, 0); + + PHALCON_INIT_NVAR(src_y); + ZVAL_LONG(src_y, 0); + + PHALCON_INIT_NVAR(src_width); + ZVAL_LONG(src_width, 1); + + PHALCON_INIT_NVAR(src_height); + ZVAL_LONG(src_height, h); + + for (x = 0; x < w; x++) + { + PHALCON_INIT_NVAR(dst_x); + ZVAL_LONG(dst_x, x); + + PHALCON_INIT_NVAR(src_x); + ZVAL_LONG(src_x, w - x - 1); + + PHALCON_CALL_FUNCTION(NULL, "imagecopy", 8, flipped_image, image, dst_x, dst_y, src_x, src_y, src_width, src_height); + } + } else { + PHALCON_INIT_NVAR(dst_x); + ZVAL_LONG(dst_x, 0); + + PHALCON_INIT_NVAR(src_x); + ZVAL_LONG(src_x, 0); + + PHALCON_INIT_NVAR(src_width); + ZVAL_LONG(src_width, w); + + PHALCON_INIT_NVAR(src_height); + ZVAL_LONG(src_height, 1); + + for (y = 0; y < h; y++) + { + PHALCON_INIT_NVAR(dst_y); + ZVAL_LONG(dst_y, y); + + PHALCON_INIT_NVAR(src_y); + ZVAL_LONG(src_y, h - y - 1); + + PHALCON_CALL_FUNCTION(NULL, "imagecopy", 8, flipped_image, image, dst_x, dst_y, src_x, src_y, src_width, src_height); + } + } + + phalcon_call_func_p1_noret("imagedestroy", image); + phalcon_update_property_this(this_ptr, SL("_image"), flipped_image TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Execute a sharpen. + * + * @param int $amount + */ +PHP_METHOD(Phalcon_Image_Adapter_GD, _sharpen) { + + zval *amount, *tmp = NULL, *tmp_amount = NULL, *precision, *matrix, *item = NULL; + zval *bundled = NULL, *image = NULL, *tmp_image, *ret, *width = NULL, *height = NULL; + int a; + double b; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 1, 0, &amount); + + PHALCON_OBS_VAR(image); + phalcon_read_property_this(&image, this_ptr, SL("_image"), PH_NOISY_CC); + + a = phalcon_get_intval(amount); + b = a; + + b = -18 + (a * 0.08); + + if (b < 0) { + b = b * -1; + } + + PHALCON_INIT_NVAR(tmp_amount); + ZVAL_DOUBLE(tmp_amount, b); + + PHALCON_INIT_NVAR(tmp); + ZVAL_LONG(tmp, a); + + PHALCON_INIT_VAR(precision); + ZVAL_LONG(precision, 2); + + PHALCON_INIT_NVAR(tmp_amount); + phalcon_call_func_p2(tmp_amount, "round", tmp, precision); + + PHALCON_INIT_VAR(matrix); + array_init_size(matrix, 3); + + // 1 + PHALCON_INIT_NVAR(item); + array_init_size(item, 3); + + phalcon_array_append_long(&item, -1, PH_SEPARATE); + phalcon_array_append_long(&item, -1, PH_SEPARATE); + phalcon_array_append_long(&item, -1, PH_SEPARATE); + + phalcon_array_append(&matrix, item, PH_SEPARATE); + + // 2 + PHALCON_INIT_NVAR(item); + array_init_size(item, 3); + + phalcon_array_append_long(&item, -1, PH_SEPARATE); + phalcon_array_append(&item, tmp_amount, PH_SEPARATE); + phalcon_array_append_long(&item, -1, PH_SEPARATE); + + phalcon_array_append(&matrix, item, PH_SEPARATE); + + // 3 + PHALCON_INIT_NVAR(item); + array_init_size(item, 3); + + phalcon_array_append_long(&item, -1, PH_SEPARATE); + phalcon_array_append_long(&item, -1, PH_SEPARATE); + phalcon_array_append_long(&item, -1, PH_SEPARATE); + + phalcon_array_append(&matrix, item, PH_SEPARATE); + + b = b - 8; + + PHALCON_INIT_NVAR(tmp_amount); + ZVAL_DOUBLE(tmp_amount, b); + + PHALCON_INIT_NVAR(tmp); + ZVAL_LONG(tmp, 0); + + PHALCON_INIT_VAR(ret); + phalcon_call_func_p4(ret, "imageconvolution", image, matrix, tmp_amount, tmp); + + if (zend_is_true(ret)) { + phalcon_update_property_this(this_ptr, SL("_image"), image TSRMLS_CC); + + PHALCON_INIT_NVAR(width); + phalcon_call_func_p1(width, "imagesx", image); + + PHALCON_INIT_NVAR(height); + phalcon_call_func_p1(height, "imagesy", image); + + phalcon_update_property_this(this_ptr, SL("_width"), width TSRMLS_CC); + phalcon_update_property_this(this_ptr, SL("_height"), height TSRMLS_CC); + } + + PHALCON_MM_RESTORE(); +} + +/** + * Execute a reflection. + * + * @param int $height + * @param int $opacity + * @param boolean $fade_in + */ +PHP_METHOD(Phalcon_Image_Adapter_GD, _reflection) { + + zval *height, *opacity, *fade_in, *o = NULL, *tmp = NULL; + zval *reflection, *line = NULL, *image, *image_width, *image_height, *dst, *src_y = NULL, *dst_y = NULL, *dst_opacity = NULL, *filtertype = NULL; + int h0, h1, tmp_opacity, int_opacity, offset; + double stepping; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 3, 0, &height, &opacity, &fade_in); + + PHALCON_SEPARATE_PARAM(height); + + PHALCON_OBS_VAR(image); + phalcon_read_property_this(&image, this_ptr, SL("_image"), PH_NOISY_CC); + + PHALCON_OBS_VAR(image_width); + phalcon_read_property_this(&image_width, this_ptr, SL("_width"), PH_NOISY_CC); + + PHALCON_OBS_VAR(image_height); + phalcon_read_property_this(&image_height, this_ptr, SL("_height"), PH_NOISY_CC); + + PHALCON_INIT_VAR(filtertype); + if (zend_get_constant(SL("IMG_FILTER_COLORIZE"), filtertype TSRMLS_CC) == FAILURE) { + RETURN_MM(); + } + + h0 = phalcon_get_intval(height); + h1 = phalcon_get_intval(image_height); + + tmp_opacity = phalcon_get_intval(opacity); + + tmp_opacity = (int)((tmp_opacity * 127 / 100) - 127 + 0.5); + + if (tmp_opacity < 0) { + tmp_opacity = tmp_opacity * -1; + } + + if (tmp_opacity < 127) { + stepping = (127 - tmp_opacity) / h0; + } else { + stepping = 127 / h0; + } + + PHALCON_INIT_NVAR(height); + ZVAL_DOUBLE(height, h0 + h1); + + PHALCON_INIT_VAR(reflection); + phalcon_call_method_p2(reflection, this_ptr, "_create", image_width, height); + + PHALCON_INIT_VAR(dst); + ZVAL_LONG(dst, 0); + + PHALCON_CALL_FUNCTION(NULL, "imagecopy", 8, reflection, image, dst, dst, dst, dst, image_width, image_height); + + PHALCON_INIT_NVAR(tmp); + ZVAL_LONG(tmp, 1); + + for (offset = 0; h0 >= offset; offset++) { + PHALCON_INIT_NVAR(src_y); + ZVAL_LONG(src_y, h1 - offset - 1); + + PHALCON_INIT_NVAR(dst_y); + ZVAL_LONG(dst_y, h1 + offset); + + if (zend_is_true(fade_in)) { + + int_opacity = (int)(tmp_opacity + (stepping * (h0 - offset)) + 0.5); + + PHALCON_INIT_NVAR(dst_opacity); + ZVAL_LONG(dst_opacity, int_opacity); + } else { + int_opacity = (int)(tmp_opacity + (stepping * offset) + 0.5); + + PHALCON_INIT_NVAR(dst_opacity); + ZVAL_LONG(dst_opacity, int_opacity); + } + + PHALCON_INIT_NVAR(line); + phalcon_call_method_p2(line, this_ptr, "_create", image_width, tmp); + + PHALCON_CALL_FUNCTION(NULL, "imagecopy", 8, line, image, dst, dst, dst, src_y, image_width, tmp); + PHALCON_CALL_FUNCTION(NULL, "imagefilter", 6, line, filtertype, dst, dst, dst, dst_opacity); + + PHALCON_CALL_FUNCTION(NULL, "imagecopy", 8, reflection, line, dst, dst_y, dst, dst, image_width, tmp); + } + + phalcon_call_func_p1_noret("imagedestroy", image); + phalcon_update_property_this(this_ptr, SL("_image"), reflection TSRMLS_CC); + + PHALCON_INIT_NVAR(image_width); + phalcon_call_func_p1(image_width, "imagesx", reflection); + + PHALCON_INIT_NVAR(image_height); + phalcon_call_func_p1(image_height, "imagesy", reflection); + + phalcon_update_property_this(this_ptr, SL("_width"), image_width TSRMLS_CC); + phalcon_update_property_this(this_ptr, SL("_height"), image_height TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Execute a watermarking. + * + * @param Phalcon\Image\Adapter $watermark + * @param int $offset_x + * @param int $offset_y + * @param int $opacity + */ +PHP_METHOD(Phalcon_Image_Adapter_GD, _watermark) { + + zval *watermark, *offset_x = NULL, *offset_y = NULL, *opacity = NULL, *ox = NULL, *oy = NULL, *op = NULL; + zval *image, *overlay, *saveflag, *width, *height, *color, *tmp = NULL, *effect, *blendmode, *ret; + int int_opacity; + double num; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 4, 0, &watermark, &offset_x, &offset_y, &opacity); + + PHALCON_SEPARATE_PARAM(watermark); + + PHALCON_OBS_VAR(image); + phalcon_read_property_this(&image, this_ptr, SL("_image"), PH_NOISY_CC); + + PHALCON_INIT_VAR(overlay); + phalcon_call_method(overlay, watermark, "getImage"); + + PHALCON_INIT_VAR(saveflag); + ZVAL_BOOL(saveflag, 1); + + phalcon_call_func_p2_noret("imagesavealpha", overlay, saveflag); + + PHALCON_INIT_VAR(width); + phalcon_call_func_p1(width, "imagesx", overlay); + + PHALCON_INIT_VAR(height); + phalcon_call_func_p1(height, "imagesy", overlay); + + int_opacity = Z_LVAL_P(opacity); + if (int_opacity < 100) { + num = (int_opacity * 127 / 100) - 127; + + if (num < 0) { + num = num * -1; + } + + int_opacity = num; + + PHALCON_INIT_VAR(op); + ZVAL_LONG(op, int_opacity); + + PHALCON_INIT_NVAR(tmp); + ZVAL_LONG(tmp, 127); + + + PHALCON_INIT_VAR(color); + phalcon_call_func_p5(color, "imagecolorallocatealpha", overlay, tmp, tmp, tmp, op); + + PHALCON_INIT_VAR(effect); + if (zend_get_constant(SL("IMG_EFFECT_OVERLAY"), effect TSRMLS_CC) == FAILURE) { + RETURN_MM(); + } + + phalcon_call_func_p2_noret("imagelayereffect", overlay, effect); + + PHALCON_INIT_NVAR(tmp); + ZVAL_LONG(tmp, 0); + + PHALCON_CALL_FUNCTION(NULL, "imagefilledrectangle", 6, overlay, tmp, tmp, width, height, color); + } + + PHALCON_INIT_NVAR(blendmode); + ZVAL_LONG(blendmode, 1); + phalcon_call_func_p2_noret("imagealphablending", image, blendmode); + + PHALCON_INIT_NVAR(tmp); + ZVAL_LONG(tmp, 0); + + PHALCON_INIT_VAR(ret); + PHALCON_CALL_FUNCTION(ret, "imagecopy", 8, image, overlay, offset_x, offset_y, tmp, tmp, width, height); + + if (zend_is_true(ret)) { + ZVAL_BOOL(return_value, 1); + } else { + ZVAL_BOOL(return_value, 0); + } + + PHALCON_MM_RESTORE(); +} + +/** + * Execute a background. + * + * @param int $r + * @param int $g + * @param int $b + * @param int $opacity + */ +PHP_METHOD(Phalcon_Image_Adapter_GD, _background) { + + zval *r, *g, *b, *opacity, *op; + zval *image, *background, *width, *height, *color, *tmp, *blendmode, *ret; + int int_opacity; + double num; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 4, 0, &r, &g, &b, &opacity); + + PHALCON_OBS_VAR(image); + phalcon_read_property_this(&image, this_ptr, SL("_image"), PH_NOISY_CC); + + PHALCON_OBS_VAR(width); + phalcon_read_property_this(&width, this_ptr, SL("_width"), PH_NOISY_CC); + + PHALCON_OBS_VAR(height); + phalcon_read_property_this(&height, this_ptr, SL("_height"), PH_NOISY_CC); + + int_opacity = Z_LVAL_P(opacity); + + num = (int_opacity * 127 / 100) - 127; + + if (num < 0) { + num = num * -1; + } + + int_opacity = num; + + PHALCON_INIT_VAR(background); + phalcon_call_method_p2(background, this_ptr, "_create", width, height); + + PHALCON_INIT_VAR(op); + ZVAL_LONG(op, int_opacity); + + PHALCON_INIT_VAR(color); + phalcon_call_func_p5(color, "imagecolorallocatealpha", background, r, g, b, op); + + PHALCON_INIT_VAR(tmp); + ZVAL_LONG(tmp, 0); + + PHALCON_CALL_FUNCTION(NULL, "imagefilledrectangle", 6, background, tmp, tmp, width, height, color); + + PHALCON_INIT_VAR(blendmode); + ZVAL_BOOL(blendmode, 1); + + phalcon_call_func_p2_noret("imagealphablending", background, blendmode); + + PHALCON_INIT_VAR(ret); + PHALCON_CALL_FUNCTION(ret, "imagecopy", 8, background, image, tmp, tmp, tmp, tmp, width, height); + + if (zend_is_true(ret)) { + phalcon_call_func_p1_noret("imagedestroy", image); + phalcon_update_property_this(this_ptr, SL("_image"), background TSRMLS_CC); + } + + PHALCON_MM_RESTORE(); +} + +/** + * Execute a save. + * + * @param string $file + * @param int $quality + * @return boolean + */ +PHP_METHOD(Phalcon_Image_Adapter_GD, _save) { + + zval *file = NULL, *quality = NULL, *exception_message, *q = NULL; + zval *ret, *extension, *type, *mime, *constant, *image; + const char *func_name = "imagegif"; + char *ext; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 2, 0, &file, &quality); + + PHALCON_INIT_VAR(constant); + if (zend_get_constant(SL("PATHINFO_EXTENSION"), constant TSRMLS_CC) == FAILURE) { + RETURN_MM(); + } + + PHALCON_INIT_VAR(ret); + phalcon_call_func_p2(ret, "pathinfo", file, constant); + + PHALCON_INIT_VAR(extension); + phalcon_fast_strtolower(extension, ret); + + ext = Z_STRVAL_P(extension); + + if (strncmp(ext, "gif", 3) == 0) { + PHALCON_INIT_VAR(type); + ZVAL_LONG(type, 1); + + PHALCON_INIT_NVAR(q); + + func_name = "imagegif"; + } else if (strncmp(ext, "jpg", 3) == 0 || strncmp(ext, "jpeg", 4) == 0) { + PHALCON_INIT_VAR(type); + ZVAL_LONG(type, 2); + + PHALCON_CPY_WRT(q, quality); + + func_name = "imagejpeg"; + } else if (strncmp(ext, "png", 3) == 0) { + PHALCON_INIT_VAR(type); + ZVAL_LONG(type, 3); + + PHALCON_INIT_NVAR(q); + ZVAL_LONG(q, 9); + + func_name = "imagepng"; + } else { + PHALCON_INIT_VAR(exception_message); + PHALCON_CONCAT_SVS(exception_message, "Installed GD does not support '", extension, "' images"); + PHALCON_THROW_EXCEPTION_ZVAL(phalcon_image_exception_ce, exception_message); + return; + } + + PHALCON_OBS_VAR(image); + phalcon_read_property_this(&image, this_ptr, SL("_image"), PH_NOISY_CC); + + if (Z_TYPE_P(quality) == IS_LONG) { + PHALCON_INIT_NVAR(ret); + phalcon_call_func_p3(ret, func_name, image, file, q); + } else { + PHALCON_INIT_NVAR(ret); + phalcon_call_func_p2(ret, func_name, image, file); + } + + if (zend_is_true(ret)) { + phalcon_update_property_this(this_ptr, SL("_type"), type TSRMLS_CC); + + PHALCON_INIT_VAR(mime); + phalcon_call_func_p1(mime, "image_type_to_mime_type", type); + phalcon_update_property_this(this_ptr, SL("_mime"), mime TSRMLS_CC); + + ZVAL_BOOL(return_value, 1); + } else { + ZVAL_BOOL(return_value, 0); + } + + RETURN_MM(); +} + +/** + * Execute a render. + * + * @param string $type + * @param int $quality + * @return string + */ +PHP_METHOD(Phalcon_Image_Adapter_GD, _render) { + + zval *extension = NULL, *quality = NULL, *exception_message, *q = NULL; + zval *file, *ret = NULL, *type, *mime, *image; + const char *func_name = "imagegif"; + char *ext; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 2, 0, &extension, &quality); + + PHALCON_INIT_VAR(file); + + PHALCON_INIT_VAR(ret); + phalcon_fast_strtolower(ret, extension); + + ext = Z_STRVAL_P(ret); + + if (strncmp(ext, "gif", 3) == 0) { + PHALCON_INIT_VAR(type); + ZVAL_LONG(type, 1); + + PHALCON_INIT_NVAR(q); + + func_name = "imagegif"; + } else if (strncmp(ext, "jpg", 3) == 0 || strncmp(ext, "jpeg", 4) == 0) { + PHALCON_INIT_VAR(type); + ZVAL_LONG(type, 2); + + PHALCON_CPY_WRT(q, quality); + + func_name = "imagejpeg"; + } else if (strncmp(ext, "png", 3) == 0) { + PHALCON_INIT_VAR(type); + ZVAL_LONG(type, 3); + + PHALCON_INIT_NVAR(q); + ZVAL_LONG(q, 9); + + func_name = "imagepng"; + } else { + PHALCON_INIT_VAR(exception_message); + PHALCON_CONCAT_SVS(exception_message, "Installed GD does not support '", extension, "' images"); + PHALCON_THROW_EXCEPTION_ZVAL(phalcon_image_exception_ce, exception_message); + return; + } + + PHALCON_OBS_VAR(image); + phalcon_read_property_this(&image, this_ptr, SL("_image"), PH_NOISY_CC); + + phalcon_ob_start(TSRMLS_C); + + if (Z_TYPE_P(quality) == IS_LONG) { + PHALCON_INIT_NVAR(ret); + phalcon_call_func_p3(ret, func_name, image, file, q); + } else { + PHALCON_INIT_NVAR(ret); + phalcon_call_func_p2(ret, func_name, image, file); + } + + phalcon_ob_get_contents(return_value TSRMLS_CC); + phalcon_ob_end_clean(TSRMLS_C); + + if (zend_is_true(ret)) { + phalcon_update_property_this(this_ptr, SL("_type"), type TSRMLS_CC); + + PHALCON_INIT_VAR(mime); + phalcon_call_func_p1(mime, "image_type_to_mime_type", type); + phalcon_update_property_this(this_ptr, SL("_mime"), mime TSRMLS_CC); + } + + RETURN_MM(); +} + +/** + * Create an empty image with the given width and height. + * + * @param int $width + * @param int $height + * @return resource + */ +PHP_METHOD(Phalcon_Image_Adapter_GD, _create) { + + zval *width, *height, *image, *blendmode, *saveflag; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 2, 0, &width, &height); + + PHALCON_INIT_VAR(image); + phalcon_call_func_p2(image, "imagecreatetruecolor", width, height); + + if (Z_TYPE_P(image) != IS_RESOURCE) { + PHALCON_THROW_EXCEPTION_STR(phalcon_image_exception_ce, "Call imagecreatetruecolor failure"); + return; + } + + PHALCON_INIT_VAR(blendmode); + ZVAL_BOOL(blendmode, 0); + + PHALCON_INIT_VAR(saveflag); + ZVAL_BOOL(saveflag, 1); + + phalcon_call_func_p2_noret("imagealphablending", image, blendmode); + phalcon_call_func_p2_noret("imagesavealpha", image, saveflag); + + RETURN_CCTOR(image); +} + +/** + * Destroys the loaded image to free up resources. + */ +PHP_METHOD(Phalcon_Image_Adapter_GD, __destruct){ + + zval *image = NULL; + + PHALCON_MM_GROW(); + + PHALCON_OBS_VAR(image); + phalcon_read_property_this(&image, this_ptr, SL("_image"), PH_NOISY_CC); + + if (!image && Z_TYPE_P(image) == IS_RESOURCE) { + phalcon_call_func_p1_noret("imagedestroy", image); + } + + PHALCON_MM_RESTORE(); +} + diff --git a/ext/image/adapter/gd.h b/ext/image/adapter/gd.h new file mode 100644 index 00000000000..0b353650240 --- /dev/null +++ b/ext/image/adapter/gd.h @@ -0,0 +1,119 @@ + +/* + +------------------------------------------------------------------------+ + | Phalcon Framework | + +------------------------------------------------------------------------+ + | Copyright (c) 2011-2013 Phalcon Team (http://www.phalconphp.com) | + +------------------------------------------------------------------------+ + | This source file is subject to the New BSD License that is bundled | + | with this package in the file docs/LICENSE.txt. | + | | + | If you did not receive a copy of the license and are unable to | + | obtain it through the world-wide-web, please send an email | + | to license@phalconphp.com so we can send you a copy immediately. | + +------------------------------------------------------------------------+ + | Authors: Andres Gutierrez | + | Eduar Carvajal | + +------------------------------------------------------------------------+ +*/ + +extern zend_class_entry *phalcon_image_adapter_gd_ce; + +PHALCON_INIT_CLASS(Phalcon_Image_Adapter_GD); + +PHP_METHOD(Phalcon_Image_Adapter_GD, check); +PHP_METHOD(Phalcon_Image_Adapter_GD, __construct); +PHP_METHOD(Phalcon_Image_Adapter_GD, _resize); +PHP_METHOD(Phalcon_Image_Adapter_GD, _crop); +PHP_METHOD(Phalcon_Image_Adapter_GD, _rotate); +PHP_METHOD(Phalcon_Image_Adapter_GD, _flip); +PHP_METHOD(Phalcon_Image_Adapter_GD, _sharpen); +PHP_METHOD(Phalcon_Image_Adapter_GD, _reflection); +PHP_METHOD(Phalcon_Image_Adapter_GD, _watermark); +PHP_METHOD(Phalcon_Image_Adapter_GD, _background); +PHP_METHOD(Phalcon_Image_Adapter_GD, _save); +PHP_METHOD(Phalcon_Image_Adapter_GD, _render); +PHP_METHOD(Phalcon_Image_Adapter_GD, _create); +PHP_METHOD(Phalcon_Image_Adapter_GD, __destruct); + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_gd___construct, 0, 0, 1) + ZEND_ARG_INFO(0, file) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_gd__resize, 0, 0, 2) + ZEND_ARG_INFO(0, width) + ZEND_ARG_INFO(0, height) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_gd__crop, 0, 0, 4) + ZEND_ARG_INFO(0, width) + ZEND_ARG_INFO(0, height) + ZEND_ARG_INFO(0, offset_x) + ZEND_ARG_INFO(0, offset_y) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_gd__rotate, 0, 0, 1) + ZEND_ARG_INFO(0, degrees) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_gd__flip, 0, 0, 1) + ZEND_ARG_INFO(0, direction) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_gd__sharpen, 0, 0, 1) + ZEND_ARG_INFO(0, amount) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_gd__reflection, 0, 0, 3) + ZEND_ARG_INFO(0, height) + ZEND_ARG_INFO(0, opacity) + ZEND_ARG_INFO(0, fade_in) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_gd__watermark, 0, 0, 4) + ZEND_ARG_INFO(0, watermark) + ZEND_ARG_INFO(0, offset_x) + ZEND_ARG_INFO(0, offset_y) + ZEND_ARG_INFO(0, opacity) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_gd__background, 0, 0, 4) + ZEND_ARG_INFO(0, r) + ZEND_ARG_INFO(0, g) + ZEND_ARG_INFO(0, b) + ZEND_ARG_INFO(0, quality) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_gd__save, 0, 0, 2) + ZEND_ARG_INFO(0, file) + ZEND_ARG_INFO(0, quality) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_gd__render, 0, 0, 2) + ZEND_ARG_INFO(0, type) + ZEND_ARG_INFO(0, quality) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_gd__create, 0, 0, 2) + ZEND_ARG_INFO(0, width) + ZEND_ARG_INFO(0, height) +ZEND_END_ARG_INFO() + +PHALCON_INIT_FUNCS(phalcon_image_adapter_gd_method_entry) { + PHP_ME(Phalcon_Image_Adapter_GD, check, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Phalcon_Image_Adapter_GD, __construct, arginfo_phalcon_image_adapter_gd___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) + PHP_ME(Phalcon_Image_Adapter_GD, _resize, arginfo_phalcon_image_adapter_gd__resize, ZEND_ACC_PROTECTED) + PHP_ME(Phalcon_Image_Adapter_GD, _crop, arginfo_phalcon_image_adapter_gd__crop, ZEND_ACC_PROTECTED) + PHP_ME(Phalcon_Image_Adapter_GD, _rotate, arginfo_phalcon_image_adapter_gd__rotate, ZEND_ACC_PROTECTED) + PHP_ME(Phalcon_Image_Adapter_GD, _flip, arginfo_phalcon_image_adapter_gd__flip, ZEND_ACC_PROTECTED) + PHP_ME(Phalcon_Image_Adapter_GD, _sharpen, arginfo_phalcon_image_adapter_gd__sharpen, ZEND_ACC_PROTECTED) + PHP_ME(Phalcon_Image_Adapter_GD, _reflection, arginfo_phalcon_image_adapter_gd__reflection, ZEND_ACC_PROTECTED) + PHP_ME(Phalcon_Image_Adapter_GD, _watermark, arginfo_phalcon_image_adapter_gd__watermark, ZEND_ACC_PROTECTED) + PHP_ME(Phalcon_Image_Adapter_GD, _background, arginfo_phalcon_image_adapter_gd__background, ZEND_ACC_PROTECTED) + PHP_ME(Phalcon_Image_Adapter_GD, _save, arginfo_phalcon_image_adapter_gd__save, ZEND_ACC_PROTECTED) + PHP_ME(Phalcon_Image_Adapter_GD, _render, arginfo_phalcon_image_adapter_gd__render, ZEND_ACC_PROTECTED) + PHP_ME(Phalcon_Image_Adapter_GD, _create, arginfo_phalcon_image_adapter_gd__create, ZEND_ACC_PROTECTED) + PHP_ME(Phalcon_Image_Adapter_GD, __destruct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_DTOR) + PHP_FE_END +}; + diff --git a/ext/image/adapter/imagick.c b/ext/image/adapter/imagick.c new file mode 100644 index 00000000000..c249474b505 --- /dev/null +++ b/ext/image/adapter/imagick.c @@ -0,0 +1,852 @@ + +/* + +------------------------------------------------------------------------+ + | Phalcon Framework | + +------------------------------------------------------------------------+ + | Copyright (c) 2011-2013 Phalcon Team (http://www.phalconphp.com) | + +------------------------------------------------------------------------+ + | This source file is subject to the New BSD License that is bundled | + | with this package in the file docs/LICENSE.txt. | + | | + | If you did not receive a copy of the license and are unable to | + | obtain it through the world-wide-web, please send an email | + | to license@phalconphp.com so we can send you a copy immediately. | + +------------------------------------------------------------------------+ + | Authors: Andres Gutierrez | + | Eduar Carvajal | + +------------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_phalcon.h" +#include "phalcon.h" + +#include "Zend/zend_operators.h" +#include "Zend/zend_exceptions.h" +#include "Zend/zend_interfaces.h" + +#include "kernel/main.h" +#include "kernel/memory.h" + +#include "kernel/array.h" +#include "kernel/string.h" +#include "kernel/concat.h" +#include "kernel/operators.h" +#include "kernel/exception.h" +#include "kernel/fcall.h" +#include "kernel/concat.h" +#include "kernel/object.h" +#include "kernel/output.h" + +/** + * Phalcon\Image\\Adapter\Imagick + * + * Image manipulation support. Allows images to be resized, cropped, etc. + * + * + * $image = new Phalcon\Image\Adapter\Imagick("upload/test.jpg"); + * $image->resize(200, 200); + * $image->save(); + * + */ + + +/** + * Phalcon\Image\Adapter\Imagick initializer + */ +PHALCON_INIT_CLASS(Phalcon_Image_Adapter_Imagick){ + + PHALCON_REGISTER_CLASS_EX(Phalcon\\Image\\Adapter, Imagick, image_adapter_imagick, "phalcon\\image\\adapter", phalcon_image_adapter_imagick_method_entry, 0); + + zend_class_implements(phalcon_image_adapter_imagick_ce TSRMLS_CC, 1, phalcon_image_adapterinterface_ce); + + return SUCCESS; +} + +/** + * Checks if Imagick is enabled + * + * @return boolean + */ +PHP_METHOD(Phalcon_Image_Adapter_Imagick, check){ + + zval *module_name, *ret = NULL, *exception_message; + + PHALCON_MM_GROW(); + + PHALCON_INIT_VAR(module_name); + ZVAL_STRING(module_name, "imagick", 1); + + PHALCON_INIT_NVAR(ret); + phalcon_call_func_p1(ret, "extension_loaded", module_name); + + if (!zend_is_true(ret)) { + PHALCON_THROW_EXCEPTION_STR(phalcon_image_exception_ce, "Imagick is not installed, or the extension is not loaded"); + return; + } + + phalcon_update_static_property(SL("phalcon\\image\\adapter\\imagick"), SL("_checked"), ret TSRMLS_CC); + + ZVAL_BOOL(return_value, 1); + + RETURN_MM(); +} + +/** + * Phalcon\Image\Imagick constructor + * + * @param string $file + */ +PHP_METHOD(Phalcon_Image_Adapter_Imagick, __construct){ + + zval *file, *exception_message; + zval *checked = NULL, *realpath, *im, *ret, *mode; + zend_class_entry *ce0; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 1, 0, &file); + + if (Z_TYPE_P(file) != IS_STRING) { + PHALCON_THROW_EXCEPTION_STR(phalcon_image_exception_ce, "file didn't return a valid string"); + return; + } + + PHALCON_OBS_VAR(checked); + phalcon_read_static_property(&checked, SL("phalcon\\image\\adapter\\imagick"), SL("_checked") TSRMLS_CC); + + if (!zend_is_true(checked)) { + phalcon_call_static_noret("phalcon\\image\\adapter\\imagick", "check"); + } + + phalcon_call_parent_p1_noret(this_ptr, phalcon_image_adapter_imagick_ce, "__construct", file); + + PHALCON_OBS_VAR(realpath); + phalcon_read_property_this(&realpath, this_ptr, SL("_realpath"), PH_NOISY_CC); + + ce0 = zend_fetch_class(SL("Imagick"), ZEND_FETCH_CLASS_AUTO TSRMLS_CC); + + PHALCON_INIT_VAR(im); + object_init_ex(im, ce0); + if (phalcon_has_constructor(im TSRMLS_CC)) { + phalcon_call_method_noret(im, "__construct"); + } + + phalcon_call_method_p1_noret(im, "readImage", realpath); + + PHALCON_INIT_VAR(ret); + phalcon_call_method(ret, im, "getImageAlphaChannel"); + + if (!zend_is_true(ret)) { + PHALCON_INIT_VAR(mode); + phalcon_get_class_constant(mode, ce0, SS("ALPHACHANNEL_SET") TSRMLS_CC); + phalcon_call_method_p1_noret(im, "setImageAlphaChannel", mode); + } + + phalcon_update_property_this(this_ptr, SL("_image"), im TSRMLS_CC); + + PHALCON_MM_RESTORE(); +} + +/** + * Execute a resize. + * + * @param int $width + * @param int $height + * @return boolean + */ +PHP_METHOD(Phalcon_Image_Adapter_Imagick, _resize) { + + zval *width = NULL, *height = NULL; + zval *im, *ret, *w, *h; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 2, 0, &width, &height); + + PHALCON_OBS_VAR(im); + phalcon_read_property_this(&im, this_ptr, SL("_image"), PH_NOISY_CC); + + PHALCON_INIT_VAR(ret); + phalcon_call_method_p2(ret, im, "scaleImage", width, height); + + if (zend_is_true(ret)) { + PHALCON_INIT_VAR(w); + phalcon_call_method(w, im, "getImageWidth"); + + PHALCON_INIT_VAR(h); + phalcon_call_method(h, im, "getImageHeight"); + + phalcon_update_property_this(this_ptr, SL("_width"), w TSRMLS_CC); + phalcon_update_property_this(this_ptr, SL("_height"), h TSRMLS_CC); + + ZVAL_BOOL(return_value, 1); + } else { + ZVAL_BOOL(return_value, 0); + } + + PHALCON_MM_RESTORE(); +} + +/** + * Execute a crop. + * + * @param int $width + * @param int $height + * @param int $offset_x + * @param int $offset_y + * @return boolean + */ +PHP_METHOD(Phalcon_Image_Adapter_Imagick, _crop) { + + zval *width, *height, *offset_x, *offset_y; + zval *im, *ret, *w, *h, *tmp; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 4, 0, &width, &height, &offset_x, &offset_y); + + PHALCON_OBS_VAR(im); + phalcon_read_property_this(&im, this_ptr, SL("_image"), PH_NOISY_CC); + + PHALCON_INIT_VAR(ret); + phalcon_call_method_p4(ret, im, "cropImage", width, height, offset_x, offset_y); + + if (zend_is_true(ret)) { + PHALCON_INIT_VAR(w); + phalcon_call_method(w, im, "getImageWidth"); + + PHALCON_INIT_VAR(h); + phalcon_call_method(h, im, "getImageHeight"); + + phalcon_update_property_this(this_ptr, SL("_width"), w TSRMLS_CC); + phalcon_update_property_this(this_ptr, SL("_height"), h TSRMLS_CC); + + PHALCON_INIT_VAR(tmp); + ZVAL_LONG(tmp, 0); + + phalcon_call_method_p4_noret(im, "setImagePage", w, h, tmp, tmp); + + ZVAL_BOOL(return_value, 1); + } else { + ZVAL_BOOL(return_value, 0); + } + + PHALCON_MM_RESTORE(); +} + +/** + * Execute a rotation. + * + * @param int $degrees + */ +PHP_METHOD(Phalcon_Image_Adapter_Imagick, _rotate) { + + zval *degrees; + zval *im, *background, *color, *ret, *w, *h, *tmp; + zend_class_entry *ce0; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 1, 0, °rees); + + PHALCON_OBS_VAR(im); + phalcon_read_property_this(&im, this_ptr, SL("_image"), PH_NOISY_CC); + + ce0 = zend_fetch_class(SL("ImagickPixel"), ZEND_FETCH_CLASS_AUTO TSRMLS_CC); + + PHALCON_INIT_VAR(background); + object_init_ex(background, ce0); + if (phalcon_has_constructor(background TSRMLS_CC)) { + PHALCON_INIT_VAR(color); + ZVAL_STRING(color, "transparent", 1); + + phalcon_call_method_p1_noret(background, "__construct", color); + } + + PHALCON_INIT_VAR(ret); + phalcon_call_method_p2(ret, im, "rotateImage", background, degrees); + + if (zend_is_true(ret)) { + PHALCON_INIT_VAR(w); + phalcon_call_method(w, im, "getImageWidth"); + + PHALCON_INIT_VAR(h); + phalcon_call_method(h, im, "getImageHeight"); + + phalcon_update_property_this(this_ptr, SL("_width"), w TSRMLS_CC); + phalcon_update_property_this(this_ptr, SL("_height"), h TSRMLS_CC); + + PHALCON_INIT_VAR(tmp); + ZVAL_LONG(tmp, 0); + + phalcon_call_method_p4_noret(im, "setImagePage", w, h, tmp, tmp); + + ZVAL_BOOL(return_value, 1); + } else { + ZVAL_BOOL(return_value, 0); + } + + PHALCON_MM_RESTORE(); +} + +/** + * Execute a flip. + * + * @param int $direction + */ +PHP_METHOD(Phalcon_Image_Adapter_Imagick, _flip) { + + zval *direction; + zval *im, *ret; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 1, 0, &direction); + + PHALCON_OBS_VAR(im); + phalcon_read_property_this(&im, this_ptr, SL("_image"), PH_NOISY_CC); + + if (Z_LVAL_P(direction) == 11) { + PHALCON_INIT_VAR(ret); + phalcon_call_method(ret, im, "flopImage"); + } else { + PHALCON_INIT_VAR(ret); + phalcon_call_method(ret, im, "flipImage"); + } + + if (zend_is_true(ret)) { + ZVAL_BOOL(return_value, 1); + } else { + ZVAL_BOOL(return_value, 0); + } + + PHALCON_MM_RESTORE(); +} + +/** + * Execute a sharpen. + * + * @param int $amount + */ +PHP_METHOD(Phalcon_Image_Adapter_Imagick, _sharpen) { + + zval *amount, *a, *ret, *im, *tmp; + int int_amount; + double num; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 1, 0, &amount); + + PHALCON_OBS_VAR(im); + phalcon_read_property_this(&im, this_ptr, SL("_image"), PH_NOISY_CC); + + int_amount = Z_LVAL_P(amount); + + int_amount = (int_amount < 5) ? 5 : int_amount; + num = (int_amount * 3.0) / 100; + + PHALCON_INIT_VAR(a); + ZVAL_DOUBLE(a, num); + + PHALCON_INIT_VAR(tmp); + ZVAL_LONG(tmp, 0); + + PHALCON_INIT_VAR(ret); + phalcon_call_method_p2(ret, im, "sharpenImage", tmp, a); + + if (zend_is_true(ret)) { + ZVAL_BOOL(return_value, 1); + } else { + ZVAL_BOOL(return_value, 0); + } + + PHALCON_MM_RESTORE(); +} + +/** + * Execute a reflection. + * + * @param int $height + * @param int $opacity + * @param boolean $fade_in + */ +PHP_METHOD(Phalcon_Image_Adapter_Imagick, _reflection) { + + zval *height, *opacity, *fade_in, *o; + zval *im, *reflection, *image_width, *image_height, *reflection_width, *reflection_height, *tmp, *direction, *tmp_direction; + zval *fade, *pseudoString, *composite, *constant, *channel, *image, *background, *mode, *ret, *w, *h; + zend_class_entry *ce0, *ce1; + int int_amount, ini_h; + double num; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 3, 0, &height, &opacity, &fade_in); + + PHALCON_OBS_VAR(im); + phalcon_read_property_this(&im, this_ptr, SL("_image"), PH_NOISY_CC); + + PHALCON_OBS_VAR(image_width); + phalcon_read_property_this(&image_width, this_ptr, SL("_width"), PH_NOISY_CC); + + PHALCON_OBS_VAR(image_height); + phalcon_read_property_this(&image_height, this_ptr, SL("_height"), PH_NOISY_CC); + + PHALCON_INIT_VAR(reflection); + phalcon_call_method(reflection, im, "clone"); + + phalcon_call_method_noret(reflection, "flipImage"); + + PHALCON_INIT_VAR(tmp); + ZVAL_LONG(tmp, 0); + + phalcon_call_method_p4_noret(reflection, "cropImage", image_width, height, tmp, tmp); + phalcon_call_method_p4_noret(reflection, "setImagePage", image_width, height, tmp, tmp); + + PHALCON_INIT_VAR(direction); + array_init_size(direction, 2); + + phalcon_array_append_string(&direction, SL("transparent"), PH_SEPARATE); + phalcon_array_append_string(&direction, SL("black"), PH_SEPARATE); + + if (zend_is_true(fade_in)) { + PHALCON_INIT_NVAR(tmp_direction); + phalcon_call_func_p1(tmp_direction, "array_reverse", direction); + } else { + PHALCON_CPY_WRT(tmp_direction, direction); + } + + + ce0 = zend_fetch_class(SL("Imagick"), ZEND_FETCH_CLASS_AUTO TSRMLS_CC); + + PHALCON_INIT_VAR(fade); + object_init_ex(fade, ce0); + if (phalcon_has_constructor(fade TSRMLS_CC)) { + phalcon_call_method_noret(fade, "__construct"); + } + + PHALCON_INIT_NVAR(tmp); + ZVAL_STRING(tmp, "gradient:%s-%s", 1); + + PHALCON_INIT_VAR(pseudoString); + phalcon_call_func_p2(pseudoString, "vsprintf", tmp, tmp_direction); + + + PHALCON_INIT_VAR(reflection_width); + phalcon_call_method(reflection_width, reflection, "getImageWidth"); + + PHALCON_INIT_VAR(reflection_height); + phalcon_call_method(reflection_height, reflection, "getImageHeight"); + + phalcon_call_method_p3_noret(fade, "newPseudoImage", reflection_width, reflection_height, pseudoString); + + PHALCON_INIT_VAR(composite); + phalcon_get_class_constant(composite, ce0, SS("COMPOSITE_DSTOUT") TSRMLS_CC); + + PHALCON_INIT_NVAR(tmp); + ZVAL_LONG(tmp, 0); + + phalcon_call_method_p4_noret(reflection, "compositeImage", fade, composite, tmp, tmp); + + PHALCON_INIT_VAR(constant); + phalcon_get_class_constant(constant, ce0, SS("EVALUATE_MULTIPLY") TSRMLS_CC); + + int_amount = Z_LVAL_P(opacity); + num = int_amount / 100; + + PHALCON_INIT_VAR(o); + ZVAL_DOUBLE(o, num); + + PHALCON_INIT_VAR(channel); + phalcon_get_class_constant(channel, ce0, SS("CHANNEL_ALPHA") TSRMLS_CC); + + phalcon_call_method_p3_noret(reflection, "evaluateImage", constant, o, channel); + + PHALCON_INIT_VAR(image); + object_init_ex(image, ce0); + if (phalcon_has_constructor(image TSRMLS_CC)) { + phalcon_call_method_noret(image, "__construct"); + } + + ini_h = Z_LVAL_P(image_height) + Z_LVAL_P(height); + + PHALCON_INIT_NVAR(tmp); + ZVAL_LONG(tmp, ini_h); + + ce1 = zend_fetch_class(SL("ImagickPixel"), ZEND_FETCH_CLASS_AUTO TSRMLS_CC); + + PHALCON_INIT_VAR(background); + object_init_ex(background, ce1); + if (phalcon_has_constructor(background TSRMLS_CC)) { + phalcon_call_method_noret(background, "__construct"); + } + + phalcon_call_method_p3_noret(image, "newImage", image_width, tmp, background); + + PHALCON_INIT_VAR(mode); + phalcon_get_class_constant(mode, ce0, SS("ALPHACHANNEL_SET") TSRMLS_CC); + phalcon_call_method_p1_noret(image, "setImageAlphaChannel", mode); + + PHALCON_INIT_VAR(ret); + phalcon_call_method(ret, im, "getColorspace"); + phalcon_call_method_p1_noret(image, "setColorspace", ret); + + PHALCON_INIT_NVAR(composite); + phalcon_get_class_constant(composite, ce0, SS("COMPOSITE_SRC") TSRMLS_CC); + + PHALCON_INIT_NVAR(tmp); + ZVAL_LONG(tmp, 0); + + PHALCON_INIT_NVAR(ret); + phalcon_call_method_p4(ret, image, "compositeImage", im, composite, tmp, tmp); + + if (zend_is_true(ret)) { + PHALCON_INIT_NVAR(composite); + phalcon_get_class_constant(composite, ce0, SS("COMPOSITE_OVER") TSRMLS_CC); + + PHALCON_INIT_NVAR(tmp); + ZVAL_LONG(tmp, 0); + + PHALCON_INIT_NVAR(ret); + phalcon_call_method_p4(ret, image, "compositeImage", reflection, composite, tmp, image_height); + if (zend_is_true(ret)) { + PHALCON_INIT_VAR(w); + phalcon_call_method(w, image, "getImageWidth"); + + PHALCON_INIT_VAR(h); + phalcon_call_method(h, image, "getImageHeight"); + + phalcon_update_property_this(this_ptr, SL("_width"), w TSRMLS_CC); + phalcon_update_property_this(this_ptr, SL("_height"), h TSRMLS_CC); + phalcon_update_property_this(this_ptr, SL("_image"), image TSRMLS_CC); + + ZVAL_BOOL(return_value, 1); + } else { + ZVAL_BOOL(return_value, 0); + } + } else { + ZVAL_BOOL(return_value, 0); + } + + PHALCON_MM_RESTORE(); +} + +/** + * Execute a watermarking. + * + * @param Phalcon\Image\Adapter $watermark + * @param int $offset_x + * @param int $offset_y + * @param int $opacity + */ +PHP_METHOD(Phalcon_Image_Adapter_Imagick, _watermark) { + + zval *watermark_image, *offset_x, *offset_y, *opacity, *op =NULL; + zval *im, *tmp, *watermark, *ret, *channel, *op_constant = NULL, *composite; + zend_class_entry *ce0; + double num; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 4, 0, &watermark_image, &offset_x, &offset_y, &opacity); + + PHALCON_SEPARATE_PARAM(watermark_image); + + PHALCON_OBS_VAR(im); + phalcon_read_property_this(&im, this_ptr, SL("_image"), PH_NOISY_CC); + + PHALCON_INIT_VAR(watermark); + phalcon_call_method(watermark, watermark_image, "getImage"); + + ce0 = zend_fetch_class(SL("Imagick"), ZEND_FETCH_CLASS_AUTO TSRMLS_CC); + + PHALCON_INIT_VAR(channel); + phalcon_get_class_constant(channel, ce0, SS("ALPHACHANNEL_ACTIVATE") TSRMLS_CC); + + PHALCON_INIT_VAR(ret); + phalcon_call_method(ret, watermark, "getImageAlphaChannel"); + + if (!PHALCON_IS_EQUAL(ret, channel)) { + PHALCON_INIT_NVAR(channel); + phalcon_get_class_constant(channel, ce0, SS("ALPHACHANNEL_OPAQUE") TSRMLS_CC); + + phalcon_call_method_p1_noret(watermark, "setImageAlphaChannel", channel); + } + + if (Z_LVAL_P(opacity) < 100) { + PHALCON_INIT_NVAR(op_constant); + phalcon_get_class_constant(op_constant, ce0, SS("EVALUATE_MULTIPLY") TSRMLS_CC); + + num = Z_LVAL_P(opacity) / 100; + + PHALCON_INIT_NVAR(op); + ZVAL_DOUBLE(op, num); + + PHALCON_INIT_NVAR(channel); + phalcon_get_class_constant(channel, ce0, SS("CHANNEL_ALPHA") TSRMLS_CC); + + phalcon_call_method_p3_noret(watermark, "evaluateImage", op_constant, op, channel); + } + + PHALCON_INIT_NVAR(composite); + phalcon_get_class_constant(composite, ce0, SS("COMPOSITE_DISSOLVE") TSRMLS_CC); + + PHALCON_INIT_NVAR(ret); + phalcon_call_method_p4(ret, im, "compositeImage", watermark, composite, offset_x, offset_y); + + if (zend_is_true(ret)) { + ZVAL_BOOL(return_value, 1); + } else { + ZVAL_BOOL(return_value, 0); + } + + PHALCON_MM_RESTORE(); +} + +/** + * Execute a background. + * + * @param int $r + * @param int $g + * @param int $b + * @param int $opacity + */ +PHP_METHOD(Phalcon_Image_Adapter_Imagick, _background) { + + zval *r, *g, *b, *opacity, *op = NULL; + zval *im, *color, *format, *background, *imagickpixel, *width, *height, *ret, *mode, *op_constant, *channel, *composite, *tmp; + zend_class_entry *ce0, *ce1; + double num; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 4, 0, &r, &g, &b, &opacity); + + ce0 = zend_fetch_class(SL("Imagick"), ZEND_FETCH_CLASS_AUTO TSRMLS_CC); + ce1 = zend_fetch_class(SL("ImagickPixel"), ZEND_FETCH_CLASS_AUTO TSRMLS_CC); + + + PHALCON_OBS_VAR(im); + phalcon_read_property_this(&im, this_ptr, SL("_image"), PH_NOISY_CC); + + PHALCON_OBS_VAR(width); + phalcon_read_property_this(&width, this_ptr, SL("_width"), PH_NOISY_CC); + + PHALCON_OBS_VAR(height); + phalcon_read_property_this(&height, this_ptr, SL("_height"), PH_NOISY_CC); + + PHALCON_INIT_VAR(format); + ZVAL_STRING(format, "rgb(%d, %d, %d)", 1); + + PHALCON_INIT_VAR(color); + phalcon_call_func_p4(color, "sprintf", format, r, g, b); + + PHALCON_INIT_VAR(background); + object_init_ex(background, ce0); + if (phalcon_has_constructor(background TSRMLS_CC)) { + phalcon_call_method_noret(background, "__construct"); + } + + PHALCON_INIT_VAR(imagickpixel); + object_init_ex(imagickpixel, ce1); + if (phalcon_has_constructor(imagickpixel TSRMLS_CC)) { + phalcon_call_method_p1_noret(imagickpixel, "__construct", color); + } + + phalcon_call_method_p3_noret(background, "newImage", width, height, imagickpixel); + + PHALCON_INIT_VAR(ret); + phalcon_call_method(ret, background, "getImageAlphaChannel"); + + if (!zend_is_true(ret)) { + PHALCON_INIT_VAR(mode); + phalcon_get_class_constant(mode, ce0, SS("ALPHACHANNEL_SET") TSRMLS_CC); + + phalcon_call_method_p1_noret(background, "setImageAlphaChannel", mode); + } + + PHALCON_INIT_NVAR(imagickpixel); + object_init_ex(imagickpixel, ce1); + if (phalcon_has_constructor(imagickpixel TSRMLS_CC)) { + PHALCON_INIT_NVAR(color); + ZVAL_STRING(color, "transparent", 1); + + phalcon_call_method_p1_noret(imagickpixel, "__construct", color); + } + + phalcon_call_method_p1_noret(background, "setImageBackgroundColor", imagickpixel); + + PHALCON_INIT_VAR(op_constant); + phalcon_get_class_constant(op_constant, ce0, SS("EVALUATE_MULTIPLY") TSRMLS_CC); + + num = Z_LVAL_P(opacity) / 100; + + PHALCON_INIT_NVAR(op); + ZVAL_DOUBLE(op, num); + + PHALCON_INIT_VAR(channel); + phalcon_get_class_constant(channel, ce0, SS("CHANNEL_ALPHA") TSRMLS_CC); + + phalcon_call_method_p3_noret(background, "evaluateImage", op_constant, op, channel); + + PHALCON_INIT_NVAR(ret); + phalcon_call_method(ret, im, "getColorspace"); + + phalcon_call_method_p1_noret(background, "setColorspace", ret); + + PHALCON_INIT_VAR(composite); + phalcon_get_class_constant(composite, ce0, SS("COMPOSITE_DISSOLVE") TSRMLS_CC); + + PHALCON_INIT_VAR(tmp); + ZVAL_LONG(tmp, 0); + + PHALCON_INIT_NVAR(ret); + phalcon_call_method_p4(ret, background, "compositeImage", im, composite, tmp, tmp); + + if (zend_is_true(ret)) { + phalcon_update_property_this(this_ptr, SL("_image"), background TSRMLS_CC); + + ZVAL_BOOL(return_value, 1); + } else { + ZVAL_BOOL(return_value, 0); + } + + PHALCON_MM_RESTORE(); +} + +/** + * Execute a save. + * + * @param string $file + * @param int $quality + * @return boolean + */ +PHP_METHOD(Phalcon_Image_Adapter_Imagick, _save) { + + zval *file, *quality, *exception_message; + zval *constant, *ret, *extension, *mime, *format, *type, *im; + char *ext; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 2, 0, &file, &quality); + + PHALCON_INIT_VAR(constant); + if (zend_get_constant(SL("PATHINFO_EXTENSION"), constant TSRMLS_CC) == FAILURE) { + RETURN_MM(); + } + + PHALCON_INIT_VAR(ret); + phalcon_call_func_p2(ret, "pathinfo", file, constant); + + PHALCON_INIT_VAR(extension); + phalcon_fast_strtolower(extension, ret); + + PHALCON_INIT_VAR(format); + phalcon_fast_strtolower(format, extension); + + ext = Z_STRVAL_P(format); + + if (strncmp(ext, "gif", 3) == 0) { + PHALCON_INIT_VAR(type); + ZVAL_LONG(type, 1); + } else if (strncmp(ext, "jpg", 3) == 0 || strncmp(ext, "jpeg", 4) == 0) { + PHALCON_INIT_VAR(type); + ZVAL_LONG(type, 2); + } else if (strncmp(ext, "png", 3) == 0) { + PHALCON_INIT_VAR(type); + ZVAL_LONG(type, 3); + } else { + PHALCON_INIT_VAR(exception_message); + PHALCON_CONCAT_SVS(exception_message, "Installed ImageMagick does not support '", extension, "' images"); + PHALCON_THROW_EXCEPTION_ZVAL(phalcon_image_exception_ce, exception_message); + return; + } + + PHALCON_OBS_VAR(im); + phalcon_read_property_this(&im, this_ptr, SL("_image"), PH_NOISY_CC); + + phalcon_call_method_p1_noret(im, "setFormat", format); + phalcon_call_method_p1_noret(im, "setImageCompressionQuality", quality); + + PHALCON_INIT_NVAR(ret); + phalcon_call_method_p1(ret, im, "writeImage", file); + + if (zend_is_true(ret)) { + phalcon_update_property_this(this_ptr, SL("_type"), type TSRMLS_CC); + + PHALCON_INIT_VAR(mime); + phalcon_call_func_p1(mime, "image_type_to_mime_type", type); + + phalcon_update_property_this(this_ptr, SL("_mime"), mime TSRMLS_CC); + + ZVAL_BOOL(return_value, 1); + } else { + ZVAL_BOOL(return_value, 0); + } + + PHALCON_MM_RESTORE(); +} + +/** + * Execute a render. + * + * @param string $type + * @param int $quality + * @return string + */ +PHP_METHOD(Phalcon_Image_Adapter_Imagick, _render) { + + zval *extension, *quality, *exception_message; + zval *mime, *format, *type, *im, *image_string; + char *ext; + + PHALCON_MM_GROW(); + + phalcon_fetch_params(1, 2, 0, &extension, &quality); + + PHALCON_INIT_VAR(format); + phalcon_fast_strtolower(format, extension); + + ext = Z_STRVAL_P(format); + + if (strncmp(ext, "gif", 3) == 0) { + PHALCON_INIT_VAR(type); + ZVAL_LONG(type, 1); + } else if (strncmp(ext, "jpg", 3) == 0 || strncmp(ext, "jpeg", 4) == 0) { + PHALCON_INIT_VAR(type); + ZVAL_LONG(type, 2); + } else if (strncmp(ext, "png", 3) == 0) { + PHALCON_INIT_VAR(type); + ZVAL_LONG(type, 3); + } else { + PHALCON_INIT_VAR(exception_message); + PHALCON_CONCAT_SVS(exception_message, "Installed ImageMagick does not support '", extension, "' images"); + PHALCON_THROW_EXCEPTION_ZVAL(phalcon_image_exception_ce, exception_message); + return; + } + + PHALCON_OBS_VAR(im); + phalcon_read_property_this(&im, this_ptr, SL("_image"), PH_NOISY_CC); + + phalcon_call_method_p1_noret(im, "setFormat", format); + phalcon_call_method_p1_noret(im, "setImageCompressionQuality", quality); + + phalcon_update_property_this(this_ptr, SL("_type"), type TSRMLS_CC); + + PHALCON_INIT_VAR(mime); + phalcon_call_func_p1(mime, "image_type_to_mime_type", type); + + phalcon_update_property_this(this_ptr, SL("_mime"), mime TSRMLS_CC); + + PHALCON_INIT_VAR(image_string); + phalcon_call_method(image_string, im, "getImagesBlob"); + + RETURN_CCTOR(image_string); +} diff --git a/ext/image/adapter/imagick.h b/ext/image/adapter/imagick.h new file mode 100644 index 00000000000..2ed60bbb48a --- /dev/null +++ b/ext/image/adapter/imagick.h @@ -0,0 +1,110 @@ + +/* + +------------------------------------------------------------------------+ + | Phalcon Framework | + +------------------------------------------------------------------------+ + | Copyright (c) 2011-2013 Phalcon Team (http://www.phalconphp.com) | + +------------------------------------------------------------------------+ + | This source file is subject to the New BSD License that is bundled | + | with this package in the file docs/LICENSE.txt. | + | | + | If you did not receive a copy of the license and are unable to | + | obtain it through the world-wide-web, please send an email | + | to license@phalconphp.com so we can send you a copy immediately. | + +------------------------------------------------------------------------+ + | Authors: Andres Gutierrez | + | Eduar Carvajal | + +------------------------------------------------------------------------+ +*/ + +extern zend_class_entry *phalcon_image_adapter_imagick_ce; + +PHALCON_INIT_CLASS(Phalcon_Image_Adapter_Imagick); + +PHP_METHOD(Phalcon_Image_Adapter_Imagick, check); +PHP_METHOD(Phalcon_Image_Adapter_Imagick, __construct); +PHP_METHOD(Phalcon_Image_Adapter_Imagick, _resize); +PHP_METHOD(Phalcon_Image_Adapter_Imagick, _crop); +PHP_METHOD(Phalcon_Image_Adapter_Imagick, _rotate); +PHP_METHOD(Phalcon_Image_Adapter_Imagick, _flip); +PHP_METHOD(Phalcon_Image_Adapter_Imagick, _sharpen); +PHP_METHOD(Phalcon_Image_Adapter_Imagick, _reflection); +PHP_METHOD(Phalcon_Image_Adapter_Imagick, _watermark); +PHP_METHOD(Phalcon_Image_Adapter_Imagick, _background); +PHP_METHOD(Phalcon_Image_Adapter_Imagick, _save); +PHP_METHOD(Phalcon_Image_Adapter_Imagick, _render); + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_imagick___construct, 0, 0, 1) + ZEND_ARG_INFO(0, file) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_imagick__resize, 0, 0, 2) + ZEND_ARG_INFO(0, width) + ZEND_ARG_INFO(0, height) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_imagick__crop, 0, 0, 4) + ZEND_ARG_INFO(0, width) + ZEND_ARG_INFO(0, height) + ZEND_ARG_INFO(0, offset_x) + ZEND_ARG_INFO(0, offset_y) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_imagick__rotate, 0, 0, 1) + ZEND_ARG_INFO(0, degrees) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_imagick__flip, 0, 0, 1) + ZEND_ARG_INFO(0, direction) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_imagick__sharpen, 0, 0, 1) + ZEND_ARG_INFO(0, amount) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_imagick__reflection, 0, 0, 3) + ZEND_ARG_INFO(0, height) + ZEND_ARG_INFO(0, opacity) + ZEND_ARG_INFO(0, fade_in) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_imagick__watermark, 0, 0, 4) + ZEND_ARG_INFO(0, watermark) + ZEND_ARG_INFO(0, offset_x) + ZEND_ARG_INFO(0, offset_y) + ZEND_ARG_INFO(0, opacity) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_imagick__background, 0, 0, 4) + ZEND_ARG_INFO(0, r) + ZEND_ARG_INFO(0, g) + ZEND_ARG_INFO(0, b) + ZEND_ARG_INFO(0, quality) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_imagick__save, 0, 0, 2) + ZEND_ARG_INFO(0, file) + ZEND_ARG_INFO(0, quality) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapter_imagick__render, 0, 0, 2) + ZEND_ARG_INFO(0, type) + ZEND_ARG_INFO(0, quality) +ZEND_END_ARG_INFO() + +PHALCON_INIT_FUNCS(phalcon_image_adapter_imagick_method_entry) { + PHP_ME(Phalcon_Image_Adapter_Imagick, check, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Phalcon_Image_Adapter_Imagick, __construct, arginfo_phalcon_image_adapter_imagick___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) + PHP_ME(Phalcon_Image_Adapter_Imagick, _resize, arginfo_phalcon_image_adapter_imagick__resize, ZEND_ACC_PROTECTED) + PHP_ME(Phalcon_Image_Adapter_Imagick, _crop, arginfo_phalcon_image_adapter_imagick__crop, ZEND_ACC_PROTECTED) + PHP_ME(Phalcon_Image_Adapter_Imagick, _rotate, arginfo_phalcon_image_adapter_imagick__rotate, ZEND_ACC_PROTECTED) + PHP_ME(Phalcon_Image_Adapter_Imagick, _flip, arginfo_phalcon_image_adapter_imagick__flip, ZEND_ACC_PROTECTED) + PHP_ME(Phalcon_Image_Adapter_Imagick, _sharpen, arginfo_phalcon_image_adapter_imagick__sharpen, ZEND_ACC_PROTECTED) + PHP_ME(Phalcon_Image_Adapter_Imagick, _reflection, arginfo_phalcon_image_adapter_imagick__reflection, ZEND_ACC_PROTECTED) + PHP_ME(Phalcon_Image_Adapter_Imagick, _watermark, arginfo_phalcon_image_adapter_imagick__watermark, ZEND_ACC_PROTECTED) + PHP_ME(Phalcon_Image_Adapter_Imagick, _background, arginfo_phalcon_image_adapter_imagick__background, ZEND_ACC_PROTECTED) + PHP_ME(Phalcon_Image_Adapter_Imagick, _save, arginfo_phalcon_image_adapter_imagick__save, ZEND_ACC_PROTECTED) + PHP_ME(Phalcon_Image_Adapter_Imagick, _render, arginfo_phalcon_image_adapter_imagick__render, ZEND_ACC_PROTECTED) + PHP_FE_END +}; + diff --git a/ext/image/adapterinterface.c b/ext/image/adapterinterface.c new file mode 100644 index 00000000000..d09ec76d981 --- /dev/null +++ b/ext/image/adapterinterface.c @@ -0,0 +1,139 @@ + +/* + +------------------------------------------------------------------------+ + | Phalcon Framework | + +------------------------------------------------------------------------+ + | Copyright (c) 2011-2013 Phalcon Team (http://www.phalconphp.com) | + +------------------------------------------------------------------------+ + | This source file is subject to the New BSD License that is bundled | + | with this package in the file docs/LICENSE.txt. | + | | + | If you did not receive a copy of the license and are unable to | + | obtain it through the world-wide-web, please send an email | + | to license@phalconphp.com so we can send you a copy immediately. | + +------------------------------------------------------------------------+ + | Authors: Andres Gutierrez | + | Eduar Carvajal | + +------------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_phalcon.h" +#include "phalcon.h" + +#include "kernel/main.h" + +/** + * Phalcon\Image\AdapterInterface initializer + */ +PHALCON_INIT_CLASS(Phalcon_Image_AdapterInterface){ + + PHALCON_REGISTER_INTERFACE(Phalcon\\Image, AdapterInterface, image_adapterinterface, phalcon_image_adapterinterface_method_entry); + + return SUCCESS; +} + +/** + * Resize the image to the given size. Either the width or the height can + * be omitted and the image will be resized proportionally. + * + * @param int $width new width + * @param int $height new height + * @param int $master master dimension + * @return Phalcon\Image\Adapter + */ +PHALCON_DOC_METHOD(Phalcon_Image_AdapterInterface, resize); + +/** + * Crop an image to the given size. Either the width or the height can be + * omitted and the current width or height will be used. + * + * @param int $width new width + * @param int $height new height + * @param int $offset_x offset from the left + * @param int $offset_y offset from the top + * @return Phalcon\Image\Adapter + */ +PHALCON_DOC_METHOD(Phalcon_Image_AdapterInterface, crop); + +/** + * Rotate the image by a given amount. + * + * @param int $degrees degrees to rotate: -360-360 + * @return Phalcon\Image\Adapter + */ +PHALCON_DOC_METHOD(Phalcon_Image_AdapterInterface, rotate); + +/** + * Flip the image along the horizontal or vertical axis. + * + * @param $int $direction direction: Image::HORIZONTAL, Image::VERTICAL + * @return Phalcon\Image\Adapter + */ +PHALCON_DOC_METHOD(Phalcon_Image_AdapterInterface, flip); + +/** + * Sharpen the image by a given amount. + * + * @param int $amount amount to sharpen: 1-100 + * @return Phalcon\Image\Adapter + */ +PHALCON_DOC_METHOD(Phalcon_Image_AdapterInterface, sharpen); + +/** + * Add a reflection to an image. The most opaque part of the reflection + * will be equal to the opacity setting and fade out to full transparent. + * Alpha transparency is preserved. + * + * @param int $height reflection height + * @param int $opacity reflection opacity: 0-100 + * @param boolean $fade_in TRUE to fade in, FALSE to fade out + * @return Phalcon\Image\Adapter + */ +PHALCON_DOC_METHOD(Phalcon_Image_AdapterInterface, reflection); + +/** + * Add a watermark to an image with a specified opacity. Alpha transparency + * will be preserved. + * + * @param Phalcon\Image\Adapter $watermark watermark Image instance + * @param int $offset_x offset from the left + * @param int $offset_y offset from the top + * @param int $opacity opacity of watermark: 1-100 + * @return Phalcon\Image\Adapter + */ +PHALCON_DOC_METHOD(Phalcon_Image_AdapterInterface, watermark); + +/** + * Set the background color of an image. This is only useful for images + * with alpha transparency. + * + * @param string $color hexadecimal color value + * @param int $opacity background opacity: 0-100 + * @return Phalcon\Image\Adapter + */ +PHALCON_DOC_METHOD(Phalcon_Image_AdapterInterface, background); + +/** + * Save the image. If the filename is omitted, the original image will + * be overwritten. + * + * @param string $file new image path + * @param int $quality quality of image: 1-100 + * @return Phalcon\Image\Adapter + */ +PHALCON_DOC_METHOD(Phalcon_Image_AdapterInterface, save); + +/** + * Render the image and return the binary string. + * + * @param string $type image type to return: png, jpg, gif, etc + * @param int $quality quality of image: 1-100 + * @return Phalcon\Image\Adapter + */ +PHALCON_DOC_METHOD(Phalcon_Image_AdapterInterface, render); + diff --git a/ext/image/adapterinterface.h b/ext/image/adapterinterface.h new file mode 100644 index 00000000000..fa5aefb2e49 --- /dev/null +++ b/ext/image/adapterinterface.h @@ -0,0 +1,89 @@ + +/* + +------------------------------------------------------------------------+ + | Phalcon Framework | + +------------------------------------------------------------------------+ + | Copyright (c) 2011-2013 Phalcon Team (http://www.phalconphp.com) | + +------------------------------------------------------------------------+ + | This source file is subject to the New BSD License that is bundled | + | with this package in the file docs/LICENSE.txt. | + | | + | If you did not receive a copy of the license and are unable to | + | obtain it through the world-wide-web, please send an email | + | to license@phalconphp.com so we can send you a copy immediately. | + +------------------------------------------------------------------------+ + | Authors: Andres Gutierrez | + | Eduar Carvajal | + +------------------------------------------------------------------------+ +*/ + +extern zend_class_entry *phalcon_image_adapterinterface_ce; + +PHALCON_INIT_CLASS(Phalcon_Image_AdapterInterface); + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapterinterface_resize, 0, 0, 0) + ZEND_ARG_INFO(0, width) + ZEND_ARG_INFO(0, height) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapterinterface_crop, 0, 0, 2) + ZEND_ARG_INFO(0, width) + ZEND_ARG_INFO(0, height) + ZEND_ARG_INFO(0, offset_x) + ZEND_ARG_INFO(0, offset_y) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapterinterface_rotate, 0, 0, 1) + ZEND_ARG_INFO(0, degrees) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapterinterface_flip, 0, 0, 1) + ZEND_ARG_INFO(0, direction) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapterinterface_sharpen, 0, 0, 1) + ZEND_ARG_INFO(0, amount) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapterinterface_reflection, 0, 0, 0) + ZEND_ARG_INFO(0, height) + ZEND_ARG_INFO(0, opacity) + ZEND_ARG_INFO(0, fade_in) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapterinterface_watermark, 0, 0, 1) + ZEND_ARG_INFO(0, watermark) + ZEND_ARG_INFO(0, offset_x) + ZEND_ARG_INFO(0, offset_y) + ZEND_ARG_INFO(0, opacity) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapterinterface_background, 0, 0, 1) + ZEND_ARG_INFO(0, color) + ZEND_ARG_INFO(0, quality) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapterinterface_save, 0, 0, 0) + ZEND_ARG_INFO(0, file) + ZEND_ARG_INFO(0, quality) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_image_adapterinterface_render, 0, 0, 0) + ZEND_ARG_INFO(0, type) + ZEND_ARG_INFO(0, quality) +ZEND_END_ARG_INFO() + +PHALCON_INIT_FUNCS(phalcon_image_adapterinterface_method_entry){ + PHP_ABSTRACT_ME(Phalcon_Image_AdapterInterface, resize, arginfo_phalcon_image_adapterinterface_resize) + PHP_ABSTRACT_ME(Phalcon_Image_AdapterInterface, crop, arginfo_phalcon_image_adapterinterface_crop) + PHP_ABSTRACT_ME(Phalcon_Image_AdapterInterface, rotate, arginfo_phalcon_image_adapterinterface_rotate) + PHP_ABSTRACT_ME(Phalcon_Image_AdapterInterface, flip, arginfo_phalcon_image_adapterinterface_flip) + PHP_ABSTRACT_ME(Phalcon_Image_AdapterInterface, sharpen, arginfo_phalcon_image_adapterinterface_sharpen) + PHP_ABSTRACT_ME(Phalcon_Image_AdapterInterface, reflection, arginfo_phalcon_image_adapterinterface_reflection) + PHP_ABSTRACT_ME(Phalcon_Image_AdapterInterface, watermark, arginfo_phalcon_image_adapterinterface_watermark) + PHP_ABSTRACT_ME(Phalcon_Image_AdapterInterface, background, arginfo_phalcon_image_adapterinterface_background) + PHP_ABSTRACT_ME(Phalcon_Image_AdapterInterface, save, arginfo_phalcon_image_adapterinterface_save) + PHP_ABSTRACT_ME(Phalcon_Image_AdapterInterface, render, arginfo_phalcon_image_adapterinterface_render) + PHP_FE_END +}; + diff --git a/ext/image/exception.c b/ext/image/exception.c new file mode 100644 index 00000000000..faa93ad4794 --- /dev/null +++ b/ext/image/exception.c @@ -0,0 +1,52 @@ + +/* + +------------------------------------------------------------------------+ + | Phalcon Framework | + +------------------------------------------------------------------------+ + | Copyright (c) 2011-2013 Phalcon Team (http://www.phalconphp.com) | + +------------------------------------------------------------------------+ + | This source file is subject to the New BSD License that is bundled | + | with this package in the file docs/LICENSE.txt. | + | | + | If you did not receive a copy of the license and are unable to | + | obtain it through the world-wide-web, please send an email | + | to license@phalconphp.com so we can send you a copy immediately. | + +------------------------------------------------------------------------+ + | Authors: Andres Gutierrez | + | Eduar Carvajal | + +------------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_phalcon.h" +#include "phalcon.h" + +#include "Zend/zend_operators.h" +#include "Zend/zend_exceptions.h" +#include "Zend/zend_interfaces.h" + +#include "kernel/main.h" +#include "kernel/memory.h" + +/** + * Phalcon\Image\Exception + * + * Exceptions thrown in Phalcon\Image will use this class + * + */ + + +/** + * Phalcon\Image\Exception initializer + */ +PHALCON_INIT_CLASS(Phalcon_Image_Exception){ + + PHALCON_REGISTER_CLASS_EX(Phalcon\\Image, Exception, image_exception, "phalcon\\exception", NULL, 0); + + return SUCCESS; +} + diff --git a/ext/image/exception.h b/ext/image/exception.h new file mode 100644 index 00000000000..1bdb8aef996 --- /dev/null +++ b/ext/image/exception.h @@ -0,0 +1,22 @@ + +/* + +------------------------------------------------------------------------+ + | Phalcon Framework | + +------------------------------------------------------------------------+ + | Copyright (c) 2011-2013 Phalcon Team (http://www.phalconphp.com) | + +------------------------------------------------------------------------+ + | This source file is subject to the New BSD License that is bundled | + | with this package in the file docs/LICENSE.txt. | + | | + | If you did not receive a copy of the license and are unable to | + | obtain it through the world-wide-web, please send an email | + | to license@phalconphp.com so we can send you a copy immediately. | + +------------------------------------------------------------------------+ + | Authors: Andres Gutierrez | + | Eduar Carvajal | + +------------------------------------------------------------------------+ +*/ + +extern zend_class_entry *phalcon_image_exception_ce; + +PHALCON_INIT_CLASS(Phalcon_Image_Exception); diff --git a/ext/phalcon.c b/ext/phalcon.c index 389af163dd4..d5cfac3979a 100644 --- a/ext/phalcon.c +++ b/ext/phalcon.c @@ -344,6 +344,12 @@ zend_class_entry *phalcon_events_manager_ce; zend_class_entry *phalcon_events_managerinterface_ce; zend_class_entry *phalcon_events_eventsawareinterface_ce; zend_class_entry *phalcon_exception_ce; +zend_class_entry *phalcon_image_ce; +zend_class_entry *phalcon_image_adapter_ce; +zend_class_entry *phalcon_image_adapterinterface_ce; +zend_class_entry *phalcon_image_exception_ce; +zend_class_entry *phalcon_image_adapter_gd_ce; +zend_class_entry *phalcon_image_adapter_imagick_ce; ZEND_DECLARE_MODULE_GLOBALS(phalcon) @@ -709,6 +715,12 @@ static PHP_MINIT_FUNCTION(phalcon){ PHALCON_INIT(Phalcon_Events_Event); PHALCON_INIT(Phalcon_Events_Manager); PHALCON_INIT(Phalcon_Events_Exception); + PHALCON_INIT(Phalcon_Image); + PHALCON_INIT(Phalcon_Image_Adapter); + PHALCON_INIT(Phalcon_Image_AdapterInterface); + PHALCON_INIT(Phalcon_Image_Exception); + PHALCON_INIT(Phalcon_Image_Adapter_GD); + PHALCON_INIT(Phalcon_Image_Adapter_Imagick); old_error_cb = zend_error_cb; zend_error_cb = phalcon_error_cb; diff --git a/ext/phalcon.h b/ext/phalcon.h index 5f5add1c846..17daa23aad5 100644 --- a/ext/phalcon.h +++ b/ext/phalcon.h @@ -324,3 +324,9 @@ #include "events/event.h" #include "events/manager.h" #include "events/exception.h" +#include "image.h" +#include "image/adapter.h" +#include "image/adapterinterface.h" +#include "image/exception.h" +#include "image/adapter/gd.h" +#include "image/adapter/imagick.h"