From d8e82950ab4965341d6e80157dc58601d17000b2 Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Tue, 28 Jun 2022 17:17:10 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=96=87=E4=BB=B6=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E8=BD=AC=E6=8D=A2=E5=8F=8A=E4=BC=A0=E8=BE=93=E6=96=B9?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- device/scanner.vcxproj | 6 +- device/scanner.vcxproj.filters | 6 ++ sane/s2t_api.h | 2 + sane/scanned_img.cpp | 23 +++++- sane/scanner.cpp | 10 +++ sane/scanner.h | 2 + twain/twain.vcxproj | 8 ++ twain/twain.vcxproj.filters | 3 + twain/twain/huagaods.cpp | 138 +++++++++++++++++++++------------ twain/twain/huagaods.hpp | 2 + 10 files changed, 146 insertions(+), 54 deletions(-) diff --git a/device/scanner.vcxproj b/device/scanner.vcxproj index 217a3cb..aea1703 100644 --- a/device/scanner.vcxproj +++ b/device/scanner.vcxproj @@ -72,14 +72,14 @@ true - $(SolutionDir)..\..\code_device\hgdriver\3rdparty\nick;$(SolutionDir)..\..\code_device\hgdriver\3rdparty\opencv\include\win;$(SolutionDir)..\..\code_device\hgdriver\3rdparty\cyusb\inc\;$(SolutionDir)..\..\code_device\hgdriver\3rdparty\libtiff\include\;$(SolutionDir)..\..\code_device\hgdriver\3rdparty\log4cplus\include\;$(SolutionDir)..\..\code_device\sdk\;$(SolutionDir)..\..\code_device\hgdriver\ImageProcess\;$(SolutionDir)..\..\sdk\include\;$(SolutionDir)..\..\code_device\hgdriver\hgdev\;$(SolutionDir)..\..\code_device\hgdriver\wrapper\;$(ProjectDir);$(IncludePath) + $(SolutionDir)..\..\code_device\hgdriver\3rdparty\nick;$(SolutionDir)..\..\code_device\hgdriver\3rdparty\opencv\include\win;$(SolutionDir)..\..\code_device\hgdriver\3rdparty\cyusb\inc\;$(SolutionDir)..\..\code_device\hgdriver\3rdparty\libtiff\include\;$(SolutionDir)..\..\code_device\hgdriver\3rdparty\log4cplus\include\;$(SolutionDir)..\..\code_device\sdk\;$(SolutionDir)..\..\code_device\hgdriver\ImageProcess\;$(SolutionDir)..\..\sdk\include\;$(SolutionDir)..\..\code_device\hgdriver\hgdev\;$(SolutionDir)..\..\code_device\hgdriver\wrapper\;$(ProjectDir);$(SolutionDir)..\..\code_device\hgdriver\3rdparty\tiff\include\;$(IncludePath) $(ProjectDir)lib\$(PlatformTarget)\$(Configuration);$(ProjectDir)..\..\sdk\lib\win\$(PlatformTarget)\$(Configuration);$(LibraryPath) $(SolutionDir)..\..\tmp\$(PlatformTarget)\$(Configuration)\$(ProjectName)\ $(SolutionDir)..\..\release\win\$(PlatformTarget)\$(Configuration)\ false - $(SolutionDir)..\..\code_device\hgdriver\3rdparty\nick;$(SolutionDir)..\..\code_device\hgdriver\3rdparty\opencv\include\win;$(SolutionDir)..\..\code_device\hgdriver\3rdparty\cyusb\inc\;$(SolutionDir)..\..\code_device\hgdriver\3rdparty\libtiff\include\;$(SolutionDir)..\..\code_device\hgdriver\3rdparty\log4cplus\include\;$(SolutionDir)..\..\code_device\sdk\;$(SolutionDir)..\..\code_device\hgdriver\ImageProcess\;$(SolutionDir)..\..\sdk\include\;$(SolutionDir)..\..\code_device\hgdriver\hgdev\;$(SolutionDir)..\..\code_device\hgdriver\wrapper\;$(ProjectDir);$(IncludePath) + $(SolutionDir)..\..\code_device\hgdriver\3rdparty\nick;$(SolutionDir)..\..\code_device\hgdriver\3rdparty\opencv\include\win;$(SolutionDir)..\..\code_device\hgdriver\3rdparty\cyusb\inc\;$(SolutionDir)..\..\code_device\hgdriver\3rdparty\libtiff\include\;$(SolutionDir)..\..\code_device\hgdriver\3rdparty\log4cplus\include\;$(SolutionDir)..\..\code_device\sdk\;$(SolutionDir)..\..\code_device\hgdriver\ImageProcess\;$(SolutionDir)..\..\sdk\include\;$(SolutionDir)..\..\code_device\hgdriver\hgdev\;$(SolutionDir)..\..\code_device\hgdriver\wrapper\;$(ProjectDir);$(SolutionDir)..\..\code_device\hgdriver\3rdparty\tiff\include\;$(IncludePath) $(ProjectDir)lib\$(PlatformTarget)\$(Configuration);$(ProjectDir)..\..\sdk\lib\win\$(PlatformTarget)\$(Configuration);$(LibraryPath) $(SolutionDir)..\..\tmp\$(PlatformTarget)\$(Configuration)\$(ProjectName)\ $(SolutionDir)..\..\release\win\$(PlatformTarget)\$(Configuration)\ @@ -218,6 +218,7 @@ move /Y "$(OutDirFullPath)$(ProjectName).pdb" "$(SolutionDir)..\..\sdk\lib\win\$ + @@ -277,6 +278,7 @@ move /Y "$(OutDirFullPath)$(ProjectName).pdb" "$(SolutionDir)..\..\sdk\lib\win\$ + diff --git a/device/scanner.vcxproj.filters b/device/scanner.vcxproj.filters index 7ffcac6..19a5f08 100644 --- a/device/scanner.vcxproj.filters +++ b/device/scanner.vcxproj.filters @@ -180,6 +180,9 @@ 源文件 + + image + @@ -386,6 +389,9 @@ 头文件 + + image + diff --git a/sane/s2t_api.h b/sane/s2t_api.h index d1d84df..7577258 100644 --- a/sane/s2t_api.h +++ b/sane/s2t_api.h @@ -169,6 +169,7 @@ __declspec(novtable) struct ISaneInvoker : public IRef COM_API_DECLARE(bool, get_value(int sn, set_opt_value, void* param)); COM_API_DECLARE(int, set_value(int sn, void* val)); + COM_API_DECLARE(int, convert_image(SANE_ImageFormatConvert* conv)); // SANE options ID ... SANE_OPTION_ID_API(is_multiout); // 多流输出 @@ -224,6 +225,7 @@ __declspec(novtable) struct ISaneInvoker : public IRef SANE_OPTION_ID_API(dogear_size); // 折角检测大小 SANE_OPTION_ID_API(is_check_skew); // 歪斜检测 SANE_OPTION_ID_API(skew_range); // 歪斜容忍度 + SANE_OPTION_ID_API(black_white_threshold); // 二值化图像阈值 // SANE-ex option ID: SANE_OPTION_ID_API_EX(multiout_type); // int diff --git a/sane/scanned_img.cpp b/sane/scanned_img.cpp index 3f2db92..487a594 100644 --- a/sane/scanned_img.cpp +++ b/sane/scanned_img.cpp @@ -454,6 +454,7 @@ std::string scanned_img::file_header(SANE_ImageType type, float resolution, twai if (type == SANE_IMAGE_TYPE_BMP && xfer != TWAIN_XFER_Memory) { BITMAPINFOHEADER bih = { 0 }; + int pal_size = 0; bih.biSize = sizeof(bih); bih.biWidth = width(); @@ -464,17 +465,37 @@ std::string scanned_img::file_header(SANE_ImageType type, float resolution, twai bih.biCompression = BI_RGB; bih.biXPelsPerMeter = bih.biYPelsPerMeter = resolution * 39.37f + .5f; + if (bih.biBitCount == 1) + pal_size = 2 * sizeof(int); + else if (bih.biBitCount == 8) + pal_size = 256 * sizeof(int); + if (xfer == TWAIN_XFER_File) { BITMAPFILEHEADER fh = { 0 }; fh.bfType = MAKEWORD('B', 'M'); fh.bfSize = sizeof(fh) + bih.biSizeImage + sizeof(bih); - fh.bfOffBits = sizeof(fh) + sizeof(bih); + fh.bfOffBits = sizeof(fh) + sizeof(bih) + pal_size; h = std::string((char*)&fh, sizeof(fh)); } h += std::string((char*)&bih, sizeof(bih)); + if (bih.biBitCount == 1) + { + int pal[] = { 0, 0x0ffffff }; + h += std::string((char*)pal, pal_size); + } + else if (bih.biBitCount == 8) + { + static unsigned int g_bmp8_pallete[256] = { 0 }; + if (g_bmp8_pallete[1] == 0) + { + for (int i = 1; i < _countof(g_bmp8_pallete); ++i) + g_bmp8_pallete[i] = MAKELONG(MAKEWORD(i, i), MAKEWORD(i, 0)); + } + h += std::string((char*)g_bmp8_pallete, pal_size); + } } return h; diff --git a/sane/scanner.cpp b/sane/scanner.cpp index 92e716d..0c6562b 100644 --- a/sane/scanner.cpp +++ b/sane/scanner.cpp @@ -323,6 +323,7 @@ int scanner::init_options_id(void) else SET_OPT_ID(dogear_size, ZJDX, extension_none) else SET_OPT_ID(is_check_skew, WXJC, extension_none) else SET_OPT_ID(skew_range, WXRRD, extension_none) + else SET_OPT_ID(black_white_threshold, HBTXYZ, extension_none) op_id++; } @@ -343,6 +344,9 @@ int scanner::init_options_id(void) EX_APPENDIX_API(hardware_version); EX_APPENDIX_API(ip); + if (black_white_threshold_id_ == -1) + black_white_threshold_id_ = 0x8836; + return ret; } int scanner::control_read_string(int code, std::string& ret) @@ -1771,6 +1775,11 @@ COM_API_IMPLEMENT(scanner, int, set_value(int sn, void* val)) return ret; } +COM_API_IMPLEMENT(scanner, int, convert_image(SANE_ImageFormatConvert* conv)) +{ + return hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_CONVERT_IMAGE_FORMAT, conv, NULL); +} + // SANE options ID ... SANE_OPTION_ID_IMPLEMENT(is_multiout) @@ -1826,6 +1835,7 @@ SANE_OPTION_ID_IMPLEMENT(is_check_dogear) SANE_OPTION_ID_IMPLEMENT(dogear_size) SANE_OPTION_ID_IMPLEMENT(is_check_skew) SANE_OPTION_ID_IMPLEMENT(skew_range) +SANE_OPTION_ID_IMPLEMENT(black_white_threshold) // SANE-ex option ID: SANE_OPTION_ID_IMPLEMENT(ex_multiout_type) diff --git a/sane/scanner.h b/sane/scanner.h index 5c746c3..09e3e04 100644 --- a/sane/scanner.h +++ b/sane/scanner.h @@ -197,6 +197,7 @@ public: COM_API_OVERRIDE(bool, get_option_info(int sn, value_type* type, value_limit* limit, int* bytes)); COM_API_OVERRIDE(bool, get_value(int sn, set_opt_value, void* param)); COM_API_OVERRIDE(int, set_value(int sn, void* val)); + COM_API_OVERRIDE(int, convert_image(SANE_ImageFormatConvert* conv)); // SANE options ID ... SANE_OPTION_ID(is_multiout); @@ -252,6 +253,7 @@ public: SANE_OPTION_ID(dogear_size); SANE_OPTION_ID(is_check_skew); SANE_OPTION_ID(skew_range); + SANE_OPTION_ID(black_white_threshold); // 二值化图像阈值 // SANE-ex option ID: SANE_OPTION_ID(ex_multiout_type); // int diff --git a/twain/twain.vcxproj b/twain/twain.vcxproj index 3a27b11..0e66d03 100644 --- a/twain/twain.vcxproj +++ b/twain/twain.vcxproj @@ -48,12 +48,14 @@ $(SolutionDir)..\..\sdk\include\;$(IncludePath) $(SolutionDir)..\..\release\win\$(PlatformTarget)\$(Configuration)\ $(SolutionDir)..\..\tmp\$(PlatformTarget)\$(Configuration)\$(ProjectName)\ + $(LibraryPath) false $(SolutionDir)..\..\sdk\include\;$(IncludePath) $(SolutionDir)..\..\release\win\$(PlatformTarget)\$(Configuration)\ $(SolutionDir)..\..\tmp\$(PlatformTarget)\$(Configuration)\$(ProjectName)\ + $(LibraryPath) @@ -64,11 +66,14 @@ true 4996 pch.h + MultiThreadedDebugDLL Console true $(ProjectDir)twain.def + + mkdir $(SolutionDir)..\..\sdk\lib\win\$(PlatformTarget)\$(Configuration) @@ -96,6 +101,8 @@ copy $(TargetPath) $(WinDir)\twain_32\HuaGoScan\huagaotwain.ds /y true true $(ProjectDir)twain.def + + mkdir $(SolutionDir)..\..\sdk\lib\win\$(PlatformTarget)\$(Configuration) @@ -107,6 +114,7 @@ copy $(TargetPath) $(WinDir)\twain_32\HuaGoScan\$(ProjectName).ds /y + diff --git a/twain/twain.vcxproj.filters b/twain/twain.vcxproj.filters index bf07ba3..10ebab4 100644 --- a/twain/twain.vcxproj.filters +++ b/twain/twain.vcxproj.filters @@ -171,6 +171,9 @@ Headers + + Headers + diff --git a/twain/twain/huagaods.cpp b/twain/twain/huagaods.cpp index 2ceec87..179200c 100644 --- a/twain/twain/huagaods.cpp +++ b/twain/twain/huagaods.cpp @@ -16,6 +16,7 @@ #include #define mktemp _mktemp #endif // WIN32 + using namespace std; #define enum2str(R) #R @@ -121,6 +122,7 @@ enum CapTypeEx : unsigned short { CAP_EX_SANE_dogear_size, CAP_EX_SANE_is_check_skew, CAP_EX_SANE_skew_range, + CAP_EX_SANE_black_white_threshold, // END for SANE豸ԭʼ͸ ///////////////////////////////////////////////////////////////////////// }; @@ -570,19 +572,7 @@ float trans_range(float val, float min_from, float max_from, float min_to, float //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // huagao_ds ... -#define PRODUCT_PID 0x0100 -#define PRODUCT_VID 0x3072 -#define PRODUCT_VENDOR "HUAGO" -#define PRODUCT_FAMILY "HG100" -#define PRODUCT_NAME "HG0100" - -#define TO_STR(a) #a -#define VERSION_MAIN 4 -#define VERSION_SUB 1007 -#define VERSION_BUILD 2022 -#define VERSION_PATCH 6131 -#define TO_VER_STR(vs) TO_STR(v##vs) -#define VERSION_STR(a, b, c, d) TO_VER_STR(a.b.c.d) +#include "../brand.h" static Identity* srcIdent = new Identity( Version(VERSION_MAIN, VERSION_SUB, Language::English, Country::China, VERSION_STR(VERSION_MAIN, VERSION_SUB, VERSION_BUILD, VERSION_PATCH)), @@ -876,7 +866,7 @@ Result huagao_ds::imageInfoGet(const Identity&, ImageInfo& data) GET_SANE_OPT(int, scanner_, resolution, &res, NULL, NULL, NULL, NULL); data.setXResolution(res); data.setYResolution(res); - data.compression(Compression::None); + data.compression(m_compression); } return success(); @@ -1054,6 +1044,30 @@ Twpp::Result huagao_ds::imageFileXferGet(const Twpp::Identity& origin) else DeleteFileA(file.c_str()); } + + if (ret.status() == ConditionCode::Success && m_fileXfer.format() != ImageFileFormat::Bmp) + { + SANE_ImageFormatConvert conv; + std::string target(m_fileXfer.filePath().string().c_str()); + + file = target + ".src"; + conv.src.fmt.img_format = SANE_IMAGE_TYPE_BMP; + conv.src.is_file = SANE_TRUE; + conv.src.data = file.c_str(); + conv.src.data_len = file.length(); + + conv.dst.fmt.img_format = (SANE_ImageType)m_fileXfer.format(); + conv.dst.fmt.compress.compression = (SANE_CompressionType)m_compression; + conv.dst.fmt.compress.detail = (void*)0; + conv.dst.fmt.detail = (void*)m_jpegQuality; + conv.dst.is_file = SANE_TRUE; + conv.dst.data = target.c_str(); + conv.dst.data_len = target.length(); + MoveFileA(target.c_str(), file.c_str()); + if(scanner_->convert_image(&conv) != SANE_STATUS_GOOD) + ret = { ReturnCode::Failure, ConditionCode::FileWriteError }; + DeleteFileA(file.c_str()); + } } return ret; @@ -1215,30 +1229,40 @@ void huagao_ds::init_support_caps(void) m_caps[CapType::ICompression] = [this](Msg msg, Capability& data)->Result { if (!scanner_.get()) return seqError(); - if (msg == Msg::Set || msg == Msg::Reset) - { - int mech = (int)data.currentItem(); - if (msg == Msg::Reset) - GET_SANE_OPT(int, scanner_, ex_final_compression, NULL, &mech, NULL, NULL); - - int ret = SCANNER_ERR_OK; - SET_SANE_OPT(ret, scanner_, ex_final_compression, (int*)&mech); - return ret == SCANNER_ERR_OK ? success() : badValue(); + if (Msg::Set == msg) { + auto mech = data.currentItem(); + if (Compression::None == mech || mech == Compression::Group4) { + m_compression = mech; + return success(); + } + else + return badValue(); } - std::vector values; - int init = 0, now = 0; - std::list vals; - Compression Now, Init; - UInt32 ni = 0, ii = 0; + return CapSupGetAllReset(msg, data, { Compression::None, Compression::Group4 }, m_compression, Compression::None, m_compression == Compression::None ? 0 : 1, 0); + //if (msg == Msg::Set || msg == Msg::Reset) + //{ + // int mech = (int)data.currentItem(); + // if (msg == Msg::Reset) + // GET_SANE_OPT(int, scanner_, ex_final_compression, NULL, &mech, NULL, NULL); - GET_SANE_OPT(int, scanner_, ex_final_compression, &now, &init, &values, NULL); - Now = (Compression)now; - Init = (Compression)init; - for (const auto& v : values) - vals.push_back((Compression)v); - ni = std::distance(values.begin(), std::find(values.begin(), values.end(), now)); - ii = std::distance(values.begin(), std::find(values.begin(), values.end(), init)); - return cap_get_enum_values(msg, data, vals, Now, Init, ni, ii); + // int ret = SCANNER_ERR_OK; + // SET_SANE_OPT(ret, scanner_, ex_final_compression, (int*)&mech); + // return ret == SCANNER_ERR_OK ? success() : badValue(); + //} + //std::vector values; + //int init = 0, now = 0; + //std::list vals; + //Compression Now, Init; + //UInt32 ni = 0, ii = 0; + + //GET_SANE_OPT(int, scanner_, ex_final_compression, &now, &init, &values, NULL); + //Now = (Compression)now; + //Init = (Compression)init; + //for (const auto& v : values) + // vals.push_back((Compression)v); + //ni = std::distance(values.begin(), std::find(values.begin(), values.end(), now)); + //ii = std::distance(values.begin(), std::find(values.begin(), values.end(), init)); + //return cap_get_enum_values(msg, data, vals, Now, Init, ni, ii); }; m_query[CapType::IUnits] = msgSupportGetAllSetReset; @@ -1518,16 +1542,20 @@ void huagao_ds::init_support_caps(void) if ((int)mech <= 0 || (int)mech > 100) return badValue(); - int ret = SCANNER_ERR_OK; - fif.detail = (void*)mech; - SET_SANE_OPT(ret, scanner_, ex_final_format, &fif); - return ret == SCANNER_ERR_OK ? success() : badValue(); + m_jpegQuality = (int)mech; + return success(); + //int ret = SCANNER_ERR_OK; + //fif.detail = (void*)mech; + //SET_SANE_OPT(ret, scanner_, ex_final_format, &fif); + //return ret == SCANNER_ERR_OK ? success() : badValue(); } - unsigned short q = 80; - fif.detail = (void*)q; - GET_SANE_OPT(SANE_FinalImgFormat, scanner_, ex_final_format, &fif, NULL, NULL, NULL); - if(fif.img_format == SANE_IMAGE_TYPE_JPG) - q = (unsigned short)fif.detail; + //unsigned short q = 80; + //fif.detail = (void*)q; + //GET_SANE_OPT(SANE_FinalImgFormat, scanner_, ex_final_format, &fif, NULL, NULL, NULL); + //if(fif.img_format == SANE_IMAGE_TYPE_JPG) + // q = (unsigned short)fif.detail; + //return CapSupGetAllResetEx(msg, data, q, 80); + unsigned short q = m_jpegQuality; return CapSupGetAllResetEx(msg, data, q, 80); }; @@ -1621,13 +1649,20 @@ void huagao_ds::init_support_caps(void) std::vector all; GET_SANE_OPT(SANE_FinalImgFormat, scanner_, ex_final_format, &now, &init, &all, NULL); if (Msg::Set == msg || Msg::Reset == msg) { - if(Msg::Set == msg) - init.img_format = (SANE_ImageType)(int)data.currentItem(); - int ret = SCANNER_ERR_OK; - SET_SANE_OPT(ret, scanner_, ex_final_format, &init); - return ret == SCANNER_ERR_OK ? success() : badValue(); + auto fmt = data.currentItem(); + if (fmt != Twpp::ImageFileFormat::Bmp && + fmt != Twpp::ImageFileFormat::Jfif && + fmt != Twpp::ImageFileFormat::Tiff) + return badValue(); + m_fileXfer.setFormat((Twpp::ImageFileFormat)data.currentItem()); + return success(); + //if(Msg::Set == msg) + // init.img_format = (SANE_ImageType)(int)data.currentItem(); + //int ret = SCANNER_ERR_OK; + //SET_SANE_OPT(ret, scanner_, ex_final_format, &init); + //return ret == SCANNER_ERR_OK ? success() : badValue(); } - ImageFileFormat Now = (ImageFileFormat)(int)now.img_format, Init = (ImageFileFormat)(int)init.img_format; + ImageFileFormat Now = m_fileXfer.format(), Init = (ImageFileFormat)(int)init.img_format; std::list vals; UInt32 i = 0, n = 0; for (const auto& v : all) @@ -2464,6 +2499,7 @@ void huagao_ds::init_support_caps_ex(void) ADD_SANE_CAP(dogear_size); ADD_SANE_CAP(is_check_skew); ADD_SANE_CAP(skew_range); + ADD_SANE_CAP(black_white_threshold); } void huagao_ds::on_scan_event(int sane_event, void* data, unsigned int* len) { diff --git a/twain/twain/huagaods.hpp b/twain/twain/huagaods.hpp index a8efb8c..2e4f9d8 100644 --- a/twain/twain/huagaods.hpp +++ b/twain/twain/huagaods.hpp @@ -38,6 +38,8 @@ class huagao_ds : public Twpp::SourceFromThis { int automaticcolortype_ = 0; bool multi_out_ = false; bool m_bIndicator = true; + int m_jpegQuality = 80; + Twpp::Compression m_compression = Twpp::Compression::None; static std::string get_hidedlg_path(void); static void showmsg(const char* msg, int err);