Closed infacto closed 1 year ago
GIF and palette-based PNG output already does this for you.
https://sharp.pixelplumbing.com/api-output#gif https://sharp.pixelplumbing.com/api-output#png
Thanks, but can I use an external palette? If I understand correctly, you can only reduce the color amount used in png from its own content. But I want to use the color palette from another file.
I already tried to use a png file with all the colors I want and enabled palette option. Then used toBuffer to use again in sharp with another file with composite ('over' to replace the content). But it ignores the color palette. I would expect to only use the available colors from the palette.
There's a work-in-progress PR for this at https://github.com/libvips/libvips/pull/3122
The most appropriate next step for you would be to take what's there so far and implement it fully, if you're able.
Okay great, looks promising. Currently I crafted a script in JS to iterate through the image and find the closest color from a color palette array.
const colorPalette = []; // [r, g, b][]
const image = await sharp('input.png').raw().toBuffer();
// Expecting 3 channels (r, g, b without alpha).
for (let i = 0; i < image.length; i += 3) {
const r = image[i + 0];
const g = image[i + 1];
const b = image[i + 2];
let closestColor = colorPalette[0];
let minDistance = Number.MAX_SAFE_INTEGER;
for (const color of colorPalette) {
const distance = Math.sqrt(
Math.pow(r - color[0], 2) +
Math.pow(g - color[1], 2) +
Math.pow(b - color[2], 2));
if (distance < minDistance) {
minDistance = distance;
closestColor = color;
}
}
image[i + 0] = closestColor[0];
image[i + 1] = closestColor[1];
image[i + 2] = closestColor[2];
}
sharp(image, { raw: { width: 64, height: 64, channels: 3 } }).toFile('output.png');
You could also use metadata
from sharp
to get width
, height
and channels
.
It would be great if sharp supports a better way to iterate and manipulate per pixel. Something like with Jimp.scan
. And support format bmp
would be also great. I use the package sharp-bmp
.
Feature request
Convert an image to use only the colors from a palette. Optional with dithering (Floyd–Steinberg). Like with the program Aseprite or Photoshop. Aka indexed color. The colors from the input image are automatically converted to a specific palette that is closest to the color. The color palette could be imported from a png or known color palette file ext.