SANE 扫描仪接口

作者:David Mosberger

SANE 代表 “Scanner Access Now Easy”(现在轻松访问扫描仪)。它是一个通用接口,使您能够从任何产生栅格图像的设备获取图像,包括平板扫描仪、视频和静态相机以及帧捕获器。SANE 的目的是使编写图像处理应用程序成为可能,而无需担心各个设备的特殊性。从另一方面来看,SANE 使编写设备驱动程序一次且仅一次成为可能。然后,任何符合 SANE 标准的应用程序都可以使用同一个设备驱动程序。

SANE 简介

您是否曾经想在 Linux 下扫描图像?如果是这样,您可能知道面对令人眼花缭乱的扫描仪驱动程序包的感觉。在撰写本文时,至少存在十四种不同的 Linux 扫描仪软件包。虽然每个单独的软件包通常质量都很高,但通常很难确定哪个软件包应该用于哪个扫描仪。此外,一些软件包带有命令行界面,另一些包括基于 Tcl/Tk 的图形前端,还有一些则带有功能齐全的图形前端。虽然据说多样性使生活充满乐趣,但在这种情况下,它更有可能引起严重的头痛。

创建 SANE 是为了解决这个难题。基本思想很简单:如果有一个通用且定义明确的应用程序编程接口 (API),那么就可以轻松地独立于扫描仪驱动程序编写应用程序。因此,新的扫描仪驱动程序的作者不必担心为驱动程序编写应用程序。应用程序程序员也有好处;由于 SANE 是通用的,因此可以独立于最终将控制的设备编写应用程序。假设我们希望五个应用程序支持十个不同的设备。使用旧方法,将需要编写 5*10=50 个程序。使用 SANE,只需要编写 5+10=15 个程序。SANE 对用户也有好处。它使用户可以自由选择自己最喜欢的应用程序,并且一个应用程序可以用于控制用户可以访问的所有图像采集设备。因此,SANE 使呈现相同一致的界面成为可能,而与正在使用的特定设备无关。

当然,SANE 并不是创建这种通用接口的第一次尝试。您可能听说过 TWAIN、PINT 或 Linux 手持扫描仪接口。问题在于,这些较旧的接口在某些方面被证明是不足的。例如,PINT 实际上是一个有些原始的内核级接口,而手持扫描仪接口按定义仅限于手持扫描仪。相比之下,SANE 足够通用,可以支持任何采集栅格图像的设备。最接近 SANE 的可能是 TWAIN。两者押韵并非巧合,但这又是另一个故事了。TWAIN 不是 SANE 的主要原因是 TWAIN 将控制设备的图形用户界面放在驱动程序中,而不是应用程序中。这使其不适合 Linux 或网络环境,在这些环境中,扫描仪驱动程序可能在一台机器上运行,而应用程序在另一台机器上运行。相比之下,SANE 强制将实际驱动程序与其控件的用户界面严格分离。实际上,当前的 SANE 发行版包括对网络透明扫描的支持。

使用 SANE

要开始使用 SANE,请从 ftp 目录 ftp://ftp.mostang.com/pub/sane/ 获取最新版本的发行版。

如果您想构建 SANE 附带的图形用户界面程序,您还需要获取、构建和安装 GIMP,或者至少安装 GTK 发行版。GIMP 和 GTK 都可以在 ftp://ftp.gimp.org/ 上找到。GTK 是最初为 GIMP 开发的用户界面工具包,但现在已被许多其他项目采用,包括 SANE。请注意,即使没有 GIMP/GTK 库,SANE 发行版也可以正常构建。但是,这样就不会构建任何漂亮的图形用户界面程序,从而大大降低了乐趣。因此,除非您仅为服务器构建 SANE,否则我建议您至少安装 GTK,如果不是 GIMP 的话。

获取 SANE 发行版后,解压缩压缩的 tar 文件,并按照 README 文件中的说明进行操作。README 解释了如何构建和安装 SANE。另外,请查看名为 PROBLEMS 的文件;它包含已知问题及其解决方法列表。

请注意,您不必拥有扫描仪或相机即可玩 SANE。该发行版包含一个伪驱动程序,该驱动程序通过读取可移植的 “anymap” (PNM) 文件来模拟扫描仪。此外,SANE 不仅限于 Linux。除了用于 Alpha、x86 和 m68k 的 Linux 之外,它还包括对 AIX、Digital Unix、FreeBSD、HP-UX、IRIX、NetBSD、SCO、Solaris、SunOS 甚至 OS/2 的支持。

安装 SANE 后,您应该能够键入命令

scanimage --list-devices

并获得如下所示的输出

device `mustek:/dev/scanner' is a Mustek MFC-06000CZ flatbed scanner
device `pnm:0' is a Noname PNM file reader virtual device
device `pnm:1' is a Noname PNM file reader virtual device
如列表所示,在这种特定情况下,Mustek 扫描仪在名称 mustek:/dev/scanner 下可用,并且两个名为 pnm:0 和 pnm:1 的伪设备可用,可用于读取 PNM 文件。要获取特定设备(例如 pnm:0)的所有选项列表,只需键入
scanimage --device pnm:0 --help
这将生成 列表 1 中显示的帮助消息。

SANE 软件包附带详细的 man 页面,其中解释了 scanimage 程序的具体细节。例如,假设我们有一个名为 input.ppm 的 PPM 文件。我们可以使用 scanimage 程序 “扫描” 该图像,并通过以下命令将其亮度提高 50%

scanimage --device pnm --brightness
50 input.ppm > out.pnm

如果您使用诸如 xv 之类的图像查看器查看文件 out.pnm,您应该能够看到 output.ppm 明显更亮。

您可能会说:酷,但是图形用户界面在哪里?假设您在构建 SANE 时安装了 GTK 库,则可以调用名为 xscanimage 的程序,该程序将向您显示一个对话框,其中包含可用设备列表。如果您双击 “pnm:0” 条目,您将获得图 1 中所示的对话框。如您所见,该对话框包括两个标记为 “Filename” 的文本输入框和一个标记为 “Brightness” 的滑块。如果您在第一个文本输入框中输入 “out.pnm”,在第二个框中输入 “input.ppm”,并将亮度滑块移动到 50.0,则可以按左下角的 Scan 按钮,获得与上面所示的 scanimage 命令行相同的结果。当然,在进行实际扫描之前,您可以按右下角的 Preview 按钮弹出一个预览窗口(参见图 2)。在预览窗口中,您可以按 Acquire<\!s>Preview 按钮以获得最终图像的低分辨率预览。例如,通过移动亮度滑块,您可以看到图像的亮度如何受到影响。移动滑块后,您需要按 Acquire Preview 按钮以获得更新的预览。

图 1. SANE 对话窗口

图 2. SANE 预览窗口

当使用真正的扫描仪或相机扫描图像时,您通常希望以各种方式增强它,例如使其看起来更清晰。xscanimage 程序的优点在于,它也可以作为 GIMP 扩展运行。为此,只需从 GIMP 插件目录创建一个指向 xscanimage 二进制文件的符号链接。假设 SANE 安装默认值,您可以使用以下命令执行此操作

ln -s /usr/local/bin/xscanimage ~/.gimp/plug-ins

创建此链接后,下次启动 GIMP 时,xscanimage 将自身附加到 GIMP 的 “Xtns” 菜单。这样就可以通过选择 “Xtns->Acquire Image->pnm:0” 来调用 PNM 伪设备。以这种方式调用时,按下 Scan 按钮会将新扫描的图像放入 GIMP 窗口中(而不是将其保存到磁盘)。现在,可以使用常用的 GIMP 图像处理功能来增强采集的图像,然后再保存它。

2395f1.gif

图 3. xscanimage 的 Mustek 对话窗口

PNM 伪设备可能很有趣,但真正的扫描仪界面是什么样的呢?图 3 显示了 Mustek 平板扫描仪的 xscanimage 对话框。该图还演示了 xscanimage 的另一个功能:工具提示(也称为 “气球帮助”)。工具提示使新用户更容易熟悉其扫描仪或相机的性能。在图中,鼠标指向 Scan<\!s>Source 菜单,因此,该菜单的帮助信息显示在鼠标指针下方的黄色框中。工具提示对于新用户来说很方便,但是过一段时间后,它们往往会妨碍您。因此,xscanimage 允许高级用户使用 Preferences 子菜单关闭工具提示。

如您所见,Mustek 对话框看起来与 PNM 伪设备界面截然不同。这是因为底层设备具有不同的功能。实际上,设备对话框不仅取决于所选设备,还取决于设备的模式。例如,当打开对话框底部附近的 “Use custom gamma table”(使用自定义伽玛表)选项时,界面会发生变化,结果如图 4 所示。如您所见,对话框的右半部分现在包含一个图形编辑器,允许用户修改强度、红色、绿色或蓝色伽玛表。换句话说,xscanimage 精确地显示了对于给定扫描模式处于活动状态或有意义的选项,从而大大降低了用户混淆的可能性。

2395f2.gif

图 4. 带有伽玛表编辑器的 Mustek 对话框

查看图中右半部分的图像强度伽玛表,您可能会想到每次启动 xscanimage 时都定义伽玛表会相当烦人。一旦找到理想的表,如果可以保存它们就好了。为此,xscanimage 允许通过 Preferences 子菜单中的条目保存当前的设备设置。保存后,每次启动 xscanimage 时,它都会自动恢复该设备的上次保存的选项值。

SANE 还附带什么?

现在您已经了解了如何使用 SANE 发行版附带的一些程序,现在是时候告诉您还包括什么了。在撰写本文时,该软件包包括以下设备的驱动程序

  • Connectix QuickCam(彩色和单色)

  • 一些 Epson SCSI 扫描仪

  • Hewlett-Packard ScanJet SCSI 扫描仪

  • Microtek SCSI 扫描仪

  • Mustek SCSI 平板扫描仪(支持单程和三程扫描仪)

  • PINT 设备:PINT 是 NetBSD、OpenBSD 和 SunOS 的 Unix 内核接口。SANE 的 PINT 驱动程序提供对任何具有 PINT 支持的扫描仪的访问

  • 大多数 UMAX SCSI 扫描仪

计划支持更多其他扫描仪和相机,其中一些应该在您阅读本文时准备就绪。有关最新信息,请访问资源中列出的网页。

可用的应用程序是命令行 scanimage、图形化 xscanimage(独立或作为 GIMP 扩展)和 xcam,xcam 是适用于产生连续图像流的相机(例如 Connectix QuickCam)的图形用户界面。

此外,还有用于 Python 和 Java API 的 SANE API 绑定,以及名为 saned 的网络守护程序,该守护程序提供对远程设备的网络透明访问。假设您具有适当的权限,这使得从欧洲运行的机器控制在美国运行的相机成为可能——所有这些都归功于 SANE 和互联网。

它是如何工作的?

构建 SANE 应用程序时,必须将其链接到名为 libsane.so 的共享库。实际上,libsane.so 只是指向 SANE 驱动程序之一的符号链接。由于每个 SANE 驱动程序都导出完全相同的接口,因此您可以随时更改 libsane.so 符号链接,并有效地更改应用程序正在使用的驱动程序。虽然这在允许升级到不同的驱动程序而无需重新链接所有应用程序方面很有用,但是如果您每次希望切换扫描设备时都必须更改符号链接,那将非常不方便。因此,SANE 支持两个名为 dllnet 的伪驱动程序。它们是伪驱动程序,因为它们不是与物理设备对话,而是与其他 SANE 驱动程序对话,如图 5 所示。

对于机器 A,libsane.so 符号链接指向 dll 伪驱动程序(称为 libsane-dll.so)。该伪驱动程序使用动态链接库 (dll) 来访问其他 SANE 驱动程序。在示例中,dll 配置为使用 pnm、mustek 和 net 驱动程序。net 驱动程序又是伪驱动程序;它通过连接到机器 B 上运行的 SANE 守护程序 (saned) 来提供对远程扫描仪的访问。机器 B 又再次使用 dll 来提供对各种其他驱动程序的访问。您可能会想到,确切的配置完全取决于机器 A 和 B 的系统管理员。libsane.so 成为指向 dll 伪驱动程序的符号链接是很典型的,但是没有理由不能指向 net 伪驱动程序或仅指向 mustek 驱动程序。当然,在后一种情况下,这意味着应用程序只能访问 mustek 驱动程序——但这对于某些环境来说是完全合理的。

图 5. 可能的 SANE 层次结构

这种方法非常灵活,但这提出了一个有趣的问题:在这种环境中我们如何命名设备?答案是每个真正的驱动程序都有自己的设备命名空间。例如,Mustek 和 HP 驱动程序使用 Unix 特殊设备控制设备的路径,例如 /dev/scanner。对于伪驱动程序,事情变得更有趣。由于 dll 必须保证每个设备名称都是唯一的,因此它只需在每个从属设备名称前面加上从属驱动程序的名称,并用冒号分隔。因此,在机器 A 上,Mustek 扫描仪将被称为 mustek:/dev/scanner。net 伪驱动程序执行类似的操作:它在远程设备名称前面加上远程主机名(再次使用冒号作为分隔符)。例如,机器 B 上的 HP 扫描仪 1 将在机器 A 上以名称 net:B.domain.com:hp:/dev/scanner1 显示。虽然这并没有产生世界上最漂亮的名称,但名称中包含的信息实际上非常有用。本质上,很像 Unix 路径名,设备名称传达了通过 SANE 层次结构通向特定设备的路径。例如,如果您知道机器 B 已关闭,那么很明显 net:B.domain.com:hp:/dev/scanner1 也将关闭。如果有人对这些名称感到不满,应用程序可以允许用户或系统管理员定义更简洁的别名。例如,应用程序可以允许用户将上述设备重命名为 “HP Scanner 1”,这对于初学者来说可能更容易。

使用 SANE 编程

按照定义,SANE 的好坏仅取决于使用它的程序。这意味着使用 SANE 的应用程序和设备越多越好。SANE 发行版附带详细的文档,解释了 SANE API;但是,该接口非常简单。下面列出了六个主要功能

  1. 句柄 <- sane_open(设备名称) 允许您按名称打开 SANE 设备(例如,pnm:0)。

  2. sane_close(句柄) 允许您按名称关闭 SANE 设备。

  3. sane_get_option_descriptor(句柄, 选项号) 用于查询设备可用的控件(例如 PNM 伪驱动程序中的亮度控件)。

  4. sane_control_option(句柄, 选项号, 操作, ) 用于获取或设置选项的值。例如,它可以用于将亮度选项的值设置为 50%。此外,某些选项支持自动模式,驱动程序在其中选择合理的值。对于此类选项,sane_control_option() 也可以用于打开或关闭自动模式。

  5. sane_start(句柄) 用于启动图像的采集。

  6. 读取的字节数 <- sane_read(句柄, 缓冲区, 缓冲区大小) 用于读取实际图像数据,直到采集到整个图像。

SANE API 的设计很简单。目标是使在短时间内完成简单任务成为可能,同时仍然提供足够的功能来支持复杂的驱动程序和应用程序。简单性最好地证明了,将 hpscanpbm 程序转换为 HP 扫描仪的 SANE 驱动程序仅用了两个晚上。另一方面,Mustek 驱动程序和 xscanimage 是相当复杂的程序,而 SANE 可以轻松地容纳它们。

SANE 和商业应用程序/驱动程序

我们对商业 SANE 驱动程序或应用程序的立场是什么?本着 GNU 通用公共许可证的精神,最好提供 SANE 程序的源代码。但是,允许在 Linux 和其他支持动态加载的平台上编写动态加载的商业 SANE 驱动程序。(驱动程序始终是动态加载的,因此这不会导致任何额外的工作。)同样,编写与 libsane.so 共享库链接的商业应用程序也是合适的。支持此立场的基本思想是

  1. 商业程序和免费程序之间的健康竞争是一种资产,而不是一种负担。

  2. SANE 的使用越广泛,对 Linux/Unix 社区越有利。

未来计划

在不久的将来,计划是增加对更多设备的支持。例如,计划支持 Agfa 和 Plustek 扫描仪以及 Nikon 胶片扫描仪驱动程序,并且希望一些更流行的数码相机的驱动程序也将很快实现。为了获得极致的网络连接,还计划在 Java 中实现扫描仪应用程序,从而可以从您最喜欢的启用 Java 的 Web 浏览器控制扫描仪。

从长远来看,将 SANE 推广到包括音频源或录像机在内的其他多媒体设备将很有趣。

换句话说,SANE 才刚刚开始,并且还有许多令人兴奋的项目即将到来。如果您有兴趣参与其中一些项目,请务必通过 SANE 邮件列表与其他开发人员联系(请参阅资源)。

资源

致谢

The SANE Scanner Interface
David 最近获得了亚利桑那大学计算机科学博士学位,现在是 Palo Alto HP 研究实验室的技术人员。David 最初参与 Linux 是因为为软盘磁带驱动器编写 Reed-Solomon 纠错代码。然后他几乎忘记了它,直到他需要一台价格实惠的 Alpha 工作站。那时他开始参与 Linux 移植到 Alpha。从那时起,他一直活跃在自由软件社区中。在不玩电脑的时候,他喜欢与他可爱的妻子共度时光。可以通过电子邮件 David.Mosberger@acm.org 与他联系。
加载 Disqus 评论