package thumbnail import ( "fmt" "image/gif" "image/jpeg" "image/png" "os" "path/filepath" "strings" lru "github.com/hashicorp/golang-lru" ) type Thumbnailer struct { Width int Height int thumbCache *lru.Cache // threadsafe } func NewThumbnailer(Width, Height, MaxCacheSize int) *Thumbnailer { thumbCache, err := lru.New(MaxCacheSize) if err != nil { panic(err) } return &Thumbnailer{ Width: Width, Height: Height, 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 (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": return this.RenderScaledFfmpeg(absPath) default: return nil, fmt.Errorf("No thumbnailer for file type '%s'", extension) } }