使用python PIL庫(kù)批量對(duì)圖片添加水印的過程詳解
1 簡(jiǎn)單引入
- 平常我們想給某些圖片添加文字水印,方法有很多,也有很多的工具可以方便的進(jìn)行;
- 今天主要是對(duì)
PIL
庫(kù)的應(yīng)用,結(jié)合Python
語言批量對(duì)圖片添加水??; - 這里需要注意的是圖片的格式,不能為JPG或JPEG,因?yàn)檫@兩種格式的圖片不支持透明度設(shè)置。
2 關(guān)于PIL
PIL
是Python
的一個(gè)圖像處理庫(kù),支持多種文件格式;PIL
提供強(qiáng)大的圖像處理和圖形處理能力;- 可完成對(duì)圖像的縮放、裁剪、疊加以及圖像添加線條、圖像和文字等操作。
- 安裝的話,使用以下命令:
pip install Pillow
3 本文涉及的PIL的幾個(gè)類
模塊或類 | 說明 |
---|---|
image模塊 | 用于對(duì)圖像就行處理 |
ImageDraw | 2D圖像對(duì)象 |
ImageFont | 存儲(chǔ)字體 |
ImageEnhance | 圖像增強(qiáng) |
4 實(shí)現(xiàn)原理
本文主要目的是批量對(duì)某個(gè)文件夾下的圖片進(jìn)行添加水印,原理如下:
- 對(duì)水印內(nèi)容設(shè)置;
- 使用
Image
對(duì)象的open()
方法打開原始圖片; - 使用
Image
對(duì)象的new()
方法新建存儲(chǔ)水印圖片對(duì)象; - 使用
Image.Draw.Draw
對(duì)象的text()
繪制水印文字; - 使用
ImageEnhance
中的Brightness
中的enhance()
設(shè)置水印透明度。
5 實(shí)現(xiàn)過程
5.1 原始圖片
- 我們?cè)O(shè)置一個(gè)原始圖片的存儲(chǔ)目錄,比如:
F:\python_study\image\image01
這個(gè)文件夾中存放了多個(gè)png
格式的圖片:
這里的一個(gè)原始圖片為:
5.2 導(dǎo)入相關(guān)模塊
- 導(dǎo)入需要的幾個(gè)
PIL
中的模塊或類:
from PIL import Image, ImageDraw, ImageFont, ImageEnhance import os
5.3 初始化數(shù)據(jù)
- 我們這里預(yù)想的是,通過用戶自己手動(dòng)輸入相關(guān)信息,比如圖片的存儲(chǔ)路徑,需要設(shè)置的水印文字,通過輸入的方式設(shè)置水印的位置,設(shè)置水印的透明度等;
class TestText(): def __init__(self): super(TestText, self).__init__() self.pic_path = input('圖片路徑:') self.pic_text = input('水印文字:') self.p_flag = int(input('水印位置(1:左上角,2:左下角,3:右上角,4:右下角,5:居中):')) self.a = float(input('水印透明度(0—1之間的1位小數(shù)):'))
5.4 水印字體設(shè)置
- 這里我們先看下
ImageFont.truetype
源碼:
def truetype(font=None, size=10, index=0, encoding="", layout_engine=None): """ Load a TrueType or OpenType font from a file or file-like object, and create a font object. This function loads a font object from the given file or file-like object, and creates a font object for a font of the given size. Pillow uses FreeType to open font files. On Windows, be aware that FreeType will keep the file open as long as the FreeTypeFont object exists. Windows limits the number of files that can be open in C at once to 512, so if many fonts are opened simultaneously and that limit is approached, an ``OSError`` may be thrown, reporting that FreeType "cannot open resource". A workaround would be to copy the file(s) into memory, and open that instead. This function requires the _imagingft service. :param font: A filename or file-like object containing a TrueType font. If the file is not found in this filename, the loader may also search in other directories, such as the :file:`fonts/` directory on Windows or :file:`/Library/Fonts/`, :file:`/System/Library/Fonts/` and :file:`~/Library/Fonts/` on macOS. :param size: The requested size, in pixels. :param index: Which font face to load (default is first available face). :param encoding: Which font encoding to use (default is Unicode). Possible encodings include (see the FreeType documentation for more information):
- 它的大意就是從系統(tǒng)中的字體庫(kù)中讀取字體;
- 那我們的系統(tǒng)字體在哪里呢?
- 系統(tǒng)字體在
C:\Windows\Fonts
如下:
- 我們隨便選一個(gè)自己喜歡的字體,復(fù)制下名字即可:
self.font = ImageFont.truetype("cambriab.ttf", size=35)
5.5 打開原始圖片并新建存儲(chǔ)對(duì)象
- 打開原始圖片,并轉(zhuǎn)換為
RGB
:
image = Image.open(img).convert('RGBA')
- 創(chuàng)建繪制對(duì)象:
new_img = Image.new('RGBA', image.size, (255, 255, 255, 0)) image_draw = ImageDraw.Draw(new_img)
5.6 計(jì)算圖片和水印的大小
- 圖片大?。?/li>
w, h = image.size
- 文字大?。?/li>
w1 = self.font.getsize(self.pic_text)[0] # 獲取字體寬度 h1 = self.font.getsize(self.pic_text)[1] # 獲取字體高度
5.7 選擇性設(shè)置水印文字
- 通過
if
語句來實(shí)現(xiàn):
if self.p_flag == 1: # 左上角 location = (0, 0) elif self.p_flag == 2: # 左下角 location = (0, h - h1) elif self.p_flag == 3: # 右上角 location = (w - w1, 0) elif self.p_flag == 4: # 右下角 location = (w - w1, h - h1) elif self.p_flag == 5: # 居中 location = (h/2, h/2)
5.8 繪制文字并設(shè)置透明度
- 繪制文字:
image_draw.text(location, self.pic_text, font=self.font, fill="blue")
- 設(shè)置透明度
transparent = new_img.split()[3] transparent = ImageEnhance.Brightness(transparent).enhance(self.a) new_img.putalpha(transparent) Image.alpha_composite(image, new_img).save(img)
5.9 遍歷獲取圖片文件并調(diào)用繪制方法
text_pic = TestText() try: file_list = os.listdir(text_pic.pic_path) for i in range(0, len(file_list)): filepath = os.path.join(text_pic.pic_path, file_list[i]) if os.path.isfile(filepath): filetype = os.path.splitext(filepath)[1] if filetype == '.png': text_pic.test_text(filepath) else: print("圖片格式有誤,無法添加水印,請(qǐng)使用png格式圖片") print('批量添加水印完成') except: print('輸入的文件路徑有誤,請(qǐng)檢查~~')
6 完整源碼
# -*- coding:utf-8 -*- # 作者:蟲無涯 # 日期:2023/11/21 # 文件名稱:test_text_pic.py # 作用:批量給圖片添加文字水印和圖片水印 # 聯(lián)系:VX(NoamaNelson) # 博客:https://blog.csdn.net/NoamaNelson from PIL import Image, ImageDraw, ImageFont, ImageEnhance import os class TestText(): def __init__(self): super(TestText, self).__init__() self.pic_path = input('圖片路徑:') self.pic_text = input('水印文字:') self.p_flag = int(input('水印位置(1:左上角,2:左下角,3:右上角,4:右下角,5:居中):')) self.a = float(input('水印透明度(0—1之間的1位小數(shù)):')) # 設(shè)置字體 self.font = ImageFont.truetype("cambriab.ttf", size=35) # 文字水印 def test_text(self, img): global location image = Image.open(img).convert('RGBA') new_img = Image.new('RGBA', image.size, (255, 255, 255, 0)) image_draw = ImageDraw.Draw(new_img) w, h = image.size # 圖片大小 w1 = self.font.getsize(self.pic_text)[0] # 字體寬度 h1 = self.font.getsize(self.pic_text)[1] # 字體高度 # 設(shè)置水印文字位置 if self.p_flag == 1: # 左上角 location = (0, 0) elif self.p_flag == 2: # 左下角 location = (0, h - h1) elif self.p_flag == 3: # 右上角 location = (w - w1, 0) elif self.p_flag == 4: # 右下角 location = (w - w1, h - h1) elif self.p_flag == 5: # 居中 location = (h/2, h/2) # 繪制文字 image_draw.text(location, self.pic_text, font=self.font, fill="blue") # 設(shè)置透明度 transparent = new_img.split()[3] transparent = ImageEnhance.Brightness(transparent).enhance(self.a) new_img.putalpha(transparent) Image.alpha_composite(image, new_img).save(img) if __name__ == "__main__": text_pic = TestText() try: file_list = os.listdir(text_pic.pic_path) for i in range(0, len(file_list)): filepath = os.path.join(text_pic.pic_path, file_list[i]) if os.path.isfile(filepath): filetype = os.path.splitext(filepath)[1] if filetype == '.png': text_pic.test_text(filepath) print('批量添加水印完成') except: print('輸入的文件路徑有誤,請(qǐng)檢查~~')
7 顯示效果
- 運(yùn)行過程:
D:\Python37\python.exe F:/python_study/python_project/test_text_pic.py
圖片路徑:F:\python_study\image\image01
水印文字:@蟲無涯
水印位置(1:左上角,2:左下角,3:右上角,4:右下角,5:居中):1
水印透明度(0—1之間的1位小數(shù)):0.5
F:/python_study/python_project/test_text_pic.py:32: DeprecationWarning: getsize is deprecated and will be removed in Pillow 10 (2023-07-01). Use getbbox or getlength instead.
w1 = self.font.getsize(self.pic_text)[0] # 獲取字體寬度
F:/python_study/python_project/test_text_pic.py:33: DeprecationWarning: getsize is deprecated and will be removed in Pillow 10 (2023-07-01). Use getbbox or getlength instead.
h1 = self.font.getsize(self.pic_text)[1] # 獲取字體高度
批量添加水印完成
不同位置的水印效果:
居中效果:
以上就是使用python PIL庫(kù)批量對(duì)圖片添加水印的過程詳解的詳細(xì)內(nèi)容,更多關(guān)于python PIL庫(kù)圖片添加水印的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python?ModuleNotFoundError:?No?module?named?‘xxx‘可能的解決方
本文主要介紹了Python?ModuleNotFoundError:?No?module?named?‘xxx‘可能的解決方案大全,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧Chat?Gpt<BR>2023-07-07使用Python對(duì)網(wǎng)易云歌單數(shù)據(jù)分析及可視化
這篇文章主要介紹了使用Python對(duì)網(wǎng)易云歌單數(shù)據(jù)分析及可視化,本項(xiàng)目以數(shù)據(jù)采集、處理、分析及數(shù)據(jù)可視化為項(xiàng)目流程,需要的朋友可以參考下2023-03-03Python初學(xué)者需要注意的事項(xiàng)小結(jié)(python2與python3)
這篇文章主要介紹了Python初學(xué)者需要注意的事項(xiàng)小結(jié),包括了python2與python3的一些區(qū)別,需要的朋友可以參考下2018-09-09在Python的框架中為MySQL實(shí)現(xiàn)restful接口的教程
這篇文章主要介紹了在Python的框架中為MySQL實(shí)現(xiàn)restful接口的教程,文中的示例基于Flask和Django框架,需要的朋友可以參考下2015-04-04利用Django-environ如何區(qū)分不同環(huán)境
這篇文章主要給大家介紹了關(guān)于利用Django-environ如何區(qū)分不同環(huán)境的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用django具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08Python實(shí)現(xiàn)插入排序和選擇排序的方法
這篇文章主要介紹了Python實(shí)現(xiàn)插入排序和選擇排序的方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-05-05