/*
Copyright © Simon Meaden 2019.
This file was developed as part of the QScan cpp library but could
easily be used elsewhere.
QScan is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QScan is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QScan. If not, see <http://www.gnu.org/licenses/>.
It is also available on request from Simon Meaden simonmeaden@sky.com.
*/
#include "saneworker.h"
#include <memory>
#include <stdlib.h>
SaneWorker::SaneWorker(QObject* parent)
: QObject(parent)
{}
void SaneWorker::scan(ScanDevice* device)
{
qDebug()<<"scan";
SANE_Status status;
SANE_Parameters parameters;
status = sane_open(device->name.toStdString().c_str(), &m_sane_handle);
QImage image;
if (status != SANE_STATUS_GOOD) {
emit scanFailed();
return;
}
status = sane_start(m_sane_handle);
if (status != SANE_STATUS_GOOD) {
emit scanFailed();
return;
}
status = sane_get_parameters(m_sane_handle, ¶meters);
if (status != SANE_STATUS_GOOD) {
emit scanFailed();
return;
}
int len;
int full_size = 0;
bool first_frame = true;
// SANE_Byte min = 0xff, max = 0;
SANE_Word total_bytes = 0;
// SANE_Word expected_bytes;
// SANE_Int hang_over = -1;
SANE_Int buffer_size = (32 * 1024);
std::unique_ptr<uchar[]> buffer(new uchar[ulong(buffer_size)]);
// SANE_Byte* buffer[buffer_size];
QImage::Format format = QImage::Format_RGB32;
full_size = parameters.bytes_per_line * parameters.lines;
if (first_frame) {
int offset = 0;
bool must_buffer = true;
bool greyscale = false;
switch (parameters.format) {
case SANE_FRAME_RED:
case SANE_FRAME_GREEN:
case SANE_FRAME_BLUE:
if (parameters.depth == 8) {
must_buffer = true;
offset = parameters.format - SANE_FRAME_RED;
format = QImage::Format_RGB32;
full_size *= 3;
//emit log(LogLevel::WARN, tr("Sane frame RED/GREEN/BLUE"));
break;
}
//emit log(LogLevel::WARN, tr("Sane frame RED/GREEN/BLUE but depth not 8"));
emit scanFailed();
return;
case SANE_FRAME_RGB:
if (parameters.depth == 8) {
format = QImage::Format_RGB32;
//emit log(LogLevel::WARN, tr("Sane frame RGB depth 8"));
break;
} else if (parameters.depth == 16) {
format = QImage::QImage::Format_RGBX64;
//emit log(LogLevel::WARN, tr("Sane frame RGB depth 16"));
break;
}
emit scanFailed();
return;
case SANE_FRAME_GRAY:
if (parameters.depth == 1) {
format = QImage::Format_Grayscale8;
// if (parameters.lines < 0) {
// must_buffer = true;
// offset = 0;
// }
// //emit log(LogLevel::WARN, tr("Sane frame Mono depth 1"));
break;
} else if (parameters.depth == 8) {
format = QImage::Format_Grayscale8;
greyscale = true;
if (parameters.lines < 0) {
must_buffer = true;
offset = 0;
}
// //emit log(LogLevel::WARN, tr("Sane frame Grey depth 8"));
break;
} else if (parameters.depth == 16) {
// QImage doesn't have a 16 bit greyscale
// so use RGB and set all three channels
// to the same value.
format = QImage::Format_RGBX64;
greyscale = true;
if (parameters.lines < 0) {
must_buffer = true;
offset = 0;
}
// //emit log(LogLevel::WARN, tr("Sane frame Grey depth 16"));
break;
} else {
emit scanFailed();
return;
}
}
image = QImage(parameters.pixels_per_line, parameters.lines, format);
} else {
// TODO not first frame ?
}
int progress;
int x = 0, y = 0;
quint32 value;
while (true) {
status = sane_read(m_sane_handle, buffer.get(), buffer_size, &len);
if (status == SANE_STATUS_GOOD) {
if (len > 0) {
total_bytes += SANE_Word(len);
progress = int((total_bytes * 100.0) / double(full_size));
emit scanProgress(progress);
if (parameters.format == SANE_FRAME_RGB) {
if (format == QImage::Format_RGB32) {
for (int i = 0; i < len; i += 3) {
if (x > 0 && ((x + 1) % parameters.pixels_per_line) == 0) {
x = 0;
y++;
} else {
x++;
}
value = 0xff000000;
quint32 c1 = buffer[ulong(i)];
c1 = c1 << 16;
quint32 c2 = buffer[ulong(i + 1)];
c2 = c2 << 8;
quint8 c3 = buffer[ulong(i + 2)];
value += c1 + c2 + c3;
image.setPixel(x, y, value);
}
} else if (format == QImage::Format_RGBX64) {
}
} else {
// SANE_FRAME_RED,GREEN & BLUE
// TODO - Multi frame scans.
}
}
}
if (total_bytes == full_size) {
break;
}
}
// //emit log(LogLevel::INFO, tr("Scan has completed"));
sane_close(m_sane_handle);
m_sane_handle = nullptr;
emit scanCompleted(image, device->options->resolution());
// emit finished();
// emit scanFailed();
// return;
}
void SaneWorker::setResolution(ScanDevice* device,
const SANE_Option_Descriptor* option,
SANE_Int option_id)
{
switch (option->unit) {
case SANE_UNIT_MM:
device->options->setUnits(ScanUnits::MM);
break;
case SANE_UNIT_DPI:
device->options->setUnits(ScanUnits::DPI);
break;
}
QVariant min_max;
if (option->constraint_type == SANE_CONSTRAINT_RANGE) {
ScanRange range{};
switch (option->type) {
case SANE_TYPE_INT:
range.min = option->constraint.range->min;
range.max = option->constraint.range->max;
break;
case SANE_TYPE_FIXED:
range.min = SANE_UNFIX(option->constraint.range->min);
range.max = SANE_UNFIX(option->constraint.range->max);
break;
default:
break;
}
min_max.setValue(range);
} else if (option->constraint_type == SANE_CONSTRAINT_WORD_LIST) {
QList<int> list;
switch (option->type) {
case SANE_TYPE_INT: {
for (int i = 1; i < option->constraint.word_list[0]; i++) {
list.append(option->constraint.word_list[i]);
}
break;
}
case SANE_TYPE_FIXED: {
for (int i = 1; i < option->constraint.word_list[0]; i++) {
list.append(SANE_UNFIX(option->constraint.word_list[i]));
}
break;
}
default:
break;
}
min_max.setValue(list);
}
device->options->setResulutionRange(min_max);
int value = -1;
SANE_Status status =
sane_control_option(device->sane_handle, option_id, SANE_ACTION_GET_VALUE, &value, nullptr);
if (status == SANE_STATUS_GOOD) {
switch (option->type) {
case SANE_TYPE_INT:
device->options->setResolution(value);
break;
case SANE_TYPE_FIXED:
device->options->setResolution(SANE_UNFIX(value));
break;
default:
break;
}
}
}
void SaneWorker::loadAvailableScannerOptions(ScanDevice* device)
{
QMutexLocker locker(&m_mutex);
SANE_Handle sane_handle;
SANE_Status status;
SANE_Int number_of_options = 0;
SANE_Int option_id = 1;
SANE_Int info;
if (!device || device->name.isEmpty()) {
return;
}
status = sane_open(device->name.toStdString().c_str(), &sane_handle);
device->sane_handle = sane_handle;
if (status != SANE_STATUS_GOOD) {
emit s
没有合适的资源?快使用搜索试试~ 我知道了~
Linux下调用扫描仪Sane协议
共77个文件
h:65个
cpp:5个
gitignore:3个
4星 · 超过85%的资源 需积分: 0 70 下载量 141 浏览量
2022-04-26
08:56:42
上传
评论 1
收藏 153KB ZIP 举报
温馨提示
linux下通过sane协议调用扫描仪,基于qt建立的工程。 可驱动扫描仪扫描图像,并可设置参数。
资源详情
资源评论
资源推荐
收起资源包目录
QT_SANE.zip (77个子文件)
QT_SANE
QT_SANE.pro.user 44KB
sane
sanei_pa4s2.h 7KB
sanei_jinclude.h 3KB
sanei_net.h 3KB
sanei_pp.h 6KB
sanei_codec_ascii.h 2KB
sanei_ab306.h 2KB
sanei.h 5KB
sanei_thread.h 6KB
sanei_codec_bin.h 2KB
sanei_lm983x.h 5KB
sanei_debug.h 4KB
sanei_scsi.h 12KB
sanei_pv8630.h 3KB
sanei_wire.h 4KB
sanei_config.h 6KB
sanei_jpeg.h 2KB
sanei_tcp.h 1KB
sanei_cderror.h 5KB
sane.h 8KB
sanei_ir.h 14KB
sanei_auth.h 3KB
.gitignore 30B
sanei_access.h 3KB
sanei_backend.h 5KB
sanei_magic.h 8KB
sanei_pio.h 2KB
saneopts.h 20KB
sanei_udp.h 1KB
sanei_usb.h 19KB
QLibSane.h 2KB
include
md5.h 5KB
lgetopt.h 6KB
sane
sanei_pa4s2.h 7KB
sanei_jinclude.h 3KB
sanei_net.h 3KB
sanei_pp.h 6KB
sanei_codec_ascii.h 2KB
sanei_ab306.h 2KB
sanei.h 5KB
sanei_thread.h 6KB
sanei_codec_bin.h 2KB
sanei_lm983x.h 5KB
sanei_debug.h 4KB
sanei_scsi.h 12KB
sanei_pv8630.h 3KB
sanei_wire.h 4KB
sanei_config.h 6KB
sanei_jpeg.h 2KB
sanei_tcp.h 1KB
sanei_cderror.h 5KB
sane.h 8KB
sanei_ir.h 14KB
sanei_auth.h 3KB
.gitignore 30B
sanei_access.h 3KB
sanei_backend.h 5KB
sanei_magic.h 8KB
sanei_pio.h 2KB
saneopts.h 20KB
sanei_udp.h 1KB
sanei_usb.h 19KB
lassert.h 2KB
font_6x11.h 66KB
lalloca.h 2KB
Makefile.am 903B
.gitignore 22B
unix
sanelibrary.h 4KB
saneworker.h 3KB
saneworker.cpp 19KB
sanelibrary.cpp 13KB
QLibSane.cpp 6KB
main.cpp 2KB
mainwindow.ui 4KB
mainwindow.cpp 7KB
mainwindow.h 1KB
QT_SANE.pro 1KB
共 77 条
- 1
奔跑的程序猿_Forrest
- 粉丝: 5
- 资源: 4
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论1