126 lines
3.9 KiB
Python
126 lines
3.9 KiB
Python
|
from PIL import Image, ImageOps, ImageDraw, ImageChops
|
||
|
from io import BytesIO
|
||
|
from glob import glob
|
||
|
import numpy as np
|
||
|
import base64
|
||
|
import os
|
||
|
|
||
|
def base64_to_img(base64_bytes: bytes) -> Image:
|
||
|
img_bytes = base64.b64decode(base64_bytes)
|
||
|
img_buffer = BytesIO(img_bytes)
|
||
|
img = Image.open(img_buffer)
|
||
|
img = img.convert("RGBA")
|
||
|
return img
|
||
|
|
||
|
def img_to_array(img: Image) -> np.array:
|
||
|
img_array = np.array(img)
|
||
|
return img_array
|
||
|
|
||
|
def avg_colors(img):
|
||
|
img_array = img_to_array(img)
|
||
|
colors, count = np.unique(img_array.reshape(-1,img_array.shape[-1]), axis=0, return_counts=True)
|
||
|
|
||
|
return tuple(colors[count.argmax()])
|
||
|
|
||
|
|
||
|
def add_background(img: Image, bg_tuple: tuple) -> Image:
|
||
|
bg = Image.new("RGBA", img.size, bg_tuple)
|
||
|
bg.paste(img, (0, 0), img)
|
||
|
return bg
|
||
|
|
||
|
def crop_to_circle(im, template):
|
||
|
im = im.copy()
|
||
|
bigsize = (im.size[0] * 3, im.size[1] * 3)
|
||
|
mask = Image.new('L', bigsize, 0)
|
||
|
ImageDraw.Draw(mask).ellipse((0, 0) + bigsize, fill=255)
|
||
|
midsize = tuple(x//2 for x in bigsize)
|
||
|
if template[0] == 1:
|
||
|
ImageDraw.Draw(mask).rectangle((0, 0) + midsize, fill=255)
|
||
|
if template[1] == 1:
|
||
|
ImageDraw.Draw(mask).rectangle((midsize[0], 0, bigsize[0], midsize[1]), fill=255)
|
||
|
if template[2] == 1:
|
||
|
ImageDraw.Draw(mask).rectangle((0, midsize[1], midsize[1], bigsize[1]), fill=255)
|
||
|
if template[3] == 1:
|
||
|
ImageDraw.Draw(mask).rectangle(midsize + bigsize, fill=255)
|
||
|
mask = mask.resize(im.size, Image.ANTIALIAS)
|
||
|
mask = ImageChops.darker(mask, im.split()[-1])
|
||
|
im.putalpha(mask)
|
||
|
return im
|
||
|
|
||
|
def parse_file(desktop_path):
|
||
|
output = {}
|
||
|
with open(desktop_path, "r") as f:
|
||
|
for line in f:
|
||
|
if not line:
|
||
|
continue
|
||
|
if line.startswith("["):
|
||
|
continue
|
||
|
key, value = line.split("=", 1)
|
||
|
output[key] = value.strip()
|
||
|
output["path"] = desktop_path
|
||
|
return output
|
||
|
|
||
|
def deparse_file(app):
|
||
|
output = ["[Desktop Entry]"]
|
||
|
for key, value in app.items():
|
||
|
output.append(f"{key}={value}")
|
||
|
return "\n".join(output)
|
||
|
|
||
|
def get_web_icons():
|
||
|
path = os.path.join(
|
||
|
os.path.expanduser("~"),
|
||
|
".local",
|
||
|
"share",
|
||
|
"applications",
|
||
|
"sailfish-browser*.desktop"
|
||
|
)
|
||
|
return glob(path)
|
||
|
|
||
|
def sailify(raw_str, pattern):
|
||
|
base64_bytes = raw_str.replace("data:image/png;base64,", "", 1).encode()
|
||
|
img = base64_to_img(base64_bytes)
|
||
|
bg_tuple = avg_colors(img)
|
||
|
img = add_background(img, bg_tuple)
|
||
|
img = crop_to_circle(img, pattern)
|
||
|
output_buffer = BytesIO()
|
||
|
img.save(output_buffer, format="PNG")
|
||
|
output_data = output_buffer.getvalue()
|
||
|
output_base64 = base64.b64encode(output_data)
|
||
|
return "data:image/png;base64," + output_base64.decode()
|
||
|
|
||
|
def main():
|
||
|
import shutil
|
||
|
|
||
|
while True:
|
||
|
apps = get_web_icons()
|
||
|
apps = list(map(parse_file, apps))
|
||
|
while True:
|
||
|
for n, app in enumerate(apps):
|
||
|
print(f"{n}) {app['Name']}")
|
||
|
index = input("select an application (the index):\n>>> ")
|
||
|
index = int(index)
|
||
|
if index >= len(apps):
|
||
|
print("Select a valid index")
|
||
|
continue
|
||
|
break
|
||
|
app = apps[index]
|
||
|
while True:
|
||
|
pattern = input("Enter the pattern (0 = round, 1 = peak):\n>>> ")
|
||
|
if len(pattern) != 4:
|
||
|
print("it is necessary to enter 4 characters")
|
||
|
pattern = tuple(map(int, pattern))
|
||
|
new_icon = sailify(app.get("old_icon", app["Icon"]), pattern)
|
||
|
# Backup the original .desktop
|
||
|
shutil.copyfile(app["path"], app["path"] + "_backup")
|
||
|
app["old_icon"] = app.get("old_icon", app["Icon"])
|
||
|
app["Icon"] = new_icon
|
||
|
new_content = deparse_file(app)
|
||
|
with open(app["path"], "w") as f:
|
||
|
f.write(new_content)
|
||
|
print(f"{app['Name']} sailified correctly")
|
||
|
break
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
main()
|