Advertisement
Anglis

Untitled

Mar 2nd, 2021
648
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.38 KB | None | 0 0
  1. import enum
  2. import pathlib
  3.  
  4. import numpy as np
  5. from PIL import Image, ImageDraw
  6.  
  7.  
  8. class UserInput(str, enum.Enum):
  9.     SUM = '1'
  10.     AVG = '2'
  11.     MAX = '3'
  12.     MIN = '4'
  13.     CYCLE_MASK = '5'
  14.     SQUARE_MASK = '6'
  15.     RECTANGLE_MASK = '7'
  16.     EXIT = '0'
  17.     MULT = '__mult'
  18.  
  19.  
  20. def _sum_tuple(size_1: tuple[int, int, int], size_2: tuple[int, int, int]) -> tuple[int, int, int]:
  21.     return tuple(np.array(size_1) + np.array(size_2))
  22.  
  23.  
  24. def _mult_tuple(size_1: tuple[int, int, int], size_2: tuple[int, int, int]) -> tuple[int, int, int]:
  25.     return tuple(np.array(size_1) * np.array(size_2))
  26.  
  27.  
  28. def _avg_tuple(size_1: tuple[int, int, int], size_2: tuple[int, int, int]) -> tuple:
  29.     return tuple(map(int, (np.array(size_1) + np.array(size_2)) / 2))
  30.  
  31.  
  32. def _max_tuple(size_1: tuple[int, int, int], size_2: tuple[int, int, int]) -> tuple[int, int, int]:
  33.     return tuple(np.maximum.reduce([size_1, size_2]))
  34.  
  35.  
  36. def _min_tuple(size_1: tuple[int, int, int], size_2: tuple[int, int, int]) -> tuple[int, int, int]:
  37.     return tuple(np.minimum.reduce([size_1, size_2]))
  38.  
  39.  
  40. def _cycle_mask(size: tuple[int, int]) -> Image.Image:
  41.     mask: Image.Image = Image.new('RGBA', size, color=(0, 0, 0, 0))
  42.     draw: ImageDraw.ImageDraw = ImageDraw.Draw(mask)
  43.  
  44.     width, height = size
  45.     center = width // 2
  46.     draw.ellipse(
  47.         (
  48.             center - width // 3,
  49.             center - height // 3,
  50.             center + width // 3,
  51.             center + height // 3,
  52.         ),
  53.         fill=(1, 1, 1, 0),
  54.     )
  55.     return mask
  56.  
  57.  
  58. def _square_mask(size: tuple[int, int]) -> Image.Image:
  59.     mask: Image.Image = Image.new('RGBA', size, color=(0, 0, 0, 0))
  60.     draw: ImageDraw.ImageDraw = ImageDraw.Draw(mask)
  61.  
  62.     width, height = size
  63.     center = width // 2
  64.     draw.rectangle(
  65.         (
  66.             center - width // 3,
  67.             center - height // 3,
  68.             center + width // 3,
  69.             center + height // 3,
  70.         ),
  71.         fill=(1, 1, 1, 0),
  72.     )
  73.     return mask
  74.  
  75.  
  76. def _rectangle_mask(size: tuple[int, int]) -> Image.Image:
  77.     mask: Image.Image = Image.new('RGBA', size, color=(0, 0, 0, 0))
  78.     draw: ImageDraw.ImageDraw = ImageDraw.Draw(mask)
  79.  
  80.     width, height = size
  81.     center = width // 2
  82.     draw.rectangle(
  83.         (
  84.             center - width // 2,
  85.             center - height // 3,
  86.             center + width // 2,
  87.             center + height // 3,
  88.         ),
  89.         fill=(1, 1, 1, 0),
  90.     )
  91.     return mask
  92.  
  93.  
  94. def _get_mask_by_user_input(user_input: UserInput, size: tuple[int, int]) -> Image.Image:
  95.     mapper = {
  96.         UserInput.RECTANGLE_MASK: _rectangle_mask,
  97.         UserInput.SQUARE_MASK: _square_mask,
  98.         UserInput.CYCLE_MASK: _cycle_mask,
  99.     }
  100.     mask_getter = mapper.get(user_input, UserInput.CYCLE_MASK)
  101.     mask = mask_getter(size)
  102.     return mask
  103.  
  104.  
  105. def _process_command(
  106.         user_input: UserInput,
  107.         img_in_1: Image.Image,
  108.         img_in_2: Image.Image,
  109.         xy: tuple[int, int],
  110. ) -> tuple[int, int, int]:
  111.     func_mapper = {
  112.         UserInput.SUM: _sum_tuple,
  113.         UserInput.AVG: _avg_tuple,
  114.         UserInput.MAX: _max_tuple,
  115.         UserInput.MIN: _min_tuple,
  116.         UserInput.MULT: _mult_tuple,
  117.     }
  118.  
  119.     img_1_pixel_slicer = slice(len(img_in_1.getpixel((0, 0))))
  120.     img_2_pixel_slicer = slice(len(img_in_2.getpixel((0, 0))))
  121.     if len(img_in_1.getpixel((0, 0))) > 3:
  122.         img_1_pixel_slicer = slice(3)
  123.     if len(img_in_2.getpixel((0, 0))) > 3:
  124.         img_2_pixel_slicer = slice(3)
  125.  
  126.     return func_mapper[user_input](img_in_1.getpixel(xy)[img_1_pixel_slicer], img_in_2.getpixel(xy)[img_2_pixel_slicer])
  127.  
  128.  
  129. def process_image(user_input: UserInput, img_in_1: Image.Image, img_in_2: Image.Image, out: Image.Image):
  130.     width, height = img_in_1.size
  131.     for x in range(width):
  132.         for y in range(height):
  133.             out.putpixel((x, y), _process_command(user_input, img_in_1, img_in_2, (x, y)))
  134.  
  135.  
  136. def is_mask(user_input: UserInput) -> bool:
  137.     return user_input in {UserInput.CYCLE_MASK, UserInput.SQUARE_MASK, UserInput.RECTANGLE_MASK}
  138.  
  139.  
  140. def process_mask(user_input: UserInput, img_in_1: Image.Image, out: Image.Image):
  141.     width, height = img_in_1.size
  142.     mask = _get_mask_by_user_input(user_input, img_in_1.size)
  143.     for x in range(width):
  144.         for y in range(height):
  145.             out.putpixel((x, y), _process_command(UserInput.MULT, img_in_1, mask, (x, y)))
  146.  
  147.  
  148. def user_input_loop():
  149.     while True:
  150.         print(
  151.             '1> Sum\n'
  152.             '2> Avg\n'
  153.             '3> Max\n'
  154.             '4> Min\n'
  155.             '5> Cycle mask\n'
  156.             '6> Square mask\n'
  157.             '7> Rectangle mask\n'
  158.             '0> Exit\n'
  159.         )
  160.  
  161.         try:
  162.             user_input = UserInput(input('> '))
  163.             return user_input
  164.         except ValueError:
  165.             print('Wrong option')
  166.             continue
  167.  
  168.  
  169. def get_init_images() -> tuple[Image.Image, Image.Image, Image.Image]:
  170.     while True:
  171.         image_1 = pathlib.Path(input('Enter first image path > '))
  172.         if not image_1.exists():
  173.             print('No such file.')
  174.             continue
  175.         break
  176.  
  177.     while True:
  178.         image_2 = pathlib.Path(input('Enter second image path > '))
  179.         if not image_2.exists():
  180.             print('No such file.')
  181.             continue
  182.  
  183.         break
  184.  
  185.     img_in_1: Image.Image = Image.open(image_1.resolve())
  186.     img_in_2: Image.Image = Image.open(image_2.resolve())
  187.     out: Image.Image = Image.new('RGBA', img_in_1.size, color=(0, 0, 0, 0))
  188.     return img_in_1, img_in_2, out
  189.  
  190.  
  191. def save_image_prompt(out: Image.Image):
  192.     while True:
  193.         path = pathlib.Path(input('Enter output image save path > '))
  194.         if path.exists():
  195.             print('This pass has been already taken.')
  196.             continue
  197.         try:
  198.             out.save(path.open('wb'))
  199.             return
  200.         except OSError as e:
  201.             print(e)
  202.             path.unlink(missing_ok=True)
  203.  
  204.  
  205. def main():
  206.     im_1, im_2, out = get_init_images()
  207.     user_input = user_input_loop()
  208.     if user_input == UserInput.EXIT:
  209.         return
  210.  
  211.     if is_mask(user_input):
  212.         process_mask(user_input, im_1, out)
  213.     else:
  214.         if im_1.size != im_2.size:
  215.             print('Image should be the same size!')
  216.             return
  217.  
  218.         process_image(user_input, im_1, im_2, out)
  219.  
  220.     save_image_prompt(out)
  221.     out.show()
  222.  
  223.  
  224. if __name__ == '__main__':
  225.     main()
  226.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement