af6e54c6bba82e3467c8b01875717f4cbe42e6b5
[toast/gimp_passport.git] / gimp_passport.py
1 import argparse
2 from PIL import Image
3
4
5 def make_passport(img_rgba: Image, fpr: float, width_mm: float, height_mm: float) -> Image:
6     """
7     :param fpr: face to picture ratio, e.g. 2/3
8     """
9     # get bounding box of head
10     bands = img_rgba.getbands()
11     if 'A' not in bands:
12         raise ValueError('Image has no transparency (needed for marking the head).')
13     alpha = img_rgba.getdata(bands.index('A'))
14     bbox_head = alpha.getbbox()  # bounding box of head
15
16     # get bounding box of passport image ("pic")
17     left, top, right, bottom = bbox_head
18     height = bottom - top
19     width = right - left
20     pic_height = int(round(height / fpr))
21     pic_width = int(round(pic_height * width_mm / height_mm))
22     pic_top = top - (pic_height - height) // 2
23     pic_bottom = pic_top + pic_height
24     pic_left = left - (pic_width - width) // 2
25     pic_right = pic_left + pic_width
26     bbox_pic = pic_left, pic_top, pic_right, pic_bottom
27
28     # cut image
29     img = img_rgba.convert('RGB')  # drop alpha channel
30     pic = img.crop(bbox_pic)
31     return pic
32
33
34 def main(source_image: str, dest_image: str):
35     img = Image.open(source_image)
36     pic = make_passport(img, 0.75, 35., 45.)
37     pic.save(dest_image)
38
39
40 if __name__ == '__main__':
41     description = 'Convert image with alpha mask marking the face to passport image.'
42     parser = argparse.ArgumentParser(description=description)
43     parser.add_argument('source', help='sourse image')
44     parser.add_argument('dest', help='destination image')
45     args = parser.parse_args()
46     main(args.source, args.dest)
47