【Python图像处理】Python粘贴PNG透明图片及处理圆角

此处记录研究图像部分替换过程中自己实践的代码段。另外,附上 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 
# 注意text()的坐标是文字的左上角坐标,需要根据实际调整
# 即使传入(0,0),文字的实际左上角并不一定就在0,0处,可能受行高和字体大小控制?未深入研究
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

发布了58 篇原创文章 · 获赞 44 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/qilei2010/article/details/104398436
今日推荐