├── .editorconfig ├── .gitignore ├── .jshintrc ├── .npmignore ├── LICENSE ├── README.md ├── TODO.md ├── examples ├── example.js ├── gravatar-test.sh ├── images │ ├── 01.png │ ├── 02.png │ ├── 03.png │ ├── 04.png │ ├── 05.png │ ├── 06.png │ ├── 07.png │ ├── 08.png │ ├── bat.png │ ├── default.png │ ├── github.png │ ├── gravatar.png │ ├── kibo.png │ ├── mini.png │ ├── mono.png │ ├── mosaic.png │ └── window.png ├── kibo.js └── large.js ├── index.js ├── lib ├── bright.js ├── bufutil.js ├── index.js └── unpack.js └── package.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | 10 | # Change these settings to your own preference 11 | indent_style = space 12 | indent_size = 2 13 | 14 | # We recommend you to keep these unchanged 15 | end_of_line = lf 16 | charset = utf-8 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | lib-cov 3 | *.seed 4 | *.log 5 | *.csv 6 | *.dat 7 | *.out 8 | *.pid 9 | *.gz 10 | 11 | pids 12 | logs 13 | results 14 | 15 | npm-debug.log 16 | node_modules 17 | examples/*.html -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "maxerr" : 50, // {int} Maximum error before stopping 3 | 4 | // Enforcing 5 | "bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.) 6 | "camelcase" : false, // true: Identifiers must be in camelCase 7 | "curly" : false, // true: Require {} for every new block or scope 8 | "eqeqeq" : true, // true: Require triple equals (===) for comparison 9 | "forin" : false, // true: Require filtering for..in loops with obj.hasOwnProperty() 10 | "immed" : true, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());` 11 | "indent" : 2, // {int} Number of spaces to use for indentation 12 | "latedef" : true, // true: Require variables/functions to be defined before being used 13 | "newcap" : true, // true: Require capitalization of all constructor functions e.g. `new F()` 14 | "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee` 15 | "noempty" : true, // true: Prohibit use of empty blocks 16 | "nonew" : true, // true: Prohibit use of constructors for side-effects (without assignment) 17 | "plusplus" : true, // true: Prohibit use of `++` & `--` 18 | "quotmark" : "single", // Quotation mark consistency: 19 | // false : do nothing (default) 20 | // true : ensure whatever is used is consistent 21 | // "single" : require single quotes 22 | // "double" : require double quotes 23 | "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks) 24 | "unused" : "vars", // true: Require all defined variables be used 25 | "strict" : true, // true: Requires all functions run in ES5 Strict Mode 26 | "maxparams" : false, // {int} Max number of formal params allowed per function 27 | "maxdepth" : false, // {int} Max depth of nested blocks (within functions) 28 | "maxstatements" : false, // {int} Max number statements per function 29 | "maxcomplexity" : false, // {int} Max cyclomatic complexity per function 30 | "maxlen" : false, // {int} Max number of characters per line 31 | 32 | // Relaxing 33 | "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons) 34 | "boss" : false, // true: Tolerate assignments where comparisons would be expected 35 | "debug" : false, // true: Allow debugger statements e.g. browser breakpoints. 36 | "eqnull" : false, // true: Tolerate use of `== null` 37 | "es5" : false, // true: Allow ES5 syntax (ex: getters and setters) 38 | "esnext" : true, // true: Allow ES.next (ES6) syntax (ex: `const`) 39 | "moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features) 40 | // (ex: `for each`, multiple try/catch, function expression…) 41 | "evil" : false, // true: Tolerate use of `eval` and `new Function()` 42 | "expr" : false, // true: Tolerate `ExpressionStatement` as Programs 43 | "funcscope" : false, // true: Tolerate defining variables inside control statements 44 | "globalstrict" : false, // true: Allow global "use strict" (also enables 'strict') 45 | "iterator" : false, // true: Tolerate using the `__iterator__` property 46 | "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block 47 | "laxbreak" : false, // true: Tolerate possibly unsafe line breakings 48 | "laxcomma" : false, // true: Tolerate comma-first style coding 49 | "loopfunc" : false, // true: Tolerate functions being defined in loops 50 | "multistr" : false, // true: Tolerate multi-line strings 51 | "proto" : false, // true: Tolerate using the `__proto__` property 52 | "scripturl" : false, // true: Tolerate script-targeted URLs 53 | "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;` 54 | "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation 55 | "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;` 56 | "validthis" : false, // true: Tolerate using this in a non-constructor function 57 | 58 | // Environments 59 | "browser" : true, // Web Browser (window, document, etc) 60 | "couch" : false, // CouchDB 61 | "devel" : true, // Development/debugging (alert, confirm, etc) 62 | "dojo" : false, // Dojo Toolkit 63 | "jquery" : false, // jQuery 64 | "mootools" : false, // MooTools 65 | "node" : true, // Node.js 66 | "nonstandard" : false, // Widely adopted globals (escape, unescape, etc) 67 | "prototypejs" : false, // Prototype and Scriptaculous 68 | "rhino" : false, // Rhino 69 | "worker" : false, // Web Workers 70 | "wsh" : false, // Windows Scripting Host 71 | "yui" : false, // Yahoo User Interface 72 | 73 | // Custom Globals 74 | "globals": { 75 | "angular" : true, 76 | "define" : false, 77 | "require" : false, 78 | "exports" : false, 79 | "module" : false, 80 | "describe" : false, 81 | "before" : false, 82 | "beforeEach" : false, 83 | "after" : false, 84 | "afterEach" : false, 85 | "it" : false, 86 | "inject" : false, 87 | "expect" : false, 88 | "spyOn" : false 89 | }, 90 | 91 | // Predefined vars 92 | "predef": [] 93 | } 94 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .git 2 | .DS_Store 3 | .gitignore 4 | .npmignore 5 | 6 | node_modules 7 | examples/*.html 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, sehrgut 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | node-identicon-github 2 | ===================== 3 | 4 | [![Dependency Status](http://img.shields.io/david/hashdog/node-identicon-github.svg?style=flat-square)](https://david-dm.org/hashdog/node-identicon-github) 5 | 6 | The author of https://github.com/sehrgut/node-retricon has not maintain module for a long time (since 2013). 7 | Some dependencies has been updated and we need to use it. 8 | 9 | Create indenticon-like image hashes styled like [Github][ghid] and [Gravatar (retro)][gravatar] avatars 10 | 11 | ![avatar](https://raw.github.com/hashdog/node-identicon-github/master/examples/images/01.png) 12 | ![avatar](https://raw.github.com/hashdog/node-identicon-github/master/examples/images/02.png) 13 | ![avatar](https://raw.github.com/hashdog/node-identicon-github/master/examples/images/03.png) 14 | ![avatar](https://raw.github.com/hashdog/node-identicon-github/master/examples/images/04.png) 15 | ![avatar](https://raw.github.com/hashdog/node-identicon-github/master/examples/images/05.png) 16 | ![avatar](https://raw.github.com/hashdog/node-identicon-github/master/examples/images/06.png) 17 | ![skull](https://raw.github.com/hashdog/node-identicon-github/master/examples/images/07.png) 18 | ![frog](https://raw.github.com/hashdog/node-identicon-github/master/examples/images/08.png) 19 | 20 | ## Example 21 | 22 | var identicon = require('identicon-github'); 23 | var fmt = require('util').format; 24 | 25 | console.log(fmt("kibo", identicon('kibo', { pixelSize: 16 }).toDataURL())); 26 | 27 | ### Output 28 | kibo 29 | ![kibo](https://raw.github.com/hashdog/node-identicon-github/master/examples/images/kibo.png) 30 | 31 | ## API 32 | 33 | ### identicon(str, pixelSize, border) 34 | 35 | * `str`: string - username, email, or other string to hash 36 | * `opts`: object 37 | * `pixelSize`: int (default: 10) - width and height in pixels to render 38 | each tile 39 | * `bgColor`: mixed (default: null) - color to fill background 40 | * `null` for transparent 41 | * 0 or 1 for first (brighter) or second (darker) random color 42 | * CSS hex colorspec (e.g. '#F0F0F0') 43 | * `pixelPadding`: int (default: 0) - background pixels within the border of 44 | each rendered tile. Use negative values for overlap, as in Github- 45 | style identicons 46 | * `imagePadding`: int (default: 0) - padding around outside of image 47 | * `tiles`: int (default: 5) - number of tiles wide and high to render 48 | * `minFill`: float (default: 0.3) - proportion of tiles which must be 49 | filled. Hash chaining is used to satisfy fill criteria. 50 | * `maxFill`: float (default: 0.9) - maximum proportion of tiles which may 51 | be filled. 52 | * `pixelColor`: mixed (default: 0) - color to fill foreground tiles. All 53 | `bgColor` values are valid for `pixelColor`. 54 | 55 | Returns a `Canvas` object containing the rendered image. 56 | 57 | ## Styles 58 | 59 | All style options can be changed, but _identicon_ comes with several prerolled 60 | styles: 61 | 62 | ### default 63 | Coloured tiles against a transparent background. 64 | 65 | ![default](https://raw.github.com/hashdog/node-identicon-github/master/examples/images/default.png) 66 | 67 | ### mini 68 | Tiny 3x3 identicons with padded tiles. 69 | 70 | ![mini](https://raw.github.com/hashdog/node-identicon-github/master/examples/images/mini.png) 71 | 72 | ### gravatar 73 | Not a perfect replica of Gravatar's "retro" style, but close. 74 | 75 | ![gravatar](https://raw.github.com/hashdog/node-identicon-github/master/examples/images/gravatar.png) 76 | 77 | ### mono 78 | Black tiles on a grey background. 79 | 80 | ![mono](https://raw.github.com/hashdog/node-identicon-github/master/examples/images/mono.png) 81 | 82 | ### mosaic 83 | Padded tiles, for a mosaic effect. 84 | 85 | ![mosaic](https://raw.github.com/hashdog/node-identicon-github/master/examples/images/mosaic.png) 86 | 87 | ### window 88 | Transparent, padded tiles against coloured background. 89 | 90 | ![window](https://raw.github.com/hashdog/node-identicon-github/master/examples/images/window.png) 91 | 92 | ### github 93 | Faithful replica of Github's identicon style. 94 | 95 | ![github](https://raw.github.com/hashdog/node-identicon-github/master/examples/images/github.png) 96 | 97 | ### custom example 98 | Absurd settings, such as: 99 | `{ pixelSize: 8, pixelPadding: -2, tiles: 30, pixelColor: 0, bgColor: 1 }` 100 | can still yield quite serviceable results. 101 | 102 | ![bat](https://raw.github.com/hashdog/node-identicon-github/master/examples/images/bat.png) 103 | 104 | 105 | ## Algorithm 106 | 107 | The input string is converted to a buffer of UTF-8 bytes. A one-byte iterator 108 | is appended to this, initialized at zero, for hash chaining. The buffer is 109 | passed through SHA-512, and the output buffer is iteratively XORed to produce a 110 | final buffer of only the number of required bytes (currently eighteen). The 111 | first six bytes are taken as RGB values for the colours. The remaining bytes 112 | are quantized to boolean values at a threshold of 127. If a minimum proportion 113 | of the booleans are true, but not more than the maximum proportion, the hash is 114 | accepted. Otherwise, the iterator is incremented, and the process repeated. 115 | 116 | The array of booleans is taken to be a row-major array covering the left half 117 | of the final image. It is reflected about the central vertical axis (or column, 118 | for odd-order arrays) which is then rendered as the final visual hash. 119 | 120 | ## Known Limitations 121 | * 30x30 tile images are the maximum which can be generated from SHA-512. 122 | 123 | [ghid]: https://github.com/blog/1586-identicons 124 | [gravatar]: https://en.gravatar.com/site/implement/images/ 125 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | ## TODO 2 | 3 | * Multiple axes of symmetry, to allow things like (x2, y4 reflections): 4 | 5 | ..X.. 6 | .X.X. 7 | XX.XX 8 | ..... 9 | X...X 10 | ..... 11 | XX.XX 12 | 13 | * Generate SVG strings instead, and render them with an external library. 14 | * Color-transform callback, which is passed the "colors" array, and must 15 | return a "colors" array. Useful for nudging colours away from low-contrast 16 | pairs, maybe desaturating, etc., to provide a more uniform look. 17 | * Allow null for foreground colour, to delete background and allow transparent 18 | * Allow pluggable hash functions 19 | * Change "pixel" references throughout source to "tile" -------------------------------------------------------------------------------- /examples/example.js: -------------------------------------------------------------------------------- 1 | var identicon = require('../'); 2 | var fmt = require('util').format; 3 | 4 | 5 | console.log('identicons'); 6 | 7 | console.log('

default

'); 8 | for (var i=0; i<10; i++) { 9 | console.log(fmt("", identicon(i.toString()).toDataURL())); 10 | } 11 | 12 | console.log('

mini

'); 13 | for (var i=0; i<10; i++) { 14 | console.log(""); 15 | } 16 | 17 | console.log('

gravatar-style

'); 18 | for (var i=0; i<10; i++) { 19 | console.log(""); 20 | } 21 | 22 | console.log('

monochrome

'); 23 | for (var i=0; i<10; i++) { 24 | console.log(""); 25 | } 26 | 27 | console.log('

mosaic

'); 28 | for (var i=0; i<10; i++) { 29 | console.log(""); 30 | } 31 | 32 | console.log('

window

'); 33 | for (var i=0; i<10; i++) { 34 | console.log(""); 35 | } 36 | 37 | console.log('

github-style

'); 38 | for (var i=0; i<10; i++) { 39 | console.log(""); 40 | } 41 | 42 | console.log(''); 43 | -------------------------------------------------------------------------------- /examples/gravatar-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Generates a page of the first 1000 retro gravatars, for comparison 3 | 4 | echo "gravatar test" 5 | 6 | for i in {0..1000}; do 7 | printf "" \ 8 | $(md5 -qs $i) 9 | done 10 | 11 | echo "" -------------------------------------------------------------------------------- /examples/images/01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashdog/node-identicon-github/1f348b6a31fd54fecfc9300c226324cd44076cd9/examples/images/01.png -------------------------------------------------------------------------------- /examples/images/02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashdog/node-identicon-github/1f348b6a31fd54fecfc9300c226324cd44076cd9/examples/images/02.png -------------------------------------------------------------------------------- /examples/images/03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashdog/node-identicon-github/1f348b6a31fd54fecfc9300c226324cd44076cd9/examples/images/03.png -------------------------------------------------------------------------------- /examples/images/04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashdog/node-identicon-github/1f348b6a31fd54fecfc9300c226324cd44076cd9/examples/images/04.png -------------------------------------------------------------------------------- /examples/images/05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashdog/node-identicon-github/1f348b6a31fd54fecfc9300c226324cd44076cd9/examples/images/05.png -------------------------------------------------------------------------------- /examples/images/06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashdog/node-identicon-github/1f348b6a31fd54fecfc9300c226324cd44076cd9/examples/images/06.png -------------------------------------------------------------------------------- /examples/images/07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashdog/node-identicon-github/1f348b6a31fd54fecfc9300c226324cd44076cd9/examples/images/07.png -------------------------------------------------------------------------------- /examples/images/08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashdog/node-identicon-github/1f348b6a31fd54fecfc9300c226324cd44076cd9/examples/images/08.png -------------------------------------------------------------------------------- /examples/images/bat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashdog/node-identicon-github/1f348b6a31fd54fecfc9300c226324cd44076cd9/examples/images/bat.png -------------------------------------------------------------------------------- /examples/images/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashdog/node-identicon-github/1f348b6a31fd54fecfc9300c226324cd44076cd9/examples/images/default.png -------------------------------------------------------------------------------- /examples/images/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashdog/node-identicon-github/1f348b6a31fd54fecfc9300c226324cd44076cd9/examples/images/github.png -------------------------------------------------------------------------------- /examples/images/gravatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashdog/node-identicon-github/1f348b6a31fd54fecfc9300c226324cd44076cd9/examples/images/gravatar.png -------------------------------------------------------------------------------- /examples/images/kibo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashdog/node-identicon-github/1f348b6a31fd54fecfc9300c226324cd44076cd9/examples/images/kibo.png -------------------------------------------------------------------------------- /examples/images/mini.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashdog/node-identicon-github/1f348b6a31fd54fecfc9300c226324cd44076cd9/examples/images/mini.png -------------------------------------------------------------------------------- /examples/images/mono.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashdog/node-identicon-github/1f348b6a31fd54fecfc9300c226324cd44076cd9/examples/images/mono.png -------------------------------------------------------------------------------- /examples/images/mosaic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashdog/node-identicon-github/1f348b6a31fd54fecfc9300c226324cd44076cd9/examples/images/mosaic.png -------------------------------------------------------------------------------- /examples/images/window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashdog/node-identicon-github/1f348b6a31fd54fecfc9300c226324cd44076cd9/examples/images/window.png -------------------------------------------------------------------------------- /examples/kibo.js: -------------------------------------------------------------------------------- 1 | var identicon = require('../'), 2 | img = identicon('kibo', { pixelSize: 16 }).toDataURL(); 3 | 4 | console.log('kibo'); 5 | -------------------------------------------------------------------------------- /examples/large.js: -------------------------------------------------------------------------------- 1 | var identicon = require('../'); 2 | 3 | console.log('identicons'); 4 | console.log('

large

'); 5 | 6 | var custom = { pixelSize: 8, pixelPadding: -2, tiles: 30, pixelColor: 0, bgColor: 1 }; 7 | for (var i=0; i<10; i++) { 8 | console.log(''); 9 | } 10 | 11 | console.log(''); 12 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib'); 2 | -------------------------------------------------------------------------------- /lib/bright.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var brightness = function(r, g, b) { 4 | var br = 0.241 * r * r, 5 | bg = 0.691 * g * g, 6 | bb = 0.068 * b * b; 7 | 8 | // http://www.nbdtech.com/Blog/archive/2008/04/27/Calculating-the-Perceived-Brightness-of-a-Color.aspx 9 | return Math.sqrt(br + bg + bb); 10 | }; 11 | 12 | var cmp_brightness = function(a, b) { 13 | return brightness(a[0], a[1], a[2]) - brightness(b[0], b[1], b[2]); 14 | }; 15 | 16 | var rcmp_brightness = function(a, b) { 17 | return cmp_brightness(b, a); 18 | }; 19 | 20 | module.exports = { 21 | ness: brightness, 22 | cmp: cmp_brightness, 23 | rcmp: rcmp_brightness 24 | }; 25 | -------------------------------------------------------------------------------- /lib/bufutil.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Inspired by: 4 | // https://code.google.com/p/nodejs-win/source/browse/node_modules/mysql/lib/auth.js 5 | var xor = function(a, b) { 6 | var n = Math.min(a.length, b.length), 7 | m = Math.max(a.length, b.length), 8 | out = new Buffer(m), 9 | longer = (a.length > b.length ? a : b) ; 10 | 11 | for (var i=0; i 64) { 13 | throw new Error('sha512 can only generate 64B of data: ' + len + 'B requested'); 14 | } 15 | 16 | return _(crypto.createHash('sha512').update(buf).digest()) 17 | .groupBy(function (x, k) { return Math.floor(k/len); }) 18 | .reduce(bu.xor); 19 | }; 20 | 21 | var idhash = function(str, n, minFill, maxFill) { 22 | var buf = new Buffer(str.length + 1); 23 | buf.write(str); 24 | 25 | for (var i=0; i<0x100; i++) { 26 | buf[buf.length - 1] = i; 27 | var f = fprint(buf, Math.ceil(n/8)+6); 28 | 29 | var pixels = _(f.slice(6)) 30 | .map(function (x) { return unpack(x); }) 31 | .flatten() 32 | .take(n); 33 | 34 | var setPixels = pixels.filter().size(); 35 | 36 | var c = [ f.slice(0, 3), f.slice(3, 6)]; 37 | c.sort(bright.cmp); 38 | 39 | if (setPixels > (minFill * n) && setPixels < (maxFill * n)) { 40 | return { 41 | colors: c.map(function (x) { return x.toString('hex'); }), 42 | pixels: pixels.value() 43 | }; 44 | } 45 | } 46 | 47 | throw new Error('String "' + str + '" unhashable in single-byte search space.'); 48 | }; 49 | 50 | 51 | var reflect = function(id, dimension) { 52 | var mid = Math.ceil(dimension / 2); 53 | var odd = Boolean(dimension % 2); 54 | 55 | var pic = []; 56 | for (var row=0; row=mid) { 62 | var d = mid - (odd ? 1 : 0) - col; 63 | var ad = Math.abs(d); 64 | p = (row * mid) + mid - 1 - ad; 65 | } 66 | pic[row][col] = id.pixels[p]; 67 | } 68 | } 69 | 70 | return pic; 71 | }; 72 | 73 | var identicon = function(str, opts) { 74 | opts = _.merge({}, identicon.defaults, opts); 75 | 76 | var dimension = opts.tiles, 77 | pixelSize = opts.pixelSize, 78 | border = opts.pixelPadding; 79 | 80 | var mid = Math.ceil(dimension / 2), 81 | id = idhash(str, mid * dimension, opts.minFill, opts.maxFill), 82 | pic = reflect(id, dimension), 83 | csize = (pixelSize * dimension) + (opts.imagePadding * 2), 84 | c = new Canvas(csize, csize), 85 | ctx = c.getContext('2d'); 86 | 87 | if (_.isString(opts.bgColor)) { 88 | ctx.fillStyle = opts.bgColor; 89 | } else if (_.isNumber(opts.bgColor)) { 90 | ctx.fillStyle = '#' + id.colors[opts.bgColor]; 91 | } 92 | 93 | if ( ! _.isNull(opts.bgColor)) { 94 | ctx.fillRect(0, 0, csize, csize); 95 | } 96 | 97 | var drawOp = ctx.fillRect.bind(ctx); 98 | 99 | if (_.isString(opts.pixelColor)) { 100 | ctx.fillStyle = opts.pixelColor; 101 | } else if (_.isNumber(opts.pixelColor)) { 102 | ctx.fillStyle = '#' + id.colors[opts.pixelColor]; 103 | } else { 104 | drawOp = ctx.clearRect.bind(ctx); 105 | } 106 | 107 | for (var x=0; x>>= 1, i++) { 6 | a.push(Boolean(nShifted & 1)); 7 | } 8 | 9 | return a; 10 | }; 11 | 12 | module.exports = unpack_byte; 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "identicon-github", 3 | "version": "0.0.1", 4 | "description": "Create indenticon-like visual hashes styled like Github and Gravatar (retro) avatars", 5 | "main": "index.js", 6 | "homepage": "https://github.com/hashdog/node-identicon-github", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/hashdog/node-identicon-github.git" 13 | }, 14 | "keywords": [ 15 | "identicon", 16 | "avatar", 17 | "visualization", 18 | "profile", 19 | "fingerprint", 20 | "image", 21 | "hash", 22 | "visual hash", 23 | "github", 24 | "gravatar" 25 | ], 26 | "author": "Mario Colque ", 27 | "license": "BSD", 28 | "dependencies": { 29 | "canvas": "^1.2.3", 30 | "lodash": "^3.10.0" 31 | }, 32 | "readmeFilename": "README.md", 33 | "directories": { 34 | "example": "examples" 35 | } 36 | } 37 | --------------------------------------------------------------------------------