null.

python 拼接图像

在我们协会的平台上看的一道题.

附件链接

题目描述:

[medium]
谁把我壁纸切了啊 ?
prpr~
请提交:flag{something}
来源:2019字节跳动网络安全大赛(byteCTF)

附件里有231个小图片. 看这意思是要把它拼成一整张壁纸. PS大佬可以尝试下手动拼接, 欸嘿嘿

对于这种图像处理的任务, 可以使用python的PIL库. 功能似乎很强大, 正在学习中…

我根据p4ssw0rd学长的一道类似题的python代码, A了这道题.

边看代码边分析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# coding=utf-8
import os
from PIL import Image

path = "./all/"
# 获取文件列表
def get_file_list(file_path):
dir_list = os.listdir(file_path) # 未排序
if not dir_list:
return
else:
# os.path.getmtime() 函数是获取文件最后修改时间
# os.path.getctime() 函数是获取文件最后创建时间
dir_list = sorted(
dir_list,
key=lambda x: os.path.getmtime(
os.path.join(file_path,x)
)
)
# 这行代码比较复杂, 逐行分析
# 首先sorted()是一个基本的内置的排序函数, 这里加入了参数key=lambda.
# lambda是一个隐函数. 后面的x代表的是列表dir_list中的某个元素
# x 本身并无实际意义, 仅仅是供表达式使用的一个名字. 类似f(x)中的x
# os.path.join(file_path,x)是将两个参数以路径的格式拼接在一起
# 即会适当的补全'/'.
# 不过因为此处的file_path就是"./all/"
# 所以这段就等效于 (file_path+x)
# os.path.getmtime(os.path.join(file_path,x))) 的意义就是
# 列表中每个元素(代表文件路径)对应的文件的最后修改时间
# 整行代码会使dir_list中的元素按照文件最后修改时间的升序排序.
return dir_list

list_im = get_file_list(path)[:]
print(list_im)
# 小图片一共有231个
# 231 = 3 * 7 * 11
# 由于要拼接的是一个壁纸, 通常宽:高约为2:1
# 所以猜测 宽=21(张), 高=11(张) (猜对了~~)
column = 21
row_num = 11
# 所有小图片的像素的宽和高
width = 35
height = 43
# 将Image对象置于列表中
imgs = [Image.open(path+i) for i in list_im]
# 建立一个Image"容器", 供我们向其中添加小图片
target = Image.new('RGB', (width*column, height*row_num))

for i in range(
len(list_im)
):
# 仅当i = 0, 21, 42, 63...时执行
if i % column == 0:
end = i + column
# enumetate() 将可迭代的遍历的数据的下标和数据组合并返回enumerate对象
# 此对象可使用for迭代遍历
# 例如:
# >>> seasons = ['Spring', 'Summer', 'Fall', 'Winter']
# >>> list(enumerate(seasons))
# [(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
for col, image in enumerate(imgs[i:i+column]):
target.paste(
image,
# 此处第二个参数, 为代表粘贴到的位置的左上角和右下角的坐标
(
width*col, # 左上 x
height*(i//column), # 左上 y
width*(col + 1), # 右下 x
height*(i//column + 1) # 右下 y
)
)
# 在Windows下此函数可直接打开生成的图片并显示
target.show()

啊, 我写的注释竟然比代码行数多了.

over.