JS+PHP实现图片裁剪

用到几个插件:
1.Jquery上传插件: Fine Uploader
2.JS图片裁剪:imgAreaSelect
3.PHP上传/PHP GD库

原理:
PHP的imagecopy()函数可以将一张图片的一部分复制到另一张图片中,而imgAreaSelect可以获得用户裁剪图片的坐标及高宽,利用imgAreaSelect将需裁剪的x轴起点、y轴起点、宽、高四个参数传给PHP,PHP完成复制图片工作。

要点:
1.图片预览/截图。如果浏览器兼容FileApi ,问题就简单多,直接读取本地文件完成预览、获得截图的坐标和宽高等参数。考虑到IE10之前都不支持的情况,可以利用AJAX上传的方法,先将图片传到服务器,然后读取出来进行预览和裁剪。
2.PHP处理图片。PHP进行图片复制需要获得以下几个参数:原图片路径、x轴起点、y轴起点、宽、高。如果服务器支持ImageMagick扩展,可以直接利用Imagick::cropImage函数进行裁剪。不支持的话,可以采用最原始的方法,先用imagecreatetruecolor函数生成一副和截图区域等宽等高的空白图片,再用imagecopy将原图的截图复制过来。

关键代码:
1.PHP的处理


class Pic{
	public $picInfo;

	public function get_pic_info( $file ){
		if( ($im = getimagesize($file)) == false ){
			$this->error = "$file is not a valid image file";
			return false;
		}

		$fileInfo = pathinfo( $file );
		$info = array(
			'width'	=> $im[0],
			'height'=> $im[1],
			'name'	=> $fileInfo['filename'],
			'type'	=> strtolower($fileInfo['extension']),
			'mime'	=> $im['mime'],
			'path'	=> $fileInfo['dirname'].'/'
			);
		$this->picInfo = $info;
		//return $info;
      	}

	/**
	 * 截取图片
	 * 
	 * @param $source_file 源文件地址
	 * @param $x 截取x轴起点
	 * @param $y 截取y轴起点
	 * @param $width 截取宽度
	 * @param $height 截取高度
	 * @return bool | resource
	 * @since v1.0
	 * @create 2012-12-20
	 */
	public function cut( $source_file, $x, $y, $width, $height ){
		$this->get_pic_info( $source_file );	
		$info = $this->picInfo;
		if( !$info ){
			$this->error = "failed to get $source_file";
			return false;
		}
		// 判断截取是否有效
		if( $x>=$info['width'] || $y>=$info['height'] || $width>$info['width'] || $height>$info['height'] || !$width || !$height ){
			$this->error = "invalid crop params";
			return false;
		}

		$type = $info['type'] == 'jpg' ? 'jpeg' : $info['type'];
		// 根据源文件类型创建对象
		$func = "imagecreatefrom".$type;
		if( ($im = $func( $source_file )) ==  false ){
			$this->error = "create gd resource failed";
			return false;		
		}

		// 创建一个目标文件
		$dst = imagecreatetruecolor( $width, $height );
		// 设定背景色为白色
		$color = imagecolorallocatealpha($dst, 255, 255, 255, 0);	
		imagefill( $dst, 0, 0, $color );
		// 复制源文件的指定区域
		if( !imagecopy( $dst, $im, 0, 0, $x, $y, $width, $height ) ){
			$this->error = "copy image fail";
			return false;
		}

		// 根据文件类型保存对象
		$func = "image".$type;

		ob_start();
		if( $type=='jpeg' ){
			$func( $dst, NULL, 85);
		}else{
			$func( $dst, NULL ); 
		}
		$newIm = ob_get_clean();

		if( !$newIm ){
			$this->error = "create image fail";
			return false;
		}
		imagedestroy( $dst );

		return $newIm;
	}
}

2. JS的处理:


var picEditor;
var imguploader = $(‘#fileuploadbtn’).fineUploader({
request: {
endpoint: ‘upload.php’,
},validation: {
allowedExtensions: [‘jpeg’, ‘jpg’, ‘png’, ‘gif’],
sizeLimit: 2097152
},
text: {
uploadButton: ‘点击上传’
},
dragAndDrop: {
extraDropzones:[$(‘#dropzone’)],
hideDropzones: true,
disableDefaultDropzone: false,
},
template: ‘

‘ +

{uploadButtonText}

‘ +

    ‘ +


    }).on(‘complete’, function(event, id, filename, json){
    // ajax上传返回json数据
    if (json.status) {
    //初始化js裁剪插件,设置参数请参看官网文档
    picEditor = $(‘#topfileupload img’).imgAreaSelect({
    handles: true,
    aspectRatio: ‘{$aspectRatio}’,
    instance: true,
    imageHeight: json.height,
    imageWidth: json.width,
    classPrefix: ‘imgareaselect’,
    onSelectEnd: function(img, sel){
    change_preview(sel);
    }
    });
    } else {
    if( json.info ) alert(‘上传失败:’+json.info);
    }
    }).on(‘error’,function(id,fileName,error){
    alert(‘只允许上传小于2M的图片’);
    });

    // 将裁剪参数传给PHP处理
    $(‘#btnSubmit’).click(function(){
    if( !picEditor ){
    $.bigpu.alert(‘请先上传图片’);
    return;
    }
    var s = picEditor.getSelection();
    var f = $(‘#topfileupload img’).attr(‘src’);
    $.ajax({
    url: ‘crop.php’,
    data: ‘file=’+f+’&x=’+s.x1+’&y=’+s.y1+’&width=’+s.width+’&height=’+s.height,
    dataType: ‘json’,
    success: function(json){
    if( json.status ){
    picEditor.remove();
    // PHP完成任务,返回Json供Js回调
    pic_editor_success( json );
    }else{
    alert(‘图片保存失败%>_<%。'); } } }); }) // 截图预览 function change_preview(selection){ //预览宽高 var prevWidth = 100; var prevHeight = 100; if ( selection.width == 0 || selection.height == 0 || !prevWidth || !prevHeight ) { return false;} // 缩放比例 var scaleX = prevWidth / selection.width; var scaleY = prevHeight / selection.height; // 预览定位 $('#imgPreview').css({ width: Math.round(scaleX * picInfo['oldWidth']) + 'px', height: Math.round(scaleY * picInfo['oldHeight']) + 'px', marginLeft: '-' + Math.round(scaleX * selection.x1) + 'px', marginTop: '-' + Math.round(scaleY * selection.y1) + 'px' }); // 记录位置 $('#x').val( selection.x1 ); $('#y').val( selection.y1 ); $('#w').val( selection.width ); $('#h').val( selection.height ); return; } [/javascript]