Django图片字段——压缩+水印+更改+删除

目录

一、打开相机

1.html网页

2.xadmin后台

二、压缩图片

1.html网页压缩

2.xadmin后台

3.制作多图压缩插件

三、添加水印

1.添加水印

2.通过html5获取手机定位

3.通过ip获取地址、经纬度

四、更改删除


一、打开相机

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获取手机定位

手机端定位获取用户位置信息

手机端定位获取用户位置信息_飞龙在天-CSDN博客

参考链接:

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博客

相关链接:

1.Django通过form和ajax提交表单数据和图片

2.django-stdimage实现上传图片功能并在xadmin后台显示(超详细,每个环节都有实例)

3.在Ddjango文件和图片的删除和修改时,同步更新media的存储文件

4.图片压缩

5.压缩图片并添加水印

6.Django多图上传——通过重写imagefield实现(可后端,xadmin适用)

猜你喜欢

转载自blog.csdn.net/qq_15028721/article/details/112764401