Finding An Image's Dominant Color In Go
· 9 min read · Views --
Last updated on

Finding An Image's Dominant Color In Go

Author: Alex Xiang

Go

Finding An Image’s Dominant Color In Go

I recently had a requirement: automatically choose a page background color based on the dominant color of an image. Since the backend service was written in Go, I first looked at whether this could be done directly in Go.

After trying a few options, github.com/cenkalti/dominantcolor turned out to be the simplest and most suitable choice.

Here is a minimal example:

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"))
}

This example downloads an image, decodes it, and prints the dominant color. In my test, the result was #544F4C.

Dominant color used as a background

The result matched the image reasonably well. But for images with several large color blocks, choosing only one dominant color may not be enough:

An image where a single dominant color is not enough

If the system must pick one color automatically, there is no perfect answer. If the user can intervene, there are more options, because dominantcolor can also output multiple candidate colors.

The official demo program is useful for this:

dominantcolor demo showing multiple colors

The demo is also written in Go, based on dominantcolor and fyne.io. It is easy to try:

go install github.com/stuartmscott/dominantcolor
$GOPATH/dominantcolor

dominantcolor desktop demo

The desktop app lets you select a local image and calculates the six most frequently used color blocks. It can also run on Windows, but because it needs GL-related dependencies and may require GCC, I did not try the Windows path. The screenshot above was taken under WSL. Modern WSL can run graphical Linux applications, which is convenient, although the performance does not look especially strong.

According to the library documentation, the algorithm uses K-means clustering in RGBA color space and is derived from Chromium source code: