209 lines
4.8 KiB
C++
209 lines
4.8 KiB
C++
#pragma once
|
||
#include "s2t_api.h"
|
||
#include <vector>
|
||
#include <mutex>
|
||
|
||
class refer : public IRef
|
||
{
|
||
volatile long ref_;
|
||
|
||
protected:
|
||
refer();
|
||
virtual ~refer();
|
||
|
||
// IRef
|
||
public:
|
||
COM_API_OVERRIDE(long, add_ref(void));
|
||
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, 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);
|
||
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_;
|
||
mapping_buf* data_;
|
||
int dpi_;
|
||
SANE_Handle dev_;
|
||
std::wstring file_;
|
||
unsigned int header_size_;
|
||
SANE_FinalImgFormat fmt_;
|
||
size_t pal_size_;
|
||
|
||
SANE_Image_Statu status_;
|
||
|
||
// 部分APP不会通过XferMech来设置传输模式,原来预先准备数据的方法不适合该场合
|
||
// 为适应该场景,增加prepare_data_for_transfer接口,在真实读取数据之前调用,以准备恰当的数据
|
||
bool data_done_ = false;
|
||
|
||
std::string file_header(SANE_ImageType type, float resolution);
|
||
void do_result(twain_xfer xfer);
|
||
void swap_rgb(void);
|
||
|
||
public:
|
||
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);
|
||
|
||
void set_image_status(SANE_Image_Statu status);
|
||
|
||
protected:
|
||
~scanned_img();
|
||
|
||
// IRef
|
||
public:
|
||
COM_API_OVERRIDE(long, add_ref(void));
|
||
COM_API_OVERRIDE(long, release(void));
|
||
|
||
// IScanImg
|
||
public:
|
||
COM_API_OVERRIDE(int, width(void));
|
||
COM_API_OVERRIDE(int, line_bytes(void));
|
||
COM_API_OVERRIDE(int, height(void));
|
||
COM_API_OVERRIDE(int, depth(void));
|
||
COM_API_OVERRIDE(int, channel(void));
|
||
COM_API_OVERRIDE(int, dpi(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));
|
||
COM_API_OVERRIDE(int, image_status(void));
|
||
COM_API_OVERRIDE(size_t, get_bits_offset(void));
|
||
|
||
public:
|
||
void prepare_data_for_transfer(twain_xfer xfer);
|
||
};
|
||
|
||
template<class T>
|
||
class safe_queue
|
||
{
|
||
typedef struct _t_and_size
|
||
{
|
||
size_t bytes;
|
||
T t;
|
||
}TNS;
|
||
std::mutex lock_;
|
||
std::vector<TNS> queue_;
|
||
size_t bytes_;
|
||
T empty_;
|
||
|
||
public:
|
||
safe_queue() : bytes_(0)
|
||
{}
|
||
virtual ~safe_queue()
|
||
{}
|
||
|
||
public:
|
||
size_t count(size_t* bytes = NULL)
|
||
{
|
||
std::lock_guard<std::mutex> lock(lock_);
|
||
|
||
if (bytes)
|
||
*bytes = bytes_;
|
||
|
||
return queue_.size();
|
||
}
|
||
bool save(T v, size_t bytes)
|
||
{
|
||
std::lock_guard<std::mutex> lock(lock_);
|
||
TNS tns = { bytes, v };
|
||
|
||
queue_.push_back(tns);
|
||
bytes_ += bytes;
|
||
|
||
return true;
|
||
}
|
||
T take(bool remove = true, void(__stdcall* first)(T) = NULL)
|
||
{
|
||
std::lock_guard<std::mutex> lock(lock_);
|
||
TNS t;
|
||
|
||
if (queue_.size())
|
||
{
|
||
t = queue_[0];
|
||
if (remove)
|
||
{
|
||
queue_.erase(queue_.begin());
|
||
bytes_ -= t.bytes;
|
||
}
|
||
if (first)
|
||
first(t.t);
|
||
}
|
||
else
|
||
t.t = empty_;
|
||
|
||
return t.t;
|
||
}
|
||
void clear(void(__stdcall* tfree)(T) = NULL)
|
||
{
|
||
std::lock_guard<std::mutex> lock(lock_);
|
||
|
||
if (tfree)
|
||
{
|
||
for (auto& v : queue_)
|
||
tfree(v.t);
|
||
}
|
||
queue_.clear();
|
||
bytes_ = 0;
|
||
}
|
||
};
|
||
|
||
class safe_img_queue : public safe_queue<scanned_img*>
|
||
{
|
||
static void __stdcall access_image(scanned_img* img);
|
||
static void __stdcall free_image(scanned_img* img);
|
||
|
||
public:
|
||
safe_img_queue();
|
||
~safe_img_queue();
|
||
|
||
public:
|
||
bool get_header(SANE_Parameters* header, size_t* bytes = NULL, int *dpi = NULL);
|
||
void clear();
|
||
};
|
||
|
||
namespace local_trans
|
||
{
|
||
std::string u2a(const wchar_t* unic, UINT cp = CP_ACP);
|
||
std::wstring a2u(const char* asc, UINT cp = CP_ACP);
|
||
|
||
std::wstring lang_trans_between_hz936(const wchar_t* in, bool from_hz = true);
|
||
const char* __stdcall lang_trans_between_hz936(const char* in, bool from_hz, void* param);
|
||
}
|