96 lines
3.3 KiB
Python
96 lines
3.3 KiB
Python
import os
|
|
import zlib
|
|
import struct
|
|
|
|
def write_png(buf, width, height, path):
|
|
# Reverse the rows for top-down processing if needed, but standard is top-down
|
|
# Simple grayscale + alpha: Type 6 (Truecolor with Alpha) is easiest or Type 4 (Grayscale with Alpha) because we want specific colors.
|
|
# We will use RGBA (Type 6).
|
|
|
|
# Signature
|
|
png = b'\x89PNG\r\n\x1a\n'
|
|
|
|
# IHDR
|
|
ihdr = struct.pack("!I", width) + struct.pack("!I", height) + b'\x08\x06\x00\x00\x00'
|
|
png += struct.pack("!I", len(ihdr)) + b'IHDR' + ihdr + struct.pack("!I", zlib.crc32(b'IHDR' + ihdr))
|
|
|
|
# IDAT
|
|
# 8-bit depth, RGBA.
|
|
# Filter type 0 (None) for each scanline.
|
|
raw_data = b''
|
|
for y in range(height):
|
|
raw_data += b'\x00' # Filter type 0
|
|
for x in range(width):
|
|
# Get pixel from buf
|
|
curr = buf[y][x] # (r, g, b, a)
|
|
raw_data += struct.pack("BBBB", *curr)
|
|
|
|
compressed = zlib.compress(raw_data)
|
|
png += struct.pack("!I", len(compressed)) + b'IDAT' + compressed + struct.pack("!I", zlib.crc32(b'IDAT' + compressed))
|
|
|
|
# IEND
|
|
png += struct.pack("!I", 0) + b'IEND' + struct.pack("!I", zlib.crc32(b'IEND'))
|
|
|
|
with open(path, 'wb') as f:
|
|
f.write(png)
|
|
|
|
def hex_to_rgba(hex_str, alpha=255):
|
|
h = hex_str.lstrip('#')
|
|
return tuple(int(h[i:i+2], 16) for i in (0, 2, 4)) + (alpha,)
|
|
|
|
def create_icons():
|
|
base_dir = r"g:\Works\YouleGames\codes\minipro\calculation\miniprogram\assets\tabs"
|
|
if not os.path.exists(base_dir):
|
|
os.makedirs(base_dir)
|
|
|
|
size = 64
|
|
|
|
# Colors
|
|
c_inactive = hex_to_rgba('#999999')
|
|
c_active = hex_to_rgba('#11616B')
|
|
c_transparent = (0, 0, 0, 0)
|
|
|
|
# Icon 1: Tools (Grid/Square)
|
|
# ---------------------------
|
|
def draw_tools(color):
|
|
grid = [[c_transparent for _ in range(size)] for _ in range(size)]
|
|
margin = 12
|
|
for y in range(margin, size-margin):
|
|
for x in range(margin, size-margin):
|
|
# Border
|
|
if x < margin+4 or x > size-margin-5 or y < margin+4 or y > size-margin-5:
|
|
grid[y][x] = color
|
|
# Inner cross/plus
|
|
elif size//2 - 2 <= x <= size//2 + 1 or size//2 - 2 <= y <= size//2 + 1:
|
|
grid[y][x] = color
|
|
return grid
|
|
|
|
# Icon 2: Profile (Circle/Person)
|
|
# -------------------------------
|
|
def draw_profile(color):
|
|
grid = [[c_transparent for _ in range(size)] for _ in range(size)]
|
|
cx, cy = size//2, size//2
|
|
r_head = 10
|
|
r_body = 20
|
|
|
|
for y in range(size):
|
|
for x in range(size):
|
|
# Head
|
|
if (x-cx)**2 + (y-(cy-10))**2 <= r_head**2:
|
|
grid[y][x] = color
|
|
# Body (arch)
|
|
elif (x-cx)**2 + (y-(cy+15))**2 <= r_body**2 and y > cy:
|
|
grid[y][x] = color
|
|
return grid
|
|
|
|
write_png(draw_tools(c_inactive), size, size, os.path.join(base_dir, "tool.png"))
|
|
write_png(draw_tools(c_active), size, size, os.path.join(base_dir, "tool-active.png"))
|
|
|
|
write_png(draw_profile(c_inactive), size, size, os.path.join(base_dir, "user.png"))
|
|
write_png(draw_profile(c_active), size, size, os.path.join(base_dir, "user-active.png"))
|
|
|
|
print("Icons created successfully.")
|
|
|
|
if __name__ == '__main__':
|
|
create_icons()
|