FDN-01: repository & projektgerüst
Git-Repository für bestehenden archivdms-Code initialisiert, Branch-/Commit-Konvention (feature/<ticket>-<slug>-Branches, Ticket-Prefix in Commit-Nachricht) etabliert.
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
// 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
|
||||
}
|
||||
Reference in New Issue
Block a user