Refactored bitmap API (partially)

- Made the scale option an interface (for easier use)
- Added rotation option
- Added utility function that converts Go bitmap to an Allegro bitmap (using a temporary file)
This commit is contained in:
Sander Schobers 2017-10-23 11:21:02 +02:00
parent 0aff140884
commit 67e2d4d788

View File

@ -6,6 +6,10 @@ import "C"
import ( import (
"fmt" "fmt"
"image"
"image/png"
"io/ioutil"
"os"
"unsafe" "unsafe"
) )
@ -18,13 +22,35 @@ type Bitmap struct {
type DrawOptions struct { type DrawOptions struct {
Center bool Center bool
Scale *Scale Scale Scale
Tint *Color Tint *Color
Rotation *Rotation
} }
type Scale struct { type Scale interface {
Horizontal float32 Horizontal() float32
Vertical float32 Vertical() float32
}
type scale struct {
horizontal float32
vertical float32
}
func (s *scale) Horizontal() float32 { return s.horizontal }
func (s *scale) Vertical() float32 { return s.vertical }
func NewScale(horizontal, vertical float32) Scale {
return &scale{horizontal, vertical}
}
func NewUniformScale(s float32) Scale {
return &scale{s, s}
}
type Rotation struct {
Angle float32
Center bool
} }
// NewBitmap creates a new bitmap of given width and height // NewBitmap creates a new bitmap of given width and height
@ -36,6 +62,29 @@ func NewBitmap(width, height int) (*Bitmap, error) {
return &Bitmap{b, width, height}, nil return &Bitmap{b, width, height}, nil
} }
func exportToPng(im image.Image) (string, error) {
tmp, err := ioutil.TempFile("", "galleg")
if nil != err {
return "", err
}
defer tmp.Close()
err = png.Encode(tmp, im)
if nil != err {
return "", err
}
return tmp.Name(), nil
}
// NewBitmapFromImage creates a new bitmap starting from a Go native image (image.Image)
func NewBitmapFromImage(im image.Image) (*Bitmap, error) {
path, err := exportToPng(im)
if nil != err {
return nil, err
}
defer os.Remove(path)
return LoadBitmap(path)
}
// LoadBitmap tries to load the image at the specified path as a bitmap // LoadBitmap tries to load the image at the specified path as a bitmap
func LoadBitmap(path string) (*Bitmap, error) { func LoadBitmap(path string) (*Bitmap, error) {
p := C.CString(path) p := C.CString(path)
@ -60,28 +109,51 @@ func (b *Bitmap) DrawOptions(left, top float32, options DrawOptions) {
scale := nil != options.Scale scale := nil != options.Scale
if scale { if scale {
width *= options.Scale.Horizontal width *= options.Scale.Horizontal()
height *= options.Scale.Vertical height *= options.Scale.Vertical()
} }
if options.Center { if options.Center {
left -= width * 0.5 left -= width * 0.5
top -= height * 0.5 top -= height * 0.5
} }
rotated := nil != options.Rotation
var centerX C.float
var centerY C.float
if rotated && options.Rotation.Center {
centerX = C.float(b.width) * 0.5
centerY = C.float(b.height) * 0.5
}
if scale { if scale {
if nil == options.Tint { if nil == options.Tint { // scaled
if rotated { // scaled & rotated
C.al_draw_scaled_rotated_bitmap(b.bitmap, centerX, centerY, C.float(left), C.float(top), C.float(options.Scale.Horizontal()), C.float(options.Scale.Vertical()), C.float(options.Rotation.Angle), 0)
} else { // scaled
C.al_draw_scaled_bitmap(b.bitmap, 0, 0, C.float(b.width), C.float(b.height), C.float(left), C.float(top), C.float(width), C.float(height), 0) C.al_draw_scaled_bitmap(b.bitmap, 0, 0, C.float(b.width), C.float(b.height), C.float(left), C.float(top), C.float(width), C.float(height), 0)
} else { }
} else { // tinted & scaled
if rotated { // scaled, tinted & rotated
C.al_draw_tinted_scaled_rotated_bitmap(b.bitmap, options.Tint.color, centerX, centerY, C.float(left), C.float(top), C.float(options.Scale.Horizontal()), C.float(options.Scale.Vertical()), C.float(options.Rotation.Angle), 0)
} else { // tinted, scaled
C.al_draw_tinted_scaled_bitmap(b.bitmap, options.Tint.color, 0, 0, C.float(b.width), C.float(b.height), C.float(left), C.float(top), C.float(width), C.float(height), 0) C.al_draw_tinted_scaled_bitmap(b.bitmap, options.Tint.color, 0, 0, C.float(b.width), C.float(b.height), C.float(left), C.float(top), C.float(width), C.float(height), 0)
} }
}
} else { } else {
if nil == options.Tint { if nil == options.Tint {
if rotated { // rotated
C.al_draw_rotated_bitmap(b.bitmap, centerX, centerY, C.float(left), C.float(top), C.float(options.Rotation.Angle), 0)
} else {
C.al_draw_bitmap(b.bitmap, C.float(left), C.float(top), 0) C.al_draw_bitmap(b.bitmap, C.float(left), C.float(top), 0)
}
} else { // tinted
if rotated { // tinted & rotated
C.al_draw_tinted_rotated_bitmap(b.bitmap, options.Tint.color, centerX, centerY, C.float(left), C.float(top), C.float(options.Rotation.Angle), 0)
} else { } else {
C.al_draw_tinted_bitmap(b.bitmap, options.Tint.color, C.float(left), C.float(top), 0) C.al_draw_tinted_bitmap(b.bitmap, options.Tint.color, C.float(left), C.float(top), 0)
} }
} }
} }
}
func (b *Bitmap) Width() int { func (b *Bitmap) Width() int {
return b.width return b.width