- текстура, чёткость, дымка, виньетка и зерно в неразрушающем редакторе - живой WebGL2-предпросмотр эффектов и CPU-фолбэк - секции редактора свёрнуты по умолчанию, состояние в localStorage - вкладка «Редактирование» доступна только из просмотрщика
111 lines
2.8 KiB
Go
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))
|
|
}
|