package ocr import ( "fmt" "github.com/otiai10/gosseract/v2" ) // Engine holds a pool of reusable Tesseract clients. type Engine struct { pool chan *gosseract.Client clients []*gosseract.Client lang string } // NewEngine warms up poolSize Tesseract clients for the given language. func NewEngine(lang string, poolSize int) (*Engine, error) { if poolSize < 1 { poolSize = 1 } e := &Engine{ pool: make(chan *gosseract.Client, poolSize), clients: make([]*gosseract.Client, 0, poolSize), lang: lang, } for i := 0; i < poolSize; i++ { client, err := newPooledClient(lang) if err != nil { e.Close() return nil, fmt.Errorf("tesseract client %d: %w", i, err) } e.clients = append(e.clients, client) e.pool <- client } return e, nil } func newPooledClient(lang string) (*gosseract.Client, error) { client := gosseract.NewClient() if err := client.SetLanguage(lang); err != nil { if err2 := client.SetLanguage("eng"); err2 != nil { _ = client.Close() return nil, fmt.Errorf("tesseract lang: %w", err) } } return client, nil } // Acquire returns a Tesseract client from the pool. func (e *Engine) Acquire() *gosseract.Client { return <-e.pool } // Release returns a client to the pool. func (e *Engine) Release(client *gosseract.Client) { e.pool <- client } // Close shuts down all pooled clients. func (e *Engine) Close() error { for _, client := range e.clients { _ = client.Close() } e.clients = nil return nil }