code_twain/sane/scanned_img.h

204 lines
4.7 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_;
std::string file_header(SANE_ImageType type, float resolution, twain_xfer xfer);
void do_result(bool ok, twain_xfer xfer);
void swap_rgb(void);
public:
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_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));
};
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);
}