kopia lustrzana https://gitlab.com/sane-project/standard
239 wiersze
11 KiB
ReStructuredText
239 wiersze
11 KiB
ReStructuredText
.. _chap:environ:
|
||
|
||
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.
|
||
|
||
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
|
||
:func:`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:: figs/hierarchy.*
|
||
:name: fig:hierarchy
|
||
:scale: 100%
|
||
:align: center
|
||
|
||
Example SANE Hiearchy
|
||
|
||
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
|
||
:numref:`fig:hierarchy`. 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.
|
||
|
||
.. index:: image data format
|
||
.. _sec:imageformat:
|
||
|
||
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).
|
||
|
||
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.
|
||
|
||
**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:: figs/xfer.*
|
||
:name: fig:xfer
|
||
:scale: 50%
|
||
:align: center
|
||
|
||
Transfer order of image data bytes
|
||
|
||
The order in which the sample values in a frame are transmitted is
|
||
illustrated in :numref:`fig:xfer`. 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. :numref:`fig:pixels`
|
||
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:: figs/image-data.*
|
||
:name: fig:pixels
|
||
:scale: 80%
|
||
:align: center
|
||
|
||
Bit and byte order or 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:
|
||
|
||
:macro:`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.
|
||
|
||
:macro:`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.
|
||
|
||
:macro:`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: :macro:`SANE_FRAME_RED`,
|
||
:macro:`SANE_FRAME_GREEN`, and
|
||
:macro:`SANE_FRAME_BLUE`. The order in which the
|
||
frames are transmitted chosen by the backend.
|
||
|
||
:macro:`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: :macro:`SANE_FRAME_RED`,
|
||
:macro:`SANE_FRAME_GREEN`, and
|
||
:macro:`SANE_FRAME_BLUE`. The order in which the
|
||
frames are transmitted chosen by the backend.
|
||
|
||
:macro:`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: :macro:`SANE_FRAME_RED`,
|
||
:macro:`SANE_FRAME_GREEN`, and
|
||
:macro:`SANE_FRAME_BLUE`. The order in which the
|
||
frames are transmitted chosen by the backend.
|
||
|
||
In frames of type :macro:`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.
|