#include "ManagerV2.h" #include "base/HGDef.h" #include "base/HGInc.h" #include "base/HGBuffer.h" #include "base/HGBase64.h" #include "base/HGUtility.h" #include "base/HGIni.h" #include "base/HGInfo.h" #include "base/HGTime.h" #include "imgfmt/HGJpeg.h" #include "imgfmt/HGOfd.h" #include "imgfmt/HGPdf.h" #include "imgfmt/HGTiff.h" #include "imgfmt/HGImgFmt.h" #include "imgproc/HGOCR.h" #include "imgproc/HGImgProc.h" #include "HGString.h" extern "C" { #include "zip.h" }; #include #include #include #include "WSUser.h" namespace ver_2 { ManagerV2::ManagerV2(HGMsgPump msgPump) : Manager(msgPump) { m_lock = NULL; HGBase_CreateLock(&m_lock); HGChar docsPath[256]; HGBase_GetDocumentsPath(docsPath, 256); HGChar procName[256]; HGBase_GetProcessName(procName, 256); HGChar defSavePath[256]; sprintf(defSavePath, "%s%s/", docsPath, procName); m_globalCfg.fileSavePath = GetCfgStringValue("global", "fileSavePath", defSavePath); m_globalCfg.fileNamePrefix = GetCfgStringValue("global", "fileNamePrefix", "Huago"); m_globalCfg.fileNameMode = GetCfgStringValue("global", "fileNameMode", "date_time"); m_globalCfg.imageFormat = GetCfgStringValue("global", "imageFormat", "jpg"); m_globalCfg.imageJpegQuality = GetCfgIntValue("global", "imageJpegQuality", 80); m_globalCfg.imageTiffCompression = GetCfgStringValue("global", "imageTiffCompression", "lzw"); m_globalCfg.imageTiffJpegQuality = GetCfgIntValue("global", "imageTiffJpegQuality", 80); m_globalCfg.fileSavePath.push_back('/'); HGChar stdSavePath[256]; HGBase_StandardiseFileName(m_globalCfg.fileSavePath.c_str(), stdSavePath, 256); m_globalCfg.fileSavePath = stdSavePath; m_user.clear(); m_stopThread = HGFALSE; m_timeout = 0xFFFFFFFF; m_event = NULL; HGBase_CreateEvent(HGFALSE, HGFALSE, &m_event); m_thread = NULL; HGBase_OpenThread(ThreadFunc, this, &m_thread); m_initDevice = false; m_devNameList.clear(); m_openDevice = false; m_devName.clear(); m_sn.clear(); m_devHandle = NULL; m_devParams.clear(); m_scanBlankCheck = false; m_scanTemp = false; m_scanning = false; m_scanEvent = NULL; m_dpi = 200; HGChar cfgPath[256]; HGBase_GetConfigPath(cfgPath, 256); HGBase_CreateDir(cfgPath); char oldDbPath[256]; sprintf(oldDbPath, "%s%s", cfgPath, "config2.db"); HGBase_DeleteFile(oldDbPath); char newDbPath[256]; sprintf(newDbPath, "%s%s", cfgPath, "newConfig2.db"); m_sqlite = NULL; sqlite3_open_v2(newDbPath, &m_sqlite, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_SHAREDCACHE, NULL); if (NULL != m_sqlite) { HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "open database success"); // 删除旧配置表 sqlite3_exec(m_sqlite, "delete from device_params", NULL, NULL, NULL); // 保存路径表 sqlite3_exec(m_sqlite, "create table save_filenames (filename text)", NULL, NULL, NULL); // 设备配置表 sqlite3_exec(m_sqlite, "create table device_params_2 (name text, title text, value_type text, value text)", NULL, NULL, NULL); int ret = sqlite3_exec(m_sqlite, "create table table_ (id integer primary key autoincrement, name text)", NULL, NULL, NULL); if (0 == ret) { ret = sqlite3_exec(m_sqlite, "begin", NULL, NULL, NULL); assert(0 == ret); do { ret = sqlite3_exec(m_sqlite, "create table 'table_default' (id integer primary key autoincrement, format text, tag text, image blob, thumb blob)", NULL, NULL, NULL); if (0 != ret) break; ret = sqlite3_exec(m_sqlite, "create table 'table_default_idx' (id integer, idx integer)", NULL, NULL, NULL); if (0 != ret) break; ret = sqlite3_exec(m_sqlite, "insert into table_ (name) values ('default')", NULL, NULL, NULL); if (0 != ret) break; } while (0); if (0 != ret) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); } else { ret = sqlite3_exec(m_sqlite, "commit", NULL, NULL, NULL); assert(0 == ret); } } sqlite3_stmt* stmt = NULL; ret = sqlite3_prepare(m_sqlite, "select name from table_ order by id desc", -1, &stmt, NULL); assert(0 == ret); ret = sqlite3_step(stmt); if (SQLITE_ROW == ret) m_currBatchId = (const char*)sqlite3_column_text(stmt, 0); ret = sqlite3_finalize(stmt); assert(0 == ret); } else { HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "open database failed"); } m_bindFolder.clear(); m_bindNameMode.clear(); m_bindNameWidth = 0; m_bindNameBase = 0; LoadSaveFilePathList(m_saveFilePathList); RestoreSaveFilePathList(m_saveFilePathList); } ManagerV2::~ManagerV2() { std::string errInfo; DeinitDevice(errInfo); if (NULL != m_sqlite) { sqlite3_close_v2(m_sqlite); m_sqlite = NULL; } m_stopThread = HGTRUE; HGBase_SetEvent(m_event); HGBase_CloseThread(m_thread); m_thread = NULL; HGBase_DestroyEvent(m_event); m_event = NULL; HGBase_DestroyLock(m_lock); m_lock = NULL; } void ManagerV2::DeinitDev(const DeinitDevParam* param) { assert(NULL != param && this == param->mgr); std::string errInfo; DeinitDevice(errInfo); } void ManagerV2::CloseDev(const CloseDevParam* param) { assert(NULL != param && this == param->mgr); if (m_devName == param->devName) { std::string errInfo; CloseDevice(errInfo); } } void ManagerV2::ScanFinish(const ScanFinishParam* param) { assert(NULL != param && this == param->mgr); std::string errInfo; StopScan(errInfo); } void ManagerV2::AddSavedFile(const AddSavedFileParam* param) { assert(NULL != param && this == param->mgr); m_saveFilePathList.push_back(param->fileName); RestoreSaveFilePathList(m_saveFilePathList); } void ManagerV2::RemoveSavedFile(const RemoveSavedFileParam* param) { assert(NULL != param && this == param->mgr); std::list::iterator iter; for (iter = m_saveFilePathList.begin(); iter != m_saveFilePathList.end(); ++iter) { if (*iter == param->fileName) { m_saveFilePathList.erase(iter); RestoreSaveFilePathList(m_saveFilePathList); break; } } } void ManagerV2::AddUser(class WSUser *user) { assert(NULL != user); HGBase_EnterLock(m_lock); m_user.push_back(user); m_timeout = 0xFFFFFFFF; HGBase_SetEvent(m_event); HGBase_LeaveLock(m_lock); } void ManagerV2::RemoveUser(class WSUser *user) { assert(NULL != user); HGBase_EnterLock(m_lock); std::list::iterator iter; for (iter = m_user.begin(); iter != m_user.end(); ++iter) { if (*iter == user) { m_user.erase(iter); if (m_user.empty()) { m_timeout = 1000 * 10 * 60; HGBase_SetEvent(m_event); } break; } } HGBase_LeaveLock(m_lock); } int ManagerV2::SetGlobalConfig(const GlobalConfig& cfg, HGUInt mask, std::string& errInfo) { errInfo = "参数错误"; if ((mask & GlobalConfig::fileSavePathMask) && cfg.fileSavePath.empty()) return -1; if ((mask & GlobalConfig::fileNameModeMask) && ("date_time" != cfg.fileNameMode && "random" != cfg.fileNameMode && "sn_date_time" != cfg.fileNameMode)) return -1; if ((mask & GlobalConfig::imageFormatMask) && ("jpg" != cfg.imageFormat && "bmp" != cfg.imageFormat && "png" != cfg.imageFormat && "tif" != cfg.imageFormat && "pdf" != cfg.imageFormat && "ofd" != cfg.imageFormat && "ocr-pdf" != cfg.imageFormat && "ocr-ofd" != cfg.imageFormat)) return -1; if ((mask & GlobalConfig::imageJpegQualityMask) && (cfg.imageJpegQuality < 0 || cfg.imageJpegQuality > 100)) return -1; if ((mask & GlobalConfig::imageTiffCompressionMask) && ("none" != cfg.imageTiffCompression && "lzw" != cfg.imageTiffCompression && "jpeg" != cfg.imageTiffCompression && "ccitt-g4" != cfg.imageTiffCompression)) return -1; if ((mask & GlobalConfig::imageTiffJpegQualityMask) && (cfg.imageTiffJpegQuality < 0 || cfg.imageTiffJpegQuality > 100)) return -1; HGBase_EnterLock(m_lock); if (mask & GlobalConfig::fileSavePathMask) { std::string fileSavePath = cfg.fileSavePath; fileSavePath.push_back('/'); HGChar stdFileSavePath[256]; HGBase_StandardiseFileName(fileSavePath.c_str(), stdFileSavePath, 256); m_globalCfg.fileSavePath = stdFileSavePath; SetCfgStringValue("global", "fileSavePath", m_globalCfg.fileSavePath); } if (mask & GlobalConfig::fileNamePrefixMask) { m_globalCfg.fileNamePrefix = cfg.fileNamePrefix; SetCfgStringValue("global", "fileNamePrefix", m_globalCfg.fileNamePrefix); } if (mask & GlobalConfig::fileNameModeMask) { m_globalCfg.fileNameMode = cfg.fileNameMode; SetCfgStringValue("global", "fileNameMode", m_globalCfg.fileNameMode); } if (mask & GlobalConfig::imageFormatMask) { m_globalCfg.imageFormat = cfg.imageFormat; SetCfgStringValue("global", "imageFormat", m_globalCfg.imageFormat); } if (mask & GlobalConfig::imageJpegQualityMask) { m_globalCfg.imageJpegQuality = cfg.imageJpegQuality; SetCfgIntValue("global", "imageJpegQuality", m_globalCfg.imageJpegQuality); } if (mask & GlobalConfig::imageTiffCompressionMask) { m_globalCfg.imageTiffCompression = cfg.imageTiffCompression; SetCfgStringValue("global", "imageTiffCompression", m_globalCfg.imageTiffCompression); } if (mask & GlobalConfig::imageTiffJpegQualityMask) { m_globalCfg.imageTiffJpegQuality = cfg.imageTiffJpegQuality; SetCfgIntValue("global", "imageTiffJpegQuality", m_globalCfg.imageTiffJpegQuality); } HGBase_LeaveLock(m_lock); errInfo.clear(); return 0; } int ManagerV2::GetGlobalConfig(GlobalConfig& cfg, std::string& errInfo) { cfg = m_globalCfg; errInfo.clear(); return 0; } int ManagerV2::LoadLocalImage(const std::string& imagePath, std::string& imgBase64, std::string& errInfo) { imgBase64.clear(); errInfo = "错误"; HGUInt imgType = 0; HGImgFmt_GetImgFmtType(imagePath.c_str(), &imgType); if (0 == imgType) return -1; int ret = LoadBase64(imagePath, imgBase64); if (0 != ret) return ret; std::string prefix = "data:image/jpeg;base64,"; if (HGIMGFMT_TYPE_BMP == imgType) prefix = "data:image/bmp;base64,"; else if (HGIMGFMT_TYPE_PNG == imgType) prefix = "data:image/png;base64,"; else if (HGIMGFMT_TYPE_TIFF == imgType) prefix = "data:image/tiff;base64,"; else if (HGIMGFMT_TYPE_PDF == imgType) prefix = "data:image/pdf;base64,"; else if (HGIMGFMT_TYPE_OFD == imgType) prefix = "data:image/ofd;base64,"; imgBase64.insert(0, prefix); errInfo.clear(); return 0; } int ManagerV2::SaveLocalImage(const std::string& imgBase64, bool temp, std::string& imagePath, std::string& errInfo) { imagePath.clear(); errInfo = "错误"; size_t pos = imgBase64.find(','); if (std::string::npos == pos) return -1; std::string prefix = imgBase64.substr(0, pos + 1); std::string suffix = "jpg"; if ("data:image/bmp;base64," == prefix) suffix = "bmp"; else if ("data:image/png;base64," == prefix) suffix = "png"; else if ("data:image/tiff;base64," == prefix) suffix = "tif"; else if ("data:image/pdf;base64," == prefix) suffix = "pdf"; else if ("data:image/ofd;base64," == prefix) suffix = "ofd"; std::string imagePath2 = GetFilePath(temp, suffix); int ret = SaveBase64(imgBase64.c_str() + pos + 1, imagePath2); if (0 != ret) return ret; imagePath = imagePath2; if (!temp) { m_saveFilePathList.push_back(imagePath); RestoreSaveFilePathList(m_saveFilePathList); } errInfo.clear(); return 0; } int ManagerV2::DeleteLocalFile(const std::string& filePath, std::string& errInfo) { int ret = -1; errInfo = "错误"; std::list::iterator iter; for (iter = m_saveFilePathList.begin(); iter != m_saveFilePathList.end(); ++iter) { if (filePath == *iter) { if (HGBASE_ERR_OK == HGBase_DeleteFile(filePath.c_str())) { m_saveFilePathList.erase(iter); RestoreSaveFilePathList(m_saveFilePathList); errInfo.clear(); ret = 0; } break; } } return ret; } int ManagerV2::ClearGlobalFileSavePath(std::string& errInfo) { std::list::const_iterator iter; for (iter = m_saveFilePathList.begin(); iter != m_saveFilePathList.end(); ++iter) { HGBase_DeleteFile((*iter).c_str()); } m_saveFilePathList.clear(); RestoreSaveFilePathList(m_saveFilePathList); errInfo.clear(); return 0; } int ManagerV2::UploadLocalFile(const std::string& filePath, const std::string& remoteFilePath, const std::string& uploadMode, const std::string& httpHost, int httpPort, const std::string& httpPath, const std::string& ftpUser, const std::string& ftpPassword, const std::string& ftpHost, int ftpPort, std::string& errInfo) { errInfo = "错误"; if (filePath.empty() || remoteFilePath.empty()) return -1; if ("http" != uploadMode && "ftp" != uploadMode) return -1; int ret = -1; if ("http" == uploadMode) { ret = HttpUpload(httpHost, httpPort, httpPath, filePath, remoteFilePath); } else { ret = FtpUpload(ftpUser, ftpPassword, ftpHost, ftpPort, filePath, remoteFilePath); } if (0 == ret) errInfo.clear(); return ret; } int ManagerV2::MergeLocalImage(const std::vector& imagePathList, const std::string& mode, const std::string& align, int interval, bool temp, std::string& outImagePath, std::string& errInfo) { outImagePath.clear(); errInfo = "错误"; if (imagePathList.empty() || interval < 0) return -1; if ("horz" == mode) { if ("top" != align && "bottom" != align && "center" != align) return -1; } else if ("vert" == mode) { if ("left" != align && "right" != align && "center" != align) return -1; } else { return -1; } HGUInt width = 0, height = 0; for (int i = 0; i < (int)imagePathList.size(); ++i) { HGImgFmtLoadInfo loadInfo; if (HGBASE_ERR_OK == HGImgFmt_LoadImage(imagePathList[i].c_str(), 0, &loadInfo, 0, 0, NULL)) { if ("horz" == mode) { if (0 != width) width += interval; width += loadInfo.width; if (loadInfo.height > height) height = loadInfo.height; } else { if (0 != height) height += interval; height += loadInfo.height; if (loadInfo.width > width) width = loadInfo.width; } } } HGImage outImage = NULL; HGBase_CreateImage(width, height, HGBASE_IMGTYPE_RGB, HGBASE_IMGORIGIN_TOP, &outImage); if (NULL == outImage) return -1; HGImageInfo outImageInfo; HGBase_GetImageInfo(outImage, &outImageInfo); HGByte *outImageData = NULL; HGBase_GetImageData(outImage, &outImageData); memset(outImageData, 255, outImageInfo.widthStep * outImageInfo.height); HGUInt start = 0; for (int i = 0; i < (int)imagePathList.size(); ++i) { HGImage img = NULL; HGImgFmt_LoadImage(imagePathList[i].c_str(), 0, NULL, HGBASE_IMGTYPE_RGB, HGBASE_IMGORIGIN_TOP, &img); if (NULL != img) { HGImageInfo imgInfo; HGBase_GetImageInfo(img, &imgInfo); if (0 != start) start += interval; HGImageRoi outImageRoi; if ("horz" == mode) { outImageRoi.left = start; outImageRoi.top = 0; if ("bottom" == align) outImageRoi.top = height - imgInfo.height; else if ("center" == align) outImageRoi.top = (height - imgInfo.height) / 2; start += imgInfo.width; } else { outImageRoi.left = 0; if ("right" == align) outImageRoi.left = width - imgInfo.width; else if ("center" == align) outImageRoi.left = (width - imgInfo.width) / 2; outImageRoi.top = start; start += imgInfo.height; } outImageRoi.right = outImageRoi.left + imgInfo.width; outImageRoi.bottom = outImageRoi.top + imgInfo.height; HGBase_SetImageROI(outImage, &outImageRoi); HGBase_CopyImage(img, outImage); HGBase_ResetImageROI(outImage); HGBase_DestroyImage(img); } } int ret = SaveImage(outImage, temp, outImagePath); if (0 == ret) { if (!temp) { m_saveFilePathList.push_back(outImagePath); RestoreSaveFilePathList(m_saveFilePathList); } errInfo.clear(); } HGBase_DestroyImage(outImage); return ret; } int ManagerV2::LocalMakeMultiImage(const std::vector& imagePathList, const std::string& format, const std::string& tiffCompression, int tiffJpegQuality, bool temp, std::string& outImagePath, std::string& errInfo) { outImagePath.clear(); errInfo = "错误"; if (imagePathList.empty()) return -1; if ("tif" != format && "pdf" != format && "ofd" != format) return -1; if ("none" != tiffCompression && "lzw" != tiffCompression && "jpeg" != tiffCompression && "ccitt-g4" != tiffCompression) return -1; if (tiffJpegQuality < 0 || tiffJpegQuality > 100) return -1; int ret = -1; std::string outImagePath2 = GetFilePath(temp, format); HGImgFmtWriter writer = NULL; HGImgFmt_OpenImageWriter(outImagePath2.c_str(), 0, &writer); if (NULL != writer) { for (int i = 0; i < (int)imagePathList.size(); ++i) { HGImage img = NULL; HGImgFmt_LoadImage(imagePathList[i].c_str(), 0, NULL, 0, HGBASE_IMGORIGIN_TOP, &img); if (NULL != img) { HGImgFmtSaveInfo saveInfo; saveInfo.jpegQuality = 80; saveInfo.tiffJpegQuality = tiffJpegQuality; saveInfo.tiffCompression = HGIMGFMT_TIFFCOMP_LZW; if ("none" == tiffCompression) saveInfo.tiffCompression = HGIMGFMT_TIFFCOMP_NONE; else if ("jpeg" == tiffCompression) saveInfo.tiffCompression = HGIMGFMT_TIFFCOMP_JPEG; else if ("ccitt-g4" == tiffCompression) saveInfo.tiffCompression = HGIMGFMT_TIFFCOMP_CCITTFAX4; if (HGBASE_ERR_OK == HGImgFmt_SaveImageToWriter(writer, img, &saveInfo)) { errInfo.clear(); ret = 0; } HGBase_DestroyImage(img); } } HGImgFmt_CloseImageWriter(writer); } if (0 != ret) { HGBase_DeleteFile(outImagePath2.c_str()); return ret; } outImagePath = outImagePath2; if (!temp) { m_saveFilePathList.push_back(outImagePath); RestoreSaveFilePathList(m_saveFilePathList); } return 0; } int ManagerV2::SplitLocalImage(const std::string& imagePath, const std::string& mode, int location, bool temp, std::vector& outImagePathList, std::string& errInfo) { outImagePathList.clear(); errInfo = "错误"; if (imagePath.empty() || location < 0) return -1; if ("horz" != mode && "vert" != mode) return -1; int ret = -1; HGImage image = NULL; HGImgFmt_LoadImage(imagePath.c_str(), 0, NULL, 0, HGBASE_IMGORIGIN_TOP, &image); { HGImageInfo imageInfo; HGBase_GetImageInfo(image, &imageInfo); for (int i = 0; i < 2; ++i) { HGImageRoi imageRoi; if ("horz" == mode) { imageRoi.top = 0; imageRoi.bottom = imageInfo.height; if (0 == i) { imageRoi.left = 0; imageRoi.right = (HGUInt)location; } else { imageRoi.left = (HGUInt)location; imageRoi.right = imageInfo.width; } } else { imageRoi.left = 0; imageRoi.right = imageInfo.width; if (0 == i) { imageRoi.top = 0; imageRoi.bottom = (HGUInt)location; } else { imageRoi.top = (HGUInt)location; imageRoi.bottom = imageInfo.height; } } if (HGBASE_ERR_OK == HGBase_SetImageROI(image, &imageRoi)) { HGImage img = NULL; HGBase_CloneImage(image, 0, 0, &img); if (NULL != img) { std::string imgPath; if (0 == SaveImage(img, temp, imgPath)) { outImagePathList.push_back(imgPath); if (!temp) { m_saveFilePathList.push_back(imgPath); RestoreSaveFilePathList(m_saveFilePathList); } errInfo.clear(); ret = 0; } HGBase_DestroyImage(img); } HGBase_ResetImageROI(image); } } HGBase_DestroyImage(image); } return ret; } int ManagerV2::LocalMakeZipFile(const std::vector& filePathList, const std::vector& nameList, const std::string &zipPath, bool temp, std::string& outZipPath, std::string& errInfo) { outZipPath.clear(); errInfo = "错误"; if (filePathList.empty()) return -1; if (!nameList.empty()) { if (nameList.size() != filePathList.size()) return - 1; for (int i = 0; i < (int)nameList.size(); ++i) { if (nameList[i].empty()) return -1; } } std::string outZipPath2 = GetFilePath(temp, "zip"); if (!zipPath.empty()) outZipPath2 = zipPath; int error = 0; zip* z = zip_open(StdStringToUtf8(outZipPath2).c_str(), ZIP_CREATE | ZIP_TRUNCATE, &error); if (NULL == z) { HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "ManagerV1::ExportZipFile Create File Fail %s", outZipPath2.c_str()); return -1; } int ret = -1; for (int i = 0; i < (int)filePathList.size(); ++i) { zip_source_t* s = zip_source_file(z, StdStringToUtf8(filePathList[i]).c_str(), 0, 0); if (NULL != s) { std::string zipName; if (!nameList.empty()) { zipName = nameList[i]; } else { HGChar name[256]; HGBase_GetFileName(filePathList[i].c_str(), name, 256); zipName = name; } if (zip_file_add(z, StdStringToUtf8(zipName).c_str(), s, ZIP_FL_OVERWRITE) >= 0) { errInfo.clear(); ret = 0; } else { zip_source_free(s); } } } zip_close(z); z = NULL; if (0 != ret) { HGBase_DeleteFile(outZipPath2.c_str()); return ret; } outZipPath = outZipPath2; if (!temp) { m_saveFilePathList.push_back(outZipPath); RestoreSaveFilePathList(m_saveFilePathList); } return 0; } int ManagerV2::LocalImageDeskew(const std::string& imagePath, bool autoCrop, bool deskew, bool fillBlank, int width, int height, bool temp, std::string& outImagePath, std::string& errInfo) { outImagePath.clear(); errInfo = "错误"; if (imagePath.empty() || width < 0 || height < 0) return -1; int ret = -1; HGImage image = NULL; HGImgFmt_LoadImage(imagePath.c_str(), 0, NULL, 0, HGBASE_IMGORIGIN_TOP, &image); if (NULL != image) { HGImage img = NULL; HGImgProc_ImageAutoCrop(image, (HGBool)autoCrop, (HGBool)deskew, (HGBool)fillBlank, NULL, (HGUInt)width, (HGUInt)height, 0, HGBASE_IMGORIGIN_TOP, &img); if (NULL != img) { if (0 == SaveImage(img, temp, outImagePath)) { if (!temp) { m_saveFilePathList.push_back(outImagePath); RestoreSaveFilePathList(m_saveFilePathList); } errInfo.clear(); ret = 0; } HGBase_DestroyImage(img); } HGBase_DestroyImage(image); } return ret; } static int tolower(int c) { if (c >= 'A' && c <= 'Z') { return c + 'a' - 'A'; } else { return c; } } static int htoi(char s[]) { int i; int n = 0; if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) { i = 2; } else { i = 0; } for (; (s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z'); ++i) { if (tolower(s[i]) > '9') { n = 16 * n + (10 + tolower(s[i]) - 'a'); } else { n = 16 * n + (tolower(s[i]) - '0'); } } return n; } static bool GetColor(const std::string& colorText, HGUInt &r, HGUInt &g, HGUInt &b) { if (7 != colorText.size()) return false; if ('#' != colorText[0]) return false; for (int i = 1; i < (int)colorText.size(); ++i) { if ((colorText[i] >= '0' && colorText[i] <= '9') || (colorText[i] >= 'a' && colorText[i] <= 'f') || (colorText[i] >= 'A' && colorText[i] <= 'F')) { } else { return false; } } char colorR[3] = { 0 }; char colorG[3] = { 0 }; char colorB[3] = { 0 }; strncpy(colorR, colorText.c_str() + 1, 2); strncpy(colorG, colorText.c_str() + 3, 2); strncpy(colorB, colorText.c_str() + 5, 2); r = htoi(colorR); g = htoi(colorG); b = htoi(colorB); return true; } int ManagerV2::LocalImageAddWatermark(const std::string& imagePath, const std::string& text, const std::string& textColor, int textOpacity, const std::string& textPos, int marginLeft, int marginTop, int marginRight, int marginBottom, int locationX, int locationY, const std::string& fontName, int fontSize, bool fontBold, bool fontUnderline, bool fontItalic, bool fontStrikeout, bool temp, std::string& outImagePath, std::string& errInfo) { outImagePath.clear(); errInfo = "错误"; if (imagePath.empty() || text.empty() || textColor.empty() || textOpacity < 0 || textOpacity > 255 || marginLeft < 0 || marginTop < 0 || marginRight < 0 || marginBottom < 0 || fontName.empty() || fontSize <= 0) return -1; HGUInt posType = 0; if ("left" == textPos) posType = HGIMGPROC_WMPOSTYPE_LEFT; else if ("top" == textPos) posType = HGIMGPROC_WMPOSTYPE_TOP; else if ("right" == textPos) posType = HGIMGPROC_WMPOSTYPE_RIGHT; else if ("bottom" == textPos) posType = HGIMGPROC_WMPOSTYPE_BOTTOM; else if ("left_top" == textPos) posType = HGIMGPROC_WMPOSTYPE_LEFTTOP; else if ("right_top" == textPos) posType = HGIMGPROC_WMPOSTYPE_RIGHTTOP; else if ("left_bottom" == textPos) posType = HGIMGPROC_WMPOSTYPE_LEFTBOTTOM; else if ("right_bottom" == textPos) posType = HGIMGPROC_WMPOSTYPE_RIGHTBOTTOM; else if ("center" == textPos) posType = HGIMGPROC_WMPOSTYPE_CENTER; else if ("location" == textPos) posType = HGIMGPROC_WMPOSTYPE_LOCATION; if (0 == posType) { return -1; } HGUInt r, g, b; if (!GetColor(textColor, r, g, b)) { return -1; } int ret = -1; HGImage image = NULL; HGImgFmt_LoadImage(imagePath.c_str(), 0, NULL, 0, HGBASE_IMGORIGIN_TOP, &image); if (NULL != image) { HGImageRoi roi; HGBase_GetImageROI(image, &roi); if (HGIMGPROC_WMPOSTYPE_LEFT == posType) { roi.left += marginLeft; } else if (HGIMGPROC_WMPOSTYPE_TOP == posType) { roi.top += marginTop; } else if (HGIMGPROC_WMPOSTYPE_RIGHT == posType) { roi.right -= marginRight; } else if (HGIMGPROC_WMPOSTYPE_BOTTOM == posType) { roi.bottom -= marginBottom; } else if (HGIMGPROC_WMPOSTYPE_LEFTTOP == posType) { roi.left += marginLeft; roi.top += marginTop; } else if (HGIMGPROC_WMPOSTYPE_RIGHTTOP == posType) { roi.top += marginTop; roi.right -= marginRight; } else if (HGIMGPROC_WMPOSTYPE_LEFTBOTTOM == posType) { roi.left += marginLeft; roi.bottom -= marginBottom; } else if (HGIMGPROC_WMPOSTYPE_RIGHTBOTTOM == posType) { roi.right -= marginRight; roi.bottom -= marginBottom; } HGImgWatermarkFontParam fontParam; strcpy(fontParam.foneName, fontName.c_str()); fontParam.fontSize = fontSize; fontParam.bold = fontBold; fontParam.underline = fontUnderline; fontParam.italic = fontItalic; fontParam.strikeout = fontStrikeout; HGColor color = HG_MAKECOLOR(r, g, b, textOpacity); if (HGBASE_ERR_OK == HGBase_SetImageROI(image, &roi) && HGBASE_ERR_OK == HGImgProc_AddImageWatermark(image, text.c_str(), color, posType, locationX, locationY, &fontParam)) { if (0 == SaveImage(image, temp, outImagePath)) { if (!temp) { m_saveFilePathList.push_back(outImagePath); RestoreSaveFilePathList(m_saveFilePathList); } errInfo.clear(); ret = 0; } } HGBase_DestroyImage(image); } return ret; } int ManagerV2::LocalImageDecontamination(const std::string& imagePath, const std::string mode, const std::string& color, int x, int y, int width, int height, bool temp, std::string& outImagePath, std::string& errInfo) { outImagePath.clear(); errInfo = "错误"; if (imagePath.empty() || mode.empty() || color.empty() || x < 0 || y < 0 || width <= 0 || height <= 0) return -1; if ("inside" != mode && "outside" != mode) return -1; HGUInt r, g, b; if (!GetColor(color, r, g, b)) { return -1; } int ret = -1; HGImage image = NULL; HGImgFmt_LoadImage(imagePath.c_str(), 0, NULL, 0, HGBASE_IMGORIGIN_TOP, &image); if (NULL != image) { HGUInt decoType = HGIMGPROC_DECOTYPE_INSIDE; if ("outside" == mode) decoType = HGIMGPROC_DECOTYPE_OUTSIDE; if (HGBASE_ERR_OK == HGImgProc_ImageDecontamination(image, image, decoType, x, y, width, height, HG_MAKECOLOR(r, g, b, 0))) { if (0 == SaveImage(image, temp, outImagePath)) { if (!temp) { m_saveFilePathList.push_back(outImagePath); RestoreSaveFilePathList(m_saveFilePathList); } errInfo.clear(); ret = 0; } } HGBase_DestroyImage(image); } return ret; } int ManagerV2::LocalImageDirectionCorrect(const std::string& imagePath, bool temp, std::string& outImagePath, std::string& errInfo) { outImagePath.clear(); errInfo = "错误"; if (imagePath.empty()) return -1; int ret = -1; HGImage image = NULL; HGImgFmt_LoadImage(imagePath.c_str(), 0, NULL, 0, HGBASE_IMGORIGIN_TOP, &image); if (NULL != image) { HGImage destImage = NULL; HGOCRMgr ocrMgr = NULL; HGImgProc_CreateOCRMgr(0, &ocrMgr); if (NULL != ocrMgr) { HGImageInfo imgInfo; HGBase_GetImageInfo(image, &imgInfo); HGUInt direct = 0; HGImgProc_ImageTextDirectOCR(ocrMgr, image, &direct); if (HGIMGPROC_OCRTEXTDIRECT_RIGHT == direct) { HGBase_CreateImage(imgInfo.height, imgInfo.width, imgInfo.type, imgInfo.origin, &destImage); HGBase_ImageRotateLeft(image, destImage); } else if (HGIMGPROC_OCRTEXTDIRECT_LEFT == direct) { HGBase_CreateImage(imgInfo.height, imgInfo.width, imgInfo.type, imgInfo.origin, &destImage); HGBase_ImageRotateRight(image, destImage); } else if (HGIMGPROC_OCRTEXTDIRECT_180 == direct) { HGBase_CreateImage(imgInfo.width, imgInfo.height, imgInfo.type, imgInfo.origin, &destImage); HGBase_ImageRotate180(image, destImage); } else { HGBase_CloneImage(image, imgInfo.type, imgInfo.origin, &destImage); } HGImgProc_DestroyOCRMgr(ocrMgr); } if (NULL != destImage) { if (0 == SaveImage(destImage, temp, outImagePath)) { if (!temp) { m_saveFilePathList.push_back(outImagePath); RestoreSaveFilePathList(m_saveFilePathList); } errInfo.clear(); ret = 0; } HGBase_DestroyImage(destImage); } HGBase_DestroyImage(image); } return ret; } int ManagerV2::LocalImageClip(const std::string& imagePath, int x, int y, int width, int height, bool temp, std::string& outImagePath, std::string& errInfo) { outImagePath.clear(); errInfo = "错误"; if (imagePath.empty() || x < 0 || y < 0 || width <= 0 || height <= 0) return -1; int ret = -1; HGImage image = NULL; HGImgFmt_LoadImage(imagePath.c_str(), 0, NULL, 0, HGBASE_IMGORIGIN_TOP, &image); if (NULL != image) { HGImageRoi roi; roi.left = x; roi.top = y; roi.right = roi.left + width; roi.bottom = roi.top + height; if (HGBASE_ERR_OK == HGBase_SetImageROI(image, &roi)) { HGImage image2 = NULL; if (HGBASE_ERR_OK == HGBase_CloneImage(image, 0, 0, &image2)) { if (0 == SaveImage(image2, temp, outImagePath)) { if (!temp) { m_saveFilePathList.push_back(outImagePath); RestoreSaveFilePathList(m_saveFilePathList); } errInfo.clear(); ret = 0; } HGBase_DestroyImage(image2); } } HGBase_DestroyImage(image); } return ret; } int ManagerV2::InitDevice(std::string& errInfo) { errInfo = "错误"; if (m_initDevice) { errInfo = "已初始化"; return -1; } SANE_Int version_code = 0; if (SANE_STATUS_GOOD != sane_init_ex(&version_code, sane_ex_callback, this)) { errInfo = "初始化失败"; return -1; } m_initDevice = true; errInfo.clear(); return 0; } int ManagerV2::DeinitDevice(std::string& errInfo) { errInfo = "错误"; if (!m_initDevice) { errInfo = "还未初始化"; return -1; } std::string errInfo2; CloseDevice(errInfo2); sane_exit(); m_devNameList.clear(); m_initDevice = false; errInfo.clear(); return 0; } bool ManagerV2::IsDeviceInit() { return m_initDevice; } int ManagerV2::GetDeviceNameList(std::vector& deviceNameList, std::string& errInfo) { deviceNameList.clear(); errInfo = "错误"; if (!m_initDevice) { errInfo = "还未初始化"; return -1; } HGBase_EnterLock(m_lock); deviceNameList = m_devNameList; HGBase_LeaveLock(m_lock); errInfo.clear(); return 0; } int ManagerV2::OpenDevice(const std::string& deviceName, std::string& errInfo) { errInfo = "错误"; if (!m_initDevice) { errInfo = "还未初始化"; return -1; } if (m_openDevice) { errInfo = "已打开设备"; return -1; } SANE_Handle dev = NULL; SANE_Status status = sane_open(deviceName.c_str(), &dev); if (SANE_STATUS_GOOD != status) { errInfo = Utf8ToStdString(sane_strstatus(status)); return -1; } // 从配置文件加载devParams std::vector devParams; LoadDeviceParams(deviceName, devParams); // 设置devParams到设备 SetParamsToDevice(dev, devParams); // 从设备获取到m_devParams if (0 == GetParamsFromDevice(dev, m_devParams)) { // 保存到配置文件 RestoreDeviceParams(deviceName, m_devParams); } m_devHandle = dev; m_devName = deviceName; m_openDevice = true; errInfo.clear(); std::string snError; GetDeviceSN(m_sn, snError); return 0; } int ManagerV2::CloseDevice(std::string& errInfo) { errInfo = "错误"; if (!m_openDevice) { errInfo = "还未打开设备"; return -1; } std::string errInfo2; StopScan(errInfo2); sane_close(m_devHandle); m_devHandle = NULL; m_devName.clear(); m_devParams.clear(); m_openDevice = false; errInfo.clear(); m_sn.clear(); return 0; } int ManagerV2::GetDeviceSN(std::string& sn, std::string& errInfo) { errInfo = "错误"; sn.clear(); if (!m_openDevice) { errInfo = "还未打开设备"; return -1; } char v[256] = {0}; SANE_Status status = sane_control_option(m_devHandle, (SANE_Int)0x8856, SANE_ACTION_GET_VALUE, v, NULL); if (SANE_STATUS_GOOD != status) { errInfo = Utf8ToStdString(sane_strstatus(status)); return -1; } sn = v; errInfo.clear(); return 0; } int ManagerV2::GetDeviceFWVersion(std::string& fwVer, std::string& errInfo) { errInfo = "错误"; fwVer.clear(); if (!m_openDevice) { errInfo = "还未打开设备"; return -1; } char v[256] = {0}; SANE_Status status = sane_control_option(m_devHandle, (SANE_Int)0x8857, SANE_ACTION_GET_VALUE, v, NULL); if (SANE_STATUS_GOOD != status) { errInfo = Utf8ToStdString(sane_strstatus(status)); return -1; } fwVer = v; errInfo.clear(); return 0; } int ManagerV2::SetDeviceParam(const std::vector& devParams, std::string& errInfo) { errInfo = "错误"; if (!m_openDevice) { errInfo = "还未打开设备"; return -1; } if (m_scanning) { errInfo = "已启动扫描"; return -1; } // 设置devParams到设备 int ret = SetParamsToDevice(m_devHandle, devParams); // 从设备获取到m_devParams if (0 == GetParamsFromDevice(m_devHandle, m_devParams)) { // 保存到配置文件 RestoreDeviceParams(m_devName, m_devParams); } if (0 == ret) errInfo.clear(); return ret; } int ManagerV2::GetDeviceParam(std::vector& devParams, std::string& errInfo) { devParams.clear(); errInfo = "错误"; if (!m_openDevice) { errInfo = "还未打开设备"; return -1; } if (m_devParams.empty()) { errInfo = "获取设备信息失败"; return -1; } devParams = m_devParams; errInfo.clear(); return 0; } int ManagerV2::ResetDeviceParam(std::string& errInfo) { errInfo = "错误"; if (!m_openDevice) { errInfo = "还未打开设备"; return -1; } if (m_scanning) { errInfo = "已启动扫描"; return -1; } // 重置参数 int ret = ResetParamsToDevice(m_devHandle); // 从设备获取到m_devParams if (0 == GetParamsFromDevice(m_devHandle, m_devParams)) { // 保存到配置文件 RestoreDeviceParams(m_devName, m_devParams); } if (0 == ret) errInfo.clear(); return ret; } int ManagerV2::GetCurrDeviceName(std::string& deviceName, std::string& errInfo) { errInfo = "错误"; if (!m_openDevice) { errInfo = "还未打开设备"; return -1; } deviceName = m_devName; errInfo.clear(); return 0; } int ManagerV2::StartScan(bool blankCheck, bool temp, std::string& errInfo) { errInfo = "错误"; if (!m_openDevice) { errInfo = "还未打开设备"; return -1; } if (m_scanning) { errInfo = "已启动扫描"; return -1; } m_scanBlankCheck = blankCheck; m_scanTemp = temp; HGBase_CreateEvent(HGFALSE, HGFALSE, &m_scanEvent); assert(NULL != m_scanEvent); m_dpi = GetDpi(); SANE_Status status = sane_start(m_devHandle); if (SANE_STATUS_GOOD != status) { errInfo = Utf8ToStdString(sane_strstatus(status)); HGBase_DestroyEvent(m_scanEvent); m_scanEvent = NULL; m_scanBlankCheck = false; m_scanTemp = false; m_dpi = 200; return -1; } m_scanning = true; errInfo.clear(); return 0; } int ManagerV2::StopScan(std::string& errInfo) { errInfo = "错误"; if (!m_scanning) { errInfo = "还未启动扫描"; return -1; } assert(NULL != m_devHandle); sane_cancel(m_devHandle); assert(NULL != m_scanEvent); HGBase_WaitEvent(m_scanEvent); HGBase_DestroyEvent(m_scanEvent); m_scanEvent = NULL; m_scanBlankCheck = false; m_scanTemp = false; m_scanning = false; m_dpi = 200; errInfo.clear(); return 0; } bool ManagerV2::IsScanning() { return m_scanning; } int ManagerV2::GetBatchIdList(std::vector& batchIdList, std::string& errInfo) { batchIdList.clear(); errInfo = "错误"; if (NULL == m_sqlite) return -1; sqlite3_stmt* stmt = NULL; int ret = sqlite3_prepare(m_sqlite, "select name from table_ order by id asc", -1, &stmt, NULL); assert(0 == ret); ret = sqlite3_step(stmt); while (SQLITE_ROW == ret) { const char *name = (const char*)sqlite3_column_text(stmt, 0); batchIdList.push_back(name); ret = sqlite3_step(stmt); } ret = sqlite3_finalize(stmt); assert(0 == ret); errInfo.clear(); return 0; } int ManagerV2::OpenBatch(const std::string& batchId, std::string& errInfo) { errInfo = "错误"; if (batchId.empty()) return -1; std::vector batchIdList; std::string errInfo2; GetBatchIdList(batchIdList, errInfo2); int ret = -1; for (int i = 0; i < (int)batchIdList.size(); ++i) { if (batchId == batchIdList[i]) { if (m_currBatchId != batchId) { m_currBatchId = batchId; if (!m_bindFolder.empty()) { ClearBindFolder(); UpdateBindFolder(); } } errInfo.clear(); ret = 0; break; } } return ret; } int ManagerV2::DeleteBatch(const std::string& batchId, std::string& errInfo) { errInfo = "错误"; if (batchId.empty() || batchId == m_currBatchId) return -1; if (NULL == m_sqlite) return -1; char sql[256]; int ret = sqlite3_exec(m_sqlite, "begin", NULL, NULL, NULL); assert(0 == ret); sprintf(sql, "drop table 'table_%s_idx'", batchId.c_str()); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); return -1; } sprintf(sql, "drop table 'table_%s'", batchId.c_str()); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); return -1; } sprintf(sql, "delete from table_ where name = '%s'", batchId.c_str()); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); return -1; } ret = sqlite3_exec(m_sqlite, "commit", NULL, NULL, NULL); assert(0 == ret); errInfo.clear(); return 0; } int ManagerV2::NewBatch(const std::string& batchId, std::string& errInfo) { errInfo = "错误"; if (batchId.empty()) return -1; if (NULL == m_sqlite) return -1; char sql[256]; int ret = sqlite3_exec(m_sqlite, "begin", NULL, NULL, NULL); assert(0 == ret); sprintf(sql, "create table 'table_%s' (id integer primary key autoincrement, format text, tag text, image blob, thumb blob)", batchId.c_str()); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); return -1; } sprintf(sql, "create table 'table_%s_idx' (id integer, idx integer)", batchId.c_str()); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); return -1; } sprintf(sql, "insert into table_ (name) values ('%s')", batchId.c_str()); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); return -1; } ret = sqlite3_exec(m_sqlite, "commit", NULL, NULL, NULL); assert(0 == ret); m_currBatchId = batchId; if (!m_bindFolder.empty()) { ClearBindFolder(); UpdateBindFolder(); } errInfo.clear(); return 0; } int ManagerV2::GetCurrBatchId(std::string& batchId, std::string& errInfo) { batchId.clear(); errInfo = "错误"; if (NULL == m_sqlite) return -1; batchId = m_currBatchId; errInfo.clear(); return 0; } int ManagerV2::ModifyBatchId(const std::string& batchId, const std::string& newBatchId, std::string& errInfo) { errInfo = "错误"; if (batchId.empty() || newBatchId.empty()) return -1; if (NULL == m_sqlite) return -1; char sql[256]; int ret = sqlite3_exec(m_sqlite, "begin", NULL, NULL, NULL); assert(0 == ret); sprintf(sql, "alter table 'table_%s' rename to 'table_%s'", batchId.c_str(), newBatchId.c_str()); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); return -1; } sprintf(sql, "alter table 'table_%s_idx' rename to 'table_%s_idx'", batchId.c_str(), newBatchId.c_str()); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); return -1; } sprintf(sql, "update table_ set name = '%s' where name = '%s'", newBatchId.c_str(), batchId.c_str()); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); return -1; } ret = sqlite3_exec(m_sqlite, "commit", NULL, NULL, NULL); assert(0 == ret); if (batchId == m_currBatchId) m_currBatchId = newBatchId; errInfo.clear(); return 0; } int ManagerV2::BindFolder(const std::string& folder, const std::string& nameMode, int nameWidth, int nameBase, std::string& errInfo) { errInfo = "错误"; if (folder.empty()) return -1; if ("order" != nameMode || nameWidth <= 0 || nameBase < 0) return -1; // 需要保证文件夹为空?? if (NULL == m_sqlite) return -1; m_bindFolder = folder; m_bindFolder.push_back('/'); HGChar stdBindFolder[256]; HGBase_StandardiseFileName(m_bindFolder.c_str(), stdBindFolder, 256); m_bindFolder = stdBindFolder; m_bindNameMode = nameMode; m_bindNameWidth = nameWidth; m_bindNameBase = nameBase; ClearBindFolder(); UpdateBindFolder(); errInfo.clear(); return 0; } int ManagerV2::StopBindFolder(std::string& errInfo) { errInfo = "错误"; if (NULL == m_sqlite) return -1; m_bindFolder.clear(); m_bindNameMode.clear(); m_bindNameWidth = 0; m_bindNameBase = 0; errInfo.clear(); return 0; } int ManagerV2::GetImageThumbnailList(std::vector& imageThumbList, std::string& errInfo) { imageThumbList.clear(); errInfo = "错误"; if (NULL == m_sqlite) return -1; int rc = -1; sqlite3_stmt* stmt = NULL; char sql[256]; sprintf(sql, "select format, tag, thumb from table_%s join table_%s_idx on table_%s.id == table_%s_idx.id order by table_%s_idx.idx asc", m_currBatchId.c_str(), m_currBatchId.c_str(), m_currBatchId.c_str(), m_currBatchId.c_str(), m_currBatchId.c_str()); int ret = sqlite3_prepare(m_sqlite, sql, -1, &stmt, NULL); assert(0 == ret); ret = sqlite3_step(stmt); while (SQLITE_ROW == ret) { ImageThumbInfo thumbInfo; imageThumbList.push_back(thumbInfo); ImageThumbInfo& thumbInfoEx = imageThumbList[imageThumbList.size() - 1]; std::string imgFmt = (const char*)sqlite3_column_text(stmt, 0); std::string imgTag = (const char*)sqlite3_column_text(stmt, 1); const void* thumbData = sqlite3_column_blob(stmt, 2); int thumbSize = sqlite3_column_bytes(stmt, 2); thumbInfoEx.tag = imgTag; SaveToBase64((const HGByte*)thumbData, thumbSize, thumbInfoEx.thumbBase64); assert(!thumbInfoEx.thumbBase64.empty()); std::string prefix; if ("jpg" == imgFmt) prefix = "data:image/jpeg;base64,"; else if ("bmp" == imgFmt) prefix = "data:image/bmp;base64,"; else if ("png" == imgFmt) prefix = "data:image/png;base64,"; else if ("tif" == imgFmt) prefix = "data:image/tiff;base64,"; else if ("pdf" == imgFmt) prefix = "data:image/pdf;base64,"; else if ("ofd" == imgFmt) prefix = "data:image/ofd;base64,"; thumbInfoEx.thumbBase64.insert(0, prefix); ret = sqlite3_step(stmt); } ret = sqlite3_finalize(stmt); assert(0 == ret); errInfo.clear(); return 0; } int ManagerV2::GetImageCount(int& imageCount, std::string& errInfo) { imageCount = 0; errInfo = "错误"; if (NULL == m_sqlite) return -1; char** result = NULL; char sql[256]; sprintf(sql, "select id from 'table_%s_idx'", m_currBatchId.c_str()); int rows, cols; int ret = sqlite3_get_table(m_sqlite, sql, &result, &rows, &cols, NULL); assert(0 == ret); imageCount = rows; sqlite3_free_table(result); errInfo.clear(); return 0; } int ManagerV2::LoadImage(int imageIndex, std::string& imageTag, std::string& imageBase64, std::string& errInfo) { imageTag.clear(); imageBase64.clear(); errInfo = "错误"; if (NULL == m_sqlite) return -1; int id = GetId(imageIndex); if (-1 == id) return -1; int rc = -1; sqlite3_stmt* stmt = NULL; char sql[256]; sprintf(sql, "select format, tag, image from 'table_%s' where id = '%d'", m_currBatchId.c_str(), id); int ret = sqlite3_prepare(m_sqlite, sql, -1, &stmt, NULL); assert(0 == ret); ret = sqlite3_step(stmt); if (SQLITE_ROW == ret) { std::string imgFmt = (const char*)sqlite3_column_text(stmt, 0); std::string imgTag = (const char*)sqlite3_column_text(stmt, 1); const void* imgData = sqlite3_column_blob(stmt, 2); int imgSize = sqlite3_column_bytes(stmt, 2); if (SaveToBase64((const HGByte*)imgData, imgSize, imageBase64)) { imageTag = imgTag; std::string prefix; if ("jpg" == imgFmt) prefix = "data:image/jpeg;base64,"; else if ("bmp" == imgFmt) prefix = "data:image/bmp;base64,"; else if ("png" == imgFmt) prefix = "data:image/png;base64,"; else if ("tif" == imgFmt) prefix = "data:image/tiff;base64,"; else if ("pdf" == imgFmt) prefix = "data:image/pdf;base64,"; else if ("ofd" == imgFmt) prefix = "data:image/ofd;base64,"; imageBase64.insert(0, prefix); errInfo.clear(); rc = 0; } } ret = sqlite3_finalize(stmt); assert(0 == ret); return rc; } int ManagerV2::SaveImage(int imageIndex, bool temp, std::string& imagePath, std::string& errInfo) { imagePath.clear(); errInfo = "错误"; if (NULL == m_sqlite) return -1; int id = GetId(imageIndex); if (-1 == id) return -1; int rc = -1; sqlite3_stmt* stmt = NULL; char sql[256]; sprintf(sql, "select format, image from 'table_%s' where id = '%d'", m_currBatchId.c_str(), id); int ret = sqlite3_prepare(m_sqlite, sql, -1, &stmt, NULL); assert(0 == ret); ret = sqlite3_step(stmt); if (SQLITE_ROW == ret) { std::string imgFmt = (const char*)sqlite3_column_text(stmt, 0); const void* imgData = sqlite3_column_blob(stmt, 1); int imgSize = sqlite3_column_bytes(stmt, 1); std::string imagePath2 = GetFilePath(temp, imgFmt.c_str()); if (SaveToFile((const HGByte*)imgData, imgSize, imagePath2)) { imagePath = imagePath2; if (!temp) { m_saveFilePathList.push_back(imagePath); RestoreSaveFilePathList(m_saveFilePathList); } errInfo.clear(); rc = 0; } } ret = sqlite3_finalize(stmt); assert(0 == ret); return rc; } int ManagerV2::InsertLocalImage(const std::string& imagePath, int insertPos, const std::string& imageTag, std::string& errInfo) { errInfo = "错误"; if (NULL == m_sqlite || imagePath.empty() || insertPos < -1) return -1; HGUInt imgSize = 0; std::string imgFormat; HGByte* imgData = LoadImageFromPath(imagePath.c_str(), imgSize, imgFormat); if (NULL == imgData) return -1; HGUInt thumbSize = 0; HGByte* thumbData = LoadThumbFromPath(imagePath.c_str(), thumbSize); if (NULL == thumbData) { delete[] imgData; return -1; } std::vector tables; GetBatchTableInfo(tables); if (-1 == insertPos) insertPos = (int)tables.size(); else if (insertPos > (int)tables.size()) { delete[] thumbData; delete[] imgData; return -1; } int ret; char sql[1024]; ret = sqlite3_exec(m_sqlite, "begin", NULL, NULL, NULL); assert(0 == ret); do { sprintf(sql, "insert into 'table_%s' (format, tag, image, thumb) values ('%s', '%s', ?, ?)", m_currBatchId.c_str(), imgFormat.c_str(), imageTag.c_str()); sqlite3_stmt* stmt = NULL; ret = sqlite3_prepare(m_sqlite, sql, -1, &stmt, NULL); assert(0 == ret); ret = sqlite3_bind_blob(stmt, 1, imgData, (int)imgSize, NULL); assert(0 == ret); ret = sqlite3_bind_blob(stmt, 2, thumbData, (int)thumbSize, NULL); assert(0 == ret); sqlite3_step(stmt); ret = sqlite3_finalize(stmt); if (0 != ret) { break; } bool ok = true; for (int i = 0; i < (int)tables.size(); ++i) { if (i >= insertPos) { sprintf(sql, "update 'table_%s_idx' set idx = '%d' where id = '%d'", m_currBatchId.c_str(), i + 1, tables[i].id); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { ok = false; break; } } } if (!ok) { break; } int id = (int)sqlite3_last_insert_rowid(m_sqlite); sprintf(sql, "insert into 'table_%s_idx' (id, idx) values ('%d', '%d')", m_currBatchId.c_str(), id, insertPos); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { break; } } while (0); if (0 != ret) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); delete[] thumbData; delete[] imgData; return -1; } ret = sqlite3_exec(m_sqlite, "commit", NULL, NULL, NULL); assert(0 == ret); if (!m_bindFolder.empty()) { InsertBindFolderImage(tables, insertPos, imgFormat, imgData, imgSize); } delete[] thumbData; delete[] imgData; errInfo.clear(); return 0; } int ManagerV2::InsertImage(const std::string& imageBase64, int insertPos, const std::string& imageTag, std::string& errInfo) { errInfo = "错误"; if (NULL == m_sqlite || imageBase64.empty() || insertPos < -1) return -1; HGUInt imgSize = 0; std::string imgFormat; HGByte* imgData = LoadImageFromBase64(imageBase64.c_str(), imgSize, imgFormat); if (NULL == imgData) return -1; HGUInt thumbSize = 0; HGByte* thumbData = LoadThumbFromBase64(imageBase64.c_str(), thumbSize); if (NULL == thumbData) { delete[] imgData; return -1; } std::vector tables; GetBatchTableInfo(tables); if (-1 == insertPos) insertPos = (int)tables.size(); else if (insertPos > (int)tables.size()) { delete[] thumbData; delete[] imgData; return -1; } int ret; char sql[1024]; ret = sqlite3_exec(m_sqlite, "begin", NULL, NULL, NULL); assert(0 == ret); do { sprintf(sql, "insert into 'table_%s' (format, tag, image, thumb) values ('%s', '%s', ?, ?)", m_currBatchId.c_str(), imgFormat.c_str(), imageTag.c_str()); sqlite3_stmt* stmt = NULL; ret = sqlite3_prepare(m_sqlite, sql, -1, &stmt, NULL); assert(0 == ret); ret = sqlite3_bind_blob(stmt, 1, imgData, (int)imgSize, NULL); assert(0 == ret); ret = sqlite3_bind_blob(stmt, 2, thumbData, (int)thumbSize, NULL); assert(0 == ret); sqlite3_step(stmt); ret = sqlite3_finalize(stmt); if (0 != ret) { break; } bool ok = true; for (int i = 0; i < (int)tables.size(); ++i) { if (i >= insertPos) { sprintf(sql, "update 'table_%s_idx' set idx = '%d' where id = '%d'", m_currBatchId.c_str(), i + 1, tables[i].id); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { ok = false; break; } } } if (!ok) { break; } int id = (int)sqlite3_last_insert_rowid(m_sqlite); sprintf(sql, "insert into 'table_%s_idx' (id, idx) values ('%d', '%d')", m_currBatchId.c_str(), id, insertPos); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { break; } } while (0); if (0 != ret) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); delete[] thumbData; delete[] imgData; return -1; } ret = sqlite3_exec(m_sqlite, "commit", NULL, NULL, NULL); assert(0 == ret); if (!m_bindFolder.empty()) { InsertBindFolderImage(tables, insertPos, imgFormat, imgData, imgSize); } delete[] thumbData; delete[] imgData; errInfo.clear(); return 0; } int ManagerV2::ModifyImageTag(const std::vector& imageIndexList, const std::vector& imageTagList, std::string& errInfo) { errInfo = "错误"; if (NULL == m_sqlite || imageIndexList.empty() || imageTagList.empty() || imageIndexList.size() != imageTagList.size()) return -1; std::vector tables; GetBatchTableInfo(tables); bool indexValid = true; for (int i = 0; i < (int)imageIndexList.size(); ++i) { if (imageIndexList[i] < 0 || imageIndexList[i] >= (int)tables.size()) { indexValid = false; break; } } if (!indexValid) return -1; int ret; char sql[1024]; ret = sqlite3_exec(m_sqlite, "begin", NULL, NULL, NULL); assert(0 == ret); bool ok = true; for (int i = 0; i < (int)imageIndexList.size(); ++i) { int id = tables[imageIndexList[i]].id; sprintf(sql, "update 'table_%s' set tag = '%s' where id = '%d'", m_currBatchId.c_str(), imageTagList[i].c_str(), id); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { ok = false; break; } } if (!ok) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); return -1; } ret = sqlite3_exec(m_sqlite, "commit", NULL, NULL, NULL); assert(0 == ret); errInfo.clear(); return 0; } int ManagerV2::DeleteImage(const std::vector& imageIndexList, std::string& errInfo) { errInfo = "错误"; if (NULL == m_sqlite || imageIndexList.empty()) return -1; std::vector tables; GetBatchTableInfo(tables); bool indexValid = true; for (int i = 0; i < (int)imageIndexList.size(); ++i) { if (imageIndexList[i] < 0 || imageIndexList[i] >= (int)tables.size()) { indexValid = false; break; } } if (!indexValid) return -1; int ret; char sql[1024]; ret = sqlite3_exec(m_sqlite, "begin", NULL, NULL, NULL); assert(0 == ret); bool ok = true; for (int i = 0; i < (int)imageIndexList.size(); ++i) { int id = tables[imageIndexList[i]].id; sprintf(sql, "delete from 'table_%s' where id = '%d'", m_currBatchId.c_str(), id); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { ok = false; break; } sprintf(sql, "delete from 'table_%s_idx' where id = '%d'", m_currBatchId.c_str(), id); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { ok = false; break; } } if (!ok) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); return -1; } int value = 0; for (int i = 0; i < (int)tables.size(); ++i) { bool find = false; for (int j = 0; j < (int)imageIndexList.size(); ++j) { if (i == imageIndexList[j]) { find = true; break; } } if (find) { ++value; } else { if (value > 0) { sprintf(sql, "update 'table_%s_idx' set idx = '%d' where id = '%d'", m_currBatchId.c_str(), i - value, tables[i].id); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { ok = false; break; } } } } if (!ok) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); return -1; } ret = sqlite3_exec(m_sqlite, "commit", NULL, NULL, NULL); assert(0 == ret); if (!m_bindFolder.empty()) { DeleteBindFolderImage(tables, imageIndexList); } errInfo.clear(); return 0; } int ManagerV2::ClearImageList(std::string& errInfo) { errInfo = "错误"; if (NULL == m_sqlite) return -1; std::vector tables; GetBatchTableInfo(tables); char sql[256]; int ret = sqlite3_exec(m_sqlite, "begin", NULL, NULL, NULL); assert(0 == ret); sprintf(sql, "delete from 'table_%s'", m_currBatchId.c_str()); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); return -1; } sprintf(sql, "delete from 'table_%s_idx'", m_currBatchId.c_str()); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); return -1; } ret = sqlite3_exec(m_sqlite, "commit", NULL, NULL, NULL); assert(0 == ret); if (!m_bindFolder.empty()) { ClearBindFolderImageList(tables); } errInfo.clear(); return 0; } int ManagerV2::ModifyImage(int imageIndex, const std::string& imageBase64, std::string& errInfo) { errInfo = "错误"; if (NULL == m_sqlite || imageIndex < 0 || imageBase64.empty()) return -1; HGUInt imgSize = 0; std::string imgFormat; HGByte* imgData = LoadImageFromBase64(imageBase64.c_str(), imgSize, imgFormat); if (NULL == imgData) return -1; HGUInt thumbSize = 0; HGByte* thumbData = LoadThumbFromBase64(imageBase64.c_str(), thumbSize); if (NULL == thumbData) { delete[] imgData; return -1; } std::vector tables; GetBatchTableInfo(tables); if (imageIndex >= (int)tables.size()) { delete[] thumbData; delete[] imgData; return -1; } int ret; char sql[1024]; ret = sqlite3_exec(m_sqlite, "begin", NULL, NULL, NULL); assert(0 == ret); int id = tables[imageIndex].id; sprintf(sql, "update 'table_%s' set format = '%s', image = ?, thumb = ? where id = '%d'", m_currBatchId.c_str(), imgFormat.c_str(), id); sqlite3_stmt* stmt = NULL; ret = sqlite3_prepare(m_sqlite, sql, -1, &stmt, NULL); assert(0 == ret); ret = sqlite3_bind_blob(stmt, 1, imgData, (int)imgSize, NULL); assert(0 == ret); ret = sqlite3_bind_blob(stmt, 2, thumbData, (int)thumbSize, NULL); assert(0 == ret); sqlite3_step(stmt); ret = sqlite3_finalize(stmt); if (0 != ret) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); delete[] thumbData; delete[] imgData; return -1; } ret = sqlite3_exec(m_sqlite, "commit", NULL, NULL, NULL); assert(0 == ret); if (!m_bindFolder.empty()) { ModifyBindFolderImage(tables, imageIndex, imgFormat, imgData, imgSize); } delete[] thumbData; delete[] imgData; errInfo.clear(); return 0; } int ManagerV2::ModifyImageByLocal(int imageIndex, const std::string& imagePath, std::string& errInfo) { errInfo = "错误"; if (NULL == m_sqlite || imageIndex < 0 || imagePath.empty()) return -1; HGUInt imgSize = 0; std::string imgFormat; HGByte* imgData = LoadImageFromPath(imagePath.c_str(), imgSize, imgFormat); if (NULL == imgData) return -1; HGUInt thumbSize = 0; HGByte* thumbData = LoadThumbFromPath(imagePath.c_str(), thumbSize); if (NULL == thumbData) { delete[] imgData; return -1; } std::vector tables; GetBatchTableInfo(tables); if (imageIndex >= (int)tables.size()) { delete[] thumbData; delete[] imgData; return -1; } int ret; char sql[1024]; ret = sqlite3_exec(m_sqlite, "begin", NULL, NULL, NULL); assert(0 == ret); int id = tables[imageIndex].id; sprintf(sql, "update 'table_%s' set format = '%s', image = ?, thumb = ? where id = '%d'", m_currBatchId.c_str(), imgFormat.c_str(), id); sqlite3_stmt* stmt = NULL; ret = sqlite3_prepare(m_sqlite, sql, -1, &stmt, NULL); assert(0 == ret); ret = sqlite3_bind_blob(stmt, 1, imgData, (int)imgSize, NULL); assert(0 == ret); ret = sqlite3_bind_blob(stmt, 2, thumbData, (int)thumbSize, NULL); assert(0 == ret); sqlite3_step(stmt); ret = sqlite3_finalize(stmt); if (0 != ret) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); delete[] thumbData; delete[] imgData; return -1; } ret = sqlite3_exec(m_sqlite, "commit", NULL, NULL, NULL); assert(0 == ret); if (!m_bindFolder.empty()) { ModifyBindFolderImage(tables, imageIndex, imgFormat, imgData, imgSize); } delete[] thumbData; delete[] imgData; errInfo.clear(); return 0; } int ManagerV2::MoveImage(const std::vector& imageIndexList, const std::string& mode, int target, std::string& errInfo) { errInfo = "错误"; if (NULL == m_sqlite || imageIndexList.empty() || target < 0) return -1; if ("pos" != mode && "index" != mode) return -1; std::vector tables; GetBatchTableInfo(tables); std::vector tables2 = tables; if (tables.empty()) return -1; if ("pos" == mode && target > (int)tables.size()) return -1; if ("index" == mode && target >= (int)tables.size()) return -1; bool indexValid = true; for (int i = 0; i < (int)imageIndexList.size(); ++i) { if (imageIndexList[i] < 0 || imageIndexList[i] >= (int)tables.size()) { indexValid = false; break; } } if (!indexValid) return -1; std::vector idList; for (int i = 0; i < (int)imageIndexList.size(); ++i) { int id = tables[imageIndexList[i]].id; idList.push_back(id); } if ("pos" == mode) { int posEx = target; for (int i = 0; i < (int)idList.size(); ++i) { int oldIndex = -1; for (int j = 0; j < (int)tables.size(); ++j) { if (idList[i] == tables[j].id) { oldIndex = j; break; } } assert(-1 != oldIndex); BatchTableInfo info = tables[oldIndex]; if (oldIndex < posEx) --posEx; tables.erase(tables.begin() + oldIndex); if (posEx != (int)tables.size()) tables.insert(tables.begin() + posEx, info); else tables.push_back(info); ++posEx; } } else { std::vector infos; for (int i = 0; i < (int)idList.size(); ++i) { int oldIndex = -1; for (int j = 0; j < (int)tables.size(); ++j) { if (idList[i] == tables[j].id) { oldIndex = j; break; } } assert(-1 != oldIndex); BatchTableInfo info = tables[oldIndex]; tables.erase(tables.begin() + oldIndex); infos.push_back(info); } if (target < (int)tables.size()) { int indexEx = target; for (int i = 0; i < (int)infos.size(); ++i) { tables.insert(tables.begin() + indexEx, infos[i]); ++indexEx; } } else { for (int i = 0; i < (int)infos.size(); ++i) { tables.push_back(infos[i]); } } } int ret; char sql[1024]; ret = sqlite3_exec(m_sqlite, "begin", NULL, NULL, NULL); assert(0 == ret); bool ok = true; for (int i = 0; i < (int)tables.size(); ++i) { sprintf(sql, "update 'table_%s_idx' set idx = '%d' where id = '%d'", m_currBatchId.c_str(), i, tables[i].id); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { ok = false; break; } } if (!ok) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); return -1; } ret = sqlite3_exec(m_sqlite, "commit", NULL, NULL, NULL); assert(0 == ret); if (!m_bindFolder.empty()) { ClearBindFolderImageList(tables2); UpdateBindFolder(); } errInfo.clear(); return 0; } int ManagerV2::ExchangeImage(int imageIndex1, int imageIndex2, std::string& errInfo) { errInfo = "错误"; if (NULL == m_sqlite || imageIndex1 == imageIndex2) return -1; std::vector tables; GetBatchTableInfo(tables); if (imageIndex1 < 0 || imageIndex1 >= (int)tables.size() || imageIndex2 < 0 || imageIndex2 >= (int)tables.size()) return -1; int ret; char sql[1024]; ret = sqlite3_exec(m_sqlite, "begin", NULL, NULL, NULL); assert(0 == ret); sprintf(sql, "update 'table_%s_idx' set idx = '%d' where id = '%d'", m_currBatchId.c_str(), imageIndex2, tables[imageIndex1].id); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); return -1; } sprintf(sql, "update 'table_%s_idx' set idx = '%d' where id = '%d'", m_currBatchId.c_str(), imageIndex1, tables[imageIndex2].id); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); return -1; } ret = sqlite3_exec(m_sqlite, "commit", NULL, NULL, NULL); assert(0 == ret); if (!m_bindFolder.empty()) { ExchangeBindFolderImage(tables, imageIndex1, imageIndex2); } errInfo.clear(); return 0; } int ManagerV2::ImageBookSort(std::string& errInfo) { errInfo = "错误"; if (NULL == m_sqlite) return -1; std::vector tables; GetBatchTableInfo(tables); std::vector tables2 = tables; std::list infos1, infos2; for (int i = 0; i < (int)tables.size(); ++i) { BatchTableInfo info = tables[i]; if (0 == i % 2) infos1.push_back(info); else infos2.push_front(info); } tables.clear(); std::list::const_iterator iter; for (iter = infos1.begin(); iter != infos1.end(); ++iter) tables.push_back(*iter); for (iter = infos2.begin(); iter != infos2.end(); ++iter) tables.push_back(*iter); int ret; char sql[1024]; ret = sqlite3_exec(m_sqlite, "begin", NULL, NULL, NULL); assert(0 == ret); bool ok = true; for (int i = 0; i < (int)tables.size(); ++i) { sprintf(sql, "update 'table_%s_idx' set idx = '%d' where id = '%d'", m_currBatchId.c_str(), i, tables[i].id); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { ok = false; break; } } if (0 != ret) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); return -1; } ret = sqlite3_exec(m_sqlite, "commit", NULL, NULL, NULL); assert(0 == ret); if (!m_bindFolder.empty()) { ClearBindFolderImageList(tables2); UpdateBindFolder(); } errInfo.clear(); return 0; } int ManagerV2::LoadBase64(const std::string& fileName, std::string& base64) { base64.clear(); int ret = -1; FILE* file = fopen(fileName.c_str(), "rb"); if (NULL != file) { fseek(file, 0, SEEK_END); long size = ftell(file); fseek(file, 0, SEEK_SET); if (size > 0) { HGByte* data = new HGByte[size]; long readLen = (long)fread(data, 1, size, file); if (readLen == size) { HGSize base64Size = 0; HGBase_Base64Encode(data, size, NULL, &base64Size); uint8_t* base64Data = new uint8_t[base64Size + 1]; HGBase_Base64Encode(data, size, base64Data, &base64Size); base64Data[base64Size] = 0; base64 = (const char*)base64Data; delete[] base64Data; ret = 0; } delete[] data; } fclose(file); } return ret; } int ManagerV2::SaveBase64(const std::string& base64, const std::string& fileName) { if (base64.empty()) return -1; const char* base64Data = base64.c_str(); size_t base64Size = base64.size(); int ret = -1; FILE* file = fopen(fileName.c_str(), "wb"); if (NULL != file) { HGSize size = 0; HGBase_Base64Decode((const HGByte*)base64Data, (HGSize)base64Size, NULL, &size); uint8_t* data = new HGByte[size]; HGBase_Base64Decode((const HGByte*)base64Data, (HGSize)base64Size, data, &size); size_t writeLen = fwrite(data, 1, size, file); if (writeLen == (size_t)size) ret = 0; delete[] data; fclose(file); } else { HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "ManagerV2::SaveBase64 Create File Fail %s", fileName.c_str()); } if (0 != ret) HGBase_DeleteFile(fileName.c_str()); return ret; } std::string ManagerV2::GetCfgStringValue(const std::string& app, const std::string& key, const std::string& def) { HGChar cfgPath[256]; HGBase_GetConfigPath(cfgPath, 256); strcat(cfgPath, "config2.ini"); HGChar val[256] = { 0 }; HGBase_GetProfileString(cfgPath, app.c_str(), key.c_str(), def.c_str(), val, 256); return val; } int ManagerV2::GetCfgIntValue(const std::string& app, const std::string& key, int def) { HGChar cfgPath[256]; HGBase_GetConfigPath(cfgPath, 256); strcat(cfgPath, "config2.ini"); HGInt val = 0; HGBase_GetProfileInt(cfgPath, app.c_str(), key.c_str(), def, &val); return val; } double ManagerV2::GetCfgDoubleValue(const std::string& app, const std::string& key, double def) { HGChar cfgPath[256]; HGBase_GetConfigPath(cfgPath, 256); strcat(cfgPath, "config2.ini"); char defStr[32]; sprintf(defStr, "%f", def); HGChar val[256] = { 0 }; HGBase_GetProfileString(cfgPath, app.c_str(), key.c_str(), defStr, val, 256); return atof(val); } bool ManagerV2::GetCfgBoolValue(const std::string& app, const std::string& key, bool def) { HGChar cfgPath[256]; HGBase_GetConfigPath(cfgPath, 256); strcat(cfgPath, "config2.ini"); HGInt val = 0; HGBase_GetProfileInt(cfgPath, app.c_str(), key.c_str(), (HGInt)def, &val); return (bool)val; } bool ManagerV2::SetCfgStringValue(const std::string& app, const std::string& key, const std::string& val) { HGChar cfgPath[256]; HGBase_GetConfigPath(cfgPath, 256); HGBase_CreateDir(cfgPath); strcat(cfgPath, "config2.ini"); return (HGBASE_ERR_OK == HGBase_SetProfileString(cfgPath, app.c_str(), key.c_str(), val.c_str())); } bool ManagerV2::SetCfgIntValue(const std::string& app, const std::string& key, int val) { HGChar cfgPath[256]; HGBase_GetConfigPath(cfgPath, 256); HGBase_CreateDir(cfgPath); strcat(cfgPath, "config2.ini"); return (HGBASE_ERR_OK == HGBase_SetProfileInt(cfgPath, app.c_str(), key.c_str(), val)); } bool ManagerV2::SetCfgDoubleValue(const std::string& app, const std::string& key, double val) { HGChar cfgPath[256]; HGBase_GetConfigPath(cfgPath, 256); HGBase_CreateDir(cfgPath); strcat(cfgPath, "config2.ini"); char valStr[32]; sprintf(valStr, "%f", val); return (HGBASE_ERR_OK == HGBase_SetProfileString(cfgPath, app.c_str(), key.c_str(), valStr)); } bool ManagerV2::SetCfgBoolValue(const std::string& app, const std::string& key, bool val) { HGChar cfgPath[256]; HGBase_GetConfigPath(cfgPath, 256); HGBase_CreateDir(cfgPath); strcat(cfgPath, "config2.ini"); return (HGBASE_ERR_OK == HGBase_SetProfileInt(cfgPath, app.c_str(), key.c_str(), (HGInt)val)); } static int xferinfo(void* p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "ulnow=%lld, ultotal=%lld", ulnow, ultotal); return 0; } int ManagerV2::HttpUpload(const std::string& host, int port, const std::string& path, const std::string& filePath, const std::string& remoteFilePath) { int ret = -1; CURL* curl = curl_easy_init(); if (NULL != curl) { struct curl_httppost* formpost = NULL; struct curl_httppost* lastptr = NULL; curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "filename", CURLFORM_FILE, filePath.c_str(), CURLFORM_END); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "remote_filename", CURLFORM_COPYCONTENTS, remoteFilePath.c_str(), CURLFORM_END); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "submit", CURLFORM_COPYCONTENTS, "Submit", CURLFORM_END); char url[512]; sprintf(url, "http://%s:%d%s", host.c_str(), port, path.c_str()); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 2); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferinfo); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); /* Perform the request, res will get the return code */ CURLcode res = curl_easy_perform(curl); /* Check for errors */ if (res != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s", curl_easy_strerror(res)); else ret = 0; /* then cleanup the formpost chain */ curl_formfree(formpost); /* always cleanup */ curl_easy_cleanup(curl); } return ret; } static size_t read_callback(char* ptr, size_t size, size_t nmemb, void* stream) { unsigned long nread; /* in real-world cases, this would probably get this data differently as this fread() stuff is exactly what the library already would do by default internally */ size_t retcode = fread(ptr, size, nmemb, (FILE*)stream); if (retcode > 0) { nread = (unsigned long)retcode; //fprintf(stderr, "*** We read %lu bytes from file\n", nread); } return retcode; } int ManagerV2::FtpUpload(const std::string& user, const std::string& password, const std::string& host, int port, const std::string& filePath, const std::string& remoteFilePath) { FILE* file = fopen(filePath.c_str(), "rb"); if (NULL == file) { return -1; } int ret = -1; fseek(file, 0, SEEK_END); long fsize = ftell(file); fseek(file, 0, SEEK_SET); /* get a curl handle */ CURL* curl = curl_easy_init(); if (NULL != curl) { /* we want to use our own read function */ curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback); curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); char url[512]; if (!user.empty() && !password.empty()) { sprintf(url, "ftp://%s:%s@%s:%d%s", user.c_str(), password.c_str(), host.c_str(), port, remoteFilePath.c_str()); } else { sprintf(url, "ftp://%s:%d%s", host.c_str(), port, remoteFilePath.c_str()); } curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 2); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS, 1); /* now specify which file to upload */ curl_easy_setopt(curl, CURLOPT_READDATA, file); /* Set the size of the file to upload (optional). If you give a *_LARGE option you MUST make sure that the type of the passed-in argument is a curl_off_t. If you use CURLOPT_INFILESIZE (without _LARGE) you must make sure that to pass in a type 'long' argument. */ curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fsize); curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferinfo); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); /* Now run off and do what you have been told! */ CURLcode res = curl_easy_perform(curl); /* Check for errors */ if (res != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); else ret = 0; /* always cleanup */ curl_easy_cleanup(curl); } fclose(file); /* close the local file */ return ret; } std::string ManagerV2::GetFilePath(bool temp, const std::string& suffix) { HGChar savePath[256] = {0}; if (temp) HGBase_GetTmpPath(savePath, 256); else strcpy(savePath, m_globalCfg.fileSavePath.c_str()); HGBase_CreateDir(savePath); char filePath[256] = { 0 }; while (1) { if ("random" == m_globalCfg.fileNameMode) { HGChar uuid[256]; HGBase_GetUuid(uuid, 256); sprintf(filePath, "%s%s%s.%s", savePath, m_globalCfg.fileNamePrefix.c_str(), uuid, suffix.c_str()); } else if ("sn_date_time" == m_globalCfg.fileNameMode) { HGTimeInfo timeInfo; HGBase_GetLocalTime(&timeInfo); sprintf(filePath, "%s%s%s_%04d%02d%02d%02d%02d%02d%03d.%s", savePath, m_globalCfg.fileNamePrefix.c_str(), m_sn.c_str(), timeInfo.year, timeInfo.month, timeInfo.day, timeInfo.hour, timeInfo.minute, timeInfo.second, timeInfo.milliseconds, suffix.c_str()); } else { HGTimeInfo timeInfo; HGBase_GetLocalTime(&timeInfo); sprintf(filePath, "%s%s%04d%02d%02d%02d%02d%02d%03d.%s", savePath, m_globalCfg.fileNamePrefix.c_str(), timeInfo.year, timeInfo.month, timeInfo.day, timeInfo.hour, timeInfo.minute, timeInfo.second, timeInfo.milliseconds, suffix.c_str()); } #if defined(HG_CMP_MSC) DWORD attr = GetFileAttributesA(filePath); if (INVALID_FILE_ATTRIBUTES == attr) break; #else struct stat buf; int result = stat(filePath, &buf); if (0 != result) break; #endif } return filePath; } int ManagerV2::SaveImage(HGImage image, bool temp, std::string& imagePath) { assert(NULL != image); imagePath.clear(); bool ocr = false; std::string suffix = m_globalCfg.imageFormat; if ("ocr-pdf" == m_globalCfg.imageFormat) { suffix = "pdf"; ocr = true; } else if ("ocr-ofd" == m_globalCfg.imageFormat) { suffix = "ofd"; ocr = true; } std::string imagePath2 = GetFilePath(temp, suffix); int ret = -1; if (ocr) { HGOCRMgr ocrMgr = NULL; HGImgProc_CreateOCRMgr(0, &ocrMgr); if (NULL != ocrMgr) { if (HGBASE_ERR_OK == HGImgProc_ImageOCRToFile(ocrMgr, image, 0, imagePath2.c_str())) { ret = 0; } HGImgProc_DestroyOCRMgr(ocrMgr); } } else { HGImgFmtSaveInfo saveInfo; saveInfo.jpegQuality = m_globalCfg.imageJpegQuality; saveInfo.tiffJpegQuality = m_globalCfg.imageTiffJpegQuality; saveInfo.tiffCompression = HGIMGFMT_TIFFCOMP_LZW; if ("none" == m_globalCfg.imageTiffCompression) saveInfo.tiffCompression = HGIMGFMT_TIFFCOMP_NONE; else if ("jpeg" == m_globalCfg.imageTiffCompression) saveInfo.tiffCompression = HGIMGFMT_TIFFCOMP_JPEG; else if ("ccitt-g4" == m_globalCfg.imageTiffCompression) saveInfo.tiffCompression = HGIMGFMT_TIFFCOMP_CCITTFAX4; if (HGBASE_ERR_OK == HGImgFmt_SaveImage(image, 0, &saveInfo, imagePath2.c_str())) { ret = 0; } } if (0 == ret) imagePath = imagePath2; return ret; } void ManagerV2::LoadSaveFilePathList(std::list& savePathList) { savePathList.clear(); sqlite3_stmt* stmt = NULL; char sql[256]; sprintf(sql, "select * from save_filenames"); int ret = sqlite3_prepare(m_sqlite, sql, -1, &stmt, NULL); assert(0 == ret); ret = sqlite3_step(stmt); while (SQLITE_ROW == ret) { std::string fileName = (const char*)sqlite3_column_text(stmt, 0); #if defined(HG_CMP_MSC) DWORD attr = GetFileAttributesA(fileName.c_str()); if (INVALID_FILE_ATTRIBUTES != attr && 0 == (FILE_ATTRIBUTE_DIRECTORY & attr)) savePathList.push_back(fileName); #else struct stat buf; int result = stat(fileName.c_str(), &buf); if (0 == result && 0 == (S_IFDIR & buf.st_mode)) savePathList.push_back(fileName); #endif ret = sqlite3_step(stmt); } ret = sqlite3_finalize(stmt); assert(0 == ret); } void ManagerV2::RestoreSaveFilePathList(const std::list& savePathList) { int ret = sqlite3_exec(m_sqlite, "begin", NULL, NULL, NULL); assert(0 == ret); ret = sqlite3_exec(m_sqlite, "delete from save_filenames", NULL, NULL, NULL); if (0 != ret) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); return; } std::list::const_iterator iter; for (iter = savePathList.begin(); iter != savePathList.end(); ++iter) { char sql[1024]; sprintf(sql, "insert into save_filenames values ('%s')", StdStringToUtf8(*iter).c_str()); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); return; } } ret = sqlite3_exec(m_sqlite, "commit", NULL, NULL, NULL); assert(0 == ret); } void ManagerV2::LoadDeviceParams(const std::string& devName, std::vector& devParams) { assert(!devName.empty()); devParams.clear(); sqlite3_stmt* stmt = NULL; char sql[256]; sprintf(sql, "select * from device_params_2"); int ret = sqlite3_prepare(m_sqlite, sql, -1, &stmt, NULL); assert(0 == ret); ret = sqlite3_step(stmt); while (SQLITE_ROW == ret) { std::string name = (const char*)sqlite3_column_text(stmt, 0); std::string title = (const char*)sqlite3_column_text(stmt, 1); std::string valueType = (const char*)sqlite3_column_text(stmt, 2); std::string value = (const char*)sqlite3_column_text(stmt, 3); DeviceParam devParam; devParam.name = name; devParam.title = title; if ("string" == valueType) devParam.stringValue = value; else if ("int" == valueType) devParam.intValue = atoi(value.c_str()); else if ("double" == valueType) devParam.doubleValue = atof(value.c_str()); else if ("bool" == valueType) devParam.boolValue = (bool)atoi(value.c_str()); devParams.push_back(devParam); ret = sqlite3_step(stmt); } ret = sqlite3_finalize(stmt); assert(0 == ret); } void ManagerV2::RestoreDeviceParams(const std::string& devName, const std::vector& devParams) { assert(!devName.empty()); int ret = sqlite3_exec(m_sqlite, "begin", NULL, NULL, NULL); assert(0 == ret); ret = sqlite3_exec(m_sqlite, "delete from device_params_2", NULL, NULL, NULL); if (0 != ret) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); return; } for (int i = 0; i < (int)devParams.size(); ++i) { for (int j = 0; j < (int)devParams[i].devParams.size(); ++j) { const DeviceParam& devParam = devParams[i].devParams[j]; char sql[1024]; if (1 == devParam.valueType) sprintf(sql, "insert into device_params_2 values ('%s', '%s', '%s', '%s')", devParam.name.c_str(), devParam.title.c_str(), "string", devParam.stringValue.c_str()); else if (2 == devParam.valueType) sprintf(sql, "insert into device_params_2 values ('%s', '%s', '%s', '%d')", devParam.name.c_str(), devParam.title.c_str(), "int", devParam.intValue); else if (3 == devParam.valueType) sprintf(sql, "insert into device_params_2 values ('%s', '%s', '%s', '%f')", devParam.name.c_str(), devParam.title.c_str(), "double", devParam.doubleValue); else if (4 == devParam.valueType) sprintf(sql, "insert into device_params_2 values ('%s', '%s', '%s', '%d')", devParam.name.c_str(), devParam.title.c_str(), "bool", (int)devParam.boolValue); ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL); if (0 != ret) { ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL); assert(0 == ret); return; } } } ret = sqlite3_exec(m_sqlite, "commit", NULL, NULL, NULL); assert(0 == ret); } int ManagerV2::SetParamsToDevice(SANE_Handle hdev, const std::vector& devParams) { assert(NULL != hdev); if (devParams.empty()) return -1; int ret = 0; for (int i = 0; i < (int)devParams.size(); ++i) { bool find = false; SANE_Int num_dev_options = 0; sane_control_option(hdev, 0, SANE_ACTION_GET_VALUE, &num_dev_options, NULL); for (int j = 1; j < num_dev_options; ++j) { const SANE_Option_Descriptor* desp = sane_get_option_descriptor(hdev, j); if (NULL == desp) continue; const char* name = desp->name; while (' ' == *name) ++name; const char* title = desp->title; while (' ' == *title) ++title; if (0 == strcmp(devParams[i].name.c_str(), name) || 0 == strcmp(devParams[i].title.c_str(), title)) { if (SANE_TYPE_STRING == desp->type) { if (SANE_STATUS_GOOD != sane_control_option(hdev, j, SANE_ACTION_SET_VALUE, (void*)devParams[i].stringValue.c_str(), NULL)) ret = -1; } else if (SANE_TYPE_INT == desp->type) { SANE_Int value = devParams[i].intValue; if (SANE_STATUS_GOOD != sane_control_option(hdev, j, SANE_ACTION_SET_VALUE, &value, NULL)) ret = -1; } else if (SANE_TYPE_FIXED == desp->type) { SANE_Fixed value = SANE_FIX(devParams[i].doubleValue); if (SANE_STATUS_GOOD != sane_control_option(hdev, j, SANE_ACTION_SET_VALUE, &value, NULL)) ret = -1; } else if (SANE_TYPE_BOOL == desp->type) { SANE_Bool value = (SANE_Bool)devParams[i].boolValue; if (SANE_STATUS_GOOD != sane_control_option(hdev, j, SANE_ACTION_SET_VALUE, &value, NULL)) ret = -1; } find = true; break; } } if (!find) ret = -1; } return ret; } int ManagerV2::GetParamsFromDevice(SANE_Handle hdev, std::vector& devParams) { assert(NULL != hdev); devParams.clear(); SANE_Int num_dev_options = 0; sane_control_option(hdev, 0, SANE_ACTION_GET_VALUE, &num_dev_options, NULL); for (int i = 1; i < num_dev_options; ++i) { const SANE_Option_Descriptor* desp = sane_get_option_descriptor(hdev, i); if (NULL == desp) continue; const char* name = desp->name; while (' ' == *name) ++name; const char* title = desp->title; while (' ' == *title) ++title; //HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "device config, title=%s", Utf8ToStdString(title).c_str()); if (SANE_TYPE_GROUP == desp->type) { DeviceParamsGroup group; group.groupTitle = title; devParams.push_back(group); } else if (SANE_TYPE_STRING == desp->type) { char value[256] = { 0 }; sane_control_option(hdev, i, SANE_ACTION_GET_VALUE, value, NULL); DeviceParam devParam; devParam.name = name; devParam.title = title; devParam.valueType = 1; devParam.stringValue = value; devParam.rangeType = 1; if (SANE_CONSTRAINT_STRING_LIST == desp->constraint_type) { const SANE_String_Const* p = desp->constraint.string_list; while (NULL != *p) { devParam.stringValueList.push_back(*p); ++p; } assert(!devParams.empty()); devParams[devParams.size() - 1].devParams.push_back(devParam); } } else if (SANE_TYPE_INT == desp->type) { SANE_Int value = 0; sane_control_option(hdev, i, SANE_ACTION_GET_VALUE, &value, NULL); DeviceParam devParam; devParam.name = name; devParam.title = title; devParam.valueType = 2; devParam.intValue = (int)value; if (SANE_CONSTRAINT_WORD_LIST == desp->constraint_type) { devParam.rangeType = 2; const SANE_Word* p = desp->constraint.word_list; for (SANE_Int i = 0; i < p[0]; ++i) { devParam.intValueList.push_back(p[i + 1]); } } else if (SANE_CONSTRAINT_RANGE == desp->constraint_type) { devParam.rangeType = 4; devParam.intValueMin = desp->constraint.range->min; devParam.intValueMax = desp->constraint.range->max; } assert(!devParams.empty()); devParams[devParams.size() - 1].devParams.push_back(devParam); } else if (SANE_TYPE_FIXED == desp->type) { SANE_Word value = 0; sane_control_option(hdev, i, SANE_ACTION_GET_VALUE, &value, NULL); DeviceParam devParam; devParam.name = name; devParam.title = title; devParam.valueType = 3; devParam.doubleValue = SANE_UNFIX(value); if (SANE_CONSTRAINT_WORD_LIST == desp->constraint_type) { devParam.rangeType = 3; const SANE_Word* p = desp->constraint.word_list; for (SANE_Int i = 0; i < p[0]; ++i) { devParam.doubleValueList.push_back(SANE_UNFIX(p[i + 1])); } } else if (SANE_CONSTRAINT_RANGE == desp->constraint_type) { devParam.rangeType = 5; devParam.doubleValueMin = SANE_UNFIX(desp->constraint.range->min); devParam.doubleValueMax = SANE_UNFIX(desp->constraint.range->max); } assert(!devParams.empty()); devParams[devParams.size() - 1].devParams.push_back(devParam); } else if (SANE_TYPE_BOOL == desp->type) { SANE_Bool value = 0; sane_control_option(hdev, i, SANE_ACTION_GET_VALUE, &value, NULL); DeviceParam devParam; devParam.name = name; devParam.title = title; devParam.valueType = 4; devParam.boolValue = (bool)value; assert(!devParams.empty()); devParams[devParams.size() - 1].devParams.push_back(devParam); } } return 0; } int ManagerV2::ResetParamsToDevice(SANE_Handle hdev) { assert(NULL != hdev); int ret = -1; SANE_Int num_dev_options = 0; sane_control_option(hdev, 0, SANE_ACTION_GET_VALUE, &num_dev_options, NULL); for (int i = 1; i < num_dev_options; ++i) { const SANE_Option_Descriptor* desp = sane_get_option_descriptor(hdev, i); if (NULL == desp) continue; const char* name = desp->name; while (' ' == *name) ++name; if (0 == strcmp(SANE_STD_OPT_NAME_RESTORE, name) && SANE_TYPE_BUTTON == desp->type) { if (SANE_STATUS_GOOD == sane_control_option(hdev, i, SANE_ACTION_SET_VALUE, NULL, NULL)) ret = 0; break; } } return ret; } HGByte* ManagerV2::LoadImageFromPath(const std::string& imagePath, HGUInt& size, std::string& format) { size = 0; format.clear(); HGUInt imgType = 0; HGImgFmt_GetImgFmtType(imagePath.c_str(), &imgType); if (0 == imgType) return NULL; std::string imgFormat; if (HGIMGFMT_TYPE_JPEG == imgType) imgFormat = "jpg"; else if (HGIMGFMT_TYPE_BMP == imgType) imgFormat = "bmp"; else if (HGIMGFMT_TYPE_PNG == imgType) imgFormat = "png"; else if (HGIMGFMT_TYPE_TIFF == imgType) imgFormat = "tif"; else if (HGIMGFMT_TYPE_PDF == imgType) imgFormat = "pdf"; else if (HGIMGFMT_TYPE_OFD == imgType) imgFormat = "ofd"; if (imgFormat.empty()) return NULL; HGByte* imgData = NULL; HGUInt imgSize = 0; FILE* file = fopen(imagePath.c_str(), "rb"); if (NULL != file) { fseek(file, 0, SEEK_END); imgSize = ftell(file); fseek(file, 0, SEEK_SET); if (imgSize > 0) { imgData = new HGByte[imgSize]; HGUInt readLen = (HGUInt)fread(imgData, 1, imgSize, file); if (readLen != imgSize) { delete[] imgData; imgData = NULL; imgSize = 0; } } fclose(file); } if (NULL == imgData) return NULL; size = imgSize; format = imgFormat; return imgData; } HGByte* ManagerV2::LoadImageFromBase64(const std::string& imageBase64, HGUInt& size, std::string& format) { size = 0; format.clear(); size_t pos = imageBase64.find(','); if (std::string::npos == pos) return NULL; std::string imgFormat; std::string prefix = imageBase64.substr(0, pos + 1); if ("data:image/jpeg;base64," == prefix) imgFormat = "jpg"; else if ("data:image/bmp;base64," == prefix) imgFormat = "bmp"; else if ("data:image/png;base64," == prefix) imgFormat = "png"; else if ("data:image/tiff;base64," == prefix) imgFormat = "tif"; else if ("data:image/pdf;base64," == prefix) imgFormat = "pdf"; else if ("data:image/ofd;base64," == prefix) imgFormat = "ofd"; if (imgFormat.empty()) return NULL; HGByte* imgData = NULL; HGSize imgSize = 0; const HGChar* base64Data = imageBase64.c_str() + pos + 1; HGSize base64Size = (HGSize)strlen(base64Data); HGBase_Base64Decode((const HGByte*)base64Data, (HGSize)base64Size, NULL, &imgSize); if (0 != imgSize) { imgData = new HGByte[imgSize]; HGBase_Base64Decode((const HGByte*)base64Data, (HGSize)base64Size, imgData, &imgSize); } if (NULL == imgData) return NULL; size = (HGUInt)imgSize; format = imgFormat; return imgData; } HGByte* ManagerV2::LoadThumbFromPath(const std::string& imagePath, HGUInt& size) { size = 0; HGUInt imgType = 0; HGImgFmt_GetImgFmtType(imagePath.c_str(), &imgType); if (0 == imgType) return NULL; HGImage img = NULL; HGImgFmt_LoadImage(imagePath.c_str(), imgType, NULL, 0, HGBASE_IMGORIGIN_TOP, &img); if (NULL == img) return NULL; HGImageInfo imgInfo; HGBase_GetImageInfo(img, &imgInfo); HGUInt width = imgInfo.width; HGUInt height = imgInfo.height; if (width >= height) { if (width > 240) { width = 240; height = HGMAX((HGUInt)(240.0 * imgInfo.height / imgInfo.width + 0.5), 1); } } else { if (height > 240) { height = 240; width = HGMAX((HGUInt)(240.0 * imgInfo.width / imgInfo.height + 0.5), 1); } } HGImage img2 = NULL; HGBase_CreateImage(width, height, imgInfo.type, HGBASE_IMGORIGIN_TOP, &img2); if (NULL == img2) { HGBase_DestroyImage(img); return NULL; } HGImgProc_ResizeImage(img, img2, HGIMGPROC_INTERPOTYPE_NN); HGBase_DestroyImage(img); HGChar tmpName[256]; HGBase_GetTmpFileName(NULL, tmpName, 256); HGResult ret = HGImgFmt_SaveImage(img2, imgType, NULL, tmpName); HGBase_DestroyImage(img2); if (HGBASE_ERR_OK != ret) { return NULL; } HGByte* imgData = NULL; HGUInt imgSize = 0; FILE* file = fopen(tmpName, "rb"); if (NULL != file) { fseek(file, 0, SEEK_END); imgSize = ftell(file); fseek(file, 0, SEEK_SET); if (imgSize > 0) { imgData = new HGByte[imgSize]; HGUInt readLen = (HGUInt)fread(imgData, 1, imgSize, file); if (readLen != imgSize) { delete[] imgData; imgData = NULL; imgSize = 0; } } fclose(file); } HGBase_DeleteFile(tmpName); if (NULL == imgData) return NULL; size = imgSize; return imgData; } HGByte* ManagerV2::LoadThumbFromBase64(const std::string& imageBase64, HGUInt& size) { size = 0; size_t pos = imageBase64.find(','); if (std::string::npos == pos) return NULL; HGChar tmpName[256]; HGBase_GetTmpFileName(NULL, tmpName, 256); if (0 != SaveBase64(imageBase64.c_str() + pos + 1, tmpName)) return NULL; HGByte* data = LoadThumbFromPath(tmpName, size); HGBase_DeleteFile(tmpName); return data; } bool ManagerV2::SaveToBase64(const HGByte* data, HGUInt size, std::string& base64) { assert(NULL != data && 0 != size); base64.clear(); HGSize base64Size = 0; HGBase_Base64Encode(data, size, NULL, &base64Size); uint8_t* p = new uint8_t[base64Size + 1]; HGBase_Base64Encode(data, size, p, &base64Size); p[base64Size] = 0; base64 = (const char*)p; delete[] p; return true; } bool ManagerV2::SaveToFile(const HGByte* data, HGUInt size, const std::string& filePath) { assert(NULL != data && 0 != size); bool ret = false; FILE* file = fopen(filePath.c_str(), "wb"); if (NULL != file) { size_t writeLen = fwrite(data, 1, size, file); if (writeLen == (size_t)size) ret = true; fclose(file); } else { HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "ManagerV2::SaveToFile Create File Fail %s", filePath.c_str()); } if (!ret) HGBase_DeleteFile(filePath.c_str()); return ret; } int ManagerV2::GetId(int idx) { int id = -1; char sql[1024]; sprintf(sql, "select id from 'table_%s_idx' where idx = '%d'", m_currBatchId.c_str(), idx); sqlite3_stmt* stmt = NULL; int ret = sqlite3_prepare(m_sqlite, sql, -1, &stmt, NULL); assert(0 == ret); ret = sqlite3_step(stmt); if (SQLITE_ROW == ret) id = sqlite3_column_int(stmt, 0); ret = sqlite3_finalize(stmt); assert(0 == ret); return id; } void ManagerV2::GetBatchTableInfo(std::vector& tables) { tables.clear(); sqlite3_stmt* stmt = NULL; char sql[256]; sprintf(sql, "select table_%s.id, table_%s.format from table_%s join table_%s_idx on table_%s.id == table_%s_idx.id order by table_%s_idx.idx asc", m_currBatchId.c_str(), m_currBatchId.c_str(), m_currBatchId.c_str(), m_currBatchId.c_str(), m_currBatchId.c_str(), m_currBatchId.c_str(), m_currBatchId.c_str()); int ret = sqlite3_prepare(m_sqlite, sql, -1, &stmt, NULL); assert(0 == ret); ret = sqlite3_step(stmt); while (SQLITE_ROW == ret) { BatchTableInfo info; info.id = sqlite3_column_int(stmt, 0); info.format = (const char *)sqlite3_column_text(stmt, 1); tables.push_back(info); ret = sqlite3_step(stmt); } ret = sqlite3_finalize(stmt); assert(0 == ret); } void ManagerV2::ClearBindFolder() { assert(!m_bindFolder.empty()); #if defined(HG_CMP_MSC) char szFind[MAX_PATH]; sprintf(szFind, "%s*.*", m_bindFolder.c_str()); WIN32_FIND_DATAA FindFileData; HANDLE hFind = FindFirstFileA(szFind, &FindFileData); if (INVALID_HANDLE_VALUE == hFind) return; do { if (0 == (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { char fileName[MAX_PATH]; sprintf(fileName, "%s%s", m_bindFolder.c_str(), FindFileData.cFileName); HGBase_DeleteFile(fileName); } } while (FindNextFileA(hFind, &FindFileData)); FindClose(hFind); #else DIR* dir = opendir(m_bindFolder.c_str()); if (NULL != dir) { struct dirent* dire = NULL; while (dire = readdir(dir)) { char fileName[256]; sprintf(fileName, "%s%s", m_bindFolder.c_str(), dire->d_name); struct stat filebuf; lstat(fileName, &filebuf); if (!S_ISDIR(filebuf.st_mode)) { HGBase_DeleteFile(fileName); } } closedir(dir); } #endif } void ManagerV2::UpdateBindFolder() { assert(!m_bindFolder.empty()); if (NULL == m_sqlite) return; sqlite3_stmt* stmt = NULL; char sql[1024]; sprintf(sql, "select table_%s_idx.idx, table_%s.format, table_%s.image from table_%s join table_%s_idx on table_%s.id == table_%s_idx.id", m_currBatchId.c_str(), m_currBatchId.c_str(), m_currBatchId.c_str(), m_currBatchId.c_str(), m_currBatchId.c_str(), m_currBatchId.c_str(), m_currBatchId.c_str()); int ret = sqlite3_prepare(m_sqlite, sql, -1, &stmt, NULL); assert(0 == ret); ret = sqlite3_step(stmt); while (SQLITE_ROW == ret) { int idx = sqlite3_column_int(stmt, 0); std::string imgFmt = (const char*)sqlite3_column_text(stmt, 1); const void* imgData = sqlite3_column_blob(stmt, 2); int imgSize = sqlite3_column_bytes(stmt, 2); char fmt[24]; sprintf(fmt, "%%s%%0%dd.%%s", m_bindNameWidth); char imagePath[256]; sprintf(imagePath, fmt, m_bindFolder.c_str(), m_bindNameBase + idx, imgFmt.c_str()); HGBase_CreateDir(m_bindFolder.c_str()); SaveToFile((const HGByte*)imgData, imgSize, imagePath); ret = sqlite3_step(stmt); } ret = sqlite3_finalize(stmt); assert(0 == ret); } void ManagerV2::InsertBindFolderImage(const std::vector& tables, int insertPos, const std::string imgFmt, const HGByte* imgData, HGUInt imgSize) { assert(!m_bindFolder.empty()); char fmt[24]; sprintf(fmt, "%%s%%0%dd.%%s", m_bindNameWidth); for (int i = (int)tables.size() - 1; i >= 0; --i) { if (i >= insertPos) { char fileName[256]; sprintf(fileName, fmt, m_bindFolder.c_str(), m_bindNameBase + i, tables[i].format.c_str()); char destName[256]; sprintf(destName, fmt, m_bindFolder.c_str(), m_bindNameBase + i + 1, tables[i].format.c_str()); #if defined(HG_CMP_MSC) MoveFileA(fileName, destName); #else rename(fileName, destName); #endif } } char fileName[256]; sprintf(fileName, fmt, m_bindFolder.c_str(), m_bindNameBase + insertPos, imgFmt.c_str()); SaveToFile(imgData, imgSize, fileName); } void ManagerV2::ModifyBindFolderImage(const std::vector& tables, int imageIndex, const std::string imgFmt, const HGByte* imgData, HGUInt imgSize) { assert(!m_bindFolder.empty()); char fmt[24]; sprintf(fmt, "%%s%%0%dd.%%s", m_bindNameWidth); std::string oldFormat = tables[imageIndex].format; char oldFileName[256]; sprintf(oldFileName, fmt, m_bindFolder.c_str(), m_bindNameBase + imageIndex, oldFormat.c_str()); HGBase_DeleteFile(oldFileName); char fileName[256]; sprintf(fileName, fmt, m_bindFolder.c_str(), m_bindNameBase + imageIndex, imgFmt.c_str()); SaveToFile(imgData, imgSize, fileName); } void ManagerV2::DeleteBindFolderImage(const std::vector& tables, const std::vector& imageIndexList) { assert(!m_bindFolder.empty()); char fmt[24]; sprintf(fmt, "%%s%%0%dd.%%s", m_bindNameWidth); for (int i = 0; i < (int)imageIndexList.size(); ++i) { int idx = imageIndexList[i]; char fileName[256]; sprintf(fileName, fmt, m_bindFolder.c_str(), m_bindNameBase + idx, tables[idx].format.c_str()); HGBase_DeleteFile(fileName); } int value = 0; for (int i = 0; i < (int)tables.size(); ++i) { bool find = false; for (int j = 0; j < (int)imageIndexList.size(); ++j) { if (i == imageIndexList[j]) { find = true; break; } } if (find) { ++value; } else { if (value > 0) { char fileName[256]; sprintf(fileName, fmt, m_bindFolder.c_str(), m_bindNameBase + i, tables[i].format.c_str()); char destName[256]; sprintf(destName, fmt, m_bindFolder.c_str(), m_bindNameBase + i - value, tables[i].format.c_str()); #if defined(HG_CMP_MSC) MoveFileA(fileName, destName); #else rename(fileName, destName); #endif } } } } void ManagerV2::ExchangeBindFolderImage(const std::vector& tables, int imageIndex1, int imageIndex2) { assert(!m_bindFolder.empty()); char fmt[24]; sprintf(fmt, "%%s%%0%dd.%%s", m_bindNameWidth); std::string format1 = tables[imageIndex1].format; std::string format2 = tables[imageIndex2].format; char fileName1[256]; sprintf(fileName1, fmt, m_bindFolder.c_str(), m_bindNameBase + imageIndex1, format1.c_str()); char TmpFileName[256]; sprintf(TmpFileName, "%sTemp", m_bindFolder.c_str()); #if defined(HG_CMP_MSC) MoveFileA(fileName1, TmpFileName); #else rename(fileName1, TmpFileName); #endif char fileName2[256]; sprintf(fileName2, fmt, m_bindFolder.c_str(), m_bindNameBase + imageIndex2, format2.c_str()); char fileName2Dest[256]; sprintf(fileName2Dest, fmt, m_bindFolder.c_str(), m_bindNameBase + imageIndex1, format2.c_str()); #if defined(HG_CMP_MSC) MoveFileA(fileName2, fileName2Dest); #else rename(fileName2, fileName2Dest); #endif char fileName1Dest[256]; sprintf(fileName1Dest, fmt, m_bindFolder.c_str(), m_bindNameBase + imageIndex2, format1.c_str()); #if defined(HG_CMP_MSC) MoveFileA(TmpFileName, fileName1Dest); #else rename(TmpFileName, fileName1Dest); #endif } void ManagerV2::ClearBindFolderImageList(const std::vector& tables) { assert(!m_bindFolder.empty()); char fmt[24]; sprintf(fmt, "%%s%%0%dd.%%s", m_bindNameWidth); for (int i = 0; i < (int)tables.size(); ++i) { char fileName[256]; sprintf(fileName, fmt, m_bindFolder.c_str(), m_bindNameBase + i, tables[i].format.c_str()); HGBase_DeleteFile(fileName); } } HGUInt ManagerV2::GetDpi() { HGUInt dpi = 200; SANE_Int num_dev_options = 0; sane_control_option(m_devHandle, 0, SANE_ACTION_GET_VALUE, &num_dev_options, nullptr); for (int i = 1; i < num_dev_options; ++i) { const SANE_Option_Descriptor* desp = sane_get_option_descriptor(m_devHandle, i); if (nullptr == desp) continue; if (SANE_TYPE_INT == desp->type) { SANE_Int value = 0; sane_control_option(m_devHandle, i, SANE_ACTION_GET_VALUE, &value, nullptr); if (0 == strcmp(desp->name, SANE_STD_OPT_NAME_RESOLUTION)) { dpi = (HGUInt)value; } } } return dpi; } int ManagerV2::sane_ex_callback(SANE_Handle hdev, int code, void* data, unsigned int* len, void* param) { (void)hdev; (void)len; ManagerV2* p = (ManagerV2*)param; switch (code) { case SANE_EVENT_DEVICE_ARRIVED: { SANE_Device* sane_dev = (SANE_Device*)data; HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_DEVICE_ARRIVED, name=%s", Utf8ToStdString(sane_dev->name).c_str()); HGBase_EnterLock(p->m_lock); p->m_devNameList.push_back(sane_dev->name); std::list::iterator iter; for (iter = p->m_user.begin(); iter != p->m_user.end(); ++iter) { WSUser::SaneEvent(SANEEVENT_ARRIVE, sane_dev->name, false, *iter); } HGBase_LeaveLock(p->m_lock); } break; case SANE_EVENT_DEVICE_LEFT: { SANE_Device* sane_dev = (SANE_Device*)data; HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_DEVICE_LEFT, name=%s", Utf8ToStdString(sane_dev->name).c_str()); CloseDevParam* closeDevParam = new CloseDevParam; closeDevParam->mgr = p; closeDevParam->devName = sane_dev->name; HGMsg msg; msg.id = MSGID_CLOSE_DEVICE; msg.data = closeDevParam; if (HGBASE_ERR_OK != HGBase_PostPumpMessage(p->m_msgPump, &msg)) { delete closeDevParam; } HGBase_EnterLock(p->m_lock); for (int i = 0; i < (int)p->m_devNameList.size(); ++i) { if (0 == strcmp(sane_dev->name, p->m_devNameList[i].c_str())) { p->m_devNameList.erase(p->m_devNameList.begin() + i); break; } } std::list::iterator iter; for (iter = p->m_user.begin(); iter != p->m_user.end(); ++iter) { WSUser::SaneEvent(SANEEVENT_REMOVE, sane_dev->name, false, *iter); } HGBase_LeaveLock(p->m_lock); } break; case SANE_EVENT_WORKING: { HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_WORKING, msg=%s", Utf8ToStdString((char*)data).c_str()); HGBase_EnterLock(p->m_lock); std::list::iterator iter; for (iter = p->m_user.begin(); iter != p->m_user.end(); ++iter) { WSUser::SaneEvent(SANEEVENT_WORKING, (const char*)data, false, *iter); } HGBase_LeaveLock(p->m_lock); } break; case SANE_EVENT_SCAN_FINISHED: { HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_SCAN_FINISHED, msg=%s", Utf8ToStdString((char*)data).c_str()); HGBase_SetEvent(p->m_scanEvent); ScanFinishParam* scanFinishParam = new ScanFinishParam; scanFinishParam->mgr = p; HGMsg msg; msg.id = MSGID_SCAN_FINISH; msg.data = scanFinishParam; if (HGBASE_ERR_OK != HGBase_PostPumpMessage(p->m_msgPump, &msg)) { delete scanFinishParam; } HGBase_EnterLock(p->m_lock); std::list::iterator iter; for (iter = p->m_user.begin(); iter != p->m_user.end(); ++iter) { WSUser::SaneEvent(SANEEVENT_FINISH, (const char*)data, (0 != *len), *iter); } HGBase_LeaveLock(p->m_lock); } break; case SANE_EVENT_STATUS: { HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_STATUS, msg=%s", Utf8ToStdString((char*)data).c_str()); HGBase_EnterLock(p->m_lock); std::list::iterator iter; for (iter = p->m_user.begin(); iter != p->m_user.end(); ++iter) { WSUser::SaneEvent(SANEEVENT_STATUS, (const char*)data, false, *iter); } HGBase_LeaveLock(p->m_lock); } break; case SANE_EVENT_ERROR: { HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_ERROR, msg=%s", Utf8ToStdString((char*)data).c_str()); HGBase_EnterLock(p->m_lock); std::list::iterator iter; for (iter = p->m_user.begin(); iter != p->m_user.end(); ++iter) { WSUser::SaneEvent(SANEEVENT_ERROR, (const char*)data, (0 != *len), *iter); } HGBase_LeaveLock(p->m_lock); } break; case SANE_EVENT_IMAGE_OK: { HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_IMAGE_OK"); SANE_Image* sane_img = (SANE_Image*)data; HGUInt imgType = 0; if (sane_img->header.format == SANE_FRAME_GRAY) { if (1 == sane_img->header.depth) imgType = HGBASE_IMGTYPE_BINARY; else if (8 == sane_img->header.depth) imgType = HGBASE_IMGTYPE_GRAY; } else if (sane_img->header.format == SANE_FRAME_RGB) imgType = HGBASE_IMGTYPE_RGB; HGByte* data = sane_img->data; HGImageInfo imgInfo = { (HGUInt)sane_img->header.pixels_per_line, (HGUInt)sane_img->header.lines, imgType, (HGUInt)sane_img->header.bytes_per_line, HGBASE_IMGORIGIN_TOP }; HGImage img = NULL; HGBase_CreateImageFromData(data, &imgInfo, NULL, 0, HGBASE_IMGORIGIN_TOP, &img); if (NULL != img) { HGBase_SetImageDpi(img, p->m_dpi, p->m_dpi); HGBool blank = HGFALSE; if (p->m_scanBlankCheck) HGImgProc_ImageBlankCheck(img, NULL, &blank); HGBase_EnterLock(p->m_lock); std::string imagePath; int ret = p->SaveImage(img, p->m_scanTemp, imagePath); if (0 == ret) { if (!p->m_scanTemp) { AddSavedFileParam* addParam = new AddSavedFileParam; addParam->mgr = p; addParam->fileName = imagePath; HGMsg msg; msg.id = MSGID_ADD_SAVEDFILE; msg.data = addParam; if (HGBASE_ERR_OK != HGBase_PostPumpMessage(p->m_msgPump, &msg)) { delete addParam; } } std::list::iterator iter; for (iter = p->m_user.begin(); iter != p->m_user.end(); ++iter) { WSUser::SaneImageCallback(imagePath.c_str(), blank ? true : false, *iter); } } HGBase_LeaveLock(p->m_lock); HGBase_DestroyImage(img); } } break; } return 0; } void HGAPI ManagerV2::ThreadFunc(HGThread thread, HGPointer param) { ManagerV2 *p = (ManagerV2 *)param; while (!p->m_stopThread) { HGBase_EnterLock(p->m_lock); HGUInt timeout = p->m_timeout; HGBase_LeaveLock(p->m_lock); HGResult ret = HGBase_WaitEventTimeout(p->m_event, timeout); if (HGBASE_ERR_TIMEOUT == ret) { HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "timeout, deinit device"); DeinitDevParam* deinitDevParam = new DeinitDevParam; deinitDevParam->mgr = p; HGMsg msg; msg.id = MSGID_DEINIT_DEVICE; msg.data = deinitDevParam; if (HGBASE_ERR_OK != HGBase_PostPumpMessage(p->m_msgPump, &msg)) { delete deinitDevParam; } } } } }