linden-0: extract_grips.py
#!/usr/bin/python
from __future__ import print_function
import sys
import gc
import glob, os
import shutil
import hashlib
import json
from PIL import Image
mirror_names = glob.glob("tiff/*-m.tif")
for m in mirror_names:
im = Image.open(m)
im_mirrored = im.transpose(Image.FLIP_LEFT_RIGHT)
im.save(m.replace("-m.tif", "-l.tif"))
im_mirrored.save(m.replace("-m.tif", "-r.tif"))
FROM_DPI = 1200
TO_DPI_2X = 2 * 80
RATIO_2X = float(TO_DPI_2X) / float(FROM_DPI)
RATIO_1X = RATIO_2X / 2
def print_status(*args):
print(*args, end=" ")
sys.stdout.flush()
def pixIn(b, p):
g = 4
return (((b['x1']-g) < p[0]) and ((b['x2']+g) > p[0]) and ((b['y1']-g) < p[1]) and ((b['y2']+g) > p[1]))
def boxCenter(b):
return { "x": (b['x1']+b['x2'])/2
, "y": ((b['y1']+b['y2'])/2)-1 }
def boxAdd(b, cx, cy):
if b:
b['x1'] = min(b['x1'], cx)
b['x2'] = max(b['x2'], cx)
b['y1'] = min(b['y1'], cy)
b['y2'] = max(b['y2'], cy)
else:
b = {'x1': cx, 'x2': cx, 'y1':cy, 'y2': cy}
return b
def floodFill(im, pix, color, cx, cy, to_color=(0, 0, 0)):
global b
b = None
global queue
queue = [(cx, cy)]
def visit((px, py)):
global b
global queue
try:
p = pix[px, py][:3]
except IndexError:
return
if p == color:
b = boxAdd(b, px, im.size[1] - py)
pix[px, py] = to_color
queue.append((px + 1, py))
queue.append((px - 1, py))
queue.append((px, py + 1))
queue.append((px, py - 1))
while queue:
visit(queue.pop(0))
return b and boxCenter(b)
if not os.path.exists("assets"):
os.makedirs("assets")
art_names = glob.glob("tiff/*.tif")
sources_seen = 0
print("")
print_status("| generating...")
for in_name in art_names:
sources_seen += 1
print_status(": [{} of {}]".format(sources_seen, len(art_names)), in_name, "|")
print_status("h")
with open(in_name, "r") as im_data:
im_hash = hashlib.sha1(im_data.read()).hexdigest()[:16]
print_status("l")
im = Image.open(in_name)
grip_name = os.path.join("assets", "{}.json".format(im_hash))
if os.path.exists(grip_name):
print_status("=")
else:
print_status("g")
root = []
attach = []
pix = im.load()
for cx in range(im.size[0]):
for cy in range(im.size[1]):
p = pix[cx, cy][:3]
if p == (255, 255, 0) or p == (0, 0, 255): # root
to_color = (255, 255, 255, 0) if p[2] == 255 else (0, 0, 0, 255)
root.append(floodFill(im, pix, p, cx, cy, to_color))
print_status("a")
elif p == (255, 0, 0) or p == (0, 255, 0): # attach
to_color = (255, 255, 255, 0) if p[1] == 255 else (0, 0, 0, 255)
attach.append(floodFill(im, pix, p, cx, cy, to_color))
print_status("r")
# scale points to 1x pixel density
for points in (root, attach):
for point in points:
point["x"] = int(point["x"] * RATIO_1X)
point["y"] = int(point["y"] * RATIO_1X)
with open(grip_name, "w") as f:
json.dump({"attach": attach, "root": root and root[0]}, f)
fname = os.path.basename(in_name)
fbarename = os.path.splitext(fname)[0]
for ratio, prefix in ((RATIO_1X, ''), (RATIO_2X, '2x-')):
resized_name = os.path.join("assets", "{}{}.png".format(prefix, fbarename))
print_status("r")
im_resized = im.resize((int(im.size[0] * ratio), int(im.size[1] * ratio)), Image.ANTIALIAS)
im_resized = im_resized.convert('RGBA')
pix_resized = im_resized.load()
# convert white to alpha
for cx in range(im_resized.size[0]):
for cy in range(im_resized.size[1]):
p = pix_resized[cx, cy]
pix_resized[cx, cy] = (0, 0, 0, 255 - (sum(p[:3]) / 3))
print_status("w")
if im_resized.info.has_key("icc_profile"):
del im_resized.info["icc_profile"]
im_resized.save(resized_name, "PNG", optimize=True)
print(".")