使用Sharp库生成不同尺寸的PNG图标
Sharp是一个高性能的Node.js图像处理库,非常适合用于生成不同尺寸的PNG图标。下面是一个完整的Node.js脚本示例,它可以接受一个输入PNG图像,并生成多个不同尺寸的输出PNG图标。
1. 安装依赖
首先,确保你已经安装了Node.js,然后在项目目录中安装sharp库:
npm install sharp
2. 创建脚本文件
创建一个名为generate-icons.js的文件,并添加以下代码:
const sharp = require('sharp');
const path = require('path');
const fs = require('fs');
// 配置输入和输出目录
const inputImagePath = 'input.png'; // 输入图标路径
const outputDir = 'icons'; // 输出目录
// 定义要生成的图标尺寸(宽度和高度)
const iconSizes = [
{ width: 16, height: 16 },
{ width: 32, height: 32 },
{ width: 48, height: 48 },
{ width: 64, height: 64 },
{ width: 128, height: 128 },
{ width: 256, height: 256 },
{ width: 512, height: 512 },
];
// 确保输出目录存在
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir);
}
// 生成图标的函数
async function generateIcons() {
try {
// 读取输入图像
const inputImage = sharp(inputImagePath);
// 获取输入图像的元数据
const metadata = await inputImage.metadata();
// 检查输入图像是否为PNG
if (metadata.format !== 'png') {
console.error('输入图像必须是PNG格式');
return;
}
// 为每个尺寸生成图标
for (const size of iconSizes) {
const outputFileName = `icon_${size.width}x${size.height}.png`;
const outputPath = path.join(outputDir, outputFileName);
console.log(`生成图标: ${outputFileName}`);
// 调整图像大小并保存
await inputImage
.resize(size.width, size.height)
.toFormat('png')
.toFile(outputPath);
}
console.log('所有图标生成完成!');
} catch (error) {
console.error('生成图标时出错:', error);
}
}
// 执行生成图标的函数
generateIcons();
3. 准备输入图像
在项目目录中放置一个名为input.png的PNG图像文件。这是脚本将要处理的输入图像。
4. 运行脚本
在终端中运行以下命令来执行脚本:
node generate-icons.js
脚本将执行以下操作:
- 检查输入图像是否为PNG格式。
- 创建icons输出目录(如果不存在)。
- 为每个定义的尺寸生成一个PNG图标,并保存到icons目录中。
5. 自定义配置
你可以根据需要自定义脚本:
- 修改iconSizes数组以生成不同尺寸的图标。
- 更改inputImagePath以使用不同的输入图像。
- 更改outputDir以使用不同的输出目录。
6. 高级选项
如果你需要更高级的选项(如调整图像质量、裁剪、旋转等),可以参考Sharp的官方文档。例如,你可以添加以下代码来调整图像质量:
await inputImage
.resize(size.width, size.height)
.png({ quality: 90 }) // 设置PNG质量(0-100)
.toFile(outputPath);
7. 批量处理多个输入图像
如果你需要批量处理多个输入图像,可以修改脚本以遍历一个输入图像目录。例如:
const inputDir = 'input-images'; // 输入图像目录
const inputImages = fs.readdirSync(inputDir).filter(file => file.endsWith('.png'));
for (const inputImageFile of inputImages) {
const inputImagePath = path.join(inputDir, inputImageFile);
console.log(`处理输入图像: ${inputImageFile}`);
// 在这里调用generateIcons函数,但需要修改为处理单个图像
// 你可以将generateIcons函数重构为接受inputImagePath作为参数
}
8. 完整示例
以下是完整的generate-icons.js脚本:
1.png->png
const sharp = require('sharp');
const path = require('path');
const fs = require('fs');
// 配置输入和输出目录
const inputImagePath = 'input.png'; // 输入图标路径
const outputDir = 'icons'; // 输出目录
// 定义要生成的图标尺寸(宽度和高度)
const iconSizes = [
{ width: 16, height: 16 },
{ width: 32, height: 32 },
{ width: 48, height: 48 },
{ width: 64, height: 64 },
{ width: 128, height: 128 },
{ width: 256, height: 256 },
{ width: 512, height: 512 },
];
// 确保输出目录存在
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir);
}
// 生成图标的函数
async function generateIcons() {
try {
// 读取输入图像
const inputImage = sharp(inputImagePath);
// 获取输入图像的元数据
const metadata = await inputImage.metadata();
// 检查输入图像是否为PNG
if (metadata.format !== 'png') {
console.error('输入图像必须是PNG格式');
return;
}
// 为每个尺寸生成图标
for (const size of iconSizes) {
const outputFileName = `icon_${size.width}x${size.height}.png`;
const outputPath = path.join(outputDir, outputFileName);
console.log(`生成图标: ${outputFileName}`);
// 调整图像大小并保存
await inputImage
.resize(size.width, size.height)
.toFormat('png')
.toFile(outputPath);
}
console.log('所有图标生成完成!');
} catch (error) {
console.error('生成图标时出错:', error);
}
}
// 执行生成图标的函数
generateIcons();
1.关键功能说明
1.智能尺寸处理:
- 自动保持原始宽高比
- 高质量Lanczos 3重采样算法(sharp默认)
- PNG优化:
- 最高压缩级别(9)
- 自适应过滤减少文件大小
3.错误处理:
- 自动创建输出目录
- 完善的错误捕获机制
扩展建议
1.添加透明背景支持:
javascript.flatten({ background: { r: 0, g: 0, b: 0, alpha: 0 } }) // 完全透明背景
批量处理多文件:
javascriptconst files = fs.readdirSync('./input-images');
await Promise.all(files.map(file =>
generateIcons(`./input-images/${file}`, './output', [32, 64])
));
- 生成iOS/Android标准尺寸:
javascriptconst mobileSizes = [
// iOS
20, 29, 40, 58, 60, 76, 80, 87, 120, 152, 167, 180, 1024,
// Android
48, 72, 96, 144, 192
];
性能提示
对于大批量处理,建议限制并发数量:
javascriptconst { default: PQueue } = require('p-queue');
const queue = new PQueue({ concurrency: 4 }); // 限制4个并发
await queue.addAll(sizes.map(size => () =>
image.clone().resize(size, size).toFile(`icon-${size}.png`)
));
原始图片建议:
- 使用至少1024x1024的源文件
- 推荐PNG或SVG格式以获得最佳效果
2.svg->png
const sharp = require('sharp');
const fs = require('fs');
const path = require('path');
/**
* 从SVG生成多尺寸PNG图标
* @param {string} svgPath - SVG源文件路径
* @param {string} outputDir - 输出目录
* @param {number[]} sizes - 需要生成的尺寸数组
* @param {Object} options - 可选配置
*/
async function generateMultiSizeIcons(svgPath, outputDir, sizes, options = {}) {
try {
// 验证输入文件
if (!fs.existsSync(svgPath)) {
throw new Error('SVG文件不存在');
}
// 创建输出目录
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
// 读取SVG内容
const svgBuffer = fs.readFileSync(svgPath);
// 并行生成所有尺寸
await Promise.all(sizes.map(async size => {
const outputPath = path.join(outputDir, `icon-${size}x${size}.png`);
await sharp(svgBuffer)
.resize(size, size, {
fit: 'contain', // 保持比例包含在尺寸内
background: options.background || { r: 0, g: 0, b: 0, alpha: 0 } // 透明背景
})
.png({
compressionLevel: 9, // 最高压缩
quality: options.quality || 90,
adaptiveFiltering: true
})
.toFile(outputPath);
console.log(`已生成: ${outputPath}`);
}));
console.log('所有尺寸图标生成完成!');
} catch (err) {
console.error('生成图标失败:', err);
}
}
// 使用示例
generateMultiSizeIcons(
'./logo.svg', // SVG源文件
'./output-icons', // 输出目录
[16, 32, 64, 128, 256, 512], // 需要生成的尺寸
{
background: { r: 255, g: 255, b: 255 }, // 白色背景(可选)
quality: 95 // 质量(可选)
}
);
1 .关键功能说明
1.智能尺寸处理:
- 自动保持SVG原始宽高比
- fit: 'contain'确保图标完整显示在目标尺寸内
2.背景控制:
- 默认透明背景(alpha: 0)
- 可通过options.background自定义背景色
3.PNG优化:
- 最高压缩级别(9级)
- 自适应过滤减少文件体积
扩展建议
1.生成标准尺寸图标组
// 常用平台标准尺寸
const platformSizes = {
web: [16, 32, 64, 128, 256, 512],
ios: [20, 29, 40, 58, 60, 76, 80, 87, 120, 152, 167, 180, 1024],
android: [48, 72, 96, 144, 192]
};
// 生成全平台图标
generateMultiSizeIcons('app-icon.svg', './output', [
...platformSizes.web,
...platformSizes.ios,
...platformSizes.android
]);
2.添加圆角效果
// 在resize后添加圆角处理
.sharp(svgBuffer)
.resize(size, size)
.composite([{
input: Buffer.from(
`<svg viewBox="0 0 ${size} ${size}">
<rect width="${size}" height="${size}" rx="${size*0.2}" fill="white"/>
</svg>`
),
blend: 'dest-in' // 使用蒙版创建圆角
}])
.png()
.toFile(outputPath);
3. 添加阴影效果:
// 生成带阴影的图标
.sharp(svgBuffer)
.resize(size, size)
.extend({
top: 10,
bottom: 10,
left: 10,
right: 10,
background: { r: 0, g: 0, b: 0, alpha: 0 }
})
.composite([{
input: await sharp({
create: {
width: size + 20,
height: size + 20,
channels: 4,
background: { r: 0, g: 0, b: 0, alpha: 0 }
}
})
.blur(10)
.toBuffer()
}])
.png()
.toFile(outputPath);
性能提示
大尺寸生成时增加Node内存限制:
NODE_OPTIONS="--max-old-space-size=4096" node icon-generator.js
原始svg建议:
- 推荐使用至少512x512像素的SVG源文件
- 确保SVG中已定义明确的viewBox尺寸
9. 运行脚本
"scripts": { "generate-icons": "node icon-generator.js" }
node generate-icons.js
脚本将生成不同尺寸的PNG图标并保存到icons目录中。
总结
使用Sharp库可以轻松地生成不同尺寸的PNG图标。Sharp提供了高性能的图像处理功能,并且易于使用。你可以根据需要自定义脚本,生成任意尺寸的图标,并应用其他图像处理操作。