package media import ( "fmt" "image" "io" "os" "path" "path/filepath" ) func (ms *MediaSource) ThumbPath(m Media, size image.Rectangle) string { size = m.NormalizeSize(size) return thumbPath(size, m.Name) } func (ms *MediaSource) ThumbFilename(m Media, size image.Rectangle) string { size = m.NormalizeSize(size) return thumbFilename(ms.ThumbDir, size, m.Name) } func thumbFilename(dir string, size image.Rectangle, name string) string { return filepath.Join(dir, thumbPath(size, name)) } func thumbPath(size image.Rectangle, name string) string { w := size.Dx() h := size.Dy() var ws, hs string if w != 0 { ws = fmt.Sprint(w) } if h != 0 { hs = fmt.Sprint(h) } thumbSlug := filepath.Join(fmt.Sprintf("%sx%s", ws, hs), name) return path.Join("", "media", thumbSlug) } func (ms *MediaSource) ThumbMax(m Media, maxDim int) (image.Rectangle, error) { width := m.Size.Dx() height := m.Size.Dy() if width == 0 && height == 0 { return m.Size, fmt.Errorf("invalid media") } if width > height { height = height * maxDim / width width = maxDim } else { width = width * maxDim / height height = maxDim } size := image.Rect(0, 0, width, height) actual, err := ms.Thumb(m, size) return actual, err } func (ms *MediaSource) HasThumb(m Media, size image.Rectangle) bool { fi, err := os.Stat(ms.ThumbFilename(m, size)) if err != nil { return false } return m.Date().Before(fi.ModTime()) } func (m Media) NormalizeSize(size image.Rectangle) image.Rectangle { return NormalizeSize(m.Size, size) } func (ms *MediaSource) Thumb(m Media, size image.Rectangle) (image.Rectangle, error) { size = m.NormalizeSize(size) if ms.HasThumb(m, size) { return size, nil } f, err := os.Open(m.FullName) if err != nil { return size, err } defer f.Close() return size, ms.thumbReader(f, m, size) } func (ms *MediaSource) thumbReader(r io.Reader, m Media, size image.Rectangle) error { size = m.NormalizeSize(size) switch m.Type { case TypeImage: img, _, err := image.Decode(r) if err != nil { return err } filename := ms.ThumbFilename(m, size) return ThumbImage(filename, img, size) case TypeVideo: return VideoEncode(m.FullName, size, ms.ThumbDir) default: return fmt.Errorf("cannot thumb media type %q", m.Type) } }