You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现高效JS/TS算法将Blurhash转换为灰度图?

解决Blurhash转灰度后的拉伸变形问题

问题分析

你的代码出现拉伸变形的核心原因是编码时的xComponents和yComponents比例与图片宽高比不匹配:你固定使用了4和3作为分量数,但图片宽高比由ASPECT_RATIO决定(比如头像通常是1:1),分量比例(4:3)和图片比例不一致,导致编码后的Blurhash色块分布失衡,最终显示拉伸。

另外,简单的RGB平均计算灰度的方式不够准确,建议使用行业标准的加权灰度公式。

修复后的代码

const WIDTH = 30;
const ASPECT_RATIO = validationConfig.media.profilePicture.aspectRatio;
const HEIGHT = Math.floor(WIDTH / ASPECT_RATIO);

// 根据宽高比计算匹配的分量数,保证比例一致
const X_COMPONENTS = 4;
const Y_COMPONENTS = Math.round(X_COMPONENTS / ASPECT_RATIO);

export function convertBlurhashToGreyscale(blurhash: string) {
  // 解码Blurhash为像素数组
  const pixels = decode(blurhash, WIDTH, HEIGHT);

  // 用ITU-R BT.601标准公式计算灰度,比简单平均更准确
  for (let i = 0; i < pixels.length; i += 4) {
    const r = pixels[i];
    const g = pixels[i + 1];
    const b = pixels[i + 2];
    const grayValue = Math.round(0.299 * r + 0.587 * g + 0.114 * b);
    
    pixels[i] = grayValue;
    pixels[i + 1] = grayValue;
    pixels[i + 2] = grayValue;
    pixels[i + 3] = 255; // 保持不透明
  }

  // 编码时使用匹配比例的分量数,且宽高与解码时一致
  return encode(pixels, WIDTH, HEIGHT, X_COMPONENTS, Y_COMPONENTS);
}

关键优化点

  • 分量数匹配宽高比:通过Y_COMPONENTS = Math.round(X_COMPONENTS / ASPECT_RATIO)让色块数量的比例和图片宽高比一致,避免拉伸变形。
  • 准确灰度计算:使用加权公式计算灰度,符合人眼对RGB通道的敏感度,生成的灰度图更自然。
  • 统一宽高参数:编码和解码使用相同的WIDTH和HEIGHT,避免不必要的重新计算导致的参数不一致。

内容的提问来源于stack exchange,提问作者Niccolò Caselli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 14:00:18