jcrop+ajaxFileUpload+PHP裁剪图片

裁剪图片用的是PHP原生的方法,首先将文件上传到后台,再利用jcrop在前台裁剪图片,将裁剪的矩形的四个点的坐标传到后台,后台根据接收到的参数利用imagecopyresampled函数对上传的图片进行裁剪。


我的界面设计效果大概如下:



首先是点击选择图片按钮弹出file对话框,在选定文件后触发文件选择框的change事件,此时用ajaxFileUpload插件(异步上传文件)先将图片上传到后台。

//选择完文件后预览
	$('#upload-file').on("change",function(){
		ajax_file_upload();
	});
function ajax_file_upload(){
	if(jcrop_api != null){
		jcrop_api.destroy();
	}
	$.ajaxFileUpload({
		url: '../ajax/upload_img', //用于文件上传的服务器端请求地址
		secureuri: false, //是否需要安全协议,一般设置为false
		fileElementId: 'upload-file', //文件上传域的ID
		dataType: 'json', //返回值类型 一般设置为json
		success: function (data, status)  //服务器成功响应处理函数
		{
			if(data.code == 1){
				pic_name = data.name;
				//将上传的图片显示到前台并开启裁剪插件
				$("#crop-img").attr("src","../../resouces/pictures_temp/"+data.name);
				$('#crop-img').Jcrop({
					setSelect:[0,0,100,100],
					aspectRatio: 1
				},function(){
					// Store the API in the jcrop_api variable
					jcrop_api = this;
				});
			}else{
				layer.msg('上传失败!',{
					offset:"200px",
				});
			}
			
			//重新绑定事件 事件失效原因未知
			$('#upload-file').on("change",function(){
				ajax_file_upload();
			});
		}, 
	});
}
有时由于未知原因,在上传后会使file选择框的change事件失效,故若想修改之前上传的图片,得在上传方法执行成功后再次绑定一次change事件。

先附上upload_img方法,我的后台采用的是CI框架,故上传用的是CI框架封装好的方法:

//上传个人头像
	public function upload_img(){
		$id = $this->session->userdata('uid');
		$config['upload_path'] = './resouces/pictures_temp/';
		
		//如果目录不存在则创建
		if(!file_exists($config['upload_path']))  {  
			mkdir($config['upload_path'],0700,true);  
		}

		$config['encrypt_name'] = false;
		$config['allowed_types'] = 'jpg|png';//文件类型
		$config['max_size'] = '10240';
		$config['file_name'] = $id.".jpg";
		
		$file = $config['upload_path'].$config['file_name'];
		if(file_exists($file)){
			unlink($file);
		}
		$result['name'] = $config['file_name'];
		$this->load->library('upload',$config);
		if ($this->upload->do_upload('upload-file')) {
			$result['code'] = 1;
			$uploaddata = $this->upload->data();
			$result['width'] = $uploaddata['image_width'];
			$result['height'] = $uploaddata['image_height'];
		}else{
			$result['code'] = 2;
			$result['error'] = $this->upload->display_errors();//输出错误原因
		}
		echo json_encode($result);
	}
后台图片上传完后,前台对jcrop进行初始化,我这边设定了一个默认的100*100的裁剪框。效果如下:

此时可根据自身需求随意设定需要裁剪的位置和大小,当点击上传时,将获取裁剪矩形的4个点的坐标,将参数传递到后台:

//上传图片
	$('#upload-img').on("click",function(){
		//获取截取框4点的坐标
		var x = jcrop_api.tellSelect().x;
		var y = jcrop_api.tellSelect().y;
		var width = jcrop_api.tellSelect().x2 - x;
		var height = jcrop_api.tellSelect().y2 - y;
		
		//将值传到php后台 php对图片进行处理
		$.post('../ajax/crop_img', {
			x:x,
			y:y,
			width:width,
			height:height,
			name:pic_name,
		},function(data){
			var imgStr = "../../resouces/pictures/"+data;
			$('.show-area > img').attr("src",imgStr);
			layer.msg('上传成功!',{
				offset:"200px",
			});
		}, 'text');
	});
由于jcrop提供的方法几乎都只能打印出矩形4个点的坐标,而imagecopyresampled这个方法需要裁剪后的图片的宽高,所以我在前台先做了一遍计算,再将值传递过去。

后台crop_img是我用来处理生成后的图片并入库的方法,它直接调用了get_crop_img()方法对图像进行裁剪:

//裁剪头像并入库
	public function crop_img(){
		$id = $this->session->userdata('uid');
		
		$x = $this->input->get_post("x");
		$y = $this->input->get_post("y");
		$width = $this->input->get_post("width");
		$height = $this->input->get_post("height");
		$name = $this->input->get_post("name");
		
		$filename = './resouces/pictures_temp/' . $name;
		$newname = './resouces/pictures/' . $name;
		get_crop_img($filename,$newname,$x,$y,$width,$height);
		
		$conditions = array($name,$id);
		$this->user_model->editPersonImgById($conditions);
		
		echo $name;
	}
//获取裁剪的头像
	function get_crop_img($filename,$newname,$x,$y,$width,$height){
		//如果文件存在则删除
		if(file_exists($newname)){
			chmod($newname,0755);
			unlink($newname);
		}
		
		//获取原图的信息
		$info = getImageInfo($filename);
		//计算新生成的图片尺寸
		$width = $width * ($info['width']/300);
		$height = $height * ($info['height']/300);
		$x = $x * ($info['width']/300);
		$y = $y * ($info['height']/300);
		
		$newimg = imagecreatetruecolor(100, 100); //创建新的图层
		$img = imagecreatefromjpeg($filename); //把原本的图片读进来
		
		imagecopyresampled($newimg, $img, 0, 0, $x, $y, 100, 100, $width, $height);  //画图
		imageinterlace($newimg,1); //隔行扫描
		imagejpeg($newimg,$newname,100);  //生成图片
		imagedestroy($newimg); 
		imagedestroy($img);
	}
getImageInfo()是随手写的一个获取当前图片部分信息的函数:

//获取图片的信息
	function getImageInfo($img){
		$imageInfo = getimagesize($img);
		if( $imageInfo!== false) {
			$imageType = strtolower(substr(image_type_to_extension($imageInfo[2]),1));
			$info = array(
					"width"		=>$imageInfo[0],
					"height"	=>$imageInfo[1],
					"type"		=>$imageType,
					"mime"		=>$imageInfo['mime'],
			);
			return $info;
		}else {
			return false;
		}
	}
生成裁剪图片的流程大概如下:

1. 用imagecreatetruecolor($width,$height)方法生成一个新的空白图层,宽高由你自定义。

2. 用imagecreatefromjpeg($src)方法读取原本图片的资源,$src为图片的路径。返回的对象为一个图层对象。

3. 用imagecopyresampled ($dst_image , $src_image , int $dst_x , int $dst_y , int $src_x , int $src_y , int $dst_w , int $dst_h , int $src_w , int $src_h )方法裁剪原图片,然后将新的图片画到之前创建的空白图层上。$dst_image即你裁剪后图片要画到哪个图层对象,$src_image即原图,$dst_x,$dst_y即为从新图层开始绘画的起始点坐标(即矩形左上角,因为我是新创建的图层,所以我是从(0,0)这个点开始画),int $src_x , $src_y 即为从原图上所截取图片的起始点(截图矩形的左上角点坐标)。dst_w,dst_h 即新图层上你所要画的图片的宽高,src_w,src_h 即为从原图上所截取图片的宽高。这里我对宽高都进行了一定运算,因为我前台是不限制上传图片的像素的,但固定按300*300显示,而jcrop获取的所有参数都是对300*300这个图层进行操作所获取到的,所以我要知道在原图上裁剪的比例,我必须对图片宽高和xy坐标重新计算一遍,即  (300像素图上裁剪的尺寸/300)*原图尺寸 = 原图裁剪的尺寸。

4. imagejpeg($newimg,$newname,$quality),$newimg即为刚刚绘画了的空白图层,$newname即为你要新生成的图片的路径地址(含名字),$quality即为生成图片的质量,默认为75,这里最好填100,不然生成的裁剪图片可能会有瑕疵。

5. imagedestroy($img)销毁图层,释放资源。

注:我为了简便,将上传的图片都做了处理,在后台都生成的是jpg文件,裁剪后的图片我也生成的是jpg文件,如果要生成png文件的话,php方法可能会有部分不同,但仅仅只是将适用与jpeg格式的方法换为适用于png格式的方法。

最后附上裁剪后的结果图:


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值