#pragma once #include "s2t_api.h" #include #include #include "../../sdk/hginclude/utils.h" class image_buf { unsigned long long bytes_; unsigned long long offset_; unsigned int mapped_bytes_; bool is_mem_; unsigned char* buf_; void close(void); public: image_buf(); ~image_buf(); public: unsigned char* allocate(const char* file, unsigned long long size = 0, bool force_file = false); bool save(const void* data, size_t* bytes, unsigned long long off); bool save(unsigned long long off, image_buf* src); unsigned long long bytes(void); unsigned long long size(void); unsigned char* buffer(unsigned long long off, unsigned int* bytes); int read(void* buf, size_t* bytes, unsigned long long off); }; class scanned_img : public IScanImg, virtual public refer { SANE_Parameters head_; int dpi_; SANE_Handle dev_; std::string file_; unsigned int header_size_; SANE_FinalImgFormat fmt_; SANE_Image_Statu status_; image_buf* data_; size_t pal_size_ = 0; // 部分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 char* 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(int32_t, add_ref(void)); COM_API_OVERRIDE(int32_t, 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 safe_queue { typedef struct _t_and_size { size_t bytes; T t; }TNS; std::mutex lock_; std::vector 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 lock(lock_); if (bytes) *bytes = bytes_; return queue_.size(); } bool save(T v, size_t bytes) { std::lock_guard lock(lock_); TNS tns = { bytes, v }; queue_.push_back(tns); bytes_ += bytes; return true; } T take(bool remove = true, void(* first)(T) = NULL) { std::lock_guard 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(* tfree)(T) = NULL) { std::lock_guard lock(lock_); if (tfree) { for (auto& v : queue_) tfree(v.t); } queue_.clear(); bytes_ = 0; } }; class safe_img_queue : public safe_queue { static void access_image(scanned_img* img); static void 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 { int load_lang_pak(const char* dll); std::string lang_trans_between_hz936(const char* in, bool from_hz = true); const char* lang_trans_between_hz936(const char* in, bool from_hz, void* param); const char* to_default_language(const char* str, bool* ok = nullptr); const char* from_default_language(const char* str, bool* ok = nullptr); }