wip colors

This commit is contained in:
Brooke Vibber 2023-03-18 21:56:36 -07:00
parent a8bbcb21cd
commit 365d968448

View file

@ -407,6 +407,18 @@ function decimate(input, palette, n, inputError) {
let width = input.length;
let inputPixel = (x, error) => {
let rgb = input[x];
if (error) {
rgb.add(error.cur[x]);
}
if (inputError) {
rgb.inc(inputError[x]);
}
rgb.cap();
return rgb;
};
// Apply dithering with given palette and collect color usage stats
let dither = (palette) => {
let fitness = new Float64Array(width);
@ -426,11 +438,7 @@ function decimate(input, palette, n, inputError) {
// Try dithering with this palette.
for (let x = 0; x < width; x++) {
let rgb = RGB.add(input[x], error.cur[x]);
if (inputError) {
rgb.inc(inputError[x]);
}
rgb.cap();
let rgb = inputPixel(x, error);
// find the closest possible color
// @todo consider doing the difference scoring in luminance and hue spaces
@ -487,16 +495,62 @@ function decimate(input, palette, n, inputError) {
//decimated = [0, 0x36, 0x0f, 0x86];
let reserved = [0]; // black
//let reserved = [0, 15]; // black, white
//let reserved = [0, 5, 10, 15]; // grayscale
//let reserved = [0, 0x48, 0x78, 15]; // vaporwave
//let reserved = [0, 0x3c, 0x78, 15]; // red/blue/white
//reserved = [0, 15]; // black, white
//reserved = [0, 5, 10, 15]; // grayscale
//reserved = [0, 0x48, 0x78, 15]; // vaporwave
//reserved = [0, 0x3c, 0x78, 15]; // red/blue/white
let keepers = new Uint8Array(256);
for (let i of reserved) {
keepers[i & 0xfe] = 1; // drop that 0 luminance bit!
}
// not happy with this alt yet
let colorCount = new Int32Array(256);
let hues = new Int32Array(16);
let lumaByHue = new Int32Array(16);
const bestColor = (rgb) => {
let best = -1;
let closest = Infinity;
for (let i = 0; i < 256; i += 2) {
let distance = rgb.difference(atariRGB[i]).magnitude();
if (distance < closest) {
closest = distance;
best = i;
}
}
return best;
};
for (let x = 0; x < width; x++ ) {
let rgb = inputPixel(x);
let i = bestColor(rgb);
colorCount[i]++;
let hue = i >> 4;
hues[hue]++;
let luma = i & 0xf;
lumaByHue[hue] = Math.max(luma, lumaByHue[hue]);
}
let xhues = [];
xhues.push.apply(xhues, hues);
let popularHues = xhues.map((count, hue) => {return {count, hue}}).sort((a, b) => b.count - a.count);
decimated = [0];
for (let {count, hue} of popularHues) {
let luma = lumaByHue[hue];
if (luma > 0 && count > 0) {
decimated.push((hue << 4) | luma);
}
if (decimated.length == n) {
break;
}
}
/*
while (decimated.length > n) {
let {popularity, fitness, output} = dither(decimated);
@ -509,8 +563,9 @@ function decimate(input, palette, n, inputError) {
continue;
}
let coolFactor = fitness[i] * popularity[i];
//let coolFactor = popularity[i];
let coolFactor = (fitness[i] ** 2) * popularity[i];
//let coolFactor = (fitness[i] ** 2) * popularity[i];
if (coolFactor < least) {
pick = i;
@ -534,6 +589,7 @@ function decimate(input, palette, n, inputError) {
throw new Error('this should not happen');
}
}
*/
// Palette fits
return dither(decimated);