1
0
Fork 0
photos/pkg/bucket/photopreview.go

136 lines
2.9 KiB
Go

package bucket
import (
"errors"
"fmt"
"mime"
"net/url"
"sort"
"strings"
)
type Preview string
const previewPrefix = "preview/"
var ErrorInvalidPreview = errors.New("invalid preview")
func (p Preview) Validate() error {
if !strings.HasPrefix(string(p), previewPrefix) {
return fmt.Errorf("%w: %v", ErrorInvalidPreview, p)
}
return nil
}
func (p Preview) String() string {
return string(p)
}
func (p Preview) Path() string {
u := url.URL{
Path: string(p),
}
return u.String()
}
func (p Preview) Format() PhotoFormat {
extIndex := strings.LastIndex(string(p), ".")
return PhotoFormat(mime.TypeByExtension(string(p)[extIndex:]))
}
type PreviewOption struct {
Height int
//Width int
Format PhotoFormat
Quality int
}
type PhotoFormat string
const (
PhotoFormatJPEG PhotoFormat = "image/jpeg"
PhotoFormatWEBP PhotoFormat = "image/webp"
PhotoFormatHEIF PhotoFormat = "image/heif"
PhotoFormatPNG PhotoFormat = "image/png"
PhotoFormatGIF PhotoFormat = "image/gif"
PhotoFormatTIFF PhotoFormat = "image/tiff"
)
func (f PhotoFormat) ContentType() string {
return string(f)
}
var SupportedFormats = []PhotoFormat{
PhotoFormatJPEG,
PhotoFormatWEBP,
PhotoFormatHEIF,
PhotoFormatPNG,
PhotoFormatGIF,
PhotoFormatTIFF,
}
type PhotoQualityLevel int
const (
PhotoQualityLevelThumbnail PhotoQualityLevel = 0
PhotoQualityLevelBasic PhotoQualityLevel = 1
PhotoQualityLevelNormal PhotoQualityLevel = 2
PhotoQualityLevelExtreme PhotoQualityLevel = 3
)
func (f PhotoFormat) Quality(level PhotoQualityLevel) int {
if f == PhotoFormatJPEG || f == PhotoFormatWEBP {
return 34 + int(level)*18
}
if f == PhotoFormatHEIF {
return 10 + int(level)*10
}
return 0
}
func (p Photo) GetPreview(option PreviewOption) Preview {
objectBase := strings.Replace(string(p), photoPrefix, previewPrefix, 1)
extIndex := strings.LastIndex(objectBase, ".")
base := objectBase[:extIndex]
res := fmt.Sprintf("_h%dq%d", option.Height, option.Quality)
exts, err := mime.ExtensionsByType(option.Format.ContentType())
if err != nil {
panic(err)
}
sort.Strings(exts)
if len(exts) < 1 {
panic("missing MIME type to extension mapping, please configure within your operating system")
}
return Preview(base + res + exts[len(exts)-1])
}
var defaultSizes = []int{640, 320, 160, 80}
var defaultSizesThumb = []int{60, 30}
var defaultFormats = []PhotoFormat{
PhotoFormatWEBP,
PhotoFormatJPEG,
}
func DefaultPreviewOptions() []PreviewOption {
options := make([]PreviewOption, 0)
for _, size := range defaultSizes {
for _, format := range defaultFormats {
options = append(options, PreviewOption{
Height: size,
Format: format,
Quality: format.Quality(PhotoQualityLevelNormal),
})
}
}
for _, size := range defaultSizesThumb {
for _, format := range defaultFormats {
options = append(options, PreviewOption{
Height: size,
Format: format,
Quality: format.Quality(PhotoQualityLevelThumbnail),
})
}
}
return options
}