🏗️Architektur von SANE

SANE trennt strikt: Frontends (Bedienung) kennen keine Hardware, Backends (Treiber) kennen keine Oberfläche. Dazwischen steht eine kleine C-API aus 14 Funktionen – und das dll-Meta-Backend, das beliebig viele Backends hinter einer Bibliothek versteckt.

🧩Schichten zum Anklicken

FrontendslibsaneBackendsTransportGerätescanimageXSaneSimple ScanSkanliteNAPS2libsane (dll)genesyspixmaepson2hpaioesclairscannettestlibusb / KernelHTTP · mDNSTCP 6566 → saned(keine Hardware)USB-ScannerNetzwerk-MFPScan-ServerTestbild

Auf einen Kasten klicken: der Weg durch die Schichten wird hervorgehoben.

Backends

net – Netzwerk-Client

Leitet alle SANE-Aufrufe über TCP an einen saned auf einem anderen Rechner weiter. Gerätenamen: net:host:backend:gerät. Hosts stehen in net.conf oder SANE_NET_HOSTS.

# /etc/sane.d/dll.conf
net

$ scanimage -L
device `net:scanner.example.org:test:0' …

Gerätenamen sind Beispiele im typischen Format des jeweiligen Backends.

🔀Wie libsane den richtigen Treiber findet

Gerätenamen haben die Form backend:gerät. Das dll-Backend schneidet am ersten Doppelpunkt ab, lädt das Backend und reicht den Rest weiter. Probiere es aus:
📄 /etc/sane.d/dll.conf
📁 /etc/sane.d/dll.d/

Tipp: # vor test entfernen – dann findet auch test:0 sein Backend.

🔢 Ladereihenfolge
  1. 1libsane-airscan.sodll.d/airscan
  2. 2libsane-net.sodll.conf
  3. 3libsane-epson2.sodll.conf
  4. 4libsane-genesys.sodll.conf
  5. 5libsane-pixma.sodll.conf
  6. 6libsane-escl.sodll.conf

Laut sane-dll(5) kommen Einträge aus dll.d/ vor denen aus dll.conf. Das Standard-Backend für Namen ohne Doppelpunkt ist das zuletzt aufgeführte.

backend = test · device = 0
❌ Backend „test“ ist nicht in dll.conf/dll.d eingetragen → sane_open() liefert SANE_STATUS_INVAL.

🧾Selbstbeschreibende Optionen

Ein Frontend fragt jede Option mit sane_get_option_descriptor() ab und baut daraus seine Oberfläche. So bekommt scanimage für jedes Gerät automatisch passende Parameter.
#nametitletypeunitconstraint
0""Number of optionsSANE_TYPE_INTSANE_UNIT_NONE–
1""Scan ModeSANE_TYPE_GROUPSANE_UNIT_NONE–
2"mode"ModeSANE_TYPE_STRINGSANE_UNIT_NONESTRING_LIST: Lineart | Gray | Color
3"depth"Bit depthSANE_TYPE_INTSANE_UNIT_BITWORD_LIST: 1, 8, 16
4"resolution"Scan resolutionSANE_TYPE_INTSANE_UNIT_DPIWORD_LIST: 75, 150, 300, 600
5"source"Scan sourceSANE_TYPE_STRINGSANE_UNIT_NONESTRING_LIST: Flatbed | Automatic Document Feeder
6""GeometrySANE_TYPE_GROUPSANE_UNIT_NONE–
7"tl-x"Top-left xSANE_TYPE_FIXEDSANE_UNIT_MMRANGE: 0 … 215,9 mm
8"tl-y"Top-left ySANE_TYPE_FIXEDSANE_UNIT_MMRANGE: 0 … 297 mm
9"br-x"Bottom-right xSANE_TYPE_FIXEDSANE_UNIT_MMRANGE: 0 … 215,9 mm
10"br-y"Bottom-right ySANE_TYPE_FIXEDSANE_UNIT_MMRANGE: 0 … 297 mm
💡 Option 0
Hat immer einen leeren Namen und enthält die Anzahl aller Optionen (inklusive sich selbst).
✅ Well-Known Options
Der Standard legt nur wenige Namen fest: resolution, preview und die Scanbereichs-Optionen tl-x, tl-y, br-x, br-y. Weitere übliche Namen wie mode oder source stehen in saneopts.h.
⚠️ Gleicher Zweck, andere Werte
Laut scanimage(1) heißt der Graustufenmodus bei einem Backend Gray, beim nächsten Grayscale. Deshalb immer zuerst scanimage -A ansehen.

🖼️Wie Bilddaten übertragen werden

Ein Bild = ein oder mehrere Rahmen (Frames)

SANE_FRAME_RGB   (ein Rahmen, verschränkt)
  Zeile 0: R G B R G B R G B …
  Zeile 1: R G B R G B R G B …        last_frame = TRUE

SANE_FRAME_RED / GREEN / BLUE  (Dreipass-Scanner)
  Rahmen 1: R R R R …                 last_frame = FALSE
  Rahmen 2: G G G G …                 last_frame = FALSE
  Rahmen 3: B B B B …                 last_frame = TRUE

SANE_FRAME_GRAY, depth = 1  (Lineart)
  Byte: 1 0 1 1 0 0 0 1   ← linkes Pixel = höchstes Bit
        ■ □ ■ ■ □ □ □ ■      1 = schwarz, 0 = weiß

Gültige Bittiefen sind 1, 8 und 16 Bit pro Sample. Ein Gerät mit 12 Bit muss die Werte selbst auf 16 Bit hochskalieren. Bei 16 Bit liegen die Bytes in der Byte-Reihenfolge der Maschine – beim Netzwerkscannen rechnet der Client sie gegebenenfalls um.

Achtung Umkehrung: Bei SANE_FRAME_GRAY mit Tiefe 1 bedeutet 1 = schwarz, bei allen anderen Tiefen ist 0 = schwarz und größere Werte sind heller.

Kennt ein Handscanner die Bildhöhe nicht im Voraus, meldet er lines = -1 – das Frontend liest dann einfach, bis SANE_STATUS_EOF kommt.

📂Wichtige Dateien

/etc/sane.d/dll.confListe der Backends, die libsane lädt (eine Zeile pro Backend, # = aus)
/etc/sane.d/dll.d/*Zusatz-Backends aus anderen Paketen (sane-airscan, HPLIP …) – werden zuerst geladen
/etc/sane.d/dll.aliasesGeräte umbenennen (alias) oder ausblenden (hide)
/etc/sane.d/<backend>.confEinstellungen je Backend, z. B. pixma.conf (Netzwerkgeräte), epson2.conf, test.conf
/etc/sane.d/net.confsaned-Server, die das net-Backend fragt
/etc/sane.d/saned.confZugriffsliste und Datenports des Servers saned
/usr/lib/<arch>/sane/libsane-*.so.1die Backend-Bibliotheken (Pfad je nach Distribution)

Bei selbst kompilierten Versionen liegt alles unter /usr/local/etc/sane.d bzw. /usr/local/lib/sane. Mit SANE_CONFIG_DIR lässt sich der Suchpfad ändern.