├── .gitignore ├── LICENSE ├── README.md ├── examples ├── test1.png ├── test2.png ├── test3.png └── test4.png └── gen.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Nikita Avdosev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Github avatars generator 2 | 3 | ![example1](./examples/test1.png) 4 | ![example2](./examples/test2.png) 5 | ![example3](./examples/test3.png) 6 | ![example4](./examples/test4.png) 7 | 8 | ## Run 9 | ``` 10 | python3 gen.py [avatar_size] [nickname] 11 | ``` 12 | 13 | avatar_size - number must be multiple 12 \ 14 | nickname - string -------------------------------------------------------------------------------- /examples/test1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avdosev/github_avatars_generator/93f528eebf8e46b2383d652d66691412ad31a501/examples/test1.png -------------------------------------------------------------------------------- /examples/test2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avdosev/github_avatars_generator/93f528eebf8e46b2383d652d66691412ad31a501/examples/test2.png -------------------------------------------------------------------------------- /examples/test3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avdosev/github_avatars_generator/93f528eebf8e46b2383d652d66691412ad31a501/examples/test3.png -------------------------------------------------------------------------------- /examples/test4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avdosev/github_avatars_generator/93f528eebf8e46b2383d652d66691412ad31a501/examples/test4.png -------------------------------------------------------------------------------- /gen.py: -------------------------------------------------------------------------------- 1 | from PIL import ImageDraw, Image 2 | import numpy as np 3 | import hashlib 4 | 5 | 6 | def generate_avatar(avatar_size: int, nickname: str) -> None: 7 | background_color = '#f2f1f2' 8 | s = nickname 9 | format = 'png' 10 | path = f'{s}.{format}' 11 | 12 | # Варианты генерации 13 | ## 12x12 - 144бит - 18байт 14 | ## 6*12 - 72бит - 9байт <- мне больше нравится 15 | ## Изображения получатся симметричными 16 | ## 6*6 - 36бит - 4.5байт 17 | 18 | ## Получаем набор псевдослучайных байт 19 | 20 | bytes = hashlib.md5(s.encode('utf-8')).digest() 21 | 22 | ## Получаем цвет из хеша 23 | 24 | main_color = bytes[:3] 25 | # rgb 26 | main_color = tuple(channel // 2 + 128 for channel in main_color) 27 | 28 | ## Генерируем матрицу заполнения блоков 29 | 30 | # массив 6 на 12 31 | need_color = np.array([bit == '1' for byte in bytes[3:3+9] for bit in bin(byte)[2:].zfill(8)]).reshape(6, 12) 32 | # получаем матрицу 12 на 12 33 | need_color = np.concatenate((need_color, need_color[::-1]), axis=0) 34 | 35 | for i in range(12): 36 | need_color[0, i] = 0 37 | need_color[11, i] = 0 38 | need_color[i, 0] = 0 39 | need_color[i, 11] = 0 40 | 41 | ## Рисуем изображения по матрице заполнения 42 | 43 | img_size = (avatar_size, avatar_size) 44 | block_size = avatar_size // 12 # размер квадрата 45 | 46 | img = Image.new('RGB', img_size, background_color) 47 | draw = ImageDraw.Draw(img) 48 | 49 | for x in range(avatar_size): 50 | for y in range(avatar_size): 51 | need_to_paint = need_color[x // block_size, y // block_size] 52 | if need_to_paint: 53 | draw.point((x, y), main_color) 54 | 55 | img.save(path, format) 56 | 57 | if __name__ == "__main__": 58 | import sys 59 | args = sys.argv 60 | avatar_size = int(args[1]) 61 | nickname = args[2] 62 | 63 | if avatar_size % 12 != 0: 64 | print('avatar size must be a multiple of 12') 65 | else: 66 | generate_avatar(avatar_size, nickname) --------------------------------------------------------------------------------