icons: ship the leather mark, with a simplified version for tab size
Christian's leather patch art is the app icon at 180px and up. It cannot be the favicon: leather grain and stitching turn to mud below 48px, and the pulse is black on brown, which is not enough contrast in a tab bar. So the set is two-tier. Sizes 180 and above come from the leather art; 16, 32, 48 and the .ico come from a flat source whose spike geometry was measured off the original (left tail at 52% height, peak at 42% width, trough at 54%, right tail at 84%). Same colours sampled from the leather body, so the small mark reads as the same object rather than a different logo. make_icons.py gained --small-from for this: one command builds both tiers. Signed-off-by: Christian Sass <csass@binaryranch.com>
BIN
icons/favicon.ico
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
BIN
icons/icon-1024.png
Normal file
|
After Width: | Height: | Size: 2.2 MiB |
BIN
icons/icon-16.png
Normal file
|
After Width: | Height: | Size: 702 B |
BIN
icons/icon-180.png
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
icons/icon-256.png
Normal file
|
After Width: | Height: | Size: 157 KiB |
BIN
icons/icon-32.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
icons/icon-48.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
icons/icon-512.png
Normal file
|
After Width: | Height: | Size: 650 KiB |
6
icons/source-flat.svg
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="1024" height="1024" viewBox="0 0 1024 1024">
|
||||||
|
<rect width="1024" height="1024" rx="224" fill="#583828"/>
|
||||||
|
<path d="M164 533 H352 L433 200 L540 840 L655 533 H859"
|
||||||
|
fill="none" stroke="#f0ede8" stroke-width="74"
|
||||||
|
stroke-linecap="square" stroke-linejoin="miter"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 330 B |
BIN
icons/source-leather.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
6
icons/source-small.svg
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="1024" height="1024" viewBox="0 0 1024 1024">
|
||||||
|
<rect width="1024" height="1024" rx="224" fill="#583828"/>
|
||||||
|
<path d="M180 520 H420 L512 250 L604 790 L700 520 H844"
|
||||||
|
fill="none" stroke="#f0ede8" stroke-width="132"
|
||||||
|
stroke-linecap="square" stroke-linejoin="miter"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 331 B |
|
|
@ -61,21 +61,29 @@ def main():
|
||||||
ap = argparse.ArgumentParser()
|
ap = argparse.ArgumentParser()
|
||||||
ap.add_argument("source", help="square-ish .svg or .png/.jpg mark")
|
ap.add_argument("source", help="square-ish .svg or .png/.jpg mark")
|
||||||
ap.add_argument("--out-dir", default="icons")
|
ap.add_argument("--out-dir", default="icons")
|
||||||
|
ap.add_argument("--small-from", default="",
|
||||||
|
help="optional simpler source used for 16/32/48 and the .ico, "
|
||||||
|
"because fine detail dies at tab size")
|
||||||
|
ap.add_argument("--small-max", type=int, default=48)
|
||||||
args = ap.parse_args()
|
args = ap.parse_args()
|
||||||
|
|
||||||
if not os.path.exists(args.source):
|
if not os.path.exists(args.source):
|
||||||
sys.exit(f"no such file: {args.source}")
|
sys.exit(f"no such file: {args.source}")
|
||||||
|
|
||||||
master = load_square(args.source)
|
master = load_square(args.source)
|
||||||
|
small = load_square(args.small_from) if args.small_from else None
|
||||||
os.makedirs(args.out_dir, exist_ok=True)
|
os.makedirs(args.out_dir, exist_ok=True)
|
||||||
for size in SIZES:
|
for size in SIZES:
|
||||||
|
src = small if (small and size <= args.small_max) else master
|
||||||
out = os.path.join(args.out_dir, f"icon-{size}.png")
|
out = os.path.join(args.out_dir, f"icon-{size}.png")
|
||||||
master.resize((size, size), RESAMPLE).save(out)
|
src.resize((size, size), RESAMPLE).save(out)
|
||||||
print(f" {out}")
|
print(f" {out}{' (simplified)' if src is small else ''}")
|
||||||
|
|
||||||
ico_path = os.path.join(args.out_dir, "favicon.ico")
|
ico_path = os.path.join(args.out_dir, "favicon.ico")
|
||||||
master.resize((256, 256), RESAMPLE).save(ico_path, sizes=[(s, s) for s in ICO_SIZES])
|
(small or master).resize((256, 256), RESAMPLE).save(
|
||||||
print(f" {ico_path} ({', '.join(str(s) for s in ICO_SIZES)})")
|
ico_path, sizes=[(s, s) for s in ICO_SIZES])
|
||||||
|
print(f" {ico_path} ({', '.join(str(s) for s in ICO_SIZES)})"
|
||||||
|
f"{' (simplified)' if small else ''}")
|
||||||
|
|
||||||
print(f"\n{len(SIZES) + 1} files in {args.out_dir}/")
|
print(f"\n{len(SIZES) + 1} files in {args.out_dir}/")
|
||||||
print("upload icon-512.png as the org avatar on both forges; the rest ship with the app")
|
print("upload icon-512.png as the org avatar on both forges; the rest ship with the app")
|
||||||
|
|
|
||||||