some oldbits

This commit is contained in:
Brooke Vibber 2023-03-19 18:22:33 -07:00
parent 9a93e7341f
commit 9826a90e02

View file

@ -426,7 +426,7 @@ function decimate(input, palette, n, inputError, y) {
// Apply dithering with given palette and collect color usage stats
let dither = (palette) => {
let fitness = new Float64Array(palette.length);
let fitness = new Float64Array(width);
let error = {
cur: [],
next: [],
@ -476,10 +476,12 @@ function decimate(input, palette, n, inputError, y) {
let mag = nextError.magnitude();
fitness[x] = maxDist / mag;
// 442 is the 3d distance across the rgb cube
//fitness[x] = 442 - (nextError.magnitude());
//fitness[x] = 442 / (442 - nextError.magnitude());
fitness[x] = 255 / (256 - Math.max(0, nextError.r, nextError.g, nextError.b));
// just store the distance2
let mag2 = nextError.magnitude2();
//fitness[x] = mag2;
distance2 += mag2;
}
return {
@ -509,11 +511,12 @@ function decimate(input, palette, n, inputError, y) {
//reserved = [0, 5, 10, 15]; // grayscale
//reserved = [0, 0x48, 0x78, 15]; // vaporwave
//reserved = [0, 0x3c, 0x78, 15]; // red/blue/white
/*
if (( y & 1 ) === 0) {
reserved = [0, 0x3c, 0x1a, 15]; // red/yellow/white
reserved = [0, 0x3c, 0x1e, 15]; // red/yellow/white
} else {
reserved = [0, 0x76, 0x9a, 15]; // blue/cyan/white
reserved = [0, 0x76, 0x9e, 0xb8]; // blue/cyan/green
}
*/
@ -553,7 +556,8 @@ function decimate(input, palette, n, inputError, y) {
a = a.sort((a, b) => b.count - a.count);
a = a.map(({hue}) => hue);
a = a.filter((color) => !keepers[color]);
a = a.slice(0, n - reserved.length);
//a = a.slice(0, n - reserved.length);
a = a.slice(0, decimated.length - 1 - reserved.length);
a = a.map((hue) => (hue << 4) | lumas[hue]);
a = a.sort((a, b) => a - b);
@ -564,20 +568,64 @@ function decimate(input, palette, n, inputError, y) {
// popularity? not really working right
// first, dither to the total atari palette
/*
while (decimated.length > n) {
let {popularity, fitness} = dither(decimated);
// temporarily strip the reserved items
//console.log(y);
let {popularity} = dither(decimated);
let a = decimated;
// temporarily strip the reserved items
a = a.filter((color) => !keepers[color]);
a = a.sort((a, b) => popularity[b] - popularity[a]);
//a = a.slice(0, n - reserved.length);
a = reserved.concat(a);
decimated = a.slice(0, decimated.length - 1);
decimated = a.slice(0, n);
//console.log(decimated);
}
//console.log('end', decimated);
*/
while (decimated.length > n) {
let {popularity, fitness, output} = dither(decimated);
// Try dropping least used color on each iteration
let least = Infinity;
let pick = -1;
for (let i = 1; i < decimated.length; i++) {
//let coolFactor = popularity[i];
let coolFactor = 0;
if (popularity[i]) {
for (let x = 0; x < width; x++) {
if (output[x] == i) {
// Scale up the scoring for close matches to prioritize
// color accuracy over raw linear usage.
//coolFactor += (fitness[x] ** 2);
coolFactor += (fitness[x] ** 4);
}
}
}
if (coolFactor < least) {
pick = i;
least = coolFactor;
}
decimated = decimated.filter((color, i) => {
if (i == 0) {
return true;
}
if (i == pick) {
return false;
}
// Also drop any non-black unused colors to save trouble.
// However -- this may change dither results.
// Try this with/without later.
if (popularity[i] == 0) {
return false;
}
return true;
});
}
}
// Palette fits
return dither(decimated);
}
@ -845,6 +893,7 @@ async function saveImage(width, height, lines, dest) {
resolve(image);
});
});
await image.resize(Math.round(width2 * 2 / 1.2), height * 2);
await image.writeAsync(dest);
}