Django&JQuery手动剪切个性头像

最近看了豆瓣的头像剪切应用,也想自己做一个,但在Django上做这样的功能,怎么入手呢?google了一下,很少相关的材料,还得自己构想一下。理清了思路,大概是这样的:前端使用JQuery,用户选择剪切区域,之后取到图片的宽度和高度,起始点的xy坐标(左上角的xy轴位置)和结束点的xy坐标(右下角的xy轴位置),然后把这六个参数呈现到表单上,提交给django处理;后端用Python的PIL来处理,Python的PIL图形处理类库功能很全,可以在里面找到相关的函数,根据前端提供的六个参数,对原图片进行剪切。
废话少说,开始动手了,搜了相关的JQuery插件,发现顶顶有名的插件:jquery imgareaselect ,恰恰是我需要的东西,通过它能得到我上面提到的六个必须参数。倒是Python的PIL库很陌生,找了很多的函数都不满意,所以暂时使用transform函数,它是我目前所需最接近的函数。
前端页面有两个图片容器,一个是放置原图的,另一个是放置缩略图,然后是六个输入框,分别呈现剪切图片的宽度 高度 起始点的x坐标值,y坐标值和结束点的x坐标值,y坐标值。只要脚本选中区域,这六个输入框就有数据,然后提交给django来处理,这样的话显然用到django的form了。准备工作算是完成了,开始编代码了:
前端代码hathead_cut.html:
<link rel="stylesheet" type="text/css" href="/media/js/jquery_imgareaselect_0_9_1/css/imgareaselect-default.css" />
<style rel="stylesheet"  type="text/css" >
.demo 
{
background
:none repeat scroll 0 0 #EEEEFF;
border
:2px solid #DDDDEE;
padding
:0.6em;
width
:85%;
}
div.frame 
{
background
:none repeat scroll 0 0 #FFFFFF;
border
:2px solid #DDDDDD;
padding
:0.8em;
}
</style>
<script type="text/javascript" src="/media/js/jquery.js"></script>
<script type="text/javascript" src="/media/js/jquery_imgareaselect_0_9_1/scripts/jquery.imgareaselect.min.js"></script> 
<script type="text/javascript">
function preview(img, selection) {
 
if (!selection.width || !selection.height)
 
return;

 
var scaleX = 100 / selection.width;
 
var scaleY = 100 / selection.height;

 $(
'#preview img').css({
 width: Math.round(scaleX 
* 300),
 height: Math.round(scaleY 
* 300),
 marginLeft: 
-Math.round(scaleX * selection.x1),
 marginTop: 
-Math.round(scaleY * selection.y1)
 });

 $(
'#id_x1').val(selection.x1);
 $(
'#id_y1').val(selection.y1);
 $(
'#id_x2').val(selection.x2);
 $(
'#id_y2').val(selection.y2);
 $(
'#id_w').val(selection.width);
 $(
'#id_h').val(selection.height);
}

$(
function () {$('#photo').imgAreaSelect({ aspectRatio: '1:1', handles: true,
fadeSpeed: 
200, minHeight:100,minWidth:100,onSelectChange: preview });
}); 
</script>

<div>
    
<h3>头像剪切  </h3>
<div class="demo">
 
<div style="float: left; width: 45%;">
  
<class="instructions">
   点击原图 选择剪切区域
  
</p>
 
  
<div style="margin: 0pt 0.3em; width: 300px; height: 300px;" class="frame">
   
<img src="{{baseinfo.hathead}}_300_300.jpg" id="photo" alt="30"/>
  
</div>
 
</div>
 
 
<div style="float: left; width: 40%; padding-top:50px;">
  
<style="font-size: 110%; font-weight: bold; padding-left: 0.1em;">
   预览选择区域
  
</p>
  
  
<div style="margin: 0pt 1em; width: 100px; height: 100px;" class="frame">
   
<div style="width: 100px; height: 100px; overflow: hidden;" id="preview">
    
<img style="width: 244px; height: 244px; margin-left: -71px; margin-top: -54px;" src="{{baseinfo.hathead}}_300_300.jpg" alt="300"/>
   
</div>
  
</div>
<form action="" method="POST">
  
<table style="margin-top: 1em;">
   
<thead>
    
<tr>
     
<th style="font-size: 110%; font-weight: bold; text-align: left; padding-left: 0.1em;" colspan="2">
      剪切坐标
     
</th>
     
<th style="font-size: 110%; font-weight: bold; text-align: left; padding-left: 0.1em;" colspan="2">
      剪切尺寸
     
</th>
    
</tr>
   
</thead>
   
<tbody>
    
<tr>
     
<td style="width: 10%;"><b>X<sub>1</sub>:</b></td>
     
<td style="width: 30%;">{{form.x1}}</td>
     
<td style="width: 20%;"><b>宽度:</b></td>
     
<td>{{form.w}}</td>
    
</tr>
    
<tr>
     
<td><b>Y<sub>1</sub>:</b></td>
     
<td>{{form.y1}}</td>
     
<td><b>高度:</b></td>
     
<td>{{form.h}}</td>
    
</tr>
    
<tr>
     
<td><b>X<sub>2</sub>:</b></td>
     
<td>{{form.x2}}</td>
     
<td></td>
     
<td></td>
    
</tr>
    
<tr>
     
<td><b>Y<sub>2</sub>:</b></td>
     
<td>{{form.y2}}</td>
     
<td></td>
     
<td><input type="submit" value="保存"/></td>
    
</tr>
   
</tbody>
  
</table>
</form>
 
</div>

 

django的form代码:
class HatHeadCutForm(forms.Form):
    x1
=forms.IntegerField(widget=forms.TextInput(attrs={'size'4,}))
    y1
=forms.IntegerField(widget=forms.TextInput(attrs={'size'4,}))
    x2
=forms.IntegerField(widget=forms.TextInput(attrs={'size'4,}))    
    y2
=forms.IntegerField(widget=forms.TextInput(attrs={'size'4,}))
    w
=forms.IntegerField(widget=forms.TextInput(attrs={'size'4,}))
    h
=forms.IntegerField(widget=forms.TextInput(attrs={'size'4,}))

 

django的views代码:
def hathead_cut(request,id):
    template_var
={}
    
try:
        baseinfo
=BaseInfo.objects.get(id=int(id))
    
except BaseInfo.DoesNotExist:
        
return Http404()
        
    
if not baseinfo.hathead:
        request.user.message_set.create(message
=u"请先上传图片!")
        
return HttpResponseRedirect(reverse("upload_hathead"))
        
    template_var[
"baseinfo"]=baseinfo
    abs_path
="%s/%s/"%(MEDIA_ROOT,"hathead")
    file_name
="%s_%s"%(request.user.username,"hathead_300_300.jpg"
    form
=HatHeadCutForm()
    
if request.method=='POST':
        form
=HatHeadCutForm(request.POST)
        
if form.is_valid():            
            
try:
                img
=Image.open(abs_path+file_name)
            
except IOError:
                request.user.message_set.create(message
=u"系统错误!")
            data
=form.cleaned_data
            img
=img.transform((data["w"],data["h"]),EXTENT,(data["x1"],data["y1"],data["x2"],data["y2"]))
          
            img.thumbnail((
100100))
            file_name
="%s_%s"%(request.user.username,"hathead_100_100.jpg")
            img.save(
"%s%s"%(abs_path,file_name),"JPEG")
            
            img.thumbnail((
5050))            
            file_name
="%s_%s"%(request.user.username,"hathead_50_50.jpg")            
            img.save(
"%s%s"%(abs_path,file_name),"JPEG")
            request.user.message_set.create(message
=u"保存成功!")
            
return HttpResponseRedirect(reverse("upload_hathead"))
        
else:
            request.user.message_set.create(message
=u"请剪切后 再保存!")
    template_var[
"form"]=form
    
return render_to_response("hathead_cut.html",template_var,context_instance=RequestContext(request))

 

以上的代码,先读取一张300*300的图片,脚本选中100*100的区域,提交给Django剪切,最后把100*100剪切好的图再剪切一张50*50的图。脚本剪切的比列是1:1。脚本jquery imgareaselect的相关文档你可以从官方网找到,可以任意做出自己需要的效果。django的form的作用是渲染出表单(六个输入框。注:图片是直接读取磁盘文件,缩略图效果全是是jquery imgareaselect生成的);django的views的作用是根据表单提交的六个参数,剪切图片,主要代码是:img=img.transform((data["w"],data["h"]),EXTENT,(data["x1"],data["y1"],data["x2"],data["y2"]))。


之前有一个操作就不在这里介绍了,它的工作主要是上传一张宽度高度不规则的图片,然后只经过PIL剪切成正方形的图片,保存到磁盘里,PIL剪切图片很简单,如果想把一张不规则的图片剪切成正方形就需要用到一点技巧了,如果兴趣的话,接下来想单独介绍一下原理。

同文:http://2goo.info/blog/panjj/Django/2010/03/12/34 

posted @ 2010-03-12 22:30 2goO 阅读(...) 评论(...) 编辑 收藏