Spaces:
Sleeping
Sleeping
Download effects.py from wisamWR/ditherforge-api: direct link, hf CLI and curl.
- Browser
- Download file 2.71 kB
-
https://huggingface.co/spaces/wisamWR/ditherforge-api/resolve/main/effects.py
- Command line
-
hf download hf://spaces/wisamWR/ditherforge-api/effects.py
-
curl -L -o effects.py https://huggingface.co/spaces/wisamWR/ditherforge-api/resolve/main/effects.py
2.71 kB
| """Pure-Python ports of DitherForge core text effects.""" | |
| from __future__ import annotations | |
| import numpy as np | |
| from PIL import Image | |
| DEFAULT_ASCII_CHARSET = " .:-=+*#%@" | |
| BRAILLE_BASE = 0x2800 | |
| DOT_BITS = [ | |
| [0x01, 0x08], | |
| [0x02, 0x10], | |
| [0x04, 0x20], | |
| [0x40, 0x80], | |
| ] | |
| def image_to_gray(img: Image.Image) -> np.ndarray: | |
| """Convert PIL Image to 2D grayscale numpy array (0-255).""" | |
| return np.array(img.convert("L"), dtype=np.uint8) | |
| def binary_effect(gray: np.ndarray, cols: int = 80, threshold: int = 128) -> str: | |
| """Convert grayscale image to binary (0/1) text.""" | |
| h, w = gray.shape | |
| cols = max(1, min(cols, w)) | |
| block_w = w / cols | |
| block_h = block_w * 2 | |
| rows = max(1, int(h / block_h)) | |
| lines = [] | |
| for row in range(rows): | |
| line = "" | |
| for col in range(cols): | |
| x0 = int(col * block_w) | |
| x1 = int((col + 1) * block_w) | |
| y0 = int(row * block_h) | |
| y1 = min(int((row + 1) * block_h), h) | |
| avg = gray[y0:y1, x0:x1].mean() | |
| line += "1" if avg >= threshold else "0" | |
| lines.append(line) | |
| return "\n".join(lines) | |
| def ascii_effect( | |
| gray: np.ndarray, cols: int = 80, charset: str = DEFAULT_ASCII_CHARSET | |
| ) -> str: | |
| """Convert grayscale image to ASCII art.""" | |
| h, w = gray.shape | |
| cols = max(1, min(cols, w)) | |
| block_w = w / cols | |
| block_h = block_w * 2 | |
| rows = max(1, int(h / block_h)) | |
| lines = [] | |
| for row in range(rows): | |
| line = "" | |
| for col in range(cols): | |
| x0 = int(col * block_w) | |
| x1 = int((col + 1) * block_w) | |
| y0 = int(row * block_h) | |
| y1 = min(int((row + 1) * block_h), h) | |
| avg = gray[y0:y1, x0:x1].mean() | |
| idx = min(int((avg / 255) * len(charset)), len(charset) - 1) | |
| line += charset[idx] | |
| lines.append(line) | |
| return "\n".join(lines) | |
| def braille_effect( | |
| gray: np.ndarray, cols: int = 40, threshold: int = 128 | |
| ) -> str: | |
| """Convert grayscale image to Unicode braille art.""" | |
| h, w = gray.shape | |
| cols = max(1, min(cols, w // 2)) | |
| pix_w = cols * 2 | |
| scale = w / pix_w | |
| pix_h = int(h / scale) | |
| rows = max(1, pix_h // 4) | |
| lines = [] | |
| for row in range(rows): | |
| line = "" | |
| for col in range(cols): | |
| cp = 0 | |
| for dy in range(4): | |
| for dx in range(2): | |
| sx = min(int((col * 2 + dx) * scale), w - 1) | |
| sy = min(int((row * 4 + dy) * scale), h - 1) | |
| if gray[sy, sx] < threshold: | |
| cp |= DOT_BITS[dy][dx] | |
| line += chr(BRAILLE_BASE + cp) | |
| lines.append(line) | |
| return "\n".join(lines) | |