Started with experimental hashing of base tiles to avoid redundant write operations and pyramid updates.

This commit is contained in:
Sascha L. Teichmann 2016-05-08 12:33:17 +02:00
parent 9f1735eb29
commit 5ee3731a27
2 changed files with 92 additions and 0 deletions

42
common/basetilehash.go Normal file
View File

@ -0,0 +1,42 @@
// Copyright 2016 by Sascha L. Teichmann
// Use of this source code is governed by the MIT license
// that can be found in the LICENSE file.
package common
import (
"bytes"
"image"
"sync"
)
type btPos struct {
x int
y int
}
type BaseTileHash struct {
// XXX: Maybe use some kind of LRU cache instead?
hashes map[btPos][]byte
sync.Mutex
}
func NewBaseTileHash() *BaseTileHash {
return &BaseTileHash{hashes: map[btPos][]byte{}}
}
func (bth *BaseTileHash) Update(x, y int, img image.Image) bool {
hash := SHA1Image(img)
key := btPos{x, y}
bth.Lock()
defer bth.Unlock()
if old, found := bth.hashes[key]; found {
equals := bytes.Equal(old, hash)
if !equals {
bth.hashes[key] = hash
}
return !equals
}
bth.hashes[key] = hash
return true
}

View File

@ -7,6 +7,7 @@ package common
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"crypto/sha1"
"errors" "errors"
"image" "image"
"image/color" "image/color"
@ -110,3 +111,52 @@ func LoadPNG(path string, bg color.RGBA) image.Image {
} }
return img return img
} }
func sha1rgba(img *image.RGBA) []byte {
hash := sha1.New()
w, h := img.Rect.Dx()*4, img.Rect.Dy()
pos := img.PixOffset(img.Rect.Min.X, img.Rect.Min.Y)
for ; h > 0; h, pos = h-1, pos+img.Stride {
hash.Write(img.Pix[pos : pos+w])
}
return hash.Sum(nil)
}
func sha1uniform(img *image.Uniform) []byte {
r, g, b, a := img.C.RGBA()
return sha1.New().Sum([]byte{
byte(r >> 16),
byte(g >> 16),
byte(b >> 16),
byte(a >> 16)})
}
func SHA1Image(img image.Image) []byte {
switch i := img.(type) {
case *image.RGBA:
return sha1rgba(i)
case *image.Uniform:
return sha1uniform(i)
}
log.Println("WARN: slow path for SHA1Image")
hash := sha1.New()
bounds := img.Bounds()
var pix [4]byte
for x := bounds.Min.X; x <= bounds.Max.X; x++ {
for y := bounds.Min.Y; y <= bounds.Max.Y; y++ {
r, g, b, a := img.At(x, y).RGBA()
pix[0] = byte(r >> 16)
pix[1] = byte(g >> 16)
pix[2] = byte(b >> 16)
pix[3] = byte(a >> 16)
hash.Write(pix[:])
}
}
return hash.Sum(nil)
}