目录
一、打开相机
1.html网页
不需要特殊环境,使用input标签 type值为file,可以调用系统默认的照相机、相册、摄像机、录音功能。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HTML5页面如何在手机端浏览器调用相机、相册功能</title>
</head>
<body>
<div>
<input type="file" accept="image/*" capture="camera">
<input type="file" accept="video/*" capture="camcorder">
<input type="file" accept="audio/*" capture="microphone">
</div>
</body>
</html>
2.xadmin后台
创建forms.py,在ImageField的表单字段中设置widget属性
img_front = forms.ImageField(label=u'正面照',widget=forms.ClearableFileInput(attrs={'capture': 'camera','type': 'file','accept':"image/*"}))
二、压缩图片
1.html网页压缩
<script type="text/javascript">
//保存个人资料
$('#jsEditUserBtn').on('click', function(){
var _self = $(this),
$jsEditUserForm = $('#jsEditUserForm')
//输入验证
verify = verifySubmit(
[
{id: '#address', require: true}
]
);
if(!verify){
return;
}
var formobj = document.getElementById("jsEditUserForm");
var dic = new FormData(formobj);
var time1 = new Date().getTime();
dic.append('img_far',dataURLtoFile(document.getElementById('img_far').src,time1+'.png'));
dic.append('img_near',dataURLtoFile(document.getElementById('img_near').src,time1+'.png'));
dic.append('img_consult',dataURLtoFile(document.getElementById('img_consult').src,time1+'.png'));
$.ajax({
type: 'post',
dataType:'json',
url:"/xadmin/supervision/scene/?time1="+time1,
data:dic,
processData: false, // tell jquery not to process the data
contentType: false, // tell jquery not to set contentType
beforeSend:function(XMLHttpRequest){
_self.val("保存中...");
_self.attr('disabled',true);
},
success: function(data) {
if(data.status == "success"){
Dml.fun.showTipsDialog({
title: '保存成功',
h2: '信息上传成功!'
});
setTimeout(function(){window.location.href = window.location.href;},1500);
}
},
complete: function(XMLHttpRequest){
_self.val("保存");
_self.removeAttr("disabled");
}
});
});
function dataURLtoFile(dataurl, filename) { //将base64转换为文件
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type:mime});
}
</script>
<script>
// 对图片进行压缩
function compress(inputid,toimgid) {
let fileObj = document.getElementById(inputid).files[0] //上传文件的对象
let reader = new FileReader()
reader.readAsDataURL(fileObj)
reader.onload = function(e) {
let image = new Image() //新建一个img标签(还没嵌入DOM节点)
image.src = e.target.result
image.onload = function() {
let canvas = document.createElement('canvas'),
context = canvas.getContext('2d'),
imageWidth = image.width / 2, //压缩后图片的大小
imageHeight = image.height / 2,
data = ''
canvas.width = imageWidth
canvas.height = imageHeight
context.drawImage(image, 0, 0, imageWidth, imageHeight)
data = canvas.toDataURL('image/jpeg')
//压缩完成
document.getElementById(toimgid).src = data
}
}
}
</script>
2.xadmin后台
下边是我的model.py
class Img(models.Model):
model = models.ForeignKey(Loopwater,on_delete=models.CASCADE,verbose_name='外键关联')
creattime = models.DateTimeField(verbose_name='创建时间',auto_now_add=True)
updatetime = models.DateTimeField(verbose_name='更新时间',auto_now=datetime.now)
image = models.ImageField(upload_to='Loopwater/img', verbose_name='图片', null=True, blank=True)
class Meta:
verbose_name = u'巡查图片'
verbose_name_plural = verbose_name
下边就是signals.py的完整代码
# -*- coding: utf-8 -*-
# @File : signals.py
# @Date : 2021-11-04
# @Author : admin
#压缩
from PIL import Image
from io import BytesIO
from django.core.files import File
#引入信号
from django.db.models.signals import pre_save,pre_delete,post_init,post_save
from django.dispatch import receiver
# pre_init # model执行构造方法前,触发
# post_init # model执行构造方法后,触发
# pre_save # model执行save对象保存前,触发
# post_save # model执行save对象保存前,触发
# pre_delete # model执行delete对象删除前,触发
# post_delete # model执行delete对象删除前,触发
# m2m_changed # model使用多对多字段操作第三张表前后,触发
# class_prepared # 程序启动时,检测已注册的model类,对每个类,触发
from .models import Img
# pre_save对象save前触发,压缩并保存图片
@receiver(pre_save, sender=Img)
def handle_image_compression(sender, instance, **kwargs):
try:
post_obj = Img.objects.get(pk=instance.pk)
if post_obj.image != instance.image:
instance.image = compress_image(instance.image)
except Img.DoesNotExist:
# the object does not exists, so compress the image
if instance.image:
instance.image = compress_image(instance.image)
# pre_delete对象delete前触发,删除图片
@receiver(pre_delete, sender=Img)
def delete(sender, instance, **kwargs):
# Pass false so FileField doesn't save the model.
instance.image.delete(False)
# 修改时,保存图片并删除旧图
@receiver(post_init, sender=Img)
def file_path(sender, instance, **kwargs):
instance._current_image = instance.image
# post_save对象save后触发
@receiver(post_save, sender=Img)
def delete_old_image(sender, instance, **kwargs):
if hasattr(instance, '_current_image'):
if instance._current_image != instance.image:
instance._current_image.delete(save=False)
# 压缩
def compress_image(image):
# 打开
out = BytesIO()
print(image)
img = Image.open(image)
if img.mode == 'RGBA':
img = img.convert("RGB") # 这个if与save对应(JPEG),当上传png会报错(cannot write mode RGBA as JPEG)
width = img.width
height = img.height
rate = 1.0 # 压缩率
# 根据图像大小设置压缩率
if width >= 2000 or height >= 2000:
rate = 0.2
elif width >= 1000 or height >= 1000:
rate = 0.4
elif width >= 500 or height >= 500:
rate = 1
width = int(width * rate) # 新的宽
height = int(height * rate) # 新的高
print(width)
img = img.resize((width, height), Image.ANTIALIAS)
img.save(out, 'JPEG', quality=70)
compressed = File(out, name=image.name)
img.close()
return compressed
3.制作多图压缩插件
尚未完成
参考链接:
django 使用 PIL 压缩图片_两鬓已不能斑白的专栏-CSDN博客_django 压缩图片
Django 实现前端图片压缩_HeJD的博客-CSDN博客
https://www.jb51.net/article/180037.htm
三、添加水印
1.添加水印
# 字体库
from PIL import ImageFont
#1.图片
img = ''
#2.添加水印
# 指定字体和大小
font = ImageFont.truetype("C:\Windows\Fonts\SIMLI.TTF", 30)
# 水印的内容
text = '唱跳练222222222222222222'
# 获取字宽高
font_w, font_h = font.getsize(text)
# 定义画笔
draw = ImageDraw.Draw(img)
# 添加(坐标,内容,颜色,字体)
draw.text((10, height - font_h), text, fill = 'red', font=font)
# 保存图片
img.show()
2.通过html5获取手机定位
手机端定位获取用户位置信息
参考链接:
html5 通过手机定位获取当前位置并在地图上居中 - lcawen - 博客园
3.通过ip获取地址、经纬度
def ip_address(ip):
"""ip地址查询物理地址"""
ak = "jQCFiGYZLugvmS80qQ0bvYyvOf8Ry5iN"
url = "http://api.map.baidu.com/location/ip?ak=" + ak +"&ip=" + ip +"&coor=bd09ll"
#u'http://api.map.*****.com/location/ip?ak=&ip={ip}&coor=bd09ll'
rsp = requests.get(url, timeout=10).text
content = json.loads(rsp)
# 请求状态 0有数据 1无数据
status = content['status']
if status:
return content['message']
print('位置:'+ content['content']['address_detail']['province'] + js['content']['address_detail']['city'])
print('纬度:'+ content['content']['point']['y'])
print('经度:'+ content['content']['point']['x'])
print('节点:'+ content['address'])
address = content['content']['address']
return address
参考链接:
Python图像处理库PIL的ImageFont模块介绍_icamera0的博客-CSDN博客_imagefont.truetype
Python Django记录用户访问页面及获取客户端IP地址 根据IP查询定位 - 简书(获取ip、获取地址)
python实现ip地址查询经纬度定位 - linyouyi - 博客园(获取经纬度)
四、更改删除
参看第二部分,xadmin后台压缩图片整体代码。简易代码如下:
#修改和删除数据时,删除旧图片,保存新图
from django.db.models.signals import pre_delete,post_save,post_init
from django.dispatch.dispatcher import receiver
#删除时
@receiver(pre_delete, sender=Template)
def delete(sender, instance, **kwargs):
# Pass false so FileField doesn't save the model.
instance.file.delete(False)
#修改时
@receiver(post_init, sender=Template)
def file_path(sender, instance, **kwargs):
instance._current_file = instance.file
@receiver(post_save, sender= Template)
def delete_old_image(sender, instance, **kwargs):
if hasattr(instance, '_current_file'):
if instance._current_file != instance.file.path:
instance._current_file.delete(save=False)
参考链接:在Ddjango文件和图片的删除和修改时,同步更新media的存储文件_黎明总是如期而至-CSDN博客
相关链接:
2.django-stdimage实现上传图片功能并在xadmin后台显示(超详细,每个环节都有实例)
3.在Ddjango文件和图片的删除和修改时,同步更新media的存储文件
4.图片压缩