CI: Apply Go linter recommendations to "thumb" package #5330

Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
Michael Mayer 2025-11-22 11:55:19 +01:00
parent 75bc6d754c
commit c909c0bd5a
15 changed files with 78 additions and 62 deletions

View file

@ -2,6 +2,7 @@ package thumb
import "github.com/photoprism/photoprism/pkg/clean"
// ColorSpace represents a thumbnail color profile preference.
type ColorSpace = string
// Supported thumbnail color profile settings.

View file

@ -5,5 +5,6 @@ import (
)
var (
// ErrNotCached indicates a requested thumbnail is not present in cache.
ErrNotCached = errors.New("not cached")
)

View file

@ -3,14 +3,14 @@ package thumb
import (
"fmt"
"image"
_ "image/gif"
_ "image/jpeg"
_ "image/png"
_ "image/gif" // register GIF decoder for config reads
_ "image/jpeg" // register JPEG decoder for config reads
_ "image/png" // register PNG decoder for config reads
"os"
"runtime/debug"
_ "golang.org/x/image/bmp"
_ "golang.org/x/image/webp"
_ "golang.org/x/image/bmp" // register BMP decoder for config reads
_ "golang.org/x/image/webp" // register WEBP decoder for config reads
"github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/fs"
@ -29,7 +29,7 @@ func FileInfo(fileName string) (info image.Config, err error) {
return info, err
}
file, err := os.Open(fileName)
file, err := os.Open(fileName) //nolint:gosec // fileName is resolved path provided by caller; reading images is expected
if err != nil || file == nil {
return info, err

View file

@ -1,5 +1,6 @@
package thumb
// Lib identifies the image processing backend.
type Lib = string
// Supported image processing libraries.

View file

@ -3,19 +3,29 @@ package thumb
import "github.com/dustin/go-humanize/english"
const (
MiB = 1024 * 1024
GiB = 1024 * MiB
DefaultCacheMem = 128 * MiB
DefaultCacheSize = 128
// MiB represents one mebibyte.
MiB = 1024 * 1024
// GiB represents one gibibyte.
GiB = 1024 * MiB
// DefaultCacheMem specifies the default libvips cache memory limit.
DefaultCacheMem = 128 * MiB
// DefaultCacheSize is the default number of cached operations.
DefaultCacheSize = 128
// DefaultCacheFiles is the default number of cached files.
DefaultCacheFiles = 16
DefaultWorkers = 1
// DefaultWorkers is the default worker count when not specified.
DefaultWorkers = 1
)
var (
MaxCacheMem = DefaultCacheMem
MaxCacheSize = DefaultCacheSize
// MaxCacheMem is the maximum memory libvips may use for caching.
MaxCacheMem = DefaultCacheMem
// MaxCacheSize limits the number of cached operations.
MaxCacheSize = DefaultCacheSize
// MaxCacheFiles limits the number of cached files.
MaxCacheFiles = DefaultCacheFiles
NumWorkers = DefaultWorkers
// NumWorkers defines the number of libvips worker threads.
NumWorkers = DefaultWorkers
)
// Init initializes the package config based on the available memory,
@ -38,14 +48,12 @@ func Init(availableMemory uint64, maxWorkers int, imgLib string) {
}
// Set the number of worker threads that libvips can use.
if maxWorkers > 0 {
// Using the specified number of workers.
NumWorkers = maxWorkers
} else if maxWorkers < 0 {
// Using built-in default.
NumWorkers = 0
} else {
// Default to one worker.
switch {
case maxWorkers > 0:
NumWorkers = maxWorkers // explicitly configured
case maxWorkers < 0:
NumWorkers = 0 // use libvips default
default:
NumWorkers = DefaultWorkers
}

View file

@ -57,5 +57,5 @@ func MemSize(img image.Image) Bytes {
bytesPerPixel = 8
}
return Bytes(pixels * bytesPerPixel)
return Bytes(uint64(pixels) * uint64(bytesPerPixel)) //nolint:gosec // pixels and bytesPerPixel are non-negative and bounded by image dimensions
}

View file

@ -49,7 +49,7 @@ func OpenJpeg(fileName string, orientation int) (image.Image, error) {
logName := clean.Log(filepath.Base(fileName))
// Open file.
fileReader, err := os.Open(fileName)
fileReader, err := os.Open(fileName) //nolint:gosec // fileName is provided by caller and validated earlier
if err != nil {
return nil, err
}
@ -76,8 +76,7 @@ func OpenJpeg(fileName string, orientation int) (image.Image, error) {
log.Tracef("thumb: %s has no color profile", logName)
} else if profile, err := iccProfile.Description(); err == nil && profile != "" {
log.Tracef("thumb: %s has color profile %s", logName, clean.Log(profile))
switch {
case colors.ProfileDisplayP3.Equal(profile):
if colors.ProfileDisplayP3.Equal(profile) {
img = colors.ToSRGB(img, colors.ProfileDisplayP3)
}
}

View file

@ -4,6 +4,7 @@ import (
"github.com/photoprism/photoprism/pkg/fs"
)
// ResampleOption enumerates thumbnail resampling strategies.
const (
ResampleFillCenter ResampleOption = iota
ResampleFillTopLeft
@ -15,6 +16,7 @@ const (
ResamplePng
)
// ResampleMethods maps resample options to their string identifiers.
var ResampleMethods = map[ResampleOption]string{
ResampleFillCenter: "center",
ResampleFillTopLeft: "left",

View file

@ -12,15 +12,16 @@ func Resample(img image.Image, width, height int, opts ...ResampleOption) image.
method, filter, _ := ResampleOptions(opts...)
if method == ResampleFit {
switch method {
case ResampleFit:
resImg = imaging.Fit(img, width, height, filter.Imaging())
} else if method == ResampleFillCenter {
case ResampleFillCenter:
resImg = imaging.Fill(img, width, height, imaging.Center, filter.Imaging())
} else if method == ResampleFillTopLeft {
case ResampleFillTopLeft:
resImg = imaging.Fill(img, width, height, imaging.TopLeft, filter.Imaging())
} else if method == ResampleFillBottomRight {
case ResampleFillBottomRight:
resImg = imaging.Fill(img, width, height, imaging.BottomRight, filter.Imaging())
} else if method == ResampleResize {
case ResampleResize:
resImg = imaging.Resize(img, width, height, filter.Imaging())
}

View file

@ -6,16 +6,17 @@ import (
"github.com/disintegration/imaging"
)
// EXIF orientation values.
const (
OrientationUnspecified int = 0
OrientationNormal = 1
OrientationFlipH = 2
OrientationRotate180 = 3
OrientationFlipV = 4
OrientationTranspose = 5
OrientationRotate270 = 6
OrientationTransverse = 7
OrientationRotate90 = 8
OrientationNormal int = 1
OrientationFlipH int = 2
OrientationRotate180 int = 3
OrientationFlipV int = 4
OrientationTranspose int = 5
OrientationRotate270 int = 6
OrientationTransverse int = 7
OrientationRotate90 int = 8
)
// Rotate rotates an image based on the Exif orientation.

View file

@ -33,11 +33,12 @@ func (m SizeMap) All() SizeList {
}
slices.SortStableFunc(result, func(a, b Size) int {
if a.Width < b.Width {
switch {
case a.Width < b.Width:
return -1
} else if a.Width > b.Width {
case a.Width > b.Width:
return 1
} else {
default:
return 0
}
})
@ -45,6 +46,7 @@ func (m SizeMap) All() SizeList {
return result
}
// Size presets used throughout the application.
var (
SizeColors = Size{Colors, Fit720, "Color Detection", 3, 3, false, false, false, true, Options{ResampleResize, ResampleNearestNeighbor, ResamplePng}}
SizeTile50 = Size{Tile50, Fit720, "List View", 50, 50, false, false, false, true, Options{ResampleFillCenter, ResampleDefault}}
@ -103,6 +105,7 @@ var Sizes = SizeMap{
// All contains all thumbnail sizes sorted by width.
var All = Sizes.All()
// ParseSize returns a Size by name or the zero value if unknown.
func ParseSize(s string) Size {
return Sizes[Name(s)]
}

View file

@ -26,14 +26,14 @@ package thumb
import (
"fmt"
_ "image/gif"
_ "image/jpeg"
_ "image/png"
_ "image/gif" // register GIF decoder for thumbnail generation
_ "image/jpeg" // register JPEG decoder for thumbnail generation
_ "image/png" // register PNG decoder for thumbnail generation
"math"
_ "golang.org/x/image/bmp"
_ "golang.org/x/image/tiff"
_ "golang.org/x/image/webp"
_ "golang.org/x/image/bmp" // register BMP decoder for thumbnail generation
_ "golang.org/x/image/tiff" // register TIFF decoder for thumbnail generation
_ "golang.org/x/image/webp" // register WEBP decoder for thumbnail generation
"github.com/photoprism/photoprism/internal/event"
)

View file

@ -14,15 +14,13 @@ var VideoSizes = SizeList{
// VideoSize returns the largest video size type for the given width limit.
func VideoSize(limit int) Size {
if limit < 0 {
// Return maximum size.
return Sizes[Fit7680]
} else if limit == 0 {
// Return default size.
return Sizes[Fit4096]
} else if limit <= 720 {
// Return minimum size.
return Sizes[Fit720]
switch {
case limit < 0:
return Sizes[Fit7680] // maximum
case limit == 0:
return Sizes[Fit4096] // default
case limit <= 720:
return Sizes[Fit720] // minimum
}
// Find match.

View file

@ -62,16 +62,17 @@ func Vips(imageName string, imageBuffer []byte, hash, thumbPath string, width, h
// Choose thumbnail crop.
var crop vips.Interesting
if method == ResampleFillTopLeft {
switch method {
case ResampleFillTopLeft:
crop = vips.InterestingLow
size = vips.SizeBoth
} else if method == ResampleFillBottomRight {
case ResampleFillBottomRight:
crop = vips.InterestingHigh
size = vips.SizeBoth
} else if method == ResampleFit {
case ResampleFit:
crop = vips.InterestingNone
size = vips.SizeDown
} else if method == ResampleFillCenter || method == ResampleResize {
case ResampleFillCenter, ResampleResize:
crop = vips.InterestingCentre
size = vips.SizeBoth
}

View file

@ -29,7 +29,7 @@ func VipsShutdown() {
// vipsInit calls vips.Startup() to initialize libvips.
func vipsInit() {
if vipsStarted == true {
if vipsStarted {
log.Warnf("vips: already initialized - you may have found a bug")
return
}