Image: defer SDL2 texture loading until Present
This commit is contained in:
parent
b87b4825af
commit
e7e8b4b2c1
85
image.go
85
image.go
|
@ -4,11 +4,13 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"image/jpeg"
|
"image/jpeg"
|
||||||
|
"image/png"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.kirsle.net/go/render"
|
"git.kirsle.net/go/render"
|
||||||
|
"golang.org/x/image/bmp"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ImageType for supported image formats.
|
// ImageType for supported image formats.
|
||||||
|
@ -27,8 +29,8 @@ type Image struct {
|
||||||
|
|
||||||
// Configurable fields for the constructor.
|
// Configurable fields for the constructor.
|
||||||
Type ImageType
|
Type ImageType
|
||||||
Image image.Image
|
Image image.Image // a Go image version
|
||||||
texture render.Texturer
|
texture render.Texturer // (SDL2) Texture, lazy inited on Present.
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewImage creates a new Image.
|
// NewImage creates a new Image.
|
||||||
|
@ -47,16 +49,10 @@ func NewImage(c Image) *Image {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImageFromImage creates an Image from a Go standard library image.Image.
|
// ImageFromImage creates an Image from a Go standard library image.Image.
|
||||||
func ImageFromImage(e render.Engine, im image.Image) (*Image, error) {
|
func ImageFromImage(im image.Image) (*Image, error) {
|
||||||
tex, err := e.StoreTexture("imgbin.png", im)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Image{
|
return &Image{
|
||||||
Type: PNG,
|
Type: PNG,
|
||||||
Image: im,
|
Image: im,
|
||||||
texture: tex,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +65,7 @@ func ImageFromTexture(tex render.Texturer) *Image {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImageFromFile creates an Image by opening a file from disk.
|
// ImageFromFile creates an Image by opening a file from disk.
|
||||||
func ImageFromFile(e render.Engine, filename string) (*Image, error) {
|
func ImageFromFile(filename string) (*Image, error) {
|
||||||
fh, err := os.Open(filename)
|
fh, err := os.Open(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -80,14 +76,8 @@ func ImageFromFile(e render.Engine, filename string) (*Image, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
tex, err := e.StoreTexture(filename, img)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Image{
|
return &Image{
|
||||||
Image: img,
|
Image: img,
|
||||||
texture: tex,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,12 +99,34 @@ func OpenImage(e render.Engine, filename string) (*Image, error) {
|
||||||
return nil, fmt.Errorf("OpenImage: %s: not a supported image type", filename)
|
return nil, fmt.Errorf("OpenImage: %s: not a supported image type", filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
tex, err := e.LoadTexture(filename)
|
// Open the file from disk.
|
||||||
|
fh, err := os.Open(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
w.texture = tex
|
// Parse it.
|
||||||
|
switch w.Type {
|
||||||
|
case PNG:
|
||||||
|
img, err := png.Decode(fh)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
w.Image = img
|
||||||
|
case JPEG:
|
||||||
|
img, err := jpeg.Decode(fh)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
w.Image = img
|
||||||
|
case BMP:
|
||||||
|
img, err := bmp.Decode(fh)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
w.Image = img
|
||||||
|
}
|
||||||
|
|
||||||
return w, nil
|
return w, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,16 +143,39 @@ func (w *Image) GetRGBA() *image.RGBA {
|
||||||
return rgba
|
return rgba
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the widget.
|
// Size returns the dimensions of the image which is also the widget's size.
|
||||||
func (w *Image) Compute(e render.Engine) {
|
func (w *Image) Size() render.Rect {
|
||||||
w.Resize(w.texture.Size())
|
if w.Image != nil {
|
||||||
|
bounds := w.Image.Bounds().Canon()
|
||||||
// Call the BaseWidget Compute in case we have subscribers.
|
return render.Rect{
|
||||||
w.BaseWidget.Compute(e)
|
W: bounds.Max.X,
|
||||||
|
H: bounds.Max.Y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return w.BaseWidget.Size()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present the widget.
|
// Counter for unique SDL2 texture names.
|
||||||
|
var __imageID int
|
||||||
|
|
||||||
|
// Present the widget. This should be called on your main thread
|
||||||
|
// if using SDL2 in case it needs to generate textures.
|
||||||
func (w *Image) Present(e render.Engine, p render.Point) {
|
func (w *Image) Present(e render.Engine, p render.Point) {
|
||||||
|
// Lazy load the (e.g. SDL2) texture from the stored bitmap.
|
||||||
|
if w.texture == nil {
|
||||||
|
if w.Image == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
__imageID++
|
||||||
|
tex, err := e.StoreTexture(fmt.Sprintf("ui.Image(%d).png", __imageID), w.Image)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("ui.Image.Present(): could not make texture: %s\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.texture = tex
|
||||||
|
}
|
||||||
|
|
||||||
size := w.texture.Size()
|
size := w.texture.Size()
|
||||||
dst := render.Rect{
|
dst := render.Rect{
|
||||||
X: p.X,
|
X: p.X,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user