diff --git a/hgdriver/hgdev/BlockingQueue.h b/hgdriver/hgdev/BlockingQueue.h index c8ce347..13ea81f 100644 --- a/hgdriver/hgdev/BlockingQueue.h +++ b/hgdriver/hgdev/BlockingQueue.h @@ -123,8 +123,10 @@ typedef struct _img_header }IMH; typedef struct _img { - IMH header; - unsigned offset; + IMH header; + unsigned offset; + bool is_file; // when this is true, then the 'data' stores the full path of the file + void* fptr; std::shared_ptr> data; }IMGDT; class image_data @@ -184,7 +186,7 @@ public: } } - void put(int w, int h, int bpp, int channels, int line_bytes, void* data, unsigned bytes) + bool put(int w, int h, int bpp, int channels, int line_bytes, void* data, unsigned bytes) { IMGDT img; img.header.width = w; @@ -194,10 +196,48 @@ public: img.header.line_bytes = line_bytes; img.offset = 0; img.header.bytes = bytes; - img.data.reset(new std::vector); - img.data->resize(bytes); + img.data.reset(new std::vector(bytes)); + if (!img.data.get()) + return false; + + img.is_file = false; + img.fptr = nullptr; memcpy(img.data->data(), data, bytes); Put(img); + + return true; + } + bool put(int w, int h, int bpp, int channels, int line_bytes, void* data, unsigned bytes, const char* file) + { + IMGDT img; + img.header.width = w; + img.header.height = h; + img.header.bits = bpp; + img.header.channels = channels; + img.header.line_bytes = line_bytes; + img.offset = 0; + img.header.bytes = bytes; + img.is_file = true; + img.fptr = nullptr; + img.data.reset(new std::vector(strlen(file) * 2)); + if (!img.data.get()) + return false; + strcpy((char*)&img.data->data()[0], file); + + FILE* dst = fopen(file, "rw+b"); + if (!dst) + return false; + fwrite(data, 1, bytes, dst); + fclose(dst); + img.fptr = fopen(file, "rb"); // open and keep it + if (!img.fptr) + { + remove(file); + return false; + } + + Put(img); + return true; } IMGDT Take() { @@ -258,20 +298,43 @@ public: else { lock_guard lock(_mutex); - if (_queue.front().data->size() - _queue.front().offset <= *len) + if (_queue.front().is_file) { - *len = _queue.front().data->size() - _queue.front().offset; - memcpy(buf, _queue.front().data->data() + _queue.front().offset, *len); - _queue.pop_front(); - if (over) - *over = true; + if (_queue.front().data->size() - _queue.front().offset <= *len) + { + *len = _queue.front().data->size() - _queue.front().offset; + fread(buf, 1, *len, (FILE*)_queue.front().fptr); + fclose((FILE*)_queue.front().fptr); + remove((const char*)_queue.front().data->data()); + _queue.pop_front(); + if (over) + *over = true; + } + else + { + fread(buf, 1, *len, (FILE*)_queue.front().fptr); + _queue.front().offset += *len; + if (over) + *over = false; + } } else { - memcpy(buf, _queue.front().data->data() + _queue.front().offset, *len); - _queue.front().offset += *len; - if (over) - *over = false; + if (_queue.front().data->size() - _queue.front().offset <= *len) + { + *len = _queue.front().data->size() - _queue.front().offset; + memcpy(buf, _queue.front().data->data() + _queue.front().offset, *len); + _queue.pop_front(); + if (over) + *over = true; + } + else + { + memcpy(buf, _queue.front().data->data() + _queue.front().offset, *len); + _queue.front().offset += *len; + if (over) + *over = false; + } } } } diff --git a/hgdriver/hgdev/hg_scanner.cpp b/hgdriver/hgdev/hg_scanner.cpp index 64cb7b9..d017301 100644 --- a/hgdriver/hgdev/hg_scanner.cpp +++ b/hgdriver/hgdev/hg_scanner.cpp @@ -93,6 +93,14 @@ hg_scanner::hg_scanner(ScannerSerial serial , notify_setting_result_(false), user_cancel_(false), cb_mem_(true), test_1_paper_(false) , setting_count_(0),img_type_(""), online_(false),is_quality_(-1),is_color_fill(false),is_multiout(false) { + final_path_ = hg_log::ini_get("paths", "final_img"); + if(final_path_.empty()) + final_path_ = g_module_path + "imgs"; + if (hg_log::create_folder(final_path_.c_str())) + final_path_ += "/"; + else + final_path_ = ""; + custom_gamma_val_ = new SANE_Gamma; memset(custom_gamma_val_, 0, sizeof(SANE_Gamma)); #ifdef MAPPING_FUNCTION_IN_BASE @@ -1868,9 +1876,25 @@ int hg_scanner::save_final_image(hg_imgproc::LPIMGHEAD head, void* buf) return ui_ev_cb_((scanner_handle)this, SANE_EVENT_IMAGE_OK, &img, &final_img_index_, NULL); } - final_imgs_.put(head->width, head->height, head->bits, head->channels, head->line_bytes, buf, head->total_bytes); + if (resolution_ <= 300 && final_imgs_.put(head->width, head->height, head->bits, head->channels, head->line_bytes, buf, head->total_bytes)) + return SCANNER_ERR_OK; + else + { + // try file ... + char name[40] = { 0 }; - return SCANNER_ERR_OK; + sprintf(name, "img_%05d.dat", final_img_index_); + if (resolution_ <= 300) + { + VLOG_MINI_2(LOG_LEVEL_WARNING, "Memory(%u bytes) allocating failed when save final image, try save to file: %s\n", head->total_bytes, (final_path_ + name).c_str()); + } + if(!final_path_.empty() && + final_imgs_.put(head->width, head->height, head->bits, head->channels, head->line_bytes, buf, head->total_bytes + , (final_path_ + name).c_str())) + return SCANNER_ERR_OK; + else + return SCANNER_ERR_INSUFFICIENT_MEMORY; + } } int hg_scanner::is_running(void) { diff --git a/hgdriver/hgdev/hg_scanner.h b/hgdriver/hgdev/hg_scanner.h index dfbdf44..2ced6a6 100644 --- a/hgdriver/hgdev/hg_scanner.h +++ b/hgdriver/hgdev/hg_scanner.h @@ -22,7 +22,6 @@ #include "PaperSize.h" #ifdef WIN32 -extern std::string g_module_path; // Ending with '\\' #else #include #endif @@ -255,6 +254,7 @@ protected: image_data final_imgs_; // JPG ... unsigned int usb_img_index_; unsigned int final_img_index_; + std::string final_path_; BlockingQueue>> imgs_; BlockingQueue paths_; diff --git a/hgdriver/wrapper/hg_log.cpp b/hgdriver/wrapper/hg_log.cpp index 787ea3a..a6c4138 100644 --- a/hgdriver/wrapper/hg_log.cpp +++ b/hgdriver/wrapper/hg_log.cpp @@ -7,7 +7,13 @@ #ifdef WIN32 #include #include +#include +#include +#include #define MKDIR(a, b) mkdir(a) +#pragma comment(lib, "imagehlp.lib") +#pragma comment(lib, "Psapi.lib") +#pragma comment(lib, "shlwapi.lib") #else #define MKDIR(a, b) mkdir(a, b) #include @@ -28,10 +34,6 @@ #define _INTSIZEOF(n) ((sizeof(n) + sizeof(long) - 1) & ~(sizeof(long) - 1)) #endif -#ifdef WIN32 -extern std::string g_module_path; // Ending with '\\' -#endif - class log_cls { typedef void(*log_to)(const char*, void*); @@ -146,7 +148,132 @@ extern "C" #endif namespace hg_log { + static simple_ini ini_; static log_callback lcb_ = NULL; + + typedef struct _find_file + { + std::string pattern; + std::string found; + }FINDFILE, * LPFF; + static bool on_found(const char* file, void* param) + { + LPFF lpff = (LPFF)param; +#ifdef WIN32 + char pth = '\\'; +#else + char pth = '/'; +#endif + const char* name = strrchr(file, pth); + + if (name++ == nullptr) + name = file; + + std::string lc(name); + str_tolower(lc); + if (lc.find(lpff->pattern) != std::string::npos) + { + lpff->found = file; + return false; + } + + return true; + } +#ifdef WIN32 + static std::string u2a(const wchar_t* u, UINT cp = CP_ACP) + { + std::string a(""); + + if (u) + { + char stack[256] = { 0 }, * 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; + } + static int enum_files(const char* dir, bool recursive, bool(*found_file)(const char* path_file, void* param), void* param) + { + int ret = 0; + HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); + MODULEENTRY32W pei = { 0 }; + + if (h == INVALID_HANDLE_VALUE) + ret = GetLastError(); + else + { + do + { + std::string ansi(u2a(pei.szExePath)); + if (!found_file(ansi.c_str(), param)) + break; + } while (Module32NextW(h, &pei)); + + CloseHandle(h); + } + + return ret; + } +#else + static std::string link_file(const char* lnk) + { + char path[256] = { 0 }; + int len = readlink(lnk, path, sizeof(path) - 1); + + return path; + } + static int enum_files(const char* dir, bool recursive, bool(*found_file)(const char* path_file, void* param), void* param) + { + int ret = 0; + DIR* pdir = nullptr; + struct dirent* ent = nullptr; + + pdir = opendir(dir); + if (!pdir) + return errno; + + while ((ent = readdir(pdir))) + { + if (ent->d_type & DT_DIR) + { + if (recursive) + { + if (strcmp(ent->d_name, ".") && strcmp(ent->d_name, "..")) + { + std::string sub(dir); + sub += "/"; + sub += ent->d_name; + ret = enum_files(sub.c_str(), recursive, found_file, param); + if (ret == 0x5e17) + break; + } + } + } + else + { + std::string file(dir); + + file += "/"; + file += ent->d_name; + if (!found_file(link_file(file.c_str()).c_str(), param)) + { + ret = 0x5e17; + break; + } + } + } + + return ret; + } +#endif + std::string format_ptr(void* ptr) { char buf[40]; @@ -218,18 +345,7 @@ extern "C" std::string utf8(""); #ifdef WIN32 - if (u) - { - char stack[256] = { 0 }, * ansi = NULL; - int len = 0; - - len = WideCharToMultiByte(CP_UTF8, 0, u, lstrlenW(u), NULL, 0, NULL, NULL); - ansi = new char[len + 2]; - len = WideCharToMultiByte(CP_UTF8, 0, u, lstrlenW(u), ansi, len, NULL, NULL); - ansi[len--] = 0; - utf8 = ansi; - delete[] ansi; - } + utf8 = u2a(u, CP_UTF8); #else #endif return utf8; @@ -285,122 +401,51 @@ extern "C" return si.freeram * si.mem_unit; #endif } - static void str_tolower(std::string& str) + void str_tolower(std::string& str) { std::transform(str.begin(), str.end(), str.begin(), tolower); } - -#ifndef WIN32 - typedef struct _find_file + bool create_folder(const char* fodler) { - std::string pattern; - std::string found; - }FINDFILE, * LPFF; - static std::string link_file(const char* lnk) - { - char path[256] = { 0 }; - int len = readlink(lnk, path, sizeof(path) - 1); - - return path; + return MKDIR(fodler, S_IREAD | S_IWRITE | S_IEXEC) == 0 || errno == EEXIST; } - static int enum_files(const char* dir, bool recursive, bool(*found_file)(const char* path_file, void* param), void* param) + std::string ini_get(const char* app, const char* key) { - int ret = 0; - DIR* pdir = nullptr; - struct dirent* ent = nullptr; - - pdir = opendir(dir); - if (!pdir) - return errno; - - while ((ent = readdir(pdir))) - { - if (ent->d_type & DT_DIR) - { - if (recursive) - { - if (strcmp(ent->d_name, ".") && strcmp(ent->d_name, "..")) - { - std::string sub(dir); - sub += "/"; - sub += ent->d_name; - ret = enum_files(sub.c_str(), recursive, found_file, param); - if (ret == 0x5e17) - break; - } - } - } - else - { - std::string file(dir); - - file += "/"; - file += ent->d_name; - if (!found_file(link_file(file.c_str()).c_str(), param)) - { - ret = 0x5e17; - break; - } - } - } - - return ret; + return ini_.get(app, key); } - static bool on_found(const char* file, void* param) + void ini_set(const char* app, const char* key, const char* val) { - LPFF lpff = (LPFF)param; - const char* name = strrchr(file, '/'); - - if (name++ == nullptr) - name = file; - - std::string lc(name); - str_tolower(lc); - if (lc.find(lpff->pattern) != std::string::npos) - { - lpff->found = file; - return false; - } - - return true; + ini_.set(app, key, val); } -#endif - static std::string get_self_path(void) + + std::string get_module_full_path(const char* module_part_name) { -#ifdef WIN32 - return g_module_path; -#else char path[128] = { 0 }; FINDFILE ff; - size_t pos = 0; - ff.pattern = GET_BACKEND_NAME; - ff.pattern += ".so"; + ff.pattern = module_part_name; str_tolower(ff.pattern); +#ifdef WIN32 +#else sprintf(path, "/proc/%u/map_files/", getpid()); +#endif enum_files(path, false, on_found, &ff); - pos = ff.found.rfind('/'); - if (pos++ == std::string::npos) - ff.found += "/"; - else - ff.found.erase(pos); return ff.found; -#endif } + static int get_log_config(const std::string& self_path, hg_log_type* type, std::string* path) { std::string me(self_path + "/configs/scanner.conf"); - simple_ini ini; int lv = LOG_LEVEL_ALL; hg_log_type tp = LOG_TYPE_FILE; if (!type) type = &tp; *type = LOG_TYPE_FILE; - if (ini.load(me.c_str()) == 0) + if (ini_.load(me.c_str()) == 0) { - std::string val(ini.get("log", "type")); + std::string val(ini_.get("log", "type")); if (val == "console") *type = LOG_TYPE_CONSOLE; else if (val == "none") @@ -410,10 +455,10 @@ extern "C" if (*type == LOG_TYPE_FILE && path) { - *path = ini.get("log", "path"); + *path = ini_.get("log", "path"); } - val = ini.get("log", "level"); + val = ini_.get("log", "level"); if (val == "debug") lv = LOG_LEVEL_DEBUG_INFO; else if (val == "warning") @@ -428,7 +473,7 @@ extern "C" int init(void) { char* file = nullptr; - std::string me(get_self_path()), path(""); + std::string me(g_module_path), path(""); hg_log_type type = LOG_TYPE_FILE; int level = get_log_config(me, &type, &path); @@ -437,13 +482,11 @@ extern "C" if (path.empty()) path = me; path += "/log"; - if (MKDIR(path.c_str(), S_IREAD | S_IWRITE | S_IEXEC) && - errno != EEXIST) + if (!create_folder(path.c_str())) { VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "Create log-folder '%s' failed(%d), now try temporary directory\n", path.c_str(), errno); path = simple_ini::temporary_path() + "/log"; - if (MKDIR(path.c_str(), S_IREAD | S_IWRITE | S_IEXEC) && - errno != EEXIST) + if (!create_folder(path.c_str())) { VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "create temporary directory '%s' failed(%d), log to console\n", path.c_str(), errno); type = LOG_TYPE_CONSOLE; diff --git a/hgdriver/wrapper/hg_log.h b/hgdriver/wrapper/hg_log.h index 28bf77d..c82687a 100644 --- a/hgdriver/wrapper/hg_log.h +++ b/hgdriver/wrapper/hg_log.h @@ -42,7 +42,13 @@ extern "C" std::string format_size(unsigned long size); std::string u2utf8(const wchar_t* u); std::string pe_path(std::string* name = nullptr); + std::string get_module_full_path(const char* module_part_name); unsigned long long available_memory(void); + void str_tolower(std::string& str); + bool create_folder(const char* fodler); + + std::string ini_get(const char* app, const char* key); + void ini_set(const char* app, const char* key, const char* val); // Function: initialize the logging type and level // diff --git a/hgdriver/wrapper/huagaoxxx_warraper_ex.cpp b/hgdriver/wrapper/huagaoxxx_warraper_ex.cpp index 1c034be..c8cb960 100644 --- a/hgdriver/wrapper/huagaoxxx_warraper_ex.cpp +++ b/hgdriver/wrapper/huagaoxxx_warraper_ex.cpp @@ -17,10 +17,21 @@ | (((unsigned long long)(c) & 0x0ffff) << 16) \ | (((unsigned long long)(d) & 0x0ffff) << 0)) +std::string g_module_path = ""; +static std::string g_sane_name = ""; +static std::string g_sane_ver = ""; + extern "C" { scanner_err hg_scanner_initialize(sane_callback callback, void* reserve) { +#ifndef WIN32 + size_t pos = 0; + g_module_path = hg_log::get_module_full_path((std::string(GET_BACKEND_NAME) + ".so").c_str()); + pos = g_module_path.rfind('/'); + if (pos++ != std::string::npos) + g_module_path.erase(pos); +#endif hg_log::init(); hg_scanner_mgr::set_version(VERSION_MAJOR, VERSION_MINOR, VERSION_YEAR, VERSION_BUILD - 100000); @@ -101,7 +112,8 @@ extern "C" void hg_scanner_set_sane_info(const char* name, const char* ver) { - + g_sane_name = name; + g_sane_ver = ver; } const char* hg_scanner_err_name(int err) { @@ -232,11 +244,22 @@ extern "C" { hg_log::log(info); } + + char* get_file_path(const char* name, char* buf) + { + std::string fp(hg_log::get_module_full_path(name)); + + if (fp.empty()) + *buf = 0; + else + strcpy(buf, fp.c_str()); + + return buf; + } } #ifdef WIN32 -std::string g_module_path = ""; BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) { diff --git a/hgsane/sane_hg_mdw.cpp b/hgsane/sane_hg_mdw.cpp index c143b61..474ecae 100644 --- a/hgsane/sane_hg_mdw.cpp +++ b/hgsane/sane_hg_mdw.cpp @@ -280,6 +280,7 @@ namespace local_utility unsigned short* w = (unsigned short*)&v; VLOG_MINI_4(LOG_LEVEL_DEBUG_INFO, "scanner version: %u.%u.%u.%u\n", w[3], w[2], w[1], w[0]); + VLOG_MINI_4(LOG_LEVEL_DEBUG_INFO, "%s version: %u.%u.%u\n", GET_BACKEND_NAME, SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, VERSION_BUILD); } void stop_work(void) { @@ -304,6 +305,16 @@ hg_sane_middleware::hg_sane_middleware(void) : opt_0_(nullptr), std_opt_(nullptr signal(SIGUSR1, &hg_sane_middleware::device_pnp); hg_scanner_set_sane_info(GET_BACKEND_NAME, sane_ver); hg_scanner_initialize(local_utility::ui_cb, NULL); + +#ifndef WIN32 + char path[512] = { 0 }; + size_t pos = 0; + + g_module_path = get_file_path((std::string(GET_BACKEND_NAME) + ".so").c_str(), path); + pos = g_module_path.rfind('/'); + if (pos++ != std::string::npos) + g_module_path.erase(pos); +#endif } hg_sane_middleware::~hg_sane_middleware() { diff --git a/hgsane/sane_option.h b/hgsane/sane_option.h index 8572db9..aa825ac 100644 --- a/hgsane/sane_option.h +++ b/hgsane/sane_option.h @@ -9,7 +9,6 @@ #include #ifdef WIN32 #define bzero(b, s) memset(b, 0, s) -extern std::string g_module_path; // Ending with '\\' #else #include #endif diff --git a/sdk/hginclude/huagaoxxx_warraper_ex.h b/sdk/hginclude/huagaoxxx_warraper_ex.h index ec209ff..b1cfe5f 100644 --- a/sdk/hginclude/huagaoxxx_warraper_ex.h +++ b/sdk/hginclude/huagaoxxx_warraper_ex.h @@ -131,6 +131,9 @@ #define MAKE_STR(str) _TO_STR(str) #define GET_BACKEND_NAME MAKE_STR(BACKEND_NAME) +#include +extern std::string g_module_path; // Ending with '\\' + typedef struct _device { char name[MAX_NAME_LEN]; // 设备ANSI名称,驱动需要保证该名称唯一, @@ -421,6 +424,15 @@ extern "C"{ bool hg_scanner_log_is_enable(int level); void hg_scanner_log(const char* info); + // Function: 获取模块全路径名称 + // + // Parameters: name - 模块名称(模块名称的一部分即可,不支持通配符) + // + // buf - 返回的全路径空间,必须保证足够大小 + // + // Return: 返回buf + char* get_file_path(const char* name, char* buf); + #ifdef __cplusplus } #endif