Skip to main content
返回博客指南

为什么你的 Favicon 看起来模糊(以及逐步缩小修复法)

单步 canvas 缩放在 16×16 下会破坏细节。为什么大多数 favicon 生成器产生模糊图标,以及逐步减半如何修复它。

2026年8月6 分钟阅读

你上传了一张极其清晰的 1024×1024 logo。生成器输出一个 16×16 favicon。而浏览器标签页中的结果是一团无法辨认的污迹。如果这听起来很熟悉,问题通常不在于你的 logo——而在于图标是如何被缩小的。以下是模糊 favicon 出现的计算机图形学原因,以及能修复它的缩放技术。

为什么单步缩放会毁掉小图标

大多数 favicon 生成器(以及大多数复制粘贴的 canvas 代码)是这样做的:

ctx.drawImage(img, 0, 0, 16, 16) // 1024px source → 16px target, one hop

一次 drawImage 调用将图像缩小 64 倍时使用的是简单的双线性插值。对于 256 个输出像素中的每一个,浏览器只采样源图像中一个极小的邻域——这意味着大约 99.98% 的输入像素在被平均之前就被丢弃了。细小的笔画、字形和 1px 间隙等精细细节没有被"混合缩小",而是在随机位置被采样,这就是为什么文字变成糊状、logo 出现泥泞色块的原因。

这是一个经典的图形学问题,也有已知的解决方案: 分步缩小,每次减半(1024 → 512 → 256 → 128 → 64 → 32 → 16)。每个 2× 的步长足够小,双线性采样可以平均一个有意义的邻域,因此细节被逐渐合并而不是被跳过。这与 3D 渲染中的 mipmap 以及 canvas 中的 imageSmoothingQuality: "high" 是同一个思路——但显式地串联减半步骤可以在各浏览器中获得一致的结果。

修复方法:在 canvas 中逐步减半

function drawDownscaled(ctx, img, targetW, targetH) {
  let source = img
  let w = img.naturalWidth
  let h = img.naturalHeight

  // Halve repeatedly while both dimensions stay above the target
  while (Math.floor(w / 2) >= targetW && Math.floor(h / 2) >= targetH) {
    const step = document.createElement('canvas')
    step.width = Math.floor(w / 2)
    step.height = Math.floor(h / 2)
    const stepCtx = step.getContext('2d')
    stepCtx.imageSmoothingEnabled = true
    stepCtx.imageSmoothingQuality = 'high'
    stepCtx.drawImage(source, 0, 0, w, h, 0, 0, step.width, step.height)
    source = step
    w = step.width
    h = step.height
  }

  // Final hop is now at most ~2x, which bilinear handles well
  ctx.imageSmoothingQuality = 'high'
  ctx.drawImage(source, 0, 0, w, h, 0, 0, targetW, targetH)
}

该循环保证最后一次缩小在每个轴上都不超过约 2×——这正是插值真正有效的范围。对于一个细节丰富的 logo,效果是天壤之别:笔画保持连通,字母的计数器(字腔)得以保留,边缘保留对比度而不是溶成灰色。

即使是完美的缩放也无法挽救糟糕的源图

两个源图侧的错误造成了大多数剩余的模糊:

  • 从已经很小的位图开始。64×64 的源图放大到 512 再缩小回来毫无益处——始终从 logo 的最大版本开始,更好的是矢量原稿。
  • 为 512 设计并指望它在 16 下可读。出色的标签页图标是为 16px 专门设计的:去掉精细细节,将笔画加粗到至少画布的 1/16,并使用一两种颜色。如果你的 logo 包含文字标识,在 favicon 尺寸下只使用标志或首字母。

如果你想完全跳过位图缩放, SVG favicon 是分辨率无关的——浏览器以精确的 16px 渲染矢量,不涉及任何插值。

如何验证你的 favicon 是否真正清晰

  1. 下载生成的 favicon-16x16.png,在图像查看器中以 400% 缩放打开。你要的是轮廓分明的边缘,而不是灰色的糊。
  2. 将它与眯眼远看时的源 logo 并排比较——轮廓应该仍然吻合。
  3. 在真实的浏览器标签页中检查,包括浅色和深色主题,并与其他标签页对比,看它是否可辨识。

我们在自己的生成器中修复了这个问题

当我们针对这种失效模式审计自己的流水线时,我们在所有输出尺寸上将单步缩放替换为逐步减半(外加 imageSmoothingQuality: "high")。这就是为什么在 Favicon.one 生成的图标在其他工具涂抹成一团时仍能在 16px 下站得住脚。如果你在比较生成器,可以这样做测试:上传一个带有细笔画和小文字的细节丰富 logo,首先查看 16×16 的输出。

更多关于流水线的内容:如何正确 将 PNG 转换为 favicon,以及 favicon 尺寸指南中你需要的每一种尺寸。

准备好生成 favicon 了吗?

上传图片,几秒内获取完整的 favicon 包。免费、私密、全部在浏览器中处理。