前台利用jcrop做头像选择预览,后台通过django利用Uploadify组件上传图最终使用PIL做图像裁切
之前一直使用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做图像裁切的更多相关文章
- [App Store Connect帮助]四、添加 App 图标、App 预览和屏幕快照(3)上传 App 预览和屏幕快照
请上传至多三个 App 预览和至多十张屏幕快照.如果您的 App 在不同设备尺寸和本地化内容间都相同,仅提供所要求的最高分辨率的屏幕快照即可. 对于 iPhone,必须提供用于 5.5 英寸设备(iP ...
- 利用tornado实现表格文件预览
项目介绍 本文将介绍笔者的一个项目,主要是利用tornado实现表格文件的预览,能够浏览的表格文件支持CSV以及Excel文件.预览的界面如下: 下面我们将看到这个功能是如何通过tornado ...
- 如何利用Python实现Office在线预览
目前,市场对于Office在线预览功能的需求是很大的.对于我们用户本身来说,下载Office文件后再实现预览是极其不方便的,何况还有一些不能打开的专业文档.压缩文件等.此时,能提供在线预览服务的软件就 ...
- javascript 利用FileReader和滤镜上传图片预览
FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File或 Blob对象指定要读取的文件或数据. 1.FileReader接口的方法 Fi ...
- 纯javascript代码实现浏览器图片选择预览、旋转、批量上传
工作中遇到的业务场景,和同事一起研究了下,主要是为了兼容IE版本 其实就是一些琐碎的知识点在网上搜集下解决方式,然后集成了下,主要有以下点: 1. IE input type=file的图片预览要用I ...
- DAY19-上传头像并预览
一个简单的注册页面: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...
- 表单提交学习笔记(三)—利用Request.Files上传图片并预览
一.html页面如下 <div id="container"> <form id="myForm"> <p class=" ...
- django 上传头像并预览 3选1
注册页面的头像上传 register.html<!DOCTYPE html> <html lang="en"> <head> <meta ...
- MUI 单个图片上传预览(拍照+系统相册):先选择->预览->上传提交
1 html部分 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> < ...
随机推荐
- 转:PHP分页技术的代码和示例
本文来自:10 Helpful PHP Pagination Scripts For Web Developers 分页是目前在显示大量结果时所采用的最好的方式.有了下面这些代码的帮助,开发人员可以在 ...
- ACM1174_爆头解题思路_空间三维坐标求点到直线的距离
/* 爆头 Description gameboy是一个CS高手,他最喜欢的就是扮演警察, 手持M4爆土匪的头.也许这里有人没玩过CS,有必 要介绍一下“爆头”这个术语:所谓爆头,就是子 弹直接命中对 ...
- linux下部署svn服务器
系统Linux debian 2.6.32-5-686 先安装svn工具:apt-get install subversion,耐心等待安装完成.安装完成后svn客户端.服务器都有了. 接者建立svn ...
- ajax的封装
ajax是前端工程中与后台进行数据交互的一门重要技术,通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新.jquer ...
- IOS消息推送情况总结
App没有启动的时候,接受到了消息通知.这个时候操作系统会按默认方式来展示一个alert,在App Icon上标记一个数字 .当程序处于关闭状态收到推送消息时,点击图标或消息栏会调用 - (BOO ...
- 打印log 保存log
using UnityEngine; using System.Collections; using System.IO; using System; using System.Text; names ...
- Android窗口管理服务WindowManagerService切换Activity窗口(App Transition)的过程分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8596449 在Android系统中,同一时刻只 ...
- System.AccessViolationException: 尝试读取或写入受保护的内存 解决办法
netsh winsock reset --运行此命令解决 错误描述: 之前装的vs2010后 再又安装了vs2013 ,运行之前的vs2010项目 就出现以上错误 错误应用程序名称: w3wp. ...
- ibatisnet框架使用说明
ibatis配置文件主要包括三个 sqlmap.config,providers.config,database.config,注意所有文件生成操作都为嵌入的资源.其中database.config主 ...
- System.Threading.Timer的使用技巧
转自:http://www.360doc.com/content/11/0812/11/1039473_139824496.shtml# System.Threading.Timer timer = ...