完善三种传输方式Native/File/Memory

This commit is contained in:
gb 2022-06-17 11:50:18 +08:00
parent 1581c452ca
commit 712d49809b
7 changed files with 151 additions and 49 deletions

View File

@ -137,7 +137,9 @@ __declspec(novtable) struct IScanImg : public IRef
COM_API_DECLARE(int, channel(void)); COM_API_DECLARE(int, channel(void));
COM_API_DECLARE(SANE_Frame, type(void)); COM_API_DECLARE(SANE_Frame, type(void));
COM_API_DECLARE(unsigned int, bytes(void)); COM_API_DECLARE(unsigned int, bytes(void));
COM_API_DECLARE(unsigned int, header_size(void));
COM_API_DECLARE(unsigned char*, data(unsigned long long off, unsigned int *bytes)); COM_API_DECLARE(unsigned char*, data(unsigned long long off, unsigned int *bytes));
COM_API_DECLARE(int, read(void* buf, size_t* bytes, unsigned long long off = 0));
COM_API_DECLARE(const char*, file(void)); COM_API_DECLARE(const char*, file(void));
COM_API_DECLARE(void, keep_file(bool keep)); COM_API_DECLARE(void, keep_file(bool keep));
COM_API_DECLARE(void, copy_header(SANE_Parameters* head)); COM_API_DECLARE(void, copy_header(SANE_Parameters* head));

View File

@ -203,7 +203,7 @@ unsigned char* mapping_buf::allocate(const wchar_t* file, unsigned long long siz
{ {
buf_ = new unsigned char[size]; buf_ = new unsigned char[size];
is_mem_ = true; is_mem_ = true;
mapped_bytes_ = size; bytes_ = mapped_bytes_ = size;
} }
catch (...) catch (...)
{ {
@ -270,6 +270,36 @@ bool mapping_buf::save(const void* data, size_t* bytes, unsigned long long off)
return ret; return ret;
} }
int mapping_buf::read(void* buf, size_t* bytes, unsigned long long off)
{
if (!bytes)
return SCANNER_ERR_INVALID_PARAMETER;
unsigned int len = *bytes, total = 0;
unsigned char *src = buffer(off, &len),
*dst = (unsigned char*)buf;
int ret = SCANNER_ERR_OUT_OF_RANGE;
while (src)
{
if (len >= *bytes - total)
{
memcpy(dst, src, *bytes - total);
total = *bytes;
ret = SCANNER_ERR_OK;
break;
}
memcpy(dst, src, len);
total += len;
off += len;
len = *bytes - total;
src = buffer(off, &len);
}
*bytes = total;
return ret;
}
void mapping_buf::unmap() void mapping_buf::unmap()
{ {
if (!is_mem_) if (!is_mem_)
@ -287,7 +317,7 @@ void mapping_buf::set_remove_file_when_destroyed(bool rmv)
} }
const char* mapping_buf::file(void) const char* mapping_buf::file(void)
{ {
return is_mem_ ? NULL : file_.c_str(); return is_mem_ ? "" : file_.c_str();
} }
unsigned long long mapping_buf::bytes(void) unsigned long long mapping_buf::bytes(void)
{ {
@ -305,24 +335,38 @@ unsigned int mapping_buf::mapped_bytes(void)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// class scanned_img // class scanned_img
scanned_img::scanned_img(SANE_Parameters head, SANE_Handle dev, int dpi scanned_img::scanned_img(SANE_Parameters head, SANE_Handle dev, int dpi
, const wchar_t* tmp_file, twain_xfer xfer) : head_(head), dpi_(dpi) , const wchar_t* tmp_file, twain_xfer xfer
, SANE_FinalImgFormat *fmt) : head_(head), dpi_(dpi), header_size_(0)
{ {
if (fmt)
fmt_ = *fmt;
else
{
fmt_.img_format = SANE_IMAGE_TYPE_BMP;
fmt_.detail = 0;
}
size_t bytes = line_bytes() * height(); size_t bytes = line_bytes() * height();
std::string h(file_header(SANE_IMAGE_TYPE_BMP, dpi, xfer)); std::string h(file_header(fmt_.img_format, dpi, xfer));
unsigned char* dst = NULL; unsigned char* dst = NULL;
bool ok = false; bool ok = false;
data_ = new mapping_buf(); data_ = new mapping_buf();
header_size_ = h.length();
dst = data_->allocate(tmp_file, bytes + h.length()); dst = data_->allocate(tmp_file, bytes + h.length());
if (dst) if (dst)
{ {
unsigned long long off = 0; unsigned long long off = 0, total = 0;
bytes = h.length(); bytes = h.length();
if (data_->save(h.c_str(), &bytes, off)) if (data_->save(h.c_str(), &bytes, off))
{ {
unsigned int line = line_bytes(), len = line; unsigned int len = line_bytes();
unsigned long long line = line_bytes();
off = data_->bytes() - line; if (xfer == TWAIN_XFER_Memory)
line *= -1;
else
off = data_->bytes() - line;
dst = data_->buffer(off, &len); dst = data_->buffer(off, &len);
int want_to_read = head_.bytes_per_line, rcv = 0, dif = line_bytes() - head_.bytes_per_line; int want_to_read = head_.bytes_per_line, rcv = 0, dif = line_bytes() - head_.bytes_per_line;
@ -330,6 +374,7 @@ scanned_img::scanned_img(SANE_Parameters head, SANE_Handle dev, int dpi
{ {
int r = want_to_read > len - rcv ? len - rcv : want_to_read; int r = want_to_read > len - rcv ? len - rcv : want_to_read;
int ret = hg_sane_middleware::instance()->read(dev, dst + rcv, &r); int ret = hg_sane_middleware::instance()->read(dev, dst + rcv, &r);
total += r;
if (ret != SANE_STATUS_GOOD) if (ret != SANE_STATUS_GOOD)
break; break;
@ -339,9 +384,10 @@ scanned_img::scanned_img(SANE_Parameters head, SANE_Handle dev, int dpi
{ {
want_to_read = head_.bytes_per_line; want_to_read = head_.bytes_per_line;
off -= line; off -= line;
len = line; len = line_bytes();
rcv = 0; rcv = 0;
dst = data_->buffer(off, &len); dst = data_->buffer(off, &len);
total += dif;
} }
else else
{ {
@ -349,13 +395,14 @@ scanned_img::scanned_img(SANE_Parameters head, SANE_Handle dev, int dpi
dst = data_->buffer(off + rcv, &len); dst = data_->buffer(off + rcv, &len);
} }
} }
ok = total + h.length() + dif == data_->bytes();
} }
ok = off == h.length();
} }
if (ok) if (ok)
{ {
if (channel() == 3) if (fmt_.img_format == SANE_IMAGE_TYPE_BMP && channel() == 3 &&
xfer != TWAIN_XFER_Memory)
{ {
// swap RGB // swap RGB
unsigned long long off = 0; unsigned long long off = 0;
@ -393,6 +440,7 @@ scanned_img::scanned_img(SANE_Parameters head, SANE_Handle dev, int dpi
{ {
delete data_; delete data_;
data_ = NULL; data_ = NULL;
header_size_ = 0;
} }
} }
scanned_img::~scanned_img() scanned_img::~scanned_img()
@ -405,7 +453,7 @@ std::string scanned_img::file_header(SANE_ImageType type, float resolution, twai
{ {
std::string h(""); std::string h("");
if (type == SANE_IMAGE_TYPE_BMP) if (type == SANE_IMAGE_TYPE_BMP && xfer != TWAIN_XFER_Memory)
{ {
BITMAPINFOHEADER bih = { 0 }; BITMAPINFOHEADER bih = { 0 };
@ -451,7 +499,10 @@ COM_API_IMPLEMENT(scanned_img, int, width(void))
} }
COM_API_IMPLEMENT(scanned_img, int, line_bytes(void)) COM_API_IMPLEMENT(scanned_img, int, line_bytes(void))
{ {
return (head_.bytes_per_line + 3) / 4 * 4; if (fmt_.img_format == SANE_IMAGE_TYPE_BMP)
return (head_.bytes_per_line + 3) / 4 * 4;
else
return head_.bytes_per_line;
} }
COM_API_IMPLEMENT(scanned_img, int, height(void)) COM_API_IMPLEMENT(scanned_img, int, height(void))
{ {
@ -477,16 +528,25 @@ COM_API_IMPLEMENT(scanned_img, unsigned int, bytes(void))
{ {
return data_ ? data_->bytes() : 0; return data_ ? data_->bytes() : 0;
} }
COM_API_IMPLEMENT(scanned_img, unsigned int, header_size(void))
{
return header_size_;
}
COM_API_IMPLEMENT(scanned_img, unsigned char*, data(unsigned long long off, unsigned int* bytes)) COM_API_IMPLEMENT(scanned_img, unsigned char*, data(unsigned long long off, unsigned int* bytes))
{ {
return data_ ? data_->buffer(off, bytes) : NULL; return data_ ? data_->buffer(off, bytes) : NULL;
} }
COM_API_IMPLEMENT(scanned_img, int, read(void* buf, size_t* bytes, unsigned long long off))
{
return data_ ? data_->read(buf, bytes, off) : SCANNER_ERR_NO_DATA;
}
COM_API_IMPLEMENT(scanned_img, const char*, file(void)) COM_API_IMPLEMENT(scanned_img, const char*, file(void))
{ {
if (data_) if (data_)
return data_->file(); return data_->file();
else else
return NULL; return "";
} }
COM_API_IMPLEMENT(scanned_img, void, keep_file(bool keep)) COM_API_IMPLEMENT(scanned_img, void, keep_file(bool keep))
{ {

View File

@ -42,6 +42,7 @@ public:
unsigned char* allocate(const wchar_t* file, unsigned long long size = 0); unsigned char* allocate(const wchar_t* file, unsigned long long size = 0);
unsigned char* buffer(unsigned long long off, unsigned int* bytes); unsigned char* buffer(unsigned long long off, unsigned int* bytes);
bool save(const void* data, size_t* bytes, unsigned long long off); bool save(const void* data, size_t* bytes, unsigned long long off);
int read(void* buf, size_t* bytes, unsigned long long off);
void unmap(); void unmap();
void set_remove_file_when_destroyed(bool rmv); void set_remove_file_when_destroyed(bool rmv);
const char* file(void); const char* file(void);
@ -54,12 +55,14 @@ class scanned_img : public IScanImg, virtual public refer
SANE_Parameters head_; SANE_Parameters head_;
mapping_buf* data_; mapping_buf* data_;
int dpi_; int dpi_;
unsigned int header_size_;
SANE_FinalImgFormat fmt_;
std::string file_header(SANE_ImageType type, float resolution, twain_xfer xfer); std::string file_header(SANE_ImageType type, float resolution, twain_xfer xfer);
public: public:
scanned_img(SANE_Parameters head, SANE_Handle dev, int dpi, const wchar_t* tmp_file scanned_img(SANE_Parameters head, SANE_Handle dev, int dpi, const wchar_t* tmp_file
, twain_xfer xfer = TWAIN_XFER_Native); , twain_xfer xfer = TWAIN_XFER_Native, SANE_FinalImgFormat *fmt = NULL);
protected: protected:
@ -79,7 +82,9 @@ public:
COM_API_OVERRIDE(int, channel(void)); COM_API_OVERRIDE(int, channel(void));
COM_API_OVERRIDE(SANE_Frame, type(void)); COM_API_OVERRIDE(SANE_Frame, type(void));
COM_API_OVERRIDE(unsigned int, bytes(void)); COM_API_OVERRIDE(unsigned int, bytes(void));
COM_API_OVERRIDE(unsigned int, header_size(void));
COM_API_OVERRIDE(unsigned char*, data(unsigned long long off, unsigned int* bytes)); COM_API_OVERRIDE(unsigned char*, data(unsigned long long off, unsigned int* bytes));
COM_API_OVERRIDE(int, read(void* buf, size_t* bytes, unsigned long long off = 0));
COM_API_OVERRIDE(const char*, file(void)); COM_API_OVERRIDE(const char*, file(void));
COM_API_OVERRIDE(void, keep_file(bool keep)); COM_API_OVERRIDE(void, keep_file(bool keep));
COM_API_OVERRIDE(void, copy_header(SANE_Parameters* head)); COM_API_OVERRIDE(void, copy_header(SANE_Parameters* head));

View File

@ -1367,6 +1367,12 @@ COM_API_IMPLEMENT(scanner, int, start(void))
if(ret == SANE_STATUS_NO_DOCS && prev_start_result_ == SANE_STATUS_GOOD) if(ret == SANE_STATUS_NO_DOCS && prev_start_result_ == SANE_STATUS_GOOD)
ret = hg_sane_middleware::instance()->start(handle_, NULL); ret = hg_sane_middleware::instance()->start(handle_, NULL);
if (ret == SANE_STATUS_GOOD)
{
unsigned int l = sizeof(img_fmt_);
if (hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_FINAL_IMAGE_FORMAT, &img_fmt_, &l))
img_fmt_.img_format = SANE_IMAGE_TYPE_BMP;
}
prev_start_result_ = ret; prev_start_result_ = ret;
return local_utility::sane_statu_2_scanner_err(ret); return local_utility::sane_statu_2_scanner_err(ret);
@ -1417,8 +1423,9 @@ COM_API_IMPLEMENT(scanner, IScanImg*, take_first_image(twain_xfer xfer))
if (hg_sane_middleware::instance()->get_image_parameters(handle_, &head) == SANE_STATUS_GOOD) if (hg_sane_middleware::instance()->get_image_parameters(handle_, &head) == SANE_STATUS_GOOD)
{ {
wchar_t name[40] = { 0 }; wchar_t name[40] = { 0 };
swprintf_s(name, _countof(name) - 1, L"img_%05u.bmp", ++img_ind_); swprintf_s(name, _countof(name) - 1, L"img_%05u.bmp", ++img_ind_);
img = new scanned_img(head, handle_, dpi_, (tmp_path_ + name).c_str(), xfer); img = new scanned_img(head, handle_, dpi_, (tmp_path_ + name).c_str(), xfer, &img_fmt_);
} }
return dynamic_cast<IScanImg*>(img); return dynamic_cast<IScanImg*>(img);

View File

@ -31,6 +31,7 @@ class scanner : public ISaneInvoker, virtual public refer
int dpi_; int dpi_;
unsigned int img_ind_; unsigned int img_ind_;
std::wstring tmp_path_; std::wstring tmp_path_;
SANE_FinalImgFormat img_fmt_;
int open(void); int open(void);
int close(void); int close(void);

View File

@ -803,16 +803,8 @@ Result huagao_ds::pendingXfersEnd(const Identity& id, PendingXfers& data)
} }
Result huagao_ds::pendingXfersReset(const Identity&, PendingXfers& data) Result huagao_ds::pendingXfersReset(const Identity&, PendingXfers& data)
{ {
pending_xfer_.clear();
data.setCount(scanner_->get_scanned_images(-1)); data.setCount(scanner_->get_scanned_images(-1));
//if (scanner_.get())
// scanner_->stop();
//if (scanner.get())
//{
// scanner->Stop_scan();
// scanner->reset();
// scanner->ResetScanner();
//}
return success(); return success();
} }
@ -827,7 +819,7 @@ Result huagao_ds::setupMemXferGet(const Identity&, SetupMemXfer& data)
{ {
int line_bytes = (head.bytes_per_line + 3) / 4 * 4; int line_bytes = (head.bytes_per_line + 3) / 4 * 4;
data.setMinSize(head.bytes_per_line); data.setMinSize(head.bytes_per_line);
data.setPreferredSize(line_bytes * head.lines); data.setPreferredSize(line_bytes);
data.setMaxSize(line_bytes * head.lines); data.setMaxSize(line_bytes * head.lines);
return success(); return success();
@ -923,36 +915,52 @@ Result huagao_ds::imageLayoutReset(const Identity& origin, ImageLayout& data)
} }
Result huagao_ds::imageMemXferGet(const Identity& origin, ImageMemXfer& data) Result huagao_ds::imageMemXferGet(const Identity& origin, ImageMemXfer& data)
{ {
if (!scanner_.get() || scanner_->get_scanned_images() == 0) if (!scanner_.get() || (scanner_->get_scanned_images() == 0 && !pending_xfer_.img))
return seqError(); return seqError();
IScanImg *img = scanner_->take_first_image(TWAIN_XFER_Memory); IScanImg *img = pending_xfer_.img ? pending_xfer_.img : scanner_->take_first_image(TWAIN_XFER_Memory);
unsigned long long off = 0; unsigned long long off = pending_xfer_.img ? pending_xfer_.off : 0;
unsigned int total = img->bytes(); unsigned char *dst = (unsigned char*)data.memory().data().data();
unsigned char *src = img->data(off, &total), unsigned int line_l = img->line_bytes(),
*dst = NULL; rows = data.memory().size() / line_l;
size_t want_read = rows * line_l;
Result ret = { ReturnCode::XferDone, ConditionCode::Success };
data.setBytesPerRow(img->line_bytes()); if (rows == 0)
data.setColumns(img->width()); return badValue();
data.setRows(img->height());
data.setBytesWritten(img->bytes()); if (pending_xfer_.img)
data.setXOffset(0);
data.setYOffset(0);
data.setCompression(Compression::None);
dst = (unsigned char*)data.memory().data().data();
while (off < img->bytes() && src)
{ {
std::copy(src, src + total, dst); img->add_ref();
dst += total; pending_xfer_.clear();
off += total; }
if (off >= img->bytes()) data.setBytesPerRow(line_l);
break; data.setColumns(img->width());
total = img->bytes() - off; data.setXOffset(0);
src = img->data(off, &total); data.setYOffset(off / line_l);
data.setCompression(Compression::None);
if (img->read(dst, &want_read, off) == SCANNER_ERR_OK)
{
want_read /= line_l;
data.setRows(want_read);
want_read *= line_l;
data.setBytesWritten(want_read);
off += want_read;
if (off < img->bytes())
{
pending_xfer_.img = img;
pending_xfer_.off = off;
img->add_ref();
ret = success();
}
}
else
{
ret = { ReturnCode::XferDone, ConditionCode::Bummer };
} }
img->release(); img->release();
return success(); return ret;
} }
Result huagao_ds::imageNativeXferGet(const Identity& id, ImageNativeXfer& data) Result huagao_ds::imageNativeXferGet(const Identity& id, ImageNativeXfer& data)
{ {
@ -987,7 +995,10 @@ Result huagao_ds::imageNativeXferGet(const Identity& id, ImageNativeXfer& data)
} }
Twpp::Result huagao_ds::pendingXfersStopFeeder(const Identity& origin, PendingXfers& data) Twpp::Result huagao_ds::pendingXfersStopFeeder(const Identity& origin, PendingXfers& data)
{ {
// load_sane_util::invoke_sane_cancel(); if (!scanner_.get())
return seqError();
scanner_->stop();
return success(); return success();
} }

View File

@ -50,6 +50,22 @@ class huagao_ds : public Twpp::SourceFromThis<huagao_ds> {
void init_support_caps_ex(void); void init_support_caps_ex(void);
void on_scan_event(int sane_event, void* data, unsigned int* len); void on_scan_event(int sane_event, void* data, unsigned int* len);
typedef struct _pending_xfer
{
IScanImg* img;
unsigned int off;
struct _pending_xfer() : img(NULL), off(0)
{}
void clear(void)
{
if (img)
img->release();
img = NULL;
off = 0;
}
}PENDXFER;
PENDXFER pending_xfer_;
public: public:
huagao_ds(); huagao_ds();