Skip to content

Instantly share code, notes, and snippets.

@lkluft
Last active November 9, 2021 10:32
Show Gist options
  • Save lkluft/2c1279aa18f10373c19fa76b38df7e31 to your computer and use it in GitHub Desktop.
Save lkluft/2c1279aa18f10373c19fa76b38df7e31 to your computer and use it in GitHub Desktop.
Create GitHub-style dark-theme identicons
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(<Figure size 320x320 with 1 Axes>, <AxesSubplot:>)"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAARYAAAEWCAYAAACjTbhPAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/MnkTPAAAACXBIWXMAAAexAAAHsQEGxWGGAAAD5ElEQVR4nO3WsY2DQBRF0WXlCiZ1Da7PNVCfa6AONl85vGZkOCcketKIq7+MMfYfgNDv7AHA+QgLkBMWIHd79/F5fx294xDr9pg9gYu7yr/lYgFywgLkhAXICQuQExYgJyxATliAnLAAOWEBcsIC5IQFyAkLkBMWICcsQE5YgJywADlhAXLCAuSEBcgJC5ATFiAnLEBOWICcsAA5YQFywgLkhAXICQuQExYgJyxATliAnLAAOWEBcsIC5IQFyAkLkBMWICcsQE5YgJywADlhAXLCAuSEBcgJC5ATFiAnLEBOWICcsAA5YQFywgLkhAXICQuQExYgt4wx9tkjjvK8v2ZP+Ih1e8yekPNW383FAuSEBcgJC5ATFiAnLEBOWICcsAA5YQFywgLkhAXICQuQExYgJyxATliAnLAAOWEBcsIC5IQFyAkLkBMWICcsQE5YgJywADlhAXLCAuSEBcgJC5ATFiAnLEBOWICcsAA5YQFywgLkhAXICQuQExYgJyxATliAnLAAOWEBcsIC5IQFyAkLkBMWICcsQE5YgJywADlhAXLCAuSEBcgJC5ATFiC3jDH22SOAc3GxADlhAXLCAuSEBcgJC5ATFiAnLEBOWICcsAA5YQFywgLkhAXICQuQExYgJyxATliAnLAAOWEBcsIC5IQFyAkLkBMWICcsQE5YgJywADlhAXLCAuSEBcgJC5ATFiAnLEBOWICcsAA5YQFywgLkhAXICQuQExYgJyxATliAnLAAOWEBcsIC5IQFyAkLkBMWICcsQE5YgJywADlhAXLCAuSEBcgJC5C7vfv4vL+O3nGIdXvMnvARZ3wvb/Vd/r+XiwXICQuQExYgJyxATliAnLAAOWEBcsIC5IQFyAkLkBMWICcsQE5YgJywADlhAXLCAuSEBcgJC5ATFiAnLEBOWICcsAA5YQFywgLkhAXICQuQExYgJyxATliAnLAAOWEBcsIC5IQFyAkLkBMWICcsQE5YgJywADlhAXLCAuSEBcgJC5ATFiAnLEBOWICcsAA5YQFywgLkhAXICQuQExYgJyxATliA3O3dx3V7HL0DLuEq/5aLBcgJC5ATFiAnLEBOWICcsAA5YQFywgLkhAXICQuQExYgJyxATliAnLAAOWEBcsIC5IQFyAkLkBMWICcsQE5YgJywADlhAXLCAuSEBcgJC5ATFiAnLEBOWICcsAA5YQFywgLkhAXICQuQExYgJyxATliAnLAAOWEBcsIC5IQFyAkLkBMWICcsQE5YgJywADlhAXLCAuSEBcgJC5ATFiAnLEBOWIDcMsbYZ48AzsXFAuSEBcgJC5ATFiD3B1esHznhtAquAAAAAElFTkSuQmCC\n",
"text/plain": [
"<Figure size 320x320 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"\"\"\"Create GitHub-style dark-theme identicons\n",
"\n",
"This project is based on the JavaScript implementation by Stewart Lord\n",
"\n",
" https://github.com/stewartlord/identicon.js/blob/master/identicon.js\n",
"\"\"\"\n",
"from hashlib import sha256\n",
"\n",
"import matplotlib as mpl\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"\n",
"\n",
"def plot_avatar(s, saturation=0.8, num=5, width=320):\n",
" \"\"\"Create a dark-themed identicon.\"\"\"\n",
" num = np.clip(num, 3, 10) # limit number of \"pixels\" to a sane range\n",
" hashsum = sha256(s.encode()).hexdigest() # create hash for input string\n",
"\n",
" bg_color = '#121212' # dark background color\n",
" fg_color = mpl.colors.hsv_to_rgb(\n",
" [\n",
" int(hashsum[-7:], 16) % 256 / 256, # hue based on last seven hash digits\n",
" saturation, # saturation\n",
" 0.9, # value\n",
" ]\n",
" ) \n",
" cmap = mpl.colors.ListedColormap([(0, 0, 0, 0), fg_color])\n",
" \n",
" # Fill the icon based on the hash values (odd/even).\n",
" mid = num // 2\n",
" m = np.zeros(num**2)\n",
" for i in range(num * (mid + 1)):\n",
" m[i] = int(hashsum[i], 16) % 2\n",
" m = m.reshape(num, num).T\n",
" m[:, mid:] = m[:, mid-(num+1)%2::-1] # mirror to right half\n",
" \n",
" # Create the actual plot\n",
" fig, ax = plt.subplots(facecolor=bg_color, figsize=(6.4, 6.4))\n",
" fig.set_dpi(width / 6.4)\n",
" ax.axis(\"off\")\n",
" ax.set_position([0.08, 0.08, 0.84, 0.84])\n",
" ax.matshow(m, cmap=cmap)\n",
" \n",
" return fig, ax\n",
"\n",
"\n",
"# for n in range(8):\n",
"plot_avatar(\"rare\")"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(<Figure size 640x640 with 1 Axes>, <AxesSubplot:>)"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 640x640 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 640x640 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"\"\"\"Create GitHub-style dark-theme identicons\n",
"\n",
"This project is based on the JavaScript implementation by Stewart Lord\n",
"\n",
" https://github.com/stewartlord/identicon.js/blob/master/identicon.js\n",
"\"\"\"\n",
"from hashlib import sha256\n",
"\n",
"import matplotlib as mpl\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"\n",
"\n",
"def plot_avatar_circle(s, saturation=0.8, num=5, distort=False, width=320):\n",
" \"\"\"Create a dark-themed identicon.\"\"\"\n",
" num = np.clip(num, 3, 10) # limit number of \"pixels\" to a sane range\n",
" hashsum = sha256(s.encode()).hexdigest() # create hash for input string\n",
"\n",
" bg_color = '#121212' # dark background color\n",
" fg_color = mpl.colors.hsv_to_rgb(\n",
" [\n",
" int(hashsum[-7:], 16) % 256 / 256, # hue based on last seven hash digits\n",
" saturation, # saturation\n",
" 0.9, # value\n",
" ]\n",
" ) \n",
" cmap = mpl.colors.ListedColormap([(0, 0, 0, 0), fg_color])\n",
"\n",
" # Construct parameters for rose based on hashsum\n",
" phi = np.linspace(0, 32 * np.pi, 4*1024)\n",
" n = int(hashsum[1], 16) % 4 + 1\n",
" d = int(hashsum[2], 16) % 3 + 1\n",
" d += int(n == d) # Precent circles (n == d)\n",
" k = n / d\n",
" \n",
" # Add an optional phase shift to one parameter to slightly distort the rose\n",
" # ro create more diversity in the created avatars.\n",
" phi_shift = np.pi / 8 * int(hashsum[3], 16) / 16 if distort else 0\n",
" \n",
" # Create the actual plot\n",
" fig, ax = plt.subplots(facecolor=bg_color, figsize=(6.4, 6.4))\n",
" fig.set_dpi(width / 3.2)\n",
" ax.axis(\"off\")\n",
" ax.set_position([0.08, 0.08, 0.84, 0.84])\n",
" ax.plot(\n",
" np.cos(k * phi) * np.cos(phi),\n",
" np.cos(k * phi + phi_shift) * np.sin(phi),\n",
" linewidth=16,\n",
" color=fg_color,\n",
" )\n",
"\n",
" return fig, ax\n",
"\n",
"\n",
"plot_avatar_circle(\"rare\")\n",
"plot_avatar_circle(\"rare\", distort=True)\n",
"\n",
"# for n in range(8):\n",
"# fig, ax = plot_avatar_circle(f\"rare{n}\")\n",
"# fig.savefig(f\"plots/circle-{n:02d}.png\")\n",
" \n",
"# for n in range(8):\n",
"# fig, ax = plot_avatar_circle(f\"rare{n}\", distort=True)\n",
"# fig.savefig(f\"plots/circle-distort-{n:02d}.png\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.7"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment