【Python圖像處理】Python粘貼PNG透明圖片及處理圓角

最近研究用Python替換微信聊天截圖的頭像,和朋友圈截圖的頭像及暱稱。功能已經實現,此處記錄研究過程中的代碼段。另外,附上 PIL 庫官方文檔的閱讀技巧。

 

Python處理圖片需要另外安裝 PIL (Python Image Library)庫,即 pillow,請自行百度安裝。以下代碼爲 Python 3.7 代碼。

 

1. 字符串格式化輸出

# 依次打開 1.jpg 到 10.jpg

from PIL import Image, ImageDraw, ImageFont

for i in range(10)
    no = i+1
    path = 'C:/code/py/imgOpe/img/{}.jpg'.format(no))
    img = Image.oepn(path)

2. 圖片的打開與保存

from PIL import Image, ImageDraw, ImageFont

# JPG圖片
flagfile = 'flag.jpg'
flag = Image.open(flagfile)

output = 'flag2.jpg'
flag.save(output, 'JPEG', quality = 100)


# PNG圖片
flagfile = 'flag.png'
flag = Image.open(flagfile).convert('RGBA')

output = 'flag2.png'
flag.save(output, 'PNG', quality = 100)

# PNG圖片需轉換爲 RGBA 模式,否則透明效果丟失

2. 粘貼JPG/透明PNG/圖層疊加


from PIL import Image, ImageDraw, ImageFont

###########################################

# 在紅旗 flag 上粘貼個星星star(JPG格式)
starfile = 'star.jpg'
flagfile = 'flag.jpg'

# 紅旗上預留給星星的位置
# 左上角x,y,右下角x,y
box = (100,100,200,200)

star = Image.open(starfile)
flag = Image.open(flagfile)

# 粘貼操作,可理解爲往 box 中放東西
flag.paste(icon, box)

# 保存結果
output = 'star-flag.jpg'
flag.save(output, 'JPEG', quality = 100)

#############################################

# 在紅旗 flag 上粘貼個鏤空的星星star(PNG格式)

starfile = 'star.png'
flagfile = 'flag.jpg'

# 紅旗上預留給星星的位置
# 左上角x,y,右下角x,y
box = (100,100,200,200)

star = Image.open(starfile).convert('RGBA')
flag = Image.open(flagfile)

# 粘貼操作,可理解爲往 box 中放東西
# 注意這裏 paste 函數的第3個參數,是alpha通道
# 傳入含有alphat通道的圖片,會自動採用該圖片的alpha通道
# 簡單說,就是PNG透明會生效。具體看文檔
flag.paste(star, box, star)

# 保存結果
output = 'star-flag.jpg'
flag.save(output, 'JPEG', quality = 100)

3. 圖片上寫字

# 圖片上寫字/朋友圈截圖P個暱稱

from PIL import Image, ImageDraw, ImageFont

nickname = '你好,世界'
file = 'pyq.jpg'
pyq = Image.open(file)

# 字體
# 例子中是 我電腦內的蘋方字體,自己測試可改成黑體 simhei.ttf 
font = ImageFont.truetype('C:/windows/fonts/PingFang Bold.ttf', 45)
fillColor = "#586b95"   #微信朋友圈暱稱顏色
draw = ImageDraw.Draw(pyq)
draw.text((165,253),text, font=font, fill=fillColor)

output = 'pyq-nick.jpg'
flag.save(output, 'JPEG', quality = 100)

4. 將圖片改成圓角矩形

此處代碼來自 pyget.cn ,經我測試通過。但實際效果和Photoshop做出的圓角的細節鋸齒並不一致,同樣的高度、寬度、圓角半徑情況下。此處我上傳了每步的輸出圖片,有個直觀的理解。

# 使用 PIL 將圖象處理爲圓角矩形
# Success

from PIL import Image, ImageDraw

radii=10
img = Image.open('flag.jpg')	

# 矩形圖像轉爲圓角矩形
def circle_corner(img, radii):
	# 畫圓(用於分離4個角)
	circle = Image.new('L', (radii * 2, radii * 2), 0)  # 創建黑色方形
	# circle.save('1.jpg','JPEG',qulity=100)
	draw = ImageDraw.Draw(circle)
	draw.ellipse((0, 0, radii * 2, radii * 2), fill=255)  # 黑色方形內切白色圓形
	# circle.save('2.jpg','JPEG',qulity=100)

	# 原圖轉爲帶有alpha通道(表示透明程度)
	img = img.convert("RGBA")
	w, h = img.size

	# 畫4個角(將整圓分離爲4個部分)
	alpha = Image.new('L', img.size, 255)	#與img同大小的白色矩形,L 表示黑白圖
	# alpha.save('3.jpg','JPEG',qulity=100)
	alpha.paste(circle.crop((0, 0, radii, radii)), (0, 0))  # 左上角
	alpha.paste(circle.crop((radii, 0, radii * 2, radii)), (w - radii, 0))  # 右上角
	alpha.paste(circle.crop((radii, radii, radii * 2, radii * 2)), (w - radii, h - radii))  # 右下角
	alpha.paste(circle.crop((0, radii, radii, radii * 2)), (0, h - radii))  # 左下角
	# alpha.save('4.jpg','JPEG',qulity=100)

	img.putalpha(alpha)		# 白色區域透明可見,黑色區域不可見
	img.save('5.png','PNG',qulity=100)

	return img

img = circle_corner(img, radii)
img.save('result.png', 'png', quality = 100)

crop函數用來截圖圖像,四個參數分別代表 左、上、右、下座標。官方說明


putalpha函數用來,將當前圖像疊加透明圖層,用PS術語就是剪切蒙版。

官方說明:

Image.putalpha(alpha)

Adds or replaces the alpha layer in this image. If the image does not have an alpha layer, it’s converted to “LA” or “RGBA”. The new layer must be either “L” or “1”.

Parameters: alpha – The new alpha layer. This can either be an “L” or “1” image having the same size as this image, or an integer or other color value.

個人理解爲:

給當前圖片,增加或者替換alpha圖層。如果當前圖片沒有alpha圖層,當前圖片會被轉換爲 LA 或者 RGBA 模式。新圖層必須是 L模式 或者 1模式。

參數: alpha - 新的alpha圖層。它可以是一個和源圖片相同大小的 L模式 或者 1模式的圖片,也可以是一個整數,或者其它的顏色值。

轉換圓角代碼中的 putalpha()函數的參數 alpha 圖片,即爲L模式,一個灰度圖。

putalpha方法的詳細說明見官方文檔: https://pillow.readthedocs.io 。 

問題:爲什麼原圖片,疊加一個 白底黑角 的圖片,就變成了圓角呢?

回單:白底黑角,即說明白色區域每個像素都是 255,黑色區域每個像素都是 0。原圖片是JPG格式,沒有alpha透明度通道(圖層),每個像素佔用24位,其中RGB各佔8位。putalpha()函數把白底黑角的圖片,作爲透明度通道(圖層),強加給了原圖片,作爲原圖片的透明度通道(圖層),可以看到原圖片也由JPG變成了PNG。原圖片由RGB模式變成了RGBA模式,每個像素現在佔用32位,除了RGB各8位,透明度也佔用8位。而四個角爲什麼不見了,就是因爲四個角的變透明瞭。

因此,putalpha可簡單理解爲增加個透明度,參數alpha灰度圖或者黑白圖就表示透明程度。越黑越透明。

5. 關於 Python PIL庫中圖片模式的說明

RGB是紅綠藍三色,RGBA其中A即代表alpha,可簡單理解爲透明度。Python Pillow庫中,圖片有幾個模式,我只寫出常用的,具體的全部模式看官方文檔Modes說明

1模式:二值圖像,非即白,但它用1個字節(8個bit)來表示,0表示黑,255表示白。

L模式:灰色圖像,除了黑和白,還有不同級別的灰色,每個像素用8個bit表示。(博主注:從0到255中間每一個數字代表一個灰色)

P模式:8位彩色,它的每個像素用8個bit表示,其對應的彩色值是按照調色板查詢出來的。(博主注:圖像表示有一種比較怪異的方式:通過自定義調色板(類似映射表),把圖片像查字典一樣從調色板上查找對應的顏色值,來存儲和顯示圖片。這種方式比較高級,不常用)

RGB模式:3*8位彩色,真彩色。(博主注:最常用的模式,一般使用Image.open()打開後的圖片均是此模式)

RGBA模式:4*8位彩色,帶有透明度的真彩色。(博主注:帶有透明效果的PNG圖片即爲此模式,但需要使用image.convert('RGBA')顯式的轉換爲RGBA模式。32個bit中,前24個bit各表示紅、綠、藍,它們三個顏色各佔8個bit,最後8個bit表示透明度,也就說透明度也有256個級別,如全透明、半透明、不透明)。

 

其它還有CMYK,YCBCr,LAB,HSV,I,F及特色模式LA,PA等,見官方文檔

6. 圓角代碼的結果圖

每個步驟結果如下:

1.jpg
1.jpg(10*10方形黑框)
1.jpg
2.jpg(黑框內切白色圓形)
3.jpg
3.jpg(與flag.jpg同大小的白色圖片)
4.jpg
4.jpg 四個邊角爲黑色
5.jpg
5.jpg 四個角變成圓角

 

另附: PIL 庫官方文檔的閱讀技巧

PIL(即 pillow庫)官方文檔在此

下圖中,

紅框內:可理解爲靜態方法,用法是 Image.blend(),即 靜態類名.方法名();

綠框內:可理解爲實例方法,用法是 myimg.convert(),即 實例對象名.方法名()。

這樣方便我們查找指定的方法。比如將圖片處理成圓角矩形的代碼中,最關鍵的一個函數 putalpha,就要從綠色框裏面查找,當然你可以在瀏覽器內全局 Ctrl + F 搜索 putalpha ,會更快。

 

另外:
阿里雲現在居然有云服務器89元/年,可以裝Python、裝JDK的那種服務器,完全是Python練手必備啊!
https://www.aliyun.com/minisite/goods?userCode=f3xmzovo&share_source=copy_link

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章