/src/Palette.js
import Controller from './Controller.js';
const palette_names = [
"EGA 16-color",
"Gray/RGB",
"Red/Blue/Yellow",
"Purple/Orange/Green",
"Red/Green",
"Orange/Blue",
"Yellow/Purple",
"Red",
"Green",
"Blue",
];
const palettes = [
[ // Palette 0 - EGA 16-color
[0x00, 0x00, 0x00], // black
[0x00, 0x00, 0xAA], // blue
[0x00, 0xAA, 0x00], // green
[0x00, 0xAA, 0xAA], // cyan
[0xAA, 0x00, 0x00], // red
[0xAA, 0x00, 0xAA], // magenta
[0xAA, 0x55, 0x00], // brown
[0xAA, 0xAA, 0xAA], // light gray
[0x55, 0x55, 0x55], // dark gray
[0x55, 0x55, 0xFF], // bright blue
[0x55, 0xFF, 0x55], // bright green
[0x55, 0xFF, 0xFF], // bright cyan
[0xFF, 0x55, 0x55], // bright red
[0xFF, 0x55, 0xFF], // bright magenta
[0xFF, 0xFF, 0x55], // bright yellow
[0xFF, 0xFF, 0xFF], // white
],
[ // Palette 1 - Gray4/R4/G4/B4
[0x00, 0x00, 0x00],
[0x3B, 0x3B, 0x3B],
[0x76, 0x76, 0x76],
[0xB8, 0xB8, 0xB8],
[0x68, 0x00, 0x00],
[0x9E, 0x00, 0x00],
[0xD7, 0x00, 0x00],
[0xFE, 0x41, 0x41],
[0x00, 0x39, 0x00],
[0x00, 0x59, 0x00],
[0x00, 0x7C, 0x00],
[0x00, 0xA0, 0x00],
[0x00, 0x2B, 0x71],
[0x00, 0x46, 0xAA],
[0x00, 0x61, 0xE7],
[0x54, 0x83, 0xFE],
],
[ // Palette 2 - Black/R5/B5/Yellow5
[0x00, 0x00, 0x00],
[0x54, 0x00, 0x00],
[0x7D, 0x00, 0x00],
[0xA9, 0x00, 0x00],
[0xD7, 0x00, 0x00],
[0xFE, 0x27, 0x28],
[0x00, 0x22, 0x5B],
[0x00, 0x36, 0x87],
[0x00, 0x4B, 0xB6],
[0x00, 0x61, 0xE7],
[0x44, 0x7C, 0xFE],
[0x43, 0x43, 0x00],
[0x70, 0x70, 0x00],
[0xA1, 0xA1, 0x00],
[0xD4, 0xD5, 0x00],
[0xFF, 0xFE, 0xFE],
],
[ // Palette 3 - Black/Purple5/Orange5/Green5
[0x00, 0x00, 0x00],
[0x4B, 0x00, 0x43],
[0x70, 0x00, 0x65],
[0x98, 0x00, 0x89],
[0xC1, 0x00, 0xAF],
[0xED, 0x00, 0xD6],
[0x48, 0x2D, 0x00],
[0x73, 0x4B, 0x00],
[0xA2, 0x6B, 0x00],
[0xD2, 0x8D, 0x00],
[0xFF, 0xB2, 0x48],
[0x00, 0x2D, 0x00],
[0x00, 0x46, 0x00],
[0x00, 0x60, 0x00],
[0x00, 0x7C, 0x00],
[0x00, 0x99, 0x00],
],
[ // Palette 4 - Red/Green
[0x41, 0x00, 0x00],
[0x68, 0x00, 0x00],
[0x7D, 0x00, 0x00],
[0x93, 0x00, 0x00],
[0xA9, 0x00, 0x00],
[0xC0, 0x00, 0x00],
[0xD7, 0x00, 0x00],
[0xEF, 0x00, 0x00],
[0x00, 0x21, 0x00],
[0x00, 0x39, 0x00],
[0x00, 0x46, 0x00],
[0x00, 0x53, 0x00],
[0x00, 0x60, 0x00],
[0x00, 0x6E, 0x00],
[0x00, 0x7C, 0x00],
[0x00, 0x8A, 0x00],
],
[ // Palette 5 - Orange/Blue
[0x48, 0x2D, 0x00],
[0x5D, 0x3C, 0x00],
[0x73, 0x4B, 0x00],
[0x8A, 0x5B, 0x00],
[0xA2, 0x6B, 0x00],
[0xBA, 0x7B, 0x00],
[0xD2, 0x8D, 0x00],
[0xEC, 0x9E, 0x00],
[0x00, 0x22, 0x5B],
[0x00, 0x2B, 0x71],
[0x00, 0x36, 0x87],
[0x00, 0x40, 0x9E],
[0x00, 0x4B, 0xB6],
[0x00, 0x56, 0xCE],
[0x00, 0x61, 0xE7],
[0x0D, 0x6D, 0xFE],
],
[ // Palette 6 - Yellow/Purple
[0x2E, 0x2E, 0x00],
[0x59, 0x59, 0x00],
[0x70, 0x70, 0x00],
[0x88, 0x88, 0x00],
[0xA1, 0xA1, 0x00],
[0xBA, 0xBB, 0x00],
[0xD4, 0xD5, 0x00],
[0xEF, 0xEF, 0x00],
[0x39, 0x00, 0x33],
[0x5D, 0x00, 0x53],
[0x70, 0x00, 0x65],
[0x83, 0x00, 0x77],
[0x98, 0x00, 0x89],
[0xAC, 0x00, 0x9C],
[0xC1, 0x00, 0xAF],
[0xD7, 0x00, 0xC2],
],
[ // Palette 7 - Red
[0x22, 0x00, 0x00],
[0x32, 0x00, 0x00],
[0x3E, 0x00, 0x00],
[0x4A, 0x00, 0x00],
[0x56, 0x00, 0x00],
[0x63, 0x00, 0x00],
[0x70, 0x00, 0x00],
[0x7D, 0x00, 0x00],
[0x8B, 0x00, 0x00],
[0x98, 0x00, 0x00],
[0xA6, 0x00, 0x00],
[0xB4, 0x00, 0x00],
[0xC3, 0x00, 0x00],
[0xD1, 0x00, 0x00],
[0xE0, 0x00, 0x00],
[0xEF, 0x00, 0x00],
],
[ // Palette 8 - Green
[0x00, 0x0F, 0x00],
[0x00, 0x18, 0x00],
[0x00, 0x20, 0x00],
[0x00, 0x27, 0x00],
[0x00, 0x2E, 0x00],
[0x00, 0x36, 0x00],
[0x00, 0x3E, 0x00],
[0x00, 0x46, 0x00],
[0x00, 0x4E, 0x00],
[0x00, 0x56, 0x00],
[0x00, 0x5F, 0x00],
[0x00, 0x67, 0x00],
[0x00, 0x70, 0x00],
[0x00, 0x78, 0x00],
[0x00, 0x81, 0x00],
[0x00, 0x8A, 0x00],
],
[ // Palette 9 - Blue
[0x00, 0x09, 0x25],
[0x00, 0x11, 0x37],
[0x00, 0x17, 0x44],
[0x00, 0x1D, 0x50],
[0x00, 0x23, 0x5E],
[0x00, 0x29, 0x6B],
[0x00, 0x2F, 0x79],
[0x00, 0x36, 0x87],
[0x00, 0x3C, 0x95],
[0x00, 0x43, 0xA4],
[0x00, 0x4A, 0xB3],
[0x00, 0x51, 0xC2],
[0x00, 0x58, 0xD1],
[0x00, 0x5F, 0xE1],
[0x00, 0x66, 0xF1],
[0x0D, 0x6D, 0xFE],
],
]
export default class Palette extends Controller {
constructor(appState) {
super(appState);
this.node = document.getElementById('palette');
this.swatches = [];
for (let i = 0; i < this.node.children.length; i++) {
let c = this.node.children[i];
if (c.className == 'swatch') {
let n = this.swatches.length;
c.addEventListener('mousedown', event => this.selectColor(n))
c.addEventListener('dblclick', event => this.editColor(n));
this.swatches.push(c);
}
}
this.selectPalette(0);
this.selectColor(0);
}
selectPalette(n) {
this.palette = n;
let p = palettes[n];
for (i = 0; i < 16; i++) {
this.swatches[i].style.backgroundColor = 'rgb(' + p[i][0] + ',' + p[i][1] + ',' + p[i][2] + ')';
}
document.getElementById('palette-id').textContent = palette_names[n];
}
nextPalette() {
this.selectPalette((this.palette + 1) % palettes.length);
}
prevPalette() {
let newPalette = this.palette - 1;
if (newPalette < 0)
newPalette = palettes.length - 1;
this.selectPalette(newPalette);
}
selectColor(n) {
if (this.color != undefined)
this.swatches[this.color].className = 'swatch';
this.color = n;
this.swatches[this.color].className = 'swatch selected';
}
getCSSColor(i = this.color) {
let c = palettes[this.palette][i];
return 'rgb(' + c[0] + ',' + c[1] + ',' + c[2] + ')';
}
findClosestColor(rgbdata) {
let closest = 0;
let distance = 1e9;
for (let i = 0; i < 16; i++) {
let tc = palettes[this.palette][i];
let d = Math.pow(
Math.abs(tc[0] - rgbdata[0]) + Math.abs(tc[1] - rgbdata[1]) + Math.abs(tc[2] - rgbdata[2]),
1/3
);
if (d < distance) {
closest = i;
distance = d;
}
}
return closest;
}
editColor(n) {
let colorpicker = document.getElementById('dialog-colorpicker');
colorpicker.style.display = null;
let colorpicker_color = document.getElementById('colorpicker-color');
let colorpicker_red = document.getElementById('colorpicker-red');
let colorpicker_green = document.getElementById('colorpicker-green');
let colorpicker_blue = document.getElementById('colorpicker-blue');
let colorpicker_ok = document.getElementById('colorpicker-ok');
let colorpicker_cancel = document.getElementById('colorpicker-cancel');
let currentPalette = this.palette;
colorpicker_red.value = palettes[currentPalette][n][0];
colorpicker_green.value = palettes[currentPalette][n][1];
colorpicker_blue.value = palettes[currentPalette][n][2];
let changefunc = () => {
let r = colorpicker_red.value;
let g = colorpicker_green.value;
let b = colorpicker_blue.value;
colorpicker_color.style.backgroundColor = 'rgb(' + r + ',' + g + ',' + b + ')';
};
colorpicker_red.onkeyup = changefunc;
colorpicker_green.onkeyup = changefunc;
colorpicker_blue.onkeyup = changefunc;
changefunc();
colorpicker_cancel.onclick = () => {
colorpicker.style.display = 'none';
}
colorpicker_ok.onclick = () => {
palette_names[currentPalette] = "Custom " + n;
let r = colorpicker_red.value;
let g = colorpicker_green.value;
let b = colorpicker_blue.value;
palettes[currentPalette][n] = [r, g, b];
this.selectPalette(currentPalette);
this.state.pixelEditor.redraw();
this.state.pixelEditor.refresh();
colorpicker.style.display = 'none';
}
}
}