Files
patrickandClaude Sonnet 5 26bb03aade
CI / Core-Modul (Build/Vet/Test) (push) Canceled after 0s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (push) Canceled after 0s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (push) Canceled after 0s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (push) Canceled after 0s
CI / Web (dms-browser) (push) Canceled after 0s
CI / Web (pdf-viewer) (push) Canceled after 0s
CI / Web (shl) (push) Canceled after 0s
INT-10: rasterung mit 200 dpi, einteilige stapel im lieferregister
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 20:09:20 +02:00

57 lines
1.3 KiB
Go

package batchsplit
import (
"context"
"fmt"
"os/exec"
"path/filepath"
"regexp"
"strconv"
"time"
)
// Renderer rastert die Seiten eines PDFs; Ergebnis: Seitennummer -> PNG-Pfad.
type Renderer interface {
Render(pdfPath, outDir string) (map[int]string, error)
}
// PopplerRenderer rastert mit pdftoppm (Graustufen-PNG).
type PopplerRenderer struct {
Binary string
DPI int
Timeout time.Duration
}
var renderedPage = regexp.MustCompile(`-(\d+)\.png$`)
func (r PopplerRenderer) Render(pdfPath, outDir string) (map[int]string, error) {
bin, dpi, timeout := r.Binary, r.DPI, r.Timeout
if bin == "" {
bin = "pdftoppm"
}
if dpi <= 0 {
dpi = 200
}
if timeout <= 0 {
timeout = 3 * time.Minute
}
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
prefix := filepath.Join(outDir, "page")
if out, err := exec.CommandContext(ctx, bin, "-r", strconv.Itoa(dpi), "-gray", "-png", pdfPath, prefix).CombinedOutput(); err != nil {
return nil, fmt.Errorf("%s: %w: %.200s", bin, err, out)
}
files, err := filepath.Glob(prefix + "-*.png")
if err != nil {
return nil, err
}
pages := make(map[int]string, len(files))
for _, f := range files {
if m := renderedPage.FindStringSubmatch(f); m != nil {
n, _ := strconv.Atoi(m[1])
pages[n] = f
}
}
return pages, nil
}