Files
opencloud/thumbnails/pkg/thumbnail/thumbnail.go
2020-11-26 16:36:51 +01:00

88 lines
2.3 KiB
Go

package thumbnail
import (
"bytes"
"image"
"github.com/owncloud/ocis/ocis-pkg/log"
"github.com/owncloud/ocis/thumbnails/pkg/thumbnail/storage"
"golang.org/x/image/draw"
)
// Request bundles information needed to generate a thumbnail for afile
type Request struct {
Resolution image.Rectangle
Encoder Encoder
ETag string
Username string
}
// Manager is responsible for generating thumbnails
type Manager interface {
// Get will return a thumbnail for a file
Get(Request, image.Image) ([]byte, error)
// GetStored loads the thumbnail from the storage.
// It will return nil if no image is stored for the given context.
GetStored(Request) []byte
}
// NewSimpleManager creates a new instance of SimpleManager
func NewSimpleManager(resolutions Resolutions, storage storage.Storage, logger log.Logger) SimpleManager {
return SimpleManager{
storage: storage,
logger: logger,
resolutions: resolutions,
}
}
// SimpleManager is a simple implementation of Manager
type SimpleManager struct {
storage storage.Storage
logger log.Logger
resolutions Resolutions
}
// Get implements the Get Method of Manager
func (s SimpleManager) Get(r Request, img image.Image) ([]byte, error) {
match := s.resolutions.ClosestMatch(r.Resolution, img.Bounds())
thumbnail := s.generate(match, img)
key := s.storage.BuildKey(mapToStorageRequest(r))
buf := new(bytes.Buffer)
err := r.Encoder.Encode(buf, thumbnail)
if err != nil {
return nil, err
}
bytes := buf.Bytes()
err = s.storage.Set(r.Username, key, bytes)
if err != nil {
s.logger.Warn().Err(err).Msg("could not store thumbnail")
}
return bytes, nil
}
// GetStored tries to get the stored thumbnail and return it.
// If there is no cached thumbnail it will return nil
func (s SimpleManager) GetStored(r Request) []byte {
key := s.storage.BuildKey(mapToStorageRequest(r))
stored := s.storage.Get(r.Username, key)
return stored
}
func (s SimpleManager) generate(r image.Rectangle, img image.Image) image.Image {
targetResolution := mapRatio(img.Bounds(), r)
thumbnail := image.NewRGBA(targetResolution)
draw.ApproxBiLinear.Scale(thumbnail, targetResolution, img, img.Bounds(), draw.Over, nil)
return thumbnail
}
func mapToStorageRequest(r Request) storage.Request {
sR := storage.Request{
ETag: r.ETag,
Resolution: r.Resolution,
Types: r.Encoder.Types(),
}
return sR
}