2022-06-15 03:04:40 +00:00
|
|
|
|
#include "scanned_img.h"
|
|
|
|
|
|
|
|
|
|
#include <Windows.h>
|
2022-06-16 08:04:58 +00:00
|
|
|
|
#include <Shlwapi.h>
|
|
|
|
|
#pragma comment(lib, "Shlwapi.lib")
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
2022-06-16 08:04:58 +00:00
|
|
|
|
#include "../../code_device/hgsane/sane_hg_mdw.h"
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
|
|
|
|
|
2022-06-16 08:04:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-15 03:04:40 +00:00
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// class refer
|
|
|
|
|
refer::refer() : ref_(1)
|
|
|
|
|
{}
|
|
|
|
|
refer::~refer()
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
COM_API_IMPLEMENT(refer, long, add_ref(void))
|
|
|
|
|
{
|
|
|
|
|
return InterlockedIncrement(&ref_);
|
|
|
|
|
}
|
|
|
|
|
COM_API_IMPLEMENT(refer, long, release(void))
|
|
|
|
|
{
|
|
|
|
|
long ref = InterlockedDecrement(&ref_);
|
|
|
|
|
|
|
|
|
|
if (ref == 0)
|
|
|
|
|
delete this;
|
|
|
|
|
|
|
|
|
|
return ref;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-06-16 08:04:58 +00:00
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// 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)
|
|
|
|
|
{
|
|
|
|
|
SYSTEM_INFO si = { 0 };
|
|
|
|
|
|
|
|
|
|
GetSystemInfo(&si);
|
|
|
|
|
page_size_ = si.dwPageSize;
|
|
|
|
|
map_unit_ = si.dwAllocationGranularity;
|
|
|
|
|
}
|
|
|
|
|
mapping_buf::~mapping_buf()
|
|
|
|
|
{
|
|
|
|
|
close();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void mapping_buf::init_map(const char* file, unsigned long long size)
|
|
|
|
|
{
|
|
|
|
|
HANDLE f = INVALID_HANDLE_VALUE;
|
|
|
|
|
|
|
|
|
|
if (size)
|
|
|
|
|
{
|
|
|
|
|
f = CreateFileA(file, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
|
if (f != INVALID_HANDLE_VALUE)
|
|
|
|
|
{
|
|
|
|
|
unsigned long long total = size - 1;
|
|
|
|
|
LONG* p32 = (LONG*)&total;
|
|
|
|
|
*p32 = SetFilePointer(f, *p32, p32 + 1, FILE_BEGIN);
|
|
|
|
|
total++;
|
|
|
|
|
if (total == size)
|
|
|
|
|
{
|
|
|
|
|
DWORD wrote = 1;
|
|
|
|
|
WriteFile(f, "\0", 1, &wrote, NULL);
|
|
|
|
|
map_ = CreateFileMapping(f, NULL, PAGE_READWRITE, p32[1], p32[0], NULL);
|
|
|
|
|
}
|
|
|
|
|
CloseHandle(f);
|
|
|
|
|
if (!map_)
|
|
|
|
|
DeleteFileA(file);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
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;
|
2022-06-17 03:50:18 +00:00
|
|
|
|
bytes_ = mapped_bytes_ = size;
|
2022-06-16 08:04:58 +00:00
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
}
|
2022-06-17 03:50:18 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
2022-06-16 08:04:58 +00:00
|
|
|
|
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)
|
|
|
|
|
{
|
2022-06-17 03:50:18 +00:00
|
|
|
|
return is_mem_ ? "" : file_.c_str();
|
2022-06-16 08:04:58 +00:00
|
|
|
|
}
|
|
|
|
|
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_;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-15 03:04:40 +00:00
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// class scanned_img
|
2022-06-16 09:28:46 +00:00
|
|
|
|
scanned_img::scanned_img(SANE_Parameters head, SANE_Handle dev, int dpi
|
2022-06-17 03:50:18 +00:00
|
|
|
|
, const wchar_t* tmp_file, twain_xfer xfer
|
|
|
|
|
, SANE_FinalImgFormat *fmt) : head_(head), dpi_(dpi), header_size_(0)
|
2022-06-15 03:04:40 +00:00
|
|
|
|
{
|
2022-06-17 03:50:18 +00:00
|
|
|
|
if (fmt)
|
|
|
|
|
fmt_ = *fmt;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fmt_.img_format = SANE_IMAGE_TYPE_BMP;
|
|
|
|
|
fmt_.detail = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-15 03:04:40 +00:00
|
|
|
|
size_t bytes = line_bytes() * height();
|
2022-06-17 03:50:18 +00:00
|
|
|
|
std::string h(file_header(fmt_.img_format, dpi, xfer));
|
2022-06-16 08:04:58 +00:00
|
|
|
|
unsigned char* dst = NULL;
|
|
|
|
|
bool ok = false;
|
|
|
|
|
|
|
|
|
|
data_ = new mapping_buf();
|
2022-06-17 03:50:18 +00:00
|
|
|
|
header_size_ = h.length();
|
2022-06-16 08:04:58 +00:00
|
|
|
|
dst = data_->allocate(tmp_file, bytes + h.length());
|
|
|
|
|
if (dst)
|
|
|
|
|
{
|
2022-06-17 03:50:18 +00:00
|
|
|
|
unsigned long long off = 0, total = 0;
|
2022-06-16 08:04:58 +00:00
|
|
|
|
bytes = h.length();
|
|
|
|
|
if (data_->save(h.c_str(), &bytes, off))
|
|
|
|
|
{
|
2022-06-17 03:50:18 +00:00
|
|
|
|
unsigned int len = line_bytes();
|
|
|
|
|
unsigned long long line = line_bytes();
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
2022-06-17 03:50:18 +00:00
|
|
|
|
if (xfer == TWAIN_XFER_Memory)
|
|
|
|
|
line *= -1;
|
|
|
|
|
else
|
|
|
|
|
off = data_->bytes() - line;
|
2022-06-16 08:04:58 +00:00
|
|
|
|
dst = data_->buffer(off, &len);
|
2022-06-15 03:04:40 +00:00
|
|
|
|
|
2022-06-16 08:04:58 +00:00
|
|
|
|
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);
|
2022-06-17 03:50:18 +00:00
|
|
|
|
total += r;
|
2022-06-16 08:04:58 +00:00
|
|
|
|
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;
|
2022-06-17 03:50:18 +00:00
|
|
|
|
len = line_bytes();
|
2022-06-16 08:04:58 +00:00
|
|
|
|
rcv = 0;
|
|
|
|
|
dst = data_->buffer(off, &len);
|
2022-06-17 03:50:18 +00:00
|
|
|
|
total += dif;
|
2022-06-16 08:04:58 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
len = want_to_read;
|
|
|
|
|
dst = data_->buffer(off + rcv, &len);
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-06-17 03:50:18 +00:00
|
|
|
|
ok = total + h.length() + dif == data_->bytes();
|
2022-06-16 08:04:58 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ok)
|
2022-06-15 03:04:40 +00:00
|
|
|
|
{
|
2022-06-17 03:50:18 +00:00
|
|
|
|
if (fmt_.img_format == SANE_IMAGE_TYPE_BMP && channel() == 3 &&
|
|
|
|
|
xfer != TWAIN_XFER_Memory)
|
2022-06-15 03:04:40 +00:00
|
|
|
|
{
|
2022-06-16 08:04:58 +00:00
|
|
|
|
// swap RGB
|
|
|
|
|
unsigned long long off = 0;
|
|
|
|
|
unsigned int line = line_bytes(), len = line;
|
|
|
|
|
for (int i = 0; i < height(); ++i)
|
2022-06-15 03:04:40 +00:00
|
|
|
|
{
|
2022-06-16 08:04:58 +00:00
|
|
|
|
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;
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-06-16 08:04:58 +00:00
|
|
|
|
data_->unmap();
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2022-06-16 08:04:58 +00:00
|
|
|
|
delete data_;
|
|
|
|
|
data_ = NULL;
|
2022-06-17 03:50:18 +00:00
|
|
|
|
header_size_ = 0;
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
scanned_img::~scanned_img()
|
|
|
|
|
{
|
|
|
|
|
if (data_)
|
2022-06-16 08:04:58 +00:00
|
|
|
|
delete data_;
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-16 09:28:46 +00:00
|
|
|
|
std::string scanned_img::file_header(SANE_ImageType type, float resolution, twain_xfer xfer)
|
2022-06-15 03:04:40 +00:00
|
|
|
|
{
|
|
|
|
|
std::string h("");
|
|
|
|
|
|
2022-06-17 03:50:18 +00:00
|
|
|
|
if (type == SANE_IMAGE_TYPE_BMP && xfer != TWAIN_XFER_Memory)
|
2022-06-15 03:04:40 +00:00
|
|
|
|
{
|
|
|
|
|
BITMAPINFOHEADER bih = { 0 };
|
|
|
|
|
|
|
|
|
|
bih.biSize = sizeof(bih);
|
|
|
|
|
bih.biWidth = width();
|
|
|
|
|
bih.biBitCount = depth();
|
|
|
|
|
bih.biSizeImage = line_bytes() * height();
|
|
|
|
|
bih.biPlanes = 1;
|
|
|
|
|
bih.biHeight = height();
|
|
|
|
|
bih.biCompression = BI_RGB;
|
|
|
|
|
bih.biXPelsPerMeter = bih.biYPelsPerMeter = resolution * 39.37f + .5f;
|
|
|
|
|
|
2022-06-16 09:28:46 +00:00
|
|
|
|
if (xfer == TWAIN_XFER_File)
|
|
|
|
|
{
|
|
|
|
|
BITMAPFILEHEADER fh = { 0 };
|
|
|
|
|
fh.bfType = MAKEWORD('B', 'M');
|
|
|
|
|
fh.bfSize = sizeof(fh) + bih.biSizeImage + sizeof(bih);
|
|
|
|
|
fh.bfOffBits = sizeof(fh) + sizeof(bih);
|
|
|
|
|
|
|
|
|
|
h = std::string((char*)&fh, sizeof(fh));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
h += std::string((char*)&bih, sizeof(bih));
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return h;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IRef
|
|
|
|
|
COM_API_IMPLEMENT(scanned_img, long, add_ref(void))
|
|
|
|
|
{
|
|
|
|
|
return refer::add_ref();
|
|
|
|
|
}
|
|
|
|
|
COM_API_IMPLEMENT(scanned_img, long, release(void))
|
|
|
|
|
{
|
|
|
|
|
return refer::release();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IScanImg
|
|
|
|
|
COM_API_IMPLEMENT(scanned_img, int, width(void))
|
|
|
|
|
{
|
|
|
|
|
return head_.pixels_per_line;
|
|
|
|
|
}
|
|
|
|
|
COM_API_IMPLEMENT(scanned_img, int, line_bytes(void))
|
|
|
|
|
{
|
2022-06-17 03:50:18 +00:00
|
|
|
|
if (fmt_.img_format == SANE_IMAGE_TYPE_BMP)
|
|
|
|
|
return (head_.bytes_per_line + 3) / 4 * 4;
|
|
|
|
|
else
|
|
|
|
|
return head_.bytes_per_line;
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
COM_API_IMPLEMENT(scanned_img, int, height(void))
|
|
|
|
|
{
|
|
|
|
|
return head_.lines;
|
|
|
|
|
}
|
|
|
|
|
COM_API_IMPLEMENT(scanned_img, int, depth(void))
|
|
|
|
|
{
|
|
|
|
|
if (head_.format == SANE_FRAME_RGB)
|
|
|
|
|
return head_.depth * 3;
|
|
|
|
|
else
|
|
|
|
|
return head_.depth;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
COM_API_IMPLEMENT(scanned_img, int, channel(void))
|
|
|
|
|
{
|
|
|
|
|
return head_.format == SANE_FRAME_RGB ? 3 : 1;
|
|
|
|
|
}
|
|
|
|
|
COM_API_IMPLEMENT(scanned_img, SANE_Frame, type(void))
|
|
|
|
|
{
|
|
|
|
|
return head_.format;
|
|
|
|
|
}
|
|
|
|
|
COM_API_IMPLEMENT(scanned_img, unsigned int, bytes(void))
|
|
|
|
|
{
|
2022-06-16 08:04:58 +00:00
|
|
|
|
return data_ ? data_->bytes() : 0;
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
2022-06-17 03:50:18 +00:00
|
|
|
|
COM_API_IMPLEMENT(scanned_img, unsigned int, header_size(void))
|
|
|
|
|
{
|
|
|
|
|
return header_size_;
|
|
|
|
|
}
|
2022-06-16 08:04:58 +00:00
|
|
|
|
COM_API_IMPLEMENT(scanned_img, unsigned char*, data(unsigned long long off, unsigned int* bytes))
|
2022-06-15 03:04:40 +00:00
|
|
|
|
{
|
2022-06-16 08:04:58 +00:00
|
|
|
|
return data_ ? data_->buffer(off, bytes) : NULL;
|
|
|
|
|
}
|
2022-06-17 03:50:18 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-16 08:04:58 +00:00
|
|
|
|
COM_API_IMPLEMENT(scanned_img, const char*, file(void))
|
|
|
|
|
{
|
|
|
|
|
if (data_)
|
|
|
|
|
return data_->file();
|
|
|
|
|
else
|
2022-06-17 03:50:18 +00:00
|
|
|
|
return "";
|
2022-06-16 08:04:58 +00:00
|
|
|
|
}
|
|
|
|
|
COM_API_IMPLEMENT(scanned_img, void, keep_file(bool keep))
|
|
|
|
|
{
|
|
|
|
|
if (data_)
|
|
|
|
|
data_->set_remove_file_when_destroyed(!keep);
|
2022-06-15 03:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
COM_API_IMPLEMENT(scanned_img, void, copy_header(SANE_Parameters* head))
|
|
|
|
|
{
|
|
|
|
|
*head = head_;
|
|
|
|
|
}
|