Git-Repository für bestehenden archivdms-Code initialisiert, Branch-/Commit-Konvention (feature/<ticket>-<slug>-Branches, Ticket-Prefix in Commit-Nachricht) etabliert.
65 lines
2.2 KiB
Go
65 lines
2.2 KiB
Go
// Package barcode wraps the system zbarimg binary (Debian package
|
|
// zbar-tools) as a best-effort barcode decoding sidecar, consistent with
|
|
// archivdms's general philosophy of shelling out to small CLI tools via
|
|
// os/exec instead of adding CGO/native Go dependencies (see
|
|
// internal/ocr/ocr.go package comment for the same rationale applied to
|
|
// tesseract/poppler-utils).
|
|
//
|
|
// Barcode decoding failures (binary missing, non-zero exit because no
|
|
// barcode was found, timeout) are never fatal to an upload: DecodeBarcodes
|
|
// returns an empty slice and a nil error in the "nothing found / binary
|
|
// missing" cases, matching how OCR failures are tolerated by callers.
|
|
package barcode
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"os/exec"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
const defaultTimeout = 20 * time.Second
|
|
|
|
// DecodeBarcodes runs `zbarimg --raw -q <imagePath>` and returns the
|
|
// decoded raw values, one per line of output. If zbarimg is not installed,
|
|
// this returns an empty slice and a nil error (tolerant, no hard-fail) —
|
|
// callers that want to warn about a missing binary should check
|
|
// exec.LookPath("zbarimg") themselves if they need to distinguish
|
|
// "not installed" from "installed, nothing found".
|
|
func DecodeBarcodes(ctx context.Context, imagePath string) ([]string, error) {
|
|
if _, err := exec.LookPath("zbarimg"); err != nil {
|
|
// Binary not present: tolerated, same as a missing tesseract binary.
|
|
return nil, nil
|
|
}
|
|
|
|
cctx, cancel := context.WithTimeout(ctx, defaultTimeout)
|
|
defer cancel()
|
|
|
|
cmd := exec.CommandContext(cctx, "zbarimg", "--raw", "-q", imagePath)
|
|
var out, stderr bytes.Buffer
|
|
cmd.Stdout = &out
|
|
cmd.Stderr = &stderr
|
|
err := cmd.Run()
|
|
if err != nil {
|
|
// zbarimg exits non-zero (typically exit code 4) when no barcode is
|
|
// found in the image at all — that is a normal, expected outcome for
|
|
// the vast majority of scanned documents, not an error condition.
|
|
if exitErr, ok := err.(*exec.ExitError); ok {
|
|
_ = exitErr
|
|
return nil, nil
|
|
}
|
|
return nil, fmt.Errorf("barcode: zbarimg failed: %w (%s)", err, strings.TrimSpace(stderr.String()))
|
|
}
|
|
|
|
var values []string
|
|
for _, line := range strings.Split(out.String(), "\n") {
|
|
line = strings.TrimSpace(line)
|
|
if line != "" {
|
|
values = append(values, line)
|
|
}
|
|
}
|
|
return values, nil
|
|
}
|