-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.py
183 lines (150 loc) · 6.94 KB
/
main.py
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
import math
import os
from datetime import datetime
import yaml
from PIL import Image, ImageDraw
from PIL import ImageFont
from PIL.ExifTags import TAGS
import piexif
# 布局,全局配置
FONT_SIZE = 220
BORDER_PIXEL = 60
UP_DOWN_MARGIN = FONT_SIZE + BORDER_PIXEL
LEFT_RIGHT_MARGIN = FONT_SIZE + BORDER_PIXEL
GAP_PIXEL = 100
# 读取配置
with open('config.yaml', 'r',encoding='utf-8') as f:
config = yaml.safe_load(f)
# 读取输入、输出配置
input_dir = config['base']['input_dir']
output_dir = config['base']['output_dir']
if not os.path.exists(output_dir):
os.makedirs(output_dir)
quality = config['base']['quality']
# 读取字体配置
font = ImageFont.truetype(config['base']['font'], FONT_SIZE)
bold_font = ImageFont.truetype(config['base']['bold_font'], FONT_SIZE)
# 读取 logo 配置
logo_enable = config['logo']['enable']
makes = config['logo']['makes']
# 读取 exif 信息,包括相机机型、相机品牌、镜头型号、图片尺寸、镜头焦距、光圈大小、曝光时间、ISO 和拍摄时间
def get_exif(image):
_exif_attrs = {'Model', 'Make', 'ExifImageWidth', 'ExifImageHeight', 'FocalLength', 'FNumber', 'ExposureTime',
'DateTimeOriginal', 'ISOSpeedRatings', 'Orientation','FocalLength','LensModel'}
_exif = {}
info = image._getexif()
exif_dict = piexif.load(img.info['exif']) # 用于写入exif信息
if info:
for attr, value in info.items():
decoded_attr = TAGS.get(attr, attr)
if decoded_attr in _exif_attrs:
_exif[decoded_attr] = value
return _exif,exif_dict
# 修改日期格式
def parse_datetime(datetime_string):
return datetime.strptime(datetime_string, '%Y:%m:%d %H:%M:%S')
# 添加 logo
def append_logo(exif_img, exif):
logo = None
if 'Make' in exif:
make = exif['Make']
for m in makes.values():
if m['id'] in make:
logo = Image.open(m['path'])
print('图片的高度:',logo.height,'图片的宽度:',logo.width)
if logo is not None:
logo_width=math.floor(logo.width*(exif_img.height*0.7/logo.height))
logo_height = math.floor(exif_img.height*0.7)
logo = logo.resize((logo_width, logo_height), Image.Resampling.LANCZOS)
return logo
# 生成元信息图片
def make_exif_image(exif):
font_ratio = .07
all_ratio = .13
original_width = exif['ExifImageWidth']
original_height = exif['ExifImageHeight']
original_ratio = original_width / original_height
if original_ratio > 1:
font_ratio = .07
all_ratio = .1
# 型号
model = exif['Model']
make = exif['Make']
lens_model = exif['LensModel']
model_mask = bold_font.getmask(model)
lens_mask = font.getmask(lens_model)
brand_img = Image.new('RGB',
(max(model_mask.size[0], lens_mask.size[0]),
model_mask.size[1] + lens_mask.size[1] + GAP_PIXEL * 3),
color='white')
brand_draw = ImageDraw.Draw(brand_img)
brand_draw.text((0, 0), model, font=bold_font, fill='black')
brand_draw.text((0, model_mask.size[1] + GAP_PIXEL), lens_model, font=font, fill='gray')
# 参数
focal_length = str(int(exif['FocalLength'])) + 'mm'
f_number = 'F' + str(exif['FNumber'])
exposure_time = str(exif['ExposureTime'].real)
iso = 'ISO' + str(exif['ISOSpeedRatings'])
shot_param = ' '.join((focal_length, f_number, exposure_time, iso))
original_date_time = datetime.strftime(parse_datetime(exif['DateTimeOriginal']), '%Y-%m-%d %H:%M')
shot_param_mask = bold_font.getmask(shot_param)
original_date_time_mask = font.getmask(original_date_time)
shot_param_img = Image.new('RGB',
(max(shot_param_mask.size[0], original_date_time_mask.size[0])+GAP_PIXEL*2,
shot_param_mask.size[1] + original_date_time_mask.size[1] + GAP_PIXEL * 3),
color='white')
shot_param_draw = ImageDraw.Draw(shot_param_img)
shot_param_draw.line((0,GAP_PIXEL, 0,shot_param_mask.size[1] + original_date_time_mask.size[1] + GAP_PIXEL*2), fill='gray', width=30)
shot_param_draw.text((GAP_PIXEL, 0), shot_param, font=bold_font, fill='black')
shot_param_draw.text((GAP_PIXEL, shot_param_mask.size[1] + GAP_PIXEL), original_date_time, font=font, fill='gray')
exif_img = Image.new('RGB', (original_width, math.floor(all_ratio * original_width)), color='white')
left_margin = BORDER_PIXEL
right_margin = BORDER_PIXEL
brand_img = brand_img.resize(
(math.floor(brand_img.width / brand_img.height * math.floor(original_width * font_ratio)),
math.floor(original_width * font_ratio)), Image.Resampling.LANCZOS)
shot_param_img = shot_param_img.resize(
(math.floor(shot_param_img.width / shot_param_img.height * math.floor(original_width * font_ratio)),
math.floor(original_width * font_ratio)), Image.Resampling.LANCZOS)
if logo_enable:
logo = append_logo(exif_img, exif)
exif_img.paste(logo, (exif_img.width - logo.width - GAP_PIXEL//4 - shot_param_img.width - right_margin, math.floor((all_ratio - font_ratio) / 2 * original_width)))
exif_img.paste(brand_img, (left_margin*2, math.floor((all_ratio - font_ratio) / 2 * original_width)))
exif_img.paste(shot_param_img, (exif_img.width - shot_param_img.width - right_margin,
math.floor((all_ratio - font_ratio) / 2 * original_width)))
return exif_img.resize((original_width, math.floor(all_ratio * original_width)), Image.Resampling.LANCZOS)
# 拼接原图片和 exif 图片
def concat_image(img_x, img_y):
img = Image.new('RGB', (img_x.width, img_x.height + img_y.height), color='white')
img.paste(img_x, (0, 0))
img.paste(img_y, (0, img_x.height))
return img
# 读取文件列表
def get_file_list():
file_list = []
for root, dirs, files in os.walk(input_dir):
for file in files:
if 'jpg' in file or 'jpeg' in file or 'JPG' in file or 'JPEG' in file:
file_list.append(file)
return file_list
if __name__ == '__main__':
file_list = get_file_list()
for file in file_list:
# 打开图片
img = Image.open(os.path.join(input_dir, file))
# 生成 exif 图片
exif,exif_dict = get_exif(img)
print(exif)
if 'Orientation' in exif:
if exif['Orientation'] == 3:
img = img.transpose(Image.ROTATE_180)
elif exif['Orientation'] == 6:
img = img.transpose(Image.ROTATE_270)
elif exif['Orientation'] == 8:
img = img.transpose(Image.ROTATE_90)
exif['ExifImageWidth'], exif['ExifImageHeight'] = img.width, img.height
exif_img = make_exif_image(exif)
# 拼接两张图片
cnt_img = concat_image(img, exif_img)
exif_bytes = piexif.dump(exif_dict)
cnt_img.save(os.path.join(output_dir, file), quality=quality,exif=exif_bytes)