thumbnail/Thumbnailer.go

139 lines
2.7 KiB
Go

package thumbnail
import (
"errors"
"image/gif"
"image/jpeg"
"image/png"
"os"
"path/filepath"
"strings"
lru "github.com/hashicorp/golang-lru"
)
type OutputFormat uint8
type AspectFormat uint8
type ScaleFormat uint8
const (
OUTPUT_PNG_CRUSH OutputFormat = 2
OUTPUT_JPG OutputFormat = 3
OUTPUT__DEFAULT = OUTPUT_PNG_CRUSH
ASPECT_PADDED AspectFormat = 80
ASPECT_SVELTE AspectFormat = 81
ASPECT__DEFAULT = ASPECT_PADDED
SCALEFMT_NN ScaleFormat = 120
SCALEFMT_BILINEAR ScaleFormat = 121
SCALEFMT__DEFAULT = SCALEFMT_BILINEAR
)
var (
ErrInvalidOption error = errors.New("Invalid format parameter")
ErrUnsupportedFiletype error = errors.New("Unsupported filetype")
)
type Thumbnailer struct {
width int
height int
ofmt OutputFormat
afmt AspectFormat
sfmt ScaleFormat
thumbCache *lru.Cache // threadsafe
}
func NewThumbnailer(Width, Height, MaxCacheSize int) *Thumbnailer {
return NewThumbnailerEx(Width, Height, MaxCacheSize, OUTPUT__DEFAULT, ASPECT__DEFAULT, SCALEFMT__DEFAULT)
}
func NewThumbnailerEx(Width, Height, MaxCacheSize int, of OutputFormat, af AspectFormat, sf ScaleFormat) *Thumbnailer {
thumbCache, err := lru.New(MaxCacheSize)
if err != nil {
panic(err)
}
return &Thumbnailer{
width: Width,
height: Height,
ofmt: of,
afmt: af,
sfmt: sf,
thumbCache: thumbCache,
}
}
func (this *Thumbnailer) RenderFile(absPath string) ([]byte, error) {
thumb, ok := this.thumbCache.Get(absPath)
if ok {
return thumb.([]byte), nil
}
// Add to cache
thumb, err := this.RenderFile_NoCache(absPath)
if err != nil {
return nil, err
}
this.thumbCache.Add(absPath, thumb)
return thumb.([]byte), nil
}
func FiletypeSupported(ext string) bool {
switch strings.ToLower(ext) {
case ".jpg", ".jpeg", ".png", ".gif", ".avi", ".mkv", ".mp4", ".ogm", ".wmv", ".flv", ".rm", ".rmvb":
return true
default:
return false
}
}
func (this *Thumbnailer) RenderFile_NoCache(absPath string) ([]byte, error) {
fh, err := os.OpenFile(absPath, os.O_RDONLY, 0400)
if err != nil {
return nil, err
}
defer fh.Close()
extension := strings.ToLower(filepath.Ext(absPath))
switch extension {
case ".jpg", ".jpeg":
src, err := jpeg.Decode(fh)
if err != nil {
return nil, err
}
return this.RenderScaledImage(src)
case ".png":
src, err := png.Decode(fh)
if err != nil {
return nil, err
}
return this.RenderScaledImage(src)
case ".gif":
src, err := gif.Decode(fh)
if err != nil {
return nil, err
}
return this.RenderScaledImage(src)
case ".avi", ".mkv", ".mp4", ".ogm", ".wmv", ".flv", ".rm", ".rmvb":
return this.RenderScaledFfmpeg(absPath)
default:
return nil, ErrUnsupportedFiletype
}
}