调整路径函数;第三方APP大DPI(600)扫描时,支持将原始图像数据存储到本地文件

This commit is contained in:
gb 2022-05-30 17:36:42 +08:00
parent 0439185933
commit 49741614f5
9 changed files with 312 additions and 131 deletions

View File

@ -123,8 +123,10 @@ typedef struct _img_header
}IMH; }IMH;
typedef struct _img typedef struct _img
{ {
IMH header; IMH header;
unsigned offset; unsigned offset;
bool is_file; // when this is true, then the 'data' stores the full path of the file
void* fptr;
std::shared_ptr<std::vector<unsigned char>> data; std::shared_ptr<std::vector<unsigned char>> data;
}IMGDT; }IMGDT;
class image_data 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; IMGDT img;
img.header.width = w; img.header.width = w;
@ -194,10 +196,48 @@ public:
img.header.line_bytes = line_bytes; img.header.line_bytes = line_bytes;
img.offset = 0; img.offset = 0;
img.header.bytes = bytes; img.header.bytes = bytes;
img.data.reset(new std::vector<unsigned char>); img.data.reset(new std::vector<unsigned char>(bytes));
img.data->resize(bytes); if (!img.data.get())
return false;
img.is_file = false;
img.fptr = nullptr;
memcpy(img.data->data(), data, bytes); memcpy(img.data->data(), data, bytes);
Put(img); 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<unsigned char>(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() IMGDT Take()
{ {
@ -258,20 +298,43 @@ public:
else else
{ {
lock_guard<mutex> lock(_mutex); lock_guard<mutex> lock(_mutex);
if (_queue.front().data->size() - _queue.front().offset <= *len) if (_queue.front().is_file)
{ {
*len = _queue.front().data->size() - _queue.front().offset; if (_queue.front().data->size() - _queue.front().offset <= *len)
memcpy(buf, _queue.front().data->data() + _queue.front().offset, *len); {
_queue.pop_front(); *len = _queue.front().data->size() - _queue.front().offset;
if (over) fread(buf, 1, *len, (FILE*)_queue.front().fptr);
*over = true; 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 else
{ {
memcpy(buf, _queue.front().data->data() + _queue.front().offset, *len); if (_queue.front().data->size() - _queue.front().offset <= *len)
_queue.front().offset += *len; {
if (over) *len = _queue.front().data->size() - _queue.front().offset;
*over = false; 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;
}
} }
} }
} }

View File

@ -93,6 +93,14 @@ hg_scanner::hg_scanner(ScannerSerial serial
, notify_setting_result_(false), user_cancel_(false), cb_mem_(true), test_1_paper_(false) , 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) , 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; custom_gamma_val_ = new SANE_Gamma;
memset(custom_gamma_val_, 0, sizeof(SANE_Gamma)); memset(custom_gamma_val_, 0, sizeof(SANE_Gamma));
#ifdef MAPPING_FUNCTION_IN_BASE #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); 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) int hg_scanner::is_running(void)
{ {

View File

@ -22,7 +22,6 @@
#include "PaperSize.h" #include "PaperSize.h"
#ifdef WIN32 #ifdef WIN32
extern std::string g_module_path; // Ending with '\\'
#else #else
#include <unistd.h> #include <unistd.h>
#endif #endif
@ -255,6 +254,7 @@ protected:
image_data final_imgs_; // JPG ... image_data final_imgs_; // JPG ...
unsigned int usb_img_index_; unsigned int usb_img_index_;
unsigned int final_img_index_; unsigned int final_img_index_;
std::string final_path_;
BlockingQueue<std::shared_ptr<std::vector<char>>> imgs_; BlockingQueue<std::shared_ptr<std::vector<char>>> imgs_;
BlockingQueue<std::string> paths_; BlockingQueue<std::string> paths_;

View File

@ -7,7 +7,13 @@
#ifdef WIN32 #ifdef WIN32
#include <Windows.h> #include <Windows.h>
#include <direct.h> #include <direct.h>
#include <Psapi.h>
#include <Tlhelp32.h>
#include <imagehlp.h>
#define MKDIR(a, b) mkdir(a) #define MKDIR(a, b) mkdir(a)
#pragma comment(lib, "imagehlp.lib")
#pragma comment(lib, "Psapi.lib")
#pragma comment(lib, "shlwapi.lib")
#else #else
#define MKDIR(a, b) mkdir(a, b) #define MKDIR(a, b) mkdir(a, b)
#include <pthread.h> #include <pthread.h>
@ -28,10 +34,6 @@
#define _INTSIZEOF(n) ((sizeof(n) + sizeof(long) - 1) & ~(sizeof(long) - 1)) #define _INTSIZEOF(n) ((sizeof(n) + sizeof(long) - 1) & ~(sizeof(long) - 1))
#endif #endif
#ifdef WIN32
extern std::string g_module_path; // Ending with '\\'
#endif
class log_cls class log_cls
{ {
typedef void(*log_to)(const char*, void*); typedef void(*log_to)(const char*, void*);
@ -146,7 +148,132 @@ extern "C"
#endif #endif
namespace hg_log namespace hg_log
{ {
static simple_ini ini_;
static log_callback lcb_ = NULL; 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) std::string format_ptr(void* ptr)
{ {
char buf[40]; char buf[40];
@ -218,18 +345,7 @@ extern "C"
std::string utf8(""); std::string utf8("");
#ifdef WIN32 #ifdef WIN32
if (u) utf8 = u2a(u, CP_UTF8);
{
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;
}
#else #else
#endif #endif
return utf8; return utf8;
@ -285,122 +401,51 @@ extern "C"
return si.freeram * si.mem_unit; return si.freeram * si.mem_unit;
#endif #endif
} }
static void str_tolower(std::string& str) void str_tolower(std::string& str)
{ {
std::transform(str.begin(), str.end(), str.begin(), tolower); std::transform(str.begin(), str.end(), str.begin(), tolower);
} }
bool create_folder(const char* fodler)
#ifndef WIN32
typedef struct _find_file
{ {
std::string pattern; return MKDIR(fodler, S_IREAD | S_IWRITE | S_IEXEC) == 0 || errno == EEXIST;
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;
} }
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; return ini_.get(app, key);
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;
} }
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; ini_.set(app, key, val);
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;
} }
#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 }; char path[128] = { 0 };
FINDFILE ff; FINDFILE ff;
size_t pos = 0;
ff.pattern = GET_BACKEND_NAME; ff.pattern = module_part_name;
ff.pattern += ".so";
str_tolower(ff.pattern); str_tolower(ff.pattern);
#ifdef WIN32
#else
sprintf(path, "/proc/%u/map_files/", getpid()); sprintf(path, "/proc/%u/map_files/", getpid());
#endif
enum_files(path, false, on_found, &ff); 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; return ff.found;
#endif
} }
static int get_log_config(const std::string& self_path, hg_log_type* type, std::string* path) 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"); std::string me(self_path + "/configs/scanner.conf");
simple_ini ini;
int lv = LOG_LEVEL_ALL; int lv = LOG_LEVEL_ALL;
hg_log_type tp = LOG_TYPE_FILE; hg_log_type tp = LOG_TYPE_FILE;
if (!type) if (!type)
type = &tp; type = &tp;
*type = LOG_TYPE_FILE; *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") if (val == "console")
*type = LOG_TYPE_CONSOLE; *type = LOG_TYPE_CONSOLE;
else if (val == "none") else if (val == "none")
@ -410,10 +455,10 @@ extern "C"
if (*type == LOG_TYPE_FILE && path) 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") if (val == "debug")
lv = LOG_LEVEL_DEBUG_INFO; lv = LOG_LEVEL_DEBUG_INFO;
else if (val == "warning") else if (val == "warning")
@ -428,7 +473,7 @@ extern "C"
int init(void) int init(void)
{ {
char* file = nullptr; char* file = nullptr;
std::string me(get_self_path()), path(""); std::string me(g_module_path), path("");
hg_log_type type = LOG_TYPE_FILE; hg_log_type type = LOG_TYPE_FILE;
int level = get_log_config(me, &type, &path); int level = get_log_config(me, &type, &path);
@ -437,13 +482,11 @@ extern "C"
if (path.empty()) if (path.empty())
path = me; path = me;
path += "/log"; path += "/log";
if (MKDIR(path.c_str(), S_IREAD | S_IWRITE | S_IEXEC) && if (!create_folder(path.c_str()))
errno != EEXIST)
{ {
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "Create log-folder '%s' failed(%d), now try temporary directory\n", path.c_str(), errno); 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"; path = simple_ini::temporary_path() + "/log";
if (MKDIR(path.c_str(), S_IREAD | S_IWRITE | S_IEXEC) && if (!create_folder(path.c_str()))
errno != EEXIST)
{ {
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "create temporary directory '%s' failed(%d), log to console\n", path.c_str(), errno); 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; type = LOG_TYPE_CONSOLE;

View File

@ -42,7 +42,13 @@ extern "C"
std::string format_size(unsigned long size); std::string format_size(unsigned long size);
std::string u2utf8(const wchar_t* u); std::string u2utf8(const wchar_t* u);
std::string pe_path(std::string* name = nullptr); 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); 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 // Function: initialize the logging type and level
// //

View File

@ -17,10 +17,21 @@
| (((unsigned long long)(c) & 0x0ffff) << 16) \ | (((unsigned long long)(c) & 0x0ffff) << 16) \
| (((unsigned long long)(d) & 0x0ffff) << 0)) | (((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" extern "C"
{ {
scanner_err hg_scanner_initialize(sane_callback callback, void* reserve) 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_log::init();
hg_scanner_mgr::set_version(VERSION_MAJOR, VERSION_MINOR, VERSION_YEAR, VERSION_BUILD - 100000); 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) 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) const char* hg_scanner_err_name(int err)
{ {
@ -232,11 +244,22 @@ extern "C"
{ {
hg_log::log(info); 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 #ifdef WIN32
std::string g_module_path = "";
BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
{ {

View File

@ -280,6 +280,7 @@ namespace local_utility
unsigned short* w = (unsigned short*)&v; 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, "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) 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); signal(SIGUSR1, &hg_sane_middleware::device_pnp);
hg_scanner_set_sane_info(GET_BACKEND_NAME, sane_ver); hg_scanner_set_sane_info(GET_BACKEND_NAME, sane_ver);
hg_scanner_initialize(local_utility::ui_cb, NULL); 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() hg_sane_middleware::~hg_sane_middleware()
{ {

View File

@ -9,7 +9,6 @@
#include <stdio.h> #include <stdio.h>
#ifdef WIN32 #ifdef WIN32
#define bzero(b, s) memset(b, 0, s) #define bzero(b, s) memset(b, 0, s)
extern std::string g_module_path; // Ending with '\\'
#else #else
#include <iconv.h> #include <iconv.h>
#endif #endif

View File

@ -131,6 +131,9 @@
#define MAKE_STR(str) _TO_STR(str) #define MAKE_STR(str) _TO_STR(str)
#define GET_BACKEND_NAME MAKE_STR(BACKEND_NAME) #define GET_BACKEND_NAME MAKE_STR(BACKEND_NAME)
#include <string>
extern std::string g_module_path; // Ending with '\\'
typedef struct _device typedef struct _device
{ {
char name[MAX_NAME_LEN]; // 设备ANSI名称驱动需要保证该名称唯一 char name[MAX_NAME_LEN]; // 设备ANSI名称驱动需要保证该名称唯一
@ -421,6 +424,15 @@ extern "C"{
bool hg_scanner_log_is_enable(int level); bool hg_scanner_log_is_enable(int level);
void hg_scanner_log(const char* info); void hg_scanner_log(const char* info);
// Function: 获取模块全路径名称
//
// Parameters: name - 模块名称(模块名称的一部分即可,不支持通配符)
//
// buf - 返回的全路径空间,必须保证足够大小
//
// Return: 返回buf
char* get_file_path(const char* name, char* buf);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif