1package hints
2
3import (
4 "context"
5 "image"
6 "image/draw"
7 "image/png"
8 "os"
9 "os/exec"
10 "path/filepath"
11 "strconv"
12 "testing"
13 "time"
14)
15
16// TestFrameBenchmark logs counts and timings, never filenames or OCR text.
17func TestFrameBenchmark(t *testing.T) {
18 dir := os.Getenv("NEFERWL_HINT_BENCH_DIR")
19 if dir == "" {
20 t.Skip("set NEFERWL_HINT_BENCH_DIR to a local PNG directory")
21 }
22 if _, err := exec.LookPath("tesseract"); err != nil {
23 t.Skip("tesseract not on PATH")
24 }
25 files, err := filepath.Glob(filepath.Join(dir, "*.png"))
26 if err != nil || len(files) == 0 {
27 t.Fatal("no PNG frames")
28 }
29 // Settings under test: NEFERWL_HINT_BENCH_WORKERS=<n>, NEFERWL_HINT_BENCH_PNG=speed|none.
30 if v, _ := strconv.Atoi(os.Getenv("NEFERWL_HINT_BENCH_WORKERS")); v > 0 {
31 ocrWorkers = v
32 }
33 if os.Getenv("NEFERWL_HINT_BENCH_PGM") == "0" {
34 rawPGM = false
35 }
36 if os.Getenv("NEFERWL_HINT_BENCH_PNG") == "none" {
37 pngLevel = png.NoCompression
38 }
39 for i, file := range files {
40 f, err := os.Open(file)
41 if err != nil {
42 t.Fatal("open frame failed")
43 }
44 src, err := png.Decode(f)
45 _ = f.Close()
46 if err != nil {
47 t.Fatal("decode frame failed")
48 }
49 img := image.NewRGBA(image.Rect(0, 0, src.Bounds().Dx(), src.Bounds().Dy()))
50 draw.Draw(img, img.Bounds(), src, src.Bounds().Min, draw.Src)
51 start := time.Now()
52 words, bands, err := readWords(context.Background(), toGray(img))
53 if err != nil {
54 t.Fatal("recognition failed")
55 }
56 t.Logf("frame=%d px=%d ocr_ms=%.1f words=%d links=%d bands=%d", i, img.Bounds().Dx()*img.Bounds().Dy(), ms(time.Since(start)), len(words), len(textLinks(words, 1)), bands)
57 if os.Getenv("NEFERWL_HINT_BENCH_STRIPS") == "" {
58 continue
59 }
60 // Experimental strips use known OCR word regions, not pixel targets.
61 // This is an oracle comparison, not a production optimization.
62 lines := make([]image.Rectangle, 0, len(words))
63 for _, word := range words {
64 lines = append(lines, word.Rect)
65 }
66 for _, normalized := range []bool{false, true} {
67 begin := time.Now()
68 compact, _, err := readStrips(context.Background(), img, lines, 8, normalized)
69 if err != nil {
70 t.Fatal("strip recognition failed")
71 }
72 t.Logf("frame=%d strips normalized=%t ocr_ms=%.1f words=%d links=%d", i, normalized, ms(time.Since(begin)), len(compact), len(textLinks(compact, 1)))
73 }
74 }
75}
76
77func toGray(img *image.RGBA) *image.Gray {
78 g := image.NewGray(img.Bounds())
79 draw.Draw(g, g.Bounds(), img, img.Bounds().Min, draw.Src)
80 return g
81}