first commit
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
"""
|
||||
this is a minimal jpg/png->xpm converter
|
||||
so that you can make your pets with almost
|
||||
any program and convert it to xpm later
|
||||
"""
|
||||
|
||||
from PIL import Image
|
||||
from typing import Any
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
|
||||
def symbol_from_output(path: str) -> str:
|
||||
base = os.path.splitext(os.path.basename(path))[0]
|
||||
# e.g., idle_0 -> xpm_idle_0
|
||||
clean = re.sub(r'[^a-zA-Z0-9_]', '_', base)
|
||||
if not clean:
|
||||
clean = "img"
|
||||
return f"xpm_{clean}"
|
||||
|
||||
def toxpm(input_path):
|
||||
output_path = sys.argv[2] if len(sys.argv) >= 3 else "img.xpm"
|
||||
symbol = symbol_from_output(output_path)
|
||||
|
||||
image = Image.open(input_path).convert("RGBA")
|
||||
image = image.quantize(256).convert("RGBA") # xpm needs 256colours
|
||||
width = image.size[0]
|
||||
height = image.size[1]
|
||||
pixels: Any = image.load()
|
||||
|
||||
colors = {}
|
||||
next_char = 33 # start printable ascii
|
||||
|
||||
def next_symbol():
|
||||
nonlocal next_char
|
||||
while True:
|
||||
char = chr(next_char)
|
||||
next_char += 1
|
||||
if char in ['"', "'", '\\']:
|
||||
continue
|
||||
break
|
||||
return char
|
||||
|
||||
pixmap = []
|
||||
for y in range(height):
|
||||
row = []
|
||||
for x in range(width):
|
||||
rgba = pixels[x, y]
|
||||
if rgba[3] < 128:
|
||||
rgba = (0, 0, 0, 0)
|
||||
if rgba not in colors:
|
||||
colors[rgba] = next_symbol()
|
||||
row.append(colors[rgba])
|
||||
pixmap.append("".join(row))
|
||||
|
||||
with open(output_path, "w") as f:
|
||||
# writing c
|
||||
f.write("/* xpm */\n")
|
||||
f.write(f"static const char* {symbol}[] = {{\n")
|
||||
f.write(f"\"{width} {height} {len(colors)} 1\",\n")
|
||||
|
||||
for rgba, sym in colors.items():
|
||||
if rgba[3] == 0:
|
||||
f.write(f"\"{sym} c None\",\n")
|
||||
else:
|
||||
f.write(f"\"{sym} c #{rgba[0]:02x}{rgba[1]:02x}{rgba[2]:02x}\",\n")
|
||||
|
||||
for y, row in enumerate(pixmap):
|
||||
line_end = "," if y < height - 1 else ""
|
||||
f.write(f"\"{row}\"{line_end}\n")
|
||||
|
||||
f.write("};\n")
|
||||
|
||||
print(f"saved xpm: {output_path} (symbol: {symbol})")
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print("usage: toxpm.py <input.(jpg/png)> [output.xpm]")
|
||||
sys.exit(1)
|
||||
|
||||
toxpm(sys.argv[1])
|
||||
Reference in New Issue
Block a user