Memory+Group4, to be complement...

This commit is contained in:
gb 2022-06-29 16:13:05 +08:00
parent d8e82950ab
commit 23cb82b7ce
7 changed files with 196 additions and 28 deletions

View File

@ -152,7 +152,7 @@ __declspec(novtable) struct ISaneInvoker : public IRef
COM_API_DECLARE(bool, wait_image(DWORD milliseconds = -1));
COM_API_DECLARE(int, get_scanned_images(DWORD milliseconds = 0));
COM_API_DECLARE(IScanImg*, take_first_image(twain_xfer xfer = TWAIN_XFER_Native)); // call 'release' on returned value, plz
COM_API_DECLARE(bool, get_first_image_header(SANE_Parameters* header));
COM_API_DECLARE(bool, get_first_image_header(SANE_Parameters* header, size_t* bytes = NULL));
COM_API_DECLARE(bool, is_online(void));
COM_API_DECLARE(bool, is_paper_on(void));
@ -170,6 +170,7 @@ __declspec(novtable) struct ISaneInvoker : public IRef
COM_API_DECLARE(bool, get_value(int sn, set_opt_value, void* param));
COM_API_DECLARE(int, set_value(int sn, void* val));
COM_API_DECLARE(int, convert_image(SANE_ImageFormatConvert* conv));
COM_API_DECLARE(void, free_buffer(void* buf, int len));
// SANE options ID ...
SANE_OPTION_ID_API(is_multiout); // 多流输出
@ -264,6 +265,7 @@ __declspec(novtable) struct ISaneInvoker : public IRef
// twain
COM_API_DECLARE(void, twain_set_transfer(twain_xfer xfer));
COM_API_DECLARE(void, twain_set_compression(SANE_CompressionType compression, void* detail = NULL));
};
struct delete_scanner

View File

@ -188,12 +188,12 @@ void mapping_buf::set_buffer(unsigned char*& buf, unsigned long long off, unsign
*bytes = mapped_bytes_ - (off - offset_);
}
unsigned char* mapping_buf::allocate(const wchar_t* file, unsigned long long size)
unsigned char* mapping_buf::allocate(const wchar_t* file, unsigned long long size, bool force_file)
{
close();
std::string ansi(local_trans::u2a(file));
if (size >= 100 * 1024 * 1024 || PathFileExistsW(file))
if (force_file || size >= 100 * 1024 * 1024 || PathFileExistsW(file))
{
init_map(ansi.c_str(), size);
}
@ -270,6 +270,27 @@ bool mapping_buf::save(const void* data, size_t* bytes, unsigned long long off)
return ret;
}
bool mapping_buf::save(unsigned long long off, mapping_buf* mbuf, unsigned long long src_off)
{
unsigned int len = mbuf->bytes() - src_off;
unsigned char* buf = mbuf->buffer(src_off, &len);
bool ret = false;
while (buf && save(buf, &len, off))
{
off += len;
src_off += len;
if (src_off >= mbuf->bytes())
{
ret = true;
break;
}
len = mbuf->bytes() - src_off;
buf = mbuf->buffer(src_off, &len);
}
return ret;
}
int mapping_buf::read(void* buf, size_t* bytes, unsigned long long off)
{
if (!bytes)
@ -334,9 +355,10 @@ unsigned int mapping_buf::mapped_bytes(void)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// class scanned_img
scanned_img::scanned_img(SANE_Parameters head, SANE_Handle dev, int dpi
scanned_img::scanned_img(SANE_Handle dev, SANE_Parameters head, int dpi
, const wchar_t* tmp_file, twain_xfer xfer
, SANE_FinalImgFormat *fmt) : head_(head), dpi_(dpi), header_size_(0)
, SANE_FinalImgFormat *fmt) : head_(head), dpi_(dpi), header_size_(0), file_(tmp_file ? tmp_file : L"")
, dev_(dev)
{
if (fmt)
fmt_ = *fmt;
@ -400,8 +422,9 @@ scanned_img::scanned_img(SANE_Parameters head, SANE_Handle dev, int dpi
}
do_result(ok, xfer);
}
scanned_img::scanned_img(SANE_Parameters head, void* data, unsigned int len, int dpi, const wchar_t* tmp_file
scanned_img::scanned_img(SANE_Handle dev, SANE_Parameters head, void* data, unsigned int len, int dpi, const wchar_t* tmp_file
, twain_xfer xfer, SANE_FinalImgFormat* fmt) : head_(head), dpi_(dpi), header_size_(0)
, file_(tmp_file ? tmp_file : L""), dev_(dev)
{
if (fmt)
fmt_ = *fmt;
@ -504,7 +527,56 @@ void scanned_img::do_result(bool ok, twain_xfer xfer)
{
if (ok)
{
if (fmt_.img_format == SANE_IMAGE_TYPE_BMP
if (fmt_.img_format == SANE_IMAGE_TYPE_BMP &&
fmt_.compress.compression == SANE_COMPRESSION_GROUP4 &&
xfer == TWAIN_XFER_Memory)
{
// convert to black-white ...
std::string head(file_header(SANE_IMAGE_TYPE_BMP, dpi_, TWAIN_XFER_File));
size_t size = head.length();
mapping_buf* buf = new mapping_buf();
std::wstring file(file_ + L".tmp");
unsigned long long off = 0;
if (buf->allocate(file.c_str(), size + data_->bytes(), true) &&
buf->save(head.c_str(), &size, off))
{
if (buf->save(size, data_))
{
SANE_ImageFormatConvert conv;
std::string sf(local_trans::u2a(file.c_str()));
buf->unmap();
conv.src.data = sf.c_str();
conv.src.data_len = sf.length();
conv.src.fmt.img_format = SANE_IMAGE_TYPE_BMP;
conv.src.fmt.compress.compression = SANE_COMPRESSION_NONE;
conv.src.is_file = SANE_TRUE;
conv.dst.data = NULL;
conv.dst.data_len = 0;
conv.dst.fmt.img_format = SANE_IMAGE_TYPE_BMP;
conv.dst.fmt.compress.compression = SANE_COMPRESSION_GROUP4;
conv.dst.fmt.compress.detail = NULL;
conv.dst.is_file = false;
if (hg_sane_middleware::instance()->io_control(dev_, IO_CTRL_CODE_CONVERT_IMAGE_FORMAT, &conv, NULL) == SANE_STATUS_GOOD)
{
delete data_;
data_ = new mapping_buf();
size = conv.dst.data_len;
data_->allocate(file_.c_str(), conv.dst.data_len);
data_->save(conv.dst.data, &size, 0);
hg_sane_middleware::instance()->io_control(dev_, IO_CTRL_CODE_FREE_MEMORY, (void*)conv.dst.data, &conv.dst.data_len);
head_.format = SANE_FRAME_GRAY;
head_.depth = 1;
head_.bytes_per_line = (head_.pixels_per_line + 7) / 8;
}
}
}
if (buf)
delete buf;
}
else if (fmt_.img_format == SANE_IMAGE_TYPE_BMP
&& channel() == 3
&& xfer != TWAIN_XFER_Memory)
{
@ -571,7 +643,7 @@ 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)
if (fmt_.img_format == SANE_IMAGE_TYPE_BMP && head_.depth >= 8)
return (head_.bytes_per_line + 3) / 4 * 4;
else
return head_.bytes_per_line;
@ -661,14 +733,19 @@ bool safe_img_queue::save(scanned_img* img)
return true;
}
bool safe_img_queue::get_header(SANE_Parameters* header)
bool safe_img_queue::get_header(SANE_Parameters* header, size_t* bytes)
{
std::lock_guard<std::mutex> lock(que_lock_);
bool ok = false;
if (bytes)
*bytes = 0;
if (queue_.size())
{
if(header)
queue_[0]->copy_header(header);
if(bytes)
*bytes = queue_[0]->bytes();
ok = true;
}

View File

@ -40,9 +40,10 @@ public:
~mapping_buf();
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, bool force_file = false);
unsigned char* buffer(unsigned long long off, unsigned int* bytes);
bool save(const void* data, size_t* bytes, unsigned long long off);
bool save(unsigned long long off, mapping_buf* mbuf, unsigned long long src_off = 0);
int read(void* buf, size_t* bytes, unsigned long long off);
void unmap();
void set_remove_file_when_destroyed(bool rmv);
@ -56,6 +57,8 @@ class scanned_img : public IScanImg, virtual public refer
SANE_Parameters head_;
mapping_buf* data_;
int dpi_;
SANE_Handle dev_;
std::wstring file_;
unsigned int header_size_;
SANE_FinalImgFormat fmt_;
@ -64,9 +67,9 @@ class scanned_img : public IScanImg, virtual public refer
void swap_rgb(void);
public:
scanned_img(SANE_Parameters head, SANE_Handle dev, int dpi, const wchar_t* tmp_file
scanned_img(SANE_Handle dev, SANE_Parameters head, int dpi, const wchar_t* tmp_file
, twain_xfer xfer = TWAIN_XFER_Native, SANE_FinalImgFormat *fmt = NULL);
scanned_img(SANE_Parameters head, void* data, unsigned int len, int dpi, const wchar_t* tmp_file
scanned_img(SANE_Handle dev, SANE_Parameters head, void* data, unsigned int len, int dpi, const wchar_t* tmp_file
, twain_xfer xfer = TWAIN_XFER_Native, SANE_FinalImgFormat *fmt = NULL);
@ -107,7 +110,7 @@ public:
public:
size_t count(void);
bool save(scanned_img* img);
bool get_header(SANE_Parameters* header);
bool get_header(SANE_Parameters* header, size_t* bytes = NULL);
scanned_img* take(void);
void clear();
};

View File

@ -116,6 +116,7 @@ scanner::scanner(SCANNERID id) : handle_(NULL), id_(id), ex_id_(EXTENSION_ID_BAS
CreateDirectoryW(tmp_path_.c_str(), NULL);
tmp_path_ += L"\\";
img_fmt_.img_format = SANE_IMAGE_TYPE_BMP;
img_fmt_.compress.compression = SANE_COMPRESSION_NONE;
err_ = open();
}
@ -1510,8 +1511,10 @@ COM_API_IMPLEMENT(scanner, int, start(void))
if (ret == SANE_STATUS_GOOD)
{
unsigned int l = sizeof(img_fmt_);
SANE_CompressionType cmprsn = img_fmt_.compress.compression;
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;
img_fmt_.compress.compression = cmprsn;
working_ = true;
}
prev_start_result_ = ret;
@ -1576,9 +1579,9 @@ COM_API_IMPLEMENT(scanner, IScanImg*, take_first_image(twain_xfer xfer))
return dynamic_cast<IScanImg*>(img);
}
COM_API_IMPLEMENT(scanner, bool, get_first_image_header(SANE_Parameters* header))
COM_API_IMPLEMENT(scanner, bool, get_first_image_header(SANE_Parameters* header, size_t* bytes))
{
return images_.get_header(header);
return images_.get_header(header, bytes);
}
COM_API_IMPLEMENT(scanner, bool, is_online(void))
{
@ -1779,7 +1782,10 @@ COM_API_IMPLEMENT(scanner, int, convert_image(SANE_ImageFormatConvert* conv))
{
return hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_CONVERT_IMAGE_FORMAT, conv, NULL);
}
COM_API_IMPLEMENT(scanner, void, free_buffer(void* buf, int len))
{
hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_FREE_MEMORY, buf, (unsigned int*)&len);
}
// SANE options ID ...
SANE_OPTION_ID_IMPLEMENT(is_multiout)
@ -1868,6 +1874,12 @@ COM_API_IMPLEMENT(scanner, void, twain_set_transfer(twain_xfer xfer))
{
xfer_ = xfer;
}
COM_API_IMPLEMENT(scanner, void, twain_set_compression(SANE_CompressionType compression, void* detail))
{
img_fmt_.compress.compression = compression;
img_fmt_.compress.detail = detail;
}
// ui ...
COM_API_IMPLEMENT(scanner, bool, ui_show_main(HWND parent))
@ -1939,8 +1951,8 @@ int scanner::handle_event(int ev_code, void* data, unsigned int* len)
wchar_t name[40] = { 0 };
swprintf_s(name, _countof(name) - 1, L"img_%05u.bmp", ++img_ind_);
img = new scanned_img(simg->header, simg->data, simg->bytes, dpi_, (tmp_path_ + name).c_str(), xfer_, &img_fmt_);
if (img->bytes() >= simg->bytes)
img = new scanned_img(handle_, simg->header, simg->data, simg->bytes, dpi_, (tmp_path_ + name).c_str(), xfer_, &img_fmt_);
if (img->bytes() /*>= simg->bytes*/)
{
images_.save(img);
}

View File

@ -191,13 +191,14 @@ public:
COM_API_OVERRIDE(bool, wait_image(DWORD milliseconds = -1));
COM_API_OVERRIDE(int, get_scanned_images(DWORD milliseconds = 0));
COM_API_OVERRIDE(IScanImg*, take_first_image(twain_xfer xfer = TWAIN_XFER_Native)); // call 'release' on returned value, plz
COM_API_OVERRIDE(bool, get_first_image_header(SANE_Parameters* header));
COM_API_OVERRIDE(bool, get_first_image_header(SANE_Parameters* header, size_t* bytes = NULL));
COM_API_OVERRIDE(bool, is_online(void));
COM_API_OVERRIDE(bool, is_paper_on(void));
COM_API_OVERRIDE(bool, get_option_info(int sn, value_type* type, value_limit* limit, int* bytes));
COM_API_OVERRIDE(bool, get_value(int sn, set_opt_value, void* param));
COM_API_OVERRIDE(int, set_value(int sn, void* val));
COM_API_OVERRIDE(int, convert_image(SANE_ImageFormatConvert* conv));
COM_API_OVERRIDE(void, free_buffer(void* buf, int len));
// SANE options ID ...
SANE_OPTION_ID(is_multiout);
@ -291,6 +292,7 @@ public:
// twain
COM_API_OVERRIDE(void, twain_set_transfer(twain_xfer xfer));
COM_API_OVERRIDE(void, twain_set_compression(SANE_CompressionType compression, void* detail = NULL));
// methods:
public:

48
twain/brand.h Normal file
View File

@ -0,0 +1,48 @@
#pragma once
// Definitions for all versions ...
//
//
// #define OEM_HANWANG
#define VERSION_MAIN 4
#define VERSION_SUB 1007
#define VERSION_BUILD 2022
#define VERSION_PATCH 6271
#define TO_STR(a) #a
#define TO_VER_STR(vs) TO_STR(v##vs)
#define VERSION_STR(a, b, c, d) TO_VER_STR(a.b.c.d)
#define PRODUCT_ID 100
#define MAKE_PID(pid) 0x##pid
#define PASTE_DEF(a, b) a##b
#define FINAL_STR(a, b, c) TO_STR(a##b##c)
#define MAKE_NAME(pid) FULL_NAME(PASTE_DEF(G, pid))
#define FULL_FAMILY(a) FINAL_STR(a, \x20, Series)
#define MAKE_FAMILY(pid) FULL_FAMILY(PASTE_DEF(G, pid))
#ifdef OEM_HANWANG
#define FULL_NAME(a) FINAL_STR(HANVONSCAN\x20, a, \x20TWAIN)
#define PRODUCT_VID 0x2903
#define PRODUCT_VENDOR "Hanvon"
#elif defined(OEM_LISICHENG)
#define FULL_NAME(a) FINAL_STR(LANXUMSCAN\x20, a, \x20TWAIN)
#define PRODUCT_VID 0x31c9
#define PRODUCT_VENDOR "Lanxum"
#else
#define FULL_NAME(a) FINAL_STR(HUAGOSCAN\x20, a, \x20TWAIN)
#define PRODUCT_VID 0x3072
#define PRODUCT_VENDOR "HUAGO"
#endif
#define PRODUCT_PID MAKE_PID(PRODUCT_ID)
#define PRODUCT_FAMILY MAKE_FAMILY(PRODUCT_ID)
#define PRODUCT_NAME MAKE_NAME(PRODUCT_ID)

View File

@ -760,6 +760,7 @@ Result huagao_ds::identityOpenDs(const Identity& id)
// ui_.reset(new twain_ui(local_utility::reg_get_app_installing_path().c_str()));
scanner_->set_event_callback(&huagao_ds::scan_event, this);
init_support_caps();
m_fileXfer.setFormat(ImageFileFormat::Bmp);
return success();
}
@ -801,16 +802,26 @@ Result huagao_ds::pendingXfersReset(const Identity&, PendingXfers& data)
Result huagao_ds::setupMemXferGet(const Identity&, SetupMemXfer& data)
{
SANE_Parameters head;
size_t total = 0;
if (!scanner_.get() || scanner_->get_scanned_images() == 0)
return seqError();
if (scanner_->get_first_image_header(&head))
if (scanner_->get_first_image_header(&head, &total))
{
if (m_compression == Compression::None)
{
int line_bytes = (head.bytes_per_line + 3) / 4 * 4;
data.setMinSize(head.bytes_per_line);
data.setPreferredSize(line_bytes);
data.setMaxSize(line_bytes * head.lines);
}
else
{
data.setMinSize(total);
data.setPreferredSize(total);
data.setMaxSize(total);
}
return success();
}
@ -929,10 +940,20 @@ Result huagao_ds::imageMemXferGet(const Identity& origin, ImageMemXfer& data)
}
data.setBytesPerRow(line_l);
data.setColumns(img->width());
data.setRows(rows);
data.setXOffset(0);
data.setYOffset(off / line_l);
data.setCompression(Compression::None);
if (img->read(dst, &want_read, off) == SCANNER_ERR_OK)
data.setCompression(m_compression);
if (m_compression != Compression::None)
{
want_read = img->bytes();
off = 0;
img->read(dst, &want_read, off);
data.setRows(1);
data.setColumns(want_read);
data.setBytesWritten(want_read);
}
else if (img->read(dst, &want_read, off) == SCANNER_ERR_OK)
{
want_read /= line_l;
data.setRows(want_read);
@ -1233,6 +1254,7 @@ void huagao_ds::init_support_caps(void)
auto mech = data.currentItem<CapType::ICompression>();
if (Compression::None == mech || mech == Compression::Group4) {
m_compression = mech;
scanner_->twain_set_compression((SANE_CompressionType)m_compression);
return success();
}
else
@ -1446,6 +1468,7 @@ void huagao_ds::init_support_caps(void)
auto mech = data.currentItem<CapType::IXferMech>();
if (mech == XferMech::Native || mech == XferMech::Memory || mech == XferMech::File) {
m_capXferMech = mech;
scanner_->twain_set_transfer((twain_xfer)m_capXferMech);
return success();
}
else {
@ -1662,7 +1685,8 @@ void huagao_ds::init_support_caps(void)
//SET_SANE_OPT(ret, scanner_, ex_final_format, &init);
//return ret == SCANNER_ERR_OK ? success() : badValue();
}
ImageFileFormat Now = m_fileXfer.format(), Init = (ImageFileFormat)(int)init.img_format;
// ImageFileFormat Now = (ImageFileFormat)(int)now.img_format, Init = (ImageFileFormat)(int)init.img_format;
ImageFileFormat Now = m_fileXfer.format() , Init = Twpp::ImageFileFormat::Bmp;
std::list<ImageFileFormat> vals;
UInt32 i = 0, n = 0;
for (const auto& v : all)