119 lines
3.5 KiB
C#
119 lines
3.5 KiB
C#
using System;
|
|
using System.Globalization;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using System.Windows;
|
|
using System.Windows.Media;
|
|
using System.Windows.Shapes;
|
|
using HandyControl.Controls;
|
|
|
|
namespace HandyControl.Tools
|
|
{
|
|
public class GithubGravatarGenerator : IGravatarGenerator
|
|
{
|
|
private const int RenderDataMaxLength = 15;
|
|
|
|
public object GetGravatar(string id)
|
|
{
|
|
var hashcode = GetHashCode(id);
|
|
var renderData = GetRenderData(hashcode);
|
|
var renderBrush = GetRenderBrush(hashcode);
|
|
var geometryGroup = new GeometryGroup();
|
|
|
|
void AddRec(int i, int j, bool hidden = false)
|
|
{
|
|
var rec = new RectangleGeometry(new Rect(new Point(i, j), hidden ? new Size() : new Size(1, 1)));
|
|
geometryGroup.Children.Add(rec);
|
|
}
|
|
|
|
var index = 0;
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
for (int j = 0; j < 5; j++, index++)
|
|
{
|
|
AddRec(i, j, renderData[index] == 0);
|
|
}
|
|
}
|
|
|
|
for (int j = 0; j < 5; j++, index++)
|
|
{
|
|
AddRec(2, j, renderData[index] == 0);
|
|
}
|
|
|
|
index -= 10;
|
|
for (int i = 3; i < 5; i++)
|
|
{
|
|
for (int j = 0; j < 5; j++, index++)
|
|
{
|
|
AddRec(i, j, renderData[index] == 0);
|
|
}
|
|
index -= 10;
|
|
}
|
|
|
|
var path = new Path
|
|
{
|
|
Data = geometryGroup,
|
|
Fill = renderBrush,
|
|
VerticalAlignment = VerticalAlignment.Top
|
|
};
|
|
|
|
RenderOptions.SetEdgeMode(path, EdgeMode.Aliased);
|
|
|
|
return path;
|
|
}
|
|
|
|
private string GetHashCode(string id)
|
|
{
|
|
var md5 = MD5.Create();
|
|
var bytes = Encoding.ASCII.GetBytes(id);
|
|
var hash = md5.ComputeHash(bytes);
|
|
var stringBuilder = new StringBuilder();
|
|
foreach (var item in hash)
|
|
{
|
|
stringBuilder.Append(item.ToString("X2"));
|
|
}
|
|
return stringBuilder.ToString();
|
|
}
|
|
|
|
private int[] GetRenderData(string hashcode)
|
|
{
|
|
var arr = new int[RenderDataMaxLength];
|
|
for (int i = 0; i < RenderDataMaxLength; i++)
|
|
{
|
|
var c = hashcode[i];
|
|
var v = (int) c;
|
|
arr[i] = v % 2;
|
|
}
|
|
|
|
return arr;
|
|
}
|
|
|
|
private Brush GetRenderBrush(string hashcode)
|
|
{
|
|
var v = (double)int.Parse(hashcode.Substring(hashcode.Length - 7), NumberStyles.HexNumber);
|
|
var scale = v / 0xfffffff;
|
|
var color = Hsl2Rgb(scale);
|
|
return new SolidColorBrush(color);
|
|
}
|
|
|
|
//adapted from https://github.com/stewartlord/identicon.js/blob/4fad7cafec1b7a4d896015e084e861625ef5d64f/identicon.js#L110
|
|
private Color Hsl2Rgb(double h, double s = 0.7, double b = 0.5)
|
|
{
|
|
h *= 6;
|
|
var arr = new[]
|
|
{
|
|
b += s *= b < .5 ? b : 1 - b,
|
|
b - h % 1 * s * 2,
|
|
b -= s *= 2,
|
|
b,
|
|
b + h % 1 * s,
|
|
b + s
|
|
};
|
|
|
|
var hValue = (int) Math.Floor(h);
|
|
|
|
return Color.FromRgb((byte) (arr[hValue % 6] * 255), (byte) (arr[(hValue | 16) % 6] * 255),
|
|
(byte) (arr[(hValue | 8) % 6] * 255));
|
|
}
|
|
}
|
|
} |