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

时间:2022-10-24 09:15:31

该扩展是基于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();
*/
MagickWand*();
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