Skip to content

Instantly share code, notes, and snippets.

@SkyzohKey
Last active June 3, 2018 22:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SkyzohKey/83e8e4c9ae2ef54db602 to your computer and use it in GitHub Desktop.
Save SkyzohKey/83e8e4c9ae2ef54db602 to your computer and use it in GitHub Desktop.
/**
* COPYRIGHT (c) 2016 SkyzohKey
*
* MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**/
using ToxIdenticon;
class DemoApp {
private int size;
private string public_key;
private string salt;
ToxIdenticon.ToxIdenticon identicon;
public DemoApp (int size, string public_key, string salt) {
this.size = size;
this.public_key = public_key;
this.salt = salt;
var dir = Environment.get_user_special_dir (UserDirectory.PICTURES);
var file_dest = File.new_for_path (@"$dir/ToxIdenticons");
if (!file_dest.query_exists()) {
try {
file_dest.make_directory();
} catch (Error e) {
stdout.printf (@"Error: $(e.message)\n");
}
}
this.identicon = new ToxIdenticon.ToxIdenticon (file_dest.get_path ());
}
public void run () {
string identicon = this.identicon.generate (this.size, this.public_key, this.salt);
stdout.printf (@"Identicon path: $identicon\n");
}
}
public static int main (string[] argv) {
if (argv[1] == null || argv[2] == null) {
stdout.printf ("Bad usage of ToxIdenticon detected.\n\n");
stdout.printf ("Correct usage:\n");
stdout.printf ("$ ./ToxIdenticon [size] [public_key] [?salt]\n");
stdout.printf ("$ ./ToxIdenticon 96 56A1ADE4B...D6FNBSF56D SALT123\n");
return 1;
}
int size = int.parse (argv[1]);
string public_key = argv[2];
string salt = (argv[3] != null) ? argv[3] : "";
var app = new DemoApp (size, public_key, salt);
app.run ();
return 0;
}
/**
* COPYRIGHT (c) 2016 SkyzohKey & Benwaffle
*
* MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**/
using Cairo;
namespace ToxIdenticon {
struct RGB {
double red;
double green;
double blue;
}
class ToxIdenticon : Object {
private ImageSurface surface;
private Context context;
private string save_path;
public string hash { get; set; }
public string salt { get; set; default = ""; }
public double margin { get; set; default = 0.08; }
public int size { get; set; default = 48; }
public ToxIdenticon (string save_path) {
this.save_path = save_path;
this.init_surface ();
}
private void init_surface () {
this.surface = new ImageSurface (Format.ARGB32, this.size, this.size);
this.context = new Context (this.surface);
}
private void draw_rect (double x, double y, double width, double height, RGB color) {
this.context.set_source_rgba (color.red, color.green, color.blue, 1);
this.context.rectangle (x, y, width, height);
this.context.fill ();
}
private RGB hsl2rgb (double h, double s, double b) {
h *= 6;
double hsl[] = {
b += s *= b < 0.5 ? b : 1 - b,
b - h % 1 * s * 2,
b -= s *= 2,
b,
b + h % 1 * s,
b + s
};
return RGB () {
red = hsl[ (int)h % 6 ],
green = hsl[ ((int)h|16) % 6 ],
blue = hsl[ ((int)h|8) % 6 ]
};
}
private int parse_base16 (string? s) {
if (s == null)
return 0;
int res;
s.scanf ("%x", out res);
return res;
}
private void render () {
var hash = Checksum.compute_for_string (ChecksumType.SHA512, this.hash + this.salt);
var size = this.size;
var baseMargin = Math.floor(size * this.margin);
var cell = Math.floor((size - (baseMargin * 2)) / 5);
var margin = Math.floor((size - cell * 5) / 2);
// Background color
var background = RGB () {
red = 240.0/255,
green = 240.0/255,
blue = 240.0/255
};
this.draw_rect (0, 0, this.size, this.size, background);
// Foreground color
var foreground = this.hsl2rgb ((double) this.parse_base16 (hash.substring (-7)) / 0xfffffff, 0.5, 0.7);
// The first 15 characters of the hash control the pixels (even/odd)
// they are drawn down the middle first, then mirrored outwards
for (var i = 0; i < 15; i++) {
var color = (this.parse_base16 ("%c".printf (hash[i])) % 2) != 0 ? background : foreground;
if (i < 5) {
this.draw_rect (2 * cell + margin, i * cell + margin, cell, cell, color);
} else if (i < 10) {
this.draw_rect (1 * cell + margin, (i - 5) * cell + margin, cell, cell, color);
this.draw_rect (3 * cell + margin, (i - 5) * cell + margin, cell, cell, color);
} else if (i < 15) {
this.draw_rect (0 * cell + margin, (i - 10) * cell + margin, cell, cell, color);
this.draw_rect (4 * cell + margin, (i - 10) * cell + margin, cell, cell, color);
}
}
}
public string generate (int size, string hash, string salt = "") {
this.size = size;
this.hash = hash;
this.salt = salt;
this.init_surface ();
this.render ();
File save_file = File.new_for_path (this.save_path + "/" + this.hash + ".png");
string file_path = save_file.get_path ();
this.context.save ();
this.surface.write_to_png (file_path);
return file_path;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment