88 lines
1.5 KiB
Go
88 lines
1.5 KiB
Go
// Copyright 2015 by Sascha L. Teichmann
|
|
// Use of this source code is governed by the MIT license
|
|
// that can be found in the LICENSE file.
|
|
|
|
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"image"
|
|
"image/color"
|
|
"image/draw"
|
|
"os"
|
|
|
|
_ "image/jpeg"
|
|
_ "image/png"
|
|
)
|
|
|
|
func loadRGBA(filename string) (*image.RGBA, error) {
|
|
|
|
file, err := os.Open(filename)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer file.Close()
|
|
|
|
var img image.Image
|
|
if img, _, err = image.Decode(bufio.NewReader(file)); err != nil {
|
|
return nil, fmt.Errorf("Decoding '%s' failed: %s", filename, err)
|
|
}
|
|
|
|
if rgba, ok := img.(*image.RGBA); ok {
|
|
return rgba, nil
|
|
}
|
|
bounds := img.Bounds()
|
|
rgba := image.NewRGBA(bounds)
|
|
draw.Draw(rgba, bounds, img, image.ZP, draw.Src)
|
|
|
|
return rgba, nil
|
|
}
|
|
|
|
func averageColor(filename string) (color.Color, error) {
|
|
|
|
img, err := loadRGBA(filename)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
bounds := img.Bounds()
|
|
if bounds.Empty() {
|
|
return color.Black, nil
|
|
}
|
|
y := img.PixOffset(bounds.Min.X, bounds.Min.Y)
|
|
yEnd := img.PixOffset(bounds.Min.X, bounds.Max.Y)
|
|
w := bounds.Dx() * 4
|
|
pix := img.Pix
|
|
|
|
var r, g, b, a uint64
|
|
|
|
for ; y < yEnd; y += img.Stride {
|
|
for pos, end := y, y+w; pos < end; pos += 4 {
|
|
pa := uint64(pix[pos+3])
|
|
r += pa * uint64(pix[pos])
|
|
g += pa * uint64(pix[pos+1])
|
|
b += pa * uint64(pix[pos+2])
|
|
a += pa
|
|
}
|
|
}
|
|
|
|
r /= 255
|
|
g /= 255
|
|
b /= 255
|
|
|
|
if s := a / 255; s > 0 {
|
|
r /= s
|
|
g /= s
|
|
b /= s
|
|
}
|
|
|
|
col := color.RGBA{
|
|
R: uint8(r),
|
|
G: uint8(g),
|
|
B: uint8(b),
|
|
A: uint8(a / uint64(bounds.Dx()*bounds.Dy()))}
|
|
|
|
return &col, nil
|
|
}
|