28 lines
1.0 KiB
JavaScript
28 lines
1.0 KiB
JavaScript
import fs from 'fs/promises';
|
|
import UPNG from 'upng-js';
|
|
|
|
const countUniqueColors = (data) => {
|
|
const uniqueColors = new Set();
|
|
for (let i = 0; i < data.length; i += 4) {
|
|
uniqueColors.add(`${data[i]},${data[i + 1]},${data[i + 2]},${data[i + 3]}`);
|
|
if (uniqueColors.size > 256) {
|
|
return uniqueColors.size;
|
|
}
|
|
}
|
|
return uniqueColors.size;
|
|
};
|
|
|
|
export async function compressPng (filePath) {
|
|
const buffer = await fs.readFile(filePath);
|
|
const arrayBuffer = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
|
const img = UPNG.decode(arrayBuffer);
|
|
const rgba = new Uint8Array(img.data);
|
|
const frameData = new Uint8Array(img.width * img.height * 4);
|
|
frameData.set(rgba.subarray(0, frameData.length));
|
|
const cnum = countUniqueColors(rgba) <= 256 ? 256 : 0;
|
|
const optimizedArrayBuffer = UPNG.encode([frameData.buffer], img.width, img.height, cnum, img.depth);
|
|
const optimizedBuffer = Buffer.from(optimizedArrayBuffer);
|
|
await fs.writeFile(filePath, optimizedBuffer);
|
|
return filePath;
|
|
};
|