From 60930a974e8973a942acb33556c435592ca5827c Mon Sep 17 00:00:00 2001 From: erjemin Date: Fri, 17 Jul 2026 13:14:12 +0300 Subject: [PATCH] =?UTF-8?q?init:=20=D0=B2=D1=80=D0=BE=D0=B4=D0=B5=20=D0=B2?= =?UTF-8?q?=D1=81=D1=91=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D0=B5=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 243 +++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 40 ++++++++ img/img_2.jpg | Bin 0 -> 28117 bytes img/img_2j.svg | 1 + main.py | 53 +++++++++++ poetry.lock | 110 ++++++++++++++++++++++ pyproject.toml | 15 +++ 7 files changed, 462 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 img/img_2.jpg create mode 100644 img/img_2j.svg create mode 100644 main.py create mode 100644 poetry.lock create mode 100644 pyproject.toml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..263c000 --- /dev/null +++ b/.gitignore @@ -0,0 +1,243 @@ +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Python template +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/latest/usage/project/#working-with-version-control +.pdm.toml +.pdm-python +.pdm-build/ + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + diff --git a/README.md b/README.md new file mode 100644 index 0000000..4b5b5ff --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +# Image Halftone Experiment + +Генерирует SVG халфтоновый эффект из изображения с анимацией мерцания точек. + +## Что делает + +Скрипт преобразует любое изображение в компактный SVG с: +- **Халфтоновым растром** — изображение из точек разного размера (как на плакате) +- **CSS-анимацией** — каждая точка пульсирует с уникальной задержкой +- **Прозрачным фоном** — работает на любом фоне (темная/светлая тема) +- **Минимальным размером** — оптимизирован через переиспользование CSS-классов + +## Быстрый старт + +```bash +# Установить зависимости +poetry install + +# Запустить +poetry run python main.py img_3.jpg +``` + +На выходе получишь `img_3j.svg` с анимацией. + +## Параметры + +В коде (строка 53) можно менять: +- `cols=90` — кол-во колонок (больше = детальнее, но тяжелее) +- `max_radius=5` — макс размер точки + +Параметры анимации в функции `generate_halftone_svg()`: +- `animation_variants=12` — кол-во групп точек с разными задержками (чем меньше --> компактнее SVG) + +В стилях CSS можно поиграться: +- `animation-duration: 1.5s` — скорость пульсации (чем меньше --> быстрее) +- `animation-delay: calc(var(--i) * 0.1s)` — задержка для каждой точки (чем меньше --> быстрее) +- `animation-iteration-count: infinite` — бесконечная анимация (можно убрать, если нужно один раз) +- `transform:scale(0.99)` — масштабирование групп точек (можно экстремально всю картинку "схлопнуть" + или наоборот ""распустить") +- `fill:#80000090` -- цвет точек (с прозрачностью) diff --git a/img/img_2.jpg b/img/img_2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9efaeab1d258e67c497957eee54d745df25e7435 GIT binary patch literal 28117 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 H{OtdKdLQ_@ literal 0 HcmV?d00001 diff --git a/img/img_2j.svg b/img/img_2j.svg new file mode 100644 index 0000000..53bf459 --- /dev/null +++ b/img/img_2j.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..c99b2f1 --- /dev/null +++ b/main.py @@ -0,0 +1,53 @@ +import sys + +from PIL import Image + +def generate_halftone_svg(image_path, output_path, cols=80, max_radius=6, animation_variants=12): + import random + + img = Image.open(image_path).convert('L') + aspect_ratio = img.height / img.width + rows = int(cols * aspect_ratio) + img_resized = img.resize((cols, rows), Image.Resampling.LANCZOS) + + step = max_radius * 2 + 2 + width = cols * step + height = rows * step + + svg_elements = [] + + # Генерируем CSS-классы для разных задержек + animation_classes = [] + for i in range(animation_variants): + delay = (i / animation_variants) * 3 + animation_classes.append(f".a{i}{{--d:{delay:.2f}s}}") + + for y in range(rows): + for x in range(cols): + brightness = img_resized.getpixel((x, y)) + factor = (255 - brightness) / 255.0 + + if factor < 0.15: + continue + + radius = factor * max_radius + cx = x * step + step // 2 + cy = y * step + step // 2 + + # Каждой точке свой класс с уникальной задержкой + anim_class = random.randint(0, animation_variants - 1) + svg_elements.append( + f'' + ) + + animation_css = "".join(animation_classes) + + svg_template = f"""{"".join(svg_elements)}""" + + with open(output_path, 'w') as f: + f.write(svg_template) + print(f"SVG успешно сгенерирован: {output_path}") + +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) diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..9b6dc22 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,110 @@ +# This file is automatically @generated by Poetry 1.8.0 and should not be changed by hand. + +[[package]] +name = "pillow" +version = "12.3.0" +description = "Python Imaging Library (fork)" +optional = false +python-versions = ">=3.10" +files = [ + {file = "pillow-12.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:6c0016e7b354317c4e9e525b937ac8596c38d2d232b419529b9cd7a1cd46e39a"}, + {file = "pillow-12.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bcc33feacfaefce60c12fd500a277533bdc02b10a19f7f6d348763d8140bbba7"}, + {file = "pillow-12.3.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5594fc43d548a7ed94949d139aa1341b270f1863f11cfd37f5a6c8b778a6b67f"}, + {file = "pillow-12.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f0606c8bf2cdefea14a43530f7657cbbb7ecf1c4222512492ef4a4434a9501ec"}, + {file = "pillow-12.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:85f998ea1848bc6757289e739cfbdda3a04adfd58b02fc018ce54d754a5ce468"}, + {file = "pillow-12.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:25b9b82bb22e6e2b3cd07b39c68b7b862001226cb3dff7130d1cb914121b39ed"}, + {file = "pillow-12.3.0-cp310-cp310-win32.whl", hash = "sha256:37dc8f7bbb66efe481bb60defacef820c950c24713fb44962ed6aa2a50966de1"}, + {file = "pillow-12.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:300557495eb45ebb8aec96c2da9c4be642fbf7cd937278b4013ba894ea8eb0eb"}, + {file = "pillow-12.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:514435a37670e3e5e08f3945b68718b6ed329bb84367777e16f9f4dfe1e61a0f"}, + {file = "pillow-12.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:00808c5e14ef63ac5161091d242999076604ff74b883423a11e5d7bbb38bf756"}, + {file = "pillow-12.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:37d6d0a00072fd2948eb22bce7e1475f34569d90c87c59f7a2ec59541b77f7a6"}, + {file = "pillow-12.3.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bcb46e2f9feff8d06323983bd83ed00c201fdcab3d74973e7072a889b3979fcd"}, + {file = "pillow-12.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23d27a3e0307ec2244cc51e7287b919aa68d097504ebe19df4e76a98a3eea5bd"}, + {file = "pillow-12.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4f883547d4b7f0495ebe7056b0cc2aea76094e7a4abc8e933540f3271df27d9c"}, + {file = "pillow-12.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:236ff70b9312fb68943c703aa842ca6a758abfa45ac187a5e7c1452e96ef72b5"}, + {file = "pillow-12.3.0-cp311-cp311-win32.whl", hash = "sha256:10e41f0fbf1eec8cfd234b8fe17a4caac7c9d0db4c204d3c173a8f9f6ef3232b"}, + {file = "pillow-12.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:8e95e1385e4998ae9694eeaa4730ba5457ff61185b3a55e2e7bea0880aef452a"}, + {file = "pillow-12.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:ebaea975e03d3141d9d3a507df75c9b3ec90fa9d2ffd07567b3a978d9d790b26"}, + {file = "pillow-12.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ba09209fbe443b4acccebe845d8a138b89a8f4fbaeedd44953490b5315d5e965"}, + {file = "pillow-12.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffd0c5368496f41b0944be820fcb7a838aa6e623d250b01acf2643939c3f99d7"}, + {file = "pillow-12.3.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9c7f76c0673154f044e9d78c8655fb4213f6ca31a836df48b40fe5d187717b9"}, + {file = "pillow-12.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:78cb2c6865a35ab8ff8b75fd122f6033b92a62c82801110e48ddd6c936a45d91"}, + {file = "pillow-12.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e491916b378fba47242221bb9ead245211b70d504f495d105d17b14a24b4907c"}, + {file = "pillow-12.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0dd2064cbc55aaec028ef5fbb60fa47bb6c3e7918e07ff17935284b227a9d2df"}, + {file = "pillow-12.3.0-cp312-cp312-win32.whl", hash = "sha256:dbce0b29841537a2fa4a214c2bbf14de3587c9680caa9b4e217568472490b28f"}, + {file = "pillow-12.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a2b55dd6b2a4c4b7d87ffa56bdb33fdc5fdb9a462173861a7bc097f17d91cb09"}, + {file = "pillow-12.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:331b624368d4f1d069149002f25f44bc61c8919ce8ddb3c45bdad8f6e2d89510"}, + {file = "pillow-12.3.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:21900ce7ba264168cd50defae43cd75d25c833ad4ad6e73ffc5596d12e25ac89"}, + {file = "pillow-12.3.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:4e8c2a84d977f50b9daed6eeaf3baef67d00d5d74d932288f02cb94518ee3ace"}, + {file = "pillow-12.3.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:ae26d61dfa7a47befdc7572b521024e8745f3d809bd95ca9505a7bba9ef849ec"}, + {file = "pillow-12.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7a743ff716f746fc19a9557f60dab1600d4613255f8a7aeb3cdde4db7eb15a66"}, + {file = "pillow-12.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d69141514cc30b774ceea5e3ed3a6635c8d8a96edf664689b890f4089111fb35"}, + {file = "pillow-12.3.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f7401aebd7f581d7f83a439d87d474999317ee099218e5ad25d125290990ba65"}, + {file = "pillow-12.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0847a763afefb695bc912d7c131e7e0632d4edc1d8698f58ddabec8e46b8b6d3"}, + {file = "pillow-12.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:571b9fcb07b97ef3a492028fb3d2dc0993ca23a06138b0315286566d29ef718a"}, + {file = "pillow-12.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:756c768d0c9c2955feb7a56c37ea24aea2e369f8d36a88da270b6a9f19e62b5e"}, + {file = "pillow-12.3.0-cp313-cp313-win32.whl", hash = "sha256:a876864214e136f0eb367788dbd7df045f4806801518e2cfe9e13229cfe06d8f"}, + {file = "pillow-12.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:1cca606cd25738df4ed873d5ad46bbdb3d83b5cbca291f6b4ff13a4df6b0bbe8"}, + {file = "pillow-12.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:b629de27fda84b42cde7edef0d85f13b958b47f6e9bbcbba9b673c562a89bd8b"}, + {file = "pillow-12.3.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:9cf95fe4d0f84c82d282745d9bb08ad9f926efa00be4697e767b814ce40d4330"}, + {file = "pillow-12.3.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:8728f216dcdb6e6d555cf971cb34076139ad74b31fc2c14da4fafc741c5f6217"}, + {file = "pillow-12.3.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:a45650e8ce7fafffd731db8550230db6b0d306d181a90b67d3e6bca2f1990930"}, + {file = "pillow-12.3.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:ba54cfebe86920a559a7c4d6b9050791c20513650a1952ebe3368c7dc70306f8"}, + {file = "pillow-12.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e158cb00350dc278f3b91551101aa7d12415a66ebf2c91d8d5ac14e56ddd3ad0"}, + {file = "pillow-12.3.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e9aeb04d6aef139de265b29683e119b638208f88cf73cdd1658aa07221165321"}, + {file = "pillow-12.3.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:251bf95b67017e27b13d82f5b326234ca62d70f9cf4c2b9032de2358a3b12c7b"}, + {file = "pillow-12.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fe3cca2e4e8a592be0f269a1ca4835c25199d9f3ce815c8491048f785b0a0198"}, + {file = "pillow-12.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:23aceaa007d6172b02c277f0cd359c79492bbb14f7072b4ede9fbcaf20648130"}, + {file = "pillow-12.3.0-cp314-cp314-win32.whl", hash = "sha256:af8d94b0db561cf68b88a267c5c44b49e134f525d0dc2cb7ed413a66bc23559a"}, + {file = "pillow-12.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:fdafc9cce40277e0f7a0feabce0ee50dd2fa1800f3b38015e51296b5e814048d"}, + {file = "pillow-12.3.0-cp314-cp314-win_arm64.whl", hash = "sha256:e91206ee562682b51b98ef4b26a6ef48fd84e15fd4c4bc5ec768eb641d206838"}, + {file = "pillow-12.3.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:164b31cd1a0490ab6efae01aa5df49da7061be0af1b30e035b6e9a1bfe34ee6e"}, + {file = "pillow-12.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5afb51d599ea772b8365ae807ae557f18bccfe46ab261fd1c2a9ed700fc6eb17"}, + {file = "pillow-12.3.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3edce1d53195db527e0191f84b71d02022de0540bf43a16ed734ed7537b07385"}, + {file = "pillow-12.3.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bf16ba1b4d0b6b7c8e534936632270cf70eb00dbe09005bc345b2677b726855c"}, + {file = "pillow-12.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:24870b09b224f7ae3c39ed07d10e819d06f8720bc551847b1d623832b5b0e28d"}, + {file = "pillow-12.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:30f2aa603c41533cc25c05acd0da21636e84a315768feb631c937177db558931"}, + {file = "pillow-12.3.0-cp314-cp314t-win32.whl", hash = "sha256:4b0a7fe987b14c31ebda6083f74f22b561fd3739bc0ac51e019622e3d72668c7"}, + {file = "pillow-12.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:962864dc93511324d51ddbb5b9f8731bf71675b93ca612a07441896f4688fb8c"}, + {file = "pillow-12.3.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0740a512dc522224c77d9aa5a8d70d8b7d73fb91f2c21125d8d025d3b8990e45"}, + {file = "pillow-12.3.0-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:0feb2e9d6ad6c9e3c06effe9d00f3f1e618a6643273576b016f591e9315a7139"}, + {file = "pillow-12.3.0-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:9e881fca225083806662a5c43d627d215f258ff43c890f831966c7d7ba9c7402"}, + {file = "pillow-12.3.0-cp315-cp315-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:4998562bf62a445225f22e07c896bb04b35b1b1f2eb6d760584c9c51d7a5f78c"}, + {file = "pillow-12.3.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:dc624f6bc473dacdf7ef7eb8678d0d08edf15cd94fad6ae5c7d6cc67a4e4902f"}, + {file = "pillow-12.3.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:71d6097b330eea8fd15097780c8e89cb1a8ce7838669f48c5bacd6f663dd4701"}, + {file = "pillow-12.3.0-cp315-cp315-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:28ce87c5ab450a9dd970b52e5aca5fe63ed432d18a2eaddd1979a00a1ba24ace"}, + {file = "pillow-12.3.0-cp315-cp315-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6b02afb9b97f65fbca5f31db6a2a3ba21aa93030225f150fa3f249717e938fb4"}, + {file = "pillow-12.3.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:1182d52bc2d5e5d7d0949503aa7e36d12f42205dc287e4883f407b1988820d39"}, + {file = "pillow-12.3.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:e795b7eb908249c4e43c7c99fac7c2c75dab0c43566e37db472a355f63693d71"}, + {file = "pillow-12.3.0-cp315-cp315-win32.whl", hash = "sha256:57b3d78c95ba9059768b10e28b813002261d3f3dfc55cc48b0c988f625175827"}, + {file = "pillow-12.3.0-cp315-cp315-win_amd64.whl", hash = "sha256:fa4ecea169a355be7a3ade2c783e2ed12f0e40d2c5621cda8b3297faf7fbb9f5"}, + {file = "pillow-12.3.0-cp315-cp315-win_arm64.whl", hash = "sha256:877c3f311ff35410f690861c4409e7ccbf0cd2f878e50628a28e5a0bb689e658"}, + {file = "pillow-12.3.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:e9871b1ffbfa9656b60aeee92ed5136a5742696006fa322b29ea3d8da0ecc9cf"}, + {file = "pillow-12.3.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:53aa02d20d10c3d814d536aa4e5ac9b84ca0ff5a88377963b085ad6822f93e64"}, + {file = "pillow-12.3.0-cp315-cp315t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:446c34dcc4324b084a53b705127dc15717b22c5e140ae0a3c38349d4efec071e"}, + {file = "pillow-12.3.0-cp315-cp315t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf1845d02ad822a369a49f2bb9345b1614744267682e7a03527dc3bf6eea1777"}, + {file = "pillow-12.3.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:186941b6aef820ad110fb01fb06eb925374dc3a21b17e37ec9a53b250c6fe2d1"}, + {file = "pillow-12.3.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:f13c32a3abd6079a66d9526e18dad9b6d280384d49d7c54040cd57b6424041d9"}, + {file = "pillow-12.3.0-cp315-cp315t-win32.whl", hash = "sha256:1657923d2d45afb66526e5b933e5b3052e6bdea196c90d3abb2424e18c77dae8"}, + {file = "pillow-12.3.0-cp315-cp315t-win_amd64.whl", hash = "sha256:8cd2f7bdda092d99c9fc2fb7391354f306d01443d22785d0cbfafa2e2c8bb418"}, + {file = "pillow-12.3.0-cp315-cp315t-win_arm64.whl", hash = "sha256:06ff022112bc9cbf83b60f8e028d94ad87b60621706487e65f673de61610ab59"}, + {file = "pillow-12.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b3c777e849237620b022f7f297dd67705f9f5cf1685f09f02e46f93e92725468"}, + {file = "pillow-12.3.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:b343699e8308bdc51978310e1c959c584e7869cc8c40780058c87da7781a1e94"}, + {file = "pillow-12.3.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbd139c8447d25dd750ab79ee274cc5e1fe80fc56340ab10b18a195e1b6eca3e"}, + {file = "pillow-12.3.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e7e480451b9fa137494bccd3a7d69adbe8ac65a87d97be61e11f1b1050a5bac3"}, + {file = "pillow-12.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:04f01d28a6aaff387bf842a13be313df23ba0597a44f1a976c9feb3c6ff4711a"}, + {file = "pillow-12.3.0.tar.gz", hash = "sha256:3b8182a766685eaa002637e28b4ec8d6b18819a0c71f579bf0dbaa5830297cce"}, +] + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=8.2)", "sphinx-autobuild", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] +fpx = ["olefile"] +mic = ["olefile"] +test-arrow = ["arro3-compute", "arro3-core", "nanoarrow", "pyarrow"] +tests = ["coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "setuptools", "trove-classifiers (>=2024.10.12)"] +xmp = ["defusedxml"] + +[metadata] +lock-version = "2.0" +python-versions = "^3.14" +content-hash = "861413ca674bcc3b80d3b03748db7bebdae031b99d857609fe5c5002482f35a9" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..a0681c4 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,15 @@ +[tool.poetry] +name = "2026-image-halftone-effect" +version = "0.1.0" +description = "" +authors = ["erjemin "] +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.14" +pillow = "^12.3.0" + + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api"