summaryrefslogtreecommitdiff
path: root/packages/backend/src/misc/gen-identicon.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/backend/src/misc/gen-identicon.ts')
-rw-r--r--packages/backend/src/misc/gen-identicon.ts91
1 files changed, 91 insertions, 0 deletions
diff --git a/packages/backend/src/misc/gen-identicon.ts b/packages/backend/src/misc/gen-identicon.ts
new file mode 100644
index 0000000000..5cedd7afaf
--- /dev/null
+++ b/packages/backend/src/misc/gen-identicon.ts
@@ -0,0 +1,91 @@
+/**
+ * Identicon generator
+ * https://en.wikipedia.org/wiki/Identicon
+ */
+
+import * as p from 'pureimage';
+import * as gen from 'random-seed';
+import { WriteStream } from 'fs';
+
+const size = 256; // px
+const n = 5; // resolution
+const margin = (size / n);
+const colors = [
+ '#e57373',
+ '#F06292',
+ '#BA68C8',
+ '#9575CD',
+ '#7986CB',
+ '#64B5F6',
+ '#4FC3F7',
+ '#4DD0E1',
+ '#4DB6AC',
+ '#81C784',
+ '#8BC34A',
+ '#AFB42B',
+ '#F57F17',
+ '#FF5722',
+ '#795548',
+ '#455A64',
+];
+const bg = '#e9e9e9';
+
+const actualSize = size - (margin * 2);
+const cellSize = actualSize / n;
+const sideN = Math.floor(n / 2);
+
+/**
+ * Generate buffer of an identicon by seed
+ */
+export function genIdenticon(seed: string, stream: WriteStream): Promise<void> {
+ const rand = gen.create(seed);
+ const canvas = p.make(size, size);
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = bg;
+ ctx.beginPath();
+ ctx.fillRect(0, 0, size, size);
+
+ ctx.fillStyle = colors[rand(colors.length)];
+
+ // side bitmap (filled by false)
+ const side: boolean[][] = new Array(sideN);
+ for (let i = 0; i < side.length; i++) {
+ side[i] = new Array(n).fill(false);
+ }
+
+ // 1*n (filled by false)
+ const center: boolean[] = new Array(n).fill(false);
+
+ // eslint:disable-next-line:prefer-for-of
+ for (let x = 0; x < side.length; x++) {
+ for (let y = 0; y < side[x].length; y++) {
+ side[x][y] = rand(3) === 0;
+ }
+ }
+
+ for (let i = 0; i < center.length; i++) {
+ center[i] = rand(3) === 0;
+ }
+
+ // Draw
+ for (let x = 0; x < n; x++) {
+ for (let y = 0; y < n; y++) {
+ const isXCenter = x === ((n - 1) / 2);
+ if (isXCenter && !center[y]) continue;
+
+ const isLeftSide = x < ((n - 1) / 2);
+ if (isLeftSide && !side[x][y]) continue;
+
+ const isRightSide = x > ((n - 1) / 2);
+ if (isRightSide && !side[sideN - (x - sideN)][y]) continue;
+
+ const actualX = margin + (cellSize * x);
+ const actualY = margin + (cellSize * y);
+ ctx.beginPath();
+ ctx.fillRect(actualX, actualY, cellSize, cellSize);
+ }
+ }
+
+ return p.encodePNGToStream(canvas, stream);
+}