[in progress] a color utility i'm making for my pixel art painting process www.val.town/x/jennschiffer/pixelstats
at main 124 lines 3.7 kB view raw
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};