Skip to content

Commit

Permalink
Identicons
Browse files Browse the repository at this point in the history
  • Loading branch information
TheArcaneBrony committed Feb 23, 2024
1 parent f69bb51 commit f7bcde9
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 19 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
ArcaneLibs.UsageTest/identicons/
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
Expand Down
88 changes: 69 additions & 19 deletions ArcaneLibs.UsageTest/Program.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// See https://aka.ms/new-console-template for more information

using System.Diagnostics;
using System.Drawing;
using ArcaneLibs;
using ArcaneLibs.Collections;
Expand Down Expand Up @@ -48,23 +49,72 @@
Console.WriteLine(Util.GetCommandOutputSync("bash", "-c asdf"));
Console.WriteLine(Util.GetCommandOutputSync("bash", "-c ls"));

var arc = new RandomClass {
Id = 1,
Name = "asdf",
DateCreated = DateTime.Now,
SubClassInst = new RandomClass.SubClass {
Description = "asdf"
}
};
var brc = new RandomClass {
Id = 2,
Name = "asdf",
DateCreated = DateTime.Now,
SubClassInst = new RandomClass.SubClass {
Description = "asdf"
}
};
// var arc = new RandomClass {
// Id = 1,
// Name = "asdf",
// DateCreated = DateTime.Now,
// SubClassInst = new RandomClass.SubClass {
// Description = "asdf"
// }
// };
// var brc = new RandomClass {
// Id = 2,
// Name = "asdf",
// DateCreated = DateTime.Now,
// SubClassInst = new RandomClass.SubClass {
// Description = "asdf"
// }
// };
//
// var differences = arc.FindDifferencesDeep(brc);
// Console.WriteLine(differences.left.ToJson());
// Console.WriteLine(differences.right.ToJson());

var differences = arc.FindDifferencesDeep(brc);
Console.WriteLine(differences.left.ToJson());
Console.WriteLine(differences.right.ToJson());
// identicon test
Directory.CreateDirectory("identicons");

// for (int i = 0; i < 100; i++) {
// var ident = new SvgIdenticonGenerator();
// var sw = Stopwatch.StartNew();
// var count = 0;
// while (sw.ElapsedMilliseconds < 10) {
// count++;
// var hash = Guid.NewGuid().ToString("N");
// var svg = ident.Generate(hash);
// // File.WriteAllText($"identicons/{hash}.svg", svg);
// }
//
// Console.WriteLine($"Generated {count} identicons in {sw.Elapsed}");
// await Task.Delay(1000);
// }

// ident.Generate("asdf");

List<string> values = [
"Zoey",
"Willow",
"Whiskers",
"Zoe",
"Sam",
"Salem",
"Snickers",
"Snowball",
"Angel",
"Simon",
"Charlie",
"Daisy",
"Sasha",
"Samantha",
"Sammy",
"Dusty",
"Sassy",
"Annie",
"Felix",
"Pepper"
];

var ident2 = new SvgIdenticonGenerator();
foreach (var value in values) {
var svg = ident2.Generate(value);
File.WriteAllText($"identicons/{values.IndexOf(value)} - {value}.svg", svg);
}
4 changes: 4 additions & 0 deletions ArcaneLibs/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace ArcaneLibs.Extensions;

Expand Down Expand Up @@ -69,4 +70,7 @@ public static string[] ParseArguments(this string text) =>
.SelectMany(element => element).ToArray();

public static IEnumerable<byte> AsBytes(this string str) => Encoding.UTF8.GetBytes(str);

public static string UrlEncode(this string str) => HttpUtility.UrlEncode(str);
public static string UrlDecode(this string str) => HttpUtility.UrlDecode(str);
}
51 changes: 51 additions & 0 deletions ArcaneLibs/SvgIdenticonGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using System.Security.Cryptography;
using ArcaneLibs.Extensions;

namespace ArcaneLibs;

public class SvgIdenticonGenerator {
// based on https://github.com/stewartlord/identicon.js/blob/master/identicon.js

public string BackgroundColor { get; set; } = "#FEFEFEFF";
public float Saturation { get; set; } = 0.7f;
public float Brightness { get; set; } = 0.5f;
public string? ForegroundColor { get; set; }


public string Generate(string identity) {
var hash = SHA1.HashData(identity.AsBytes().ToArray());


var hashArray = new byte[hash.Length];
for (var i = 0; i < hash.Length; i++) {
hashArray[i] = hash[i];
}

var hashInt = BitConverter.ToInt32(hashArray, 0);
var hashIntAbs = Math.Abs(hashInt);
var color = ForegroundColor ?? $"#{(hashIntAbs % 0xFFFFFF):X6}";

var svg = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"5\" height=\"5\" viewBox=\"0 0 5 5\">";
svg += $"<rect x=\"0\" y=\"0\" width=\"5\" height=\"5\" fill=\"{BackgroundColor}\" />";
for (var i = 0; i < 25; i++) {
if ((hashIntAbs & (1 << i)) != 0) {
var x = i % 3; // Only use the first 3 columns
var y = (int)Math.Floor(i / 5f);
svg += $"<rect x=\"{x}\" y=\"{y}\" width=\"1\" height=\"1\" fill=\"{color}\" />";
svg += $"<rect x=\"{4 - x}\" y=\"{y}\" width=\"1\" height=\"1\" fill=\"{color}\" />"; // Mirror the square to the other half
}
}

svg += "</svg>";
return svg;
}

public string GenerateAsBase64(string identity) {
return Convert.ToBase64String(Generate(identity).AsBytes().ToArray());
}

public string GenerateAsDataUri(string identity) {
return $"data:image/svg+xml;base64,{GenerateAsBase64(identity)}";
}

}

0 comments on commit f7bcde9

Please sign in to comment.