基于django micro搭建网站实现加水印功能


Posted in Python onMay 22, 2020

用django_micro搭建的,给图片加文字水印的前端+后端功能开发;

大体功能是:输入水印的文字,选择要加水印的图片,最后生成加好水印的图片。

可在一页中显示多个加好水印的图片,且可点击显示或隐藏图片的缩略图。实现效果如下:

基于django micro搭建网站实现加水印功能

基于django micro搭建网站实现加水印功能

代码如下

from django_micro import route, run, configure
from django.http import HttpRequest, HttpResponse
from dominate.document import document
import dominate.tags as dom
from wand.drawing import Drawing   # 加水印用
from wand.image import Image  # 加水印用
import base64  # 图片转字符串用
 
 
configure({'DEBUG':True})
 
# 一些元素的cls
CENTERFRAME = "flex flex-col items-center justify-center bg-teal-200 h-screen"
UPLOAD_FORM_ATTRIS ={
  "class":"flex flex-col justify-center",
  "ic-post-to": "/file",
  "ic-target": "#result_item",
  "ic-replace-target": "true",
  "enctype": "multipart/form-data"
}
CARD1 = "flex flex-col bg-green-400 shadow-xl p-1 rounded-lg w-80 h-auto"
TEXT_INPUT = "shadow border rounded m-1 p-1 text-base text-center font-thin"
CARD2 = "flex flex-col bg-white shadow-xl p-2 rounded-lg w-80 h-80"
DASHED_BOX = "flex flex-col items-center justify-center border-dashed border-2 border-gray-200 h-full"
UPLOAD_ICON = "fas fa-file-upload text-gray-300 font-medium text-6xl"
UPLOAD_BUTTON = "flex justify-center bg-green-400 px-3 py-2 mt-4 text-white rounded shadow"
RESULT_CONTAINER = "flex flex-col bg-white items-center"
RESULT_ITEM = "flex flex-col justify-center bg-white p-2 border-t border-gray-200 w-64"
TOGGLE_TEXT_ATTRIS = {   # 这个常量后来没用
  "ic-action":"slideToggle",
  # "ic-target":"#toggle_img", # 以ID定位,只能选择第一个元素
  "ic-target":"figure"   # 以元素类型定位,会对所有同类元素进行操作
}
 
 
# 为了写head部分的引入方便,写个link_函数;下面script_函数类似
def link_(lk):
  return dom.link(rel="stylesheet",type="text/css",href=lk)
 
def script_(s):
  return dom.script(src=s)
 
def page():
  doc = document()
  with doc.head:
    link_("https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css") # tailwind
    link_("https://extra-uru1z3cxu.now.sh/css/extra.css") # 额外写的扩展库
    link_("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.css") # 为了使用font-awesome的图标
    script_("https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js") # jquery
    script_("http://intercoolerjs.org/release/intercooler-1.2.2.js")  # intercooler
  with doc.body:
    with dom.div(cls=CENTERFRAME) as CenterFrame:
      with dom.form(UPLOAD_FORM_ATTRIS) as UploadForm:
        # 输入水印文字区
        with dom.div(cls=CARD1) as Card1:
          dom.p("Write down your mark here",cls="text-base font-thin text-white" )
          dom.input(cls=TEXT_INPUT,id="wm_text",type="text",name="mark_text",placeholder="your watermark text")
        # 上传图片区
        with dom.div(cls=CARD2) as Card2:
          with dom.div(cls=DASHED_BOX):
            dom.i(cls=UPLOAD_ICON,onclick='''$('#fileupload').click()''')
            dom.p("Find File", id="show_info", cls="text-gray-500 mt-4")
            dom.button("Upload", cls=UPLOAD_BUTTON)
            dom.input(cls="hidden", type="file", id="fileupload",name="ori_img",
                 onchange='''$('#show_info').text(this.value.split("\\\\").pop(-1))''')
 
      # 生成水印图片区
      with dom.div(cls=RESULT_CONTAINER) as ResultContainer:
        dom.span(id="result_item")
 
  return doc.render()
 
 
def item(result_file_path):
  filename = result_file_path.split('/',1)[-1].split('.')[0]
  print('filename:',filename)
  # 处理图片,转成字符串
  with open(result_file_path, "rb") as imageFile:
    img_str = base64.b64encode(imageFile.read())
 
  with dom.div(cls=RESULT_ITEM) as ResultItem:
    with dom.a( {
      "ic-action":"slideToggle",
      "ic-target":f"#{filename}"
    }) as ToggleText:
      dom.p(filename, cls="text-sm font-thin text-center text-gray-800")
    with dom.figure(cls="hidden",id=filename): # id中不能带'.'(点)
      dom.img(title="data src",alt="",
          src = "data:image/jpeg;base64," + str(img_str,'utf-8') ) # 转str时要加'utf-8',否则不能去掉b'
 
  return dom.span(id="result_item").render() + ResultItem.render()
 
 
@route('')
def index(request: HttpRequest):
  return HttpResponse(page())
 
@route('file')
def filehandler(request:HttpRequest):
  ori_img = request.FILES.get('ori_img')
  mark_text = request.POST.get('mark_text') # 得用request.POST,因为form提交是用POST方式
  print('mark_text:',mark_text)
  result_file_path = 'output/Toggle_'+ori_img.name  # 打水印后的文件保存路径
 
  with Image(file=ori_img) as img:
    # 先保存原始图片
    img.save(filename='userupload/' + ori_img.name)
    # 画图,把字画在原图上
    with Drawing() as ctx:
      ctx.font_family = 'Times New Roman, Nimbus Roman No9'
      # ctx.font_size = 50
      ctx.font_size = int(img.height) * 0.1
      ctx.text_kerning = 20 # 字间距
      ctx.fill_color = 'grey'
      # ctx.opacity = 0.9  # 不透明性
      img.annotate(mark_text, ctx, left=int(img.width) * 0.1, baseline=int(img.height) * 0.45)
    img.save(filename=result_file_path)
 
  return HttpResponse(item(result_file_path))
 
app = run()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
跟老齐学Python之折腾一下目录
Oct 24 Python
python中argparse模块用法实例详解
Jun 03 Python
Python PyQt5标准对话框用法示例
Aug 23 Python
Python内建模块struct实例详解
Feb 02 Python
详解tensorflow载入数据的三种方式
Apr 24 Python
python 使用正则表达式按照多个空格分割字符的实例
Dec 20 Python
python飞机大战pygame游戏背景设计详解
Dec 17 Python
使用Django和Postgres进行全文搜索的实例代码
Feb 13 Python
python 伯努利分布详解
Feb 25 Python
Windows下pycharm安装第三方库失败(通用解决方案)
Sep 17 Python
python的数学算法函数及公式用法
Nov 18 Python
python推导式的使用方法实例
Feb 28 Python
基于Tensorflow一维卷积用法详解
May 22 #Python
Python参数传递机制传值和传引用原理详解
May 22 #Python
python filecmp.dircmp实现递归比对两个目录的方法
May 22 #Python
关于keras.layers.Conv1D的kernel_size参数使用介绍
May 22 #Python
Python参数传递对象的引用原理解析
May 22 #Python
Python configparser模块常用方法解析
May 22 #Python
keras中的卷积层&池化层的用法
May 22 #Python
You might like
excellent!――ASCII Art(由目标图象生成ascii)
2007/02/20 PHP
php打印输出棋盘的实现方法
2014/12/23 PHP
ThinkPHP3.2.3实现分页的方法详解
2016/06/03 PHP
如何正确配置Nginx + PHP
2016/07/15 PHP
PHP生成图片验证码功能示例
2017/01/12 PHP
thinkPHP5.0框架API优化后的友好性分析
2017/03/17 PHP
JavaScript高级程序设计 读书笔记之八 Function类及闭包
2012/02/27 Javascript
js解析与序列化json数据(一)json.stringify()的基本用法
2013/02/01 Javascript
Node.js实现简单聊天服务器
2014/06/20 Javascript
jquery实现一个简单的表单验证实例
2016/03/30 Javascript
js实现九宫格的随机颜色跳转
2017/02/19 Javascript
Angular 2父子组件数据传递之@Input和@Output详解(下)
2017/07/05 Javascript
新版vue-cli模板下本地开发环境使用node服务器跨域的方法
2018/04/03 Javascript
微信小程序利用canvas 绘制幸运大转盘功能
2018/07/06 Javascript
Node4-5静态资源服务器实战以及优化压缩文件实例内容
2019/08/29 Javascript
原生js实现密码强度验证功能
2020/03/18 Javascript
如何在Vue.JS中使用图标组件
2020/08/04 Javascript
vant组件中 dialog的确认按钮的回调事件操作
2020/11/04 Javascript
[01:03:27]Optic vs VGJ.S 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/20 DOTA
python如何拆分含有多种分隔符的字符串
2018/03/20 Python
pandas将DataFrame的列变成行索引的方法
2018/04/10 Python
pycharm 批量修改变量名称的方法
2019/08/01 Python
Python 开发工具PyCharm安装教程图文详解(新手必看)
2020/02/28 Python
使用Django xadmin 实现修改时间选择器为不可输入状态
2020/03/30 Python
利用python3筛选excel中特定的行(行值满足某个条件/行值属于某个集合)
2020/09/04 Python
绝对令人的惊叹的CSS3折叠效果(3D效果)整理
2012/12/30 HTML / CSS
联想哥伦比亚网上商城:Lenovo Colombia
2017/01/10 全球购物
日本热销NO.1胶原蛋白冻:Aishitoto爱希特多
2019/06/20 全球购物
Ruby中的保护方法和私有方法与一般面向对象程序设计语言的一样吗
2013/05/01 面试题
生产厂厂长岗位职责
2013/12/25 职场文书
社团文化节策划书
2014/02/01 职场文书
通用自荐信范文
2014/03/14 职场文书
党的群众路线教育实践活动宣传标语口号
2014/06/06 职场文书
安全生产宣传标语
2014/06/06 职场文书
MySQL 自定义变量的概念及特点
2021/05/13 MySQL
vue数据字典取键值项目的字典问题
2022/04/12 Vue.js