发现一个简单低成本的全平台“高斯模糊”方案,让你的产品更漂亮一点。

科技   2024-06-27 10:49   浙江  

前段时间在看 ActivityPub 文档时发现它们的客户端在加载图片时使用了一种叫做 BlurHash 的技术来显示图片加载出来之前的 Placeholder,效果非常好,而且成本极低,如果集成到 App 中可以很大程度上提高多图页面的用户体验。

这种技术可以让你图片加载出来之前显示一个填充图,这个图看起来有点像原图的高斯模糊,并且显示这个“高斯模糊”时并不需要提前把图片加载出来,计算成本也很低,完全可以当作图片加载完成前的 Placeholder 使用,而不必使用纯色块来填充,类似于下图这样:

右边就是 BlurHash 生成的图片,看起来效果还是可以的,下面就说要如何实现这种技术。

BlurHash 的使用

上面图中的中间图片有一个称为 BlurHash 的字符串,这个字符串就是通过算法计算出来的左边的原图的颜色分布信息,计算结果是一个不算长的字符串,然后客户端按照算法输入 BlurHash String,即可生成右边的那种看起来像高斯模糊一样的图片。

BlurHash 本质上就是一系列算法,因此适用所有的前端平台,包括 Web、Android、iOS 等等,接入的成本也很低。

使用起来是非常简单的,因为算法都很简单,不过我们需要后端的支持,因为后端接口在返回图片 url 给客户端时需要同时把这个图片的 BlurHash String 也返回过来,客户端根据 BlurHash 生成图片当作 Placeholder,再去加载图片,提供用户体验。

项目地址如下:

https://github.com/woltapp/blurhash

因为算法确实比较简单,他们甚至没有提供 SDK,只是提供了每一种语言的实现代码,大家直接把这个代码复制到项目中即可,Kotlin 代码就一个文件,提供 BlurHash ,返回 Bitmap,就这么简单。

不过 Compose 实际使用时需要自己写一点胶水代码,也可以直接用我写好的。

fun Modifier.blurhash(blurHash: String): Modifier = composed {    var size: Size? by remember {        mutableStateOf(null)    }    var bitmap: Bitmap? by remember {        mutableStateOf(null)    }    val coroutineScope = rememberCoroutineScope()    if (size != null) {        DisposableEffect(blurHash) {
if (bitmap == null && size != null) { coroutineScope.launch { bitmap = withContext(Dispatchers.IO) { BlurHashDecoder.decode( blurHash = blurHash, width = (size!!.width * 0.5F).roundToInt(), height = (size!!.height * 0.5F).roundToInt(), ) } } }
onDispose { bitmap?.recycle() bitmap = null } } } onSizeChanged { size = it.toSize() }.drawBehind { if (bitmap != null && size != null) { drawImage( image = bitmap!!.asImageBitmap(), dstSize = IntSize(size!!.width.roundToInt(), size!!.height.roundToInt()), ) } }}

其他平台,iOS、Web 这些也按照类似的方式直接集成即可,后端的 SDK 也是有的,直接集成就行了。


虎哥Lovedroid
Android技术达人 近10年一线开发经验 关注并分享Android、Kotlin新技术,新框架 多年Android底层框架修改经验,对Framework、Server、Binder等架构有深入理解
 最新文章