diff --git a/dither-image.js b/dither-image.js index e39b5ea..17efe94 100644 --- a/dither-image.js +++ b/dither-image.js @@ -485,6 +485,15 @@ function decimate(input, palette, n, inputError) { // force to rWb //decimated = [0, 0x36, 0x0f, 0x86]; + + let reserved = [0]; // black + //let reserved = [0, 15]; // black, white + //let reserved = [0, 5, 10, 15]; // grayscale + + let keepers = new Uint8Array(256); + for (let i of reserved) { + keepers[i & 0xfe] = 1; // drop that 0 luminance bit! + } while (decimated.length > n) { let {popularity, fitness, output} = dither(decimated); @@ -492,7 +501,11 @@ function decimate(input, palette, n, inputError) { // Try dropping least used color on each iteration let least = Infinity; let pick = -1; - for (let i = 1; i < decimated.length; i++) { + for (let i = 0; i < decimated.length; i++) { + let color = decimated[i]; + if (keepers[color]) { + continue; + } //let coolFactor = popularity[i]; @@ -513,22 +526,22 @@ function decimate(input, palette, n, inputError) { least = coolFactor; } } + + let last = decimated.length; decimated = decimated.filter((color, i) => { - if (palette[i] == 0) { - // solid black + if (keepers[color]) { 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; }); + + if (decimated.length == last && last > n) { + console.log(decimated); + throw new Error('this should not happen'); + } } // Palette fits