-
Notifications
You must be signed in to change notification settings - Fork 1
/
pixel-image-canvas.js
77 lines (70 loc) · 2.74 KB
/
pixel-image-canvas.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
define(function () {
'use strict';
const imageCanvasContext = img => {
const canvas = document.createElement('canvas');
canvas.height = img.naturalHeight;
canvas.width = img.naturalWidth;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
return ctx;
};
const averageColors = pixels => {
const rgba = [0, 0, 0, 0];
let count = 0;
for (let i = 0; i < pixels.length; i += 4) {
count++;
rgba[0] += pixels[i];
rgba[1] += pixels[i + 1];
rgba[2] += pixels[i + 2];
rgba[3] += pixels[i + 3];
}
return count === 0 ? undefined : rgba.map(x => Math.floor(x / count));
};
const extractColorsFromImage = (img, cols, rows) => {
const ctx = imageCanvasContext(img);
const cellW = Math.max(Math.floor(img.naturalWidth / cols), 1);
const cellH = Math.max(Math.floor(img.naturalHeight / rows), 1);
const colors = [];
for (let y = 0; y < rows; y++) {
for (let x = 0; x < cols; x++) {
let pixels = ctx.getImageData(x * cellW, y * cellH, cellW, cellH).data;
colors[y] || (colors[y] = []);
colors[y][x] = averageColors(pixels);
}
}
return colors;
};
/**
* Expects a canvas DOM element and a 2 dimensional array with rows of colors.
* Renders rectangles with the given colors across the canvas.
*/
const rasterCanvas = (canvas, colors) => {
const rows = colors.length;
const cols = colors[0].length;
const cellW = Math.max(Math.floor(canvas.offsetWidth / cols), 1);
const cellH = Math.max(Math.floor(canvas.offsetHeight / rows), 1);
const ctx = canvas.getContext('2d');
for (let y = 0; y < rows; y++) {
for (let x = 0; x < cols; x++) {
const color = colors[y] && colors[y][x] || [0, 0, 0, 0];
ctx.fillStyle = 'rgb(' + color.join(',') + ')';
ctx.fillRect(x * cellW, y * cellH, cellW, cellH);
}
}
};
const loadImageColors = (src, cols, rows) => {
return new Promise(resolve => {
const img = new Image();
img.addEventListener('load', e => resolve(extractColorsFromImage(e.target, cols, rows)));
img.src = src;
});
};
/**
* Load the given image from src and pixelate it onto the given canvas DOM element.
* The pixel size is dictated by the canvas size and how many cols and rows to use.
*/
return (canvas, src, cols, rows) => {
loadImageColors(src, Math.max(cols, 1), Math.max(rows, 1))
.then(colors => rasterCanvas(canvas, colors));
}
});