在Ubuntu上用sane api实现通用扫描功能

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

最近由于工作需要,要写一套扫描相关的接口。

在这里记录一下,实现还有有点复杂的。

目录

依赖

主要功能

初始化

获取当前扫描仪列表

打开扫描仪

 sane_open

设置扫描选项

sane_control_option

扫描

关闭设备

结束使用

参考资料


依赖

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值