mirror of
https://github.com/photoprism/photoprism.git
synced 2025-12-12 08:44:04 +01:00
People: Refactor thumb package and variable names #22
This commit is contained in:
@@ -57,7 +57,7 @@ func RemoveFromFolderCache(rootName string) {
|
|||||||
func RemoveFromAlbumCoverCache(uid string) {
|
func RemoveFromAlbumCoverCache(uid string) {
|
||||||
cache := service.CoverCache()
|
cache := service.CoverCache()
|
||||||
|
|
||||||
for typeName := range thumb.Types {
|
for typeName := range thumb.Sizes {
|
||||||
cacheKey := CacheKey(albumCover, uid, typeName)
|
cacheKey := CacheKey(albumCover, uid, typeName)
|
||||||
|
|
||||||
cache.Delete(cacheKey)
|
cache.Delete(cacheKey)
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ func AlbumCover(router *gin.RouterGroup) {
|
|||||||
typeName := c.Param("type")
|
typeName := c.Param("type")
|
||||||
uid := c.Param("uid")
|
uid := c.Param("uid")
|
||||||
|
|
||||||
thumbType, ok := thumb.Types[typeName]
|
size, ok := thumb.Sizes[typeName]
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Errorf("%s: invalid type %s", albumCover, typeName)
|
log.Errorf("%s: invalid type %s", albumCover, typeName)
|
||||||
@@ -92,8 +92,8 @@ func AlbumCover(router *gin.RouterGroup) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use original file if thumb size exceeds limit, see https://github.com/photoprism/photoprism/issues/157
|
// Use original file if thumb size exceeds limit, see https://github.com/photoprism/photoprism/issues/157
|
||||||
if thumbType.ExceedsSizeUncached() && c.Query("download") == "" {
|
if size.ExceedsLimit() && c.Query("download") == "" {
|
||||||
log.Debugf("%s: using original, size exceeds limit (width %d, height %d)", albumCover, thumbType.Width, thumbType.Height)
|
log.Debugf("%s: using original, size exceeds limit (width %d, height %d)", albumCover, size.Width, size.Height)
|
||||||
AddCoverCacheHeader(c)
|
AddCoverCacheHeader(c)
|
||||||
c.File(fileName)
|
c.File(fileName)
|
||||||
return
|
return
|
||||||
@@ -101,10 +101,10 @@ func AlbumCover(router *gin.RouterGroup) {
|
|||||||
|
|
||||||
var thumbnail string
|
var thumbnail string
|
||||||
|
|
||||||
if conf.ThumbUncached() || thumbType.OnDemand() {
|
if conf.ThumbUncached() || size.Uncached() {
|
||||||
thumbnail, err = thumb.FromFile(fileName, f.FileHash, conf.ThumbPath(), thumbType.Width, thumbType.Height, f.FileOrientation, thumbType.Options...)
|
thumbnail, err = thumb.FromFile(fileName, f.FileHash, conf.ThumbPath(), size.Width, size.Height, f.FileOrientation, size.Options...)
|
||||||
} else {
|
} else {
|
||||||
thumbnail, err = thumb.FromCache(fileName, f.FileHash, conf.ThumbPath(), thumbType.Width, thumbType.Height, thumbType.Options...)
|
thumbnail, err = thumb.FromCache(fileName, f.FileHash, conf.ThumbPath(), size.Width, size.Height, size.Options...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -148,7 +148,7 @@ func LabelCover(router *gin.RouterGroup) {
|
|||||||
typeName := c.Param("type")
|
typeName := c.Param("type")
|
||||||
uid := c.Param("uid")
|
uid := c.Param("uid")
|
||||||
|
|
||||||
thumbType, ok := thumb.Types[typeName]
|
size, ok := thumb.Sizes[typeName]
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Errorf("%s: invalid type %s", labelCover, txt.Quote(typeName))
|
log.Errorf("%s: invalid type %s", labelCover, txt.Quote(typeName))
|
||||||
@@ -202,8 +202,8 @@ func LabelCover(router *gin.RouterGroup) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use original file if thumb size exceeds limit, see https://github.com/photoprism/photoprism/issues/157
|
// Use original file if thumb size exceeds limit, see https://github.com/photoprism/photoprism/issues/157
|
||||||
if thumbType.ExceedsSizeUncached() {
|
if size.ExceedsLimit() {
|
||||||
log.Debugf("%s: using original, size exceeds limit (width %d, height %d)", labelCover, thumbType.Width, thumbType.Height)
|
log.Debugf("%s: using original, size exceeds limit (width %d, height %d)", labelCover, size.Width, size.Height)
|
||||||
|
|
||||||
AddCoverCacheHeader(c)
|
AddCoverCacheHeader(c)
|
||||||
c.File(fileName)
|
c.File(fileName)
|
||||||
@@ -213,10 +213,10 @@ func LabelCover(router *gin.RouterGroup) {
|
|||||||
|
|
||||||
var thumbnail string
|
var thumbnail string
|
||||||
|
|
||||||
if conf.ThumbUncached() || thumbType.OnDemand() {
|
if conf.ThumbUncached() || size.Uncached() {
|
||||||
thumbnail, err = thumb.FromFile(fileName, f.FileHash, conf.ThumbPath(), thumbType.Width, thumbType.Height, f.FileOrientation, thumbType.Options...)
|
thumbnail, err = thumb.FromFile(fileName, f.FileHash, conf.ThumbPath(), size.Width, size.Height, f.FileOrientation, size.Options...)
|
||||||
} else {
|
} else {
|
||||||
thumbnail, err = thumb.FromCache(fileName, f.FileHash, conf.ThumbPath(), thumbType.Width, thumbType.Height, thumbType.Options...)
|
thumbnail, err = thumb.FromCache(fileName, f.FileHash, conf.ThumbPath(), size.Width, size.Height, size.Options...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const (
|
|||||||
// Parameters:
|
// Parameters:
|
||||||
// uid: string folder uid
|
// uid: string folder uid
|
||||||
// token: string url security token, see config
|
// token: string url security token, see config
|
||||||
// type: string thumb type, see thumb.Types
|
// type: string thumb type, see thumb.Sizes
|
||||||
func GetFolderCover(router *gin.RouterGroup) {
|
func GetFolderCover(router *gin.RouterGroup) {
|
||||||
router.GET("/folders/t/:uid/:token/:type", func(c *gin.Context) {
|
router.GET("/folders/t/:uid/:token/:type", func(c *gin.Context) {
|
||||||
if InvalidPreviewToken(c) {
|
if InvalidPreviewToken(c) {
|
||||||
@@ -37,7 +37,7 @@ func GetFolderCover(router *gin.RouterGroup) {
|
|||||||
typeName := c.Param("type")
|
typeName := c.Param("type")
|
||||||
download := c.Query("download") != ""
|
download := c.Query("download") != ""
|
||||||
|
|
||||||
thumbType, ok := thumb.Types[typeName]
|
size, ok := thumb.Sizes[typeName]
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Errorf("folder: invalid thumb type %s", txt.Quote(typeName))
|
log.Errorf("folder: invalid thumb type %s", txt.Quote(typeName))
|
||||||
@@ -45,11 +45,11 @@ func GetFolderCover(router *gin.RouterGroup) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if thumbType.ExceedsSize() && !conf.ThumbUncached() {
|
if size.Uncached() && !conf.ThumbUncached() {
|
||||||
typeName, thumbType = thumb.Find(conf.ThumbSize())
|
typeName, size = thumb.Find(conf.ThumbSizePrecached())
|
||||||
|
|
||||||
if typeName == "" {
|
if typeName == "" {
|
||||||
log.Errorf("folder: invalid thumb size %d", conf.ThumbSize())
|
log.Errorf("folder: invalid thumb size %d", conf.ThumbSizePrecached())
|
||||||
c.Data(http.StatusOK, "image/svg+xml", folderIconSvg)
|
c.Data(http.StatusOK, "image/svg+xml", folderIconSvg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -101,8 +101,8 @@ func GetFolderCover(router *gin.RouterGroup) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use original file if thumb size exceeds limit, see https://github.com/photoprism/photoprism/issues/157
|
// Use original file if thumb size exceeds limit, see https://github.com/photoprism/photoprism/issues/157
|
||||||
if thumbType.ExceedsSizeUncached() && !download {
|
if size.ExceedsLimit() && !download {
|
||||||
log.Debugf("%s: using original, size exceeds limit (width %d, height %d)", folderCover, thumbType.Width, thumbType.Height)
|
log.Debugf("%s: using original, size exceeds limit (width %d, height %d)", folderCover, size.Width, size.Height)
|
||||||
AddCoverCacheHeader(c)
|
AddCoverCacheHeader(c)
|
||||||
c.File(fileName)
|
c.File(fileName)
|
||||||
return
|
return
|
||||||
@@ -110,10 +110,10 @@ func GetFolderCover(router *gin.RouterGroup) {
|
|||||||
|
|
||||||
var thumbnail string
|
var thumbnail string
|
||||||
|
|
||||||
if conf.ThumbUncached() || thumbType.OnDemand() {
|
if conf.ThumbUncached() || size.Uncached() {
|
||||||
thumbnail, err = thumb.FromFile(fileName, f.FileHash, conf.ThumbPath(), thumbType.Width, thumbType.Height, f.FileOrientation, thumbType.Options...)
|
thumbnail, err = thumb.FromFile(fileName, f.FileHash, conf.ThumbPath(), size.Width, size.Height, f.FileOrientation, size.Options...)
|
||||||
} else {
|
} else {
|
||||||
thumbnail, err = thumb.FromCache(fileName, f.FileHash, conf.ThumbPath(), thumbType.Width, thumbType.Height, thumbType.Options...)
|
thumbnail, err = thumb.FromCache(fileName, f.FileHash, conf.ThumbPath(), size.Width, size.Height, size.Options...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import (
|
|||||||
// Parameters:
|
// Parameters:
|
||||||
// hash: string sha1 file hash
|
// hash: string sha1 file hash
|
||||||
// token: string url security token, see config
|
// token: string url security token, see config
|
||||||
// type: string thumb type, see thumb.Types
|
// type: string thumb type, see thumb.Sizes
|
||||||
func GetThumb(router *gin.RouterGroup) {
|
func GetThumb(router *gin.RouterGroup) {
|
||||||
router.GET("/t/:hash/:token/:type", func(c *gin.Context) {
|
router.GET("/t/:hash/:token/:type", func(c *gin.Context) {
|
||||||
if InvalidPreviewToken(c) {
|
if InvalidPreviewToken(c) {
|
||||||
@@ -37,7 +37,7 @@ func GetThumb(router *gin.RouterGroup) {
|
|||||||
typeName := c.Param("type")
|
typeName := c.Param("type")
|
||||||
download := c.Query("download") != ""
|
download := c.Query("download") != ""
|
||||||
|
|
||||||
thumbType, ok := thumb.Types[typeName]
|
size, ok := thumb.Sizes[typeName]
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Errorf("thumbs: invalid type %s", txt.Quote(typeName))
|
log.Errorf("thumbs: invalid type %s", txt.Quote(typeName))
|
||||||
@@ -45,11 +45,11 @@ func GetThumb(router *gin.RouterGroup) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if thumbType.ExceedsSize() && !conf.ThumbUncached() {
|
if size.Uncached() && !conf.ThumbUncached() {
|
||||||
typeName, thumbType = thumb.Find(conf.ThumbSize())
|
typeName, size = thumb.Find(conf.ThumbSizePrecached())
|
||||||
|
|
||||||
if typeName == "" {
|
if typeName == "" {
|
||||||
log.Errorf("thumbs: invalid size %d", conf.ThumbSize())
|
log.Errorf("thumbs: invalid size %d", conf.ThumbSizePrecached())
|
||||||
c.Data(http.StatusOK, "image/svg+xml", photoIconSvg)
|
c.Data(http.StatusOK, "image/svg+xml", photoIconSvg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ func GetThumb(router *gin.RouterGroup) {
|
|||||||
|
|
||||||
// Return existing thumbs straight away.
|
// Return existing thumbs straight away.
|
||||||
if !download {
|
if !download {
|
||||||
if fileName, err := thumb.FileName(fileHash, conf.ThumbPath(), thumbType.Width, thumbType.Height, thumbType.Options...); err == nil && fs.FileExists(fileName) {
|
if fileName, err := thumb.FileName(fileHash, conf.ThumbPath(), size.Width, size.Height, size.Options...); err == nil && fs.FileExists(fileName) {
|
||||||
c.File(fileName)
|
c.File(fileName)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -131,8 +131,8 @@ func GetThumb(router *gin.RouterGroup) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use original file if thumb size exceeds limit, see https://github.com/photoprism/photoprism/issues/157
|
// Use original file if thumb size exceeds limit, see https://github.com/photoprism/photoprism/issues/157
|
||||||
if thumbType.ExceedsSizeUncached() && c.Query("download") == "" {
|
if size.ExceedsLimit() && c.Query("download") == "" {
|
||||||
log.Debugf("thumbs: using original, size exceeds limit (width %d, height %d)", thumbType.Width, thumbType.Height)
|
log.Debugf("thumbs: using original, size exceeds limit (width %d, height %d)", size.Width, size.Height)
|
||||||
|
|
||||||
AddThumbCacheHeader(c)
|
AddThumbCacheHeader(c)
|
||||||
c.File(fileName)
|
c.File(fileName)
|
||||||
@@ -142,10 +142,10 @@ func GetThumb(router *gin.RouterGroup) {
|
|||||||
|
|
||||||
var thumbnail string
|
var thumbnail string
|
||||||
|
|
||||||
if conf.ThumbUncached() || thumbType.OnDemand() {
|
if conf.ThumbUncached() || size.Uncached() {
|
||||||
thumbnail, err = thumb.FromFile(fileName, f.FileHash, conf.ThumbPath(), thumbType.Width, thumbType.Height, f.FileOrientation, thumbType.Options...)
|
thumbnail, err = thumb.FromFile(fileName, f.FileHash, conf.ThumbPath(), size.Width, size.Height, f.FileOrientation, size.Options...)
|
||||||
} else {
|
} else {
|
||||||
thumbnail, err = thumb.FromCache(fileName, f.FileHash, conf.ThumbPath(), thumbType.Width, thumbType.Height, thumbType.Options...)
|
thumbnail, err = thumb.FromCache(fileName, f.FileHash, conf.ThumbPath(), size.Width, size.Height, size.Options...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -178,7 +178,7 @@ func GetThumb(router *gin.RouterGroup) {
|
|||||||
// Parameters:
|
// Parameters:
|
||||||
// hash: string sha1 file hash
|
// hash: string sha1 file hash
|
||||||
// token: string url security token, see config
|
// token: string url security token, see config
|
||||||
// type: string thumb type, see thumb.Types
|
// type: string thumb type, see thumb.Sizes
|
||||||
// area: string image area identifier, e.g. 022004010015
|
// area: string image area identifier, e.g. 022004010015
|
||||||
func GetThumbCrop(router *gin.RouterGroup) {
|
func GetThumbCrop(router *gin.RouterGroup) {
|
||||||
router.GET("/t/:hash/:token/:type/:area", func(c *gin.Context) {
|
router.GET("/t/:hash/:token/:type/:area", func(c *gin.Context) {
|
||||||
@@ -193,19 +193,19 @@ func GetThumbCrop(router *gin.RouterGroup) {
|
|||||||
cropArea := c.Param("area")
|
cropArea := c.Param("area")
|
||||||
download := c.Query("download") != ""
|
download := c.Query("download") != ""
|
||||||
|
|
||||||
thumbType, ok := thumb.Types[typeName]
|
size, ok := thumb.Sizes[typeName]
|
||||||
|
|
||||||
if !ok || len(thumbType.Options) < 1 {
|
if !ok || len(size.Options) < 1 {
|
||||||
log.Errorf("thumbs: invalid type %s", txt.Quote(typeName))
|
log.Errorf("thumbs: invalid type %s", txt.Quote(typeName))
|
||||||
c.Data(http.StatusOK, "image/svg+xml", photoIconSvg)
|
c.Data(http.StatusOK, "image/svg+xml", photoIconSvg)
|
||||||
return
|
return
|
||||||
} else if thumbType.Options[0] != thumb.ResampleCrop {
|
} else if size.Options[0] != thumb.ResampleCrop {
|
||||||
log.Errorf("thumbs: invalid crop %s", txt.Quote(typeName))
|
log.Errorf("thumbs: invalid crop %s", txt.Quote(typeName))
|
||||||
c.Data(http.StatusOK, "image/svg+xml", photoIconSvg)
|
c.Data(http.StatusOK, "image/svg+xml", photoIconSvg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fileName, err := crop.FromCache(fileHash, conf.ThumbPath(), thumbType.Width, thumbType.Height, cropArea)
|
fileName, err := crop.FromCache(fileHash, conf.ThumbPath(), size.Width, size.Height, cropArea)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("thumbs: %s", err)
|
log.Errorf("thumbs: %s", err)
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ func SharePreview(router *gin.RouterGroup) {
|
|||||||
return
|
return
|
||||||
} else if count < 12 {
|
} else if count < 12 {
|
||||||
f := p[0]
|
f := p[0]
|
||||||
thumbType, _ := thumb.Types["fit_720"]
|
size, _ := thumb.Sizes["fit_720"]
|
||||||
|
|
||||||
fileName := photoprism.FileName(f.FileRoot, f.FileName)
|
fileName := photoprism.FileName(f.FileRoot, f.FileName)
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ func SharePreview(router *gin.RouterGroup) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
thumbnail, err := thumb.FromFile(fileName, f.FileHash, conf.ThumbPath(), thumbType.Width, thumbType.Height, f.FileOrientation, thumbType.Options...)
|
thumbnail, err := thumb.FromFile(fileName, f.FileHash, conf.ThumbPath(), size.Width, size.Height, f.FileOrientation, size.Options...)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
@@ -117,7 +117,7 @@ func SharePreview(router *gin.RouterGroup) {
|
|||||||
y := 0
|
y := 0
|
||||||
|
|
||||||
preview := imaging.New(width, height, color.NRGBA{255, 255, 255, 255})
|
preview := imaging.New(width, height, color.NRGBA{255, 255, 255, 255})
|
||||||
thumbType, _ := thumb.Types["tile_224"]
|
size, _ := thumb.Sizes["tile_224"]
|
||||||
|
|
||||||
for _, f := range p {
|
for _, f := range p {
|
||||||
fileName := photoprism.FileName(f.FileRoot, f.FileName)
|
fileName := photoprism.FileName(f.FileRoot, f.FileName)
|
||||||
@@ -128,7 +128,7 @@ func SharePreview(router *gin.RouterGroup) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
thumbnail, err := thumb.FromFile(fileName, f.FileHash, conf.ThumbPath(), thumbType.Width, thumbType.Height, f.FileOrientation, thumbType.Options...)
|
thumbnail, err := thumb.FromFile(fileName, f.FileHash, conf.ThumbPath(), size.Width, size.Height, f.FileOrientation, size.Options...)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ func configAction(ctx *cli.Context) error {
|
|||||||
fmt.Printf("%-25s %s\n", "preview-token", conf.PreviewToken())
|
fmt.Printf("%-25s %s\n", "preview-token", conf.PreviewToken())
|
||||||
fmt.Printf("%-25s %s\n", "thumb-filter", conf.ThumbFilter())
|
fmt.Printf("%-25s %s\n", "thumb-filter", conf.ThumbFilter())
|
||||||
fmt.Printf("%-25s %t\n", "thumb-uncached", conf.ThumbUncached())
|
fmt.Printf("%-25s %t\n", "thumb-uncached", conf.ThumbUncached())
|
||||||
fmt.Printf("%-25s %d\n", "thumb-size", conf.ThumbSize())
|
fmt.Printf("%-25s %d\n", "thumb-size", conf.ThumbSizePrecached())
|
||||||
fmt.Printf("%-25s %d\n", "thumb-size-uncached", conf.ThumbSizeUncached())
|
fmt.Printf("%-25s %d\n", "thumb-size-uncached", conf.ThumbSizeUncached())
|
||||||
fmt.Printf("%-25s %s\n", "thumb-path", conf.ThumbPath())
|
fmt.Printf("%-25s %s\n", "thumb-path", conf.ThumbPath())
|
||||||
fmt.Printf("%-25s %d\n", "jpeg-size", conf.JpegSize())
|
fmt.Printf("%-25s %d\n", "jpeg-size", conf.JpegSize())
|
||||||
|
|||||||
@@ -9,21 +9,21 @@ import (
|
|||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ResampleCommand registers the thumbs cli command.
|
// ResampleCommand registers the resample cli command.
|
||||||
var ResampleCommand = cli.Command{
|
var ResampleCommand = cli.Command{
|
||||||
Name: "resample",
|
Name: "resample",
|
||||||
Aliases: []string{"thumbs"},
|
Aliases: []string{"thumbs"},
|
||||||
Usage: "Pre-renders thumbnails (significantly reduces memory and cpu usage)",
|
Usage: "Pre-caches thumbnails to reduce memory and cpu usage",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "force, f",
|
Name: "force, f",
|
||||||
Usage: "re-create existing thumbnails",
|
Usage: "replace existing thumbnails",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Action: resampleAction,
|
Action: resampleAction,
|
||||||
}
|
}
|
||||||
|
|
||||||
// resampleAction pre-render the thumbnails
|
// resampleAction pre-caches default thumbnails.
|
||||||
func resampleAction(ctx *cli.Context) error {
|
func resampleAction(ctx *cli.Context) error {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ type ClientConfig struct {
|
|||||||
Lenses entity.Lenses `json:"lenses"`
|
Lenses entity.Lenses `json:"lenses"`
|
||||||
Countries entity.Countries `json:"countries"`
|
Countries entity.Countries `json:"countries"`
|
||||||
People entity.People `json:"people"`
|
People entity.People `json:"people"`
|
||||||
Thumbs ThumbTypes `json:"thumbs"`
|
Thumbs ThumbSizes `json:"thumbs"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
MapKey string `json:"mapKey"`
|
MapKey string `json:"mapKey"`
|
||||||
DownloadToken string `json:"downloadToken"`
|
DownloadToken string `json:"downloadToken"`
|
||||||
|
|||||||
@@ -72,12 +72,12 @@ func init() {
|
|||||||
LowMem = TotalMem < MinMem
|
LowMem = TotalMem < MinMem
|
||||||
|
|
||||||
// Init public thumb sizes for use in client apps.
|
// Init public thumb sizes for use in client apps.
|
||||||
for i := len(thumb.DefaultTypes) - 1; i >= 0; i-- {
|
for i := len(thumb.DefaultSizes) - 1; i >= 0; i-- {
|
||||||
size := thumb.DefaultTypes[i]
|
name := thumb.DefaultSizes[i]
|
||||||
t := thumb.Types[size]
|
t := thumb.Sizes[name]
|
||||||
|
|
||||||
if t.Public {
|
if t.Public {
|
||||||
Thumbs = append(Thumbs, ThumbType{Size: size, Use: t.Use, Width: t.Width, Height: t.Height})
|
Thumbs = append(Thumbs, ThumbSize{Size: name, Use: t.Use, Width: t.Width, Height: t.Height})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,7 +131,7 @@ func (c *Config) Options() *Options {
|
|||||||
func (c *Config) Propagate() {
|
func (c *Config) Propagate() {
|
||||||
log.SetLevel(c.LogLevel())
|
log.SetLevel(c.LogLevel())
|
||||||
|
|
||||||
thumb.Size = c.ThumbSize()
|
thumb.SizePrecached = c.ThumbSizePrecached()
|
||||||
thumb.SizeUncached = c.ThumbSizeUncached()
|
thumb.SizeUncached = c.ThumbSizeUncached()
|
||||||
thumb.Filter = c.ThumbFilter()
|
thumb.Filter = c.ThumbFilter()
|
||||||
thumb.JpegQuality = c.JpegQuality()
|
thumb.JpegQuality = c.JpegQuality()
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PhotoPrism command-line parameters and flags.
|
// GlobalFlags describes global command-line parameters and flags.
|
||||||
var GlobalFlags = []cli.Flag{
|
var GlobalFlags = []cli.Flag{
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
@@ -387,7 +387,7 @@ var GlobalFlags = []cli.Flag{
|
|||||||
},
|
},
|
||||||
cli.IntFlag{
|
cli.IntFlag{
|
||||||
Name: "thumb-size, s",
|
Name: "thumb-size, s",
|
||||||
Usage: "static thumbnail size limit in `PIXELS` (720-7680)",
|
Usage: "pre-cached thumbnail size in `PIXELS` (720-7680)",
|
||||||
Value: 2048,
|
Value: 2048,
|
||||||
EnvVar: "PHOTOPRISM_THUMB_SIZE",
|
EnvVar: "PHOTOPRISM_THUMB_SIZE",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ func (c *Config) ThumbUncached() bool {
|
|||||||
return c.options.ThumbUncached
|
return c.options.ThumbUncached
|
||||||
}
|
}
|
||||||
|
|
||||||
// ThumbSize returns the pre-rendered thumbnail size limit in pixels (720-7680).
|
// ThumbSizePrecached returns the pre-cached thumbnail size limit in pixels (720-7680).
|
||||||
func (c *Config) ThumbSize() int {
|
func (c *Config) ThumbSizePrecached() int {
|
||||||
size := c.options.ThumbSize
|
size := c.options.ThumbSize
|
||||||
|
|
||||||
if size < 720 {
|
if size < 720 {
|
||||||
@@ -79,8 +79,8 @@ func (c *Config) ThumbSizeUncached() int {
|
|||||||
limit = 7680 // 8K Ultra HD
|
limit = 7680 // 8K Ultra HD
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.ThumbSize() > limit {
|
if c.ThumbSizePrecached() > limit {
|
||||||
limit = c.ThumbSize()
|
limit = c.ThumbSizePrecached()
|
||||||
}
|
}
|
||||||
|
|
||||||
return limit
|
return limit
|
||||||
|
|||||||
@@ -50,9 +50,9 @@ func TestConfig_ThumbSizeUncached(t *testing.T) {
|
|||||||
func TestConfig_ThumbSize(t *testing.T) {
|
func TestConfig_ThumbSize(t *testing.T) {
|
||||||
c := NewConfig(CliTestContext())
|
c := NewConfig(CliTestContext())
|
||||||
|
|
||||||
assert.Equal(t, int(720), c.ThumbSize())
|
assert.Equal(t, int(720), c.ThumbSizePrecached())
|
||||||
c.options.ThumbSize = 7681
|
c.options.ThumbSize = 7681
|
||||||
assert.Equal(t, int(7680), c.ThumbSize())
|
assert.Equal(t, int(7680), c.ThumbSizePrecached())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfig_ThumbSizeUncached2(t *testing.T) {
|
func TestConfig_ThumbSizeUncached2(t *testing.T) {
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ func NewTestConfig() *Config {
|
|||||||
|
|
||||||
c.InitTestDb()
|
c.InitTestDb()
|
||||||
|
|
||||||
thumb.Size = c.ThumbSize()
|
thumb.SizePrecached = c.ThumbSizePrecached()
|
||||||
thumb.SizeUncached = c.ThumbSizeUncached()
|
thumb.SizeUncached = c.ThumbSizeUncached()
|
||||||
thumb.Filter = c.ThumbFilter()
|
thumb.Filter = c.ThumbFilter()
|
||||||
thumb.JpegQuality = c.JpegQuality()
|
thumb.JpegQuality = c.JpegQuality()
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
// ThumbType represents thumbnail info for use in client apps.
|
// ThumbSize represents thumbnail info for use in client apps.
|
||||||
type ThumbType struct {
|
type ThumbSize struct {
|
||||||
Size string `json:"size"`
|
Size string `json:"size"`
|
||||||
Use string `json:"use"`
|
Use string `json:"use"`
|
||||||
Width int `json:"w"`
|
Width int `json:"w"`
|
||||||
Height int `json:"h"`
|
Height int `json:"h"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ThumbTypes represents a list of thumbnail types.
|
// ThumbSizes represents a list of thumbnail types.
|
||||||
type ThumbTypes []ThumbType
|
type ThumbSizes []ThumbSize
|
||||||
|
|
||||||
// Thumbs is a list of thumbnails for use in client apps.
|
// Thumbs is a list of thumbnails for use in client apps.
|
||||||
var Thumbs ThumbTypes
|
var Thumbs ThumbSizes
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ func ImportWorker(jobs <-chan ImportJob) {
|
|||||||
|
|
||||||
if res.Indexed() && f.IsJpeg() {
|
if res.Indexed() && f.IsJpeg() {
|
||||||
if err := f.ResampleDefault(ind.thumbPath(), false); err != nil {
|
if err := f.ResampleDefault(ind.thumbPath(), false); err != nil {
|
||||||
log.Errorf("import: failed creating thumbnails for %s (%s)", txt.Quote(f.BaseName()), err.Error())
|
log.Errorf("import: failed creating thumbs for %s (%s)", txt.Quote(f.BaseName()), err.Error())
|
||||||
query.SetFileError(res.FileUID, err.Error())
|
query.SetFileError(res.FileUID, err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ func (ind *Index) detectFaces(jpeg *MediaFile) face.Faces {
|
|||||||
var thumbSize string
|
var thumbSize string
|
||||||
|
|
||||||
// Select best thumbnail depending on configured size.
|
// Select best thumbnail depending on configured size.
|
||||||
if Config().ThumbSize() < 1280 {
|
if Config().ThumbSizePrecached() < 1280 {
|
||||||
minSize = 30
|
minSize = 30
|
||||||
thumbSize = "fit_720"
|
thumbSize = "fit_720"
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ func IndexMain(related *RelatedFiles, ind *Index, opt IndexOptions) (result Inde
|
|||||||
log.Debugf("index: %s created", txt.Quote(jpegFile.BaseName()))
|
log.Debugf("index: %s created", txt.Quote(jpegFile.BaseName()))
|
||||||
|
|
||||||
if err := jpegFile.ResampleDefault(ind.thumbPath(), false); err != nil {
|
if err := jpegFile.ResampleDefault(ind.thumbPath(), false); err != nil {
|
||||||
result.Err = fmt.Errorf("index: failed creating thumbnails for %s (%s)", txt.Quote(f.BaseName()), err.Error())
|
result.Err = fmt.Errorf("index: failed creating thumbs for %s (%s)", txt.Quote(f.BaseName()), err.Error())
|
||||||
result.Status = IndexFailed
|
result.Status = IndexFailed
|
||||||
|
|
||||||
return result
|
return result
|
||||||
@@ -59,7 +59,7 @@ func IndexMain(related *RelatedFiles, ind *Index, opt IndexOptions) (result Inde
|
|||||||
|
|
||||||
if result.Indexed() && f.IsJpeg() {
|
if result.Indexed() && f.IsJpeg() {
|
||||||
if err := f.ResampleDefault(ind.thumbPath(), false); err != nil {
|
if err := f.ResampleDefault(ind.thumbPath(), false); err != nil {
|
||||||
log.Errorf("index: failed creating thumbnails for %s (%s)", txt.Quote(f.BaseName()), err.Error())
|
log.Errorf("index: failed creating thumbs for %s (%s)", txt.Quote(f.BaseName()), err.Error())
|
||||||
query.SetFileError(result.FileUID, err.Error())
|
query.SetFileError(result.FileUID, err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,7 +126,7 @@ func IndexRelated(related RelatedFiles, ind *Index, opt IndexOptions) (result In
|
|||||||
log.Debugf("index: %s created", txt.Quote(jpegFile.BaseName()))
|
log.Debugf("index: %s created", txt.Quote(jpegFile.BaseName()))
|
||||||
|
|
||||||
if err := jpegFile.ResampleDefault(ind.thumbPath(), false); err != nil {
|
if err := jpegFile.ResampleDefault(ind.thumbPath(), false); err != nil {
|
||||||
result.Err = fmt.Errorf("index: failed creating thumbnails for %s (%s)", txt.Quote(f.BaseName()), err.Error())
|
result.Err = fmt.Errorf("index: failed creating thumbs for %s (%s)", txt.Quote(f.BaseName()), err.Error())
|
||||||
result.Status = IndexFailed
|
result.Status = IndexFailed
|
||||||
|
|
||||||
return result
|
return result
|
||||||
@@ -140,7 +140,7 @@ func IndexRelated(related RelatedFiles, ind *Index, opt IndexOptions) (result In
|
|||||||
|
|
||||||
if res.Indexed() && f.IsJpeg() {
|
if res.Indexed() && f.IsJpeg() {
|
||||||
if err := f.ResampleDefault(ind.thumbPath(), false); err != nil {
|
if err := f.ResampleDefault(ind.thumbPath(), false); err != nil {
|
||||||
log.Errorf("index: failed creating thumbnails for %s (%s)", txt.Quote(f.BaseName()), err.Error())
|
log.Errorf("index: failed creating thumbs for %s (%s)", txt.Quote(f.BaseName()), err.Error())
|
||||||
query.SetFileError(res.FileUID, err.Error())
|
query.SetFileError(res.FileUID, err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -888,14 +888,14 @@ func (m *MediaFile) Orientation() int {
|
|||||||
|
|
||||||
// Thumbnail returns a thumbnail filename.
|
// Thumbnail returns a thumbnail filename.
|
||||||
func (m *MediaFile) Thumbnail(path string, typeName string) (filename string, err error) {
|
func (m *MediaFile) Thumbnail(path string, typeName string) (filename string, err error) {
|
||||||
thumbType, ok := thumb.Types[typeName]
|
size, ok := thumb.Sizes[typeName]
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Errorf("media: invalid type %s", typeName)
|
log.Errorf("media: invalid type %s", typeName)
|
||||||
return "", fmt.Errorf("media: invalid type %s", typeName)
|
return "", fmt.Errorf("media: invalid type %s", typeName)
|
||||||
}
|
}
|
||||||
|
|
||||||
thumbnail, err := thumb.FromFile(m.FileName(), m.Hash(), path, thumbType.Width, thumbType.Height, m.Orientation(), thumbType.Options...)
|
thumbnail, err := thumb.FromFile(m.FileName(), m.Hash(), path, size.Width, size.Height, m.Orientation(), size.Options...)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("media: failed creating thumbnail for %s (%s)", txt.Quote(m.BaseName()), err)
|
err = fmt.Errorf("media: failed creating thumbnail for %s (%s)", txt.Quote(m.BaseName()), err)
|
||||||
@@ -917,7 +917,7 @@ func (m *MediaFile) Resample(path string, typeName string) (img image.Image, err
|
|||||||
return imaging.Open(filename)
|
return imaging.Open(filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResampleDefault pre-renders default thumbnails.
|
// ResampleDefault pre-caches default thumbnails.
|
||||||
func (m *MediaFile) ResampleDefault(thumbPath string, force bool) (err error) {
|
func (m *MediaFile) ResampleDefault(thumbPath string, force bool) (err error) {
|
||||||
count := 0
|
count := 0
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
@@ -925,11 +925,11 @@ func (m *MediaFile) ResampleDefault(thumbPath string, force bool) (err error) {
|
|||||||
defer func() {
|
defer func() {
|
||||||
switch count {
|
switch count {
|
||||||
case 0:
|
case 0:
|
||||||
log.Debug(capture.Time(start, fmt.Sprintf("media: no new thumbnails created for %s", m.BasePrefix(false))))
|
log.Debug(capture.Time(start, fmt.Sprintf("media: no new thumbs created for %s", m.BasePrefix(false))))
|
||||||
case 1:
|
case 1:
|
||||||
log.Info(capture.Time(start, fmt.Sprintf("media: one thumbnail created for %s", m.BasePrefix(false))))
|
log.Info(capture.Time(start, fmt.Sprintf("media: one thumbnail created for %s", m.BasePrefix(false))))
|
||||||
default:
|
default:
|
||||||
log.Info(capture.Time(start, fmt.Sprintf("media: %d thumbnails created for %s", count, m.BasePrefix(false))))
|
log.Info(capture.Time(start, fmt.Sprintf("media: %d thumbs created for %s", count, m.BasePrefix(false))))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -939,15 +939,15 @@ func (m *MediaFile) ResampleDefault(thumbPath string, force bool) (err error) {
|
|||||||
var sourceImg image.Image
|
var sourceImg image.Image
|
||||||
var sourceImgType string
|
var sourceImgType string
|
||||||
|
|
||||||
for _, name := range thumb.DefaultTypes {
|
for _, name := range thumb.DefaultSizes {
|
||||||
thumbType := thumb.Types[name]
|
size := thumb.Sizes[name]
|
||||||
|
|
||||||
if thumbType.OnDemand() {
|
if size.Uncached() {
|
||||||
// Skip, size exceeds limit
|
// Skip, exceeds pre-cached size limit.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if fileName, err := thumb.FileName(hash, thumbPath, thumbType.Width, thumbType.Height, thumbType.Options...); err != nil {
|
if fileName, err := thumb.FileName(hash, thumbPath, size.Width, size.Height, size.Options...); err != nil {
|
||||||
log.Errorf("media: failed creating %s (%s)", txt.Quote(name), err)
|
log.Errorf("media: failed creating %s (%s)", txt.Quote(name), err)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
@@ -969,14 +969,14 @@ func (m *MediaFile) ResampleDefault(thumbPath string, force bool) (err error) {
|
|||||||
originalImg = img
|
originalImg = img
|
||||||
}
|
}
|
||||||
|
|
||||||
if thumbType.Source != "" {
|
if size.Source != "" {
|
||||||
if thumbType.Source == sourceImgType && sourceImg != nil {
|
if size.Source == sourceImgType && sourceImg != nil {
|
||||||
_, err = thumb.Create(sourceImg, fileName, thumbType.Width, thumbType.Height, thumbType.Options...)
|
_, err = thumb.Create(sourceImg, fileName, size.Width, size.Height, size.Options...)
|
||||||
} else {
|
} else {
|
||||||
_, err = thumb.Create(originalImg, fileName, thumbType.Width, thumbType.Height, thumbType.Options...)
|
_, err = thumb.Create(originalImg, fileName, size.Width, size.Height, size.Options...)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sourceImg, err = thumb.Create(originalImg, fileName, thumbType.Width, thumbType.Height, thumbType.Options...)
|
sourceImg, err = thumb.Create(originalImg, fileName, size.Width, size.Height, size.Options...)
|
||||||
sourceImgType = name
|
sourceImgType = name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1873,7 +1873,7 @@ func TestMediaFile_RenderDefaultThumbs(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
thumbFilename, err := thumb.FileName(m.Hash(), thumbsPath, thumb.Types["tile_50"].Width, thumb.Types["tile_50"].Height, thumb.Types["tile_50"].Options...)
|
thumbFilename, err := thumb.FileName(m.Hash(), thumbsPath, thumb.Sizes["tile_50"].Width, thumb.Sizes["tile_50"].Height, thumb.Sizes["tile_50"].Options...)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ func TestResampleOptions(t *testing.T) {
|
|||||||
|
|
||||||
func TestResample(t *testing.T) {
|
func TestResample(t *testing.T) {
|
||||||
t.Run("tile50 options", func(t *testing.T) {
|
t.Run("tile50 options", func(t *testing.T) {
|
||||||
tile50 := Types["tile_50"]
|
tile50 := Sizes["tile_50"]
|
||||||
|
|
||||||
src := "testdata/example.jpg"
|
src := "testdata/example.jpg"
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ func TestResample(t *testing.T) {
|
|||||||
assert.Equal(t, 50, boundsNew.Max.Y)
|
assert.Equal(t, 50, boundsNew.Max.Y)
|
||||||
})
|
})
|
||||||
t.Run("left_224 options", func(t *testing.T) {
|
t.Run("left_224 options", func(t *testing.T) {
|
||||||
left224 := Types["left_224"]
|
left224 := Sizes["left_224"]
|
||||||
|
|
||||||
src := "testdata/example.jpg"
|
src := "testdata/example.jpg"
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ func TestResample(t *testing.T) {
|
|||||||
assert.Equal(t, 224, boundsNew.Max.Y)
|
assert.Equal(t, 224, boundsNew.Max.Y)
|
||||||
})
|
})
|
||||||
t.Run("right_224 options", func(t *testing.T) {
|
t.Run("right_224 options", func(t *testing.T) {
|
||||||
right224 := Types["right_224"]
|
right224 := Sizes["right_224"]
|
||||||
|
|
||||||
src := "testdata/example.jpg"
|
src := "testdata/example.jpg"
|
||||||
|
|
||||||
@@ -110,7 +110,7 @@ func TestResample(t *testing.T) {
|
|||||||
assert.Equal(t, 224, boundsNew.Max.Y)
|
assert.Equal(t, 224, boundsNew.Max.Y)
|
||||||
})
|
})
|
||||||
t.Run("fit_1280 options", func(t *testing.T) {
|
t.Run("fit_1280 options", func(t *testing.T) {
|
||||||
fit1280 := Types["fit_1280"]
|
fit1280 := Sizes["fit_1280"]
|
||||||
|
|
||||||
src := "testdata/example.jpg"
|
src := "testdata/example.jpg"
|
||||||
|
|
||||||
@@ -137,7 +137,7 @@ func TestResample(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSuffix(t *testing.T) {
|
func TestSuffix(t *testing.T) {
|
||||||
tile50 := Types["tile_50"]
|
tile50 := Sizes["tile_50"]
|
||||||
|
|
||||||
result := Suffix(tile50.Width, tile50.Height, tile50.Options...)
|
result := Suffix(tile50.Width, tile50.Height, tile50.Options...)
|
||||||
|
|
||||||
@@ -146,7 +146,7 @@ func TestSuffix(t *testing.T) {
|
|||||||
|
|
||||||
func TestFileName(t *testing.T) {
|
func TestFileName(t *testing.T) {
|
||||||
t.Run("colors", func(t *testing.T) {
|
t.Run("colors", func(t *testing.T) {
|
||||||
colorThumb := Types["colors"]
|
colorThumb := Sizes["colors"]
|
||||||
|
|
||||||
result, err := FileName("123456789098765432", "testdata", colorThumb.Width, colorThumb.Height, colorThumb.Options...)
|
result, err := FileName("123456789098765432", "testdata", colorThumb.Width, colorThumb.Height, colorThumb.Options...)
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ func TestFileName(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("fit_720", func(t *testing.T) {
|
t.Run("fit_720", func(t *testing.T) {
|
||||||
fit720 := Types["fit_720"]
|
fit720 := Sizes["fit_720"]
|
||||||
|
|
||||||
result, err := FileName("123456789098765432", "testdata", fit720.Width, fit720.Height, fit720.Options...)
|
result, err := FileName("123456789098765432", "testdata", fit720.Width, fit720.Height, fit720.Options...)
|
||||||
|
|
||||||
@@ -169,7 +169,7 @@ func TestFileName(t *testing.T) {
|
|||||||
assert.Equal(t, "testdata/1/2/3/123456789098765432_720x720_fit.jpg", result)
|
assert.Equal(t, "testdata/1/2/3/123456789098765432_720x720_fit.jpg", result)
|
||||||
})
|
})
|
||||||
t.Run("invalid width", func(t *testing.T) {
|
t.Run("invalid width", func(t *testing.T) {
|
||||||
colorThumb := Types["colors"]
|
colorThumb := Sizes["colors"]
|
||||||
|
|
||||||
result, err := FileName("123456789098765432", "testdata", -2, colorThumb.Height, colorThumb.Options...)
|
result, err := FileName("123456789098765432", "testdata", -2, colorThumb.Height, colorThumb.Options...)
|
||||||
|
|
||||||
@@ -180,7 +180,7 @@ func TestFileName(t *testing.T) {
|
|||||||
assert.Empty(t, result)
|
assert.Empty(t, result)
|
||||||
})
|
})
|
||||||
t.Run("invalid height", func(t *testing.T) {
|
t.Run("invalid height", func(t *testing.T) {
|
||||||
colorThumb := Types["colors"]
|
colorThumb := Sizes["colors"]
|
||||||
|
|
||||||
result, err := FileName("123456789098765432", "testdata", colorThumb.Width, -3, colorThumb.Options...)
|
result, err := FileName("123456789098765432", "testdata", colorThumb.Width, -3, colorThumb.Options...)
|
||||||
|
|
||||||
@@ -191,7 +191,7 @@ func TestFileName(t *testing.T) {
|
|||||||
assert.Empty(t, result)
|
assert.Empty(t, result)
|
||||||
})
|
})
|
||||||
t.Run("invalid hash", func(t *testing.T) {
|
t.Run("invalid hash", func(t *testing.T) {
|
||||||
colorThumb := Types["colors"]
|
colorThumb := Sizes["colors"]
|
||||||
|
|
||||||
result, err := FileName("12", "testdata", colorThumb.Width, colorThumb.Height, colorThumb.Options...)
|
result, err := FileName("12", "testdata", colorThumb.Width, colorThumb.Height, colorThumb.Options...)
|
||||||
|
|
||||||
@@ -202,7 +202,7 @@ func TestFileName(t *testing.T) {
|
|||||||
assert.Empty(t, result)
|
assert.Empty(t, result)
|
||||||
})
|
})
|
||||||
t.Run("invalid thumb path", func(t *testing.T) {
|
t.Run("invalid thumb path", func(t *testing.T) {
|
||||||
colorThumb := Types["colors"]
|
colorThumb := Sizes["colors"]
|
||||||
|
|
||||||
result, err := FileName("123456789098765432", "", colorThumb.Width, colorThumb.Height, colorThumb.Options...)
|
result, err := FileName("123456789098765432", "", colorThumb.Width, colorThumb.Height, colorThumb.Options...)
|
||||||
|
|
||||||
@@ -216,7 +216,7 @@ func TestFileName(t *testing.T) {
|
|||||||
|
|
||||||
func TestFromFile(t *testing.T) {
|
func TestFromFile(t *testing.T) {
|
||||||
t.Run("colors", func(t *testing.T) {
|
t.Run("colors", func(t *testing.T) {
|
||||||
colorThumb := Types["colors"]
|
colorThumb := Sizes["colors"]
|
||||||
src := "testdata/example.gif"
|
src := "testdata/example.gif"
|
||||||
dst := "testdata/1/2/3/123456789098765432_3x3_resize.png"
|
dst := "testdata/1/2/3/123456789098765432_3x3_resize.png"
|
||||||
|
|
||||||
@@ -234,7 +234,7 @@ func TestFromFile(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("orientation >1 ", func(t *testing.T) {
|
t.Run("orientation >1 ", func(t *testing.T) {
|
||||||
colorThumb := Types["colors"]
|
colorThumb := Sizes["colors"]
|
||||||
src := "testdata/example.gif"
|
src := "testdata/example.gif"
|
||||||
dst := "testdata/1/2/3/123456789098765432_3x3_resize.png"
|
dst := "testdata/1/2/3/123456789098765432_3x3_resize.png"
|
||||||
|
|
||||||
@@ -252,7 +252,7 @@ func TestFromFile(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("missing file", func(t *testing.T) {
|
t.Run("missing file", func(t *testing.T) {
|
||||||
colorThumb := Types["colors"]
|
colorThumb := Sizes["colors"]
|
||||||
src := "testdata/example.xxx"
|
src := "testdata/example.xxx"
|
||||||
|
|
||||||
assert.NoFileExists(t, src)
|
assert.NoFileExists(t, src)
|
||||||
@@ -263,7 +263,7 @@ func TestFromFile(t *testing.T) {
|
|||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
})
|
})
|
||||||
t.Run("empty filename", func(t *testing.T) {
|
t.Run("empty filename", func(t *testing.T) {
|
||||||
colorThumb := Types["colors"]
|
colorThumb := Sizes["colors"]
|
||||||
|
|
||||||
fileName, err := FromFile("", "193456789098765432", "testdata", colorThumb.Width, colorThumb.Height, OrientationNormal, colorThumb.Options...)
|
fileName, err := FromFile("", "193456789098765432", "testdata", colorThumb.Width, colorThumb.Height, OrientationNormal, colorThumb.Options...)
|
||||||
|
|
||||||
@@ -277,7 +277,7 @@ func TestFromFile(t *testing.T) {
|
|||||||
|
|
||||||
func TestFromCache(t *testing.T) {
|
func TestFromCache(t *testing.T) {
|
||||||
t.Run("missing thumb", func(t *testing.T) {
|
t.Run("missing thumb", func(t *testing.T) {
|
||||||
tile50 := Types["tile_50"]
|
tile50 := Sizes["tile_50"]
|
||||||
src := "testdata/example.jpg"
|
src := "testdata/example.jpg"
|
||||||
|
|
||||||
assert.FileExists(t, src)
|
assert.FileExists(t, src)
|
||||||
@@ -292,7 +292,7 @@ func TestFromCache(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("missing file", func(t *testing.T) {
|
t.Run("missing file", func(t *testing.T) {
|
||||||
tile50 := Types["tile_50"]
|
tile50 := Sizes["tile_50"]
|
||||||
src := "testdata/example.xxx"
|
src := "testdata/example.xxx"
|
||||||
|
|
||||||
assert.NoFileExists(t, src)
|
assert.NoFileExists(t, src)
|
||||||
@@ -303,7 +303,7 @@ func TestFromCache(t *testing.T) {
|
|||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
})
|
})
|
||||||
t.Run("invalid hash", func(t *testing.T) {
|
t.Run("invalid hash", func(t *testing.T) {
|
||||||
tile50 := Types["tile_50"]
|
tile50 := Sizes["tile_50"]
|
||||||
src := "testdata/example.jpg"
|
src := "testdata/example.jpg"
|
||||||
|
|
||||||
assert.FileExists(t, src)
|
assert.FileExists(t, src)
|
||||||
@@ -317,7 +317,7 @@ func TestFromCache(t *testing.T) {
|
|||||||
assert.Empty(t, fileName)
|
assert.Empty(t, fileName)
|
||||||
})
|
})
|
||||||
t.Run("empty filename", func(t *testing.T) {
|
t.Run("empty filename", func(t *testing.T) {
|
||||||
tile50 := Types["tile_50"]
|
tile50 := Sizes["tile_50"]
|
||||||
|
|
||||||
fileName, err := FromCache("", "193456789098765432", "testdata", tile50.Width, tile50.Height, tile50.Options...)
|
fileName, err := FromCache("", "193456789098765432", "testdata", tile50.Width, tile50.Height, tile50.Options...)
|
||||||
|
|
||||||
@@ -331,7 +331,7 @@ func TestFromCache(t *testing.T) {
|
|||||||
|
|
||||||
func TestCreate(t *testing.T) {
|
func TestCreate(t *testing.T) {
|
||||||
t.Run("tile_500", func(t *testing.T) {
|
t.Run("tile_500", func(t *testing.T) {
|
||||||
tile500 := Types["tile_500"]
|
tile500 := Sizes["tile_500"]
|
||||||
src := "testdata/example.jpg"
|
src := "testdata/example.jpg"
|
||||||
dst := "testdata/example.tile_500.jpg"
|
dst := "testdata/example.tile_500.jpg"
|
||||||
|
|
||||||
@@ -368,7 +368,7 @@ func TestCreate(t *testing.T) {
|
|||||||
assert.Equal(t, 500, boundsNew.Max.Y)
|
assert.Equal(t, 500, boundsNew.Max.Y)
|
||||||
})
|
})
|
||||||
t.Run("width & height <= 150", func(t *testing.T) {
|
t.Run("width & height <= 150", func(t *testing.T) {
|
||||||
tile500 := Types["tile_500"]
|
tile500 := Sizes["tile_500"]
|
||||||
src := "testdata/example.jpg"
|
src := "testdata/example.jpg"
|
||||||
dst := "testdata/example.tile_500.jpg"
|
dst := "testdata/example.tile_500.jpg"
|
||||||
|
|
||||||
@@ -405,7 +405,7 @@ func TestCreate(t *testing.T) {
|
|||||||
assert.Equal(t, 150, boundsNew.Max.Y)
|
assert.Equal(t, 150, boundsNew.Max.Y)
|
||||||
})
|
})
|
||||||
t.Run("invalid width", func(t *testing.T) {
|
t.Run("invalid width", func(t *testing.T) {
|
||||||
tile500 := Types["tile_500"]
|
tile500 := Sizes["tile_500"]
|
||||||
src := "testdata/example.jpg"
|
src := "testdata/example.jpg"
|
||||||
dst := "testdata/example.tile_500.jpg"
|
dst := "testdata/example.tile_500.jpg"
|
||||||
|
|
||||||
@@ -433,7 +433,7 @@ func TestCreate(t *testing.T) {
|
|||||||
t.Log(resized)
|
t.Log(resized)
|
||||||
})
|
})
|
||||||
t.Run("invalid height", func(t *testing.T) {
|
t.Run("invalid height", func(t *testing.T) {
|
||||||
tile500 := Types["tile_500"]
|
tile500 := Sizes["tile_500"]
|
||||||
src := "testdata/example.jpg"
|
src := "testdata/example.jpg"
|
||||||
dst := "testdata/example.tile_500.jpg"
|
dst := "testdata/example.tile_500.jpg"
|
||||||
|
|
||||||
|
|||||||
@@ -235,7 +235,6 @@ func TestJpeg(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("foo", func(t *testing.T) {
|
t.Run("foo", func(t *testing.T) {
|
||||||
|
|
||||||
src := "testdata/example.foo"
|
src := "testdata/example.foo"
|
||||||
dst := "testdata/example.foo.jpg"
|
dst := "testdata/example.foo.jpg"
|
||||||
|
|
||||||
|
|||||||
@@ -3,16 +3,16 @@ package thumb
|
|||||||
import "github.com/disintegration/imaging"
|
import "github.com/disintegration/imaging"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
Size = 2048
|
SizePrecached = 2048
|
||||||
SizeUncached = 7680
|
SizeUncached = 7680
|
||||||
Filter = ResampleLanczos
|
|
||||||
JpegQuality = 95
|
JpegQuality = 95
|
||||||
JpegQualitySmall = 80
|
JpegQualitySmall = 80
|
||||||
|
Filter = ResampleLanczos
|
||||||
)
|
)
|
||||||
|
|
||||||
func MaxSize() int {
|
func MaxSize() int {
|
||||||
if Size > SizeUncached {
|
if SizePrecached > SizeUncached {
|
||||||
return Size
|
return SizePrecached
|
||||||
}
|
}
|
||||||
|
|
||||||
return SizeUncached
|
return SizeUncached
|
||||||
@@ -69,7 +69,7 @@ var ResampleMethods = map[ResampleOption]string{
|
|||||||
ResampleResize: "resize",
|
ResampleResize: "resize",
|
||||||
}
|
}
|
||||||
|
|
||||||
type Type struct {
|
type Size struct {
|
||||||
Use string `json:"use"`
|
Use string `json:"use"`
|
||||||
Source string `json:"-"`
|
Source string `json:"-"`
|
||||||
Width int `json:"w"`
|
Width int `json:"w"`
|
||||||
@@ -78,9 +78,9 @@ type Type struct {
|
|||||||
Options []ResampleOption `json:"-"`
|
Options []ResampleOption `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type TypeMap map[string]Type
|
type SizeMap map[string]Size
|
||||||
|
|
||||||
var Types = TypeMap{
|
var Sizes = SizeMap{
|
||||||
"tile_50": {"Lists", "tile_500", 50, 50, false, []ResampleOption{ResampleFillCenter, ResampleDefault}},
|
"tile_50": {"Lists", "tile_500", 50, 50, false, []ResampleOption{ResampleFillCenter, ResampleDefault}},
|
||||||
"tile_100": {"Maps", "tile_500", 100, 100, false, []ResampleOption{ResampleFillCenter, ResampleDefault}},
|
"tile_100": {"Maps", "tile_500", 100, 100, false, []ResampleOption{ResampleFillCenter, ResampleDefault}},
|
||||||
"crop_160": {"FaceNet", "", 160, 160, false, []ResampleOption{ResampleCrop, ResampleDefault}},
|
"crop_160": {"FaceNet", "", 160, 160, false, []ResampleOption{ResampleCrop, ResampleDefault}},
|
||||||
@@ -99,7 +99,7 @@ var Types = TypeMap{
|
|||||||
"fit_7680": {"8K Ultra HD 2, Retina 6K", "", 7680, 4320, true, []ResampleOption{ResampleFit, ResampleDefault}},
|
"fit_7680": {"8K Ultra HD 2, Retina 6K", "", 7680, 4320, true, []ResampleOption{ResampleFit, ResampleDefault}},
|
||||||
}
|
}
|
||||||
|
|
||||||
var DefaultTypes = []string{
|
var DefaultSizes = []string{
|
||||||
"fit_7680",
|
"fit_7680",
|
||||||
"fit_4096",
|
"fit_4096",
|
||||||
"fit_2560",
|
"fit_2560",
|
||||||
@@ -117,29 +117,24 @@ var DefaultTypes = []string{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find returns the largest default thumbnail type for the given size limit.
|
// Find returns the largest default thumbnail type for the given size limit.
|
||||||
func Find(limit int) (name string, result Type) {
|
func Find(limit int) (name string, result Size) {
|
||||||
for _, name = range DefaultTypes {
|
for _, name = range DefaultSizes {
|
||||||
t := Types[name]
|
t := Sizes[name]
|
||||||
|
|
||||||
if t.Width <= limit && t.Height <= limit {
|
if t.Width <= limit && t.Height <= limit {
|
||||||
return name, t
|
return name, t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", Type{}
|
return "", Size{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExceedsSize tests if thumbnail type exceeds the cached thumbnails size.
|
// Uncached tests if thumbnail type exceeds the cached thumbnails size limit.
|
||||||
func (t Type) ExceedsSize() bool {
|
func (s Size) Uncached() bool {
|
||||||
return t.Width > Size || t.Height > Size
|
return s.Width > SizePrecached || s.Height > SizePrecached
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExceedsSizeUncached tests if thumbnail type is too large and can not be rendered at all.
|
// ExceedsLimit tests if thumbnail type is too large, and can not be rendered at all.
|
||||||
func (t Type) ExceedsSizeUncached() bool {
|
func (s Size) ExceedsLimit() bool {
|
||||||
return t.Width > MaxSize() || t.Height > MaxSize()
|
return s.Width > MaxSize() || s.Height > MaxSize()
|
||||||
}
|
|
||||||
|
|
||||||
// OnDemand tests if thumbnail type should not be pre-rendered.
|
|
||||||
func (t Type) OnDemand() bool {
|
|
||||||
return t.Width > Size || t.Height > Size
|
|
||||||
}
|
}
|
||||||
@@ -6,54 +6,37 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestType_ExceedsLimit(t *testing.T) {
|
func TestSize_ExceedsLimit(t *testing.T) {
|
||||||
Size = 1024
|
SizePrecached = 1024
|
||||||
SizeUncached = 2048
|
SizeUncached = 2048
|
||||||
|
|
||||||
fit4096 := Types["fit_4096"]
|
fit4096 := Sizes["fit_4096"]
|
||||||
assert.True(t, fit4096.ExceedsSizeUncached())
|
assert.True(t, fit4096.ExceedsLimit())
|
||||||
|
|
||||||
fit2048 := Types["fit_2048"]
|
fit2048 := Sizes["fit_2048"]
|
||||||
assert.False(t, fit2048.ExceedsSizeUncached())
|
assert.False(t, fit2048.ExceedsLimit())
|
||||||
|
|
||||||
tile500 := Types["tile_500"]
|
tile500 := Sizes["tile_500"]
|
||||||
assert.False(t, tile500.ExceedsSizeUncached())
|
assert.False(t, tile500.ExceedsLimit())
|
||||||
|
|
||||||
Size = 2048
|
SizePrecached = 2048
|
||||||
SizeUncached = 7680
|
SizeUncached = 7680
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestType_ExceedsSize(t *testing.T) {
|
func TestSize_Uncached(t *testing.T) {
|
||||||
Size = 1024
|
SizePrecached = 1024
|
||||||
SizeUncached = 2048
|
SizeUncached = 2048
|
||||||
|
|
||||||
fit4096 := Types["fit_4096"]
|
fit4096 := Sizes["fit_4096"]
|
||||||
assert.True(t, fit4096.ExceedsSize())
|
assert.True(t, fit4096.Uncached())
|
||||||
|
|
||||||
fit2048 := Types["fit_2048"]
|
fit2048 := Sizes["fit_2048"]
|
||||||
assert.True(t, fit2048.ExceedsSize())
|
assert.True(t, fit2048.Uncached())
|
||||||
|
|
||||||
tile500 := Types["tile_500"]
|
tile500 := Sizes["tile_500"]
|
||||||
assert.False(t, tile500.ExceedsSize())
|
assert.False(t, tile500.Uncached())
|
||||||
|
|
||||||
Size = 2048
|
SizePrecached = 2048
|
||||||
SizeUncached = 7680
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestType_SkipPreRender(t *testing.T) {
|
|
||||||
Size = 1024
|
|
||||||
SizeUncached = 2048
|
|
||||||
|
|
||||||
fit4096 := Types["fit_4096"]
|
|
||||||
assert.True(t, fit4096.OnDemand())
|
|
||||||
|
|
||||||
fit2048 := Types["fit_2048"]
|
|
||||||
assert.True(t, fit2048.OnDemand())
|
|
||||||
|
|
||||||
tile500 := Types["tile_500"]
|
|
||||||
assert.False(t, tile500.OnDemand())
|
|
||||||
|
|
||||||
Size = 2048
|
|
||||||
SizeUncached = 7680
|
SizeUncached = 7680
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +55,7 @@ func TestResampleFilter_Imaging(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFinde(t *testing.T) {
|
func TestFind(t *testing.T) {
|
||||||
t.Run("2048", func(t *testing.T) {
|
t.Run("2048", func(t *testing.T) {
|
||||||
tName, tType := Find(2048)
|
tName, tType := Find(2048)
|
||||||
assert.Equal(t, "fit_2048", tName)
|
assert.Equal(t, "fit_2048", tName)
|
||||||
@@ -18,7 +18,7 @@ func TestMain(m *testing.M) {
|
|||||||
code := m.Run()
|
code := m.Run()
|
||||||
|
|
||||||
// remove temporary test files
|
// remove temporary test files
|
||||||
os.RemoveAll("testdata/1")
|
_ = os.RemoveAll("testdata/1")
|
||||||
|
|
||||||
os.Exit(code)
|
os.Exit(code)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,14 +97,14 @@ func (worker *Share) Start() (err error) {
|
|||||||
srcFileName := photoprism.FileName(file.File.FileRoot, file.File.FileName)
|
srcFileName := photoprism.FileName(file.File.FileRoot, file.File.FileName)
|
||||||
|
|
||||||
if a.ShareSize != "" {
|
if a.ShareSize != "" {
|
||||||
thumbType, ok := thumb.Types[a.ShareSize]
|
size, ok := thumb.Sizes[a.ShareSize]
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Errorf("share: invalid size %s", a.ShareSize)
|
log.Errorf("share: invalid size %s", a.ShareSize)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
srcFileName, err = thumb.FromFile(srcFileName, file.File.FileHash, worker.conf.ThumbPath(), thumbType.Width, thumbType.Height, file.File.FileOrientation, thumbType.Options...)
|
srcFileName, err = thumb.FromFile(srcFileName, file.File.FileHash, worker.conf.ThumbPath(), size.Width, size.Height, file.File.FileOrientation, size.Options...)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
worker.logError(err)
|
worker.logError(err)
|
||||||
|
|||||||
Reference in New Issue
Block a user