Backend: Add thumb config options and lower defaults #157

Signed-off-by: Michael Mayer <michael@liquidbytes.net>
This commit is contained in:
Michael Mayer 2020-01-13 11:07:09 +01:00
parent 106e9c3e1e
commit e184cad553
28 changed files with 162 additions and 150 deletions

View file

@ -12,11 +12,11 @@ import (
"github.com/photoprism/photoprism/internal/entity"
"github.com/photoprism/photoprism/internal/event"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/internal/form"
"github.com/photoprism/photoprism/internal/query"
"github.com/photoprism/photoprism/pkg/rnd"
"github.com/photoprism/photoprism/internal/thumb"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/pkg/rnd"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
@ -444,13 +444,9 @@ func AlbumThumbnail(router *gin.RouterGroup, conf *config.Config) {
}
// Use original file if thumb size exceeds limit, see https://github.com/photoprism/photoprism/issues/157
if thumbType.Height > thumb.MaxHeight || thumbType.Width > thumb.MaxWidth {
if thumbType.ExceedsLimit() && c.Query("download") == "" {
log.Debugf("album: using original, thumbnail size exceeds limit (width %d, height %d)", thumbType.Width, thumbType.Height)
if c.Query("download") != "" {
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", f.DownloadFileName()))
}
c.File(fileName)
return

View file

@ -5,8 +5,8 @@ import (
"path"
"github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/internal/query"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/gin-gonic/gin"
)

View file

@ -11,8 +11,8 @@ import (
"github.com/gin-gonic/gin"
"github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/internal/event"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/internal/photoprism"
"github.com/photoprism/photoprism/pkg/fs"
)
var imp *photoprism.Import

View file

@ -12,10 +12,10 @@ import (
"github.com/gin-gonic/gin/binding"
"github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/internal/event"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/internal/form"
"github.com/photoprism/photoprism/internal/query"
"github.com/photoprism/photoprism/internal/thumb"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/pkg/txt"
)
@ -164,7 +164,7 @@ func LabelThumbnail(router *gin.RouterGroup, conf *config.Config) {
}
// Use original file if thumb size exceeds limit, see https://github.com/photoprism/photoprism/issues/157
if thumbType.Height > thumb.MaxHeight || thumbType.Width > thumb.MaxWidth {
if thumbType.ExceedsLimit() {
log.Debugf("label: using original, thumbnail size exceeds limit (width %d, height %d)", thumbType.Width, thumbType.Height)
c.File(fileName)

View file

@ -7,8 +7,8 @@ import (
"github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/internal/event"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/internal/query"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/pkg/txt"
"github.com/gin-gonic/gin"

View file

@ -7,9 +7,9 @@ import (
"github.com/gin-gonic/gin"
"github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/internal/query"
"github.com/photoprism/photoprism/internal/thumb"
"github.com/photoprism/photoprism/pkg/fs"
)
// GET /api/v1/thumbnails/:hash/:type
@ -51,13 +51,9 @@ func GetThumbnail(router *gin.RouterGroup, conf *config.Config) {
}
// Use original file if thumb size exceeds limit, see https://github.com/photoprism/photoprism/issues/157
if thumbType.Height > thumb.MaxHeight || thumbType.Width > thumb.MaxWidth {
if thumbType.ExceedsLimit() && c.Query("download") == "" {
log.Debugf("photo: using original, thumbnail size exceeds limit (width %d, height %d)", thumbType.Width, thumbType.Height)
if c.Query("download") != "" {
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", f.DownloadFileName()))
}
c.File(fileName)
return

View file

@ -12,10 +12,10 @@ import (
"github.com/disintegration/imaging"
"github.com/gin-gonic/gin"
"github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/internal/form"
"github.com/photoprism/photoprism/internal/query"
"github.com/photoprism/photoprism/internal/thumb"
"github.com/photoprism/photoprism/pkg/fs"
)
// GET /api/v1/preview

View file

@ -11,9 +11,9 @@ import (
"time"
"github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/internal/form"
"github.com/photoprism/photoprism/internal/query"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/pkg/rnd"
"github.com/photoprism/photoprism/pkg/txt"

View file

@ -76,6 +76,8 @@ func configAction(ctx *cli.Context) error {
fmt.Printf("geocoding-api %s\n", conf.GeoCodingApi())
fmt.Printf("thumb-quality %d\n", conf.ThumbQuality())
fmt.Printf("thumb-size %d\n", conf.ThumbSize())
fmt.Printf("thumb-limit %d\n", conf.ThumbLimit())
fmt.Printf("thumb-algorithm %s\n", conf.ThumbAlgorithm())
return nil
}

View file

@ -3,8 +3,8 @@ package commands
import (
"testing"
"github.com/photoprism/photoprism/pkg/capture"
"github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/pkg/capture"
"github.com/stretchr/testify/assert"
)

View file

@ -10,8 +10,8 @@ import (
"time"
"github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/internal/server"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/sevlyar/go-daemon"
"github.com/urfave/cli"
)

View file

@ -4,8 +4,8 @@ import (
"strings"
"time"
"github.com/photoprism/photoprism/pkg/colors"
"github.com/photoprism/photoprism/internal/entity"
"github.com/photoprism/photoprism/pkg/colors"
"github.com/photoprism/photoprism/pkg/fs"
)

View file

@ -3,6 +3,7 @@ package config
import (
"context"
"runtime"
"strings"
"time"
"github.com/jinzhu/gorm"
@ -55,8 +56,9 @@ func NewConfig(ctx *cli.Context) *Config {
log.SetLevel(c.LogLevel())
thumb.JpegQuality = c.ThumbQuality()
thumb.MaxWidth = c.ThumbSize()
thumb.MaxHeight = c.ThumbSize()
thumb.PreRenderSize = c.ThumbSize()
thumb.MaxRenderSize = c.ThumbLimit()
thumb.Algorithm = c.ThumbAlgorithm()
return c
}
@ -211,10 +213,10 @@ func (c *Config) ThumbQuality() int {
return c.config.ThumbQuality
}
// ThumbSize returns the thumbnail size limit in pixels (720-16384).
// ThumbSize returns the pre-rendered thumbnail size limit in pixels (720-3840).
func (c *Config) ThumbSize() int {
if c.config.ThumbSize > 16384 {
return 16384
if c.config.ThumbSize > 3840 {
return 3840
}
if c.config.ThumbSize < 720 {
@ -224,6 +226,33 @@ func (c *Config) ThumbSize() int {
return c.config.ThumbSize
}
// ThumbLimit returns the on-demand thumbnail size limit in pixels (720-3840).
func (c *Config) ThumbLimit() int {
if c.config.ThumbLimit > 3840 {
return 3840
}
if c.config.ThumbLimit < 720 {
return 720
}
return c.config.ThumbLimit
}
// ThumbAlgorithm returns the thumbnail algorithm name (lanczos, cubic or linear).
func (c *Config) ThumbAlgorithm() thumb.ResampleAlgorithm {
switch strings.ToLower(c.config.ThumbAlgorithm) {
case "lanczos":
return thumb.ResampleLanczos
case "cubic":
return thumb.ResampleCubic
case "linear":
return thumb.ResampleLinear
default:
return thumb.ResampleLanczos
}
}
// GeoCodingApi returns the preferred geo coding api (none, osm or places).
func (c *Config) GeoCodingApi() string {
switch c.config.GeoCodingApi {

View file

@ -233,13 +233,25 @@ var GlobalFlags = []cli.Flag{
cli.IntFlag{
Name: "thumb-quality, q",
Usage: "jpeg quality of thumbnails (25-100)",
Value: 95,
Value: 90,
EnvVar: "PHOTOPRISM_THUMB_QUALITY",
},
cli.IntFlag{
Name: "thumb-size, s",
Usage: "max thumbnail size in pixels (720-16384)",
Value: 8192,
Usage: "pre-rendered thumbnail size limit in pixels (720-3840)",
Value: 2048,
EnvVar: "PHOTOPRISM_THUMB_SIZE",
},
cli.IntFlag{
Name: "thumb-limit, x",
Usage: "on-demand thumbnail size limit in pixels (720-3840)",
Value: 3840,
EnvVar: "PHOTOPRISM_THUMB_LIMIT",
},
cli.StringFlag{
Name: "thumb-algorithm, a",
Usage: "thumbnail algorithm (lanczos, cubic or linear)",
Value: "lanczos",
EnvVar: "PHOTOPRISM_THUMB_ALGORITHM",
},
}

View file

@ -74,6 +74,8 @@ type Params struct {
GeoCodingApi string `yaml:"geocoding-api" flag:"geocoding-api"`
ThumbQuality int `yaml:"thumb-quality" flag:"thumb-quality"`
ThumbSize int `yaml:"thumb-size" flag:"thumb-size"`
ThumbLimit int `yaml:"thumb-limit" flag:"thumb-limit"`
ThumbAlgorithm string `yaml:"thumb-algorithm" flag:"thumb-algorithm"`
}
// NewParams() creates a new configuration entity by using two methods:

View file

@ -10,8 +10,8 @@ import (
_ "github.com/jinzhu/gorm/dialects/mysql"
_ "github.com/jinzhu/gorm/dialects/sqlite"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/internal/thumb"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
)
@ -95,8 +95,9 @@ func NewTestConfig() *Config {
c.ImportSQL(c.ExamplesPath() + "/fixtures.sql")
thumb.JpegQuality = c.ThumbQuality()
thumb.MaxWidth = c.ThumbSize()
thumb.MaxHeight = c.ThumbSize()
thumb.PreRenderSize = c.ThumbSize()
thumb.MaxRenderSize = c.ThumbLimit()
thumb.Algorithm = c.ThumbAlgorithm()
return c
}

View file

@ -5,6 +5,7 @@ import (
"testing"
"github.com/photoprism/photoprism/internal/maps/osm"
"github.com/photoprism/photoprism/internal/maps/places"
"github.com/photoprism/photoprism/pkg/s2"
"github.com/stretchr/testify/assert"
)
@ -49,17 +50,15 @@ func TestLocation_Assign(t *testing.T) {
lng := 13.40953
id := s2.Token(lat, lng)
o, err := osm.FindLocation(id)
o, err := places.FindLocation(id)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, "Fernsehturm Berlin", o.LocName)
assert.Equal(t, "10178", o.Address.Postcode)
assert.Equal(t, "Berlin", o.Address.State)
assert.Equal(t, "de", o.Address.CountryCode)
assert.Equal(t, "Germany", o.Address.Country)
assert.Equal(t, "Fernsehturm Berlin", o.Name())
assert.Equal(t, "Berlin", o.State())
assert.Equal(t, "de", o.CountryCode())
var l Location
@ -157,72 +156,12 @@ func TestLocation_Assign(t *testing.T) {
assert.Equal(t, "Berlin, Germany", l.LocLabel)
})
t.Run("PinkBeach", func(t *testing.T) {
lat := 35.26967222222222
lng := 23.53711666666667
id := s2.Token(lat, lng)
o, err := osm.FindLocation(id)
if err != nil {
t.Fatal(err)
}
assert.False(t, o.Cached)
assert.Equal(t, "Pink Beach", o.LocName)
assert.Equal(t, "", o.Address.Postcode)
assert.Equal(t, "Crete", o.Address.State)
assert.Equal(t, "gr", o.Address.CountryCode)
assert.Equal(t, "Greece", o.Address.Country)
var l Location
if err := l.Assign(o); err != nil {
t.Fatal(err)
}
assert.True(t, strings.HasPrefix(l.ID, "149ce785"))
assert.Equal(t, "Pink Beach", l.LocName)
assert.Equal(t, "Chrisoskalitissa, Crete, Greece", l.LocLabel)
})
t.Run("NewJersey", func(t *testing.T) {
lat := 40.74290
lng := -74.04862
id := s2.Token(lat, lng)
o, err := osm.FindLocation(id)
if err != nil {
t.Fatal(err)
}
assert.False(t, o.Cached)
assert.Equal(t, "", o.LocName)
assert.Equal(t, "07307", o.Address.Postcode)
assert.Equal(t, "New Jersey", o.Address.State)
assert.Equal(t, "us", o.Address.CountryCode)
assert.Equal(t, "United States of America", o.Address.Country)
var l Location
if err := l.Assign(o); err != nil {
t.Fatal(err)
}
assert.True(t, strings.HasPrefix(l.ID, "89c25741"))
assert.Equal(t, "", l.LocName)
assert.Equal(t, "Jersey City, New Jersey, USA", l.LocLabel)
})
t.Run("SouthAfrica", func(t *testing.T) {
lat := -31.976301666666668
lng := 29.148046666666666
id := s2.Token(lat, lng)
o, err := osm.FindLocation(id)
o, err := places.FindLocation(id)
if err != nil {
t.Fatal(err)
@ -230,11 +169,9 @@ func TestLocation_Assign(t *testing.T) {
assert.False(t, o.Cached)
assert.Equal(t, "R411", o.LocName)
assert.Equal(t, "", o.Address.Postcode)
assert.Equal(t, "Eastern Cape", o.Address.State)
assert.Equal(t, "za", o.Address.CountryCode)
assert.Equal(t, "South Africa", o.Address.Country)
assert.Equal(t, "", o.Name())
assert.Equal(t, "Eastern Cape", o.State())
assert.Equal(t, "za", o.CountryCode())
var l Location
@ -243,29 +180,34 @@ func TestLocation_Assign(t *testing.T) {
}
assert.True(t, strings.HasPrefix(l.ID, "1e5e4205"))
assert.Equal(t, "R411", l.LocName)
assert.Equal(t, "", l.LocName)
assert.Equal(t, "Eastern Cape, South Africa", l.LocLabel)
})
t.Run("Unknown", func(t *testing.T) {
t.Run("ocean", func(t *testing.T) {
lat := -21.976301666666668
lng := 49.148046666666666
id := s2.Token(lat, lng)
log.Printf("ID: %s", id)
o, err := osm.FindLocation(id)
o, err := places.FindLocation(id)
log.Printf("Output: %+v", o)
if err == nil {
t.Fatal("expected error")
if err != nil {
t.Fatal(err)
}
assert.False(t, o.Cached)
var l Location
assert.Error(t, l.Assign(o))
assert.Equal(t, "unknown", l.LocCategory)
if err := l.Assign(o); err != nil {
t.Fatal(err)
}
assert.Equal(t, "Indian Ocean", l.LocName)
assert.Equal(t, "", l.LocCategory)
assert.Equal(t, "", l.LocCity)
// TODO: Should be zz for international waters, fixed in places server
// assert.Equal(t, "", l.LocCountry)
})
}

View file

@ -6,8 +6,8 @@ import (
"strings"
"testing"
"github.com/photoprism/photoprism/pkg/colors"
"github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/pkg/colors"
"github.com/stretchr/testify/assert"
)

View file

@ -12,8 +12,8 @@ import (
"github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/internal/entity"
"github.com/photoprism/photoprism/internal/event"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/internal/mutex"
"github.com/photoprism/photoprism/pkg/fs"
)
// Import represents an importer that can copy/move MediaFiles to the originals directory.

View file

@ -73,7 +73,7 @@ func importWorker(jobs <-chan ImportJob) {
if jpg, err := importedMainFile.Jpeg(); err != nil {
log.Error(err)
} else {
if err := jpg.CreateDefaultThumbnails(imp.conf.ThumbnailsPath(), false); err != nil {
if err := jpg.RenderDefaultThumbnails(imp.conf.ThumbnailsPath(), false); err != nil {
log.Errorf("import: could not create default thumbnails (%s)", err)
}
}

View file

@ -14,11 +14,11 @@ import (
"github.com/disintegration/imaging"
"github.com/djherbis/times"
"github.com/photoprism/photoprism/pkg/capture"
"github.com/photoprism/photoprism/internal/entity"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/internal/meta"
"github.com/photoprism/photoprism/internal/thumb"
"github.com/photoprism/photoprism/pkg/capture"
"github.com/photoprism/photoprism/pkg/fs"
)
// MediaFile represents a single photo, video or sidecar file.
@ -714,7 +714,7 @@ func (m *MediaFile) Resample(path string, typeName string) (img image.Image, err
return imaging.Open(filename, imaging.AutoOrientation(true))
}
func (m *MediaFile) CreateDefaultThumbnails(thumbPath string, force bool) (err error) {
func (m *MediaFile) RenderDefaultThumbnails(thumbPath string, force bool) (err error) {
defer log.Debug(capture.Time(time.Now(), fmt.Sprintf("thumbs: created for \"%s\"", m.Filename())))
hash := m.Hash()
@ -732,7 +732,7 @@ func (m *MediaFile) CreateDefaultThumbnails(thumbPath string, force bool) (err e
for _, name := range thumb.DefaultTypes {
thumbType := thumb.Types[name]
if thumbType.Height > thumb.MaxHeight || thumbType.Width > thumb.MaxWidth {
if thumbType.SkipPreRender() {
// Skip, size exceeds limit
continue
}

View file

@ -4,8 +4,8 @@ import (
"os"
"testing"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/internal/thumb"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/internal/config"
"github.com/stretchr/testify/assert"
@ -958,7 +958,7 @@ func TestMediaFile_CreateDefaultThumbnails(t *testing.T) {
m, err := NewMediaFile(conf.ExamplesPath() + "/elephants.jpg")
assert.Nil(t, err)
err = m.CreateDefaultThumbnails(thumbsPath, true)
err = m.RenderDefaultThumbnails(thumbsPath, true)
assert.Empty(t, err)
@ -968,7 +968,7 @@ func TestMediaFile_CreateDefaultThumbnails(t *testing.T) {
assert.FileExists(t, thumbFilename)
err = m.CreateDefaultThumbnails(thumbsPath, false)
err = m.RenderDefaultThumbnails(thumbsPath, false)
assert.Empty(t, err)
}

View file

@ -8,7 +8,7 @@ type ThumbnailsJob struct {
func thumbnailsWorker(jobs <-chan ThumbnailsJob) {
for job := range jobs {
if err := job.mediaFile.CreateDefaultThumbnails(job.path, job.force); err != nil {
if err := job.mediaFile.RenderDefaultThumbnails(job.path, job.force); err != nil {
log.Errorf("thumbs: %s", err)
}
}

View file

@ -5,9 +5,9 @@ import (
"strings"
"time"
"github.com/photoprism/photoprism/pkg/capture"
"github.com/photoprism/photoprism/internal/entity"
"github.com/photoprism/photoprism/internal/form"
"github.com/photoprism/photoprism/pkg/capture"
)
// AlbumResult contains found albums

View file

@ -6,9 +6,9 @@ import (
"time"
"github.com/gosimple/slug"
"github.com/photoprism/photoprism/pkg/capture"
"github.com/photoprism/photoprism/internal/entity"
"github.com/photoprism/photoprism/internal/form"
"github.com/photoprism/photoprism/pkg/capture"
)
// LabelResult contains found labels

View file

@ -6,9 +6,9 @@ import (
"time"
"github.com/gosimple/slug"
"github.com/photoprism/photoprism/pkg/capture"
"github.com/photoprism/photoprism/internal/entity"
"github.com/photoprism/photoprism/internal/form"
"github.com/photoprism/photoprism/pkg/capture"
)
// PhotoResult contains found photos and their main file plus other meta data.

View file

@ -25,8 +25,8 @@ func ResampleOptions(opts ...ResampleOption) (method ResampleOption, filter imag
format = fs.TypePng
case ResampleNearestNeighbor:
filter = imaging.NearestNeighbor
case ResampleLanczos:
filter = imaging.Lanczos
case ResampleDefault:
filter = Algorithm.Filter()
case ResampleFillTopLeft:
method = ResampleFillTopLeft
case ResampleFillCenter:
@ -72,11 +72,11 @@ func Postfix(width, height int, opts ...ResampleOption) (result string) {
}
func Filename(hash string, thumbPath string, width, height int, opts ...ResampleOption) (filename string, err error) {
if width < 0 || width > MaxWidth {
if width < 0 || width > MaxRenderSize {
return "", fmt.Errorf("thumbs: width exceeds limit (%d)", width)
}
if height < 0 || height > MaxHeight {
if height < 0 || height > MaxRenderSize {
return "", fmt.Errorf("thumbs: height exceeds limit (%d)", height)
}
@ -135,11 +135,11 @@ func FromFile(imageFilename string, hash string, thumbPath string, width, height
}
func Create(img image.Image, fileName string, width, height int, opts ...ResampleOption) (result image.Image, err error) {
if width < 0 || width > MaxWidth {
if width < 0 || width > MaxRenderSize {
return img, fmt.Errorf("thumbs: width has an invalid value (%d)", width)
}
if height < 0 || height > MaxHeight {
if height < 0 || height > MaxRenderSize {
return img, fmt.Errorf("thumbs: height has an invalid value (%d)", height)
}

View file

@ -1,12 +1,36 @@
package thumb
import "github.com/disintegration/imaging"
var (
MaxWidth = 8192
MaxHeight = 8192
PreRenderSize = 3840
MaxRenderSize = 3840
JpegQuality = 95
JpegQualitySmall = 80
Algorithm = ResampleLanczos
)
const (
ResampleLanczos ResampleAlgorithm = "lanczos"
ResampleCubic = "cubic"
ResampleLinear = "linear"
)
type ResampleAlgorithm string
func (a ResampleAlgorithm) Filter() imaging.ResampleFilter {
switch a {
case ResampleLanczos:
return imaging.Lanczos
case ResampleCubic:
return imaging.CatmullRom
case ResampleLinear:
return imaging.Linear
default:
return imaging.Lanczos
}
}
const (
ResampleFillCenter ResampleOption = iota
ResampleFillTopLeft
@ -14,7 +38,7 @@ const (
ResampleFit
ResampleResize
ResampleNearestNeighbor
ResampleLanczos
ResampleDefault
ResamplePng
)
@ -37,21 +61,29 @@ type Type struct {
}
var Types = map[string]Type{
"tile_50": {"tile_500", 50, 50, false, []ResampleOption{ResampleFillCenter, ResampleLanczos}},
"tile_100": {"tile_500", 100, 100, false, []ResampleOption{ResampleFillCenter, ResampleLanczos}},
"tile_224": {"tile_500", 224, 224, false, []ResampleOption{ResampleFillCenter, ResampleLanczos}},
"tile_500": {"", 500, 500, false, []ResampleOption{ResampleFillCenter, ResampleLanczos}},
"tile_50": {"tile_500", 50, 50, false, []ResampleOption{ResampleFillCenter, ResampleDefault}},
"tile_100": {"tile_500", 100, 100, false, []ResampleOption{ResampleFillCenter, ResampleDefault}},
"tile_224": {"tile_500", 224, 224, false, []ResampleOption{ResampleFillCenter, ResampleDefault}},
"tile_500": {"", 500, 500, false, []ResampleOption{ResampleFillCenter, ResampleDefault}},
"colors": {"fit_720", 3, 3, false, []ResampleOption{ResampleResize, ResampleNearestNeighbor, ResamplePng}},
"left_224": {"fit_720", 224, 224, false, []ResampleOption{ResampleFillTopLeft, ResampleLanczos}},
"right_224": {"fit_720", 224, 224, false, []ResampleOption{ResampleFillBottomRight, ResampleLanczos}},
"fit_720": {"", 720, 720, true, []ResampleOption{ResampleFit, ResampleLanczos}},
"fit_1280": {"fit_2048", 1280, 1024, true, []ResampleOption{ResampleFit, ResampleLanczos}},
"fit_1920": {"fit_2048", 1920, 1200, true, []ResampleOption{ResampleFit, ResampleLanczos}},
"fit_2048": {"", 2048, 2048, true, []ResampleOption{ResampleFit, ResampleLanczos}},
"fit_2560": {"", 2560, 1600, true, []ResampleOption{ResampleFit, ResampleLanczos}},
"fit_3840": {"", 3840, 2400, true, []ResampleOption{ResampleFit, ResampleLanczos}},
"left_224": {"fit_720", 224, 224, false, []ResampleOption{ResampleFillTopLeft, ResampleDefault}},
"right_224": {"fit_720", 224, 224, false, []ResampleOption{ResampleFillBottomRight, ResampleDefault}},
"fit_720": {"", 720, 720, true, []ResampleOption{ResampleFit, ResampleDefault}},
"fit_1280": {"fit_2048", 1280, 1024, true, []ResampleOption{ResampleFit, ResampleDefault}},
"fit_1920": {"fit_2048", 1920, 1200, true, []ResampleOption{ResampleFit, ResampleDefault}},
"fit_2048": {"", 2048, 2048, true, []ResampleOption{ResampleFit, ResampleDefault}},
"fit_2560": {"", 2560, 1600, true, []ResampleOption{ResampleFit, ResampleDefault}},
"fit_3840": {"", 3840, 2400, true, []ResampleOption{ResampleFit, ResampleDefault}},
}
var DefaultTypes = []string{
"fit_3840", "fit_2560", "fit_2048", "fit_1920", "fit_1280", "fit_720", "right_224", "left_224", "colors", "tile_500", "tile_224", "tile_100", "tile_50",
}
func (t Type) ExceedsLimit() bool {
return t.Width > MaxRenderSize || t.Height > MaxRenderSize
}
func (t Type) SkipPreRender() bool {
return t.Width > PreRenderSize || t.Height > PreRenderSize
}