-
Notifications
You must be signed in to change notification settings - Fork 0
/
Kernel.py
129 lines (109 loc) · 4.73 KB
/
Kernel.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
import sys
from os import path, mkdir
from PIL import Image, ImageOps, ImageDraw
class Config():
LEFT = 0x0
CENTER = 0x1
RIGHT = 0x2
def __init__(self, crop_type, size=(450, 450)):
self.type = crop_type
self.size = size
self.path = Rect(*self.getMap())
def getMap(self):
if self.type == self.LEFT:
return (328, 3, 778, 454)
elif self.type == self.CENTER:
return (556, 3, 1005, 454)
elif self.type == self.RIGHT:
return (782, 3, 1232, 454)
else:
return (0, 0, 1, 1)
class Rect():
def __init__(self, left, top, right, bottom):
self.left = left
self.top = top
self.right = right
self.bottom = bottom
def check_dimensions(self, rect):
if rect.left < self.left or rect.left > rect.right - 1:
return False, 'Invalid left value: %d (Min: %d, Max: %d).' % (rect.left, self.left, rect.right - 1)
if rect.right < rect.left + 1 or rect.right > self.right:
return False, 'Invalid right value: %d (Min: %d, Max: %d).' % (rect.right, rect.left + 1, self.right)
if rect.top < self.top or rect.top > rect.bottom - 1:
return False, 'Invalid top value: %d (Min: %d, Max: %d).' % (rect.top, self.top, rect.bottom - 1)
if rect.bottom < rect.top + 1 or rect.bottom > self.bottom:
return False, 'Invalid bottom value: %d (Min: %d, Max: %d).' % (rect.bottom, rect.top + 1, self.bottom)
return True, None
class Cropper():
def __init__(self, file):
if not path.exists(file):
raise FileExistsError('Unable to find image file at: %s' % path)
self.exports_count = 0
self.basedir = path.dirname(file)
self.filename, self.extension = path.splitext(path.basename(file))
self.image = Image.open(file)
self.width, self.height = self.image.size
self.rect = Rect(0, 0, self.width, self.height)
print('[%s] Loaded: [W: %d, H: %d]' % (self.filename, self.width, self.height))
def crop(self, rect):
success, error = self.rect.check_dimensions(rect)
if not success:
raise ValueError(error)
width = rect.right - rect.left
height = rect.bottom - rect.top
self.cropped = self.image.crop((rect.left, rect.top, rect.right, rect.bottom))
print("[%s] Cropped: [W: %d, H: %d]" % (self.filename, width, height))
def crop_ellipse(self, mask_size):
tmp_size = tuple(map(lambda x: x * 2, mask_size))
mask = Image.new('L', tmp_size, 0)
ImageDraw.Draw(mask).ellipse((0, 0) + tmp_size, fill=255)
mask = mask.resize(mask_size, Image.LANCZOS)
self.ellipse = ImageOps.fit(self.cropped, mask_size, method=Image.LANCZOS, centering=(0.5, 0.5))
self.ellipse.putalpha(mask)
print("[%s] Ellipse: [W: %d, H: %d]" % ((self.filename,) + mask_size))
def crop_all(self):
configs = (
Config(Config.LEFT),
Config(Config.CENTER),
Config(Config.RIGHT)
)
for config in configs:
self.crop(config.path)
self.resize(config.size)
self.crop_ellipse(config.size)
self.export()
self.cropped.close()
self.ellipse.close()
print("[%s] Done." % self.filename)
def resize(self, resize):
self.cropped = self.cropped.resize(resize, Image.LANCZOS)
print("[%s] Resized: [W: %d, H: %d]" % ((self.filename,) + resize))
def export(self, png=True, jpeg=True):
if not png and not jpeg:
raise ValueError('Either PNG or JPEG must be true.')
self.exports_count += 1
output_dir = path.join(self.basedir, self.filename)
if not path.isdir(output_dir):
mkdir(output_dir)
if png:
filename_png = '%s-%d.png' % (self.filename, self.exports_count)
output = path.join(output_dir, filename_png)
self.cropped.save(output, quality=100)
if jpeg:
filename_jpeg = '%s-%d.jpg' % (self.filename, self.exports_count)
output = path.join(output_dir, filename_jpeg)
self.cropped.save(output, quality=100)
if not self.ellipse is None:
ellipse_filename = '%s-%d_ellipse.png' % (self.filename, self.exports_count)
output = path.join(output_dir, ellipse_filename)
self.ellipse.save(output, quality=100)
def show(self, image=None):
(image if not image is None else self.cropped).show()
def close(self):
self.image.close()
print("[%s] Released." % self.filename)
if __name__ == "__main__":
for file in sys.argv[1:]:
image = Cropper(file)
image.crop_all()
image.close()