最近有一个需求,根据图片的主要色值自动设置页面的背景色。我们的服务端是go语言写的,自然先评估一下是否能用go实现这个需求。找了几个方案,其中github.com/cenkalti/dominantcolor的方案最为简单,也最合适。
先看看简单的例子
package main
import (
"bytes"
"fmt"
"image"
"image/jpeg"
"io"
"io/ioutil"
"net/http"
"github.com/cenkalti/dominantcolor"
)
func GetImageByUrl(url string) (img image.Image, err error) {
res, err := http.Get(url)
if err != nil {
return
}
defer func(body io.ReadCloser) {
_ = body.Close()
}(res.Body)
data, err := ioutil.ReadAll(res.Body)
if err != nil {
return
}
reader := bytes.NewReader(data)
img, err = jpeg.Decode(reader)
return
}
func FindDomiantColor(url string) (c string, err error) {
img, err := GetImageByUrl(url)
if err != nil {
return
}
return dominantcolor.Hex(dominantcolor.Find(img)), nil
}
func main() {
fmt.Println(FindDomiantColor("https://n.sinaimg.cn/news/transform/310/w710h400/20220701/8cd8-e663ace484b6d8dcc548a18691e30c0a.jpg"))
}
这个例子打开一个网络图片,然后获取其主要的颜色,输出是#544F4C,可以看一下背景的效果图:
可以看出背景还是比较匹配的。不过对于某些有多个色块的图片,是拿不到单一的颜色的,例如下面这个例子:
当然,如果只能选一种颜色,并且是自动的,那确实没有太简单的办法。不过如果可以让用户干预,其实还是可以有办法的,因为dominantcolor是可以输出多个颜色的。我们来看一下官方的演示程序:
这个程序也是go写的,基于dominantcolor和fyne.io,有兴趣的可以试试,也很简单:
go install github.com/stuartmscott/dominantcolor
$GOPATH/dominantcolor
上面是运行的界面,可以选一张本地的图片,计算6个使用最多的颜色块。windows下也可以运行,只不过因为需要gl库,看上去依赖gcc编译,所以没有尝试。上图是在wsl下运行的,现在windows的wsl已经支持图形界面的程序运行,还是挺方便的,就是性能看上去一般般。
从代码库的文档看,这个库用的是K聚类算法计算RGBA颜色空间的聚类,源自Chromium的源码: