diff --git a/data.go b/data.go index b1f2507..05bcef7 100644 --- a/data.go +++ b/data.go @@ -1,6 +1,7 @@ package pixel import ( + "embed" "fmt" "image" "image/color" @@ -191,7 +192,7 @@ func DefaultDecoderFunc(r io.Reader) (image.Image, error) { return i, err } -// PictureDataFromFile loads an image from a file using the given decoder and converts it into PictureData. +// ImageFromEmbed loads an image from an embedded file using the given decoder. // // 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 @@ -205,7 +206,35 @@ func DefaultDecoderFunc(r io.Reader) (image.Image, error) { // formats you wish to use. // // See the example https://github.com/gopxl/pixel-examples/tree/main/core/loadingpictures. -func PictureDataFromFile(path string, decoder DecoderFunc) (*PictureData, error) { +func ImageFromEmbed(fs embed.FS, path string, decoder DecoderFunc) (image.Image, error) { + f, err := fs.Open(path) + if err != nil { + return nil, err + } + defer f.Close() + + if decoder == nil { + decoder = DefaultDecoderFunc + } + + return decoder(f) +} + +// ImageFromFile loads an image from a file using the given decoder. +// +// 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 ImageFromFile(path string, decoder DecoderFunc) (image.Image, error) { f, err := os.Open(path) if err != nil { return nil, err @@ -216,7 +245,25 @@ func PictureDataFromFile(path string, decoder DecoderFunc) (*PictureData, error) decoder = DefaultDecoderFunc } - img, err := decoder(f) + return decoder(f) +} + +// 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 DecoderFunc) (*PictureData, error) { + img, err := ImageFromFile(path, decoder) if err != nil { return nil, err } diff --git a/ext/atlas/atlas.go b/ext/atlas/atlas.go index 298189b..f61c287 100644 --- a/ext/atlas/atlas.go +++ b/ext/atlas/atlas.go @@ -133,7 +133,7 @@ func (a *Atlas) Pack() { } // If we've already packed the textures, we need to convert them back to images to repack them - if a.internal != nil && len(a.internal) > 0 { + if len(a.internal) > 0 { images := make([]*image.RGBA, len(a.internal)) for i, data := range a.internal { images[i] = data.Image() @@ -260,10 +260,10 @@ func (a *Atlas) Pack() { case iImageEntry: sprite = add.Data() case iEmbedEntry: - sprite, err = loadEmbedSprite(add.FS(), add.Path(), add.DecoderFunc()) + sprite, err = pixel.ImageFromEmbed(add.FS(), add.Path(), add.DecoderFunc()) err = errors.Wrapf(err, "failed to load embed sprite: %v", add.Path()) case iFileEntry: - sprite, err = loadSprite(add.Path(), add.DecoderFunc()) + sprite, err = pixel.ImageFromFile(add.Path(), add.DecoderFunc()) err = errors.Wrapf(err, "failed to load sprite file: %v", add.Path()) } if err != nil { @@ -281,6 +281,4 @@ func (a *Atlas) Pack() { a.adding = nil a.clean = true - - return } diff --git a/ext/atlas/group.go b/ext/atlas/group.go index 58eb618..4dedac8 100644 --- a/ext/atlas/group.go +++ b/ext/atlas/group.go @@ -85,7 +85,7 @@ func (g *Group) AddImage(img image.Image) (id TextureId) { // AddEmbed loads an embed.FS image to the atlas. func (g *Group) AddEmbed(fs embed.FS, path string, decoder pixel.DecoderFunc) (id TextureId) { - img, err := loadEmbedSprite(fs, path, decoder) + img, err := pixel.ImageFromEmbed(fs, path, decoder) if err != nil { panic(err) } @@ -105,7 +105,7 @@ func (g *Group) AddEmbed(fs embed.FS, path string, decoder pixel.DecoderFunc) (i // AddFile loads an image file to the atlas. func (g *Group) AddFile(path string, decoder pixel.DecoderFunc) (id TextureId) { - img, err := loadSprite(path, decoder) + img, err := pixel.ImageFromFile(path, decoder) if err != nil { panic(err) } @@ -149,7 +149,7 @@ func (g *Group) SliceImage(img image.Image, cellSize pixel.Vec) (id SliceId) { // SliceFile loads an image and evenly divides it into cells of the given size. func (g *Group) SliceFile(path string, cellSize pixel.Vec, decoder pixel.DecoderFunc) (id SliceId) { frame := image.Pt(int(cellSize.X), int(cellSize.Y)) - img, err := loadSprite(path, decoder) + img, err := pixel.ImageFromFile(path, decoder) if err != nil { panic(err) } @@ -180,7 +180,7 @@ func (g *Group) SliceFile(path string, cellSize pixel.Vec, decoder pixel.Decoder // 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, decoder pixel.DecoderFunc) (id SliceId) { - img, err := loadEmbedSprite(fs, path, decoder) + img, err := pixel.ImageFromEmbed(fs, path, decoder) if err != nil { panic(err) } diff --git a/ext/atlas/help.go b/ext/atlas/help.go index 928cc05..058a334 100644 --- a/ext/atlas/help.go +++ b/ext/atlas/help.go @@ -1,9 +1,7 @@ package atlas import ( - "embed" "image" - "os" // need the following to automatically register for image.decode _ "image/jpeg" @@ -29,34 +27,6 @@ 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, decoder pixel.DecoderFunc) (i image.Image, err error) { - f, err := fs.Open(file) - if err != nil { - return - } - defer f.Close() - - if decoder == nil { - decoder = pixel.DefaultDecoderFunc - } - - return decoder(f) -} - -func loadSprite(file string, decoder pixel.DecoderFunc) (i image.Image, err error) { - f, err := os.Open(file) - if err != nil { - return - } - defer f.Close() - - if decoder == nil { - decoder = pixel.DefaultDecoderFunc - } - - return decoder(f) -} - // split is the actual algorithm for splitting a given space (by j in spcs) to fit the given width and height. // Will return an empty rectangle if a space wasn't available // This function is based on this project (https://github.com/TeamHypersomnia/rectpack2D)