package stone import "sync" import "image" import "image/color" 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 } 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 }