Oh MyUtils

图片格式转换器 - PNG, JPG, WebP, AVIF在线转换

在浏览器中转换PNG、JPG、WebP和AVIF格式的图片。批量转换、质量控制和文件大小对比 — 无需上传到服务器。

常见问题

什么是图片格式转换器,为什么需要它?

图片格式转换器可以将图片从一种文件格式转换为另一种格式(例如PNG转WebP、JPG转AVIF)。这对于Web开发至关重要,因为WebP和AVIF等现代格式比传统的PNG和JPEG提供更小的文件大小,从而带来更快的页面加载速度、更低的带宽成本和更好的Core Web Vitals分数。一张典型的2MB PNG图片可以在最小视觉质量损失的情况下转换为不到500KB的WebP。

如何使用这个图片格式转换器?

1. 将图片拖放到上传区域(或点击浏览文件)。2. 选择目标输出格式(PNG、JPG、WebP或AVIF)。3. 调整有损格式的质量滑块(默认为80%)。4. 点击单个图片的「转换」或「全部转换」进行批量处理。5. 查看转换前后的文件大小对比。6. 下载单个图片或使用「全部下载」获取ZIP压缩包。

我的图片数据安全吗?图片会上传到服务器吗?

您的图片100%安全,永远不会离开您的浏览器。所有格式转换均使用HTML5 Canvas API在客户端执行。没有任何图片数据会传输到任何服务器,使这个工具完全私密。页面加载后,您甚至可以离线使用它。

PNG、JPG、WebP和AVIF有什么区别?

PNG是支持透明度的无损格式,最适合图形和图标,但文件较大。JPG/JPEG是不支持透明度的有损格式,最适合照片,具有良好的压缩率。WebP是一种现代格式,支持有损和无损压缩以及透明度,通常比JPEG小25-35%,拥有95%以上的浏览器支持。AVIF是最新的格式,具有最佳压缩比(比WebP小20-50%),支持透明度,但浏览器支持仍在增长中。

为什么转换后的文件比原始文件更大?

当从高度压缩的格式转换为效率较低的格式时(例如WebP转PNG),或者当原始文件已经很好地优化时,可能会出现这种情况。Canvas API的PNG输出始终是无损的,可能比有损替代方案更大。尝试使用WebP或AVIF并将质量设置为80%,以获得最佳的大小与质量比。

这个工具在所有浏览器中都支持AVIF吗?

通过Canvas API的AVIF编码目前在Chrome 96+和Edge 96+中受支持。Firefox和Safari的AVIF编码支持有限。该工具会自动检测您的浏览器功能,如果不支持AVIF,将禁用该选项并显示明确的提示信息。

转换为JPG时透明度会怎样?

JPEG不支持透明度。将透明的PNG或WebP图片转换为JPG时,透明区域将用背景色填充(默认为白色)。当选择JPG作为输出格式时,工具会显示颜色选择器,您可以使用它选择自定义背景色。

可以一次转换多张图片吗?

是的,批量转换同时支持最多20张图片。所有图片将使用相同的目标格式和相同的质量设置进行转换。转换后,使用「全部下载(ZIP)」将所有转换后的图片下载为一个ZIP文件。

代码示例

// Client-side image format conversion using Canvas API
async function convertImageFormat(file, outputFormat, quality = 0.8) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    const url = URL.createObjectURL(file);

    img.onload = () => {
      URL.revokeObjectURL(url);

      const canvas = document.createElement('canvas');
      canvas.width = img.width;
      canvas.height = img.height;

      const ctx = canvas.getContext('2d');

      // Fill background for JPEG (no transparency support)
      if (outputFormat === 'image/jpeg') {
        ctx.fillStyle = '#ffffff';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
      }

      ctx.drawImage(img, 0, 0);

      canvas.toBlob(
        (blob) => {
          if (!blob) {
            reject(new Error('Conversion failed'));
            return;
          }
          resolve({
            blob,
            originalSize: file.size,
            convertedSize: blob.size,
            inputFormat: file.type,
            outputFormat: outputFormat,
            sizeDiff: Math.round(((blob.size - file.size) / file.size) * 100),
          });
        },
        outputFormat,
        outputFormat === 'image/png' ? undefined : quality
      );
    };

    img.onerror = () => {
      URL.revokeObjectURL(url);
      reject(new Error('Failed to load image'));
    };

    img.src = url;
  });
}

// Check AVIF support
async function checkAvifSupport() {
  const canvas = document.createElement('canvas');
  canvas.width = 1;
  canvas.height = 1;
  return new Promise((resolve) => {
    canvas.toBlob(
      (blob) => resolve(blob?.type === 'image/avif'),
      'image/avif',
      0.5
    );
  });
}

// Batch conversion
async function convertBatch(files, outputFormat, quality = 0.8) {
  const results = [];
  for (const file of files) {
    try {
      const result = await convertImageFormat(file, outputFormat, quality);
      results.push({ filename: file.name, ...result });
    } catch (error) {
      results.push({ filename: file.name, error: error.message });
    }
  }
  return results;
}

// Usage
const input = document.querySelector('input[type="file"]');
input.addEventListener('change', async (e) => {
  const files = Array.from(e.target.files);
  const results = await convertBatch(files, 'image/webp', 0.8);

  results.forEach((result) => {
    if (result.error) {
      console.error(`${result.filename}: ${result.error}`);
    } else {
      console.log(
        `${result.filename}: ${result.inputFormat} -> ${result.outputFormat}, ` +
        `${result.originalSize} -> ${result.convertedSize} (${result.sizeDiff}%)`
      );
    }
  });
});

相关工具