[in progress] a color utility i'm making for my pixel art painting process
www.val.town/x/jennschiffer/pixelstats
1const MAX_PIXELS = 80;
2const sizeText = document.getElementById("size-text");
3sizeText.innerHTML = "(< " + MAX_PIXELS + "px)";
4const dropload = document.getElementById("dropload");
5
6// drop event
7dropload.addEventListener("drop", dropHandler);
8window.addEventListener("drop", (e) => {
9 if ([...e.dataTransfer.items].some((item) => item.kind === "file")) {
10 e.preventDefault();
11 }
12});
13
14// dragover event
15dropload.addEventListener("dragover", (e) => {
16 const fileItems = [...e.dataTransfer.items].filter(
17 (item) => item.kind === "file",
18 );
19 if (fileItems.length > 0) {
20 e.preventDefault();
21 if (fileItems.some((item) => item.type.startsWith("image/"))) {
22 e.dataTransfer.dropEffect = "copy";
23 } else {
24 e.dataTransfer.dropEffect = "none";
25 }
26 }
27});
28window.addEventListener("dragover", (e) => {
29 const fileItems = [...e.dataTransfer.items].filter(
30 (item) => item.kind === "file",
31 );
32 if (fileItems.length > 0) {
33 e.preventDefault();
34 if (!dropload.contains(e.target)) {
35 e.dataTransfer.dropEffect = "none";
36 }
37 }
38});
39
40const preview = document.getElementById("preview");
41
42function displayImages(files) {
43 for (const file of files) {
44 if (file.type.startsWith("image/")) {
45 const li = document.createElement("li");
46 const img = document.createElement("img");
47 img.src = URL.createObjectURL(file);
48 img.onload = function() {
49 // don't allow images bigger than max
50 if (this.width <= MAX_PIXELS && this.height <= MAX_PIXELS) {
51 img.alt = file.name;
52 li.classList.add('clickable');
53 li.appendChild(img);
54 li.appendChild(document.createTextNode(" click to get pixelstats"));
55 li.addEventListener("click", (e) => {
56 getPixelStats(e, file)
57 });
58 } else {
59 li.appendChild(document.createTextNode('file \"' + file.name + '\" is bigger than ' + MAX_PIXELS + 'px'));
60 }
61 preview.appendChild(li);
62 }
63 }
64 }
65}
66
67function dropHandler(e) {
68 e.preventDefault();
69 const files = [...e.dataTransfer.items]
70 .map((item) => item.getAsFile())
71 .filter((file) => file);
72 displayImages(files);
73}
74
75const fileInput = document.getElementById("file-input");
76fileInput.addEventListener("change", (e) => {
77 displayImages(e.target.files);
78});
79
80// clear button
81const clearButton = document.getElementById("clear");
82clearButton.addEventListener("click", () => {
83 for (const img of preview.querySelectorAll("img")) {
84 URL.revokeObjectURL(img.src);
85 }
86 preview.textContent = "";
87});
88
89// show pixel stats
90const stats = document.getElementById("stats");
91
92function getPixelStats(e, file) {
93 stats.innerHTML = "";
94 const formData = new FormData();
95 formData.append('image', file);
96 const element = e.target;
97
98 fetch('/process-pixels', {
99 method: 'POST',
100 body: formData
101 }).then(
102 response => response.json()
103 ).then(
104 success => {
105 const data = JSON.parse(success.processed);
106 console.log(data);
107 let colorTable = '<table>';
108 for (const [color, count] of Object.entries(data.colors.colorsDistributionSorted)) {
109 colorTable += '<tr><td style="width:50px;background-color:rgba(' + color + ')" data-color=' + color + ' title="rgba(' + color +
110 ')"> </td><td data-color=' + count + '>' + count + ' (' + (count / (data.width * data.height) * 100).toFixed(3) + '%)</tr>';
111 }
112 colorTable += '</table>';
113 stats.innerHTML = '<h3>file stats</h3><table><tr>' +
114 '<th>name</th><td>' + data.fileName +
115 '</td></tr><tr><th>size</th><td>' + data.fileSize +
116 '</td></tr><tr><th>type</th><td>' + data.fileType +
117 '</td></tr><tr><th>width</th><td>' + data.width +
118 '</td></tr><tr><th>height</th><td>' + data.height +
119 '</td></tr></table><h3>pixel color distribution</h3>' + colorTable;
120 }
121 ).catch(
122 error => console.log(error)
123 );
124};