From 371d0ea711796720994295377afc3a79ddfeffcb Mon Sep 17 00:00:00 2001 From: Deluan Date: Tue, 8 Mar 2016 23:31:48 -0500 Subject: [PATCH] Added size parameter to getCoverArt.view endpoint --- .gopmfile | 1 + .travis.yml | 1 + api/get_cover_art.go | 4 ++-- api/get_cover_art_test.go | 16 +++++++++---- engine/cover.go | 47 ++++++++++++++++++++++++++++++--------- 5 files changed, 53 insertions(+), 16 deletions(-) diff --git a/.gopmfile b/.gopmfile index 94933d578..40018f564 100644 --- a/.gopmfile +++ b/.gopmfile @@ -8,6 +8,7 @@ github.com/siddontang/ledisdb = commit:713b229 github.com/smartystreets/goconvey = commit:899ed5a github.com/karlkfi/inject = commit:fe06da2 github.com/dhowden/tag = commit:bccc91e +github.com/nfnt/resize = commit:4d93a29 [res] include = conf diff --git a/.travis.yml b/.travis.yml index 90171d66f..8b30b9446 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,7 @@ install: - go get github.com/karlkfi/inject - go get github.com/smartystreets/goconvey - go get github.com/dhowden/tag + - go get github.com/nfnt/resize script: - go test ./... -v diff --git a/api/get_cover_art.go b/api/get_cover_art.go index c2f1942d6..71f2f15d2 100644 --- a/api/get_cover_art.go +++ b/api/get_cover_art.go @@ -17,11 +17,11 @@ func (c *GetCoverArtController) Prepare() { inject.ExtractAssignable(utils.Graph, &c.cover) } -// TODO accept size parameter func (c *GetCoverArtController) Get() { id := c.RequiredParamString("id", "id parameter required") + size := c.ParamInt("size") - err := c.cover.GetCover(id, 0, c.Ctx.ResponseWriter) + err := c.cover.Get(id, size, c.Ctx.ResponseWriter) switch { case err == engine.DataNotFound: diff --git a/api/get_cover_art_test.go b/api/get_cover_art_test.go index 76cb43edb..5ee5055aa 100644 --- a/api/get_cover_art_test.go +++ b/api/get_cover_art_test.go @@ -3,16 +3,17 @@ package api_test import ( "testing" + "fmt" + "net/http" + "net/http/httptest" + + "github.com/astaxie/beego" "github.com/deluan/gosonic/api/responses" "github.com/deluan/gosonic/domain" . "github.com/deluan/gosonic/tests" "github.com/deluan/gosonic/tests/mocks" "github.com/deluan/gosonic/utils" . "github.com/smartystreets/goconvey/convey" - "net/http" - "net/http/httptest" - "github.com/astaxie/beego" - "fmt" ) func getCoverArt(params ...string) (*http.Request, *httptest.ResponseRecorder) { @@ -52,6 +53,13 @@ func TestGetCoverArt(t *testing.T) { So(w.Body.Bytes(), ShouldMatchMD5, "e859a71cd1b1aaeb1ad437d85b306668") So(w.Header().Get("Content-Type"), ShouldEqual, "image/jpeg") }) + Convey("When specifying a size", func() { + mockMediaFileRepo.SetData(`[{"Id":"2","HasCoverArt":true,"Path":"tests/fixtures/01 Invisible (RED) Edit Version.mp3"}]`, 1) + _, w := getCoverArt("id=2", "size=100") + + So(w.Body.Bytes(), ShouldMatchMD5, "04378f523ca3e8ead33bf7140d39799e") + So(w.Header().Get("Content-Type"), ShouldEqual, "image/jpeg") + }) Reset(func() { mockMediaFileRepo.SetData("[]", 0) mockMediaFileRepo.SetError(false) diff --git a/engine/cover.go b/engine/cover.go index 8f2feb193..5c0bc75e9 100644 --- a/engine/cover.go +++ b/engine/cover.go @@ -2,15 +2,23 @@ package engine import ( "io" - "io/ioutil" "os" + "image" + _ "image/gif" + _ "image/jpeg" + _ "image/png" + + "bytes" + "image/jpeg" + "github.com/deluan/gosonic/domain" "github.com/dhowden/tag" + "github.com/nfnt/resize" ) type Cover interface { - GetCover(id string, size int, out io.Writer) error + Get(id string, size int, out io.Writer) error } type cover struct { @@ -21,29 +29,48 @@ func NewCover(mr domain.MediaFileRepository) Cover { return cover{mr} } -func (c cover) GetCover(id string, size int, out io.Writer) error { +func (c cover) Get(id string, size int, out io.Writer) error { mf, err := c.mfileRepo.Get(id) if err != nil { return err } - var img []byte + var reader io.Reader if mf != nil && mf.HasCoverArt { - img, err = readFromTag(mf.Path) + reader, err = readFromTag(mf.Path) } else { - img, err = ioutil.ReadFile("static/default_cover.jpg") + f, err := os.Open("static/default_cover.jpg") + if err == nil { + defer f.Close() + reader = f + } } if err != nil { return DataNotFound } - _, err = out.Write(img) - return err + if size > 0 { + return resizeImage(reader, size, out) + } else { + _, err = io.Copy(out, reader) + return err + } + } -func readFromTag(path string) ([]byte, error) { +func resizeImage(reader io.Reader, size int, out io.Writer) error { + img, _, err := image.Decode(reader) + if err != nil { + return err + } + + m := resize.Resize(uint(size), 0, img, resize.NearestNeighbor) + return jpeg.Encode(out, m, &jpeg.Options{Quality: 75}) +} + +func readFromTag(path string) (io.Reader, error) { f, err := os.Open(path) if err != nil { return nil, err @@ -55,5 +82,5 @@ func readFromTag(path string) ([]byte, error) { return nil, err } - return m.Picture().Data, nil + return bytes.NewReader(m.Picture().Data), nil }