gopxl / pixel

A hand-crafted 2D game library in Go.
MIT License
225 stars 9 forks source link

Add convenience function for loading a picture directly from a file #111

Closed dusk125 closed 1 week ago

dusk125 commented 3 weeks ago

Not directly, but I can update the atlas to mimic this functionality.

The atlas loads the images as image.Image so it can pack them, then creates the pixel.PictureData from the already loaded images.

dusk125 commented 3 weeks ago

Thanks for the review, converting back to draft as I want to test something else out.

bhperry commented 3 weeks ago

Alternative proposal from discord discussions:

type ImageLoader interface {
    Image(path string) (image.Image, error)
    PictureData(path string) (*PictureData, error)
}

func NewFileLoader(decoder DecoderFunc) FileLoader {
    if decoder == nil {
        decoder = DefaultImageDecoder
    }
    return FileLoader{decoder: decoder}
}

type FileLoader struct {
    decoder DecoderFunc
}

func (fl FileLoader) Image(path string) (image.Image, error) {
    f, err := os.Open(path)
    if err != nil {
        return nil, err
    }
    defer f.Close()

    return fl.decoder(f)
}

func (fl FileLoader) PictureData(path string) (*PictureData, error) {
    img, err := fl.Image(path)
    if err != nil {
        return nil, err
    }
    return PictureDataFromImage(img), nil
}

func NewEmbedLoader(fs fs.FS, decoder DecoderFunc) EmbedLoader {
    if decoder == nil {
        decoder = DefaultImageDecoder
    }
    return EmbedLoader{fs: fs, decoder: decoder}
}

type EmbedLoader struct {
    fs      fs.FS
    decoder DecoderFunc
}

func (el EmbedLoader) Image(path string) (image.Image, error) {
    f, err := el.fs.Open(path)
    if err != nil {
        return nil, err
    }
    defer f.Close()

    return el.decoder(f)
}

func (el EmbedLoader) PictureData(path string) (*PictureData, error) {
    img, err := el.Image(path)
    if err != nil {
        return nil, err
    }
    return PictureDataFromImage(img), nil
}

Interface style allows pixel to provide a powerful set of loaders that come with self-contained state, while also allowing users to implement their own custom loaders (e.g. MyHttpServerLoader) that will work with the pixel ecosystem.