# Golang : Find relative luminance or color brightness

Problem:

You need to find the relative luminance (brightness or perceived brightness) of a color to another color. You also want to check if the luminance of a color is compatible with another color. How to do that?

Solution:

We will use the formula taken from https://www.w3.org/TR/AERT#color-contrast

Color brightness is determined by the following formula:

((Red value X 299) + (Green value X 587) + (Blue value X 114)) / 1000

to calculate the luminance or brightness of a color. You can change the formula for your own need.

Here you go!

`````` package main

import (
"fmt"
"image/color"
"math"
"os"
"strconv"
)

// find out if the two colors are the same
func SameColor(color1, color2 color.RGBA) bool {
red1, green1, blue1, alpha1 := color1.RGBA()
red2, green2, blue2, alpha2 := color2.RGBA()

return red1 == red2 && green1 == green2 && blue1 == blue2 && alpha1 == alpha2
}

// find luminance of a given color - ignoring alpha
func Luminance(aColor color.RGBA) float64 {

// because of
// http://stackoverflow.com/questions/35374300/why-does-golang-rgba-rgba-method-use-and
// we cannot use .RGBA() values. It will screw up the final luminance result
// red, green, blue, _ := aColor.RGBA()

//fmt.Println("red : ", red)
//fmt.Println("green : ", green)
//fmt.Println("blue : ", blue)

// instead, we will use the colors value from 0..255 for calculation purpose
red := aColor.R
green := aColor.G
blue := aColor.B

// need to convert uint32 to float64
return float64(float64(0.299)*float64(red) + float64(0.587)*float64(green) + float64(0.114)*float64(blue))
}

// the diff is big enough?
func Compatible(color1, color2 color.RGBA) bool {
return math.Abs(Luminance(color1)-Luminance(color2)) >= 128.0
}

func SaneColorCheck(arg string) int {
colorCode, err := strconv.Atoi(arg)
if err != nil {
fmt.Println("Input arguments must be integer from 0..255")
os.Exit(-1)
}

if (colorCode > 255) || (colorCode < 0) {
fmt.Println("Invalid color code : ", colorCode)
fmt.Println("Color values must be in range of 0..255")
os.Exit(-1)
}
return colorCode
}

func main() {
if len(os.Args) != 9 {
fmt.Printf("Usage : %s <red1> <green1> <blue1> <alpha1> <red2> <green2> <blue2> <alpha1> \n", os.Args[0])
os.Exit(0)
}

//sanity checks
red1 := uint8(SaneColorCheck(os.Args[1]))
green1 := uint8(SaneColorCheck(os.Args[2]))
blue1 := uint8(SaneColorCheck(os.Args[3]))
alpha1 := uint8(SaneColorCheck(os.Args[4]))
red2 := uint8(SaneColorCheck(os.Args[5]))
green2 := uint8(SaneColorCheck(os.Args[6]))
blue2 := uint8(SaneColorCheck(os.Args[7]))
alpha2 := uint8(SaneColorCheck(os.Args[8]))

fmt.Println("Red 1 : ", red1)
fmt.Println("Green 1 : ", green1)
fmt.Println("Blue 1 : ", blue1)
fmt.Println("Alpha 1 : ", alpha1)

fmt.Println("Red 2 : ", red2)
fmt.Println("Green 2 : ", green2)
fmt.Println("Blue 2 : ", blue2)
fmt.Println("Alpha 2 : ", alpha2)

// create new colors from given arguments/command line parameters
color1 := color.RGBA{red1, green1, blue1, alpha1}
color2 := color.RGBA{red2, green2, blue2, alpha2}

fmt.Println("Color 1 = ", color1)
fmt.Println("Color 2 = ", color2)
fmt.Println("Color 1 same as Color 2 ? : ", SameColor(color1, color2))
fmt.Println("Luminance of color 1 = ", Luminance(color1))
fmt.Println("Luminance of color 2 = ", Luminance(color2))
fmt.Println("Is color 1 and color 2 compatible? : ", Compatible(color1, color2))

}
``````

References:

https://en.wikipedia.org/wiki/Relative_luminance

http://stackoverflow.com/questions/596216/formula-to-determine-brightness-of-rgb-color

https://socketloop.com/tutorials/golang-create-new-color-from-command-line-parameters

https://www.w3.org/TR/AERT#color-contrast