From 4dd039d6e703979427263e1604fd1492e6f4ef66 Mon Sep 17 00:00:00 2001 From: erjemin Date: Sat, 18 Jul 2026 17:53:04 +0300 Subject: [PATCH] =?UTF-8?q?mod:=20=D0=9A=D1=83=D1=87=D0=B0=20=D0=BE=D0=BF?= =?UTF-8?q?=D1=82=D0=B8=D0=BC=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D0=B9:=20?= =?UTF-8?q?=D0=B3=D1=80=D1=83=D0=BF=D0=BF=D0=B8=D1=80=D0=BE=D0=B2=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=BA=D1=80=D1=83=D0=B6=D0=BE=D1=87=D0=BA=D0=BE=D0=B2?= =?UTF-8?q?=20=D0=BE=D0=B4=D0=BD=D0=BE=D0=B3=D0=BE=20=D1=80=D0=B0=D0=B4?= =?UTF-8?q?=D0=B8=D1=83=D1=81=D0=B0,=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B8?= =?UTF-8?q?=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=BA=D1=80=D1=83=D0=B6=D0=BE=D1=87=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2=20=D1=87=D0=B5=D1=80=D0=B5=D0=B7=20use=20=D0=B8=20=D1=82?= =?UTF-8?q?.=D0=BF.=20=D0=A0=D0=B0=D0=B7=D0=BC=D0=B5=D1=80=20=D1=80=D0=B5?= =?UTF-8?q?=D0=B7=D1=83=D0=BB=D1=8C=D1=82=D0=B8=D1=80=D1=83=D1=8E=D1=89?= =?UTF-8?q?=D0=B5=D0=B3=D0=BE=20=D1=84=D0=B0=D0=B9=D0=BB=D0=B0=20=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D1=8C=D1=88=D0=B5=20=D0=BD=D0=B0=20~30-70%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 ++--- img/cc.svg | 1 + img/img_2.jpg | Bin 28117 -> 0 bytes img/img_2j.svg | 1 - img/lp.svg | 1 + img/lp_8j.svg | 1 - main.py | 53 ++++++++++++++++++++++++++++++++++++++----------- 7 files changed, 45 insertions(+), 17 deletions(-) create mode 100644 img/cc.svg delete mode 100644 img/img_2.jpg delete mode 100644 img/img_2j.svg create mode 100644 img/lp.svg delete mode 100644 img/lp_8j.svg diff --git a/README.md b/README.md index 53d228f..776222f 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,7 @@ Генерирует SVG халфтоновый эффект из изображения с анимацией мерцания точек. Например: - -![Пример](img/img_2j.svg) +![Пример](img/lp.svg) ## Что делает @@ -48,4 +47,4 @@ poetry run python main.py img/img_2.jpg или наоборот ""распустить") - `fill:#80000090` -- цвет точек (с прозрачностью) -![Еще пример](img/lp_8j.svg) +![Еще пример](img/cc.svg) diff --git a/img/cc.svg b/img/cc.svg new file mode 100644 index 0000000..4a7ed92 --- /dev/null +++ b/img/cc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/img/img_2.jpg b/img/img_2.jpg deleted file mode 100644 index 9efaeab1d258e67c497957eee54d745df25e7435..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28117 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 H{OtdKdLQ_@ diff --git a/img/img_2j.svg b/img/img_2j.svg deleted file mode 100644 index b3a1841..0000000 --- a/img/img_2j.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/img/lp.svg b/img/lp.svg new file mode 100644 index 0000000..278e2e0 --- /dev/null +++ b/img/lp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/img/lp_8j.svg b/img/lp_8j.svg deleted file mode 100644 index dc96562..0000000 --- a/img/lp_8j.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/main.py b/main.py index 0874ab4..382b8a9 100644 --- a/main.py +++ b/main.py @@ -8,7 +8,7 @@ def encode_to_base36(num): if num < 0: raise ValueError("Number must be non-negative") - charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" if num < len(charset): return charset[num] @@ -19,8 +19,9 @@ def encode_to_base36(num): return ''.join(reversed(result)) -def generate_halftone_svg(image_path, output_path, cols=80, max_radius=6, animation_variants=12): +def generate_halftone_svg(image_path, output_path, cols=80, max_radius=8, animation_variants=12): import random + from collections import defaultdict img = Image.open(image_path).convert('L') aspect_ratio = img.height / img.width @@ -31,14 +32,21 @@ def generate_halftone_svg(image_path, output_path, cols=80, max_radius=6, animat width = cols * step height = rows * step - svg_elements = [] - # Генерируем CSS-классы для разных задержек animation_classes = [] for i in range(animation_variants): delay = (i / animation_variants) * 3 encoded_i = encode_to_base36(i) - animation_classes.append(f".a{encoded_i}{{--d:{delay:.2f}s}}") + # Убрать .0 для целых чисел: 1.0s → 1s + if delay == int(delay): + delay_str = f"{int(delay)}" + else: + delay_str = f"{delay:.1f}".lstrip('0') + animation_classes.append(f".{encoded_i}{{--d:{delay_str}s}}") + + # Собираем элементы группируя по классам: {class: [(radius, cx, cy), ...]} + elements_by_class = defaultdict(list) + unique_radii = set() for y in range(rows): for x in range(cols): @@ -48,20 +56,41 @@ def generate_halftone_svg(image_path, output_path, cols=80, max_radius=6, animat if factor < 0.15: continue - radius = factor * max_radius + radius = int(factor * max_radius) + if radius == 0: + continue + cx = x * step + step // 2 cy = y * step + step // 2 - # Каждой точке свой класс с уникальной задержкой anim_class = random.randint(0, animation_variants - 1) encoded_class = encode_to_base36(anim_class) - svg_elements.append( - f'' - ) + + elements_by_class[encoded_class].append((radius, cx, cy)) + unique_radii.add(radius) + + # Создаем с определениями кружков для каждого радиуса + defs = '' + for radius in sorted(unique_radii): + encoded_radius = encode_to_base36(radius) + defs += f'' + defs += '' + + # Создаем группы по классам + groups = [] + for anim_class in sorted(elements_by_class.keys()): + group_elements = elements_by_class[anim_class] + uses = ''.join( + f'' + for radius, cx, cy in group_elements + ) + if uses: + groups.append(f'{uses}') animation_css = "".join(animation_classes) + groups_html = "".join(groups) - svg_template = f"""{"".join(svg_elements)}""" + svg_template = f'''{defs}{groups_html}''' with open(output_path, 'w') as f: f.write(svg_template) @@ -69,4 +98,4 @@ def generate_halftone_svg(image_path, output_path, cols=80, max_radius=6, animat if __name__ == '__main__': file_name_in = sys.argv[-1] - generate_halftone_svg(file_name_in, f'{file_name_in.split(".")[0]}j.svg', cols=90, max_radius=5) + generate_halftone_svg(file_name_in, f'{file_name_in.split(".")[0]}j.svg', cols=63, max_radius=7)