2022-11-17 12:09:31 -07:00
|
|
|
package stone
|
|
|
|
|
2022-11-17 16:58:30 -07:00
|
|
|
import "sync"
|
2022-11-17 12:09:31 -07:00
|
|
|
import "image"
|
|
|
|
import "image/color"
|
|
|
|
|
2022-11-17 16:58:30 -07:00
|
|
|
type ImageManager struct {
|
|
|
|
lock sync.RWMutex
|
|
|
|
images []*ColorImage
|
|
|
|
}
|
|
|
|
|
|
|
|
func (manager *ImageManager) For (callback func (im *ColorImage)) {
|
|
|
|
manager.lock.RLock()
|
|
|
|
defer manager.lock.RUnlock()
|
|
|
|
|
|
|
|
for _, im := range manager.images {
|
|
|
|
callback(im)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (manager *ImageManager) Add (im *ColorImage) {
|
|
|
|
manager.lock.Lock()
|
|
|
|
defer manager.lock.Unlock()
|
|
|
|
|
|
|
|
manager.images = append(manager.images, im)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (manager *ImageManager) Size () (size int) {
|
|
|
|
manager.lock.RLock()
|
|
|
|
defer manager.lock.RUnlock()
|
|
|
|
|
|
|
|
size = len(manager.images)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (manager *ImageManager) At (index int) (im *ColorImage) {
|
|
|
|
manager.lock.RLock()
|
|
|
|
defer manager.lock.RUnlock()
|
|
|
|
|
|
|
|
if index < 0 || index > len(manager.images) { return }
|
|
|
|
im = manager.images[index]
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (manager *ImageManager) Remove (im *ColorImage) (removed bool) {
|
|
|
|
manager.lock.Lock()
|
|
|
|
defer manager.lock.Unlock()
|
|
|
|
|
|
|
|
index := 0
|
|
|
|
for manager.images[index] != im && index < len(manager.images) {
|
|
|
|
index ++
|
|
|
|
}
|
|
|
|
|
|
|
|
if index >= len(manager.images) { return }
|
|
|
|
|
|
|
|
manager.images = append (
|
|
|
|
manager.images[:index],
|
|
|
|
manager.images[index + 1:]...)
|
|
|
|
removed = true
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-11-17 12:09:31 -07:00
|
|
|
type ColorImage struct {
|
|
|
|
x, y int
|
|
|
|
width, height int
|
|
|
|
bufferWidth, bufferHeight int
|
|
|
|
cellWidth, cellHeight int
|
|
|
|
buffer []color.RGBA
|
|
|
|
|
|
|
|
clean bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func (im *ColorImage) Model () (model color.Model) {
|
|
|
|
model = color.RGBAModel
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (im *ColorImage) Bounds () (bounds image.Rectangle) {
|
|
|
|
bounds.Max.X = im.width
|
|
|
|
bounds.Max.Y = im.height
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (im *ColorImage) Size () (width, height int) {
|
|
|
|
width = im.width
|
|
|
|
height = im.height
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (im *ColorImage) SetSize (width, height int) {
|
|
|
|
im.width = width
|
|
|
|
im.height = height
|
|
|
|
im.bufferWidth = im.cellWidth * im.width
|
|
|
|
im.bufferHeight = im.cellHeight * im.height
|
|
|
|
im.buffer = make([]color.RGBA, im.bufferWidth * im.bufferHeight)
|
|
|
|
im.clean = false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (im *ColorImage) At (x, y int) (pixel color.Color) {
|
|
|
|
if im.outOfBounds(x, y) { return }
|
|
|
|
pixel = im.buffer[x + y * im.width]
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (im *ColorImage) AtRGBA (x, y int) (pixel color.RGBA) {
|
|
|
|
if im.outOfBounds(x, y) { return }
|
|
|
|
pixel = im.buffer[x + y * im.width]
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (im *ColorImage) Set (x, y int, pixel color.Color) {
|
|
|
|
if im.outOfBounds(x, y) { return }
|
|
|
|
r, g, b, a := pixel.RGBA()
|
|
|
|
im.buffer[x + y * im.width] = color.RGBA {
|
|
|
|
R: uint8(r >> 8),
|
|
|
|
G: uint8(g >> 8),
|
|
|
|
B: uint8(b >> 8),
|
|
|
|
A: uint8(a >> 8),
|
|
|
|
}
|
|
|
|
|
|
|
|
im.clean = false
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (im *ColorImage) SetRGBA (x, y int, pixel color.RGBA) {
|
|
|
|
if im.outOfBounds(x, y) { return }
|
|
|
|
im.buffer[x + y * im.width] = pixel
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (im *ColorImage) MarkClean () {
|
|
|
|
im.clean = true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (im *ColorImage) outOfBounds (x, y int) (outOfBounds bool) {
|
|
|
|
outOfBounds =
|
|
|
|
x >= im.width ||
|
|
|
|
y >= im.height ||
|
|
|
|
x < 0 ||
|
|
|
|
y < 0
|
|
|
|
return
|
|
|
|
}
|