SANE (Scanner Access Now Easy)是Linux平台用于访问扫描仪的接口。这里分享下如何用C语言来编写一个最简单的扫描应用。
SANE下载
安装SANE:
sudo apt-get update
sudo apt-get install sane
下载源码。
在Ubuntu和树莓派上扫描文档
准备工作
- 阅读官方文档。
- 学习scanimage.c。
SANE工作流程
代码实现
SANE初始化:
void init()
{
SANE_Int version_code = 0;
sane_init (&version_code, auth_callback);
printf("SANE version code: %d\n", version_code);
}
查询所有连接设备。这里会比较耗时:
SANE_Status get_devices(const SANE_Device ***device_list)
{
printf("Get all devices...\n");
SANE_Status sane_status = 0;
if (sane_status = sane_get_devices (device_list, SANE_FALSE))
{
printf("sane_get_devices status: %s\n", sane_strstatus(sane_status));
}
return sane_status;
}
使用设备名字打开设备:
SANE_Status open_device(SANE_Device *device, SANE_Handle *sane_handle)
{
SANE_Status sane_status = 0;
printf("Name: %s, vendor: %s, model: %s, type: %s\n", device->name, device->model, device->vendor, device->type);
if (sane_status = sane_open(device->name, sane_handle))
{
printf("sane_open status: %s\n", sane_strstatus(sane_status));
}
return sane_status;
}
扫描文档:
SANE_Status start_scan(SANE_Handle sane_handle, SANE_String_Const fileName)
{
SANE_Status sane_status = 0;
device = sane_handle;
return do_scan(fileName);
}
扫描之后保存为pnm格式的文件。先写文件头:
static void write_pnm_header (SANE_Frame format, int width, int height, int depth, FILE *ofp)
{
switch (format)
{
case SANE_FRAME_RED:
case SANE_FRAME_GREEN:
case SANE_FRAME_BLUE:
case SANE_FRAME_RGB:
fprintf (ofp, "P6\n# SANE data follows\n%d %d\n%d\n", width, height, (depth <= 8) ? 255 : 65535);
break;
default:
if (depth == 1)
fprintf (ofp, "P4\n# SANE data follows\n%d %d\n", width, height);
else
fprintf (ofp, "P5\n# SANE data follows\n%d %d\n%d\n", width, height,(depth <= 8) ? 255 : 65535);
break;
}
}
不断的读取数据写入到文件中:
while (1)
{
double progr;
status = sane_read (device, buffer, buffer_size, &len);
total_bytes += (SANE_Word) len;
progr = ((total_bytes * 100.) / (double) hundred_percent);
if (progr > 100.)
progr = 100.;
if (status != SANE_STATUS_GOOD)
{
if (status != SANE_STATUS_EOF)
{
return status;
}
break;
}
if ((parm.depth != 16))
fwrite (buffer, 1, len, ofp);
else
{
#if !defined(WORDS_BIGENDIAN)
int i, start = 0;
/* check if we have saved one byte from the last sane_read */
if (hang_over > -1)
{
if (len > 0)
{
fwrite (buffer, 1, 1, ofp);
buffer[0] = (SANE_Byte) hang_over;
hang_over = -1;
start = 1;
}
}
/* now do the byte-swapping */
for (i = start; i < (len - 1); i += 2)
{
unsigned char LSB;
LSB = buffer[i];
buffer[i] = buffer[i + 1];
buffer[i + 1] = LSB;
}
/* check if we have an odd number of bytes */
if (((len - start) % 2) != 0)
{
hang_over = buffer[len - 1];
len--;
}
#endif
fwrite (buffer, 1, len, ofp);
}
关闭设备:
void close_device(SANE_Handle sane_handle)
{
sane_close(sane_handle);
}
释放所有资源:
void exit()
{
sane_exit();
}
编译工程
Ubuntu上生成SANE动态链接库的符号链接:
sudo ln –s /usr/lib/x86_64-linux-gnu/libsane.so.1 /usr/lib/libsane.so
树莓派上:
sudo ln –s /usr/lib/arm-linux-gnueabihf/libsane.so.1 /usr/lib/libsane.so
makefile中修改头文件路径:
SANE_INCLUDE=<Your SANE Package Path>/include
编译工程:
make
执行程序:
sudo ./hellosane
最后用GIMP打开pnm文件。
源码
https://github.com/yushulx/linux-document-scanning