photopea / UPNG.js

Fast and advanced PNG (APNG) decoder and encoder (lossy / lossless)
MIT License
2.1k stars 259 forks source link

Reduce colors of raw ImageData without having to encode then decode a PNG #75

Closed Merlin04 closed 2 years ago

Merlin04 commented 2 years ago

In my application I have to use UPNG to compress a large quantity of images - specifically, given an ImageData, I need to reduce the colors to the provided value then output another ImageData. The way I'm currently doing this involves encoding the data as a PNG then decoding it again:

function transform(quality: number, image: ImageData): ImageData {
    const png = UPNG.encode([image.data.buffer], image.width, image.height, quality);
    const buf = UPNG.toRGBA8(UPNG.decode(png))[0];
    return new ImageData(new Uint8ClampedArray(buf), image.width, image.height);
}

However, from some testing it appears the decoding of the PNG on the second line of the function creates a significant performance bottleneck. Is it possible to avoid creating a PNG in the first place so I don't have to decode it, and just reduce the number of colors of the raw pixel data and output that?

photopea commented 2 years ago

Sure, check out our quantizer: UPNG.quantize(), it is described in the README.md

photopea commented 2 years ago

https://en.wikipedia.org/wiki/Color_quantization

Merlin04 commented 2 years ago

That works great, thanks so much for the help (and for making such a great library!)