完善三种传输方式Native/File/Memory
This commit is contained in:
parent
1581c452ca
commit
712d49809b
|
@ -137,7 +137,9 @@ __declspec(novtable) struct IScanImg : public IRef
|
|||
COM_API_DECLARE(int, channel(void));
|
||||
COM_API_DECLARE(SANE_Frame, type(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(int, read(void* buf, size_t* bytes, unsigned long long off = 0));
|
||||
COM_API_DECLARE(const char*, file(void));
|
||||
COM_API_DECLARE(void, keep_file(bool keep));
|
||||
COM_API_DECLARE(void, copy_header(SANE_Parameters* head));
|
||||
|
|
|
@ -203,7 +203,7 @@ unsigned char* mapping_buf::allocate(const wchar_t* file, unsigned long long siz
|
|||
{
|
||||
buf_ = new unsigned char[size];
|
||||
is_mem_ = true;
|
||||
mapped_bytes_ = size;
|
||||
bytes_ = mapped_bytes_ = size;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
@ -270,6 +270,36 @@ bool mapping_buf::save(const void* data, size_t* bytes, unsigned long long off)
|
|||
|
||||
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()
|
||||
{
|
||||
if (!is_mem_)
|
||||
|
@ -287,7 +317,7 @@ void mapping_buf::set_remove_file_when_destroyed(bool rmv)
|
|||
}
|
||||
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)
|
||||
{
|
||||
|
@ -305,23 +335,37 @@ unsigned int mapping_buf::mapped_bytes(void)
|
|||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// class scanned_img
|
||||
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();
|
||||
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;
|
||||
bool ok = false;
|
||||
|
||||
data_ = new mapping_buf();
|
||||
header_size_ = h.length();
|
||||
dst = data_->allocate(tmp_file, bytes + h.length());
|
||||
if (dst)
|
||||
{
|
||||
unsigned long long off = 0;
|
||||
unsigned long long off = 0, total = 0;
|
||||
bytes = h.length();
|
||||
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();
|
||||
|
||||
if (xfer == TWAIN_XFER_Memory)
|
||||
line *= -1;
|
||||
else
|
||||
off = data_->bytes() - line;
|
||||
dst = data_->buffer(off, &len);
|
||||
|
||||
|
@ -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 ret = hg_sane_middleware::instance()->read(dev, dst + rcv, &r);
|
||||
total += r;
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
break;
|
||||
|
||||
|
@ -339,9 +384,10 @@ scanned_img::scanned_img(SANE_Parameters head, SANE_Handle dev, int dpi
|
|||
{
|
||||
want_to_read = head_.bytes_per_line;
|
||||
off -= line;
|
||||
len = line;
|
||||
len = line_bytes();
|
||||
rcv = 0;
|
||||
dst = data_->buffer(off, &len);
|
||||
total += dif;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -349,13 +395,14 @@ scanned_img::scanned_img(SANE_Parameters head, SANE_Handle dev, int dpi
|
|||
dst = data_->buffer(off + rcv, &len);
|
||||
}
|
||||
}
|
||||
ok = total + h.length() + dif == data_->bytes();
|
||||
}
|
||||
ok = off == h.length();
|
||||
}
|
||||
|
||||
if (ok)
|
||||
{
|
||||
if (channel() == 3)
|
||||
if (fmt_.img_format == SANE_IMAGE_TYPE_BMP && channel() == 3 &&
|
||||
xfer != TWAIN_XFER_Memory)
|
||||
{
|
||||
// swap RGB
|
||||
unsigned long long off = 0;
|
||||
|
@ -393,6 +440,7 @@ scanned_img::scanned_img(SANE_Parameters head, SANE_Handle dev, int dpi
|
|||
{
|
||||
delete data_;
|
||||
data_ = NULL;
|
||||
header_size_ = 0;
|
||||
}
|
||||
}
|
||||
scanned_img::~scanned_img()
|
||||
|
@ -405,7 +453,7 @@ std::string scanned_img::file_header(SANE_ImageType type, float resolution, twai
|
|||
{
|
||||
std::string h("");
|
||||
|
||||
if (type == SANE_IMAGE_TYPE_BMP)
|
||||
if (type == SANE_IMAGE_TYPE_BMP && xfer != TWAIN_XFER_Memory)
|
||||
{
|
||||
BITMAPINFOHEADER bih = { 0 };
|
||||
|
||||
|
@ -451,7 +499,10 @@ COM_API_IMPLEMENT(scanned_img, int, width(void))
|
|||
}
|
||||
COM_API_IMPLEMENT(scanned_img, int, line_bytes(void))
|
||||
{
|
||||
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))
|
||||
{
|
||||
|
@ -477,16 +528,25 @@ COM_API_IMPLEMENT(scanned_img, unsigned int, bytes(void))
|
|||
{
|
||||
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))
|
||||
{
|
||||
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))
|
||||
{
|
||||
if (data_)
|
||||
return data_->file();
|
||||
else
|
||||
return NULL;
|
||||
return "";
|
||||
}
|
||||
COM_API_IMPLEMENT(scanned_img, void, keep_file(bool keep))
|
||||
{
|
||||
|
|
|
@ -42,6 +42,7 @@ public:
|
|||
unsigned char* allocate(const wchar_t* file, unsigned long long size = 0);
|
||||
unsigned char* buffer(unsigned long long off, unsigned int* bytes);
|
||||
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 set_remove_file_when_destroyed(bool rmv);
|
||||
const char* file(void);
|
||||
|
@ -54,12 +55,14 @@ class scanned_img : public IScanImg, virtual public refer
|
|||
SANE_Parameters head_;
|
||||
mapping_buf* data_;
|
||||
int dpi_;
|
||||
unsigned int header_size_;
|
||||
SANE_FinalImgFormat fmt_;
|
||||
|
||||
std::string file_header(SANE_ImageType type, float resolution, twain_xfer xfer);
|
||||
|
||||
public:
|
||||
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:
|
||||
|
@ -79,7 +82,9 @@ public:
|
|||
COM_API_OVERRIDE(int, channel(void));
|
||||
COM_API_OVERRIDE(SANE_Frame, type(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(int, read(void* buf, size_t* bytes, unsigned long long off = 0));
|
||||
COM_API_OVERRIDE(const char*, file(void));
|
||||
COM_API_OVERRIDE(void, keep_file(bool keep));
|
||||
COM_API_OVERRIDE(void, copy_header(SANE_Parameters* head));
|
||||
|
|
|
@ -1367,6 +1367,12 @@ COM_API_IMPLEMENT(scanner, int, start(void))
|
|||
if(ret == SANE_STATUS_NO_DOCS && prev_start_result_ == SANE_STATUS_GOOD)
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
wchar_t name[40] = { 0 };
|
||||
|
||||
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);
|
||||
|
|
|
@ -31,6 +31,7 @@ class scanner : public ISaneInvoker, virtual public refer
|
|||
int dpi_;
|
||||
unsigned int img_ind_;
|
||||
std::wstring tmp_path_;
|
||||
SANE_FinalImgFormat img_fmt_;
|
||||
|
||||
int open(void);
|
||||
int close(void);
|
||||
|
|
|
@ -803,16 +803,8 @@ Result huagao_ds::pendingXfersEnd(const Identity& id, PendingXfers& data)
|
|||
}
|
||||
Result huagao_ds::pendingXfersReset(const Identity&, PendingXfers& data)
|
||||
{
|
||||
pending_xfer_.clear();
|
||||
data.setCount(scanner_->get_scanned_images(-1));
|
||||
//if (scanner_.get())
|
||||
// scanner_->stop();
|
||||
|
||||
//if (scanner.get())
|
||||
//{
|
||||
// scanner->Stop_scan();
|
||||
// scanner->reset();
|
||||
// scanner->ResetScanner();
|
||||
//}
|
||||
|
||||
return success();
|
||||
}
|
||||
|
@ -827,7 +819,7 @@ Result huagao_ds::setupMemXferGet(const Identity&, SetupMemXfer& data)
|
|||
{
|
||||
int line_bytes = (head.bytes_per_line + 3) / 4 * 4;
|
||||
data.setMinSize(head.bytes_per_line);
|
||||
data.setPreferredSize(line_bytes * head.lines);
|
||||
data.setPreferredSize(line_bytes);
|
||||
data.setMaxSize(line_bytes * head.lines);
|
||||
|
||||
return success();
|
||||
|
@ -923,36 +915,52 @@ Result huagao_ds::imageLayoutReset(const Identity& origin, ImageLayout& 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();
|
||||
|
||||
IScanImg *img = scanner_->take_first_image(TWAIN_XFER_Memory);
|
||||
unsigned long long off = 0;
|
||||
unsigned int total = img->bytes();
|
||||
unsigned char *src = img->data(off, &total),
|
||||
*dst = NULL;
|
||||
IScanImg *img = pending_xfer_.img ? pending_xfer_.img : scanner_->take_first_image(TWAIN_XFER_Memory);
|
||||
unsigned long long off = pending_xfer_.img ? pending_xfer_.off : 0;
|
||||
unsigned char *dst = (unsigned char*)data.memory().data().data();
|
||||
unsigned int line_l = img->line_bytes(),
|
||||
rows = data.memory().size() / line_l;
|
||||
size_t want_read = rows * line_l;
|
||||
Result ret = { ReturnCode::XferDone, ConditionCode::Success };
|
||||
|
||||
data.setBytesPerRow(img->line_bytes());
|
||||
data.setColumns(img->width());
|
||||
data.setRows(img->height());
|
||||
data.setBytesWritten(img->bytes());
|
||||
data.setXOffset(0);
|
||||
data.setYOffset(0);
|
||||
data.setCompression(Compression::None);
|
||||
dst = (unsigned char*)data.memory().data().data();
|
||||
while (off < img->bytes() && src)
|
||||
if (rows == 0)
|
||||
return badValue();
|
||||
|
||||
if (pending_xfer_.img)
|
||||
{
|
||||
std::copy(src, src + total, dst);
|
||||
dst += total;
|
||||
off += total;
|
||||
if (off >= img->bytes())
|
||||
break;
|
||||
total = img->bytes() - off;
|
||||
src = img->data(off, &total);
|
||||
img->add_ref();
|
||||
pending_xfer_.clear();
|
||||
}
|
||||
data.setBytesPerRow(line_l);
|
||||
data.setColumns(img->width());
|
||||
data.setXOffset(0);
|
||||
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();
|
||||
|
||||
return success();
|
||||
return ret;
|
||||
}
|
||||
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)
|
||||
{
|
||||
// load_sane_util::invoke_sane_cancel();
|
||||
if (!scanner_.get())
|
||||
return seqError();
|
||||
|
||||
scanner_->stop();
|
||||
|
||||
return success();
|
||||
}
|
||||
|
|
|
@ -50,6 +50,22 @@ class huagao_ds : public Twpp::SourceFromThis<huagao_ds> {
|
|||
void init_support_caps_ex(void);
|
||||
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:
|
||||
huagao_ds();
|
||||
|
|
Loading…
Reference in New Issue