wip colors
This commit is contained in:
parent
a8bbcb21cd
commit
365d968448
1 changed files with 66 additions and 10 deletions
|
@ -407,6 +407,18 @@ function decimate(input, palette, n, inputError) {
|
||||||
|
|
||||||
let width = input.length;
|
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
|
// Apply dithering with given palette and collect color usage stats
|
||||||
let dither = (palette) => {
|
let dither = (palette) => {
|
||||||
let fitness = new Float64Array(width);
|
let fitness = new Float64Array(width);
|
||||||
|
@ -426,11 +438,7 @@ function decimate(input, palette, n, inputError) {
|
||||||
|
|
||||||
// Try dithering with this palette.
|
// Try dithering with this palette.
|
||||||
for (let x = 0; x < width; x++) {
|
for (let x = 0; x < width; x++) {
|
||||||
let rgb = RGB.add(input[x], error.cur[x]);
|
let rgb = inputPixel(x, error);
|
||||||
if (inputError) {
|
|
||||||
rgb.inc(inputError[x]);
|
|
||||||
}
|
|
||||||
rgb.cap();
|
|
||||||
|
|
||||||
// find the closest possible color
|
// find the closest possible color
|
||||||
// @todo consider doing the difference scoring in luminance and hue spaces
|
// @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];
|
//decimated = [0, 0x36, 0x0f, 0x86];
|
||||||
|
|
||||||
let reserved = [0]; // black
|
let reserved = [0]; // black
|
||||||
//let reserved = [0, 15]; // black, white
|
//reserved = [0, 15]; // black, white
|
||||||
//let reserved = [0, 5, 10, 15]; // grayscale
|
//reserved = [0, 5, 10, 15]; // grayscale
|
||||||
//let reserved = [0, 0x48, 0x78, 15]; // vaporwave
|
//reserved = [0, 0x48, 0x78, 15]; // vaporwave
|
||||||
//let reserved = [0, 0x3c, 0x78, 15]; // red/blue/white
|
//reserved = [0, 0x3c, 0x78, 15]; // red/blue/white
|
||||||
|
|
||||||
let keepers = new Uint8Array(256);
|
let keepers = new Uint8Array(256);
|
||||||
for (let i of reserved) {
|
for (let i of reserved) {
|
||||||
keepers[i & 0xfe] = 1; // drop that 0 luminance bit!
|
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) {
|
while (decimated.length > n) {
|
||||||
let {popularity, fitness, output} = dither(decimated);
|
let {popularity, fitness, output} = dither(decimated);
|
||||||
|
|
||||||
|
@ -509,8 +563,9 @@ function decimate(input, palette, n, inputError) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let coolFactor = fitness[i] * popularity[i];
|
||||||
//let coolFactor = popularity[i];
|
//let coolFactor = popularity[i];
|
||||||
let coolFactor = (fitness[i] ** 2) * popularity[i];
|
//let coolFactor = (fitness[i] ** 2) * popularity[i];
|
||||||
|
|
||||||
if (coolFactor < least) {
|
if (coolFactor < least) {
|
||||||
pick = i;
|
pick = i;
|
||||||
|
@ -534,6 +589,7 @@ function decimate(input, palette, n, inputError) {
|
||||||
throw new Error('this should not happen');
|
throw new Error('this should not happen');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Palette fits
|
// Palette fits
|
||||||
return dither(decimated);
|
return dither(decimated);
|
||||||
|
|
Loading…
Reference in a new issue