Files

107 lines
3.2 KiB
Python

#!/usr/bin/env python3
"""Quick ASCII art generator from images.
Usage:
python ascii_tool.py test # Run self-test
python ascii_tool.py <image_file> [width] # Convert local image
Produces ASCII art output saved to output_ascii.txt
"""
import sys
from PIL import Image
ASCII_CHARS = "@%#*+=-:. "
def resize_image(img: Image.Image, new_width: int = 80) -> Image.Image:
"""Resize image maintaining aspect ratio."""
w, h = img.size
aspect_ratio = h / w
new_height = int(aspect_ratio * new_width * 0.55)
return img.resize((new_width, max(1, new_height)))
def image_to_ascii(img: Image.Image, width: int = 80) -> str:
"""Convert PIL Image to ASCII art string."""
img = resize_image(img, width)
img = img.convert("L")
# Use get_flattened_data for Pillow 11+, fallback to getdata()
try:
pixels = list(img.get_flattened_data())
except AttributeError:
pixels = list(img.getdata())
chars_per_pixel = len(ASCII_CHARS)
lines = []
row = []
for i, pixel in enumerate(pixels):
if i > 0 and (i % width) == 0:
lines.append("".join(row))
row = []
idx = min(pixel * (chars_per_pixel - 1) // 255, chars_per_pixel - 1)
row.append(ASCII_CHARS[idx])
if row:
lines.append("".join(row))
return "\n".join(lines)
def run_self_test():
"""Create test image and verify ASCII conversion works."""
# Create a simple 20x20 test image with a gradient
img = Image.new("RGB", (20, 20))
pixels = img.load()
for x in range(20):
for y in range(20):
# Create a diagonal gradient
val = int((x + y) * 255 / 40)
pixels[x, y] = (val, val, val)
ascii_result = image_to_ascii(img, 40)
lines = ascii_result.split("\n")
print(f"Self-test: Created 20x20 gradient image")
print(f"ASCII result: {len(lines)} lines")
print(f"First line: '{lines[0][:20]}...'")
print(f"Line lengths vary: {set(len(l) for l in lines)} chars")
# Verify output is saved
output_path = "/root/.hermes/wizard-outputs/spark/output_ascii.txt"
with open(output_path, "w") as f:
f.write(ascii_result)
print(f"Saved to {output_path}")
# Verify file exists
with open(output_path) as f:
verify = f.read()
if verify == ascii_result:
print("VERIFICATION: File written correctly")
return True
else:
print("ERROR: File content mismatch")
return False
def main():
if len(sys.argv) < 2:
print(__doc__)
sys.exit(1)
if sys.argv[1] == "test":
success = run_self_test()
sys.exit(0 if success else 1)
# Convert local image file
img_path = sys.argv[1]
width = int(sys.argv[2]) if len(sys.argv) > 2 else 80
print(f"Loading {img_path}...")
img = Image.open(img_path)
print(f"Original size: {img.size}, converting to ASCII (width={width})...")
ascii_art = image_to_ascii(img, width)
print(ascii_art)
output_path = "/root/.hermes/wizard-outputs/spark/output_ascii.txt"
with open(output_path, "w") as f:
f.write(ascii_art)
print(f"\nSaved to {output_path}")
if __name__ == "__main__":
main()