mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-10 06:10:05 -06:00
refactor(thumbnails): separate out 'kovidgoyal/imaging' dependencies
Move code using the 'kovidgoyal/imaging' package to separate files to make it easier to create alternative implementations based on build tags.
This commit is contained in:
committed by
Ralf Haferkamp
parent
d0ce57dfc2
commit
358adc15dc
@@ -27,18 +27,6 @@ type FileConverter interface {
|
||||
Convert(r io.Reader) (interface{}, error)
|
||||
}
|
||||
|
||||
// ImageDecoder is a converter for the image file
|
||||
type ImageDecoder struct{}
|
||||
|
||||
// Convert reads the image file and returns the thumbnail image
|
||||
func (i ImageDecoder) Convert(r io.Reader) (interface{}, error) {
|
||||
img, err := imaging.Decode(r, imaging.AutoOrientation(true))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, `could not decode the image`)
|
||||
}
|
||||
return img, nil
|
||||
}
|
||||
|
||||
// GifDecoder is a converter for the gif file
|
||||
type GifDecoder struct{}
|
||||
|
||||
|
||||
20
services/thumbnails/pkg/preprocessor/preprocessor_imaging.go
Normal file
20
services/thumbnails/pkg/preprocessor/preprocessor_imaging.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package preprocessor
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/kovidgoyal/imaging"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ImageDecoder is a converter for the image file
|
||||
type ImageDecoder struct{}
|
||||
|
||||
// Convert reads the image file and returns the thumbnail image
|
||||
func (i ImageDecoder) Convert(r io.Reader) (interface{}, error) {
|
||||
img, err := imaging.Decode(r, imaging.AutoOrientation(true))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, `could not decode the image`)
|
||||
}
|
||||
return img, nil
|
||||
}
|
||||
@@ -1,10 +1,7 @@
|
||||
package thumbnail
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/gif"
|
||||
"image/jpeg"
|
||||
"image/png"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
@@ -29,50 +26,6 @@ type Encoder interface {
|
||||
MimeType() string
|
||||
}
|
||||
|
||||
// PngEncoder encodes to png
|
||||
type PngEncoder struct{}
|
||||
|
||||
// Encode encodes to png format
|
||||
func (e PngEncoder) Encode(w io.Writer, img interface{}) error {
|
||||
m, ok := img.(image.Image)
|
||||
if !ok {
|
||||
return errors.ErrInvalidType
|
||||
}
|
||||
return png.Encode(w, m)
|
||||
}
|
||||
|
||||
// Types returns the png suffix
|
||||
func (e PngEncoder) Types() []string {
|
||||
return []string{typePng}
|
||||
}
|
||||
|
||||
// MimeType returns the mimetype for png files.
|
||||
func (e PngEncoder) MimeType() string {
|
||||
return "image/png"
|
||||
}
|
||||
|
||||
// JpegEncoder encodes to jpg
|
||||
type JpegEncoder struct{}
|
||||
|
||||
// Encode encodes to jpg
|
||||
func (e JpegEncoder) Encode(w io.Writer, img interface{}) error {
|
||||
m, ok := img.(image.Image)
|
||||
if !ok {
|
||||
return errors.ErrInvalidType
|
||||
}
|
||||
return jpeg.Encode(w, m, nil)
|
||||
}
|
||||
|
||||
// Types returns the jpg suffixes.
|
||||
func (e JpegEncoder) Types() []string {
|
||||
return []string{typeJpeg, typeJpg}
|
||||
}
|
||||
|
||||
// MimeType returns the mimetype for jpg files.
|
||||
func (e JpegEncoder) MimeType() string {
|
||||
return "image/jpeg"
|
||||
}
|
||||
|
||||
// GifEncoder encodes to gif
|
||||
type GifEncoder struct{}
|
||||
|
||||
|
||||
54
services/thumbnails/pkg/thumbnail/encoding_imaging.go
Normal file
54
services/thumbnails/pkg/thumbnail/encoding_imaging.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package thumbnail
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/jpeg"
|
||||
"image/png"
|
||||
"io"
|
||||
|
||||
"github.com/owncloud/ocis/v2/services/thumbnails/pkg/errors"
|
||||
)
|
||||
|
||||
// PngEncoder encodes to png
|
||||
type PngEncoder struct{}
|
||||
|
||||
// Encode encodes to png format
|
||||
func (e PngEncoder) Encode(w io.Writer, img interface{}) error {
|
||||
m, ok := img.(image.Image)
|
||||
if !ok {
|
||||
return errors.ErrInvalidType
|
||||
}
|
||||
return png.Encode(w, m)
|
||||
}
|
||||
|
||||
// Types returns the png suffix
|
||||
func (e PngEncoder) Types() []string {
|
||||
return []string{typePng}
|
||||
}
|
||||
|
||||
// MimeType returns the mimetype for png files.
|
||||
func (e PngEncoder) MimeType() string {
|
||||
return "image/png"
|
||||
}
|
||||
|
||||
// JpegEncoder encodes to jpg
|
||||
type JpegEncoder struct{}
|
||||
|
||||
// Encode encodes to jpg
|
||||
func (e JpegEncoder) Encode(w io.Writer, img interface{}) error {
|
||||
m, ok := img.(image.Image)
|
||||
if !ok {
|
||||
return errors.ErrInvalidType
|
||||
}
|
||||
return jpeg.Encode(w, m, nil)
|
||||
}
|
||||
|
||||
// Types returns the jpg suffixes.
|
||||
func (e JpegEncoder) Types() []string {
|
||||
return []string{typeJpeg, typeJpg}
|
||||
}
|
||||
|
||||
// MimeType returns the mimetype for jpg files.
|
||||
func (e JpegEncoder) MimeType() string {
|
||||
return "image/jpeg"
|
||||
}
|
||||
@@ -14,44 +14,17 @@ import (
|
||||
// Generator generates a web friendly file version.
|
||||
type Generator interface {
|
||||
Generate(size image.Rectangle, img interface{}) (interface{}, error)
|
||||
Dimensions(img interface{}) (image.Rectangle, error)
|
||||
ProcessorID() string
|
||||
}
|
||||
|
||||
// SimpleGenerator is the default image generator and is used for all image types expect gif.
|
||||
type SimpleGenerator struct {
|
||||
processor Processor
|
||||
}
|
||||
|
||||
func NewSimpleGenerator(filetype, process string) (SimpleGenerator, error) {
|
||||
processor, err := ProcessorFor(filetype, process)
|
||||
if err != nil {
|
||||
return SimpleGenerator{}, err
|
||||
}
|
||||
return SimpleGenerator{processor: processor}, nil
|
||||
}
|
||||
|
||||
// ProcessorID returns the processor identification.
|
||||
func (g SimpleGenerator) ProcessorID() string {
|
||||
return g.processor.ID()
|
||||
}
|
||||
|
||||
// Generate generates a alternative image version.
|
||||
func (g SimpleGenerator) Generate(size image.Rectangle, img interface{}) (interface{}, error) {
|
||||
m, ok := img.(image.Image)
|
||||
if !ok {
|
||||
return nil, errors.ErrInvalidType
|
||||
}
|
||||
|
||||
return g.processor.Process(m, size.Dx(), size.Dy(), imaging.Lanczos), nil
|
||||
}
|
||||
|
||||
// GifGenerator is used to create a web friendly version of the provided gif image.
|
||||
type GifGenerator struct {
|
||||
processor Processor
|
||||
}
|
||||
|
||||
func NewGifGenerator(filetype, process string) (GifGenerator, error) {
|
||||
processor, err := ProcessorFor(filetype, process)
|
||||
processor, err := ProcessorFor(process, filetype)
|
||||
if err != nil {
|
||||
return GifGenerator{}, err
|
||||
}
|
||||
@@ -97,6 +70,14 @@ func (g GifGenerator) Generate(size image.Rectangle, img interface{}) (interface
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (g GifGenerator) Dimensions(img interface{}) (image.Rectangle, error) {
|
||||
m, ok := img.(*gif.GIF)
|
||||
if !ok {
|
||||
return image.Rectangle{}, errors.ErrInvalidType
|
||||
}
|
||||
return m.Image[0].Bounds(), nil
|
||||
}
|
||||
|
||||
func (g GifGenerator) imageToPaletted(img image.Image, p color.Palette) *image.Paletted {
|
||||
b := img.Bounds()
|
||||
pm := image.NewPaletted(b, p)
|
||||
|
||||
44
services/thumbnails/pkg/thumbnail/generator_simple.go
Normal file
44
services/thumbnails/pkg/thumbnail/generator_simple.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package thumbnail
|
||||
|
||||
import (
|
||||
"image"
|
||||
|
||||
"github.com/kovidgoyal/imaging"
|
||||
"github.com/owncloud/ocis/v2/services/thumbnails/pkg/errors"
|
||||
)
|
||||
|
||||
// SimpleGenerator is the default image generator and is used for all image types expect gif.
|
||||
type SimpleGenerator struct {
|
||||
processor Processor
|
||||
}
|
||||
|
||||
func NewSimpleGenerator(filetype, process string) (SimpleGenerator, error) {
|
||||
processor, err := ProcessorFor(process, filetype)
|
||||
if err != nil {
|
||||
return SimpleGenerator{}, err
|
||||
}
|
||||
return SimpleGenerator{processor: processor}, nil
|
||||
}
|
||||
|
||||
// ProcessorID returns the processor identification.
|
||||
func (g SimpleGenerator) ProcessorID() string {
|
||||
return g.processor.ID()
|
||||
}
|
||||
|
||||
// Generate generates a alternative image version.
|
||||
func (g SimpleGenerator) Generate(size image.Rectangle, img interface{}) (interface{}, error) {
|
||||
m, ok := img.(image.Image)
|
||||
if !ok {
|
||||
return nil, errors.ErrInvalidType
|
||||
}
|
||||
|
||||
return g.processor.Process(m, size.Dx(), size.Dy(), imaging.Lanczos), nil
|
||||
}
|
||||
|
||||
func (g SimpleGenerator) Dimensions(img interface{}) (image.Rectangle, error) {
|
||||
m, ok := img.(image.Image)
|
||||
if !ok {
|
||||
return image.Rectangle{}, errors.ErrInvalidType
|
||||
}
|
||||
return m.Bounds(), nil
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package thumbnail
|
||||
import (
|
||||
"bytes"
|
||||
"image"
|
||||
"image/gif"
|
||||
"mime"
|
||||
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
@@ -70,15 +69,12 @@ type SimpleManager struct {
|
||||
// Generate creates a thumbnail and stores it
|
||||
func (s SimpleManager) Generate(r Request, img interface{}) (string, error) {
|
||||
var match image.Rectangle
|
||||
var inputDimensions image.Rectangle
|
||||
switch m := img.(type) {
|
||||
case *gif.GIF:
|
||||
match = s.resolutions.ClosestMatch(r.Resolution, m.Image[0].Bounds())
|
||||
inputDimensions = m.Image[0].Bounds()
|
||||
case image.Image:
|
||||
match = s.resolutions.ClosestMatch(r.Resolution, m.Bounds())
|
||||
inputDimensions = m.Bounds()
|
||||
|
||||
inputDimensions, err := r.Generator.Dimensions(img)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
match = s.resolutions.ClosestMatch(r.Resolution, inputDimensions)
|
||||
|
||||
// validate max input image dimensions - 6016x4000
|
||||
if inputDimensions.Size().X > s.maxDimension.X || inputDimensions.Size().Y > s.maxDimension.Y {
|
||||
|
||||
@@ -183,6 +183,10 @@ func TestPreviewGenerationTooBigImage(t *testing.T) {
|
||||
|
||||
ext := path.Ext(tt.fileName)
|
||||
req.Encoder, _ = EncoderForType(ext)
|
||||
req.Generator, err = GeneratorFor(ext, "fit")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
generate, err := sut.Generate(req, convert)
|
||||
if err != nil {
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user