Atomized the functionality of the base tomo package
This commit is contained in:
90
canvas/canvas.go
Normal file
90
canvas/canvas.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package canvas
|
||||
|
||||
import "image"
|
||||
import "image/draw"
|
||||
import "image/color"
|
||||
|
||||
// Canvas is like draw.Image but is also able to return a raw pixel buffer for
|
||||
// more efficient drawing. This interface can be easily satisfied using a
|
||||
// BasicCanvas struct.
|
||||
type Canvas interface {
|
||||
draw.Image
|
||||
Buffer () (data []color.RGBA, stride int)
|
||||
}
|
||||
|
||||
// BasicCanvas is a general purpose implementation of tomo.Canvas.
|
||||
type BasicCanvas struct {
|
||||
pix []color.RGBA
|
||||
stride int
|
||||
rect image.Rectangle
|
||||
}
|
||||
|
||||
// NewBasicCanvas creates a new basic canvas with the specified width and
|
||||
// height, allocating a buffer for it.
|
||||
func NewBasicCanvas (width, height int) (canvas BasicCanvas) {
|
||||
canvas.pix = make([]color.RGBA, height * width)
|
||||
canvas.stride = width
|
||||
canvas.rect = image.Rect(0, 0, width, height)
|
||||
return
|
||||
}
|
||||
|
||||
// you know what it do
|
||||
func (canvas BasicCanvas) Bounds () (bounds image.Rectangle) {
|
||||
return canvas.rect
|
||||
}
|
||||
|
||||
// you know what it do
|
||||
func (canvas BasicCanvas) At (x, y int) (color.Color) {
|
||||
if !image.Pt(x, y).In(canvas.rect) { return nil }
|
||||
return canvas.pix[x + y * canvas.stride]
|
||||
}
|
||||
|
||||
// you know what it do
|
||||
func (canvas BasicCanvas) ColorModel () (model color.Model) {
|
||||
return color.RGBAModel
|
||||
}
|
||||
|
||||
// you know what it do
|
||||
func (canvas BasicCanvas) Set (x, y int, c color.Color) {
|
||||
if !image.Pt(x, y).In(canvas.rect) { return }
|
||||
r, g, b, a := c.RGBA()
|
||||
canvas.pix[x + y * canvas.stride] = color.RGBA {
|
||||
R: uint8(r >> 8),
|
||||
G: uint8(g >> 8),
|
||||
B: uint8(b >> 8),
|
||||
A: uint8(a >> 8),
|
||||
}
|
||||
}
|
||||
|
||||
// you know what it do
|
||||
func (canvas BasicCanvas) Buffer () (data []color.RGBA, stride int) {
|
||||
return canvas.pix, canvas.stride
|
||||
}
|
||||
|
||||
// Reallocate efficiently reallocates the canvas. The data within will be
|
||||
// garbage. This method will do nothing if this is a cut image.
|
||||
func (canvas *BasicCanvas) Reallocate (width, height int) {
|
||||
if canvas.rect.Min != (image.Point { }) { return }
|
||||
|
||||
previousLen := len(canvas.pix)
|
||||
newLen := width * height
|
||||
bigger := newLen > previousLen
|
||||
smaller := newLen < previousLen / 2
|
||||
if bigger || smaller {
|
||||
canvas.pix = make (
|
||||
[]color.RGBA,
|
||||
((height * width) / 4096) * 4096 + 4096)
|
||||
}
|
||||
canvas.stride = width
|
||||
canvas.rect = image.Rect(0, 0, width, height)
|
||||
}
|
||||
|
||||
// Cut returns a sub-canvas of a given canvas.
|
||||
func Cut (canvas Canvas, bounds image.Rectangle) (reduced BasicCanvas) {
|
||||
// println(canvas.Bounds().String(), bounds.String())
|
||||
bounds = bounds.Intersect(canvas.Bounds())
|
||||
if bounds.Empty() { return }
|
||||
reduced.rect = bounds
|
||||
reduced.pix, reduced.stride = canvas.Buffer()
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user