1
Fork 0

Changed downsampling method to custom type.

This commit is contained in:
PJ-Watson 2022-08-09 06:09:55 +01:00
parent 866a3b4c1d
commit 3e780dbe48
12 changed files with 146 additions and 51 deletions

View File

@ -170,7 +170,7 @@ type ComplexityRoot struct {
SetFaceGroupLabel func(childComplexity int, faceGroupID int, label *string) int
SetPeriodicScanInterval func(childComplexity int, interval int) int
SetScannerConcurrentWorkers func(childComplexity int, workers int) int
SetThumbnailDownsampleMethod func(childComplexity int, method int) int
SetThumbnailDownsampleMethod func(childComplexity int, method models.ThumbnailFilter) int
ShareAlbum func(childComplexity int, albumID int, expire *time.Time, password *string) int
ShareMedia func(childComplexity int, mediaID int, expire *time.Time, password *string) int
UpdateUser func(childComplexity int, id int, username *string, password *string, admin *bool) int
@ -328,7 +328,7 @@ type MutationResolver interface {
UserRemoveRootAlbum(ctx context.Context, userID int, albumID int) (*models.Album, error)
SetPeriodicScanInterval(ctx context.Context, interval int) (int, error)
SetScannerConcurrentWorkers(ctx context.Context, workers int) (int, error)
SetThumbnailDownsampleMethod(ctx context.Context, method int) (int, error)
SetThumbnailDownsampleMethod(ctx context.Context, method models.ThumbnailFilter) (models.ThumbnailFilter, error)
ChangeUserPreferences(ctx context.Context, language *string) (*models.UserPreferences, error)
ResetAlbumCover(ctx context.Context, albumID int) (*models.Album, error)
SetAlbumCover(ctx context.Context, coverID int) (*models.Album, error)
@ -1070,7 +1070,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return 0, false
}
return e.complexity.Mutation.SetThumbnailDownsampleMethod(childComplexity, args["method"].(int)), true
return e.complexity.Mutation.SetThumbnailDownsampleMethod(childComplexity, args["method"].(models.ThumbnailFilter)), true
case "Mutation.shareAlbum":
if e.complexity.Mutation.ShareAlbum == nil {
@ -2181,10 +2181,10 @@ func (ec *executionContext) field_Mutation_setScannerConcurrentWorkers_args(ctx
func (ec *executionContext) field_Mutation_setThumbnailDownsampleMethod_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
var err error
args := map[string]interface{}{}
var arg0 int
var arg0 models.ThumbnailFilter
if tmp, ok := rawArgs["method"]; ok {
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("method"))
arg0, err = ec.unmarshalNInt2int(ctx, tmp)
arg0, err = ec.unmarshalNThumbnailFilter2githubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐThumbnailFilter(ctx, tmp)
if err != nil {
return nil, err
}
@ -7210,7 +7210,7 @@ func (ec *executionContext) _Mutation_setThumbnailDownsampleMethod(ctx context.C
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
directive0 := func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return ec.resolvers.Mutation().SetThumbnailDownsampleMethod(rctx, fc.Args["method"].(int))
return ec.resolvers.Mutation().SetThumbnailDownsampleMethod(rctx, fc.Args["method"].(models.ThumbnailFilter))
}
directive1 := func(ctx context.Context) (interface{}, error) {
if ec.directives.IsAdmin == nil {
@ -7226,10 +7226,10 @@ func (ec *executionContext) _Mutation_setThumbnailDownsampleMethod(ctx context.C
if tmp == nil {
return nil, nil
}
if data, ok := tmp.(int); ok {
if data, ok := tmp.(models.ThumbnailFilter); ok {
return data, nil
}
return nil, fmt.Errorf(`unexpected type %T from directive, should be int`, tmp)
return nil, fmt.Errorf(`unexpected type %T from directive, should be github.com/photoview/photoview/api/graphql/models.ThumbnailFilter`, tmp)
})
if err != nil {
ec.Error(ctx, err)
@ -7241,9 +7241,9 @@ func (ec *executionContext) _Mutation_setThumbnailDownsampleMethod(ctx context.C
}
return graphql.Null
}
res := resTmp.(int)
res := resTmp.(models.ThumbnailFilter)
fc.Result = res
return ec.marshalNInt2int(ctx, field.Selections, res)
return ec.marshalNThumbnailFilter2githubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐThumbnailFilter(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_Mutation_setThumbnailDownsampleMethod(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
@ -7253,7 +7253,7 @@ func (ec *executionContext) fieldContext_Mutation_setThumbnailDownsampleMethod(c
IsMethod: true,
IsResolver: true,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type Int does not have child fields")
return nil, errors.New("field of type ThumbnailFilter does not have child fields")
},
}
defer func() {
@ -10729,10 +10729,10 @@ func (ec *executionContext) _SiteInfo_thumbnailMethod(ctx context.Context, field
if tmp == nil {
return nil, nil
}
if data, ok := tmp.(int); ok {
if data, ok := tmp.(models.ThumbnailFilter); ok {
return data, nil
}
return nil, fmt.Errorf(`unexpected type %T from directive, should be int`, tmp)
return nil, fmt.Errorf(`unexpected type %T from directive, should be github.com/photoview/photoview/api/graphql/models.ThumbnailFilter`, tmp)
})
if err != nil {
ec.Error(ctx, err)
@ -10744,9 +10744,9 @@ func (ec *executionContext) _SiteInfo_thumbnailMethod(ctx context.Context, field
}
return graphql.Null
}
res := resTmp.(int)
res := resTmp.(models.ThumbnailFilter)
fc.Result = res
return ec.marshalNInt2int(ctx, field.Selections, res)
return ec.marshalNThumbnailFilter2githubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐThumbnailFilter(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_SiteInfo_thumbnailMethod(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
@ -10756,7 +10756,7 @@ func (ec *executionContext) fieldContext_SiteInfo_thumbnailMethod(ctx context.Co
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type Int does not have child fields")
return nil, errors.New("field of type ThumbnailFilter does not have child fields")
},
}
return fc, nil
@ -16802,6 +16802,16 @@ func (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.S
return res
}
func (ec *executionContext) unmarshalNThumbnailFilter2githubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐThumbnailFilter(ctx context.Context, v interface{}) (models.ThumbnailFilter, error) {
var res models.ThumbnailFilter
err := res.UnmarshalGQL(v)
return res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) marshalNThumbnailFilter2githubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐThumbnailFilter(ctx context.Context, sel ast.SelectionSet, v models.ThumbnailFilter) graphql.Marshaler {
return v
}
func (ec *executionContext) unmarshalNTime2timeᚐTime(ctx context.Context, v interface{}) (time.Time, error) {
res, err := graphql.UnmarshalTime(v)
return res, graphql.ErrorOnPath(ctx, err)

View File

@ -251,3 +251,53 @@ func (e *OrderDirection) UnmarshalGQL(v interface{}) error {
func (e OrderDirection) MarshalGQL(w io.Writer) {
fmt.Fprint(w, strconv.Quote(e.String()))
}
// Supported downsampling filters for thumbnail generation
type ThumbnailFilter string
const (
ThumbnailFilterNearestNeighbor ThumbnailFilter = "NearestNeighbor"
ThumbnailFilterBox ThumbnailFilter = "Box"
ThumbnailFilterLinear ThumbnailFilter = "Linear"
ThumbnailFilterMitchellNetravali ThumbnailFilter = "MitchellNetravali"
ThumbnailFilterCatmullRom ThumbnailFilter = "CatmullRom"
ThumbnailFilterLanczos ThumbnailFilter = "Lanczos"
)
var AllThumbnailFilter = []ThumbnailFilter{
ThumbnailFilterNearestNeighbor,
ThumbnailFilterBox,
ThumbnailFilterLinear,
ThumbnailFilterMitchellNetravali,
ThumbnailFilterCatmullRom,
ThumbnailFilterLanczos,
}
func (e ThumbnailFilter) IsValid() bool {
switch e {
case ThumbnailFilterNearestNeighbor, ThumbnailFilterBox, ThumbnailFilterLinear, ThumbnailFilterMitchellNetravali, ThumbnailFilterCatmullRom, ThumbnailFilterLanczos:
return true
}
return false
}
func (e ThumbnailFilter) String() string {
return string(e)
}
func (e *ThumbnailFilter) UnmarshalGQL(v interface{}) error {
str, ok := v.(string)
if !ok {
return fmt.Errorf("enums must be strings")
}
*e = ThumbnailFilter(str)
if !e.IsValid() {
return fmt.Errorf("%s is not a valid ThumbnailFilter", str)
}
return nil
}
func (e ThumbnailFilter) MarshalGQL(w io.Writer) {
fmt.Fprint(w, strconv.Quote(e.String()))
}

View File

@ -10,7 +10,7 @@ type SiteInfo struct {
InitialSetup bool `gorm:"not null"`
PeriodicScanInterval int `gorm:"not null"`
ConcurrentWorkers int `gorm:"not null"`
ThumbnailMethod int `gorm:"not null"`
ThumbnailMethod ThumbnailFilter `gorm:"not null"`
}
func (SiteInfo) TableName() string {
@ -27,7 +27,7 @@ func DefaultSiteInfo(db *gorm.DB) SiteInfo {
InitialSetup: true,
PeriodicScanInterval: 0,
ConcurrentWorkers: defaultConcurrentWorkers,
ThumbnailMethod: 0,
ThumbnailMethod: ThumbnailFilterNearestNeighbor,
}
}

View File

@ -22,7 +22,7 @@ func TestSiteInfo(t *testing.T) {
site_info.InitialSetup = false
site_info.PeriodicScanInterval = 360
site_info.ConcurrentWorkers = 10
site_info.ThumbnailMethod = 5
site_info.ThumbnailMethod = ThumbnailFilterLanczos
if !assert.NoError(t, db.Session(&gorm.Session{AllowGlobalUpdate: true}).Save(&site_info).Error) {
return
@ -37,7 +37,7 @@ func TestSiteInfo(t *testing.T) {
InitialSetup: false,
PeriodicScanInterval: 360,
ConcurrentWorkers: 10,
ThumbnailMethod: 5,
ThumbnailMethod: ThumbnailFilterLanczos,
}, *site_info)
}

View File

@ -2,29 +2,35 @@ package resolvers
import (
"context"
"github.com/photoview/photoview/api/graphql/models"
"github.com/pkg/errors"
// "github.com/pkg/errors"
"gorm.io/gorm"
)
func (r *mutationResolver) SetThumbnailDownsampleMethod(ctx context.Context, method int) (int, error) {
func (r *mutationResolver) SetThumbnailDownsampleMethod(ctx context.Context, method models.ThumbnailFilter) (models.ThumbnailFilter, error) {
db := r.DB(ctx)
if method > 5 {
return 0, errors.New("The requested filter is unsupported, defaulting to nearest neighbor")
}
// if method > 5 {
// return 0, errors.New("The requested filter is unsupported, defaulting to nearest neighbor")
// }
if err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).Model(&models.SiteInfo{}).Update("thumbnail_method", method).Error; err != nil {
return 0, err
return models.ThumbnailFilterNearestNeighbor, err
}
var siteInfo models.SiteInfo
if err := db.First(&siteInfo).Error; err != nil {
return 0, err
return models.ThumbnailFilterNearestNeighbor, err
}
// scanner_queue.ChangeScannerConcurrentWorkers(siteInfo.ConcurrentWorkers)
return siteInfo.ThumbnailMethod, nil
// var langTrans *models.LanguageTranslation = nil
// if language != nil {
// lng := models.LanguageTranslation(*language)
// langTrans = &lng
// }
}

View File

@ -164,7 +164,7 @@ type Mutation {
setScannerConcurrentWorkers(workers: Int!): Int! @isAdmin
"Set the filter to be used when generating thumbnails"
setThumbnailDownsampleMethod(method: Int!): Int! @isAdmin
setThumbnailDownsampleMethod(method: ThumbnailFilter!): ThumbnailFilter! @isAdmin
"Change user preferences for the logged in user"
changeUserPreferences(language: String): UserPreferences! @isAuthorized
@ -250,6 +250,16 @@ type ShareToken {
media: Media
}
"Supported downsampling filters for thumbnail generation"
enum ThumbnailFilter {
NearestNeighbor,
Box,
Linear,
MitchellNetravali,
CatmullRom,
Lanczos,
}
"General information about the site"
type SiteInfo {
"Whether or not the initial setup wizard should be shown"
@ -261,7 +271,7 @@ type SiteInfo {
"How many max concurrent scanner jobs that should run at once"
concurrentWorkers: Int! @isAdmin
"The filter to use when generating thumbnails"
thumbnailMethod: Int! @isAdmin
thumbnailMethod: ThumbnailFilter! @isAdmin
}
type User {

View File

@ -21,13 +21,13 @@ import (
"gorm.io/gorm"
)
var thumbFilter = map[int]imaging.ResampleFilter{
0: imaging.NearestNeighbor,
1: imaging.Box,
2: imaging.Linear,
3: imaging.MitchellNetravali,
4: imaging.CatmullRom,
5: imaging.Lanczos,
var thumbFilter = map[models.ThumbnailFilter]imaging.ResampleFilter{
models.ThumbnailFilterNearestNeighbor: imaging.NearestNeighbor,
models.ThumbnailFilterBox: imaging.Box,
models.ThumbnailFilterLinear: imaging.Linear,
models.ThumbnailFilterMitchellNetravali: imaging.MitchellNetravali,
models.ThumbnailFilterCatmullRom: imaging.CatmullRom,
models.ThumbnailFilterLanczos: imaging.Lanczos,
}
func EncodeThumbnail(db *gorm.DB, inputPath string, outputPath string) (*media_utils.PhotoDimensions, error) {

View File

@ -3,6 +3,8 @@ import { MockedProvider } from '@apollo/client/testing'
import { render, screen } from '@testing-library/react'
import { ThumbnailFilter } from '../../__generated__/globalTypes'
import ThumbnailPreferences, {
THUMBNAIL_METHOD_QUERY,
SET_THUMBNAIL_METHOD_MUTATION,
@ -16,7 +18,7 @@ test('load ThumbnailPreferences', () => {
},
result: {
data: {
siteInfo: { method: 0 },
siteInfo: { method: ThumbnailFilter.NearestNeighbor },
},
},
},
@ -24,7 +26,7 @@ test('load ThumbnailPreferences', () => {
request: {
query: SET_THUMBNAIL_METHOD_MUTATION,
variables: {
method: '5',
method: ThumbnailFilter.Lanczos,
},
},
result: {

View File

@ -7,6 +7,7 @@ import {
InputLabelTitle,
} from './SettingsPage'
import { useTranslation } from 'react-i18next'
import { ThumbnailFilter } from '../../__generated__/globalTypes'
import { thumbnailMethodQuery } from './__generated__/thumbnailMethodQuery'
import {
setThumbnailMethodMutation,
@ -24,7 +25,7 @@ export const THUMBNAIL_METHOD_QUERY = gql`
`
export const SET_THUMBNAIL_METHOD_MUTATION = gql`
mutation setThumbnailMethodMutation($method: Int!) {
mutation setThumbnailMethodMutation($method: ThumbnailFilter!) {
setThumbnailDownsampleMethod(method: $method)
}
`
@ -67,33 +68,33 @@ const ThumbnailPreferences = () => {
'settings.thumbnails.method.filter.nearest_neighbor',
'Nearest Neighbor (default)'
),
value: 0,
value: ThumbnailFilter.NearestNeighbor,
},
{
label: t('settings.thumbnails.method.filter.box', 'Box'),
value: 1,
value: ThumbnailFilter.Box,
},
{
label: t('settings.thumbnails.method.filter.linear', 'Linear'),
value: 2,
value: ThumbnailFilter.Linear,
},
{
label: t(
'settings.thumbnails.method.filter.mitchell_netravali',
'Mitchell-Netravali'
),
value: 3,
value: ThumbnailFilter.MitchellNetravali,
},
{
label: t('settings.thumbnails.method.filter.catmull_rom', 'Catmull-Rom'),
value: 4,
value: ThumbnailFilter.CatmullRom,
},
{
label: t(
'settings.thumbnails.method.filter.Lanczos',
'Lanczos (highest quality)'
),
value: 5,
value: ThumbnailFilter.Lanczos,
},
]

View File

@ -3,6 +3,8 @@
// @generated
// This file was automatically generated and should not be edited.
import { ThumbnailFilter } from './../../../__generated__/globalTypes'
// ====================================================
// GraphQL mutation operation: setThumbnailMethodMutation
// ====================================================
@ -11,9 +13,9 @@ export interface setThumbnailMethodMutation {
/**
* Set the filter to be used when generating thumbnails
*/
setThumbnailDownsampleMethod: number
setThumbnailDownsampleMethod: ThumbnailFilter
}
export interface setThumbnailMethodMutationVariables {
method: number
method: ThumbnailFilter
}

View File

@ -3,6 +3,8 @@
// @generated
// This file was automatically generated and should not be edited.
import { ThumbnailFilter } from './../../../__generated__/globalTypes'
// ====================================================
// GraphQL query operation: thumbnailMethodQuery
// ====================================================
@ -12,7 +14,7 @@ export interface thumbnailMethodQuery_siteInfo {
/**
* The filter to use when generating thumbnails
*/
thumbnailMethod: number
thumbnailMethod: ThumbnailFilter
}
export interface thumbnailMethodQuery {

View File

@ -48,6 +48,18 @@ export enum OrderDirection {
DESC = 'DESC',
}
/**
* Supported downsampling filters for thumbnail generation
*/
export enum ThumbnailFilter {
Box = 'Box',
CatmullRom = 'CatmullRom',
Lanczos = 'Lanczos',
Linear = 'Linear',
MitchellNetravali = 'MitchellNetravali',
NearestNeighbor = 'NearestNeighbor',
}
//==============================================================
// END Enums and Input Objects
//==============================================================