quintodrome/engine/cover.go

105 lines
1.8 KiB
Go
Raw Normal View History

package engine
import (
"bytes"
"image"
_ "image/gif"
"image/jpeg"
_ "image/png"
"io"
"os"
"strings"
2020-01-14 18:22:34 -09:00
"github.com/cloudsonic/sonic-server/model"
"github.com/dhowden/tag"
"github.com/nfnt/resize"
)
type Cover interface {
Get(id string, size int, out io.Writer) error
}
type cover struct {
ds model.DataStore
}
func NewCover(ds model.DataStore) Cover {
return &cover{ds}
}
func (c *cover) getCoverPath(id string) (string, error) {
switch {
case strings.HasPrefix(id, "al-"):
id = id[3:]
al, err := c.ds.Album().Get(id)
if err != nil {
return "", err
}
return al.CoverArtPath, nil
default:
mf, err := c.ds.MediaFile().Get(id)
if err != nil {
return "", err
}
if mf.HasCoverArt {
return mf.Path, nil
}
}
2020-01-14 18:22:34 -09:00
return "", model.ErrNotFound
}
2016-03-21 19:11:57 -08:00
func (c *cover) Get(id string, size int, out io.Writer) error {
path, err := c.getCoverPath(id)
2020-01-14 18:22:34 -09:00
if err != nil && err != model.ErrNotFound {
return err
}
var reader io.Reader
2020-01-14 18:22:34 -09:00
if err != model.ErrNotFound {
reader, err = readFromTag(path)
} else {
var f *os.File
f, err = os.Open("static/default_cover.jpg")
if err == nil {
defer f.Close()
reader = f
}
}
if err != nil {
2020-01-14 18:22:34 -09:00
return model.ErrNotFound
}
if size > 0 {
return resizeImage(reader, size, out)
}
2016-03-10 05:37:35 -09:00
_, err = io.Copy(out, reader)
return err
}
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
}
defer f.Close()
m, err := tag.ReadFrom(f)
if err != nil {
return nil, err
}
return bytes.NewReader(m.Picture().Data), nil
}