diff --git a/css/collapsible.css b/css/collapsible.css
index 84465fc..0f7ce42 100644
--- a/css/collapsible.css
+++ b/css/collapsible.css
@@ -1 +1 @@
-.collabsible-wrapper{margin-bottom:1.2rem 0;position:fixed;top:20px;right:20px;z-index:1000;width:600px}.collapsible-content{max-height:0px;background:rgba(8,8,8,.937254902);width:calc(100% - 10px);top:0;padding:0;margin:0;overflow:hidden;transition:max-height .25s ease-in-out;border-bottom-left-radius:4px;border-bottom-right-radius:4px}input#collapsible[type=checkbox]{display:none}.lbl-toggle{display:block;font-weight:bold;font-family:monospace;font-size:16px;text-transform:uppercase;padding:.5rem 1rem;color:#fff;background:#000;cursor:pointer;border-radius:4px;transition:all .25s ease-out;user-select:none}.lbl-toggle:hover{color:#ccc}.lbl-toggle::before{content:" ";display:inline-block;border-top:5px solid rgba(0,0,0,0);border-bottom:5px solid rgba(0,0,0,0);border-left:5px solid currentColor;vertical-align:middle;margin-right:.7rem;transform:translateY(-2px);transition:transform .2s ease-out}.toggle:checked+.lbl-toggle::before{transform:rotate(90deg) translateX(-2px)}.toggle:checked+.lbl-toggle+.collapsible-content{max-height:100vh}.toggle:checked+.lbl-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}
\ No newline at end of file
+.collapsible-content{max-height:0px;background:rgba(8,8,8,.937254902);width:100%;top:0;padding:0;margin:0;overflow:hidden;transition:max-height .25s ease-in-out;border-bottom-left-radius:4px;border-bottom-right-radius:4px}input.toggle[type=checkbox]{display:none}.lbl-toggle{display:block;font-weight:bold;font-size:16px;text-transform:uppercase;padding:.5rem 1rem;color:#fff;background:#000;cursor:pointer;border-radius:4px;transition:all .25s ease-out;user-select:none}.lbl-toggle:hover{color:#ccc}.lbl-toggle::before{content:"";display:inline-block;border-top:5px solid rgba(0,0,0,0);border-bottom:5px solid rgba(0,0,0,0);border-left:5px solid currentColor;vertical-align:middle;margin-right:.7rem;transform:translateY(-2px);transition:transform .2s ease-out}.toggle:checked+.lbl-toggle::before{transform:rotate(90deg) translateX(-2px)}.toggle:checked+.lbl-toggle+.collapsible-content{max-height:100vh}.toggle:checked+.lbl-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}
\ No newline at end of file
diff --git a/css/image-drop.css b/css/image-drop.css
new file mode 100644
index 0000000..87b27ec
--- /dev/null
+++ b/css/image-drop.css
@@ -0,0 +1 @@
+#drop-area{border:2px dashed #ccc;padding:10px;margin:10px;text-align:center;width:200px;border-radius:10px;cursor:pointer}#drop-area label{cursor:pointer}#drop-area.highlight{border-color:#2185d0}#image-preview{max-width:100%;image-rendering:pixelated;position:absolute}
\ No newline at end of file
diff --git a/css/styles.css b/css/styles.css
index af9b05c..f32fb1f 100644
--- a/css/styles.css
+++ b/css/styles.css
@@ -1 +1 @@
-*{box-sizing:border-box}html,body{margin:0;background:#222;font-family:Arial}body{margin:20px}h1{color:#fff;font-size:18px;line-height:0}p,#downloadlink{color:#ccc;font-size:12px;padding:.5rem}#output{height:50vh;padding:10px;margin:0;color:#fff;width:100%;border:0;outline:none;background:none;font-family:courier;font-weight:bold;font-size:10px;overflow:scroll}table{background:#000;border-collapse:collapse;font-size:10px;color:#aaa;text-align:left;font-family:courier;font-weight:bold}thead td{padding:10px}td{border:0;padding:0 20px;margin:0;border:1px solid #222}tr{padding:0;margin:0;height:6px;position:relative}tr:hover{background:#333}.cell,.cell-odd,.cell-even{width:16px;height:16px}.cell{position:relative}.cell-odd{position:absolute;display:none}.odd .cell-odd{display:block}.cell-even{position:absolute;display:block}.odd .cell-even{display:none}select{margin-bottom:20px;margin-right:30px}label{font-size:12px;margin-right:10px;color:#fff}#canvas-container{position:relative}#canvas{position:absolute;display:block;margin-bottom:20px;cursor:pointer}#canvas-alt{opacity:0}.odd #canvas-alt{opacity:1}#canvas{opacity:1}.odd #canvas{opacity:0}#text{background:none;border:none;color:#fff;width:30px}#slider{-webkit-appearance:none;height:2px;background:#fff;outline:none;padding:0;margin:0}#slider::-webkit-slider-thumb{-webkit-appearance:none;outline:none;width:16px;height:16px;border-radius:50%;background:#fff;cursor:pointer}
\ No newline at end of file
+*{box-sizing:border-box;font-family:monospace}html,body{margin:0;background:#222;font-family:Arial}body{margin:20px}h1{color:#fff;font-size:18px;line-height:0}p,#downloadlink{color:#ccc;font-size:12px}#downloadlink{padding:.5rem}input{cursor:pointer}#output{height:50vh;padding:10px;margin:0;color:#fff;width:100%;border:0;outline:none;background:none;font-family:courier;font-weight:bold;font-size:10px;overflow:scroll}table{background:#000;border-collapse:collapse;font-size:10px;color:#aaa;text-align:left;font-family:courier;font-weight:bold;margin-top:10px}thead td{padding:10px}td{border:0;padding:0 20px;margin:0;border:1px solid #222}tr{padding:0;margin:0;height:6px;position:relative}tr:hover{background:#333}.cell,.cell-odd,.cell-even{width:16px;height:16px}.cell{position:relative}.cell-odd{position:absolute;display:none}.odd .cell-odd{display:block}.cell-even{position:absolute;display:block}.odd .cell-even{display:none}select{margin-right:20px;cursor:pointer;font-size:11px}label{font-size:10px;color:#fff}canvas{image-rendering:pixelated}#canvas-container{position:relative}#canvas{position:absolute;display:block;margin-bottom:20px;cursor:pointer}#canvas-alt{opacity:0}.odd #canvas-alt{opacity:1}#canvas{opacity:1}.odd #canvas{opacity:0}#image-1{position:absolute;opacity:0}.odd #image-1{opacity:1}#image-2{position:absolute;opacity:1}.odd #image-2{opacity:0}#text{background:none;border:none;padding-left:5px;color:#fff;font-size:10px;width:40px}#slider{-webkit-appearance:none;height:2px;background:#fff;outline:none;padding:0;margin:0}#slider::-webkit-slider-thumb{-webkit-appearance:none;outline:none;width:16px;height:16px;border-radius:50%;background:#fff;cursor:pointer}.side-panel{margin-bottom:1.2rem 0;position:fixed;top:20px;right:20px;z-index:1000;bottom:20px;width:600px;overflow-y:scroll}
\ No newline at end of file
diff --git a/index.html b/index.html
index e451eab..81fae01 100644
--- a/index.html
+++ b/index.html
@@ -1 +1 @@
-
C64 Palette ExplorerRetro C64 Palette Explorer v0.53
by Digger/Elysium © 2016-24
\ No newline at end of file
+C64 Palette ExplorerRetro C64 Palette Explorer v0.6.1
by Digger/Elysium © 2016-24
\ No newline at end of file
diff --git a/js/file-upload.js b/js/file-upload.js
new file mode 100644
index 0000000..390a04d
--- /dev/null
+++ b/js/file-upload.js
@@ -0,0 +1,50 @@
+var FileUpload;
+
+FileUpload = class FileUpload {
+ static handleDragOver(event) {
+ event.preventDefault();
+ return document.getElementById('drop-area').classList.add('highlight');
+ }
+
+ static handleDragLeave(event) {
+ event.preventDefault();
+ return document.getElementById('drop-area').classList.remove('highlight');
+ }
+
+ static handleDrop(event) {
+ var files;
+ event.preventDefault();
+ document.getElementById('drop-area').classList.remove('highlight');
+ files = event.dataTransfer.files;
+ if (files.length > 0) {
+ return this.handleFile(files[0]);
+ }
+ }
+
+ static handleFileSelect(event) {
+ var files;
+ files = event.target.files;
+ if (files.length > 0) {
+ return this.handleFile(files[0]);
+ }
+ }
+
+ static handleFile(file) {
+ var imagePreview, reader;
+ imagePreview = document.getElementById('image-preview');
+ if (file.type.startsWith('image/')) {
+ reader = new FileReader();
+ reader.onload = function(event) {
+ var data;
+ data = event.target.result;
+ imagePreview.src = data;
+ imagePreview.style = "display: block";
+ return ProcessImage.processImage(data);
+ };
+ return reader.readAsDataURL(file);
+ } else {
+ return alert('Please select a valid image file.');
+ }
+ }
+
+};
diff --git a/js/main.js b/js/main.js
index ebea7cb..9166ffb 100644
--- a/js/main.js
+++ b/js/main.js
@@ -3,6 +3,7 @@ var Main, main;
Main = (function() {
class Main {
constructor() {
+ this.imageContainer = document.getElementById('image-container');
this.canvasContainer = document.getElementById('canvas-container');
this.canvasContainer.addEventListener('click', (event) => {
this.scale = this.scale === 1 ? 2 : 1;
@@ -30,7 +31,6 @@ Main = (function() {
this.ditherSelect = document.getElementById('dither');
this.ditherSelect.onchange = (event) => {
this.ditherType = event.target.options[event.target.selectedIndex].value;
- console.log(this.ditherType);
if (this.ditherType === 'lace') {
this.stopLoop = false;
this.loop();
@@ -39,7 +39,8 @@ Main = (function() {
this.stopLoop = true;
setTimeout(() => {
this.table.classList.remove('odd');
- return this.canvasContainer.classList.remove('odd');
+ this.canvasContainer.classList.remove('odd');
+ return this.imageContainer.classList.remove('odd');
}, 100);
}
return this.filter();
@@ -75,7 +76,8 @@ Main = (function() {
; slots will be set to white (FFFFFFFF). If there are more, then the remaining colors will be ignored.
`;
this.mixed = [];
- this.json = [];
+ Main.json = {};
+ this.paletteData = [];
for (index1 = j = 0; j <= 15; index1 = ++j) {
for (index2 = k = ref = index1; (ref <= 0xf ? k <= 0xf : k >= 0xf); index2 = ref <= 0xf ? ++k : --k) {
col1 = ColorUtils.colorToHEX(this.palette[index1]);
@@ -88,14 +90,8 @@ Main = (function() {
distance = ColorUtils.getHEXDistance(col1, col2);
diffLuma = Math.abs(Palettes.lumas[index1] - Palettes.lumas[index2]) / 32;
diffL = Math.abs(col2HSL.l - col1HSL.l);
- if (this.paletteType === 'PICO8') {
- if (diffL > this.lumaDiffThreshold) {
- continue;
- }
- } else {
- if (diffLuma > this.lumaDiffThreshold) {
- continue;
- }
+ if (diffLuma > this.lumaDiffThreshold) {
+ continue;
}
// if @excludeNative and (col1 is col2) then continue
if (this.excludeNative && (col1 !== col2)) {
@@ -145,10 +141,10 @@ Main = (function() {
distToGreen: ColorUtils.getHEXDistance(mix, ColorUtils.colorToHEX(0x00ff00)),
distToBlue: ColorUtils.getHEXDistance(mix, ColorUtils.colorToHEX(0x0000ff))
});
- // @json.push
- // index1: index1
- // index2: index2
- // mix: mix
+ Main.json[mix] = {
+ color1: ColorUtils.colorToHEX(this.palette[index1]),
+ color2: ColorUtils.colorToHEX(this.palette[index2])
+ };
this.output.value += mix.split('#').join('ff').toUpperCase() + '\n';
}
}
@@ -159,13 +155,11 @@ Main = (function() {
this.output.value += 'FFFFFFFF' + '\n';
}
}
- this.json = this.output.value;
+ this.paletteData = this.output.value;
+ log(this.json);
}
filter() {
- if (this.paletteType === 'PICO8') {
- this.sortBy = this.sortBy.join(',').replace('luma', 'l').split(',');
- }
this.createData();
this.sortBy.unshift('diffLuma');
if (this.sortBy.length > 0) {
@@ -174,11 +168,11 @@ Main = (function() {
this.createTable();
this.fillTable();
this.drawColors();
- // @createGradient()
- // @print JSON.stringify @json
- this.print(this.json);
}
+ // @createGradient()
+ // @print JSON.stringify @json
+ // @print @paletteData
print(buffer) {
FileSaver.saveAsTextFile(buffer);
}
@@ -252,7 +246,7 @@ Main = (function() {
while (this.table.firstChild) {
this.table.removeChild(this.table.firstChild);
}
- fields = ["#", "mixed", "color1", "color2", "color1", "color2", "RGB distance", "hue", "saturation", "luma", "luma diff", "hex luma", "hex luma diff", "hex value"];
+ fields = ["# of ", "mixed", "#col1", "#col2", "col1", "col2", "RGB dist", "hue", "saturation", "luma", "luma diff", "hex luma", "hex luma diff", "hex value"];
header = this.table.createTHead();
row = header.insertRow(0);
for (i = j = 0, len = fields.length; j < len; i = ++j) {
@@ -312,7 +306,7 @@ Main = (function() {
}
fillTable() {
- var body, canvas, cellSize, context, i, j, len, obj, ref, row;
+ var body, canvas, cellSize, context, i, j, len, numCols, obj, ref, ref1, ref2, row;
cellSize = 16;
body = this.table.createTBody();
ref = this.mixed;
@@ -343,12 +337,15 @@ Main = (function() {
row.insertCell(11).innerHTML = obj.l.toFixed(2);
row.insertCell(12).innerHTML = obj.diffL.toFixed(4);
row.insertCell(13).innerHTML = obj.mix;
+ numCols = (ref1 = this.table.querySelector('thead')) != null ? (ref2 = ref1.childNodes[0]) != null ? ref2.childNodes[0] : void 0 : void 0;
+ numCols.innerHTML = '#/' + this.mixed.length;
}
}
loop() {
this.table.classList.toggle('odd');
this.canvasContainer.classList.toggle('odd');
+ this.imageContainer.classList.toggle('odd');
if (this.stopLoop) {
return;
}
@@ -377,6 +374,8 @@ Main = (function() {
Main.prototype.stopLoop = false;
+ Main.json = {};
+
return Main;
}).call(this);
diff --git a/js/palettes.js b/js/palettes.js
index dd7365d..76c94e0 100644
--- a/js/palettes.js
+++ b/js/palettes.js
@@ -46,8 +46,6 @@ Palettes = (function() {
Palettes.JAMPAL = [0x000000, 0xffffff, 0x7d202c, 0x4fb3a5, 0x84258c, 0x339840, 0x2a1b9d, 0xbfd04a, 0x7f410d, 0x4c2e00, 0xb44f5c, 0x3c3c3c, 0x646464, 0x7ce587, 0x6351db, 0x939393];
- Palettes.PICO8 = [0x000000, 0x161e42, 0x6b1442, 0x03783e, 0x9b3e26, 0x4d453e, 0xb5b6bb, 0xffeee2, 0xff0039, 0xff9300, 0xffff00, 0x0bea3c, 0x1c98ff, 0x70608b, 0xff5a97, 0xffc197];
-
Palettes.DEEKAY = [
0x000000, //0
0xffffff, //1
diff --git a/js/process-image.js b/js/process-image.js
new file mode 100644
index 0000000..6b5e025
--- /dev/null
+++ b/js/process-image.js
@@ -0,0 +1,66 @@
+var ProcessImage;
+
+ProcessImage = class ProcessImage {
+ static processImage(data) {
+ var img;
+ this.canvas = document.createElement('canvas');
+ this.context = this.canvas.getContext('2d');
+ this.canvas1 = document.getElementById('image-1');
+ this.canvas2 = document.getElementById('image-2');
+ this.context1 = this.canvas1.getContext('2d');
+ this.context2 = this.canvas2.getContext('2d');
+ img = new Image();
+ img.src = data;
+ return img.onload = () => {
+ var imageData, pixelData;
+ this.canvas.width = img.width;
+ this.canvas.height = img.height;
+ this.canvas1.width = img.width;
+ this.canvas1.height = img.height;
+ this.canvas1.imageSmoothingEnabled = false;
+ this.canvas2.width = img.width;
+ this.canvas2.height = img.height;
+ this.canvas2.imageSmoothingEnabled = false;
+ this.context.drawImage(img, 0, 0);
+ imageData = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height).data;
+ return pixelData = this.processPixelData(imageData);
+ };
+ }
+
+ // console.table(pixelData)
+ static processPixelData(imageData) {
+ var b, color1, color2, g, hex, i, j, pixelData, r, ref, ref1, ref2, x, y;
+ pixelData = {};
+ for (i = j = 0, ref = imageData.length; j < ref; i = j += 4) {
+ r = imageData[i];
+ g = imageData[i + 1];
+ b = imageData[i + 2];
+ hex = this.rgbToHex(r, g, b);
+ pixelData[hex] = (pixelData[hex] || 0) + 1;
+ // plot pixel on canvas1 with color1
+ x = (i / 4) % this.canvas.width;
+ y = Math.floor((i / 4) / this.canvas.width);
+ color1 = (ref1 = Main.json[hex]) != null ? ref1.color1 : void 0;
+ this.context1.fillStyle = color1;
+ this.context1.fillRect(x, y, 1, 1);
+ color2 = (ref2 = Main.json[hex]) != null ? ref2.color2 : void 0;
+ this.context2.fillStyle = color2;
+ this.context2.fillRect(x, y, 1, 1);
+ }
+ return pixelData;
+ }
+
+ static componentToHex(c) {
+ var hex;
+ hex = c.toString(16);
+ if (hex.length === 1) {
+ return '0' + hex;
+ }
+ return hex;
+ }
+
+ static rgbToHex(r, g, b) {
+ return '#' + this.componentToHex(r) + this.componentToHex(g) + this.componentToHex(b);
+ }
+
+};