feat: implement main logic and implement webp support

This commit is contained in:
2021-10-04 09:14:38 +03:00
parent f2cfc0feea
commit 9451d2c679
5 changed files with 82 additions and 9 deletions
+6 -2
View File
@@ -1,10 +1,14 @@
# ColorX (WIP) # ColorX
ColorX is a library to determine the most prominent color in an image. ColorX is a library to determine the most prominent color in an image.
ColorX doesn't use any sort of complex algorithms to calculate the prominent color, it simply loops over the image pixels and returns the color that occurs the most.
The `getProminentColor` function returns the color in 2 formats, a hex string such as: `#abfecd` and a variable of type `color.Color`.
# Example # Example
Example code is written in [example/example.go](https://github.com/illusionman1212/colorx/blob/master/example/example.go) An example on how to use this library is written in [example/example.go](https://github.com/illusionman1212/colorx/blob/master/example/example.go)
# Supported Image Formats # Supported Image Formats
Currently ColorX supports these image formats: Currently ColorX supports these image formats:
- png - png
- jpeg - jpeg
- webp
+70 -7
View File
@@ -20,28 +20,91 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"image" "image"
"strconv"
"image/color"
_ "image/jpeg" _ "image/jpeg"
_ "image/png" _ "image/png"
_ "golang.org/x/image/webp"
) )
// downsampleImage downsamples images larger than 20000px for faster image processing.
func downsampleImage(img image.Image) image.Image {
// TODO: implement downsampling
return img
}
// calculateColorMap loops through the image pixels and creates a map-
// of all unique pixel colors and how many times they occur.
func calculateColorMap(img image.Image, width int, height int) map[color.Color]int {
colorMap := map[color.Color]int{}
for x := 0; x < width; x++ {
for y := 0; y < height; y++ {
color := img.At(x, y)
// if the alpha is bigger than 100 then add the color to the map
if _, _, _, a := color.RGBA(); a > 100 {
colorMap[color] = colorMap[color] + 1
}
}
}
return colorMap
}
// GetProminentColor gets the most prominent color in the image bytes reader that gets passed in. // GetProminentColor gets the most prominent color in the image bytes reader that gets passed in.
// returns a hex color as a string. // returns a hex color as a string.
func GetProminentColor(data []byte) (string, error) { func GetProminentColor(data []byte) (string, color.Color, error) {
buf := bytes.NewBuffer(data) buf := bytes.NewBuffer(data)
img, _, err := image.Decode(buf) img, _, err := image.Decode(buf)
if err != nil { if err != nil {
return "", err return "", nil, err
} }
width := img.Bounds().Max.X width := img.Bounds().Max.X
height := img.Bounds().Max.Y height := img.Bounds().Max.Y
// amount of pixels in image
pixels := height * width pixels := height * width
fmt.Printf("Pixels in image: %v\n", pixels) // image is too big, downsample to a reasonable size
fmt.Printf("Width: %v\n", width) if pixels > 20000 {
fmt.Printf("Height: %v\n", height) img = downsampleImage(img)
}
return "", nil
colorMap := calculateColorMap(img, width, height)
var maxColor color.Color
maxAmmount := 0
for color, amount := range colorMap {
if amount > maxAmmount {
maxColor = color
maxAmmount = amount
}
}
RGBAColor := color.RGBAModel.Convert(maxColor).(color.RGBA)
red := strconv.FormatUint(uint64(RGBAColor.R), 16)
green := strconv.FormatUint(uint64(RGBAColor.G), 16)
blue := strconv.FormatUint(uint64(RGBAColor.B), 16)
// prepend 0 if the hex number has less than 2 digits
if len(red) < 2 {
red = "0" + red
}
if len(green) < 2 {
green = "0" + green
}
if len(blue) < 2 {
blue = "0" + blue
}
hexColor := fmt.Sprintf("#%2s%2s%2s", red, green, blue)
return hexColor, maxColor, nil
} }
+1 -1
View File
@@ -38,7 +38,7 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
color, err := colorx.GetProminentColor(data) color, _, err := colorx.GetProminentColor(data)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
+2
View File
@@ -1,3 +1,5 @@
module github.com/illusionman1212/colorx module github.com/illusionman1212/colorx
go 1.16 go 1.16
require golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d
+4
View File
@@ -0,0 +1,4 @@
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d h1:RNPAfi2nHY7C2srAV8A49jpsYr0ADedCk1wq6fTMTvs=
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=