Node.js脚本来生成不同尺寸的PNG图标。sharp库,这是一个高性能的Node.js图像处理库

142 阅读4分钟

使用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

脚本将执行以下操作:

  1. 检查输入图像是否为PNG格式。
  2. 创建icons输出目录(如果不存在)。
  3. 为每个定义的尺寸生成一个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默认)
  1. 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])
));
  1. 生成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提供了高性能的图像处理功能,并且易于使用。你可以根据需要自定义脚本,生成任意尺寸的图标,并应用其他图像处理操作。