-
Notifications
You must be signed in to change notification settings - Fork 0
/
pfp.js
89 lines (73 loc) · 2.16 KB
/
pfp.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
function genColor(rng) {
const color = [Math.floor(rng() * 255), Math.floor(rng() * 255), Math.floor(rng() * 255)];
color.rgb = `rgb(${color[0]},${color[1]},${color[2]})`;
return color;
}
class Palette {
constructor(rng, paletteSize = 3) {
this.rng = rng;
this.palette = Array.from({ length: paletteSize }, () => genColor(this.rng));
}
genColor() {
return this.palette[Math.floor(this.rng() * this.palette.length)];
}
}
export function drawGridPfp(ctx, height, width, rng) {
const palette = new Palette(rng, 3);
const cols = 8;
const rows = 8;
const cellHeight = Math.ceil(height / rows);
const cellWidth = Math.ceil(width / cols);
for (let row = 0; row < rows; row++) {
for (let col = 0; col < cols; col++) {
const color = palette.genColor();
ctx.fillStyle = color.rgb;
ctx.fillRect(col * cellWidth, row * cellHeight, cellWidth, cellHeight);
}
}
}
export function drawVoronoiPfp(ctx, height, width, rng, mode = 'euclidean') {
const palette = new Palette(rng, 6);
const points = new Set();
// generate points
for (let i = 0; i < rng() * 30 + 30; i++) {
const point = {
x: rng() * width,
y: rng() * height,
color: palette.genColor(),
};
points.add(point);
}
const imageData = ctx.createImageData(width, height);
const data = new Uint8Array(imageData.data.buffer);
// draw voronoi
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
// find closest point
let closestPoint = null;
let closestPointDistance = null;
for (const point of points) {
let distance;
if (mode === 'euclidean') {
distance = Math.sqrt((x - point.x) ** 2 + (y - point.y) ** 2);
} else {
distance = Math.abs(x - point.x) + Math.abs(y - point.y);
}
if (!closestPointDistance || distance < closestPointDistance) {
closestPoint = point;
closestPointDistance = distance;
}
}
if (closestPoint) {
// draw pixel at place.
const color = closestPoint.color;
const pixelIndex = (y * width + x) * 4;
data[pixelIndex] = color[0];
data[pixelIndex + 1] = color[1];
data[pixelIndex + 2] = color[2];
data[pixelIndex + 3] = 255;
}
}
}
ctx.putImageData(imageData, 0, 0);
}