Repository navigation
Expand file tree
/
Copy pathretroifier.html
More file actions
121 lines (104 loc) · 4.02 KB
/
Copy pathretroifier.html
File metadata and controls
121 lines (104 loc) · 4.02 KB
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
<!DOCTYPE html>
<html>
<head>
<title>retroifier</title>
</head>
<body>
<input type="file" id="imageLoader" name="imageLoader"/>
<input type="range" id="resizeSlider" min="1" max="100" value="100">
<label for="resizeSlider">resize</label>
<input type="range" id="colorCountSlider" min="1" max="56" value="5">
<label for="colorCountSlider">number of colors</label>
<canvas id="imageCanvas"></canvas>
<button id="downloadBtn">download as png</button>
<script>
var imageLoader = document.getElementById('imageLoader');
imageLoader.addEventListener('change', handleImage, false);
var canvas = document.getElementById('imageCanvas');
var ctx = canvas.getContext('2d');
function handleImage(e){
var reader = new FileReader();
reader.onload = function(event){
window.lastImageSrc = event.target.result;
processImage(event.target.result);
}
reader.readAsDataURL(e.target.files[0]);
}
function processImage(imageSrc) {
var img = new Image();
img.onload = function(){
var scaleFactor = document.getElementById('resizeSlider').value / 100;
var newWidth = img.width * scaleFactor;
var newHeight = img.height * scaleFactor;
canvas.width = newWidth;
canvas.height = newHeight;
ctx.drawImage(img, 0, 0, newWidth, newHeight);
retroify(ctx, newWidth, newHeight);
}
img.src = imageSrc;
}
function getFrequentColors(data, count) {
var colorCount = {};
for (var i = 0; i < data.length; i += 4) {
if (data[i+3] === 0) continue;
var color = `${data[i]},${data[i+1]},${data[i+2]}`;
colorCount[color] = (colorCount[color] || 0) + 1;
}
return Object.entries(colorCount)
.sort((a, b) => b[1] - a[1])
.slice(0, count)
.map(entry => entry[0].split(',').map(Number));
}
function findClosestPaletteColor(color, palette) {
var closest = palette[0];
var closestDistance = Infinity;
palette.forEach(paletteColor => {
var distance = Math.sqrt(
(color[0] - paletteColor[0]) ** 2 +
(color[1] - paletteColor[1]) ** 2 +
(color[2] - paletteColor[2]) ** 2
);
if (distance < closestDistance) {
closestDistance = distance;
closest = paletteColor;
}
});
return closest;
}
function retroify(ctx, width, height) {
var imageData = ctx.getImageData(0, 0, width, height);
var data = imageData.data;
var colorCount = document.getElementById('colorCountSlider').value;
var palette = getFrequentColors(data, colorCount);
for (var i = 0; i < data.length; i += 4) {
var originalColor = [data[i], data[i+1], data[i+2]];
var closestColor = findClosestPaletteColor(originalColor, palette);
data[i] = closestColor[0];
data[i+1] = closestColor[1];
data[i+2] = closestColor[2];
}
ctx.putImageData(imageData, 0, 0);
}
document.getElementById('resizeSlider').addEventListener('input', function() {
if (window.lastImageSrc) {
processImage(window.lastImageSrc);
}
});
document.getElementById('colorCountSlider').addEventListener('input', function() {
if (window.lastImageSrc) {
processImage(window.lastImageSrc);
}
});
document.getElementById('downloadBtn').addEventListener('click', function() {
var canvas = document.getElementById('imageCanvas');
var dataURL = canvas.toDataURL('image/png');
var downloadLink = document.createElement('a');
downloadLink.href = dataURL;
downloadLink.download = 'image.png';
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
});
</script>
</body>
</html>