Python 批量加水印!轻松搞定!

关注+星标,听说他有点东西e681dd82cc46f816a819a0e3a2a007c2.png

全文共2003字,阅读全文需5分钟


大家好,我是小一2ee7985236850a774339ee0e5fd47a2b.png

想必有读者会遇到这种情况:自己辛辛苦苦写的文章被盗,而且对方在文章中既不显示原文链接,也不做任务说明,堂而皇之的自己标记“原创”

碰见这种事情,搁谁都会拍案而起。如果对方有良知的话你私信过去他可能会修改或者删文,可是要是对方不讲武德,那可真的太TM烦人了。

小一刚开始写文章的时候也有遇到过被抄袭,但是对方经不过我站在道德高点上的炮火猛击,后来就默默删文了

今天呢,小一教你们如何预防被抄袭,用 Python 给文章中的图片加水印!

水印应该都不陌生吧,一般像微博图片、微信文章的图片右下角都会有一个作者的 ID,更难一点的会在图片的某个随机部位有一个斜放的作者 ID

比如下面这个图,右下角的是原作者的水印 ID,图片中斜着的是我用 Python 添加的水印 ID

1bb1ec11c59eb0435cdbd594b5d6e6b7.png


ok,下面来看一下如何用 Python 进行水印的添加

用 Python 进行水印的添加总共需要三步

  • 生成一张透明的水印

  • 将水印添加到一张空白图片上生成水印背景

  • 将水印背景粘贴到原图对应的位置上去

一般我们生成水印可以选择两种方式:固定位置的水印和全屏水印

类似微博照片那种一般会在图片的右下角、图片中间等部位添加水印标识,比较简单,也容易被去水印。

全屏水印就像上图中那种,会在很多很多位置生成水印标识,一般会在付费文档中使用,很难被去掉。

对了,说明一下,今天的文章源码绝大多数来源于 github 上的一个开源作者,小一在他的基础上进行了一些改进,使得初学者看起来会更容易理解!!

github 链接会在文末贴出来,小一修改后的源码也会在文末贴出来。

开始之前,我们需要明确以下参数含义,分别是:

dirpath_input = 'pic_bg'            # 图像路径
filepath_output = 'out/'            # 输出水印图像的文件夹,如果没有则在当前目录下主动创建
mark_content = '小一的学习笔记'        # 水印内容,默认是 "小一的学习笔记"。可不设置
mark_color = '#232862'              # 水印颜色,默认是 #232862【灰色】。可不设置
mark_space = 75                     # 水印之间的空隙,默认值为 75。可不设置
mark_angle = 30                     # 水印的角度,默认是 30°。可不设置
mark_size = 35                      # 水印字体的大小,默认是 50。可不设置
mark_opacity = 0.15                 # 水印透明度,默认是 0.05,数值越小越透明。可不设置
mark_quality = 90                   # 图片输出质量,默认是。可不设置

【左右滑动查看更多】

首先,生成一张透明的水印

这一步需要设置好水印的字体和内容,调用 Image 函数创建一张有关字体内容的透明水印

字体越大、内容越多,这个透明水印就越大,道理应该都懂。

代码如下:

# 字体宽度
width = len(mark_content) * mark_size
# 创建水印图片(宽度、高度)
mark = Image.new(mode='RGBA', size=(width, mark_size))

之后添加水印文字,设置水印透明度,裁剪图片的空白部分

水印字体的大小默认是 50。

水印透明度默认是 0.05,数值越小越透明。

代码如下:

# 生成文字
draw_table = ImageDraw.Draw(im=mark)
draw_table.text(xy=(0, 0), text=mark_content, fill=mark_color, font=ImageFont.truetype(TTF_FONT, size=mark_size))
del draw_table
# 裁剪空白
mark = crop_image(mark)
# 透明度
set_opacity(mark, mark_opacity)

字体 35,内容:小一的学习笔记,生成的水印图片是这样的:

392990409f11c3754035314535ee81ad.png


其次,将水印添加到一张空白图片上生成水印背景

调用 Image 函数创建一张背景图片,如果是固定位置水印那只需要创建和原图同样大小的背景图片,如果是全屏水印那需要根据原图的对角线 C 生成一张 C*C 的背景图片

全屏水印一般需要设置倾角,所以最好设置大一点,对角线正好合适

全屏水印代码如下:

# 计算斜边长度
c = int(math.sqrt(im.size[0]*im.size[0] + im.size[1]*im.size[1]))
"""创建满屏的水印"""
# 以斜边长度为宽高创建大图(旋转后大图才足以覆盖原图)
mark2 = Image.new(mode='RGBA', size=(c, c))
y, idx = 0, 0
while y < c:
    x = -int((mark.size[0] + mark_space)*0.5*idx)
    idx = (idx + 1) % 2

    while x < c:
        mark2.paste(mark, (x, y))
        x = x + mark.size[0] + mark_space
        y = y + mark.size[1] + mark_space

# 将大图旋转一定角度
mark2 = mark2.rotate(mark_angle)

特定位置的水印需要设置相应的图片坐标,具体的在代码 get_mark_style 函数可以设置常见的几种水印:水平居中、顶部居中、底部居中、底部靠左、底部靠右

相比在特定位置生成水印代码就简单很多:

# 创建一模一样的原图并添加水印
mark2 = Image.new(mode='RGBA', size=(im.size[0], im.size[1]))
x, y = get_mark_style(im, mark, "")
mark2.paste(mark, (x, y))

生成的水印背景图分别如下:

水印背景都是透明的,为了更清晰的体现底色加了深色背景

5d7aff112d64a7d7b780c689a1244e39.png

【左边为全局水印,右边为水平居中水印】

最后,将水印背景粘贴到原图对应的位置上去

这一步很简单,只需要设置好粘贴的位置,将水印背景粘贴到原图上就行了。

如果是特定位置水印,因为水印背景和原图一样大,位置设成(0,0)即可;全局水印的话需要根据对角线选择位置,示例中的水印根据原图 (0,0) 点需要设置成 (-230,-114),大致就是下图所示

a0a2e01bea9305d6598c2247f2b05d59.png

相应的代码为:

# 在原图上添加大图水印
if im.mode != 'RGBA':
    im = im.convert('RGBA')
# 全局水印设置
im.paste(mark2, (int((im.size[0]-c)/2), int((im.size[1]-c)/2)),  mask=mark2.split()[3])
# 特定位置水印设置
im.paste(mark2, (0, 0), mask=mark2.split()[3])

到此,水印的添加就结束了,最终我们通过全局水印和特征位置水印的水印图分别是:

89b1ec98a7c4d344fed95ca2b3666eab.png

【左边为全局水印,右边为底部居中水印】
写在后面的话

加水印是一种最简单的方式,但是稍微会 P 图的人都会轻松的把你的水印 P 掉,要是你觉得不影响观看体验,可以直接用全屏水印,就算他再不讲武德也很难轻松去掉全屏水印。

提到了去水印,大家有没有什么想法?

本节相关的代码可以在公众号 后台回复【加水印】 获取源码。

感兴趣的同学也可以去 github 上查看 2Dou 作者的源码,链接:https://github.com/2Dou/watermarker

往期文章

77e9c363bc08bb9285f8ed66a97503b4.png

千万级别数据 de 筛选过滤,小一教你一招

我是小一,坚持向暮光所走的人,终将成为耀眼的存在!

期待你的三连我们下节见

改变图片透明度 很好的学习用工码 attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); Bitmap resultImage = new Bitmap(srcImage.Width, srcImage.Height); Graphics g = Graphics.FromImage(resultImage); g.DrawImage(srcImage, new Rectangle(0, 0, srcImage.Width, srcImage.Height), 0, 0, srcImage.Width, srcImage.Height, GraphicsUnit.Pixel, attributes); return resultImage; } #region 不安全代码 需要设置项目允许不安全代码 /// /// 方法二 设置图像透明度,若原图不为32位ARGB格式,则自动转换为32位ARGB输出 /// /// 原图 /// 透明度(0~1之间双精度浮点数) //public static unsafe void SetTransparent(ref Bitmap src, double transparency) //{ // if (transparency 1.0) // throw new ArgumentOutOfRangeException("透明度必须为0~1之间的双精度浮点数"); // BitmapData srcData; // Rectangle rect; // byte* p; // rect = new Rectangle(0, 0, src.Width, src.Height); // src = src.Clone(rect, PixelFormat.Format32bppArgb); // //转换到32位,否则丢失透明度 // srcData = src.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); // //锁定字节数组到内存 // p = (byte*)srcData.Scan0.ToPointer(); // //获取字节数组在内存中地址 // if (src.PixelFormat == PixelFormat.Format32bppArgb) // { // //如果是32位图片,有Alpha通道,以原Alpha通道的值为基准 // p += 3; // //默认修改Alpha通道的值 // for (int i = 0; i < srcData.Stride * srcData.Height; i += 4) // { // *p = (byte)(*p * transparency); // //原Alpha通道值*透明度 // p += 4; // }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值