Files
ds-galo/backend/internal/photos/edit_bench_test.go
T
iu c953008a86 feat(photos): добавить эффекты и настройки панели редактора
- текстура, чёткость, дымка, виньетка и зерно в неразрушающем редакторе
- живой WebGL2-предпросмотр эффектов и CPU-фолбэк
- секции редактора свёрнуты по умолчанию, состояние в localStorage
- вкладка «Редактирование» доступна только из просмотрщика
2026-10-24 22:57:30 +03:00

111 lines
2.8 KiB
Go

package photos
import (
"bytes"
"image"
"image/png"
"testing"
"time"
)
func BenchmarkApplyLight(b *testing.B) {
w, h := 4000, 3000
src := image.NewNRGBA(image.Rect(0, 0, w, h))
for i := range src.Pix {
src.Pix[i] = uint8(i % 251)
}
p := LightParams{
Exposure: 0.5,
Contrast: 20,
Highlights: -30,
Shadows: 40,
Curve: CurveParams{
RGB: []CurvePoint{{X: 0, Y: 0}, {X: 0.5, Y: 0.4}, {X: 1, Y: 1}},
},
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = applyLight(src, p)
}
b.StopTimer()
b.Logf("кадров: %d", b.N)
}
// BenchmarkBoxBlur3 measures the O(n) box-blur passes on a 12 MP luminance
// plane with the radius the clarity pass uses for that frame.
func BenchmarkBoxBlur3(b *testing.B) {
w, h := 4000, 3000
src := make([]uint8, w*h)
for i := range src {
src[i] = uint8(i % 251)
}
radius := int(0.008 * float64(min(w, h)))
if radius < 2 {
radius = 2
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = boxBlur3(src, w, h, radius)
}
b.StopTimer()
b.Logf("кадров: %d, радиус: %d", b.N, radius)
}
// BenchmarkFullRenderWithEffects measures the whole edited render of a 12 MP
// photo with all effects enabled: decode, light, color, dehaze, texture,
// clarity, vignette and grain. This is the work the background worker does for
// one edit job.
func BenchmarkFullRenderWithEffects(b *testing.B) {
w, h := 4000, 3000
src := image.NewNRGBA(image.Rect(0, 0, w, h))
for y := 0; y < h; y++ {
for x := 0; x < w; x++ {
i := y*src.Stride + x*4
src.Pix[i] = uint8(x*255/w) ^ uint8(y*255/h)
src.Pix[i+1] = uint8(x * 3)
src.Pix[i+2] = uint8(y * 5)
src.Pix[i+3] = 255
}
}
var buf bytes.Buffer
encoder := png.Encoder{CompressionLevel: png.BestSpeed}
if err := encoder.Encode(&buf, src); err != nil {
b.Fatalf("encode png: %v", err)
}
data := buf.Bytes()
params := EditParams{
Light: LightParams{Exposure: 0.2, Contrast: 12, Shadows: 15},
Color: ColorParams{Vibrance: 20, Temperature: 8},
Effects: EffectsParams{
Texture: 30,
Clarity: 25,
Dehaze: 20,
Vignette: VignetteParams{
Mode: VignetteColor, Amount: 35, Color: "#ff8800", Highlights: 25,
},
Grain: GrainParams{Amount: 30, Size: 30, Roughness: 55},
},
}
seed := editSeed("benchmark-photo")
b.ResetTimer()
for i := 0; i < b.N; i++ {
if _, err := decodeAndAdjust(data, params, seed); err != nil {
b.Fatalf("decode and adjust: %v", err)
}
}
b.StopTimer()
b.Logf("кадров: %d, эффекты: текстура/чёткость/дымка/виньетка/зерно", b.N)
}
func TestRenderSpeed(t *testing.T) {
w, h := 4000, 3000
src := image.NewNRGBA(image.Rect(0, 0, w, h))
for i := range src.Pix {
src.Pix[i] = uint8(i % 251)
}
start := time.Now()
_ = applyLight(src, LightParams{Exposure: 0.5, Contrast: 20})
t.Logf("applyLight %dx%d: %s", w, h, time.Since(start))
}