增加内存映射文件,以支持在小内存工况下正常工作
This commit is contained in:
parent
8da59821bd
commit
e579975168
|
@ -131,7 +131,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 char*, bits(void));
|
||||
COM_API_DECLARE(unsigned char*, data(unsigned long long off, unsigned int *bytes));
|
||||
COM_API_DECLARE(const char*, file(void));
|
||||
COM_API_DECLARE(void, keep_file(bool keep));
|
||||
COM_API_DECLARE(void, copy_header(SANE_Parameters* head));
|
||||
};
|
||||
__declspec(novtable) struct ISaneInvoker : public IRef
|
||||
|
|
|
@ -1,9 +1,58 @@
|
|||
#include "scanned_img.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include <Shlwapi.h>
|
||||
#pragma comment(lib, "Shlwapi.lib")
|
||||
|
||||
#include "../../code_device/hgsane/sane_hg_mdw.h"
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
namespace local_trans
|
||||
{
|
||||
std::string u2a(const wchar_t* u, UINT cp)
|
||||
{
|
||||
std::string a("");
|
||||
|
||||
if (u)
|
||||
{
|
||||
char * ansi = NULL;
|
||||
int len = 0;
|
||||
|
||||
len = WideCharToMultiByte(cp, 0, u, lstrlenW(u), NULL, 0, NULL, NULL);
|
||||
ansi = new char[len + 2];
|
||||
len = WideCharToMultiByte(cp, 0, u, lstrlenW(u), ansi, len, NULL, NULL);
|
||||
ansi[len--] = 0;
|
||||
a = ansi;
|
||||
delete[] ansi;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
std::wstring a2u(const char* asc, UINT cp)
|
||||
{
|
||||
std::wstring u(L"");
|
||||
|
||||
if (asc)
|
||||
{
|
||||
wchar_t *buf = NULL;
|
||||
int len = 0;
|
||||
|
||||
len = MultiByteToWideChar(cp, 0, asc, lstrlenA(asc), NULL, 0);
|
||||
buf = new wchar_t[len + 2];
|
||||
len = MultiByteToWideChar(cp, 0, asc, lstrlenA(asc), buf, len);
|
||||
buf[len--] = 0;
|
||||
u = buf;
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
return u;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// class refer
|
||||
refer::refer() : ref_(1)
|
||||
|
@ -27,44 +76,328 @@ COM_API_IMPLEMENT(refer, long, release(void))
|
|||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// class scanned_img
|
||||
scanned_img::scanned_img(SANE_Parameters head, unsigned char* data) : head_(head)
|
||||
// class mapping_buf
|
||||
const unsigned int max_mem_block = 2 * 1024 * 1024;
|
||||
|
||||
mapping_buf::mapping_buf() : bytes_(0), offset_(0), mapped_bytes_(0), map_(NULL), buf_(NULL), file_(""), rmv_file_(true), page_size_(0), is_mem_(false)
|
||||
{
|
||||
size_t bytes = line_bytes() * height();
|
||||
std::string h(file_header(SANE_IMAGE_TYPE_BMP, 200.0f));
|
||||
unsigned char* src = data + head.bytes_per_line * head.lines - head.bytes_per_line,
|
||||
* dst = NULL;
|
||||
SYSTEM_INFO si = { 0 };
|
||||
|
||||
bytes_ = bytes + h.length();
|
||||
data_ = new unsigned char[bytes_];
|
||||
memcpy(data_, h.c_str(), h.length());
|
||||
dst = data_ + h.length();
|
||||
GetSystemInfo(&si);
|
||||
page_size_ = si.dwPageSize;
|
||||
map_unit_ = si.dwAllocationGranularity;
|
||||
}
|
||||
mapping_buf::~mapping_buf()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
if (head.format == SANE_FRAME_RGB)
|
||||
void mapping_buf::init_map(const char* file, unsigned long long size)
|
||||
{
|
||||
HANDLE f = INVALID_HANDLE_VALUE;
|
||||
|
||||
if (size)
|
||||
{
|
||||
for (int i = 0; i < height(); ++i)
|
||||
f = CreateFileA(file, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (f != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
for (int j = 0; j < head.pixels_per_line; ++j)
|
||||
unsigned long long total = size - 1;
|
||||
LONG* p32 = (LONG*)&total;
|
||||
*p32 = SetFilePointer(f, *p32, p32 + 1, FILE_BEGIN);
|
||||
total++;
|
||||
if (total == size)
|
||||
{
|
||||
dst[j * 3 + 0] = src[j * 3 + 2];
|
||||
dst[j * 3 + 1] = src[j * 3 + 1];
|
||||
dst[j * 3 + 2] = src[j * 3 + 0];
|
||||
DWORD wrote = 1;
|
||||
WriteFile(f, "\0", 1, &wrote, NULL);
|
||||
map_ = CreateFileMapping(f, NULL, PAGE_READWRITE, p32[1], p32[0], NULL);
|
||||
}
|
||||
src -= head.bytes_per_line;
|
||||
dst += line_bytes();
|
||||
CloseHandle(f);
|
||||
if (!map_)
|
||||
DeleteFileA(file);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < height(); ++i, dst += line_bytes(), src -= head.bytes_per_line)
|
||||
memcpy(dst, src, head.bytes_per_line);
|
||||
f = CreateFileA(file, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (f != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD* p32 = (DWORD*)&size;
|
||||
*p32 = GetFileSize(f, p32 + 1);
|
||||
map_ = CreateFileMapping(f, NULL, PAGE_READWRITE, p32[1], p32[0], NULL);
|
||||
CloseHandle(f);
|
||||
}
|
||||
}
|
||||
|
||||
if (map_)
|
||||
{
|
||||
bytes_ = size;
|
||||
file_ = file;
|
||||
buffer(0, NULL);
|
||||
if (!map_)
|
||||
close();
|
||||
}
|
||||
}
|
||||
void mapping_buf::close(void)
|
||||
{
|
||||
if (buf_)
|
||||
{
|
||||
if (is_mem_)
|
||||
delete[] buf_;
|
||||
else
|
||||
UnmapViewOfFile(buf_);
|
||||
}
|
||||
buf_ = NULL;
|
||||
if (map_)
|
||||
CloseHandle(map_);
|
||||
map_ = NULL;
|
||||
if (rmv_file_ && file_.length())
|
||||
DeleteFileA(file_.c_str());
|
||||
file_ = "";
|
||||
bytes_ = offset_ = 0;
|
||||
mapped_bytes_ = 0;
|
||||
rmv_file_ = true;
|
||||
is_mem_ = false;
|
||||
}
|
||||
void mapping_buf::map(void)
|
||||
{
|
||||
DWORD* off = (DWORD*)&offset_;
|
||||
|
||||
buf_ = (unsigned char*)MapViewOfFile(map_, FILE_MAP_READ | FILE_MAP_WRITE, off[1], off[0], mapped_bytes_);
|
||||
if (!buf_)
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
mapped_bytes_ /= map_unit_;
|
||||
mapped_bytes_ *= map_unit_;
|
||||
while (mapped_bytes_ > map_unit_)
|
||||
{
|
||||
buf_ = (unsigned char*)MapViewOfFile(map_, FILE_MAP_READ | FILE_MAP_WRITE, off[1], off[0], mapped_bytes_);
|
||||
if (buf_)
|
||||
break;
|
||||
mapped_bytes_ /= 2;
|
||||
}
|
||||
if (!buf_)
|
||||
mapped_bytes_ = 0;
|
||||
}
|
||||
}
|
||||
void mapping_buf::set_buffer(unsigned char*& buf, unsigned long long off, unsigned int* bytes)
|
||||
{
|
||||
buf = buf_ + (off - offset_);
|
||||
if (bytes)
|
||||
*bytes = mapped_bytes_ - (off - offset_);
|
||||
}
|
||||
|
||||
unsigned char* mapping_buf::allocate(const wchar_t* file, unsigned long long size)
|
||||
{
|
||||
close();
|
||||
|
||||
std::string ansi(local_trans::u2a(file));
|
||||
if (size >= 100 * 1024 * 1024 || PathFileExistsW(file))
|
||||
{
|
||||
init_map(ansi.c_str(), size);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
buf_ = new unsigned char[size];
|
||||
is_mem_ = true;
|
||||
mapped_bytes_ = size;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
is_mem_ = false;
|
||||
init_map(ansi.c_str(), size);
|
||||
}
|
||||
}
|
||||
|
||||
return buf_;
|
||||
}
|
||||
unsigned char* mapping_buf::buffer(unsigned long long off, unsigned int* bytes)
|
||||
{
|
||||
unsigned int size = bytes ? *bytes : 1 * 1024 * 1024 * 1024;
|
||||
unsigned char* buf = NULL;
|
||||
|
||||
if (size > bytes_ - offset_)
|
||||
size = bytes_ - offset_;
|
||||
|
||||
if (buf_ && off >= offset_ && size + (off - offset_) <= mapped_bytes_)
|
||||
{
|
||||
set_buffer(buf, off, bytes);
|
||||
}
|
||||
else if (!is_mem_)
|
||||
{
|
||||
if (off < bytes_)
|
||||
{
|
||||
if (buf_)
|
||||
UnmapViewOfFile(buf_);
|
||||
|
||||
offset_ = off / map_unit_ * map_unit_;
|
||||
mapped_bytes_ = bytes_ - offset_;
|
||||
map();
|
||||
if (buf_)
|
||||
set_buffer(buf, off, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
bool mapping_buf::save(const void* data, size_t* bytes, unsigned long long off)
|
||||
{
|
||||
unsigned int len = *bytes, total = 0;
|
||||
unsigned char* buf = buffer(off, &len);
|
||||
bool ret = false;
|
||||
const char* src = (const char*)data;
|
||||
|
||||
while (buf)
|
||||
{
|
||||
if (len > *bytes - total)
|
||||
{
|
||||
memcpy(buf, src, *bytes - total);
|
||||
total = *bytes;
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
memcpy(buf, data, len);
|
||||
total += len;
|
||||
off += len;
|
||||
src += len;
|
||||
len = *bytes - total;
|
||||
buf = buffer(off, &len);
|
||||
}
|
||||
*bytes = total;
|
||||
|
||||
return ret;
|
||||
}
|
||||
void mapping_buf::unmap()
|
||||
{
|
||||
if (!is_mem_)
|
||||
{
|
||||
if (buf_)
|
||||
UnmapViewOfFile(buf_);
|
||||
buf_ = NULL;
|
||||
offset_ = 0;
|
||||
mapped_bytes_ = 0;
|
||||
}
|
||||
}
|
||||
void mapping_buf::set_remove_file_when_destroyed(bool rmv)
|
||||
{
|
||||
rmv_file_ = rmv;
|
||||
}
|
||||
const char* mapping_buf::file(void)
|
||||
{
|
||||
return is_mem_ ? NULL : file_.c_str();
|
||||
}
|
||||
unsigned long long mapping_buf::bytes(void)
|
||||
{
|
||||
return bytes_;
|
||||
}
|
||||
unsigned long long mapping_buf::offset(void)
|
||||
{
|
||||
return offset_;
|
||||
}
|
||||
unsigned int mapping_buf::mapped_bytes(void)
|
||||
{
|
||||
return mapped_bytes_;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// class scanned_img
|
||||
scanned_img::scanned_img(SANE_Parameters head, SANE_Handle dev, int dpi, const wchar_t* tmp_file) : head_(head), dpi_(dpi)
|
||||
{
|
||||
size_t bytes = line_bytes() * height();
|
||||
std::string h(file_header(SANE_IMAGE_TYPE_BMP, dpi));
|
||||
unsigned char* dst = NULL;
|
||||
bool ok = false;
|
||||
|
||||
data_ = new mapping_buf();
|
||||
dst = data_->allocate(tmp_file, bytes + h.length());
|
||||
if (dst)
|
||||
{
|
||||
unsigned long long off = 0;
|
||||
bytes = h.length();
|
||||
if (data_->save(h.c_str(), &bytes, off))
|
||||
{
|
||||
unsigned int line = line_bytes(), len = line;
|
||||
|
||||
off = data_->bytes() - line;
|
||||
dst = data_->buffer(off, &len);
|
||||
|
||||
int want_to_read = head_.bytes_per_line, rcv = 0, dif = line_bytes() - head_.bytes_per_line;
|
||||
while (dst)
|
||||
{
|
||||
int r = want_to_read > len - rcv ? len - rcv : want_to_read;
|
||||
int ret = hg_sane_middleware::instance()->read(dev, dst + rcv, &r);
|
||||
if (ret != SANE_STATUS_GOOD)
|
||||
break;
|
||||
|
||||
want_to_read -= r;
|
||||
rcv += r;
|
||||
if (want_to_read == 0)
|
||||
{
|
||||
want_to_read = head_.bytes_per_line;
|
||||
off -= line;
|
||||
len = line;
|
||||
rcv = 0;
|
||||
dst = data_->buffer(off, &len);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = want_to_read;
|
||||
dst = data_->buffer(off + rcv, &len);
|
||||
}
|
||||
}
|
||||
}
|
||||
ok = off == h.length();
|
||||
}
|
||||
|
||||
if (ok)
|
||||
{
|
||||
if (channel() == 3)
|
||||
{
|
||||
// swap RGB
|
||||
unsigned long long off = 0;
|
||||
unsigned int line = line_bytes(), len = line;
|
||||
for (int i = 0; i < height(); ++i)
|
||||
{
|
||||
int l = head_.bytes_per_line, cur = 0;
|
||||
|
||||
off = i * line + h.length();
|
||||
while (l > 0)
|
||||
{
|
||||
len = l;
|
||||
dst = data_->buffer(off + cur, &len);
|
||||
if (!dst)
|
||||
break;
|
||||
if (len > l)
|
||||
len = l;
|
||||
len /= 3;
|
||||
for (int pos = 0; pos < len; ++pos)
|
||||
{
|
||||
unsigned char uc = dst[pos * 3 + 0];
|
||||
dst[pos * 3 + 0] = dst[pos * 3 + 2];
|
||||
dst[pos * 3 + 2] = uc;
|
||||
}
|
||||
l -= len * 3;
|
||||
cur += len * 3;
|
||||
}
|
||||
if (!dst)
|
||||
break;
|
||||
}
|
||||
}
|
||||
data_->unmap();
|
||||
}
|
||||
else
|
||||
{
|
||||
delete data_;
|
||||
data_ = NULL;
|
||||
}
|
||||
}
|
||||
scanned_img::~scanned_img()
|
||||
{
|
||||
if (data_)
|
||||
delete[] data_;
|
||||
delete data_;
|
||||
}
|
||||
|
||||
std::string scanned_img::file_header(SANE_ImageType type, float resolution)
|
||||
|
@ -131,11 +464,23 @@ COM_API_IMPLEMENT(scanned_img, SANE_Frame, type(void))
|
|||
}
|
||||
COM_API_IMPLEMENT(scanned_img, unsigned int, bytes(void))
|
||||
{
|
||||
return bytes_;
|
||||
return data_ ? data_->bytes() : 0;
|
||||
}
|
||||
COM_API_IMPLEMENT(scanned_img, unsigned char*, bits(void))
|
||||
COM_API_IMPLEMENT(scanned_img, unsigned char*, data(unsigned long long off, unsigned int* bytes))
|
||||
{
|
||||
return data_;
|
||||
return data_ ? data_->buffer(off, bytes) : NULL;
|
||||
}
|
||||
COM_API_IMPLEMENT(scanned_img, const char*, file(void))
|
||||
{
|
||||
if (data_)
|
||||
return data_->file();
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
COM_API_IMPLEMENT(scanned_img, void, keep_file(bool keep))
|
||||
{
|
||||
if (data_)
|
||||
data_->set_remove_file_when_destroyed(!keep);
|
||||
}
|
||||
COM_API_IMPLEMENT(scanned_img, void, copy_header(SANE_Parameters* head))
|
||||
{
|
||||
|
|
|
@ -16,16 +16,49 @@ public:
|
|||
COM_API_OVERRIDE(long, release(void));
|
||||
};
|
||||
|
||||
class mapping_buf
|
||||
{
|
||||
unsigned long long bytes_;
|
||||
unsigned long long offset_;
|
||||
unsigned int page_size_;
|
||||
unsigned int map_unit_;
|
||||
unsigned int mapped_bytes_;
|
||||
HANDLE map_;
|
||||
bool is_mem_;
|
||||
unsigned char* buf_;
|
||||
std::string file_;
|
||||
bool rmv_file_;
|
||||
|
||||
void init_map(const char* file, unsigned long long size);
|
||||
void close(void);
|
||||
void map(void);
|
||||
void set_buffer(unsigned char*& buf, unsigned long long off, unsigned int* bytes);
|
||||
|
||||
public:
|
||||
mapping_buf();
|
||||
~mapping_buf();
|
||||
|
||||
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);
|
||||
void unmap();
|
||||
void set_remove_file_when_destroyed(bool rmv);
|
||||
const char* file(void);
|
||||
unsigned long long bytes(void);
|
||||
unsigned long long offset(void);
|
||||
unsigned int mapped_bytes(void);
|
||||
};
|
||||
class scanned_img : public IScanImg, virtual public refer
|
||||
{
|
||||
SANE_Parameters head_;
|
||||
unsigned char* data_;
|
||||
unsigned int bytes_;
|
||||
mapping_buf* data_;
|
||||
int dpi_;
|
||||
|
||||
std::string file_header(SANE_ImageType type, float resolution);
|
||||
|
||||
public:
|
||||
scanned_img(SANE_Parameters head, unsigned char* data);
|
||||
scanned_img(SANE_Parameters head, SANE_Handle dev, int dpi, const wchar_t* tmp_file);
|
||||
|
||||
|
||||
protected:
|
||||
|
@ -45,7 +78,14 @@ 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 char*, bits(void));
|
||||
COM_API_OVERRIDE(unsigned char*, data(unsigned long long off, unsigned int* bytes));
|
||||
COM_API_OVERRIDE(const char*, file(void));
|
||||
COM_API_OVERRIDE(void, keep_file(bool keep));
|
||||
COM_API_OVERRIDE(void, copy_header(SANE_Parameters* head));
|
||||
};
|
||||
|
||||
namespace local_trans
|
||||
{
|
||||
std::string u2a(const wchar_t* unic, UINT cp = CP_ACP);
|
||||
std::wstring a2u(const char* asc, UINT cp = CP_ACP);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,13 @@ static IMPLEMENT_OPTION_STRING_COMPARE(compare_sane_opt);
|
|||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// class scanner
|
||||
scanner::scanner(SCANNERID id) : handle_(NULL), id_(id), ex_id_(EXTENSION_ID_BASE), prev_start_result_(SCANNER_ERR_NOT_START)
|
||||
, dpi_(200), tmp_path_(L""), img_ind_(0)
|
||||
{
|
||||
tmp_path_ = local_trans::a2u(hg_sane_middleware::sane_path().c_str());
|
||||
tmp_path_ += L"imgs";
|
||||
CreateDirectoryW(tmp_path_.c_str(), NULL);
|
||||
tmp_path_ += L"\\";
|
||||
|
||||
err_ = open();
|
||||
}
|
||||
scanner::~scanner()
|
||||
|
@ -419,32 +425,50 @@ int scanner::set_option_value(int sn, SANE_Value_Type type, int size, void* data
|
|||
SANE_Int si = 0, after = 0;
|
||||
SANE_Fixed sf = 0;
|
||||
int ret = SCANNER_ERR_OK;
|
||||
void* val = data;
|
||||
|
||||
if (type == SANE_TYPE_BOOL)
|
||||
{
|
||||
sb = *(bool*)data ? SANE_TRUE : SANE_FALSE;
|
||||
data = &sb;
|
||||
val = &sb;
|
||||
}
|
||||
else if (type == SANE_TYPE_INT)
|
||||
{
|
||||
si = *(int*)data;
|
||||
data = &si;
|
||||
val = &si;
|
||||
}
|
||||
else if (type == SANE_TYPE_FIXED)
|
||||
{
|
||||
sf = SANE_FIX(*(float*)data);
|
||||
data = &sf;
|
||||
val = &sf;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf = new char[size + 4];
|
||||
memset(buf, 0, size + 4);
|
||||
strcpy(buf, ((std::string*)data)->c_str());
|
||||
data = buf;
|
||||
val = buf;
|
||||
}
|
||||
ret = hg_sane_middleware::instance()->set_option(handle_, sn, SANE_ACTION_SET_VALUE, data, &after);
|
||||
if (buf)
|
||||
|
||||
ret = hg_sane_middleware::instance()->set_option(handle_, sn, SANE_ACTION_SET_VALUE, val, &after);
|
||||
|
||||
if (type == SANE_TYPE_BOOL)
|
||||
{
|
||||
*(bool*)data = sb == SANE_TRUE;
|
||||
}
|
||||
else if (type == SANE_TYPE_INT)
|
||||
{
|
||||
*(int*)data = si;
|
||||
}
|
||||
else if (type == SANE_TYPE_FIXED)
|
||||
{
|
||||
*(float*)data = SANE_UNFIX(sf);
|
||||
}
|
||||
else if(buf)
|
||||
{
|
||||
strcpy((char*)val, buf);
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1345,7 +1369,7 @@ COM_API_IMPLEMENT(scanner, int, start(void))
|
|||
|
||||
prev_start_result_ = ret;
|
||||
|
||||
return ret;
|
||||
return local_utility::sane_statu_2_scanner_err(ret);
|
||||
}
|
||||
COM_API_IMPLEMENT(scanner, int, stop(void))
|
||||
{
|
||||
|
@ -1392,19 +1416,9 @@ COM_API_IMPLEMENT(scanner, IScanImg*, take_first_image(void))
|
|||
|
||||
if (hg_sane_middleware::instance()->get_image_parameters(handle_, &head) == SANE_STATUS_GOOD)
|
||||
{
|
||||
int off = 0, size = head.bytes_per_line * head.lines, rcv = size;
|
||||
unsigned char* buf = new unsigned char[size];
|
||||
|
||||
while (hg_sane_middleware::instance()->read(handle_, buf + off, &rcv) == SANE_STATUS_GOOD)
|
||||
{
|
||||
off += rcv;
|
||||
if (off >= size)
|
||||
break;
|
||||
rcv = size - off;
|
||||
}
|
||||
|
||||
img = new scanned_img(head, buf);
|
||||
delete[] buf;
|
||||
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());
|
||||
}
|
||||
|
||||
return dynamic_cast<IScanImg*>(img);
|
||||
|
@ -1476,6 +1490,8 @@ COM_API_IMPLEMENT(scanner, bool, get_value(int sn, set_opt_value setval, void* p
|
|||
|
||||
hg_sane_middleware::instance()->get_cur_value(handle_, sn, &cur);
|
||||
val = cur;
|
||||
if (sn == resolution_id_)
|
||||
dpi_ = cur;
|
||||
do
|
||||
{
|
||||
if (desc->constraint_type == SANE_CONSTRAINT_RANGE)
|
||||
|
@ -1508,6 +1524,8 @@ COM_API_IMPLEMENT(scanner, bool, get_value(int sn, set_opt_value setval, void* p
|
|||
float val = .0f;
|
||||
|
||||
hg_sane_middleware::instance()->get_cur_value(handle_, sn, &cur);
|
||||
if (sn == resolution_id_)
|
||||
dpi_ = SANE_UNFIX(cur) + .5f;
|
||||
do
|
||||
{
|
||||
if (desc->constraint_type == SANE_CONSTRAINT_RANGE)
|
||||
|
@ -1594,6 +1612,14 @@ COM_API_IMPLEMENT(scanner, int, set_value(int sn, void* val))
|
|||
ret = (this->*ex->ex_api)(ex->base_ind, val, NULL);
|
||||
}
|
||||
|
||||
if (sn == resolution_id_)
|
||||
{
|
||||
if (desc->type == SANE_TYPE_FIXED)
|
||||
dpi_ = *(float*)val + .5f;
|
||||
else
|
||||
dpi_ = *(int*)val;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,9 @@ class scanner : public ISaneInvoker, virtual public refer
|
|||
int err_;
|
||||
int ex_id_;
|
||||
int prev_start_result_;
|
||||
int dpi_;
|
||||
unsigned int img_ind_;
|
||||
std::wstring tmp_path_;
|
||||
|
||||
int open(void);
|
||||
int close(void);
|
||||
|
|
|
@ -926,7 +926,9 @@ Result huagao_ds::imageMemXferGet(const Identity& origin, ImageMemXfer& data)
|
|||
return seqError();
|
||||
|
||||
IScanImg *img = scanner_->take_first_image();
|
||||
unsigned char *src = img->bits() + img->bytes() - img->line_bytes(),
|
||||
unsigned long long off = 0;
|
||||
unsigned int total = img->bytes();
|
||||
unsigned char *src = img->data(off, &total),
|
||||
*dst = NULL;
|
||||
|
||||
data.setBytesPerRow(img->line_bytes());
|
||||
|
@ -937,8 +939,16 @@ Result huagao_ds::imageMemXferGet(const Identity& origin, ImageMemXfer& data)
|
|||
data.setYOffset(0);
|
||||
data.setCompression(Compression::None);
|
||||
dst = (unsigned char*)data.memory().data().data();
|
||||
for (int i = 0; i < img->height(); ++i, src -= img->line_bytes(), dst += img->line_bytes())
|
||||
std::copy(src, src + img->line_bytes(), dst);
|
||||
while (off < img->bytes() && src)
|
||||
{
|
||||
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->release();
|
||||
|
||||
return success();
|
||||
|
@ -955,7 +965,21 @@ Result huagao_ds::imageNativeXferGet(const Identity& id, ImageNativeXfer& data)
|
|||
if (data)
|
||||
data.release();
|
||||
data = ImageNativeXfer(img->bytes());
|
||||
std::copy(img->bits(), img->bits() + img->bytes(), data.data<unsigned char>().data());
|
||||
|
||||
unsigned long long off = 0;
|
||||
unsigned int total = img->bytes();
|
||||
unsigned char* src = img->data(off, &total),
|
||||
* dst = data.data<unsigned char>().data();
|
||||
while (off < img->bytes() && src)
|
||||
{
|
||||
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->release();
|
||||
|
||||
return { ReturnCode::XferDone, ConditionCode::Success };
|
||||
|
@ -978,17 +1002,43 @@ Twpp::Result huagao_ds::imageFileXferGet(const Twpp::Identity& origin)
|
|||
|
||||
if (img)
|
||||
{
|
||||
dst = fopen(m_fileXfer.filePath().string().c_str(), "wb");
|
||||
ret = { ReturnCode::Failure, ConditionCode::FileWriteError };
|
||||
if (dst)
|
||||
std::string file(img->file());
|
||||
if (file.empty())
|
||||
{
|
||||
if(fwrite(img->bits(), 1, img->bytes(), dst) == img->bytes())
|
||||
ret = Result(ReturnCode::XferDone, ConditionCode::Success);
|
||||
dst = fopen(m_fileXfer.filePath().string().c_str(), "wb");
|
||||
ret = { ReturnCode::Failure, ConditionCode::FileWriteError };
|
||||
if (dst)
|
||||
{
|
||||
unsigned long long off = 0;
|
||||
unsigned int total = img->bytes();
|
||||
unsigned char* src = img->data(off, &total);
|
||||
while (src)
|
||||
{
|
||||
if (fwrite(src, 1, total, dst) != total)
|
||||
break;
|
||||
off += total;
|
||||
if (off >= img->bytes())
|
||||
{
|
||||
ret = Result(ReturnCode::XferDone, ConditionCode::Success);
|
||||
break;
|
||||
}
|
||||
total = img->bytes() - off;
|
||||
src = img->data(off, &total);
|
||||
}
|
||||
|
||||
fclose(dst);
|
||||
fclose(dst);
|
||||
}
|
||||
img->release();
|
||||
}
|
||||
else
|
||||
{
|
||||
img->keep_file(true);
|
||||
img->release();
|
||||
if (MoveFileA(file.c_str(), m_fileXfer.filePath().string().c_str()))
|
||||
ret = Result(ReturnCode::XferDone, ConditionCode::Success);
|
||||
else
|
||||
DeleteFileA(file.c_str());
|
||||
}
|
||||
|
||||
img->release();
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
Loading…
Reference in New Issue