当前位置: 首页 > 工具软件 > Imagetool > 使用案例 >

C实现PHP扩展《Image_Tool》图片常用处理工具类

宋明亮
2023-12-01

该扩展是基于ImageMagick基础实现的,图片操作调用的是ImageMagick API。

一、类文档说明

class Image_Tool{
    /**
     * 构造Image_Tool对象
     * @param string|array $img_data
     * $img_data可以为图片的路径
     */
	function __construct($img_data="");
    
	/**
	 * 添加文字注解,或用于文字水印
	 * @access public
	 * @param string $txt UTF8编码的文本
	 * @param float $opacity 设置透明度
	 * @param constant $gravity 
	 * 设置文字摆放位置:
	 * NorthWest,North,NorthEast,West, Center,East,SouthWest,South,SouthEast,Static
	 * @param array $font 字体数组可以设置如下属性:
	 * name,常量,字体名称,如果需要添加中文注解,请使用中文字体,否则中文会显示乱码。
     *        支持的字体:SimSun(宋体,默认)、SimKai(楷体)、SimHei(正黑)、MicroHei(微米黑)、Arial
     * weight,字体宽度,int
     * size,字体大小,int
     * color,字体颜色,例如:"blue", "#0000ff", "rgb(0,0,255)"等,默认为"black";
     * @return boolean
	 */
	function annotate($txt, $opacity, $gravity, array $font);
    
	/**
	 * 将对象的数据重新初始化,用于多次重用一个Image_Tool对象
	 * @access public
	 * @return void
	 */
	function clean();
    
	*
	 * 图片合成,可以进行多张图片的合成,也可以做图片水印用
	 * @access public
	 * @param int $src_img 合成的目标图片,可以为ImageTool对象或图片二进制数据
	 * @param int $x 合成在画布的X坐标
	 * @param string $y 合成在画布的Y坐标
	 * @return boolean
	 * 
	function composite($src_img, $x, $y);
    
	/**
	 * 返回错误信息
	 * @access public
	 * @return string
	 */
	function errmsg();
    
	/**
	 * 返回错误编号
	 * @access public
	 * @return int
	 */
	function errcode();
    
	/**
	 * 进行图片处理操作
	 * @access public
	 * @param string $format
	 * @param boolean $display
	 * @return boolean|string 若设置$display为true,返回void,否则返回图片二进制数据。失败时返回false
	 */
	function exec($format, $display=false);
    
	/**
	 * 水平翻转
	 * @access public
	 * @return boolean
	 */
	function flipH();
    
	/**
	 * 垂直翻转
	 * @access public
	 * @return boolean
	 */
	function flipV();
    
	/**
	 * 取得图片属性
	 * @access public
	 * @return array|boolean 错误返回false
	 */
	function getImageAttr();
    
	/**
	 * 去噪点,改善图片质量,通常用于exec之前
	 * @access public
	 * @return boolean
	 */
	function improve();
    
	/**
	 * 缩放图片,只指定width或者height时,将进行等比缩放
	 * @access public
	 * @param int $width
	 * @param int $height
	 * @param boolean $thumbnail 是否清除图片附加信息
	 * @return boolean
	 */
	function resize($width, $height, $thumbnail=true);
    
	/**
	 * 按比例缩放.1为原大小
	 * @access public
	 * @param float $ratio
	 * @param boolean $thumbnail 是否清除图片附加信息
	 * @return boolean
	 */
	function resizeRatio($ratio, $thumbnail=true);
    
	/**
	 * 顺时针旋转图片
	 * @access public
	 * @param int $degree 旋转度数(0 - 360)
	 * @return boolean
	 */
	function rotate($degree=90);
    
	/**
	 * 设置要处理的图片二进制数据
	 * @access public
	 * @param string $img_blob
	 * @return boolean
	 */
	function setData($img_blob);
}

二、使用案例

$img1 = new Image_Tool("C:/Users/Administrator/Desktop/1.jpg");
$font = array('name'=>'Simsun', 'color'=>'red', 'size'=>20, 'weight'=>900);
$img1->annotate('Good Bye!', 0.1, IMAGETOOL_NORTHWEST, $font); //打上文字水印
// $img1->rotate(90);
$img1->flipV();//垂直翻转
// $img1->resize(250, 250, 0);
$img1->resizeRatio(0.5, 1);
$img_arr = $img1->getImageAttr();//图片属性 宽、高、类型
$img1->improve();//除噪点


$img2 = new Image_Tool();
$img2->setData(file_get_contents("C:/Users/Administrator/Desktop/3.png"));

$background_img = new Image_Tool("C:/Users/Administrator/Desktop/2.png");
$background_img->composite($img1, 200, 100); //以background_img为画布,基于左上角0,0坐标开始向右200、向下100像素将图片img1合成
$background_img->composite($img2, 0, 0); //将background_img与img1合成后的图片,基于左上角0,0点合成img2
$background_img->exec("C:/Users/Administrator/Desktop/composite.jpg");//生成三张图片合并后的新图片

三、扩展实现

1.php_fetch_url.h

/*
  +----------------------------------------------------------------------+
  | PHP Version 5                                                        |
  +----------------------------------------------------------------------+
  | Copyright (c) 1997-2012 The PHP Group                                |
  +----------------------------------------------------------------------+
  | This source file is subject to version 3.01 of the PHP license,      |
  | that is bundled with this package in the file LICENSE, and is        |
  | available through the world-wide-web at the following url:           |
  | http://www.php.net/license/3_01.txt                                  |
  | If you did not receive a copy of the PHP license and are unable to   |
  | obtain it through the world-wide-web, please send a note to          |
  | license@php.net so we can mail you a copy immediately.               |
  +----------------------------------------------------------------------+
  | Author:                                                              |
  +----------------------------------------------------------------------+
*/

/* $Id$ */

#ifndef PHP_IMAGE_TOOL_H
#define PHP_IMAGE_TOOL_H

extern zend_module_entry image_tool_module_entry;
#define phpext_image_tool_ptr &image_tool_module_entry

#ifdef PHP_WIN32
#	define PHP_IMAGE_TOOL_API __declspec(dllexport)
#elif defined(__GNUC__) && __GNUC__ >= 4
#	define PHP_IMAGE_TOOL_API __attribute__ ((visibility("default")))
#else
#	define PHP_IMAGE_TOOL_API
#endif

#ifdef ZTS
#include "TSRM.h"
#endif

#define FETCH_THIS Z_OBJCE_P(getThis()), getThis()
#define IMAGETOOL_MAGICKWAND_RSRC_NAME "MagickWand"
#define IMAGETOOL_PIXELWAND_RSRC_NAME "PixelWand"

#define IMAGETOOL_NORTHWEST 1
#define IMAGETOOL_NORTH     2
#define IMAGETOOL_NORTHEAST 3
#define IMAGETOOL_WEST      4
#define IMAGETOOL_CENTER    5
#define IMAGETOOL_EAST      6
#define IMAGETOOL_SOUTHWEST 7
#define IMAGETOOL_SOUTH     8
#define IMAGETOOL_SOUTHEAST 9
#define IMAGETOOL_STATIC    10

#define IMAGETOOL_TOP_LEFT      1
#define IMAGETOOL_TOP_CENTER    2
#define IMAGETOOL_TOP_RIGHT     3
#define IMAGETOOL_CENTER_LEFT   4
#define IMAGETOOL_CENTER_CENTER 5
#define IMAGETOOL_CENTER_RIGHT  6
#define IMAGETOOL_BOTTOM_LEFT   7
#define IMAGETOOL_BOTTOM_CENTER 8
#define IMAGETOOL_BOTTOM_RIGHT  9

#define GET_MAGICK_WAND(zval, magick_wand) zval = zend_read_property(FETCH_THIS, ZEND_STRL("magick_wand"), 0 TSRMLS_CC);\
        ZEND_FETCH_RESOURCE_NO_RETURN(magick_wand, MagickWand*, &zval, -1, IMAGETOOL_MAGICKWAND_RSRC_NAME, le_image_wand);

PHP_MINIT_FUNCTION(image_tool);
PHP_MSHUTDOWN_FUNCTION(image_tool);
PHP_RINIT_FUNCTION(image_tool);
PHP_RSHUTDOWN_FUNCTION(image_tool);
PHP_MINFO_FUNCTION(image_tool);


#ifdef ZTS
#define IMAGE_TOOL_G(v) TSRMG(image_tool_globals_id, zend_image_tool_globals *, v)
#else
#define IMAGE_TOOL_G(v) (image_tool_globals.v)
#endif

#endif	/* PHP_IMAGE_TOOL_H */


2.fetch_url.c

/*
  +----------------------------------------------------------------------+
  | PHP Version 5                                                        |
  +----------------------------------------------------------------------+
  | Copyright (c) 1997-2012 The PHP Group                                |
  +----------------------------------------------------------------------+
  | This source file is subject to version 3.01 of the PHP license,      |
  | that is bundled with this package in the file LICENSE, and is        |
  | available through the world-wide-web at the following url:           |
  | http://www.php.net/license/3_01.txt                                  |
  | If you did not receive a copy of the PHP license and are unable to   |
  | obtain it through the world-wide-web, please send a note to          |
  | license@php.net so we can mail you a copy immediately.               |
  +----------------------------------------------------------------------+
  | Author:                                                              |
  +----------------------------------------------------------------------+
*/

/* $Id$ */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "main/SAPI.h"  
#include "Zend/zend_interfaces.h"  
#include "ext/standard/php_var.h"  
#include "ext/standard/php_string.h"  
#include "ext/standard/php_smart_str.h"  
#include "ext/standard/url.h"
#include <wand/MagickWand.h>
#include <string.h>
#include "php_image_tool.h"

/* If you declare any globals in php_image_tool.h uncomment this:
ZEND_DECLARE_MODULE_GLOBALS(image_tool)
*/ 
zend_class_entry *g_imagetool_ce;

/* True global resources - no need for thread safety here */
static int le_image_tool, le_image_wand/*ImageMagick::MagickWand句柄*/, le_image_pixel/*ImageMagick::PixelWand句柄*/;

static destroy_magick_wand(zend_rsrc_list_entry *rsrc TSRMLS_DC){
	MagickWand *magick_wand = (MagickWand*)rsrc->ptr;

	DestroyMagickWand(magick_wand);
}

static destroy_pixel_wand(zend_rsrc_list_entry *rsrc TSRMLS_DC){
	PixelWand *pixel_wand = (PixelWand*)rsrc->ptr;

	DestroyPixelWand(pixel_wand);
}

ZEND_BEGIN_ARG_INFO_EX(void_arginfo, 0, 0, 0)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(setData_arginfo, 0, 0, 0)
	ZEND_ARG_INFO(0, img_data)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(annotate_arginfo, 0, 0, 3)
	ZEND_ARG_INFO(0, txt)
	ZEND_ARG_INFO(0, opacity)
	ZEND_ARG_INFO(0, gravity)
	ZEND_ARG_INFO(0, font)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(composite_arginfo, 0, 0, 3)
	ZEND_ARG_INFO(0, width)
	ZEND_ARG_INFO(0, height)
	ZEND_ARG_INFO(0, color)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(exec_arginfo, 0, 0, 1)
	ZEND_ARG_INFO(0, format)
	ZEND_ARG_INFO(0, display)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(resize_arginfo, 0, 0, 2)
	ZEND_ARG_INFO(0, width)
	ZEND_ARG_INFO(0, height)
	ZEND_ARG_INFO(0, thumbnail)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(resizeRatio_arginfo, 0, 0, 1)
	ZEND_ARG_INFO(0, ratio)
	ZEND_ARG_INFO(0, thumbnail)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(rotate_arginfo, 0, 0, 1)
	ZEND_ARG_INFO(0, degree)
ZEND_END_ARG_INFO()

//Image_Tool::__construct($img_data="");
ZEND_METHOD(Image_Tool, __construct){
	zval *img_data=NULL, *z_magick_wand;
	MagickWand *magick_wand;

	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z", &img_data) == FAILURE){
		RETURN_FALSE;
	}
	
	MagickWandGenesis();
	magick_wand = NewMagickWand();
	z_magick_wand = zend_read_property(FETCH_THIS, ZEND_STRL("magick_wand"), 0 TSRMLS_CC);
	MAKE_STD_ZVAL(z_magick_wand);
	ZEND_REGISTER_RESOURCE(z_magick_wand, magick_wand, le_image_wand);
	zend_update_property(FETCH_THIS, ZEND_STRL("magick_wand"), z_magick_wand TSRMLS_CC);

	if(img_data != NULL && Z_TYPE_P(img_data) == IS_STRING){
		if( MagickReadImage(magick_wand, Z_STRVAL_P(img_data)) == MagickFalse){
			zend_error(E_WARNING, "img filepath not exists!");
			RETURN_FALSE;
		}
	}

	RETURN_TRUE;
}

ZEND_METHOD(Image_Tool, __tostring){
	zval *z_magick_wand;
	MagickWand *magick_wand;
	size_t img_size;
	unsigned char *img_data;

	z_magick_wand = zend_read_property(FETCH_THIS, ZEND_STRL("magick_wand"), 0 TSRMLS_CC);
	ZEND_FETCH_RESOURCE_NO_RETURN(magick_wand, MagickWand*, &z_magick_wand, -1, IMAGETOOL_MAGICKWAND_RSRC_NAME, le_image_wand);

	img_data = MagickGetImageBlob(magick_wand, &img_size);
	ZVAL_STRINGL(return_value, img_data, img_size, 1);
	MagickRelinquishMemory(img_data);
}

//Image_Tool::annotate($txt, $opacity, $gravity, array $font);
ZEND_METHOD(Image_Tool, annotate){
	zval *txt, *opacity, *gravity, *font;
	zval *z_magick_wand;
	MagickWand *magick_wand;
	DrawingWand *drawing_wand;
	int img_width, img_height;
	float x, y;

	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zzzz!", &txt, &opacity, &gravity, &font) == FAILURE){
		RETURN_FALSE;
	}

	if(Z_TYPE_P(txt) != IS_STRING){
		zend_error(E_WARNING, "txt must be string.");
		RETURN_FALSE;
	}

	if(Z_TYPE_P(opacity) != IS_DOUBLE){
		zend_error(E_WARNING, "opacity must be float.");
		RETURN_FALSE;
	}

	if(Z_TYPE_P(gravity) != IS_LONG){
		zend_error(E_WARNING, "gravity must be int.");
		RETURN_FALSE;
	}

	if(Z_TYPE_P(font) != IS_ARRAY){
		zend_error(E_WARNING, "font must be array.");
		RETURN_FALSE;
	}

	z_magick_wand = zend_read_property(FETCH_THIS, ZEND_STRL("magick_wand"), 0 TSRMLS_CC);
	drawing_wand = NewDrawingWand();
	DrawSetTextEncoding(drawing_wand, "UTF-8");
	DrawSetFillOpacity(drawing_wand, Z_DVAL_P(opacity));
	DrawSetTextAlignment(drawing_wand, CenterAlign);
	ZEND_FETCH_RESOURCE_NO_RETURN(magick_wand, MagickWand*, &z_magick_wand, -1, IMAGETOOL_MAGICKWAND_RSRC_NAME, le_image_wand);
	img_height = MagickGetImageHeight(magick_wand);
	img_width= MagickGetImageWidth(magick_wand);

	switch(Z_LVAL_P(gravity)){
		case IMAGETOOL_NORTHWEST:
			DrawSetTextAlignment(drawing_wand, LeftAlign);
			x = 0.0;
			y = 20.0;
		break;
		case IMAGETOOL_NORTH:
			x = img_width/2;
			y = 20.0;
		break;
		case IMAGETOOL_NORTHEAST:
			DrawSetTextAlignment(drawing_wand, RightAlign);
			x = img_width;
			y = 20.0;
		break;
		case IMAGETOOL_WEST:
			DrawSetTextAlignment(drawing_wand, LeftAlign);
			x = 0.0;
			y = img_height/2;
		break;
		case IMAGETOOL_CENTER:
			x = img_width/2;
			y = img_height/2;
		break;
		case IMAGETOOL_EAST:
			DrawSetTextAlignment(drawing_wand, RightAlign);
			x = img_width;
			y = img_height/2;
		break;
		case IMAGETOOL_SOUTHWEST:
			DrawSetTextAlignment(drawing_wand, LeftAlign);
			x = 0.0;
			y = img_height;
		break;
		case IMAGETOOL_SOUTH:
			x = img_width/2;
			y = img_height;
		break;
		case IMAGETOOL_SOUTHEAST:
			DrawSetTextAlignment(drawing_wand, RightAlign);
			x = img_width;
			y = img_height;
		break;
		case IMAGETOOL_STATIC:
		default:
			x = 0.0;
			y = 20.0;
	}

	if(font != NULL){
		for(zend_hash_internal_pointer_reset(Z_ARRVAL_P(font));
			zend_hash_has_more_elements(Z_ARRVAL_P(font)) == SUCCESS;
			zend_hash_move_forward(Z_ARRVAL_P(font))){
			char *key;
			uint key_len;
			ulong idx;
			zval **pp_zval;

			if(zend_hash_get_current_key_ex(Z_ARRVAL_P(font), &key, &key_len, &idx, 0, NULL) != HASH_KEY_IS_STRING){
				continue;
			}

			if(zend_hash_get_current_data(Z_ARRVAL_P(font), (void**)&pp_zval) == FAILURE){
				continue;
			}

			if(stricmp(key, "color") == 0){
				PixelWand *pixel_wand;
				pixel_wand = NewPixelWand();
				convert_to_string(*pp_zval);

				PixelSetColor(pixel_wand, Z_STRVAL_PP(pp_zval));
				DrawSetFillColor(drawing_wand, pixel_wand);
			}else if(stricmp(key, "name") == 0){
				convert_to_string(*pp_zval);
				DrawSetFont(drawing_wand, Z_STRVAL_PP(pp_zval));
			}else if(stricmp(key, "size") == 0){
				convert_to_long(*pp_zval);
				DrawSetFontSize(drawing_wand, Z_LVAL_PP(pp_zval));
			}else if(stricmp(key, "weight") == 0){
				convert_to_long(*pp_zval);
				DrawSetFontWeight(drawing_wand, Z_LVAL_PP(pp_zval));
			}
		}
	}
	// php_printf("width=%d,height=%d,x=%f,y=%f\n", img_width, img_height, x, y);
	DrawAnnotation(drawing_wand, x, y, Z_STRVAL_P(txt));
	MagickDrawImage(magick_wand, drawing_wand);
}

ZEND_METHOD(Image_Tool, clean){
	zval *z_magick_wand;
	MagickWand *magick_wand;

	GET_MAGICK_WAND(z_magick_wand, magick_wand);
	ClearMagickWand(magick_wand);
	RETURN_TRUE;
}


//Image_Tool::composite($src_img, $x, $y)
ZEND_METHOD(Image_Tool, composite){
	zval *z_magick_wand, *z_x, *z_y;
	zval *z_src_magcik_wand, *src_img;
	MagickWand *magick_wand, *src_magcik_wand;
	MagickSizeType img_size;

	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zzz", &src_img, &z_x, &z_y) == FAILURE){
		RETURN_FALSE;
	}

	GET_MAGICK_WAND(z_magick_wand, magick_wand);
	convert_to_long(z_x);
	convert_to_long(z_y);

	if(Z_TYPE_P(src_img) == IS_OBJECT && instanceof_function(Z_OBJCE_P(src_img), g_imagetool_ce)){
		z_src_magcik_wand = zend_read_property(Z_OBJCE_P(src_img), src_img, ZEND_STRL("magick_wand"), 0 TSRMLS_CC);
		src_magcik_wand = ZEND_FETCH_RESOURCE_NO_RETURN(src_magcik_wand, MagickWand*, &z_src_magcik_wand, -1, IMAGETOOL_MAGICKWAND_RSRC_NAME, le_image_wand);
		if(MagickGetImageLength(src_magcik_wand, &img_size) == MagickFalse) {
			RETURN_FALSE;
		}
	}else if(Z_TYPE_P(src_img) == IS_STRING){
		src_magcik_wand = NewMagickWand();
		if(MagickReadImageBlob(src_magcik_wand, (void*)Z_STRVAL_P(src_img), Z_STRLEN_P(src_img)) == MagickFalse){
			RETURN_FALSE;
		}
	}else{
		RETURN_FALSE;
	}

	if(MagickCompositeImage(magick_wand, src_magcik_wand, OverCompositeOp, Z_LVAL_P(z_x), Z_LVAL_P(z_y)) == MagickFalse){
		RETURN_FALSE;
	}

	RETURN_TRUE;
}

ZEND_METHOD(Image_Tool, errmsg){
	zval *errmsg;
	errmsg = zend_read_property(FETCH_THIS, ZEND_STRL("errmsg"), 0 TSRMLS_CC);

	if(Z_TYPE_P(errmsg) == IS_NULL){
		RETURN_NULL();
	}
	else{
		RETURN_STRINGL(Z_STRVAL_P(errmsg), Z_STRLEN_P(errmsg), 1);
	}
}

ZEND_METHOD(Image_Tool, errcode){
	zval *errcode;
	errcode = zend_read_property(FETCH_THIS, ZEND_STRL("errcode"), 0 TSRMLS_CC);

	RETURN_LONG(Z_LVAL_P(errcode));
}

//Image_Tool::exec($filename, $display=false);
ZEND_METHOD(Image_Tool, exec){
	zval *filename, *display = NULL, *z_magick_wand;
	MagickWand *magick_wand;

	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z", &filename, &display) == FAILURE){
		RETURN_FALSE;
	}

	z_magick_wand = zend_read_property(FETCH_THIS, ZEND_STRL("magick_wand"), 0 TSRMLS_CC);
	ZEND_FETCH_RESOURCE_NO_RETURN(magick_wand, MagickWand*, &z_magick_wand, -1, IMAGETOOL_MAGICKWAND_RSRC_NAME, le_image_wand);

	if(display == NULL){
		MAKE_STD_ZVAL(display);
		ZVAL_LONG(display, 0);
	}
	convert_to_boolean(display);
	if(Z_BVAL_P(display) <= 0){
		if(MagickWriteImage(magick_wand, Z_STRVAL_P(filename)) == MagickFalse){
			zend_error(E_WARNING, "write image error.");
			RETURN_FALSE;
		}
	}else{
		if(MagickWriteImage(magick_wand, Z_STRVAL_P(filename)) == MagickFalse){
			zend_error(E_WARNING, "write image error.");
			RETURN_FALSE;
		}
	}
}

//Image_Tool::flipH()
ZEND_METHOD(Image_Tool, flipH){
	zval *function_name, *params[1];
	MAKE_STD_ZVAL(function_name);
	ZVAL_STRINGL(function_name, "rotate", 6, 1);

	MAKE_STD_ZVAL(params[0]);
	ZVAL_LONG(params[0], 180);

	call_user_function(NULL, &this_ptr, function_name, return_value, 1, params TSRMLS_CC);
	zval_dtor(function_name);
	zval_dtor(params[0]);
	RETURN_TRUE;
}

//Image_Tool::flipV()
ZEND_METHOD(Image_Tool, flipV){
	zval *function_name, *params[1];
	MAKE_STD_ZVAL(function_name);
	ZVAL_STRINGL(function_name, "rotate", 6, 1);

	MAKE_STD_ZVAL(params[0]);
	ZVAL_LONG(params[0], 90);

	call_user_function(NULL, &this_ptr, function_name, return_value, 1, params TSRMLS_CC);
	zval_dtor(function_name);
	zval_dtor(params[0]);
	RETURN_TRUE;
}

//Image_Tool::getImageAttr()
ZEND_METHOD(Image_Tool, getImageAttr){
	zval *z_magick_wand;
	size_t width, height;
	MagickWand *magick_wand;
	char *type;

	GET_MAGICK_WAND(z_magick_wand, magick_wand);

	width = MagickGetImageWidth(magick_wand);
	height= MagickGetImageHeight(magick_wand);
	type= MagickGetImageFormat(magick_wand);

	array_init(return_value);
	add_assoc_long(return_value, "width", width);
	add_assoc_long(return_value, "height", height);
	add_assoc_stringl(return_value, "type", type, strlen(type), 1);
}

//Image_Tool::getImageAttr()
ZEND_METHOD(Image_Tool, improve){
	zval *z_magick_wand;
	MagickWand *magick_wand;

	GET_MAGICK_WAND(z_magick_wand, magick_wand);

	MagickEnhanceImage(magick_wand);

	RETURN_TRUE;
}

//Image_Tool::resize($width=0, $height=0, $thumbnail=true);
ZEND_METHOD(Image_Tool, resize){
	zval *z_magick_wand, *width, *height, *thumbnail=NULL;
	size_t img_width, img_height;
	MagickWand *magick_wand;

	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|l", &width, &height, &thumbnail) == FAILURE){
		RETURN_FALSE;
	}

	convert_to_long(width);
	convert_to_long(height);
	if(thumbnail == NULL){
		MAKE_STD_ZVAL(thumbnail);
		ZVAL_LONG(thumbnail, 1);
	}else{
		convert_to_long(thumbnail);
	}

	GET_MAGICK_WAND(z_magick_wand, magick_wand);

	img_width = MagickGetImageWidth(magick_wand);
	img_height= MagickGetImageHeight(magick_wand);
	Z_LVAL_P(width) = (Z_LVAL_P(width) > img_width) ? img_width : Z_LVAL_P(width);
	Z_LVAL_P(height) = (Z_LVAL_P(height) > img_height) ? img_height : Z_LVAL_P(height);

	if(Z_LVAL_P(thumbnail) > 0){
		MagickThumbnailImage(magick_wand, Z_LVAL_P(width), Z_LVAL_P(height));
	}else{
		MagickResizeImage(magick_wand, Z_LVAL_P(width), Z_LVAL_P(height), LanczosFilter, 1.0);
	}

	RETURN_TRUE;
}

//Image_Tool::resizeRatio($ratio, $thumbnail=true)
ZEND_METHOD(Image_Tool, resizeRatio){
	zval *z_magick_wand, *ratio, *thumbnail = NULL;
	MagickWand *magick_wand;
	size_t src_width, src_height, dst_width, dst_height;

	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z", &ratio, &thumbnail) == FAILURE){
		RETURN_FALSE;
	}

	GET_MAGICK_WAND(z_magick_wand, magick_wand);

	convert_to_double(ratio);

	src_width = MagickGetImageWidth(magick_wand);
	src_height= MagickGetImageHeight(magick_wand);

	if(Z_DVAL_P(ratio) > 1.0) Z_DVAL_P(ratio) = 1.0;
	if(Z_DVAL_P(ratio) < 0.0) Z_DVAL_P(ratio) = 0.0;

	dst_width = src_width * Z_DVAL_P(ratio);
	dst_height= src_height* Z_DVAL_P(ratio); 

	if(thumbnail == NULL){
		MAKE_STD_ZVAL(thumbnail);
		ZVAL_LONG(thumbnail, 1);
	}

	if(Z_LVAL_P(thumbnail) > 0){
		MagickThumbnailImage(magick_wand, dst_width, dst_height);
	}else{
		MagickResizeImage(magick_wand, dst_width, dst_height, LanczosFilter, 1.0);
	}

	RETURN_TRUE;
}

//Image_Tool:rotate($degree=90);
ZEND_METHOD(Image_Tool, rotate){
	zval *z_magick_wand, *degree;
	MagickWand *magick_wand;
	PixelWand *pixel_wand;

	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z!", °ree) == FAILURE){
		RETURN_FALSE;
	}

	if(Z_TYPE_P(degree) == IS_NULL){
		MAKE_STD_ZVAL(degree);
		ZVAL_LONG(degree, 90);
	}

	if(Z_TYPE_P(degree) != IS_LONG) convert_to_long(degree);

	pixel_wand = NewPixelWand();
	z_magick_wand = zend_read_property(FETCH_THIS, ZEND_STRL("magick_wand"), 0 TSRMLS_CC);
	ZEND_FETCH_RESOURCE_NO_RETURN(magick_wand, MagickWand *, &z_magick_wand, -1, IMAGETOOL_MAGICKWAND_RSRC_NAME, le_image_wand);

	MagickRotateImage(magick_wand, pixel_wand, Z_LVAL_P(degree));
}

//ImageTool::setData($img_blob)
ZEND_METHOD(Image_Tool, setData){
	zval *z_magick_wand, *z_img_blob;
	MagickWand *magick_wand;

	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &z_img_blob) == FAILURE){
		RETURN_FALSE;
	}

	if(Z_TYPE_P(z_img_blob) != IS_STRING){
		RETURN_FALSE;
	}

	GET_MAGICK_WAND(z_magick_wand, magick_wand);

	if(MagickReadImageBlob(magick_wand, (void*)Z_STRVAL_P(z_img_blob), Z_STRLEN_P(z_img_blob)) == MagickTrue){
		RETURN_TRUE;
	}else{
		RETURN_FALSE;
	}
}

static zend_function_entry image_tool_methods[] = {
	ZEND_ME(Image_Tool, __construct, setData_arginfo, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC)
	ZEND_ME(Image_Tool, __tostring, void_arginfo, ZEND_ACC_PUBLIC)
	ZEND_ME(Image_Tool, annotate, annotate_arginfo, ZEND_ACC_PUBLIC)
	ZEND_ME(Image_Tool, clean, void_arginfo, ZEND_ACC_PUBLIC)
	ZEND_ME(Image_Tool, composite, composite_arginfo, ZEND_ACC_PUBLIC)
	ZEND_ME(Image_Tool, errmsg, void_arginfo, ZEND_ACC_PUBLIC)
	ZEND_ME(Image_Tool, errcode, void_arginfo, ZEND_ACC_PUBLIC)
	ZEND_ME(Image_Tool, exec, exec_arginfo, ZEND_ACC_PUBLIC)
	ZEND_ME(Image_Tool, flipH, void_arginfo, ZEND_ACC_PUBLIC)
	ZEND_ME(Image_Tool, flipV, void_arginfo, ZEND_ACC_PUBLIC)
	ZEND_ME(Image_Tool, getImageAttr, void_arginfo, ZEND_ACC_PUBLIC)
	ZEND_ME(Image_Tool, improve, void_arginfo, ZEND_ACC_PUBLIC)
	ZEND_ME(Image_Tool, resize, resize_arginfo, ZEND_ACC_PUBLIC)
	ZEND_ME(Image_Tool, resizeRatio, resizeRatio_arginfo, ZEND_ACC_PUBLIC)
	ZEND_ME(Image_Tool, rotate, rotate_arginfo, ZEND_ACC_PUBLIC)
	ZEND_ME(Image_Tool, setData, setData_arginfo, ZEND_ACC_PUBLIC)
	{NULL, NULL, NULL}
};

/* {{{ image_tool_functions[]
 *
 * Every user visible function must have an entry in image_tool_functions[].
 */
const zend_function_entry image_tool_functions[] = {
	PHP_FE_END	/* Must be the last line in image_tool_functions[] */
};
/* }}} */

/* {{{ image_tool_module_entry
 */
zend_module_entry image_tool_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
	STANDARD_MODULE_HEADER,
#endif
	"image_tool",
	image_tool_functions,
	PHP_MINIT(image_tool),
	PHP_MSHUTDOWN(image_tool),
	PHP_RINIT(image_tool),		/* Replace with NULL if there's nothing to do at request start */
	PHP_RSHUTDOWN(image_tool),	/* Replace with NULL if there's nothing to do at request end */
	PHP_MINFO(image_tool),
#if ZEND_MODULE_API_NO >= 20010901
	"0.1", /* Replace with version number for your extension */
#endif
	STANDARD_MODULE_PROPERTIES
};
/* }}} */

#ifdef COMPILE_DL_IMAGE_TOOL
ZEND_GET_MODULE(image_tool)
#endif

/* {{{ PHP_MINIT_FUNCTION
 */
PHP_MINIT_FUNCTION(image_tool)
{
	/* If you have INI entries, uncomment these lines 
	REGISTER_INI_ENTRIES();
	*/
	zend_class_entry image_tool_ce;
	INIT_CLASS_ENTRY(image_tool_ce, "Image_Tool", image_tool_methods);
	g_imagetool_ce = zend_register_internal_class(&image_tool_ce TSRMLS_CC);

	zend_declare_property_null(g_imagetool_ce, ZEND_STRL("magick_wand"), ZEND_ACC_PROTECTED TSRMLS_CC);
	zend_declare_property_long(g_imagetool_ce, ZEND_STRL("errcode"), 0, ZEND_ACC_PROTECTED TSRMLS_CC);
	zend_declare_property_null(g_imagetool_ce, ZEND_STRL("errmsg"), ZEND_ACC_PROTECTED TSRMLS_CC);

	REGISTER_LONG_CONSTANT("IMAGETOOL_NORTHWEST", IMAGETOOL_NORTHWEST, CONST_CS);
	REGISTER_LONG_CONSTANT("IMAGETOOL_NORTH", IMAGETOOL_NORTH, CONST_CS);
	REGISTER_LONG_CONSTANT("IMAGETOOL_NORTHEAST", IMAGETOOL_NORTHEAST, CONST_CS);
	REGISTER_LONG_CONSTANT("IMAGETOOL_WEST", IMAGETOOL_WEST, CONST_CS);
	REGISTER_LONG_CONSTANT("IMAGETOOL_CENTER", IMAGETOOL_CENTER, CONST_CS);
	REGISTER_LONG_CONSTANT("IMAGETOOL_EAST", IMAGETOOL_EAST, CONST_CS);
	REGISTER_LONG_CONSTANT("IMAGETOOL_SOUTHWEST", IMAGETOOL_SOUTHWEST, CONST_CS);
	REGISTER_LONG_CONSTANT("IMAGETOOL_SOUTH", IMAGETOOL_SOUTH, CONST_CS);
	REGISTER_LONG_CONSTANT("IMAGETOOL_SOUTHEAST", IMAGETOOL_SOUTHEAST, CONST_CS);
	REGISTER_LONG_CONSTANT("IMAGETOOL_STATIC", IMAGETOOL_STATIC, CONST_CS);

	REGISTER_LONG_CONSTANT("IMAGETOOL_TOP_LEFT", IMAGETOOL_TOP_LEFT, CONST_CS);
	REGISTER_LONG_CONSTANT("IMAGETOOL_TOP_CENTER", IMAGETOOL_TOP_CENTER, CONST_CS);
	REGISTER_LONG_CONSTANT("IMAGETOOL_TOP_RIGHT", IMAGETOOL_TOP_RIGHT, CONST_CS);
	REGISTER_LONG_CONSTANT("IMAGETOOL_CENTER_LEFT", IMAGETOOL_CENTER_LEFT, CONST_CS);
	REGISTER_LONG_CONSTANT("IMAGETOOL_CENTER_CENTER", IMAGETOOL_CENTER_CENTER, CONST_CS);
	REGISTER_LONG_CONSTANT("IMAGETOOL_CENTER_RIGHT", IMAGETOOL_CENTER_RIGHT, CONST_CS);
	REGISTER_LONG_CONSTANT("IMAGETOOL_BOTTOM_LEFT", IMAGETOOL_BOTTOM_LEFT, CONST_CS);
	REGISTER_LONG_CONSTANT("IMAGETOOL_BOTTOM_CENTER", IMAGETOOL_BOTTOM_CENTER, CONST_CS);
	REGISTER_LONG_CONSTANT("IMAGETOOL_BOTTOM_RIGHT", IMAGETOOL_BOTTOM_RIGHT, CONST_CS);

	//注册MagickWand、PixelWand资源
	le_image_wand = zend_register_list_destructors_ex(destroy_magick_wand, NULL, IMAGETOOL_MAGICKWAND_RSRC_NAME, module_number);
	le_image_pixel= zend_register_list_destructors_ex(destroy_pixel_wand, NULL, IMAGETOOL_PIXELWAND_RSRC_NAME, module_number);

	return SUCCESS;
}
/* }}} */

/* {{{ PHP_MSHUTDOWN_FUNCTION
 */
PHP_MSHUTDOWN_FUNCTION(image_tool)
{
	/* uncomment this line if you have INI entries
	UNREGISTER_INI_ENTRIES();
	*/
	MagickWandTerminus();
	return SUCCESS;
}
/* }}} */

/* Remove if there's nothing to do at request start */
/* {{{ PHP_RINIT_FUNCTION
 */
PHP_RINIT_FUNCTION(image_tool)
{
	return SUCCESS;
}
/* }}} */

/* Remove if there's nothing to do at request end */
/* {{{ PHP_RSHUTDOWN_FUNCTION
 */
PHP_RSHUTDOWN_FUNCTION(image_tool)
{
	return SUCCESS;
}
/* }}} */

/* {{{ PHP_MINFO_FUNCTION
 */
PHP_MINFO_FUNCTION(image_tool)
{
	php_info_print_table_start();
	php_info_print_table_header(2, "image_tool support", "enabled");
	php_info_print_table_end();

	/* Remove comments if you have entries in php.ini
	DISPLAY_INI_ENTRIES();
	*/
}
/* }}} */

源码下载地址:http://git.oschina.net/365690485/php-class-image_tool

 类似资料: