go-opengl-pixel/picture.go

107 lines
2.9 KiB
Go
Raw Normal View History

2016-12-06 09:36:23 -06:00
package pixel
import (
"image"
"image/draw"
"github.com/faiface/mainthread"
2016-12-06 09:36:23 -06:00
"github.com/faiface/pixel/pixelgl"
)
// Picture is a raster picture. It is usually used with sprites.
//
// A picture is created from an image.Image, that can be either loaded from a file, or
// generated. After the creation a picture can be sliced (slicing creates a "sub-picture"
// from a picture) into smaller pictures.
2016-12-06 09:36:23 -06:00
type Picture struct {
texture *pixelgl.Texture
bounds Rect
}
// NewPicture creates a new picture from an image.Image.
2016-12-21 13:51:05 -06:00
func NewPicture(img image.Image, smooth bool) *Picture {
// convert the image to NRGBA format
2017-01-20 15:50:51 -06:00
bounds := img.Bounds()
nrgba := image.NewNRGBA(image.Rect(0, 0, bounds.Dx(), bounds.Dy()))
draw.Draw(nrgba, nrgba.Bounds(), img, bounds.Min, draw.Src)
2016-12-06 09:36:23 -06:00
// flip the image vertically
tmp := make([]byte, nrgba.Stride)
for i, j := 0, bounds.Dy()-1; i < j; i, j = i+1, j-1 {
iSlice := nrgba.Pix[i*nrgba.Stride : (i+1)*nrgba.Stride]
jSlice := nrgba.Pix[j*nrgba.Stride : (j+1)*nrgba.Stride]
copy(tmp, iSlice)
copy(iSlice, jSlice)
copy(jSlice, tmp)
}
2017-01-01 15:12:12 -06:00
var texture *pixelgl.Texture
mainthread.Call(func() {
texture = pixelgl.NewTexture(
2017-01-01 15:12:12 -06:00
img.Bounds().Dx(),
img.Bounds().Dy(),
smooth,
2017-01-20 12:26:28 -06:00
nrgba.Pix,
2017-01-01 15:12:12 -06:00
)
})
2016-12-06 09:36:23 -06:00
2016-12-18 18:11:34 -06:00
return &Picture{
2016-12-06 09:36:23 -06:00
texture: texture,
bounds: R(0, 0, float64(texture.Width()), float64(texture.Height())),
}
}
2017-01-22 06:45:43 -06:00
// Image returns the content of the Picture as an image.NRGBA.
func (p *Picture) Image() *image.NRGBA {
bounds := p.Bounds()
2017-01-22 07:16:19 -06:00
nrgba := image.NewNRGBA(image.Rect(0, 0, int(bounds.W()), int(bounds.H())))
2017-01-22 06:45:43 -06:00
mainthread.Call(func() {
2017-01-22 07:16:19 -06:00
p.texture.Begin()
2017-01-22 06:45:43 -06:00
nrgba.Pix = p.texture.Pixels(
int(bounds.X()),
int(bounds.Y()),
int(bounds.W()),
int(bounds.H()),
)
2017-01-22 07:16:19 -06:00
p.texture.End()
2017-01-22 06:45:43 -06:00
})
// flip the image vertically
tmp := make([]byte, nrgba.Stride)
for i, j := 0, nrgba.Bounds().Dy()-1; i < j; i, j = i+1, j-1 {
iSlice := nrgba.Pix[i*nrgba.Stride : (i+1)*nrgba.Stride]
jSlice := nrgba.Pix[j*nrgba.Stride : (j+1)*nrgba.Stride]
copy(tmp, iSlice)
copy(iSlice, jSlice)
copy(jSlice, tmp)
}
return nrgba
}
2016-12-06 09:36:23 -06:00
// Texture returns a pointer to the underlying OpenGL texture of a picture.
2016-12-18 18:11:34 -06:00
func (p *Picture) Texture() *pixelgl.Texture {
2016-12-06 09:36:23 -06:00
return p.texture
}
// Slice returns a picture within the supplied rectangle of the original picture. The original
// and the sliced picture share the same texture.
2016-12-06 09:36:23 -06:00
//
// For example, suppose we have a 100x200 pixels picture. If we slice it with rectangle (50,
// 100, 50, 100), we get the upper-right quadrant of the original picture.
2016-12-18 18:11:34 -06:00
func (p *Picture) Slice(slice Rect) *Picture {
return &Picture{
2016-12-06 09:36:23 -06:00
texture: p.texture,
bounds: Rect{p.bounds.Pos + slice.Pos, slice.Size},
}
}
// Bounds returns the bounding rectangle of this picture relative to the most original picture.
//
// If the original picture gets sliced with the return value of this method, this picture will
// be obtained.
2016-12-18 18:11:34 -06:00
func (p *Picture) Bounds() Rect {
2016-12-06 09:36:23 -06:00
return p.bounds
}