Mastering Windows 10 appearance with Python

Using Windows 10 for a while has been a very pleasant experience. Microsoft has succeeded creating a smooth and pleasant user experience thoughout the OS, while it has also managed to unify the user interface of both the desktop and mobile versions. Despite the overall beauty, there is something that still bothers me, and doesn't fit the overall aesthetics. The taskbar icons. So I challenged myself to make them match the accent color and the mobile style (white icons on top of accent colored tile).

To be more clear let's take a look to the final result:

and a closer look...

Requirements

Many metro-style icons can be found throughout the internet. I chose to use the icon set referred below because it offers a huge variety of icons of excellent quality. Copyrights belong to Dakirby309.

Preparation

Before you are able to run anything you have to be sure that you have Python installed alongside with the Pillow library. In this tutorial I worked with Python 2.7.

  1. Install Python
  2. Install Pillow
  3. Download the icon set
Scripting

**Getting the accent color**

Now that we have the icons, we must use Python to replace their background color with the user's current accent color. First things first, let's see how we retrieve that color with Python. In Windows 10 this info is stored within some registry keys. After some searching in the Windows registry I found that the accent color information is stored under the HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Accent path, within the AccentColorMenu key. There is one problem here, the key's value is not a hex code that we can use directly. It has a value offset (an extra ff on the left), and instead of the usual RGB code, colors follow the BGR order. That's a minor problem. So let's write down a Python function that returns the accent color as HEX string. Let's put that inside a create-icons.py file:

from _winreg import *

def getAccentColor():
    """
    Return the Windows 10 accent color used by the user in a HEX format
    """
    #Open the registry
    registry = ConnectRegistry(None,HKEY_CURRENT_USER)
    #Navigate to the key that contains the accent color info
    key = OpenKey(registry, r'SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Accent')
    #Read the value in a REG_DWORD format
    key_value = QueryValueEx(key,'AccentColorMenu')
    #Convert the interger to Hex and remove its offset
    accent_int = key_value[0]
    accent_hex = hex(accent_int+4278190080) #Remove FF offset and convert to HEX again
    accent_hex = str(accent_hex)[4:-1] #Remove prefix and suffix
    #The HEX value was originally in a BGR order, instead of RGB,
    #so we reverse it...
    accent = accent_hex[4:6]+accent_hex[2:4]+accent_hex[0:2]
    return '#'+accent

Processing the icons

Now we must use the accent color we retrieved and change the background color of the icons to that. First of all, let's create an organized structure:

  1. Within your working directory (the one you placed the script above), create an src-icons folder
  2. Choose the icons you want to convert and place them inside that folder. Both .ico and .png formats are compatible

To change the background color of the icons is a very easy process since all of them have the same logic, white content on top of solid color. So we want to isolate the white pixels, and paste them on top of a solid-colored tile. The script must do the following:

  1. Open all icons one by one
  2. Delete the pixels that are not white (or close to white)
  3. Create a fixed sized tile filled with the accent color
  4. Paste the icon on top of the tile
  5. Save to a new file using .ico format

So here is the algorithm in Python (the function above is skipped):

import os
from _winreg import *
from PIL import Image

icons_dir = os.path.dirname(os.path.abspath(__file__)) + '/src-icons'
icon_list = [ f for f in os.listdir(icons_dir) if os.path.isfile(icons_dir+'/'+f) ]

def getAccentColor():
    [...]

#Find the accent color
accent_color = getAccentColor()
#Create the directory that stores the final icons
out_dir = 'out-icons'
if not os.path.exists(out_dir):
    os.makedirs(out_dir)
#Loop through each icon
for icon in icon_list:
    img = Image.open(icons_dir+'/'+icon)
    img = img.convert('RGBA')
    pixels = img.getdata()
    newPixels = []
    for pixel in pixels:
        # if color is "close to white" then add a white pixel there
        total = pixel[0]+pixel[1]+pixel[2]
        if total > 3*250:
            #Average alpha compared to the maximum of 255
            alpha = total/3
            newPixels.append((255, 255, 255, total))
        else:
        	#Fully transparent pixel
            newPixels.append((0, 0, 0, 0))
    img.putdata(newPixels)
    img = img.resize((128,128), Image.ANTIALIAS)
    #Create the solid-colored tile that will be used as background
    final = Image.new('RGBA', (128,128), accent_color)
    final.paste(img,(0,0), img)
    final.save(out_dir+'/'+icon, format='ico')

You are ready to create your own theme-colored icons. Simply run the script by typing python create-icons.py or create a run.bat file that contains that command.

Usage

Now it's time to use what we created. Change your taskbar icons by following these instructions. In order for the changes to take place you have to restart the explorer process or restart your computer. Everytime you change your accent color you have to run the script again (to generate the new icons) but not change the icons of the taskbar apps. I would be perfect if you could schedule the script to run whenever the accent color is changed, but Windows don't provide such an event. Do you have any ideas of how the script could be automated? Feel free to share your ideas with me!