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