diff --git a/internal/api/cache.go b/internal/api/cache.go index e30d3f3a0..9bb66f20e 100644 --- a/internal/api/cache.go +++ b/internal/api/cache.go @@ -57,7 +57,7 @@ func RemoveFromFolderCache(rootName string) { func RemoveFromAlbumCoverCache(uid string) { cache := service.CoverCache() - for typeName := range thumb.Types { + for typeName := range thumb.Sizes { cacheKey := CacheKey(albumCover, uid, typeName) cache.Delete(cacheKey) diff --git a/internal/api/covers.go b/internal/api/covers.go index e831b61f5..1d7283cba 100644 --- a/internal/api/covers.go +++ b/internal/api/covers.go @@ -38,7 +38,7 @@ func AlbumCover(router *gin.RouterGroup) { typeName := c.Param("type") uid := c.Param("uid") - thumbType, ok := thumb.Types[typeName] + size, ok := thumb.Sizes[typeName] if !ok { 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 - if thumbType.ExceedsSizeUncached() && c.Query("download") == "" { - log.Debugf("%s: using original, size exceeds limit (width %d, height %d)", albumCover, thumbType.Width, thumbType.Height) + if size.ExceedsLimit() && c.Query("download") == "" { + log.Debugf("%s: using original, size exceeds limit (width %d, height %d)", albumCover, size.Width, size.Height) AddCoverCacheHeader(c) c.File(fileName) return @@ -101,10 +101,10 @@ func AlbumCover(router *gin.RouterGroup) { var thumbnail string - if conf.ThumbUncached() || thumbType.OnDemand() { - thumbnail, err = thumb.FromFile(fileName, f.FileHash, conf.ThumbPath(), thumbType.Width, thumbType.Height, f.FileOrientation, thumbType.Options...) + if conf.ThumbUncached() || size.Uncached() { + thumbnail, err = thumb.FromFile(fileName, f.FileHash, conf.ThumbPath(), size.Width, size.Height, f.FileOrientation, size.Options...) } 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 { @@ -148,7 +148,7 @@ func LabelCover(router *gin.RouterGroup) { typeName := c.Param("type") uid := c.Param("uid") - thumbType, ok := thumb.Types[typeName] + size, ok := thumb.Sizes[typeName] if !ok { 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 - if thumbType.ExceedsSizeUncached() { - log.Debugf("%s: using original, size exceeds limit (width %d, height %d)", labelCover, thumbType.Width, thumbType.Height) + if size.ExceedsLimit() { + log.Debugf("%s: using original, size exceeds limit (width %d, height %d)", labelCover, size.Width, size.Height) AddCoverCacheHeader(c) c.File(fileName) @@ -213,10 +213,10 @@ func LabelCover(router *gin.RouterGroup) { var thumbnail string - if conf.ThumbUncached() || thumbType.OnDemand() { - thumbnail, err = thumb.FromFile(fileName, f.FileHash, conf.ThumbPath(), thumbType.Width, thumbType.Height, f.FileOrientation, thumbType.Options...) + if conf.ThumbUncached() || size.Uncached() { + thumbnail, err = thumb.FromFile(fileName, f.FileHash, conf.ThumbPath(), size.Width, size.Height, f.FileOrientation, size.Options...) } 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 { diff --git a/internal/api/folder_cover.go b/internal/api/folder_cover.go index af7210eb2..0f70960b1 100644 --- a/internal/api/folder_cover.go +++ b/internal/api/folder_cover.go @@ -23,7 +23,7 @@ const ( // Parameters: // uid: string folder uid // 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) { router.GET("/folders/t/:uid/:token/:type", func(c *gin.Context) { if InvalidPreviewToken(c) { @@ -37,7 +37,7 @@ func GetFolderCover(router *gin.RouterGroup) { typeName := c.Param("type") download := c.Query("download") != "" - thumbType, ok := thumb.Types[typeName] + size, ok := thumb.Sizes[typeName] if !ok { log.Errorf("folder: invalid thumb type %s", txt.Quote(typeName)) @@ -45,11 +45,11 @@ func GetFolderCover(router *gin.RouterGroup) { return } - if thumbType.ExceedsSize() && !conf.ThumbUncached() { - typeName, thumbType = thumb.Find(conf.ThumbSize()) + if size.Uncached() && !conf.ThumbUncached() { + typeName, size = thumb.Find(conf.ThumbSizePrecached()) 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) 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 - if thumbType.ExceedsSizeUncached() && !download { - log.Debugf("%s: using original, size exceeds limit (width %d, height %d)", folderCover, thumbType.Width, thumbType.Height) + if size.ExceedsLimit() && !download { + log.Debugf("%s: using original, size exceeds limit (width %d, height %d)", folderCover, size.Width, size.Height) AddCoverCacheHeader(c) c.File(fileName) return @@ -110,10 +110,10 @@ func GetFolderCover(router *gin.RouterGroup) { var thumbnail string - if conf.ThumbUncached() || thumbType.OnDemand() { - thumbnail, err = thumb.FromFile(fileName, f.FileHash, conf.ThumbPath(), thumbType.Width, thumbType.Height, f.FileOrientation, thumbType.Options...) + if conf.ThumbUncached() || size.Uncached() { + thumbnail, err = thumb.FromFile(fileName, f.FileHash, conf.ThumbPath(), size.Width, size.Height, f.FileOrientation, size.Options...) } 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 { diff --git a/internal/api/photo_thumb.go b/internal/api/photo_thumb.go index 7f9a0a1d1..73ea37c0b 100644 --- a/internal/api/photo_thumb.go +++ b/internal/api/photo_thumb.go @@ -23,7 +23,7 @@ import ( // Parameters: // hash: string sha1 file hash // 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) { router.GET("/t/:hash/:token/:type", func(c *gin.Context) { if InvalidPreviewToken(c) { @@ -37,7 +37,7 @@ func GetThumb(router *gin.RouterGroup) { typeName := c.Param("type") download := c.Query("download") != "" - thumbType, ok := thumb.Types[typeName] + size, ok := thumb.Sizes[typeName] if !ok { log.Errorf("thumbs: invalid type %s", txt.Quote(typeName)) @@ -45,11 +45,11 @@ func GetThumb(router *gin.RouterGroup) { return } - if thumbType.ExceedsSize() && !conf.ThumbUncached() { - typeName, thumbType = thumb.Find(conf.ThumbSize()) + if size.Uncached() && !conf.ThumbUncached() { + typeName, size = thumb.Find(conf.ThumbSizePrecached()) 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) return } @@ -82,7 +82,7 @@ func GetThumb(router *gin.RouterGroup) { // Return existing thumbs straight away. 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) 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 - if thumbType.ExceedsSizeUncached() && c.Query("download") == "" { - log.Debugf("thumbs: using original, size exceeds limit (width %d, height %d)", thumbType.Width, thumbType.Height) + if size.ExceedsLimit() && c.Query("download") == "" { + log.Debugf("thumbs: using original, size exceeds limit (width %d, height %d)", size.Width, size.Height) AddThumbCacheHeader(c) c.File(fileName) @@ -142,10 +142,10 @@ func GetThumb(router *gin.RouterGroup) { var thumbnail string - if conf.ThumbUncached() || thumbType.OnDemand() { - thumbnail, err = thumb.FromFile(fileName, f.FileHash, conf.ThumbPath(), thumbType.Width, thumbType.Height, f.FileOrientation, thumbType.Options...) + if conf.ThumbUncached() || size.Uncached() { + thumbnail, err = thumb.FromFile(fileName, f.FileHash, conf.ThumbPath(), size.Width, size.Height, f.FileOrientation, size.Options...) } 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 { @@ -178,7 +178,7 @@ func GetThumb(router *gin.RouterGroup) { // Parameters: // hash: string sha1 file hash // 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 func GetThumbCrop(router *gin.RouterGroup) { router.GET("/t/:hash/:token/:type/:area", func(c *gin.Context) { @@ -193,19 +193,19 @@ func GetThumbCrop(router *gin.RouterGroup) { cropArea := c.Param("area") 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)) c.Data(http.StatusOK, "image/svg+xml", photoIconSvg) return - } else if thumbType.Options[0] != thumb.ResampleCrop { + } else if size.Options[0] != thumb.ResampleCrop { log.Errorf("thumbs: invalid crop %s", txt.Quote(typeName)) c.Data(http.StatusOK, "image/svg+xml", photoIconSvg) 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 { log.Errorf("thumbs: %s", err) diff --git a/internal/api/share_preview.go b/internal/api/share_preview.go index e34861593..9ce11029f 100644 --- a/internal/api/share_preview.go +++ b/internal/api/share_preview.go @@ -88,7 +88,7 @@ func SharePreview(router *gin.RouterGroup) { return } else if count < 12 { f := p[0] - thumbType, _ := thumb.Types["fit_720"] + size, _ := thumb.Sizes["fit_720"] fileName := photoprism.FileName(f.FileRoot, f.FileName) @@ -98,7 +98,7 @@ func SharePreview(router *gin.RouterGroup) { 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 { log.Error(err) @@ -117,7 +117,7 @@ func SharePreview(router *gin.RouterGroup) { y := 0 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 { fileName := photoprism.FileName(f.FileRoot, f.FileName) @@ -128,7 +128,7 @@ func SharePreview(router *gin.RouterGroup) { 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 { log.Error(err) diff --git a/internal/commands/config.go b/internal/commands/config.go index 17fa58d2e..305f23191 100644 --- a/internal/commands/config.go +++ b/internal/commands/config.go @@ -132,7 +132,7 @@ func configAction(ctx *cli.Context) error { fmt.Printf("%-25s %s\n", "preview-token", conf.PreviewToken()) fmt.Printf("%-25s %s\n", "thumb-filter", conf.ThumbFilter()) 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 %s\n", "thumb-path", conf.ThumbPath()) fmt.Printf("%-25s %d\n", "jpeg-size", conf.JpegSize()) diff --git a/internal/commands/resample.go b/internal/commands/resample.go index 4ef9220d6..6e2c3b12c 100644 --- a/internal/commands/resample.go +++ b/internal/commands/resample.go @@ -9,21 +9,21 @@ import ( "github.com/urfave/cli" ) -// ResampleCommand registers the thumbs cli command. +// ResampleCommand registers the resample cli command. var ResampleCommand = cli.Command{ Name: "resample", 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{ cli.BoolFlag{ Name: "force, f", - Usage: "re-create existing thumbnails", + Usage: "replace existing thumbnails", }, }, Action: resampleAction, } -// resampleAction pre-render the thumbnails +// resampleAction pre-caches default thumbnails. func resampleAction(ctx *cli.Context) error { start := time.Now() diff --git a/internal/config/client.go b/internal/config/client.go index fc7894a81..b8b917cea 100644 --- a/internal/config/client.go +++ b/internal/config/client.go @@ -43,7 +43,7 @@ type ClientConfig struct { Lenses entity.Lenses `json:"lenses"` Countries entity.Countries `json:"countries"` People entity.People `json:"people"` - Thumbs ThumbTypes `json:"thumbs"` + Thumbs ThumbSizes `json:"thumbs"` Status string `json:"status"` MapKey string `json:"mapKey"` DownloadToken string `json:"downloadToken"` diff --git a/internal/config/config.go b/internal/config/config.go index 84e99739f..33a511b31 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -72,12 +72,12 @@ func init() { LowMem = TotalMem < MinMem // Init public thumb sizes for use in client apps. - for i := len(thumb.DefaultTypes) - 1; i >= 0; i-- { - size := thumb.DefaultTypes[i] - t := thumb.Types[size] + for i := len(thumb.DefaultSizes) - 1; i >= 0; i-- { + name := thumb.DefaultSizes[i] + t := thumb.Sizes[name] 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() { log.SetLevel(c.LogLevel()) - thumb.Size = c.ThumbSize() + thumb.SizePrecached = c.ThumbSizePrecached() thumb.SizeUncached = c.ThumbSizeUncached() thumb.Filter = c.ThumbFilter() thumb.JpegQuality = c.JpegQuality() diff --git a/internal/config/flags.go b/internal/config/flags.go index db88fcb7a..26f60fe46 100644 --- a/internal/config/flags.go +++ b/internal/config/flags.go @@ -5,7 +5,7 @@ import ( "github.com/urfave/cli" ) -// PhotoPrism command-line parameters and flags. +// GlobalFlags describes global command-line parameters and flags. var GlobalFlags = []cli.Flag{ cli.BoolFlag{ Name: "debug", @@ -387,7 +387,7 @@ var GlobalFlags = []cli.Flag{ }, cli.IntFlag{ Name: "thumb-size, s", - Usage: "static thumbnail size limit in `PIXELS` (720-7680)", + Usage: "pre-cached thumbnail size in `PIXELS` (720-7680)", Value: 2048, EnvVar: "PHOTOPRISM_THUMB_SIZE", }, diff --git a/internal/config/resample.go b/internal/config/resample.go index 35827d6b8..d0ccc906c 100644 --- a/internal/config/resample.go +++ b/internal/config/resample.go @@ -56,8 +56,8 @@ func (c *Config) ThumbUncached() bool { return c.options.ThumbUncached } -// ThumbSize returns the pre-rendered thumbnail size limit in pixels (720-7680). -func (c *Config) ThumbSize() int { +// ThumbSizePrecached returns the pre-cached thumbnail size limit in pixels (720-7680). +func (c *Config) ThumbSizePrecached() int { size := c.options.ThumbSize if size < 720 { @@ -79,8 +79,8 @@ func (c *Config) ThumbSizeUncached() int { limit = 7680 // 8K Ultra HD } - if c.ThumbSize() > limit { - limit = c.ThumbSize() + if c.ThumbSizePrecached() > limit { + limit = c.ThumbSizePrecached() } return limit diff --git a/internal/config/resample_test.go b/internal/config/resample_test.go index 24977cc10..43c810d75 100644 --- a/internal/config/resample_test.go +++ b/internal/config/resample_test.go @@ -50,9 +50,9 @@ func TestConfig_ThumbSizeUncached(t *testing.T) { func TestConfig_ThumbSize(t *testing.T) { c := NewConfig(CliTestContext()) - assert.Equal(t, int(720), c.ThumbSize()) + assert.Equal(t, int(720), c.ThumbSizePrecached()) c.options.ThumbSize = 7681 - assert.Equal(t, int(7680), c.ThumbSize()) + assert.Equal(t, int(7680), c.ThumbSizePrecached()) } func TestConfig_ThumbSizeUncached2(t *testing.T) { diff --git a/internal/config/test.go b/internal/config/test.go index 140818868..83d0e39a6 100644 --- a/internal/config/test.go +++ b/internal/config/test.go @@ -138,7 +138,7 @@ func NewTestConfig() *Config { c.InitTestDb() - thumb.Size = c.ThumbSize() + thumb.SizePrecached = c.ThumbSizePrecached() thumb.SizeUncached = c.ThumbSizeUncached() thumb.Filter = c.ThumbFilter() thumb.JpegQuality = c.JpegQuality() diff --git a/internal/config/thumbs.go b/internal/config/thumbs.go index 403a11f70..c0ddfe0ea 100644 --- a/internal/config/thumbs.go +++ b/internal/config/thumbs.go @@ -1,15 +1,15 @@ package config -// ThumbType represents thumbnail info for use in client apps. -type ThumbType struct { +// ThumbSize represents thumbnail info for use in client apps. +type ThumbSize struct { Size string `json:"size"` Use string `json:"use"` Width int `json:"w"` Height int `json:"h"` } -// ThumbTypes represents a list of thumbnail types. -type ThumbTypes []ThumbType +// ThumbSizes represents a list of thumbnail types. +type ThumbSizes []ThumbSize // Thumbs is a list of thumbnails for use in client apps. -var Thumbs ThumbTypes +var Thumbs ThumbSizes diff --git a/internal/photoprism/import_worker.go b/internal/photoprism/import_worker.go index 86505aa2e..22281ba1a 100644 --- a/internal/photoprism/import_worker.go +++ b/internal/photoprism/import_worker.go @@ -210,7 +210,7 @@ func ImportWorker(jobs <-chan ImportJob) { if res.Indexed() && f.IsJpeg() { 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()) } } diff --git a/internal/photoprism/index_faces.go b/internal/photoprism/index_faces.go index d595d83b2..386e8c869 100644 --- a/internal/photoprism/index_faces.go +++ b/internal/photoprism/index_faces.go @@ -17,7 +17,7 @@ func (ind *Index) detectFaces(jpeg *MediaFile) face.Faces { var thumbSize string // Select best thumbnail depending on configured size. - if Config().ThumbSize() < 1280 { + if Config().ThumbSizePrecached() < 1280 { minSize = 30 thumbSize = "fit_720" } else { diff --git a/internal/photoprism/index_related.go b/internal/photoprism/index_related.go index d4c3abab2..ee206fe7a 100644 --- a/internal/photoprism/index_related.go +++ b/internal/photoprism/index_related.go @@ -45,7 +45,7 @@ func IndexMain(related *RelatedFiles, ind *Index, opt IndexOptions) (result Inde log.Debugf("index: %s created", txt.Quote(jpegFile.BaseName())) 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 return result @@ -59,7 +59,7 @@ func IndexMain(related *RelatedFiles, ind *Index, opt IndexOptions) (result Inde if result.Indexed() && f.IsJpeg() { 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()) } } @@ -126,7 +126,7 @@ func IndexRelated(related RelatedFiles, ind *Index, opt IndexOptions) (result In log.Debugf("index: %s created", txt.Quote(jpegFile.BaseName())) 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 return result @@ -140,7 +140,7 @@ func IndexRelated(related RelatedFiles, ind *Index, opt IndexOptions) (result In if res.Indexed() && f.IsJpeg() { 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()) } } diff --git a/internal/photoprism/mediafile.go b/internal/photoprism/mediafile.go index e723446c8..2fa64ab50 100644 --- a/internal/photoprism/mediafile.go +++ b/internal/photoprism/mediafile.go @@ -888,14 +888,14 @@ func (m *MediaFile) Orientation() int { // Thumbnail returns a thumbnail filename. func (m *MediaFile) Thumbnail(path string, typeName string) (filename string, err error) { - thumbType, ok := thumb.Types[typeName] + size, ok := thumb.Sizes[typeName] if !ok { log.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 { 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) } -// ResampleDefault pre-renders default thumbnails. +// ResampleDefault pre-caches default thumbnails. func (m *MediaFile) ResampleDefault(thumbPath string, force bool) (err error) { count := 0 start := time.Now() @@ -925,11 +925,11 @@ func (m *MediaFile) ResampleDefault(thumbPath string, force bool) (err error) { defer func() { switch count { 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: log.Info(capture.Time(start, fmt.Sprintf("media: one thumbnail created for %s", m.BasePrefix(false)))) 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 sourceImgType string - for _, name := range thumb.DefaultTypes { - thumbType := thumb.Types[name] + for _, name := range thumb.DefaultSizes { + size := thumb.Sizes[name] - if thumbType.OnDemand() { - // Skip, size exceeds limit + if size.Uncached() { + // Skip, exceeds pre-cached size limit. 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) return err @@ -969,14 +969,14 @@ func (m *MediaFile) ResampleDefault(thumbPath string, force bool) (err error) { originalImg = img } - if thumbType.Source != "" { - if thumbType.Source == sourceImgType && sourceImg != nil { - _, err = thumb.Create(sourceImg, fileName, thumbType.Width, thumbType.Height, thumbType.Options...) + if size.Source != "" { + if size.Source == sourceImgType && sourceImg != nil { + _, err = thumb.Create(sourceImg, fileName, size.Width, size.Height, size.Options...) } else { - _, err = thumb.Create(originalImg, fileName, thumbType.Width, thumbType.Height, thumbType.Options...) + _, err = thumb.Create(originalImg, fileName, size.Width, size.Height, size.Options...) } } 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 } diff --git a/internal/photoprism/mediafile_test.go b/internal/photoprism/mediafile_test.go index 3673eb058..a753c21dd 100644 --- a/internal/photoprism/mediafile_test.go +++ b/internal/photoprism/mediafile_test.go @@ -1873,7 +1873,7 @@ func TestMediaFile_RenderDefaultThumbs(t *testing.T) { 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 { t.Fatal(err) diff --git a/internal/thumb/create_test.go b/internal/thumb/create_test.go index 57d75e110..b849d6370 100644 --- a/internal/thumb/create_test.go +++ b/internal/thumb/create_test.go @@ -35,7 +35,7 @@ func TestResampleOptions(t *testing.T) { func TestResample(t *testing.T) { t.Run("tile50 options", func(t *testing.T) { - tile50 := Types["tile_50"] + tile50 := Sizes["tile_50"] src := "testdata/example.jpg" @@ -60,7 +60,7 @@ func TestResample(t *testing.T) { assert.Equal(t, 50, boundsNew.Max.Y) }) t.Run("left_224 options", func(t *testing.T) { - left224 := Types["left_224"] + left224 := Sizes["left_224"] src := "testdata/example.jpg" @@ -85,7 +85,7 @@ func TestResample(t *testing.T) { assert.Equal(t, 224, boundsNew.Max.Y) }) t.Run("right_224 options", func(t *testing.T) { - right224 := Types["right_224"] + right224 := Sizes["right_224"] src := "testdata/example.jpg" @@ -110,7 +110,7 @@ func TestResample(t *testing.T) { assert.Equal(t, 224, boundsNew.Max.Y) }) t.Run("fit_1280 options", func(t *testing.T) { - fit1280 := Types["fit_1280"] + fit1280 := Sizes["fit_1280"] src := "testdata/example.jpg" @@ -137,7 +137,7 @@ func TestResample(t *testing.T) { } func TestSuffix(t *testing.T) { - tile50 := Types["tile_50"] + tile50 := Sizes["tile_50"] result := Suffix(tile50.Width, tile50.Height, tile50.Options...) @@ -146,7 +146,7 @@ func TestSuffix(t *testing.T) { func TestFileName(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...) @@ -158,7 +158,7 @@ func TestFileName(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...) @@ -169,7 +169,7 @@ func TestFileName(t *testing.T) { assert.Equal(t, "testdata/1/2/3/123456789098765432_720x720_fit.jpg", result) }) t.Run("invalid width", func(t *testing.T) { - colorThumb := Types["colors"] + colorThumb := Sizes["colors"] result, err := FileName("123456789098765432", "testdata", -2, colorThumb.Height, colorThumb.Options...) @@ -180,7 +180,7 @@ func TestFileName(t *testing.T) { assert.Empty(t, result) }) t.Run("invalid height", func(t *testing.T) { - colorThumb := Types["colors"] + colorThumb := Sizes["colors"] result, err := FileName("123456789098765432", "testdata", colorThumb.Width, -3, colorThumb.Options...) @@ -191,7 +191,7 @@ func TestFileName(t *testing.T) { assert.Empty(t, result) }) 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...) @@ -202,7 +202,7 @@ func TestFileName(t *testing.T) { assert.Empty(t, result) }) 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...) @@ -216,7 +216,7 @@ func TestFileName(t *testing.T) { func TestFromFile(t *testing.T) { t.Run("colors", func(t *testing.T) { - colorThumb := Types["colors"] + colorThumb := Sizes["colors"] src := "testdata/example.gif" 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) { - colorThumb := Types["colors"] + colorThumb := Sizes["colors"] src := "testdata/example.gif" 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) { - colorThumb := Types["colors"] + colorThumb := Sizes["colors"] src := "testdata/example.xxx" assert.NoFileExists(t, src) @@ -263,7 +263,7 @@ func TestFromFile(t *testing.T) { assert.Error(t, err) }) 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...) @@ -277,7 +277,7 @@ func TestFromFile(t *testing.T) { func TestFromCache(t *testing.T) { t.Run("missing thumb", func(t *testing.T) { - tile50 := Types["tile_50"] + tile50 := Sizes["tile_50"] src := "testdata/example.jpg" assert.FileExists(t, src) @@ -292,7 +292,7 @@ func TestFromCache(t *testing.T) { }) t.Run("missing file", func(t *testing.T) { - tile50 := Types["tile_50"] + tile50 := Sizes["tile_50"] src := "testdata/example.xxx" assert.NoFileExists(t, src) @@ -303,7 +303,7 @@ func TestFromCache(t *testing.T) { assert.Error(t, err) }) t.Run("invalid hash", func(t *testing.T) { - tile50 := Types["tile_50"] + tile50 := Sizes["tile_50"] src := "testdata/example.jpg" assert.FileExists(t, src) @@ -317,7 +317,7 @@ func TestFromCache(t *testing.T) { assert.Empty(t, fileName) }) 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...) @@ -331,7 +331,7 @@ func TestFromCache(t *testing.T) { func TestCreate(t *testing.T) { t.Run("tile_500", func(t *testing.T) { - tile500 := Types["tile_500"] + tile500 := Sizes["tile_500"] src := "testdata/example.jpg" dst := "testdata/example.tile_500.jpg" @@ -368,7 +368,7 @@ func TestCreate(t *testing.T) { assert.Equal(t, 500, boundsNew.Max.Y) }) t.Run("width & height <= 150", func(t *testing.T) { - tile500 := Types["tile_500"] + tile500 := Sizes["tile_500"] src := "testdata/example.jpg" dst := "testdata/example.tile_500.jpg" @@ -405,7 +405,7 @@ func TestCreate(t *testing.T) { assert.Equal(t, 150, boundsNew.Max.Y) }) t.Run("invalid width", func(t *testing.T) { - tile500 := Types["tile_500"] + tile500 := Sizes["tile_500"] src := "testdata/example.jpg" dst := "testdata/example.tile_500.jpg" @@ -433,7 +433,7 @@ func TestCreate(t *testing.T) { t.Log(resized) }) t.Run("invalid height", func(t *testing.T) { - tile500 := Types["tile_500"] + tile500 := Sizes["tile_500"] src := "testdata/example.jpg" dst := "testdata/example.tile_500.jpg" diff --git a/internal/thumb/jpeg_test.go b/internal/thumb/jpeg_test.go index 823006aae..28513e45c 100644 --- a/internal/thumb/jpeg_test.go +++ b/internal/thumb/jpeg_test.go @@ -235,7 +235,6 @@ func TestJpeg(t *testing.T) { } t.Run("foo", func(t *testing.T) { - src := "testdata/example.foo" dst := "testdata/example.foo.jpg" diff --git a/internal/thumb/types.go b/internal/thumb/sizes.go similarity index 82% rename from internal/thumb/types.go rename to internal/thumb/sizes.go index c6e1ffa5e..820421ab3 100644 --- a/internal/thumb/types.go +++ b/internal/thumb/sizes.go @@ -3,16 +3,16 @@ package thumb import "github.com/disintegration/imaging" var ( - Size = 2048 + SizePrecached = 2048 SizeUncached = 7680 - Filter = ResampleLanczos JpegQuality = 95 JpegQualitySmall = 80 + Filter = ResampleLanczos ) func MaxSize() int { - if Size > SizeUncached { - return Size + if SizePrecached > SizeUncached { + return SizePrecached } return SizeUncached @@ -69,7 +69,7 @@ var ResampleMethods = map[ResampleOption]string{ ResampleResize: "resize", } -type Type struct { +type Size struct { Use string `json:"use"` Source string `json:"-"` Width int `json:"w"` @@ -78,9 +78,9 @@ type Type struct { 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_100": {"Maps", "tile_500", 100, 100, false, []ResampleOption{ResampleFillCenter, 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}}, } -var DefaultTypes = []string{ +var DefaultSizes = []string{ "fit_7680", "fit_4096", "fit_2560", @@ -117,29 +117,24 @@ var DefaultTypes = []string{ } // Find returns the largest default thumbnail type for the given size limit. -func Find(limit int) (name string, result Type) { - for _, name = range DefaultTypes { - t := Types[name] +func Find(limit int) (name string, result Size) { + for _, name = range DefaultSizes { + t := Sizes[name] if t.Width <= limit && t.Height <= limit { return name, t } } - return "", Type{} + return "", Size{} } -// ExceedsSize tests if thumbnail type exceeds the cached thumbnails size. -func (t Type) ExceedsSize() bool { - return t.Width > Size || t.Height > Size +// Uncached tests if thumbnail type exceeds the cached thumbnails size limit. +func (s Size) Uncached() bool { + return s.Width > SizePrecached || s.Height > SizePrecached } -// ExceedsSizeUncached tests if thumbnail type is too large and can not be rendered at all. -func (t Type) ExceedsSizeUncached() bool { - return t.Width > MaxSize() || t.Height > MaxSize() -} - -// OnDemand tests if thumbnail type should not be pre-rendered. -func (t Type) OnDemand() bool { - return t.Width > Size || t.Height > Size +// ExceedsLimit tests if thumbnail type is too large, and can not be rendered at all. +func (s Size) ExceedsLimit() bool { + return s.Width > MaxSize() || s.Height > MaxSize() } diff --git a/internal/thumb/types_test.go b/internal/thumb/sizes_test.go similarity index 50% rename from internal/thumb/types_test.go rename to internal/thumb/sizes_test.go index 64464b25b..550f02ee4 100644 --- a/internal/thumb/types_test.go +++ b/internal/thumb/sizes_test.go @@ -6,54 +6,37 @@ import ( "github.com/stretchr/testify/assert" ) -func TestType_ExceedsLimit(t *testing.T) { - Size = 1024 +func TestSize_ExceedsLimit(t *testing.T) { + SizePrecached = 1024 SizeUncached = 2048 - fit4096 := Types["fit_4096"] - assert.True(t, fit4096.ExceedsSizeUncached()) + fit4096 := Sizes["fit_4096"] + assert.True(t, fit4096.ExceedsLimit()) - fit2048 := Types["fit_2048"] - assert.False(t, fit2048.ExceedsSizeUncached()) + fit2048 := Sizes["fit_2048"] + assert.False(t, fit2048.ExceedsLimit()) - tile500 := Types["tile_500"] - assert.False(t, tile500.ExceedsSizeUncached()) + tile500 := Sizes["tile_500"] + assert.False(t, tile500.ExceedsLimit()) - Size = 2048 + SizePrecached = 2048 SizeUncached = 7680 } -func TestType_ExceedsSize(t *testing.T) { - Size = 1024 +func TestSize_Uncached(t *testing.T) { + SizePrecached = 1024 SizeUncached = 2048 - fit4096 := Types["fit_4096"] - assert.True(t, fit4096.ExceedsSize()) + fit4096 := Sizes["fit_4096"] + assert.True(t, fit4096.Uncached()) - fit2048 := Types["fit_2048"] - assert.True(t, fit2048.ExceedsSize()) + fit2048 := Sizes["fit_2048"] + assert.True(t, fit2048.Uncached()) - tile500 := Types["tile_500"] - assert.False(t, tile500.ExceedsSize()) + tile500 := Sizes["tile_500"] + assert.False(t, tile500.Uncached()) - Size = 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 + SizePrecached = 2048 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) { tName, tType := Find(2048) assert.Equal(t, "fit_2048", tName) diff --git a/internal/thumb/thumb_test.go b/internal/thumb/thumb_test.go index 4c46098e1..dfb6792d0 100644 --- a/internal/thumb/thumb_test.go +++ b/internal/thumb/thumb_test.go @@ -18,7 +18,7 @@ func TestMain(m *testing.M) { code := m.Run() // remove temporary test files - os.RemoveAll("testdata/1") + _ = os.RemoveAll("testdata/1") os.Exit(code) } diff --git a/internal/workers/share.go b/internal/workers/share.go index b1a9c6489..c78d461af 100644 --- a/internal/workers/share.go +++ b/internal/workers/share.go @@ -97,14 +97,14 @@ func (worker *Share) Start() (err error) { srcFileName := photoprism.FileName(file.File.FileRoot, file.File.FileName) if a.ShareSize != "" { - thumbType, ok := thumb.Types[a.ShareSize] + size, ok := thumb.Sizes[a.ShareSize] if !ok { log.Errorf("share: invalid size %s", a.ShareSize) 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 { worker.logError(err)