feat: image variants per image

This commit is contained in:
fsylvain committed 2026-10-08 19:57:51 +02:00
1 parent f567866161
commit 951fef18ba
92 files changed
+8695 -413

No files matched your search

+63
View File
@@ -4,7 +4,9 @@ import (
"crypto/sha256"
"encoding/hex"
"errors"
"math"
"regexp"
"slices"
"strconv"
"strings"
"time"
@@ -17,6 +19,8 @@ var ErrVariantFormatUnavailable = errors.New("variant format cannot be encoded")
var ErrUnknownVariant = errors.New("unknown variant")
var ErrUnsupportedParameter = errors.New("unsupported parameter")
var ErrSourceTooLarge = errors.New("source image is too large to generate this variant")
var ErrVariantSourceUnsupported = errors.New("variants are not generated for this format")
var ErrVariantSourceUnreadable = errors.New("the source image cannot be read")
type VariantFit string
@@ -220,3 +224,62 @@ type VariantFileTotals struct {
Files int
Bytes int64
}
func OutputSize(sourceWidth int, sourceHeight int, settings VariantSettings) (int, int) {
if sourceWidth < 1 || sourceHeight < 1 {
return 0, 0
}
if settings.Width == nil || settings.Height == nil {
return proportionalOutput(sourceWidth, sourceHeight, settings)
}
boxWidth, boxHeight := *settings.Width, *settings.Height
switch settings.Fit {
case FitContain:
return boxWidth, boxHeight
case FitInside:
return scaledOutput(sourceWidth, sourceHeight, math.Min(1, math.Min(ratio(boxWidth, sourceWidth), ratio(boxHeight, sourceHeight))))
default:
shrink := math.Min(1, math.Min(ratio(sourceWidth, boxWidth), ratio(sourceHeight, boxHeight)))
return scaledOutput(boxWidth, boxHeight, shrink)
}
}
func proportionalOutput(sourceWidth int, sourceHeight int, settings VariantSettings) (int, int) {
scale := 1.0
if settings.Width != nil {
scale = math.Min(scale, ratio(*settings.Width, sourceWidth))
}
if settings.Height != nil {
scale = math.Min(scale, ratio(*settings.Height, sourceHeight))
}
return scaledOutput(sourceWidth, sourceHeight, scale)
}
func scaledOutput(width int, height int, factor float64) (int, int) {
return scaledLength(width, factor), scaledLength(height, factor)
}
func scaledLength(length int, factor float64) int {
return max(1, int(math.Round(float64(length)*factor)))
}
func ratio(numerator int, denominator int) float64 {
return float64(numerator) / float64(denominator)
}
var sourceContentTypeFormats = map[string]VariantFormat{
"image/jpeg": FormatJPEG,
"image/png": FormatPNG,
"image/webp": FormatWebP,
"image/gif": FormatPNG,
}
func OutputFormat(format VariantFormat, sourceContentType string, encodable []VariantFormat) VariantFormat {
if format == FormatOriginal {
format = sourceContentTypeFormats[sourceContentType]
}
if slices.Contains(encodable, format) {
return format
}
return FormatPNG
}