from dataclasses import dataclass import random from PIL import Image, ImageDraw, ImageFont # from numba import prange @dataclass class Drawing: """Рисуем чернилами на листке""" COLOR_USE: bool stroka: str font_use: ImageFont list_size: int clear_paper: ImageDraw line_start: int offset: int spaser_word: int font_name: str font_color: list def _drawing_word(self, number: int, slovo: str): """Рисуем слово""" img_slovo = Image.new('RGBA', (self.width+number, self.height), (255, random.randint(0, 150), random.randint(0, 200), self.color_word)) draw = ImageDraw.Draw(img_slovo) draw.text((number, 0), slovo, fill=( self.font_color[0], self.font_color[1], self.font_color[2] ), font=self.font_use) return img_slovo def _drawing_line(self): """Рисуем слова на строке""" for slovo in self.stroka.split(): # print(self.width, self.height) new_size = self.font_use.getbbox(slovo) self.width, self.height = new_size[2], new_size[3] self.color_word = 200 if self.COLOR_USE else 0 # Пишем на этой картинке шрифтом if self.font_name == 'Salavat': img_slovo = self._drawing_word(15, slovo) else: img_slovo = self._drawing_word(10, slovo) # поварачиваем текст ran_rotate = random.uniform(-2.0, 1.5) img_slovo = img_slovo.rotate(ran_rotate, expand=True) # img_slovo = img_slovo.transform(img_slovo.size, Image.AFFINE, (1, 20, 0, 0, 1, 0), resample=Image.BICUBIC) # Добавляем картинку со словом в масив self.mass_img.append(img_slovo) return self.mass_img def _paste_on_paper(self): """Рисуем строки на листке""" self.color_line = 155 if self.COLOR_USE else 0 # Создаём картинку всей строки stroka_img = Image.new('RGBA', (self.list_size, 135), (255, 255, 255, self.color_line)) line_width = 0 for i in range(len(self.mass_img)): # Узнаём ширину картинки) width = self.mass_img[i].width # Наносим картинку фото на картинку строки ran_down_text = random.randint(-2, 2) stroka_img.paste(self.mass_img[i], (line_width, ran_down_text), mask=self.mass_img[i]) # Если есть это не последнее слово то добавляем после него пробел # рандомный отступ между слов ran_spase = random.randint(25, 35) # 30/len(mass_img) # print(ran_spase) line_width += width + ran_spase # spaser_word # 30 # except: # len_width += width self.clear_paper.paste(stroka_img, (self.line_start, self.offset), mask=stroka_img) def draw(self): self.mass_img = [] self._drawing_line() self._paste_on_paper()
Public
Simple rule: read a variable name as if you were English-speaking person without a context and guess what's inside - and if you have no clue, then you should give it a better name. Exceptions: i
, j
, x
, y
etc.
Type hints help humans and linters (like mypy
) to understand what to expect "in" and "out" for a function. Not only it serves as a documentation for others (and you after some time, when the code is wiped from your "brain cache"), but also allows using automated tools to find type errors.
Missing return type hint
This code is not really needed or may be simplified
fill=self.font_color[:3]
Copy-paste lead to errors very, very often because developers forget to change value on one of copy-pasted lines . You should avoid it as much as possible. Usually a good solution is to extract the things that differ into separate variables.
number = 15 if self.font_name == 'Salavat' else 10 img_slovo = self._drawing_word(number, slovo)
Side effects are evil: it's very hard to track what function does under the hood, because function signature does not reflect side effects. Always try to write "pure" functions, i.e. those which receive inputs, do something internally, and return output. You should be able to run such function million times and get exactly the same result with nothing changed in the environment. However, side effects are totally OK if that's the only thing the function does.
Using len
and range
in python's for
loop smells. Idiomatic python iteration looks like for element in collection
. If you need element's index as well, use for i, element in enumerate(collection)
.
for img in self.mass_img
Create new review request