diff --git a/_assets/tests/elephant.jpg b/_assets/tests/elephant.jpg new file mode 100644 index 000000000..8dfd44d17 Binary files /dev/null and b/_assets/tests/elephant.jpg differ diff --git a/_assets/tests/rose.webp b/_assets/tests/rose.webp new file mode 100644 index 000000000..1e4b57ce8 Binary files /dev/null and b/_assets/tests/rose.webp differ diff --git a/_assets/tests/spin.gif b/_assets/tests/spin.gif new file mode 100644 index 000000000..4ca5fb82b Binary files /dev/null and b/_assets/tests/spin.gif differ diff --git a/_assets/tests/status.png b/_assets/tests/status.png new file mode 100644 index 000000000..3c511b7a1 Binary files /dev/null and b/_assets/tests/status.png differ diff --git a/images/files.go b/images/files.go index d5842266d..e9540d06f 100644 --- a/images/files.go +++ b/images/files.go @@ -7,7 +7,6 @@ import ( "image/jpeg" "image/png" "io" - "net/http" "os" "golang.org/x/image/webp" @@ -20,27 +19,45 @@ func Get(fileName string) (image.Image, error) { } defer file.Close() - fb := make([]byte, 12) - file.Read(fb) - ft := GetFileType(fb) - if ft == UNKNOWN { - return nil, errors.New("unsupported file type") + fb, err := prepareFileForDecode(file) + if err != nil { + return nil, err } - var img image.Image - switch ft { + return decodeImageData(fb, file) +} + +func prepareFileForDecode(file *os.File) ([]byte, error) { + // Read the first 14 bytes, used for performing image type checks before parsing the image data + fb := make([]byte, 14) + _, err := file.Read(fb) + if err != nil { + return nil, err + } + + // Reset the read cursor + _, err = file.Seek(0, 0) + if err != nil { + return nil, err + } + + return fb, nil +} + +func decodeImageData(buf []byte, r io.Reader) (img image.Image, err error) { + switch GetFileType(buf) { case JPEG: - img, err = jpeg.Decode(file) - break + img, err = jpeg.Decode(r) case PNG: - img, err = png.Decode(file) - break + img, err = png.Decode(r) case GIF: - img, err = gif.Decode(file) - break + img, err = gif.Decode(r) case WEBP: - img, err = webp.Decode(file) - break + img, err = webp.Decode(r) + case UNKNOWN: + fallthrough + default: + return nil, errors.New("unsupported file type") } if err != nil { return nil, err diff --git a/images/files_test.go b/images/files_test.go new file mode 100644 index 000000000..89dd3acf9 --- /dev/null +++ b/images/files_test.go @@ -0,0 +1,79 @@ +package images + +import ( + "github.com/stretchr/testify/require" + "image" + "testing" +) + +func TestGet(t *testing.T) { + + cs := []struct{ + Filepath string + Error bool + Nil bool + Bounds image.Rectangle + }{ + { + "../_assets/tests/elephant.jpg", + false, + false, + image.Rectangle{ + Min: image.Point{X: 0, Y: 0}, + Max: image.Point{X: 80, Y: 80}, + }, + }, + { + "../_assets/tests/status.png", + false, + false, + image.Rectangle{ + Min: image.Point{X: 0, Y: 0}, + Max: image.Point{X: 256, Y: 256}, + }, + }, + { + "../_assets/tests/spin.gif", + false, + false, + image.Rectangle{ + Min: image.Point{X: 0, Y: 0}, + Max: image.Point{X: 256, Y: 256}, + }, + }, + { + "../_assets/tests/rose.webp", + false, + false, + image.Rectangle{ + Min: image.Point{X: 0, Y: 0}, + Max: image.Point{X: 400, Y: 301}, + }, + }, + { + "../_assets/tests/test.aac", + true, + true, + image.Rectangle{}, + }, + } + + for _, test := range cs { + img, err := Get(test.Filepath) + + if test.Error { + require.Error(t, err) + } else { + require.NoError(t, err) + } + + if test.Nil { + require.Nil(t, img) + continue + } else { + require.NotNil(t, img) + } + + require.Exactly(t, test.Bounds, img.Bounds()) + } +}