Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion internal/render/common/styles.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,22 @@ var (
style.SetZIndex(-99),
)


FooterWrapperLayout = style.Style{
Direction: style.DirectionHorizontal,
AlignItems: style.AlignItemsCenter,
Gap: 5,
}
)

func CardsBackgroundStyleForTheme(theme Theme) style.StyleOptions {
blur := DefaultBackgroundBlur
if theme.BackgroundBlur != nil {
blur = *theme.BackgroundBlur
}
return style.NewStyle(
style.SetBorderRadius(BorderRadius2XL),
style.SetBlur(blur),
style.SetPosition(style.PositionAbsolute),
style.SetZIndex(-99),
)
}
3 changes: 3 additions & 0 deletions internal/render/common/theme.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ type Theme struct {
// Optional background image bundled with the theme.
// Used as the default background when no explicit background is provided.
Background image.Image
// BackgroundBlur overrides the default blur applied to the background image
// at render time. nil = use DefaultBackgroundBlur, non-nil = use this value.
BackgroundBlur *float64

// BackgroundOverlay is rendered behind cards, on top of the background image.
// seed is derived from the account ID for deterministic patterns.
Expand Down
5 changes: 3 additions & 2 deletions internal/stats/render/period/v2/cards.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,12 @@ func generateCards(stats fetch.AccountStatsOverPeriod, cards period.Cards, _ []m
opts.Background = common.AddWN8BackgroundBranding(opts.Background, stats.RegularBattles.Vehicles, seed)
}

bgStyle := common.CardsBackgroundStyleForTheme(theme)
var layers []*facepaint.Block
layers = append(layers, facepaint.MustNewImageContent(common.CardsBackgroundStyle, opts.Background))
layers = append(layers, facepaint.MustNewImageContent(bgStyle, opts.Background))
if theme.BackgroundOverlay != nil {
if overlay := theme.BackgroundOverlay(opts.Background.Bounds(), seed); overlay != nil {
layers = append(layers, facepaint.MustNewImageContent(common.CardsBackgroundStyle, overlay))
layers = append(layers, facepaint.MustNewImageContent(bgStyle, overlay))
}
}
layers = append(layers, cardsFrame)
Expand Down
5 changes: 3 additions & 2 deletions internal/stats/render/session/v2/cards.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,12 @@ func generateCards(sessionData, careerData fetch.AccountStatsOverPeriod, cards s
opts.Background = common.AddWN8BackgroundBranding(opts.Background, sessionData.RegularBattles.Vehicles, seed)
}

bgStyle := common.CardsBackgroundStyleForTheme(theme)
var layers []*facepaint.Block
layers = append(layers, facepaint.MustNewImageContent(common.CardsBackgroundStyle, opts.Background))
layers = append(layers, facepaint.MustNewImageContent(bgStyle, opts.Background))
if theme.BackgroundOverlay != nil {
if overlay := theme.BackgroundOverlay(opts.Background.Bounds(), seed); overlay != nil {
layers = append(layers, facepaint.MustNewImageContent(common.CardsBackgroundStyle, overlay))
layers = append(layers, facepaint.MustNewImageContent(bgStyle, overlay))
}
}
layers = append(layers, cardsFrame)
Expand Down
5 changes: 1 addition & 4 deletions internal/stats/render/themes/spring2026/assets.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@ import (
_ "image/png"
"path"
"strings"

"github.com/nao1215/imaging"
)

//go:embed assets/background.jpg
//go:embed assets/background_blurred.jpg
var backgroundBytes []byte

//go:embed assets/petals/processed
Expand All @@ -29,7 +27,6 @@ func init() {
if err != nil {
panic("spring2026: failed to decode background: " + err.Error())
}
backgroundImage = imaging.Blur(backgroundImage, 3)
backgroundBytes = nil

entries, err := petalsFS.ReadDir("assets/petals/processed")
Expand Down
1 change: 1 addition & 0 deletions internal/stats/render/themes/spring2026/assets/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
background_blurred.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
70 changes: 70 additions & 0 deletions internal/stats/render/themes/spring2026/assets/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"image"
"image/color"
"image/jpeg"
"image/png"
"math"
"os"
Expand Down Expand Up @@ -37,6 +38,11 @@ var tints = []tintPreset{
}

func main() {
generatePetals()
generateBlurredBackground()
}

func generatePetals() {
sourceDir := filepath.Join("petals", "source")
outDir := filepath.Join("petals", "processed")

Expand Down Expand Up @@ -103,6 +109,70 @@ func main() {
fmt.Printf("generated %d processed petal images\n", idx)
}

func generateBlurredBackground() {
const (
minSigma = 0.5
maxSigma = 8.0
levels = 8
quality = 95
)

bg, err := imaging.Open("background.jpg")
if err != nil {
panic(fmt.Sprintf("failed to open background.jpg: %v", err))
}

dm, err := imaging.Open("depthmap.png")
if err != nil {
panic(fmt.Sprintf("failed to open depthmap.png: %v", err))
}

w, h := bg.Bounds().Dx(), bg.Bounds().Dy()
dm = imaging.Resize(dm, w, h, imaging.Linear)

stack := make([]*image.NRGBA, levels)
for i := range levels {
sigma := minSigma + (maxSigma-minSigma)*float64(i)/float64(levels-1)
stack[i] = imaging.Blur(bg, sigma)
fmt.Printf(" blur level %d/%d (sigma=%.1f)\n", i+1, levels, sigma)
}

out := image.NewNRGBA(image.Rect(0, 0, w, h))
for y := range h {
for x := range w {
r, _, _, _ := dm.At(x, y).RGBA()
depth := float64(r>>8) / 255.0 // 1.0 = close (bright), 0.0 = far (dark)

// close → low index (less blur), far → high index (more blur)
idx := (1.0 - depth) * float64(levels-1)
lo := int(math.Floor(idx))
hi := int(math.Ceil(idx))
lo = max(lo, 0)
hi = min(hi, levels-1)
frac := idx - float64(lo)

c1 := stack[lo].NRGBAAt(x, y)
c2 := stack[hi].NRGBAAt(x, y)
out.SetNRGBA(x, y, color.NRGBA{
R: uint8(lerp(float64(c1.R), float64(c2.R), frac)),
G: uint8(lerp(float64(c1.G), float64(c2.G), frac)),
B: uint8(lerp(float64(c1.B), float64(c2.B), frac)),
A: 255,
})
}
}

f, err := os.Create("background_blurred.jpg")
if err != nil {
panic(err)
}
defer f.Close()
if err := jpeg.Encode(f, out, &jpeg.Options{Quality: quality}); err != nil {
panic(err)
}
fmt.Println("generated depth-blurred background")
}

// trimAlpha crops transparent borders, keeping at least minPad pixels of padding.
func trimAlpha(img *image.NRGBA, minPad int) *image.NRGBA {
b := img.Bounds()
Expand Down
4 changes: 3 additions & 1 deletion internal/stats/render/themes/spring2026/theme.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ var (
)

func Theme() common.Theme {
noBlur := 0.0
return common.Theme{
Background: backgroundImage,
Background: backgroundImage,
BackgroundBlur: &noBlur,
Frame: style.NewStyle(func(s *style.Style) {
s.PaddingLeft = 15
s.PaddingRight = 15
Expand Down
Loading