Часть 2 Генерация векторного изображения Самый простой спосо | Geeks
Часть 2
Генерация векторного изображения
Самый простой способ вывести изображение, состоящее из примитивов, это ручками слепить данные для SVG, и сохранить их в файл. SVG представляет из себя обычный XML. Я быстро сделал Jinja2-шаблон и циклом в нем нарисовал необходимые прямоугольники. Потом почесал затылок и решил, что Jinja2 всё таки пакет сторонний, а хочется свести количество зависимостей к нулю (спойлер: у меня так не выйдет).
Заглянем в будущее и рассмотрим фрагмент XML-файла, который у нас должен получиться:
Кажется, что комментировать тут особо и нечего - сначала рисуем один прямоугольник во всю величину аватарки. А затем на ней начинаем рисовать прямоугольники второго цвета.
Итак, даже тщательно не вглядываясь в XML можно приметить, что условно данные можно разделить на две части:
- Основной блок в котором мы задаем размер области видимости. То есть главный прямоугольник в который и будет вписана аватарка. И в этот блок мы вписываем сгенерированные прямоугольники. Зададим значение вот такой чудесной строкой:
SVG_WRAPPER = """
"""
- И множество блоков прямоугольников, которые будут генерироваться из вот такой строки:
SVG_RECT_TAG = '
Для получения готовых к использованию фрагментов XML будем использовать format для подмены значений в строках. И теперь мы можем написать функцию для создания svg-тега прямоугольника:
И пробежав по списку со списками сырых значений мы можем сгенерировать все прямоугольники и подставить их в строку SVG_WRAPPER. Готовая функция примет следующий вид:
def make_svg_data( data: List[List[bool]], cell_size: int, offset: int, first_color: Optional[str], second_color: Optional[str], ) -> str: box_size = len(data) * cell_size + 2 * offset box = make_svg_cell( x=0, y=0, offset=0, size=box_size, color=first_color, ) rects: List[str] = [box] for y, row in enumerate(data): for x, cell in enumerate(row): if not cell: continue rect = make_svg_cell( x=x, y=y, offset=offset, size=cell_size, color=second_color, ) rects.append(rect) svg_xml = SVG_WRAPPER.format( rects="\\n".join(rects), size=box_size, color=first_color, ) return svg_xml
И завершающий шаг, на котором можно проверить результат работы скрипта:
data = generate_data() svg = make_svg_data(data, cell_size=16, offset=8, first_color="#fff", second_color="#f6f") with open("test.svg", "w") as file: file.write(data)
Теперь можно открыть файл и полюбоваться на сгенеренное. Если хочется растровое изображение, то самый простой способ его получить - конвертнув его из SVG (на pypi можно найти пакет CairoSVG, но в системе должна стоять либа cairo).