You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

111 lines
2.2 KiB

  1. package media
  2. import (
  3. "fmt"
  4. "image"
  5. "io"
  6. "os"
  7. "path"
  8. "path/filepath"
  9. )
  10. func (ms *MediaSource) ThumbPath(m Media, size image.Rectangle) string {
  11. size = m.NormalizeSize(size)
  12. return thumbPath(size, m.Name)
  13. }
  14. func (ms *MediaSource) ThumbFilename(m Media, size image.Rectangle) string {
  15. size = m.NormalizeSize(size)
  16. return thumbFilename(ms.ThumbDir, size, m.Name)
  17. }
  18. func thumbFilename(dir string, size image.Rectangle, name string) string {
  19. return filepath.Join(dir, thumbPath(size, name))
  20. }
  21. func thumbPath(size image.Rectangle, name string) string {
  22. w := size.Dx()
  23. h := size.Dy()
  24. var ws, hs string
  25. if w != 0 {
  26. ws = fmt.Sprint(w)
  27. }
  28. if h != 0 {
  29. hs = fmt.Sprint(h)
  30. }
  31. thumbSlug := filepath.Join(fmt.Sprintf("%sx%s", ws, hs), name)
  32. return path.Join("", "media", thumbSlug)
  33. }
  34. func (ms *MediaSource) ThumbMax(m Media, maxDim int) (image.Rectangle, error) {
  35. width := m.Size.Dx()
  36. height := m.Size.Dy()
  37. if width == 0 && height == 0 {
  38. return m.Size, fmt.Errorf("invalid media")
  39. }
  40. if width > height {
  41. height = height * maxDim / width
  42. width = maxDim
  43. } else {
  44. width = width * maxDim / height
  45. height = maxDim
  46. }
  47. size := image.Rect(0, 0, width, height)
  48. actual, err := ms.Thumb(m, size)
  49. return actual, err
  50. }
  51. func (ms *MediaSource) HasThumb(m Media, size image.Rectangle) bool {
  52. fi, err := os.Stat(ms.ThumbFilename(m, size))
  53. if err != nil {
  54. return false
  55. }
  56. return m.Date().Before(fi.ModTime())
  57. }
  58. func (m Media) NormalizeSize(size image.Rectangle) image.Rectangle {
  59. return NormalizeSize(m.Size, size)
  60. }
  61. func (ms *MediaSource) Thumb(m Media, size image.Rectangle) (image.Rectangle, error) {
  62. size = m.NormalizeSize(size)
  63. if ms.HasThumb(m, size) {
  64. return size, nil
  65. }
  66. f, err := os.Open(m.FullName)
  67. if err != nil {
  68. return size, err
  69. }
  70. defer f.Close()
  71. return size, ms.thumbReader(f, m, size)
  72. }
  73. func (ms *MediaSource) thumbReader(r io.Reader, m Media, size image.Rectangle) error {
  74. size = m.NormalizeSize(size)
  75. switch m.Type {
  76. case TypeImage:
  77. img, _, err := image.Decode(r)
  78. if err != nil {
  79. return err
  80. }
  81. filename := ms.ThumbFilename(m, size)
  82. return ThumbImage(filename, img, size)
  83. case TypeVideo:
  84. return VideoEncode(m.FullName, size, ms.ThumbDir)
  85. default:
  86. return fmt.Errorf("cannot thumb media type %q", m.Type)
  87. }
  88. }