code_twain/sane/scanned_img.h

209 lines
4.8 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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);
}