// http://www.html5rocks.com/en/tutorials/file/dndfiles/ var num_files, dropzone, curlist, outlist, numdisplay, files, scale_x = 1, scale_y = 1, digitsize = 1, palette, palettes, palette_name, palette_names, palette_elem, palette_elems, max = Math.max, min = Math.min, round = Math.round, abs = Math.abs; function load() { // Set up the global element references dropzone = document.getElementById("dropzone"); curlist = document.getElementById("curlist"); outlist = document.getElementById("outlist"); numdisplay = document.getElementById("num_files"); num_files = 0; // Set up the drag & drop listeners. // dropzone.addEventListener("click", handleFileClick, false); dropzone.onchange = handleInputChange; dropzone.ondragover = handleDragOver; dropzone.ondragleave = handleDragOff; dropzone.ondrop = handleFileSelect; // Set up the palettes initializePalettes(); // Scale // var scales = document.getElementsByTagName("input"), alphas = ["x", "y"]; // for(var i = 0, scale, len = scales.length; i < len; ++i) { // scale = scales[i]; // scale.onclick = scale.onchange = scale.onkeydown = setScaleValue; // scale.alpha = alphas[i]; // } } function handleInputChange(event) { dropzone.ondragleave(); event.target.ondragleave(); console.log(window.e = event); } function handleFileSelect(event) { preventAll(event); this.style.backgroundColor = ""; var files = window.files = event.dataTransfer.files, output = [], type; for(var i = 0, f; f = files[i]; i++) { type = f.type.split("/")[1]; // Only images allowed! if(type == "gif" || type == "png" || type == "jpeg" || type == "jpg") { ++num_files; output.push("
  • ", f.name, " (", type, ")"); outlist.appendChild(getWorkerElement(f)); } else output.push("
  • Only images are supported! (" + type + ")
  • "); } // Update output & outlist dropzone.innerHTML = files.length + " file" + (files.length == 1 ? "" : "s") + " selected" curlist.innerHTML = output.join(""); // numdisplay.innerHTML = "Showing " + num_files + " file" + (num_files == 1 ? "" : "s") + ":"; } function getWorkerElement(file) { var element = getOutputListElement(file.name), reader = new FileReader(); // Set up the file upload reader.onprogress = updateProgress; reader.element = element; // Once the upload finishes, start the worker reader.onloadend = startWorking; // Start the upload reader.readAsDataURL(file); return element; } function getOutputListElement(name) { var element = document.createElement("li"), status = document.createElement("div"), progress = document.createElement("div"), base64 = document.createElement("div"), results = document.createElement("div"), close = document.createElement("div"); element.name = name; element.statusbase = status.innerText = "Uploading " + name + "..."; element.status = status; element.progress = progress element.base64 = base64, element.results = results; element.close = close; element.appendChild(status); element.appendChild(progress); element.appendChild(base64); element.appendChild(results); element.appendChild(close); status.className = "status"; element.className = "output"; progress.className = "progress"; base64.className = "base64"; results.className = "results"; close.className = "close"; setTextDisplayer(base64, "Base 64"); setTextDisplayer(results, "Sprite"); return element; } function updateProgress(event) { if(event.lengthComputable) { var percentLoaded = round((event.loaded / event.total) * 100); // Increase the progress bar length. if(percentLoaded <= 100) { this.element.status.innerText = this.element.statusbase + " (" + percentLoaded + "%)"; this.element.progress.style.width = percentLoaded + "%"; } } } function startWorking(event) { var reader = event.currentTarget, element = reader.element, result = reader.result; // Update visually setTimeout(function() { element.status.innerText = "Working on " + element.name + "..."; element.progress.style.backgroundColor = "rgb(117,175,245)"; }, 350); setDisplayerText(element.base64, result); // Create the canvas var canvas = document.createElement("canvas"), context = canvas.getContext("2d"); // Create the image var img = document.createElement("image"); img.src = result; // Draw & parse the image once it's loaded img.onload = function() { canvas.width = img.width; canvas.height = img.height; context.drawImage(img, 0, 0); // var data = context.getImageData(0, 0, img.width / scale_x, img.height / scale_y); var data = context.getImageData(0, 0, img.width, img.height), output; // Update visually, then work setTimeout(function() { element.status.innerHTML = "" + element.name + "(" + palette_name + ")"; element.status.style.color = "white"; element.progress.style.backgroundColor = "rgb(35,35,70)"; // Pass the data to the parser (to do: use a worker) output = parseData(data.data, element, palette); setDisplayerText(element.results, output); }, 350); } } function parseData(data, element) { var outs = [], occurences = {}, me, i, j, len = data.length; // For each rgba pixel, get the closest color in the current palette_parsed // Also count the occurences for(i = 0, j = 0; i < len; i += 4, ++j) { // outs[j] = getClosestPalette(data.slice(i, i + 4)); me = outs[j] = getClosestPalette([data[i], data[i+1], data[i+2], data[i+3]]); if(occurences[me]) ++occurences[me]; else occurences[me] = 1; } // Iterate through, repeating loops return combineSimilarChars(outs, getNewPaletteFromOccurences(occurences)); } // To do: allow for digitsize != 1? // Paletteinfo = [newpalette, digitsize] function combineSimilarChars(textraw, paletteinfo) { var newpalette = paletteinfo[0], digitsize = paletteinfo[1], threshold = max(3, round(4 / digitsize)), text = "", i, j, len, cur; console.log(digitsize); for(i = 0, len = textraw.length; i < len; ++i) { j = i + 1; // Duplicates found // Order is 'x char times ,' cur = textraw[i]; while(cur == textraw[j]) ++j; // += digitsize? if(j - i > threshold) { text += "x" + makedigit(cur, digitsize, newpalette) + String(j - i) + ","; i = j - 1; } else text += makedigit(cur, digitsize, newpalette); } return "p[" + grabKeys(newpalette) + "]" + text; } function getNewPaletteFromOccurences(occurences) { var counts = [], key, len = 0; for(key in occurences) { counts[key] = len; ++len; } console.log(len); return [counts,getDigitSizeFromLength(len)]; } function makedigit(num, digitsize, newpalette) { return fillChars(max(0, digitsize - String(num).length), "0") + newpalette[num]; } function fillChars(num, a) { var text = ""; while(num--) text += a; return text; } function grabKeys(object) { var output = [], i; for(i in object) output.push(i); return output.join(","); } function getClosestPalette(rgba) { var i, bestloc, diff, bestdiff = Infinity; for(i = palette.length - 1; i >= 0; --i) { diff = arrayDiff(rgba, palette[i]); if(diff < bestdiff) { bestdiff = diff; bestloc = i; } } return bestloc; } // Assumes equal size function arrayDiff(a, b) { var sum = 0, i; for(i = a.length - 1; i >= 0; --i) sum += abs(a[i] - b[i]); return sum; } function arrayEquals(a,b) { return !(a"; // Add the squares for(j = 0; j < current.length; ++j) { square = document.createElement("div"); squarein = document.createElement("div"); square.className = "square"; squarein.className = "squarein"; squarein.style.background = getColorFromArray(current[j]); square.appendChild(squarein); mine.appendChild(square); } // Set the events mine.palettenum = i; mine.onclick = setCurrentPalette; mine.className = "squares"; container.appendChild(mine); } palette_elems[localStorage.palette_num || 0].click(); } function getColorFromArray(arr) { // if(arr.reduce(sum) < 7) return ""; return "rgba(" + arr.join(", ") + ")"; } function setCurrentPalette(event) { var num = this.palettenum; palette = palettes[num]; palette_name = palette_names[num]; digitsize = getDigitSize(palette); digitsize = palette.length >= 10 ? 2 : 1; if(palette_elem) palette_elem.className = "squares"; palette_elem = this; this.className = "squares selected"; localStorage.palette_num = num; } function getDigitSize(palette) { return Number(String(palette.length).length) } function getDigitSizeFromLength(length) { return Number(String(length).length) } function setScaleValue(event) { window["scale_" + this.alpha] = Number(this.value) || 1; } function sum(a,b) { return Number(a) + Number(b); }