SALAH 0.2: prayer times for Casablanca (Morocco method), chord-tapered round layout

This commit is contained in:
2026-09-09 17:12:23 +01:00
commit e86921d966
14 changed files with 10982 additions and 0 deletions
+65
View File
@@ -0,0 +1,65 @@
#!/usr/bin/env python3
"""Convert the user-supplied mosque icon art to a 192x192 RGB Vela app icon.
Proven pipeline (from the sundial v0.5 icon): detect the round disc bounds on the
mid row/column of the dark-square source, crop square around disc center, apply an
anti-aliased circular alpha mask (drawn at 4x, LANCZOS down), resize to 192x192,
flatten to RGB over the dark background color.
"""
from PIL import Image, ImageDraw
SRC = "/home/iliasmohuchine/Downloads/ChatGPT Image Sep 9, 2026, 04_42_51 PM.png"
OUT = "/home/iliasmohuchine/vela-salah/src/common/icon.png"
im = Image.open(SRC).convert("RGB")
w, h = im.size
print("source:", im.size)
# detect disc bounds on mid row / mid column (background ~ rgb(17,17,24) dark)
px = im.load()
midy, midx = h // 2, w // 2
BG = px[2, 2]
print("bg color:", BG)
def is_fg(p):
return abs(p[0] - BG[0]) + abs(p[1] - BG[1]) + abs(p[2] - BG[2]) > 40
row = [x for x in range(w) if is_fg(px[x, midy])]
col = [y for y in range(h) if is_fg(px[midx, y])]
left, right = min(row), max(row)
top, bottom = min(col), max(col)
print("disc bounds: x", left, right, " y", top, bottom)
# square crop around disc center, sized to the larger span
cx, cy = (left + right) / 2, (top + bottom) / 2
span = max(right - left, bottom - top)
half = span / 2 + 2
box = (int(cx - half), int(cy - half), int(cx + half), int(cy + half))
disc = im.crop(box)
print("crop box:", box, "disc size:", disc.size)
# circular alpha mask at 4x
size = disc.size[0]
mask = Image.new("L", (size * 4, size * 4), 0)
d = ImageDraw.Draw(mask)
d.ellipse((0, 0, size * 4 - 1, size * 4 - 1), fill=255)
mask = mask.resize((size, size), Image.LANCZOS)
out = disc.convert("RGBA")
out.putalpha(mask)
out = out.resize((192, 192), Image.LANCZOS)
# flatten to RGB over dark bg
bg = Image.new("RGB", (192, 192), BG)
bg.paste(out, (0, 0), out)
bg.save(OUT, "PNG")
print("saved", OUT, bg.size, bg.mode)
# side-by-side montage for preview: source | converted
src_small = im.copy()
src_small.thumbnail((192, 192))
mont = Image.new("RGB", (192 * 2 + 24, 192), (17, 17, 24))
mont.paste(src_small, (0, 0))
mont.paste(bg, (192 + 24, 0))
mont.save("/home/iliasmohuchine/vela-salah/icon-preview.png")
print("montage saved")