Warning: This document is for the development version of SANE Standard. The latest version is 1.06.

3 The SANE Environment

SANE is defined as a C-callable library interface. Accessing a raster scanner device typically consists of two phases: first, various controls of the scanner need to be setup or queried. In the second phase, one or more images are acquired.

Since the device controls are widely different from device to device, SANE provides a generic interface that makes it easy for a frontend to give a user access to all controls without having to understand each and every device control. The design principle used here is to abstract each device control into a SANE option. An option is a self-describing name/value pair. For example, the brightness control of a camera might be represented by an option called brightness whose value is an integer in the range from 0 to 255.

With self-describing options, a backend need not be concerned with presentation issues: the backend simply provides a list of options that describe all the controls available in the device. Similarly, there are benefits to the frontend: it need not be concerned with the meaning of each option. It simply provides means to present and alter the options defined by the backend.

3.1 Attaching to a SANE backend

The process through which a SANE frontend connects to a backend is platform dependent. Several possibilities exist:

  • Static linking: A SANE backend may be linked directly into a frontend. While the simplest method of attaching to a backend, it is somewhat limited in functionality since the available devices is limited to the ones for which support has been linked in when the frontend was built. But even so static linking can be quite useful, particularly when combined with a backend that can access scanners via a network. Also, it is possible to support multiple backends simultaneously by implementing a meta backend that manages several backends that have been compiled in such a manner that they export unique function names. For example, a backend called be would normally export a function called sane_read(). If each backend would provide such a function, static linking would fail due to multiple conflicting definitions of the same symbol. This can be resolved by having backend be include a header file that has lines of the form:

    #define sane_read be_sane_read

    With definitions of this kind, backend be will export function name be_sane_read(). Thus, all backends will export unique names. As long as a meta backend knows about these names, it is possible to combine several backends at link time and select and use them dynamically at runtime.

  • Dynamic linking: A simpler yet more powerful way to support multiple backends is to exploit dynamic linking on platforms that support it. In this case, a frontend is linked against a shared library that implements any SANE backend. Since each dynamically linked backend exports the same set of global symbols (all starting with the prefix sane_), the dynamic library that gets loaded at runtime does not necessarily have to be the same one as one the frontend got linked against. In other words, it is possible to switch the backend by installing the appropriate backend dynamic library.

    More importantly, dynamic linking makes it easy to implement a meta backend that loads other backends on demand. This is a powerful mechanism since it allows adding new backends merely by installing a shared library and updating a configuration file.

  • Network connection: Arguably the ultimate way to attach to a scanner is by using the network to connect to a backend on a remote machine. This makes it possible to scan images from any host in the universe, as long as there is a network connection to that host and provided the user is permitted to access that scanner.


Figure 3.1 Example SANE Hierarchy

The above discussion lists just a few ways for frontends to attach to a backend. It is of course possible to combine these solutions to provide an entire hierarchy of SANE backends. Such a hierarchy is depicted in Figure 3.1. The figure shows that machine A uses a dynamic-linking based meta backend called dll to access the backends called pnm, mustek, and net. The first two are real backends, whereas the last one is a meta backend that provides network transparent access to remote scanners. In the figure, machine B provides non-local access to its scanners through the SANE frontend called saned. The saned in turn has access to the hp and autolum backends through another instance of the dll backend. The autolum meta backend is used to automatically adjust the luminance (brightness) of the image data acquired by the camera backend called qcam.

Note that a meta backend really is both a frontend and a backend at the same time. It is a frontend from the viewpoint of the backends that it manages and a backend from the viewpoint of the frontends that access it. The name “meta backend” was chosen primarily because the SANE standard describes the interface from the viewpoint of a (real) frontend.

3.2 Image Data Format

Arguably the most important aspect of an image acquisition system is how images are represented. The SANE approach is to define a simple yet powerful representation that is sufficient for vast majority of applications and devices. While the representation is simple, the interface has been defined carefully to allow extending it in the future without breaking backwards compatibility. Thus, it will be possible to accommodate future applications or devices that were not anticipated at the time this standard was created.

A SANE image is a rectangular area. The rectangular area is subdivided into a number of rows and columns. At the intersection of each row and column is a quadratic pixel. A pixel consists of one or more sample values. Each sample value represents one channel (e.g., the red channel). Each sample value has a certain bit depth. The bit depth is fixed for the entire image and can be as small as one bit. Valid bit depths are 1, 8, or 16 bits per sample. If a device’s natural bit depth is something else, it is up to the driver to scale the sample values appropriately (e.g., a 4 bit sample could be scaled by a factor of four to represent a sample value of depth 8).

3.2.1 Image Transmission

The SANE API transmits an image as a sequence of frames. Each frame covers the same rectangular area as the entire image, but may contain only a subset of the channels in the final image. For example, a red/green/blue image could either be transmitted as a single frame that contains the sample values for all three channels or it could be transmitted as a sequence of three frames: the first frame containing the red channel, the second the green channel, and the third the blue channel.

Conceptually, each frame is transmitted a byte at a time. Each byte may contain 8 sample values (for an image bit depth of 1), one full sample value (for an image bit depth of 8), or a partial sample value (for an image bit depth of 16 or bigger). In the latter case, the bytes of each sample value are transmitted in the machine’s native byte order. For depth 1, the leftmost pixel is stored in the most significant bit, and the rightmost pixel in the least significant bit.

Backend Implementation Note

A network-based meta backend will have to ensure that the byte order in image data is adjusted appropriately if necessary. For example, when the meta backend attaches to the server proxy, the proxy may inform the backend of the server’s byte order. The backend can then apply the adjustment if necessary. In essence, this implements a “receiver-makes-right” approach.


Figure 3.2 Transfer order of image data bytes

The order in which the sample values in a frame are transmitted is illustrated in Figure 3.2. As can be seen, the values are transmitted row by row and each row is transmitted from left-most to right-most column. The left-to-right, top-to-bottom transmission order applies when the image is viewed in its normal orientation (as it would be displayed on a screen, for example).

If a frame contains multiple channels, then the channels are transmitted in an interleaved fashion. Figure 3.3 illustrates this for the case where a frame contains a complete red/green/blue image with a bit-depth of 8. For a bit depth of 1, each byte contains 8 sample values of a single channel. In other words, a bit depth 1 frame is transmitted in a byte interleaved fashion.


Figure 3.3 Bit and byte order of image data

When transmitting an image frame by frame, the frontend needs to know what part of the image a frame represents (and how many frames it should expect). For that purpose, the SANE API tags every frame with a type. This version of the SANE standard supports the following frame types:

SANE_FRAME_GRAY: The frame contains a single channel of data that represents sample values from a spectral band that covers the human visual range. The image consists of this frame only.

SANE_FRAME_RGB: The frame contains three channels of data that represent sample values from the red, green, and blue spectral bands. The sample values are interleaved in the order red, green, and blue. The image consists of this frame only.

SANE_FRAME_RED: The frame contains one channel of data that represents sample values from the red spectral band. The complete image consists of three frames: SANE_FRAME_RED, SANE_FRAME_GREEN, and SANE_FRAME_BLUE. The order in which the frames are transmitted chosen by the backend.

SANE_FRAME_GREEN: The frame contains one channel of data that represents sample values from the green spectral band. The complete image consists of three frames: SANE_FRAME_RED, SANE_FRAME_GREEN, and SANE_FRAME_BLUE. The order in which the frames are transmitted chosen by the backend.

SANE_FRAME_BLUE: The frame contains one channel of data that represents sample values from the blue spectral band. The complete image consists of three frames: SANE_FRAME_RED, SANE_FRAME_GREEN, and SANE_FRAME_BLUE. The order in which the frames are transmitted chosen by the backend.

In frames of type SANE_FRAME_GRAY, when the bit depth is 1 there are only two sample values possible, 1 represents minimum intensity (black) and 0 represents maximum intensity (white). For all other bit depth and frame type combinations, a sample value of 0 represents minimum intensity and larger values represent increasing intensity.

The combination of bit depth 1 and SANE_FRAME_RGB (or SANE_FRAME_RED, SANE_FRAME_GREEN, SANE_FRAME_BLUE) is rarely used and may not be supported by every frontend.