我的网站搭建(第37天) 上传图片加水印

  • 发布时间:2016年12月12日 15:30
  • 作者:杨仕航
* 该文是基于Python2.7开发的,最新Python3.x和Django2.x视频教程可以前往 >> Django2.0视频教程

这几天使用django-ueditor的时候,总想着能否实现上传的图片自动加水印。

为了能够更加保护我的知识产权,有必要给图片自动加水印。


Python2.7,3x对图片操作需要安装PIL。可用pip命令行安装:

pip install pillow

若你安装不了,就升级pip

python -m pip install --upgrade pip

安装完成之后,测试看看下面模块是否能够正常加载

from PIL import Image

可以正常加载,就写个测试文件,代码如下:

#coding:utf-8
from PIL import Image, ImageDraw, ImageFont

#打开当前文件夹的1.png文件
im = Image.open("1.png").convert('RGBA')

#创建文本图层
txt = Image.new('RGBA', im.size, (0,0,0,0))
draw = ImageDraw.Draw(txt)

mark = u'杨仕航的博客\nhttp://yshblog.com'
point = (txt.size[0]-155, txt.size[1]-45)  #写入位置
draw.text(point, mark, fill=(255,255,255,255))

#低版本PIL没有这个alpha_composite
#out = Image.alpha_composite(im, txt)
out = Image.composite(txt, im, txt)
out.save('3.png') #保存文件
out.close()

一开始写入的水印只是网址,可以正常写入。但把水印加入中文之后,就出错。

20161212/20161212145444501.png


不管怎么修改字符串的编码都不行。后来发现应该加载中文字体才行。

从系统复制一份字体,放到测试脚本的目录中。我复制了微软雅黑字体。名字为msyhbd.ttf,代码修改如下:

#coding:utf-8
from PIL import Image, ImageDraw, ImageFont

im = Image.open("1.png").convert('RGBA')
txt=Image.new('RGBA', im.size, (0,0,0,0))

draw = ImageDraw.Draw(txt)
mark = u'杨仕航的博客\nhttp://yshblog.com'
fnt = ImageFont.truetype('msyhbd.ttf', 15) #要加中文字体才能识别中文
point = (txt.size[0]-155, txt.size[1]-45)  #位置
draw.text(point, mark, font=fnt, fill=(255,255,255,255))

out=Image.alpha_composite(im, txt)
out.save('3.png')
out.close()


测试代码可以正常运行之后,就考虑集成到我的网站中。

我使用上传图片的地方是django-ueditor富文本框。该组件可以在我的Github中下载:https://github.com/HaddyYang/django-ueditor (Github我已经更新加水印功能了,但默认没有开启)


当然,你可以借鉴一下,运用到你的网站中。

打开django-ueditor中的ueconfig.json文件,该文件是服务器配置文件。

该文件是json数据,在其末端添加如下设置项:

"openWaterMark": true,
"waterMarkText": "杨仕航的博客\nhttp://yshblog.com",
"waterMarkFont": "msyhbd.ttf",
"waterMarkSize": 15,
"waterMarkBottom": 45,
"waterMarkRight": 155

各个参数意义如下:

"openWaterMark": 是否开启加水印功能
"waterMarkText": 水印内容
"waterMarkFont": 字体名称
"waterMarkSize": 字体大小
"waterMarkBottom": 下边距
"waterMarkRight": 右边距


然后,打开controller.py文件,添加如下方法:

#加水印
def add_watermark(savePath):
    try:
        #判断是否是图片文件
        if not os.path.splitext(savePath)[-1].lower() in ['.jpg', '.jpge', '.png', '.bmp']:
            return

        #获取配置
        config = getConfigContent()
        is_mark = config.get('openWaterMark', False) #是否开启加水印功能
        watermark = config.get('waterMarkText', '')  #水印内容
        font = config.get('waterMarkFont', 'msyhbd.ttf') #字体
        size = config.get('waterMarkSize', 15)		 #字体大小
        bottom = config.get('waterMarkBottom', 45)	 #下边距
        right = config.get('waterMarkRight', 155)	 #右边距

        #判断是否开启了加水印功能
        if not is_mark:
            return

        #python2.7 pillow
        from PIL import Image, ImageDraw, ImageFont

        #打开图片
        im = Image.open(savePath).convert('RGBA')
        
        #透明的图层,用于写文本
        text_layer = Image.new('RGBA', im.size, (0,0,0,0))
        draw = ImageDraw.Draw(text_layer)

        #加载字体,设置大小
        font_path = os.path.join(os.path.dirname(__file__), font)
        fnt = ImageFont.truetype(font_path, 15) #要加中文字体才能识别中文

        point = (text_layer.size[0]-right, text_layer.size[1]-bottom)  #位置
        draw.text(point, watermark, font=fnt, fill=(255,255,255,255))
        
        #低版本PIL没有这个alpha_composite
        #out=Image.alpha_composite(im, text_layer)
        out = Image.composite(text_layer, im, text_layer)
        
        out.save(savePath)
        out.close()
    except Exception as e:
        print('[error]', e.message)

添加完成之后,同样在这个文件中,找到上传文件方法uploadFile,在里面加入加水印的函数。如下图位置:

20161212/20161212152934378.png

保存代码,重启服务。上传图片测试效果。

测试发现回车符的问题,我在本地测试是可以识别\n为回车符,而上传的服务器却不识别。

建议尽量不用多行文本,用一行文本,而且内容尽可能短。

上一篇:C#的序列化和反序列化

下一篇:我的笔记本第二次改造:更换主板和外壳

评论列表

智慧如你,不想发表一下意见吗?

新的评论

清空