Files
zh-grammar/make-square-icon.js
T
2026-03-24 12:59:56 +07:00

65 lines
1.9 KiB
JavaScript

const sharp = require("sharp");
const { spawnSync } = require("child_process");
async function resizeAndMakeWhiteTransparent(inputPath, outputPath) {
const whiteThreshold = 250; // treat >= as white
const img = sharp(inputPath).ensureAlpha();
// Get metadata to compute resize dimensions preserving aspect ratio
const meta = await img.metadata();
const origW = meta.width || 0;
const origH = meta.height || 0;
if (!origW || !origH) throw new Error("Unable to read image dimensions");
const targetW = Math.max(origW, origH);
const targetH = targetW;
// Resize and output raw RGBA buffer
const { data, info } = await img
.resize(targetW, targetH, { fit: "fill" })
.raw()
.toBuffer({ resolveWithObject: true });
const { width: w, height: h, channels } = info; // channels should be 4 (RGBA)
if (channels < 3) throw new Error("Unexpected channel count");
// Modify alpha for near-white pixels
for (let i = 0; i < data.length; i += channels) {
const r = data[i];
const g = data[i + 1];
const b = data[i + 2];
const a = channels === 4 ? data[i + 3] : 255;
if (
a > 0 &&
r >= whiteThreshold &&
g >= whiteThreshold &&
b >= whiteThreshold
) {
if (channels === 4) data[i + 3] = 0;
else {
// expand to RGBA if input lacked alpha
// create a new buffer would be required; throw for simplicity
throw new Error(
"Input image missing alpha channel; ensure ensureAlpha() was applied.",
);
}
}
}
// Recreate and save PNG
await sharp(data, { raw: { width: w, height: h, channels } })
.png({ compressionLevel: 9 })
.toFile(outputPath);
}
const [, , input] = process.argv;
if (!input) {
throw new Error(`Input is required: input=${input}`);
}
// Example usage
resizeAndMakeWhiteTransparent(input, "app-icon.png")
.then(() => spawnSync("pnpm tauri icon", { shell: true, stdio: "inherit" }))
.catch((err) => console.error(err));