无聊在Github上看见python的趣味练习题,自己试着做了做
https://github.com/Yixiaohan/show-me-the-code
第 0000 题: 将你的 QQ 头像(或者微博头像)右上角加上红色的数字,类似于微信未读信息数量那种提示效果。
这个题目主要是练习对Pillow模块的使用,豆子之前也没用过,今天试了试发现很强大也很方便
首先安装
1
2
3
4
5
6
7
8
9
10
11
12
13
|
C:\Users\yuan.li>pip
install
pillow
Collecting pillow
Downloading Pillow-4.3.0-cp36-cp36m-win32.whl (1.4MB)
100% |████████████████████████████████| 1.4MB 654kB
/s
Collecting olefile (from pillow)
Downloading olefile-0.44.zip (74kB)
100% |████████████████████████████████| 81kB 2.8MB
/s
Building wheels
for
collected packages: olefile
Running setup.py bdist_wheel
for
olefile ...
done
Stored
in
directory: C:\Users\yuan.li\AppData\Local\pip\Cache\wheels\20\58\49\cc7bd00345397059149a10b0259ef38b867935ea2ecff99a9b
Successfully built olefile
Installing collected packages: olefile, pillow
Successfully installed olefile-0.44 pillow-4.3.0
|
这个模块可以帮助我们读取和修改图片。为了完成上面的任务,我们需要了解一些基本的模块使用
https://pillow.readthedocs.io/en/4.3.x/index.html
首先看看Image 模块,他的主要作用就是读取一个图片,然后可以打开或者另存为其他格式。
例1
1
2
3
4
5
|
from
PIL
import
Image
im
=
Image.
open
(
'c:\\temp\\download.png'
,
'r'
)
print
(im.
format
, im.size, im.mode)
#把图片保存为临时文件打开
im.show()
|
例2, 再例1 的基础上做些修改,这次我们把打开的文件另存为jpg的格式
1
2
3
4
5
6
7
8
9
10
11
12
13
|
import
os, sys
from
PIL
import
Image
#对每一个参数
for
infile
in
sys.argv[
1
:]:
f, e
=
os.path.splitext(infile)
outfile
=
f
+
".jpg"
print
(infile,outfile)
if
infile !
=
outfile:
try
:
#需要先转换格式为RGB,否则PNG格式无法直接转换为JPEG
Image.
open
(infile).convert(
'RGB'
).save(outfile)
except
IOError:
print
(
"cannot convert"
, infile)
|
例3, 打开图片的方式和打开普通文件的方式一样,也可以用with as的格式
1
2
3
4
5
6
7
8
|
import
sys
from
PIL
import
Image
for
infile
in
sys.argv[
1
:]:
try
:
with Image.
open
(infile) as im:
print
(infile, im.
format
,
"%dx%d"
%
im.size, im.mode)
except
IOError:
pass
|
例4,我们还可以对图片进行剪切
1
2
3
4
5
6
7
8
|
im
=
Image.
open
(
'c:\\temp\d1.png'
)
box
=
(
50
,
50
,
100
,
100
)
region
=
im.crop(box)
region.show()
region.transpose(Image.ROTATE_180)
region.show()
im.paste(region,box)
im.show()
|
第二个很重要的模块是ImageDraw模块,这个可以让我们对图片和文字进行创建和二次加工
例5,打开一个图片,在上面画线
1
2
3
4
5
6
7
8
9
10
11
|
from
PIL
import
Image, ImageDraw
import
sys
im
=
Image.
open
(
"c:\\temp\\d1.jpg"
)
print
(im.size)
draw
=
ImageDraw.Draw(im)
#元组相加等于一个合并的元组,这里设置划线的起始坐标和重点坐标, 注意x坐标是向下跑的 fill里面设置RGBA的值
draw.line(((
0
,
0
)
+
im.size), fill
=
(
340
,
83
,
45
),width
=
10
)
draw.line((
0
, im.size[
1
], im.size[
0
],
0
), fill
=
128
)
del
draw
im.show()
im.save(
"c:\\temp\\d10.png"
)
|
例6. 在图片上写字 (题目要求)注意我们这里还调用了ImageFont 模块, 他的作用就是处理位图字体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
from
PIL
import
Image, ImageDraw, ImageFont
# 首先打开一图片,转换为RGBA方便保存和修改
base
=
Image.
open
(
'c:/temp/d1.png'
).convert(
'RGBA'
)
# 这里创建了一个同样大小的空白文件
txt
=
Image.new(
'RGBA'
, base.size, (
255
,
255
,
255
,
0
))
# 获取字体类型,大小
fnt
=
ImageFont.truetype(
'c:/windows/fonts/arial.ttf'
,
40
)
# 准备修改这个图片
d
=
ImageDraw.Draw(txt)
# 指定坐标写字,颜色用RGBA来显示
d.text((
10
,
10
),
"Hello"
, font
=
fnt, fill
=
(
340
,
83
,
45
,
255
))
# 指定坐标写字,颜色用RGBA来显示
d.text((
100
,
60
),
"World"
, font
=
fnt, fill
=
(
255
,
255
,
255
,
255
))
#alpha通道组合2个图片,要求图片大小一致,都使用了RGBA
out
=
Image.alpha_composite(base, txt)
out.show()
|
例6里面我们使用了一个函数alpha_composite,他的意思是 alpha通道混合图像
注意RGBA的A就是指Alpha通道,一般理解为透明度的设置
下面是如何根据Alpha通道数据进行图像混合的算法:
事实上,我们把需要组合的颜色计算出不含Alpha分量的原始RGB分量然后相加便可。如:两幅图像分别为A和B,由这两幅图像组合而成的图像称为C,则可用如下四元组表示图A和B,三元组表示图像C:
A:(Ra,Ga,Ba,Alphaa)
B:(Rb,Gb,Bb,Alphab)
C:(Rc,Gc,Bc)
根据上述算法,则:
Rc=Ra*Alphaa+Rb*Alphab
Gc=Ga*Alphaa+Gb*Alphab
Bc=Ba*Alphaa+Bb*Alphab
这就是两图像混合后的三原色分量。如果有多幅图像需要混合,则按照以上方法两幅两幅地进行混合。