Skip to content

Commit

Permalink
algorithm changes to allow >10 tiles wide
Browse files Browse the repository at this point in the history
  • Loading branch information
sehrgut committed Aug 26, 2013
1 parent fafd44a commit 72f886b
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 18 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ Faithful replica of Github's identicon style.

![github](https://raw.github.com/sehrgut/node-retricon/master/examples/images/github.png)

### custom example
Absurd settings, such as:
`{ pixelSize: 8, pixelPadding: -2, tiles: 30, pixelColor: 0, bgColor: 1 }`
can still yield quite serviceable results.

![bat](https://raw.github.com/sehrgut/node-retricon/master/examples/images/bat.png)


## Algorithm

Expand All @@ -106,5 +113,8 @@ The array of booleans is taken to be a row-major array covering the left half
of the final image. It is reflected about the central vertical axis (or column,
for odd-order arrays) which is then rendered as the final visual hash.

## Known Limitations
* 30x30 tile images are the maximum which can be generated from SHA-512.

[ghid]: https://github.com/blog/1586-identicons
[gravatar]: https://en.gravatar.com/site/implement/images/
3 changes: 2 additions & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@
return a "colors" array. Useful for nudging colours away from low-contrast
pairs, maybe desaturating, etc., to provide a more uniform look.
* Allow null for foreground colour, to delete background and allow transparent
* Allow pluggable hash functions
* Allow pluggable hash functions
* Change "pixel" references throughout source to "tile"
1 change: 1 addition & 0 deletions examples/example.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
var retricon = require('../');
var fmt = require('util').format;


console.log('<html><head><title>retricons</title></head><body>');

console.log('<div><h2>default</h2>');
Expand Down
Binary file added examples/images/bat.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions examples/large.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
var retricon = require('../');
var fmt = require('util').format;


console.log('<html><head><title>retricons</title></head><body>');

console.log('<h2>large</h2>');
var custom = { pixelSize: 8, pixelPadding: -2, tiles: 30, pixelColor: 0, bgColor: 1 };
for (var i=0; i<10; i++) {
console.log("<img src='" + retricon(i.toString(), custom).toDataURL() + "'>");
}

console.log('</body></html>');
18 changes: 18 additions & 0 deletions lib/bright.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
function brightness(r, g, b) {
// http://www.nbdtech.com/Blog/archive/2008/04/27/Calculating-the-Perceived-Brightness-of-a-Color.aspx
return Math.sqrt( .241 * r * r + .691 * g * g + .068 * b * b )
}

function cmp_brightness(a, b) {
return brightness(a[0], a[1], a[2]) - brightness(b[0], b[1], b[2]);
}

function rcmp_brightness(a, b) {
return cmp_brightness(b, a);
}

module.exports = {
ness: brightness,
cmp: cmp_brightness,
rcmp: rcmp_brightness
};
30 changes: 13 additions & 17 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,35 @@ var Canvas = require('canvas');
var _ = require('lodash');
var bu = require('./bufutil');
var fmt = require('util').format;
var unpack = require('./unpack');
var bright = require('./bright');

function fprint(buf, len) {
if (len > 64)
throw new Error(fmt("sha512 can only generate 64B of data: %dB requested", len));

return _(crypto.createHash('sha512').update(buf).digest())
.groupBy(function (x, k) { return Math.floor(k/len); })
.reduce(bu.xor);
}

function brightness(r, g, b) {
// http://www.nbdtech.com/Blog/archive/2008/04/27/Calculating-the-Perceived-Brightness-of-a-Color.aspx
return Math.sqrt( .241 * r * r + .691 * g * g + .068 * b * b )
}

function cmp_brightness(a, b) {
return brightness(a[0], a[1], a[2]) - brightness(b[0], b[1], b[2]);
}

function rcmp_brightness(a, b) {
return cmp_brightness(b, a);
}

function idhash(str, n, minFill, maxFill) {
var buf = new Buffer(str.length + 1);
buf.write(str);

for (var i=0; i<0x100; i++) {
buf[buf.length - 1] = i;
var f = fprint(buf, n+6);
var pixels = _(f.slice(6)).map(function (x) { return x > 0x7f; });
var f = fprint(buf, Math.ceil(n/8)+6);
var pixels = _(f.slice(6))
.map(function (x) { return unpack(x); })
.flatten().take(n);

var setPixels = pixels.filter().size();

var c = [ f.slice(0, 3), f.slice(3, 6)];
c.sort(cmp_brightness);
c.sort(bright.cmp);
// console.error(fmt("%d < %d < %d", minFill*n, setPixels, maxFill*n));
if (setPixels > (minFill * n) && setPixels < (maxFill * n))
return {
colors: c.map(function (x) { return x.toString('hex'); }),
Expand All @@ -60,9 +57,9 @@ function reflect(id, dimension) {
p = (row * mid) + mid - 1 - ad;
}
pic[row][col] = id.pixels[p];
// console.error(fmt("looking for %d, of %d for %d,%d", p, id.pixels.length, row, col))
}
}

return pic;
}

Expand Down Expand Up @@ -107,7 +104,6 @@ function retricon(str, opts) {
(y*pixelSize) + border + opts.imagePadding,
pixelSize - (border * 2),
pixelSize - (border * 2));

return c;
}

Expand Down
9 changes: 9 additions & 0 deletions lib/unpack.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

function unpack_byte(nMask) {
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators
for (var i=0, nShifted = nMask, a = []; i<8; nShifted >>>= 1, i++)
a.push(Boolean(nShifted & 1));
return a;
}

module.exports = unpack_byte;

0 comments on commit 72f886b

Please sign in to comment.