-
Notifications
You must be signed in to change notification settings - Fork 0
/
pixelsort.js
125 lines (110 loc) · 3.05 KB
/
pixelsort.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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
const canvasSketch = require("canvas-sketch");
const load = require("load-asset");
const SimplexNoise = require("simplex-noise");
const noise = new SimplexNoise(0);
const settings = {
dimensions: [1080, 1080],
};
const thresh = 0.1;
const randomness = 0.3;
const channelSize = 1;
const imageFile = "./lolli.png";
const zeroPad = (num, places) => String(num).padStart(places, "0");
function rgbToHsl(r, g, b) {
(r /= 255), (g /= 255), (b /= 255);
var max = Math.max(r, g, b),
min = Math.min(r, g, b);
var h,
s,
l = (max + min) / 2;
if (max == min) {
h = s = 0; // achromatic
} else {
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0);
break;
case g:
h = (b - r) / d + 2;
break;
case b:
h = (r - g) / d + 4;
break;
}
h /= 6;
}
return [h, s, l];
}
let t = 1;
const sketch = async () => {
const image = await load(imageFile);
return ({ context, width, height }) => {
t += 0.1;
const imgCanvas = document.createElement("canvas");
imgCanvas.width = image.width;
imgCanvas.height = image.height;
const imgCtx = imgCanvas.getContext("2d");
imgCtx.drawImage(image, 0, 0);
const imageData = imgCtx.getImageData(
0,
0,
imgCanvas.width,
imgCanvas.height
);
const pixels = imageData.data;
const brightness = (x, y) => {
const [h, s, l] = rgbToHsl(...get(x, y));
return l;
};
const get = (x, y) => {
const i = (y * image.width + x) * 4;
return pixels.slice(i, i + 4);
};
const set = (x, y, r, g, b) => {
const i = (y * image.width + x) * 4;
pixels[i] = r;
pixels[i + 1] = g;
pixels[i + 2] = b;
};
const sort = (x, yStart, yEnd) => {
let arr = [];
for (var y = yStart; y < yEnd; y++) {
arr.push(get(x, y));
}
arr.sort((a, b) => rgbToHsl(...b)[2] - rgbToHsl(...a)[2]);
let i = 0;
for (var y = yStart; y < yEnd; y++) {
for (var j = 0; j < channelSize; j++) {
set(x + j, y, ...arr[i]);
}
i++;
}
};
for (var x = 0; x < image.width; x += channelSize) {
let yStart = 0;
let inStretch = false;
let aboveThresh = false;
let c = [Math.random() * 255, Math.random() * 255, Math.random() * 255];
for (var y = 0; y < image.height; y++) {
const l = brightness(x, y);
const nextAboveThresh = l > thresh;
const switching =
(!nextAboveThresh && aboveThresh) ||
(nextAboveThresh && !aboveThresh);
aboveThresh = nextAboveThresh;
const rand = noise.noise2D(0, t) * 0.5 + 0.5;
if (switching || rand > 1 - randomness || y == image.height - 1) {
inStretch = false;
sort(x, yStart, y);
yStart = y + 1;
}
}
}
context.fillStyle = "white";
context.fillRect(0, 0, width, height);
context.putImageData(imageData, 0, 0);
};
};
canvasSketch(sketch, settings);