Skip to content

Commit

Permalink
Messing with loader
Browse files Browse the repository at this point in the history
  • Loading branch information
Allen Ray committed Aug 22, 2024
1 parent 5aaad40 commit 9afd359
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 184 deletions.
38 changes: 3 additions & 35 deletions data.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"image/draw"
"io"
"math"
"os"
)

// zeroValueTriangleData is the default value of a TriangleData element
Expand Down Expand Up @@ -181,44 +180,13 @@ func verticalFlip(rgba *image.RGBA) {
}
}

func defaultDecoder(r io.Reader) (image.Image, error) {
type DecoderFunc (func(r io.Reader) (image.Image, error))

func DefaultImageDecoder(r io.Reader) (image.Image, error) {
i, _, err := image.Decode(r)
return i, err
}

// PictureDataFromFile loads an image from a file using the given decoder and converts it into PictureData.
//
// We take a decoder function (png.Decode, jpeg.Decode, etc.) as an argument; in order to decode images,
// you have to register the format (png, jpeg, etc.) with the image package, this will increase the number
// of dependencies imposed on a project. We want to avoid importing these in Pixel as it will increase the
// size of the project and it will increase maintanence if we miss a format, or if a new format is added.
//
// With this argument, you implicitly import and register the file formats you need and the Pixel project
// doesn't have to carry all formats around.
//
// The decoder can be nil, and Pixel will fallback onto using image.Decode and require you to import the
// formats you wish to use.
//
// See the example https://github.com/gopxl/pixel-examples/tree/main/core/loadingpictures.
func PictureDataFromFile(path string, decoder func(r io.Reader) (image.Image, error)) (*PictureData, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()

if decoder == nil {
decoder = defaultDecoder
}

img, err := decoder(f)
if err != nil {
return nil, err
}

return PictureDataFromImage(img), nil
}

// PictureDataFromImage converts an image.Image into PictureData.
//
// The resulting PictureData's Bounds will be the equivalent of the supplied image.Image's Bounds.
Expand Down
44 changes: 10 additions & 34 deletions ext/atlas/atlas.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package atlas

import (
"embed"
"fmt"
"image"
"image/draw"
Expand All @@ -12,7 +11,6 @@ import (
"sort"

"github.com/gopxl/pixel/v2"
"github.com/pkg/errors"
)

const (
Expand Down Expand Up @@ -93,34 +91,12 @@ func (a *Atlas) Images() []image.Image {
return images
}

// AddImage loads an image to the atlas.
func (a *Atlas) AddImage(img image.Image) (id TextureId) {
return a.DefaultGroup().AddImage(img)
func (a *Atlas) Add(loader pixel.LoaderFunc) (id TextureId) {
return a.DefaultGroup().Add(loader)
}

// AddEmbed loads an embed.FS image to the atlas.
func (a *Atlas) AddEmbed(fs embed.FS, path string) (id TextureId) {
return a.DefaultGroup().AddEmbed(fs, path)
}

// AddFile loads an image file to the atlas.
func (a *Atlas) AddFile(path string) (id TextureId) {
return a.DefaultGroup().AddFile(path)
}

// SliceImage evenly divides the given image into cells of the given size.
func (a *Atlas) SliceImage(img image.Image, cellSize pixel.Vec) (id SliceId) {
return a.DefaultGroup().SliceImage(img, cellSize)
}

// Slice loads an image and evenly divides it into cells of the given size.
func (a *Atlas) SliceFile(path string, cellSize pixel.Vec) (id SliceId) {
return a.DefaultGroup().SliceFile(path, cellSize)
}

// SliceEmbed loads an embeded image and evenly divides it into cells of the given size.
func (a *Atlas) SliceEmbed(fs embed.FS, path string, cellSize pixel.Vec) (id SliceId) {
return a.DefaultGroup().SliceEmbed(fs, path, cellSize)
func (a *Atlas) Slice(loader pixel.LoaderFunc, cellSize pixel.Vec) (id SliceId) {
return a.DefaultGroup().Slice(loader, cellSize)
}

// Pack takes all of the added textures and adds them to the atlas largest to smallest,
Expand Down Expand Up @@ -259,12 +235,12 @@ func (a *Atlas) Pack() {
switch add := add.(type) {
case iImageEntry:
sprite = add.Data()
case iEmbedEntry:
sprite, err = loadEmbedSprite(add.FS(), add.Path())
err = errors.Wrapf(err, "failed to load embed sprite: %v", add.Path())
case iFileEntry:
sprite, err = loadSprite(add.Path())
err = errors.Wrapf(err, "failed to load sprite file: %v", add.Path())
// case iEmbedEntry:
// sprite, err = loadEmbedSprite(add.FS(), add.Path())
// err = errors.Wrapf(err, "failed to load embed sprite: %v", add.Path())
// case iFileEntry:
// sprite, err = loadSprite(add.Path())
// err = errors.Wrapf(err, "failed to load sprite file: %v", add.Path())
}
if err != nil {
panic(err)
Expand Down
109 changes: 8 additions & 101 deletions ext/atlas/group.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package atlas

import (
"embed"
"fmt"
"image"

Expand Down Expand Up @@ -71,8 +70,11 @@ func (g *Group) addEntry(entry iEntry) (id TextureId) {
return
}

// AddImage loads an image to the atlas.
func (g *Group) AddImage(img image.Image) (id TextureId) {
func (g *Group) Add(loader pixel.LoaderFunc) (id TextureId) {
img, err := loader()
if err != nil {
panic(err)
}
e := imageEntry{
entry: entry{
id: g.atlas.id,
Expand All @@ -83,43 +85,13 @@ func (g *Group) AddImage(img image.Image) (id TextureId) {
return g.addEntry(e)
}

// AddEmbed loads an embed.FS image to the atlas.
func (g *Group) AddEmbed(fs embed.FS, path string) (id TextureId) {
img, err := loadEmbedSprite(fs, path)
// SliceImage evenly divides the given image into cells of the given size.
func (g *Group) Slice(loader pixel.LoaderFunc, cellSize pixel.Vec) (id SliceId) {
img, err := loader()
if err != nil {
panic(err)
}
e := embedEntry{
fileEntry: fileEntry{
entry: entry{
id: g.atlas.id,
bounds: img.Bounds(),
},
path: path,
},
fs: fs,
}
return g.addEntry(e)
}

// AddFile loads an image file to the atlas.
func (g *Group) AddFile(path string) (id TextureId) {
img, err := loadSprite(path)
if err != nil {
panic(err)
}
e := fileEntry{
entry: entry{
id: g.atlas.id,
bounds: img.Bounds(),
},
path: path,
}
return g.addEntry(e)
}

// SliceImage evenly divides the given image into cells of the given size.
func (g *Group) SliceImage(img image.Image, cellSize pixel.Vec) (id SliceId) {
frame := image.Pt(int(cellSize.X), int(cellSize.Y))
bounds := img.Bounds()
if bounds.Dx()%frame.X != 0 || bounds.Dy()%frame.Y != 0 {
Expand All @@ -143,68 +115,3 @@ func (g *Group) SliceImage(img image.Image, cellSize pixel.Vec) (id SliceId) {
len: uint32((bounds.Dx() / frame.X) * (bounds.Dy() / frame.Y)),
}
}

// SliceFile loads an image and evenly divides it into cells of the given size.
func (g *Group) SliceFile(path string, cellSize pixel.Vec) (id SliceId) {
frame := image.Pt(int(cellSize.X), int(cellSize.Y))
img, err := loadSprite(path)
if err != nil {
panic(err)
}
bounds := img.Bounds()
if bounds.Dx()%frame.X != 0 || bounds.Dy()%frame.Y != 0 {
panic(fmt.Sprintf("Texture size (%v,%v) must be multiple of cellSize (%v,%v)", bounds.Dx(), bounds.Dy(), cellSize.X, cellSize.Y))
}

e := sliceFileEntry{
fileEntry: fileEntry{
entry: entry{
id: g.atlas.id,
bounds: bounds,
},
path: path,
},
sliceEntry: sliceEntry{
frame: frame,
},
}

return SliceId{
start: g.addEntry(e),
len: uint32((bounds.Dx() / frame.X) * (bounds.Dy() / frame.Y)),
}
}

// SliceEmbed loads an embeded image and evenly divides it into cells of the given size.
func (g *Group) SliceEmbed(fs embed.FS, path string, cellSize pixel.Vec) (id SliceId) {
img, err := loadEmbedSprite(fs, path)
if err != nil {
panic(err)
}
frame := image.Pt(int(cellSize.X), int(cellSize.Y))
bounds := img.Bounds()
if bounds.Dx()%frame.X != 0 || bounds.Dy()%frame.Y != 0 {
panic(fmt.Sprintf("Texture size (%v,%v) must be multiple of cellSize (%v,%v)", bounds.Dx(), bounds.Dy(), cellSize.X, cellSize.Y))
}

e := sliceEmbedEntry{
embedEntry: embedEntry{
fileEntry: fileEntry{
entry: entry{
id: g.atlas.id,
bounds: bounds,
},
path: path,
},
fs: fs,
},
sliceEntry: sliceEntry{
frame: frame,
},
}

return SliceId{
start: g.addEntry(e),
len: uint32((bounds.Dx() / frame.X) * (bounds.Dy() / frame.Y)),
}
}
9 changes: 5 additions & 4 deletions ext/atlas/group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"image/color"
"testing"

"github.com/gopxl/pixel/v2"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -32,8 +33,8 @@ func TestAtlas_Clear(t *testing.T) {
g1 := a.MakeGroup()

// Add our two images to the atlas
s1 := a.AddImage(i1)
g1.AddImage(i2)
s1 := a.Add(pixel.LoadFromImage(i1))
g1.Add(pixel.LoadFromImage(i2))

a.Pack()

Expand All @@ -56,8 +57,8 @@ func TestAtlas_ClearAll(t *testing.T) {
a := Atlas{}

// Add our two images to the atlas
a.AddImage(i1)
a.AddImage(i2)
a.Add(pixel.LoadFromImage(i1))
a.Add(pixel.LoadFromImage(i2))

a.Pack()

Expand Down
22 changes: 12 additions & 10 deletions ext/atlas/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ import (
"image"
"os"

// need the following to automatically register for image.decode
_ "image/jpeg"
_ "image/png"

"github.com/gopxl/pixel/v2"
"golang.org/x/exp/constraints"
)
Expand All @@ -29,26 +25,32 @@ func image2PixelRect(r image.Rectangle) pixel.Rect {
return pixelRect(r.Min.X, r.Min.Y, r.Max.X, r.Max.Y)
}

func loadEmbedSprite(fs embed.FS, file string) (i image.Image, err error) {
func loadEmbedSprite(fs embed.FS, file string, decoder pixel.DecoderFunc) (i image.Image, err error) {
f, err := fs.Open(file)
if err != nil {
return
}
defer f.Close()

i, _, err = image.Decode(f)
return
if decoder == nil {
decoder = pixel.DefaultImageDecoder
}

return decoder(f)
}

func loadSprite(file string) (i image.Image, err error) {
func loadSprite(file string, decoder pixel.DecoderFunc) (i image.Image, err error) {
f, err := os.Open(file)
if err != nil {
return
}
defer f.Close()

i, _, err = image.Decode(f)
return
if decoder == nil {
decoder = pixel.DefaultImageDecoder
}

return decoder(f)
}

// split is the actual algorithm for splitting a given space (by j in spcs) to fit the given width and height.
Expand Down
Loading

0 comments on commit 9afd359

Please sign in to comment.