9 Commits

Author SHA1 Message Date
394427d1b8 doc: README 2017-11-18 14:33:11 +13:00
9e7eca86b7 add height/width accessor methods 2017-11-18 13:26:07 +13:00
3378948eb2 doc: README 2017-11-18 13:10:52 +13:00
fb04e02c99 move files into top-level directory 2017-11-18 13:03:21 +13:00
05744a728e update tags 2017-11-17 12:01:43 +00:00
2791bc2cd7 thumbnailer: allow passing 0 as cache size 2017-11-18 12:52:53 +13:00
f89726198b thumbnailer: rename (unused) ASPECT_ constants 2017-11-18 12:52:42 +13:00
5b7b22bd95 thumbnailer: imports for previous 2017-11-18 12:52:24 +13:00
3905686363 thumbnailer: option to set custom mime type for file decoding 2017-11-18 12:52:17 +13:00
9 changed files with 72 additions and 27 deletions

1
.hgtags Normal file
View File

@@ -0,0 +1 @@
efd7b407177086c57e8c086605c2c8d1cee23840 release-1.0

View File

@@ -5,6 +5,7 @@ import (
"image/gif" "image/gif"
"image/jpeg" "image/jpeg"
"image/png" "image/png"
"mime"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@@ -21,9 +22,10 @@ const (
OUTPUT_JPG OutputFormat = 3 OUTPUT_JPG OutputFormat = 3
OUTPUT__DEFAULT = OUTPUT_PNG_CRUSH OUTPUT__DEFAULT = OUTPUT_PNG_CRUSH
ASPECT_PADDED AspectFormat = 80 ASPECT_PAD_TO_DIMENSIONS AspectFormat = 80
ASPECT_SVELTE AspectFormat = 81 ASPECT_RESPECT_MAX_DIMENSION_ONLY AspectFormat = 81
ASPECT__DEFAULT = ASPECT_PADDED ASPECT_CROP_TO_DIMENSIONS AspectFormat = 82
ASPECT__DEFAULT = ASPECT_PAD_TO_DIMENSIONS
SCALEFMT_NN ScaleFormat = 120 SCALEFMT_NN ScaleFormat = 120
SCALEFMT_BILINEAR ScaleFormat = 121 SCALEFMT_BILINEAR ScaleFormat = 121
@@ -42,35 +44,51 @@ type Thumbnailer struct {
afmt AspectFormat afmt AspectFormat
sfmt ScaleFormat sfmt ScaleFormat
thumbCache *lru.Cache // threadsafe thumbCache *lru.Cache // threadsafe, might be nil
} }
func NewThumbnailer(Width, Height, MaxCacheSize int) *Thumbnailer { func NewThumbnailer(Width, Height int, MaxCacheSize uint) *Thumbnailer {
return NewThumbnailerEx(Width, Height, MaxCacheSize, OUTPUT__DEFAULT, ASPECT__DEFAULT, SCALEFMT__DEFAULT) return NewThumbnailerEx(Width, Height, MaxCacheSize, OUTPUT__DEFAULT, ASPECT__DEFAULT, SCALEFMT__DEFAULT)
} }
func NewThumbnailerEx(Width, Height, MaxCacheSize int, of OutputFormat, af AspectFormat, sf ScaleFormat) *Thumbnailer { func NewThumbnailerEx(Width, Height int, MaxCacheSize uint, of OutputFormat, af AspectFormat, sf ScaleFormat) *Thumbnailer {
thumbCache, err := lru.New(MaxCacheSize)
if err != nil {
panic(err)
}
return &Thumbnailer{ ret := &Thumbnailer{
width: Width, width: Width,
height: Height, height: Height,
ofmt: of, ofmt: of,
afmt: af, afmt: af,
sfmt: sf, sfmt: sf,
thumbCache: thumbCache, thumbCache: nil,
} }
if MaxCacheSize > 0 {
thumbCache, err := lru.New(int(MaxCacheSize))
if err != nil {
panic(err)
}
ret.thumbCache = thumbCache
}
return ret
}
func (this *Thumbnailer) Width() int {
return this.width
}
func (this *Thumbnailer) Height() int {
return this.height
} }
func (this *Thumbnailer) RenderFile(absPath string) ([]byte, error) { func (this *Thumbnailer) RenderFile(absPath string) ([]byte, error) {
if this.thumbCache != nil {
thumb, ok := this.thumbCache.Get(absPath) thumb, ok := this.thumbCache.Get(absPath)
if ok { if ok {
return thumb.([]byte), nil return thumb.([]byte), nil
} }
}
// Add to cache // Add to cache
thumb, err := this.RenderFile_NoCache(absPath) thumb, err := this.RenderFile_NoCache(absPath)
@@ -78,8 +96,11 @@ func (this *Thumbnailer) RenderFile(absPath string) ([]byte, error) {
return nil, err return nil, err
} }
if this.thumbCache != nil {
this.thumbCache.Add(absPath, thumb) this.thumbCache.Add(absPath, thumb)
return thumb.([]byte), nil }
return thumb, nil
} }
func FiletypeSupported(ext string) bool { func FiletypeSupported(ext string) bool {
@@ -92,18 +113,18 @@ func FiletypeSupported(ext string) bool {
} }
func (this *Thumbnailer) RenderFile_NoCache(absPath string) ([]byte, error) { func (this *Thumbnailer) RenderFile_NoCache(absPath string) ([]byte, error) {
return this.RenderFile_NoCache_MimeType(absPath, mime.TypeByExtension(filepath.Ext(absPath)))
}
func (this *Thumbnailer) RenderFile_NoCache_MimeType(absPath, mimeType string) ([]byte, error) {
fh, err := os.OpenFile(absPath, os.O_RDONLY, 0400) fh, err := os.OpenFile(absPath, os.O_RDONLY, 0400)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer fh.Close() defer fh.Close()
extension := strings.ToLower(filepath.Ext(absPath)) if mimeType == `image/jpeg` {
switch extension {
case ".jpg", ".jpeg":
src, err := jpeg.Decode(fh) src, err := jpeg.Decode(fh)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -111,7 +132,7 @@ func (this *Thumbnailer) RenderFile_NoCache(absPath string) ([]byte, error) {
return this.RenderScaledImage(src) return this.RenderScaledImage(src)
case ".png": } else if mimeType == `image/png` {
src, err := png.Decode(fh) src, err := png.Decode(fh)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -119,7 +140,7 @@ func (this *Thumbnailer) RenderFile_NoCache(absPath string) ([]byte, error) {
return this.RenderScaledImage(src) return this.RenderScaledImage(src)
case ".gif": } else if mimeType == `image/gif` {
src, err := gif.Decode(fh) src, err := gif.Decode(fh)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -127,10 +148,10 @@ func (this *Thumbnailer) RenderFile_NoCache(absPath string) ([]byte, error) {
return this.RenderScaledImage(src) return this.RenderScaledImage(src)
case ".avi", ".mkv", ".mp4", ".ogm", ".wmv", ".flv", ".rm", ".rmvb": } else if strings.HasPrefix(mimeType, `video/`) {
return this.RenderScaledFfmpeg(absPath) return this.RenderScaledFfmpeg(absPath)
default: } else {
return nil, ErrUnsupportedFiletype return nil, ErrUnsupportedFiletype
} }

23
_dist/README.txt Normal file
View File

@@ -0,0 +1,23 @@
A thumbnailing library for Go.
Written in Go
Earlier versions of this project were vendored into `webdir`.
- Supports jpeg / png / gif files (internally) and video files (requires `ffmpeg` in `$PATH`)
- LRU cache of recent thumbnails for performance
- Scaling algorithms: Nearest-neighbour or bilinear
- Aspect ratio preserving (fit outside with image crop; fit inside with transparent background; fit inside with dimension reduction)
- Output formats: JPG (internal) or transparent PNG (via `go-imagequant`)
A standalone binary `mkthumb` is provided as a sample utility.
=CHANGELOG=
2017-11-18 0.2.0
- Initial standalone release
- Feature: Decode input with specified mime type
- Feature: Allow passing zero as thumbnail cache size
2017-01-03 webdir-1.0
- Version of `thumbnail` vendored with `webdir` 1.0

View File

@@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"os" "os"
"code.ivysaur.me/webdir/thumbnail" "code.ivysaur.me/thumbnail"
) )
func main() { func main() {