最近由于工作需要,要写一套扫描相关的接口。
在这里记录一下,实现还有有点复杂的。
目录
依赖
sudo apt install libsane-dev sane-utils
主要功能
初始化
我们在操作扫描仪之前需要初始化才能正常使用。
初始化使用的是sane里的sane_init。
void scanner_init()
{
printf("[%s] Start\n", __FUNCTION__);
SANE_Int version_code = 0;
sane_init(&version_code, auth_callback);
printf("SANE version code: %d\n", version_code);
}
static void
auth_callback(SANE_String_Const resource,
SANE_Char *username, SANE_Char *password)
{
}
初始化成功则version_code为SANE_STATUS_GOOD(0)。
获取当前扫描仪列表
核心是sane_get_devices函数。
先通过sane_get_devices获取扫描仪列表,然后申请一个二维数组,将扫描仪列表放入二维数组中返回。
const char **scanner_get_available_list()
{
printf("[%s] Start\n", __FUNCTION__);
SANE_Status status;
SANE_Int num_devices = 0;
const SANE_Device **device_list;
//获取扫描仪列表
status = sane_get_devices(&device_list, SANE_FALSE);
if (status != SANE_STATUS_GOOD)
{
printf("Error getting device list: %s\n", sane_strstatus(status));
return NULL;
}
// 获取当前设备数量
while (device_list[num_devices])
num_devices++;
// 如果设备列表为空,返回
if (num_devices == 0)
{
printf("No scanners found.\n");
sane_exit();
return NULL;
}
// 分配内存
const char **scanner_list = malloc(sizeof(SANE_Device *) * (num_devices + 1));
if (!scanner_list)
{
printf("Failed to allocate memory.\n");
sane_exit();
return NULL;
}
// 继续分配内存
for (int i = 0; i < num_devices; i++)
{
scanner_list[i] = strdup(device_list[i]->name);
if (!scanner_list[i])
{
printf("Failed to allocate memory.\n");
for (int j = 0; j < i; j++)
{
free(scanner_list[j]);
}
free(scanner_list);
sane_exit();
return NULL;
}
}
scanner_list[num_devices] = NULL;
// 返回设备列表
return scanner_list;
}
我们再把获取到的设备列表循环打印一下。
const char **scanner_list = scanner_get_available_list();
if (scanner_list != NULL)
{
for (int num_devices = 0; scanner_list[num_devices]; ++num_devices)
{
if (scanner_list[num_devices] != NULL) // 添加一个检查
{
printf("Device %d: name=%s \n",
num_devices, scanner_list[num_devices]);
}
}
}
else
{
return;
}
打开扫描仪
sane_open
这里介绍一下sane_open,我们打开扫描仪主要是用sane中的这个api。
它的第一个参数是扫描仪的名称,第二个参数是一个空的句柄,打开后通过句柄进行后续操作。
extern SANE_Status sane_open (SANE_String_Const devicename,
SANE_Handle * handle);
函数的具体实现如下:
static SANE_Handle sane_handle = NULL; // 扫描仪设备句柄,全局变量
int scanner_open_device(char *scanner_name)
{
printf("[%s] Start\n", __FUNCTION__);
SANE_Status sane_status = 0;
if (sane_status = sane_open(scanner_name, &sane_handle))
{
printf("sane_open status: %s\n", sane_strstatus(sane_status));
}
if (sane_status != SANE_STATUS_GOOD)
sane_handle = NULL;
return sane_status;
}
这里的入参scanner_name是获取扫描仪列表的scanner_list,如果要打开第一个扫描仪的话是入参是scanner_list[0]。
如果函数的返回值不是SANE_STATUS_GOOD,表示打开失败了。
设置扫描选项
sane_control_option
扫描的所有参数都是通过sane_control_option实现的,每个参数的功能详见备注。
extern SANE_Status sane_control_option (SANE_Handle handle, //sane_open的句柄
SANE_Int option, //要设置选项的序号,2是颜色,3是分辨率
SANE_Action action, //操作的类型,给选项赋值或者获取当前值
void *value, //value的实际值
SANE_Int *info); //没发现有什么用
操作的类型一共有以下三种,我们这里只用到第二种。
typedef enum
{
SANE_ACTION_GET_VALUE = 0,
SANE_ACTION_SET_VALUE,
SANE_ACTION_SET_AUTO
}
SANE_Action;
我这里设置了颜色,扫描的分辨率和纸张大小,还有很多可以设置的选项,可以自行探索。
static SANE_Handle sane_handle = NULL; // 扫描仪设备句柄,全局变量
// 设置指定扫描仪颜色,通过传入参数val_color进行设置扫描设备的颜色
int scanner_set_color(SANE_String val_color)
{
printf("[%s] Start!\n", __FUNCTION__);
SANE_Status status;
status = sane_control_option(sane_handle, 2,
SANE_ACTION_SET_VALUE, val_color, NULL);
if (status != SANE_STATUS_GOOD)
{
printf("Option did not set, desc = %s\n", sane_strstatus(status));
return statu

因工作需要,博主记录了在Linux下实现扫描相关接口的过程。介绍了使用SANE API的主要功能,包括初始化、获取扫描仪列表、打开扫描仪、设置扫描选项、扫描、关闭设备等,还提及单页单面和多页双面扫描的区别及扫描文件的生成。
最低0.47元/天 解锁文章
2861

被折叠的 条评论
为什么被折叠?



