-
Notifications
You must be signed in to change notification settings - Fork 0
/
export_images_from_layers.py
139 lines (107 loc) · 4.64 KB
/
export_images_from_layers.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
"""
Before calling this, manually merge 'jelen_bez_pozadi' into the 'srnka_bez_pozadi' layer.
This is to make it so that each object has exactly one image for pairing purposes.
"""
import json
from pathlib import Path
import PIL
from psd_tools import PSDImage
from tqdm import tqdm
IMAGE_TO_AUDIO_NAME = {
'kyticky': 'kviti',
'ptacek': 'sykorka',
'prarodice': 'pejskari',
}
def get_all_layers(root):
for layer in root:
if layer.kind == 'smartobject' or layer.kind == 'pixel':
layer.name = rename_layer(layer.name)
print(f'Layer: {layer.name}')
layers[layer.name] = layer
elif layer.kind == 'group':
print(f'Group: {layer.name}')
get_all_layers(layer)
def rename_layer(name):
name = name.split('_')[0]
if name in IMAGE_TO_AUDIO_NAME:
name = IMAGE_TO_AUDIO_NAME[name]
return name
def to_percent(ratio):
return f'{ratio * 100:.1f}'
def export_layers(background_layer, path: Path, target_width=0, target_height=0):
"""
Exports each layer as an image, and export a json with all layer metadata:
- name
- page: single page, calculated using the layer parent and its relative positions
- bounding box: [x1, y1, x2, y2], where [x1, y1] is the top-left corner, [x2, y2] is the bottom right corner
"""
canvas_width, canvas_height = background_layer.size
page_width = canvas_width // 2
scale_down_factor = 0
if target_width:
scale_down_factor = canvas_width / target_width
if target_height:
scale_down_factor = max(scale_down_factor, canvas_height / target_height)
if scale_down_factor:
print(f'Will scale down by a factor of {scale_down_factor:.2f}, {1 / scale_down_factor:.2f} magnification')
print(
f'Resulting background dimensions:'
f' {round(canvas_width / scale_down_factor)}'
f'x{round(canvas_height / scale_down_factor)}'
)
layer_dict = {}
for layer in tqdm(layers.values()):
page = None
if layer.parent and layer.parent.kind == 'group':
pages = layer.parent.name.split()[1].split('-')
if len(pages) == 1:
page = int(pages[0])
elif len(pages) == 2:
if layer.offset[0] > page_width:
page = int(pages[1])
else:
page = int(pages[0])
else:
raise ValueError(f'Layer {layer} has invalid group page name: {layer.parent.name}')
left, top = layer.offset
if left > page_width:
left -= page_width
layer_image = layer.topil()
if scale_down_factor:
layer_image = layer_image.resize([
round(layer_image.width / scale_down_factor), round(layer_image.height / scale_down_factor)
], PIL.Image.ANTIALIAS)
# Background isn't export as an image object...
if layer.name != 'pozadi':
layer_dict[layer.name] = {
'page': page,
'top': to_percent(top / canvas_height),
'left': to_percent(left / page_width),
'width': to_percent(layer.width / page_width),
}
layer_image.save(path / 'images' / f'{layer.name}.png')
layer_image.save(path / 'images' / f'{layer.name}.webp', quality=80, method=6)
else:
# ...and background is the only layer we want to save as a jpg (as it doesn't have transparency)
if layer_image.mode == 'RGBA':
layer_image = layer_image.convert('RGB')
width, height = layer_image.size
half_width = width // 2
layer_image.crop((0, 0, half_width, height)).save(path / 'images' / f'{layer.name}_0.jpg',
quality=60)
layer_image.crop((half_width, 0, width, height)).save(path / 'images' / f'{layer.name}_1.jpg',
quality=60)
with open(path / 'images.json', 'w') as f:
json.dump(layer_dict, f, sort_keys=True, indent=4)
if __name__ == '__main__':
psd = PSDImage.open(r'E:\code\book-for-ukraine\static\in\VitejApojdSiPovidatV04.psd')
layers = {}
get_all_layers(psd)
print(len(layers))
print(layers)
print(sorted(layers.keys()))
export_layers(
layers['pozadi'],
path=Path(r'E:\code\book-for-ukraine\static\in'),
target_width=720 * 2, # target 720 for a single page
)