之前一直使用python的PIL自定义裁切图片,今天有需求需要做一个前端的选择预览页面,索性就把这个功能整理一下,分享给大家。

实现思路

1、前端页面:

用户选择本地一张图片,然后通过鼠标缩放和移动,确定自己所需要的图片切块,最终把图片切块的 左边距,上边距,长,宽这些个参数传给后台

2、后台:

使用的django,主要实现2部分的功能,第一:图片上传,第二:图片裁切

先看一张图片:

前端页面:

后台最后得到的图片:

对于该demo中,我用到了以下js插件

jquery-webox:弹出图层(你可以不关心)

jcrop:在线裁切预览图片 http://deepliquid.com/content/Jcrop_Implementation_Theory.html

jquery.uploadify:上传附件

html页面:

a)用户信息页面:userinfo.html

b)弹出页面用于用户选择、上传、预览图片:index.html

django程序:

UploadImage模块下有以下几个文件:

c)urls.py

d)views.py

下面就开始贴代码了

a)的代码:

{% extends "kidcrate/base.html" %}
{%block contentBar%} <link href="/site_media/uploadify/uploadify.css" type="text/css" rel="stylesheet" />
<script type="text/javascript" src="/site_media/uploadify/jquery.uploadify.min.js"></script> <script type="text/javascript" src="/site_media/js/thickbox.js"></script>
<link rel='stylesheet' type='text/css' href='/site_media/css/thickbox.css' /> <link href="/site_media/common/jquery_webox/jquery-webox.css" rel="stylesheet" type="text/css"> <script src="/site_media/common/jquery_webox/jquery-webox.js"></script>
<script type="text/javascript">
$(document).ready(function(){ //iframe弹出层调用
$('#outside').click(function(){
$.webox({ height:500,
width:800,
bgvisibel:true,
title:'修改头像',
iframe:'/uploadify?uuid='+$('#uuid').val()+'&rd='+Math.random()
});
}); })
</script> <DIV class="yyh-page grid_9">
<DIV class=widget>
<DIV class=widget-content>
<!-- basic form -->
<FORM id=basic class="yyh-form tabs-rel tabs-info on" method=post
action="/account/userinfo/"> <input type="hidden" id="uuid" name="uuid" value="{{uuid}}" /> <DL class=required>
<DT>
<LABEL for=producer>
账号
</LABEL>
</DT>
<DD>
<INPUT class=inputText style="color: #400080;font - size: 16px;" readonly="true" value="{{username}}">
<SPAN>
<B class=error>
</B>
</SPAN>
<P class=hint>
</P>
</DD>
<DT>
<LABEL for=producer>
联系人真实姓名
</LABEL>
</DT>
<DD>
<INPUT class=inputText name=devName value="{{devName}}">
<SPAN>
<B class=error>
</B>
</SPAN>
<P class=hint>
</P>
</DD>
</DL>
<DL class=required>
<DT>
<LABEL for=phone>
联系电话
</LABEL>
</DT>
<DD>
<INPUT class=inputText name=contactPhone value="{{contactPhone}}">
<SPAN>
<B class=error>
</B>
</SPAN>
<P class=hint>
</P>
</DD>
</DL>
<DL class=required>
<DT>
<LABEL for=address>
联系地址
</LABEL>
</DT>
<DD>
<INPUT class=inputText name=contactAddress value="{{contactAddress}}">
<SPAN>
<B class=error>
</B>
</SPAN>
<P class=hint>
请填写真实的联系地址
</P>
</DD>
</DL>
<DL class=required>
<DT>
<LABEL for=zipcode>
邮政编码
</LABEL>
</DT>
<DD>
<INPUT class="inputText NumberValidate" name=contactZipCode value="{{contactZipCode}}">
<SPAN>
<B class=error>
</B>
</SPAN>
</DD>
</DL> <DL>
<DT>
<LABEL for=headimg>
头像
</LABEL>
</DT>
<DD> <img id="screenshot_img" name="screeshot_img" src="/site_media/images/account_head/femail.jpg" width="120" height="120" /><br><br/> <div id="upload_div" style="display:visible;">
<a class="Button blueButton Button18" href="javascript:void(0);" id="outside"><strong>点我修改</strong></a>
</div> </DD>
</DL> <DL class=submit>
<DT>
</DT>
<DD>
<INPUT class="inputSubmit blue" value=保存 type=button onclick="this.form.submit();
">
</DD>
</DL>
</FORM>
<!-- end of basic form --> </DIV>
</DIV>
</DIV>
{%endblock%}"

b)的代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Django下利用Uploadify组件上传图片</title> <link rel="stylesheet" href="/site_media/jcrop/demos/demo_files/main.css" type="text/css" />
<link rel="stylesheet" href="/site_media/jcrop/demos/demo_files/demos.css" type="text/css" />
<link rel="stylesheet" href="/site_media/jcrop/css/jquery.Jcrop.css" type="text/css" /> <script src="/site_media/jcrop/js/jquery.min.js"></script>
<script src="/site_media/jcrop/js/jquery.Jcrop.js"></script>
<script type="text/javascript">
var img_top_margin,img_left_margin,img_width,img_height;//最后使用的2个变量 jQuery(function($){ // Create variables (in this scope) to hold the API and image size
var jcrop_api,
boundx,
boundy,
topw,
leftw, // Grab some information about the preview pane
$preview = $('#preview-pane'),
$pcnt = $('#preview-pane .preview-container'),
$pimg = $('#preview-pane .preview-container img'), xsize = $pcnt.width(),
ysize = $pcnt.height(); console.log('init',[xsize,ysize]);
$('#target').Jcrop({
onChange: updatePreview,
onSelect: updatePreview,
aspectRatio: xsize / ysize
},function(){
// Use the API to get the real image size
var bounds = this.getBounds();
boundx = bounds[0];
boundy = bounds[1];
// Store the API in the jcrop_api variable
jcrop_api = this; // Move the preview into the jcrop container for css positioning
$preview.appendTo(jcrop_api.ui.holder);
}); function updatePreview(c)
{
if (parseInt(c.w) > 0)
{
var rx = xsize / c.w;
var ry = ysize / c.h;
console.log("new width:"+Math.round(rx * boundx) );
console.log("new height:"+Math.round(ry * boundy) ); console.log("marginTop:"+Math.round(ry * c.y));
console.log("marginLeft:"+Math.round(rx * c.x)); img_top_margin=c.y;
img_left_margin=c.x;
img_width=c.w;
img_height=c.h; $pimg.css({
width: Math.round(rx * boundx) + 'px',
height: Math.round(ry * boundy) + 'px',
marginLeft: '-' + Math.round(rx * c.x) + 'px',
marginTop: '-' + Math.round(ry * c.y) + 'px'
});
}
}; }); </script> <link href="/site_media/uploadify/uploadify.css" type="text/css" rel="stylesheet" />
<script type="text/javascript" src="/site_media/uploadify/swfobject.js"></script>
<script type="text/javascript" src="/site_media/uploadify/jquery.uploadify.v2.1.4.min.js"></script> <script type="text/javascript" charset="utf-8" async defer>
function go() {
alert(2);
} function replace_image(flag,path,uuid) {
console.log("==========replace_image======="); console.log("marginTop:"+img_top_margin);
console.log("marginLeft:"+img_left_margin); console.log("width:"+img_width);
console.log("height:"+img_height);
var params="&marginTop="+img_top_margin+"&marginLeft="+img_left_margin+"&width="+img_width+"&height="+img_height;
$.ajax({
type: "GET",
url: "?replace_flag="+flag+"&savepath="+path+params,
dataType: "json",
success: function (json) {
alert(json.message);
//document.getElementById("btnquery").click();
document.getElementById("echo_href_msg").innerHTML = json.message;
}
})
}
</script> <script type="text/javascript">
$(document).ready(function() { $('#file_upload').uploadify({
'uploader' : '/site_media/uploadify/uploadify.swf',
'script' : '{%url uploadify_script %}',
'cancelImg' : '/site_media/uploadify/cancel.png',
'folder' : '/upload',
'auto' : false,//
'multi': true,//设置可以上传多个文件
'queueSizeLimit':20,//设置可以同时20个文件
'removeCompleted':false,//
'sizeLimit':10240000,//设置上传文件大小单位kb
'fileExt':'*.jpg;*.gif;*.png',//设置上传文件类型为常用图片格式
'fileDesc':'Image Files',
'onInit': function () {},
'onError' : function (event,ID,fileObj,errorObj) {
$('#id_span_msg').html("上传失败,错误码:"+errorObj.type+" "+errorObj.info);
},
'onSelect': function (e, queueId, fileObj) {
$('#id_span_msg').html("");
},
'onAllComplete': function (event, data) {
if(data.filesUploaded>=1){
$('#id_span_msg').html("上传成功!");
}
}
}); });
</script> <style type="text/css"> /* Apply these styles only when #preview-pane has
been placed within the Jcrop widget */
.jcrop-holder #preview-pane {
display: block;
position: absolute;
z-index: 2000;
top: 10px;
right: -280px;
padding: 6px;
border: 1px rgba(0,0,0,.4) solid;
background-color: white; -webkit-border-radius: 6px;
-moz-border-radius: 6px;
border-radius: 6px; -webkit-box-shadow: 1px 1px 5px 2px rgba(0, 0, 0, 0.2);
-moz-box-shadow: 1px 1px 5px 2px rgba(0, 0, 0, 0.2);
box-shadow: 1px 1px 5px 2px rgba(0, 0, 0, 0.2);
} /* The Javascript code will set the aspect ratio of the crop
area based on the size of the thumbnail preview,
specified here */
#preview-pane .preview-container {
width: 180px;
height: 180px;
overflow: hidden;
} </style> </head>
<body>
<h1>请选择图片上传</h1>
<div class="demo-box">
<form action="." method="post" enctype="multipart/form-data">{% csrf_token %} <input type="file" name="Filedata"/>
<input type="submit" value="上传"/> {%if message%}{{message}}{%endif%}
{% ifequal upload_flag 1 %}
<img id="target" src="/site_media/upload/tmp/{{savepath}}"/> <div id="preview-pane">
<div class="preview-container">
<img src="/site_media/upload/tmp/{{savepath}}" class="jcrop-preview" alt="Preview" />
</div>
</div> <br/><br/>
<div id="echo_href_msg" >
<a href="#" onclick="replace_image('1','{{savepath}}');" >你确定要替换原来的图片?</a>
</div>
{%endifequal%}
</form>
</div>
<!--
<p></p>
<h1>Uploadify组件上传方式</h1>
<div class="demo-box">
<input id="file_upload" type="file" name="Filedata">
<div id="file_uploadQueue" class="uploadifyQueue"></div>
<p><a href="javascript:$('#file_upload').uploadifyUpload()">上传图片</a>
<a href="javascript:$('#file_upload').uploadifyClearQueue()">取消上传</a>
</p>
<p><span id="id_span_msg"></span></p>
//-->
</div> </body>
</html>

c)的代码:

from django.conf.urls.defaults import patterns, url

urlpatterns = patterns('xue_wan_le.UploadImage.views',
url(r'^$', 'index', name='uploadify'),
url(r'^index/', 'index',name="uploadify_index"),
url(r'^uploadify_script/', 'uploadify_script',name="uploadify_script"),
)

d)的代码:

#coding=utf-8
from django.http import HttpResponse
from django.template import RequestContext
from django.shortcuts import render_to_response
import os,ImageFile,uuid,shutil
from django.conf import settings
from django.views.decorators.csrf import csrf_exempt
from django.utils import simplejson from xue_wan_le.Common.CookieUtil import CookieUtil def index(request):
ctx=dict() uuid=''
marginTop=0
marginLeft=0
width=0
height=0
if request.GET.get('marginTop'):
marginTop=int(request.GET.get('marginTop'))
if request.GET.get('marginLeft'):
marginLeft=int(request.GET.get('marginLeft'))
if request.GET.get('width'):
width=int(request.GET.get('width'))
if request.GET.get('height'):
height=int(request.GET.get('height'))
if request.GET.get('uuid'):
uuid=request.GET.get('uuid')
print '===uuid:'+request.GET.get('uuid')
request.session['replace_site_icon_uuid'] = uuid#保存UUID if request.GET.get('replace_flag'):
filepath=request.GET.get('savepath')
olduuid=request.session['replace_site_icon_uuid'] print '===filepath:'+filepath
print '===olduuid:'+olduuid
print '====uuid:'+uuid
path=os.path.join(settings.MEDIA_ROOT,settings.SOURCE_IMAGE_TMP)
if filepath and olduuid:
if os.path.isfile(os.path.join(path,filepath)):
#先把新文件,换成旧文件名字
try:
print 'olduuid:'+olduuid
newname=os.path.join(settings.MEDIA_ROOT,settings.SOURCE_IMAGE_TMP,olduuid+'.jpg')
print 'newname:'+newname os.rename(os.path.join(path,filepath),newname)
#覆盖
shutil.move(os.path.join(settings.MEDIA_ROOT,settings.SOURCE_IMAGE_TMP,olduuid+'.jpg'),
os.path.join(settings.MEDIA_ROOT,'urls','sitethumbs',olduuid+'.jpg')) #裁切
try:
from PIL import Image
path=os.path.join(settings.MEDIA_ROOT,'urls','sitethumbs',olduuid+'.jpg')
f = Image.open(path)
xsize,ysize=f.size
print 'image size:'+str(xsize)+":"+str(ysize)
#box变量是一个四元组(左,上,右,下)。
box=(marginLeft,marginTop,marginLeft+width,marginTop+height)
print box
print '----1'
f.crop(box).save(path)
print '----2'
print 'crop image:'+path
except Exception,e:
print e
return HttpResponse(simplejson.dumps({'message':'替换成功,关闭窗口'}))
except Exception,e:
print e
else:
print 'error.==' if request.method=="POST":
file = request.FILES.get("Filedata",None)
(upload_flag,savepath)=_upload(file)
if upload_flag:
ctx["message"]=u"上传成功!"
ctx["upload_flag"]=1
else:
ctx["message"]=u"上传出错!"
ctx["upload_flag"]=0
ctx["savepath"]=savepath return render_to_response("uploadpic/index.html",ctx,RequestContext(request)) @csrf_exempt
def uploadify_script(request):
response=HttpResponse()
response['Content-Type']="text/javascript"
ret="0"
file = request.FILES.get("Filedata",None)
if file:
if _upload(file):
ret="1"
ret="2"
response.write(ret)
return response def _upload(file):
'''图片上传函数'''
if file:
path=os.path.join(settings.MEDIA_ROOT,settings.SOURCE_IMAGE_TMP)
if not os.path.exists(path): #如果目录不存在创建目录
os.makedirs(path) file_name=str(uuid.uuid1())+".jpg"
path_file=os.path.join(path,file_name)
parser = ImageFile.Parser()
for chunk in file.chunks():
parser.feed(chunk)
img = parser.close()
try:
if img.mode != "RGB":
img = img.convert("RGB")
img.save(path_file, 'jpeg',quality=100)
print 'img.save:'+path_file
except Exception,e:
print e
return (False,"")
return (True,file_name)
return (False,"")

index.html和view.py是功能实现的主要部分,如果有疑问可以发评论给我,或者新浪微博私信给我http://weibo.com/changeself

前台利用jcrop做头像选择预览,后台通过django利用Uploadify组件上传图最终使用PIL做图像裁切的更多相关文章

  1. [App Store Connect帮助]四、添加 App 图标、App 预览和屏幕快照(3)上传 App 预览和屏幕快照

    请上传至多三个 App 预览和至多十张屏幕快照.如果您的 App 在不同设备尺寸和本地化内容间都相同,仅提供所要求的最高分辨率的屏幕快照即可. 对于 iPhone,必须提供用于 5.5 英寸设备(iP ...

  2. 利用tornado实现表格文件预览

    项目介绍   本文将介绍笔者的一个项目,主要是利用tornado实现表格文件的预览,能够浏览的表格文件支持CSV以及Excel文件.预览的界面如下:   下面我们将看到这个功能是如何通过tornado ...

  3. 如何利用Python实现Office在线预览

    目前,市场对于Office在线预览功能的需求是很大的.对于我们用户本身来说,下载Office文件后再实现预览是极其不方便的,何况还有一些不能打开的专业文档.压缩文件等.此时,能提供在线预览服务的软件就 ...

  4. javascript 利用FileReader和滤镜上传图片预览

    FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File或 Blob对象指定要读取的文件或数据. 1.FileReader接口的方法 Fi ...

  5. 纯javascript代码实现浏览器图片选择预览、旋转、批量上传

    工作中遇到的业务场景,和同事一起研究了下,主要是为了兼容IE版本 其实就是一些琐碎的知识点在网上搜集下解决方式,然后集成了下,主要有以下点: 1. IE input type=file的图片预览要用I ...

  6. DAY19-上传头像并预览

    一个简单的注册页面: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...

  7. 表单提交学习笔记(三)—利用Request.Files上传图片并预览

    一.html页面如下 <div id="container"> <form id="myForm"> <p class=" ...

  8. django 上传头像并预览 3选1

    注册页面的头像上传 register.html<!DOCTYPE html> <html lang="en"> <head> <meta ...

  9. MUI 单个图片上传预览(拍照+系统相册):先选择->预览->上传提交

    1 html部分 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> < ...

随机推荐

  1. UVA10304---(区间DP)

    第一开始想着枚举根节点,然后记忆化搜索..结果TLE,最后还是看了一眼题解瞬间明白了..唉,还是思维太局限了 由于数据是按照从小到大排列的,可以自然地组成一颗二叉排序树. 设dp[i][j]是区间[i ...

  2. MongoDB安装,打开及增,删,改,查

    MongoDB是目前最流行的NoSQl之一,NoSQL及No Only Sql,之所以这样叫我的理解是它摒弃了传统关系型数据库的字段类型的概念,而是将所有的数据以key-value方式存储,以key索 ...

  3. POJ 3046 Ant Counting DP

    大致题意:给你a个数字,这些数字范围是1到t,每种数字最多100个,求问你这些a个数字进行组合(不包含重复),长度为s到b的集合一共有多少个. 思路:d[i][j]——前i种数字组成长度为j的集合有多 ...

  4. hdu 5248 序列变换(二分枚举)

    Problem Description 给定序列A={A1,A2,...,An}, 要求改变序列A中的某些元素,形成一个严格单调的序列B(严格单调的定义为:Bi<Bi+,≤i<N). 我们 ...

  5. mysql常用操作命令

    本章内容:(引用原文:http://www.cnblogs.com/suoning/p/5769141.html) 查看\创建\使用\删除 数据库 用户管理及授权实战 局域网远程连接法 查看\创建\使 ...

  6. Android学习总结——欢迎页和导航页的实现

    activity_welcome.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayo ...

  7. NoSQL 简介

    NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL". 在现代的计算系统上每天网络上都会产生庞大的数据量. 这些数据有很大一部分是由关系数据库管理系统( ...

  8. HDU 4287 (13.08.17)

    Problem Description We all use cell phone today. And we must be familiar with the intelligent Englis ...

  9. qt 操作excel表格

     自己编写的一个Qt C++类,用于操作excel表格,在Qt中操作excel需在.pro中增加CONFIG+=qaxcontainer配置. 1.打开Excel:objExcel = new QAx ...

  10. SEO 外链 内链 的定义

    外链 外链就是指从别的网站导入到自己网站的链接.导入链接对于网站优化来说是非常重要的一个过程.导入链接的质量(即导入链接所在页面的权重)直接决定了我们的网站在搜索引擎中的权重. 外链是互联网的血液,是 ...