diff --git a/app/scanner/config.cpp b/app/scanner/config.cpp index aeeccc62..2a338c8e 100644 --- a/app/scanner/config.cpp +++ b/app/scanner/config.cpp @@ -159,6 +159,34 @@ void config::to_lower(std::string& str) str[i] -= 'A' - 'a'; } } +bool config::load_custom_gamma(const char* file, SANE_Gamma* gamma) +{ + bool ret = false; + FILE* src = fopen(file, "rb"); + if(src) + { + long l = 0; + SANE_Gamma tmp = {0}; + fseek(src, 0, SEEK_END); + l = ftell(src); + fseek(src, 0, SEEK_SET); + if(l == sizeof(SANE_Gamma) && + fread(&tmp, l, 1, src) == 1) + { + if( tmp.pt_count >= 0 && tmp.pt_count <= sizeof (tmp.keypoint) / sizeof(tmp.keypoint[0]) && + tmp.pt_count_r >= 0 && tmp.pt_count_r <= sizeof (tmp.keypoint_r) / sizeof(tmp.keypoint_r[0]) && + tmp.pt_count_g >= 0 && tmp.pt_count_g <= sizeof (tmp.keypoint_g) / sizeof(tmp.keypoint_g[0]) && + tmp.pt_count_b >= 0 && tmp.pt_count_b <= sizeof (tmp.keypoint_b) / sizeof(tmp.keypoint_b[0])) + { + memcpy(gamma, &tmp, l); + ret = true; + } + } + fclose(src); + } + + return ret; +} int config::load(QString file) { diff --git a/app/scanner/config.h b/app/scanner/config.h index 7c76f65c..42cc2b2a 100644 --- a/app/scanner/config.h +++ b/app/scanner/config.h @@ -4,7 +4,8 @@ #include #include #include - +#include "sane/sane_ex.h" +#include "sane/sane_option_definitions.h" #include "json.h" #define IS_DOUBLE_EQUAL(a, b) fabs((a) - (b)) < .00001 @@ -141,6 +142,7 @@ public: static int find_config(QString dev_name, std::vector& cfgs); static bool is_accessible_file(const std::string& path_file); static void to_lower(std::string& str); + static bool load_custom_gamma(const char* file, SANE_Gamma* gamma); public: int load(QString file = ""); diff --git a/app/scanner/dialog_log.cpp b/app/scanner/dialog_log.cpp index bbf7ec35..204f74ef 100644 --- a/app/scanner/dialog_log.cpp +++ b/app/scanner/dialog_log.cpp @@ -35,7 +35,7 @@ dialog_log::dialog_log(QWidget *parent) ui->verticalLayout->addItem(bottom); - cBox_autoScroll->setChecked(getCfgValue("log", "autoScroll", false)); + cBox_autoScroll->setChecked(getCfgValue("log", "autoScroll", true)); connect(cBox_autoScroll, SIGNAL(stateChanged(int)), this, SLOT(on_cbox_autoScroll_stateChanged(int))); connect(pbtn_stop, SIGNAL(clicked(bool)), this, SLOT(on_pbtn_stop_clicked())); diff --git a/app/scanner/hg_settingdialog.cpp b/app/scanner/hg_settingdialog.cpp index 4a1b0de2..d4f5e89c 100644 --- a/app/scanner/hg_settingdialog.cpp +++ b/app/scanner/hg_settingdialog.cpp @@ -14,6 +14,7 @@ hg_settingdialog::hg_settingdialog(void *handle, QWidget *parent , DEVCFG* cfg) : QDialog(parent) , schemes_(cfg), cur_ind_(cfg->cur_scheme), changed_count_(0), save_(false) + , btn_cut_area_(nullptr), btn_gamma_(nullptr), cfg_file_(nullptr) { m_dpiId = -1; m_dpiValue = 200; @@ -33,6 +34,8 @@ hg_settingdialog::hg_settingdialog(void *handle, QWidget *parent m_colorModeId = -1; m_colorModeValue.clear(); memset(&m_gammaData, 0, sizeof(m_gammaData)); + for(int i = 0; i < sizeof(m_gammaData.table) / sizeof(m_gammaData.table[0]); ++i) + m_gammaData.table[i] = i & 0x0ff; m_handle = handle; initUi(); @@ -318,13 +321,48 @@ void hg_settingdialog::createUI() if(schemes_ && cur_ind_ != -1) ind = find_opt_setting(opt->title, schemes_->schemes[scheme].opts); init.opt = i + 1; + h = nullptr; switch (opt->type) { case SANE_TYPE_BOOL: { QCheckBox *checkBoxCreation = new QCheckBox(scrollArea); - reinterpret_cast(widget->layout())->addRow(opt->title + QString(" : "), checkBoxCreation); + if (strcmp(opt->title, OPTION_TITLE_ZDYSMQY) == 0) + { + QLabel *title = new QLabel(scrollArea); + h = new QHBoxLayout(); + title->setText(QString::fromStdString(opt->title) + QString(" : ")); + h->addWidget(title); + h->addWidget(checkBoxCreation); + + btn_cut_area_ = new QPushButton(this); + btn_cut_area_->setText(StdStringToUtf8("区域裁剪").c_str()); + btn_cut_area_->setFixedWidth(120); + h->addWidget(btn_cut_area_); + + reinterpret_cast(widget->layout())->addRow(h); + connect(btn_cut_area_, SIGNAL(clicked(bool)), this, SLOT(slot_cutButtonClicked())); + } + else if (strcmp(opt->title, OPTION_TITLE_QYSDQX) == 0) + { + QLabel *title = new QLabel(scrollArea); + h = new QHBoxLayout(); + title->setText(QString::fromStdString(opt->title) + QString(" : ")); + h->addWidget(title); + h->addWidget(checkBoxCreation); + + btn_gamma_ = new QPushButton(this); + btn_gamma_->setText(StdStringToUtf8("自定义色调曲线").c_str()); + btn_gamma_->setFixedWidth(120); + h->addWidget(btn_gamma_); + + reinterpret_cast(widget->layout())->addRow(h); + connect(btn_gamma_, SIGNAL(clicked(bool)), this, SLOT(slot_gammaButtonClicked())); + } + else + reinterpret_cast(widget->layout())->addRow(opt->title + QString(" : "), checkBoxCreation); checkBoxCreation->setToolTip(opt->desc); + int id = i + 1; checkBoxCreation->setProperty("controls_id", id); if(ind != -1) @@ -332,6 +370,10 @@ void hg_settingdialog::createUI() else init.val = m_list_defaultOptions.at(i).second; checkBoxCreation->setChecked(init.val.toBool()); + if (strcmp(opt->title, OPTION_TITLE_ZDYSMQY) == 0) + btn_cut_area_->setEnabled(init.val.toBool()); + else if (strcmp(opt->title, OPTION_TITLE_QYSDQX) == 0) + btn_gamma_->setEnabled(init.val.toBool()); connect(checkBoxCreation, SIGNAL(stateChanged(int)), this, SLOT(slot_checkedClicked())); m_list_widgets.append(checkBoxCreation); @@ -649,35 +691,13 @@ void hg_settingdialog::createUI() m_cutBottomValue = SANE_UNFIX(m_list_defaultOptions.at(i).second.toInt()); } -// if (Utf8ToStdString(opt->title) == "分辨率") - if (strcmp(opt->title, OPTION_TITLE_FBL) == 0) - { - QPushButton* pushButton = new QPushButton(this); - pushButton->setText(StdStringToUtf8("区域裁剪").c_str()); - pushButton->setFixedWidth(120); - widget->layout()->addWidget(pushButton); - - connect(pushButton, SIGNAL(clicked(bool)), this, SLOT(slot_cutButtonClicked())); - } // else if (Utf8ToStdString(opt->title) == "颜色模式") - else if (strcmp(opt->title, OPTION_TITLE_YSMS) == 0) + if (strcmp(opt->title, OPTION_TITLE_YSMS) == 0) { m_colorModeId = i + 1; m_colorModeValue = m_list_defaultOptions.at(i).second.toString(); } // else if (Utf8ToStdString(opt->title) == "伽玛" || Utf8ToStdString(opt->title) == "伽玛值") - else if (strcmp(opt->title, OPTION_TITLE_GMZ) == 0) - { - unsigned int len = sizeof(SANE_Gamma); - sane_io_control(m_handle, IO_CTRL_CODE_GET_CUSTOM_GAMMA, &m_gammaData, &len); - - QPushButton* pushButton = new QPushButton(this); - pushButton->setText(StdStringToUtf8("自定义色调曲线").c_str()); - pushButton->setFixedWidth(120); - widget->layout()->addWidget(pushButton); - - connect(pushButton, SIGNAL(clicked(bool)), this, SLOT(slot_gammaButtonClicked())); - } if(init.opt != -1) init_vals_.push_back(init); @@ -856,7 +876,8 @@ void hg_settingdialog::updateUIStatus() if (widget == nullptr) continue; QWidget* parentWidget = widget->parentWidget(); - while (typeid(*(parentWidget->layout())) != typeid(QFormLayout)) + while (parentWidget->layout() && + typeid(*(parentWidget->layout())) != typeid(QFormLayout)) { widget = parentWidget; parentWidget = widget->parentWidget(); @@ -864,19 +885,19 @@ void hg_settingdialog::updateUIStatus() QFormLayout* layout = reinterpret_cast(parentWidget->layout()); const SANE_Option_Descriptor* opt = reinterpret_cast(m_list_defaultOptions.at(id - 1).first); + bool hide = (opt->cap & SANE_CAP_INACTIVE) == SANE_CAP_INACTIVE; + QWidget* w_label = layout ? layout->labelForField(widget) : nullptr; + + if( strcmp(opt->title, OPTION_TITLE_SMQYZCmm) == 0 || + strcmp(opt->title, OPTION_TITLE_SMQYSCmm) == 0 || + strcmp(opt->title, OPTION_TITLE_SMQYYCmm) == 0 || + strcmp(opt->title, OPTION_TITLE_SMQYXCmm) == 0 ) + hide = true; + refresh_control_value(id); - if((opt->cap & SANE_CAP_INACTIVE) == SANE_CAP_INACTIVE) - { - QWidget* w_label = layout->labelForField(widget); - if(w_label != nullptr) - w_label->hide(); - widget->setVisible(false); - }else{ - QWidget* w_label = layout->labelForField(widget); - if(w_label != nullptr) - w_label->show(); - widget->setVisible(true); - } + if(w_label) + hide ? w_label->hide() : w_label->show(); + widget->setVisible(!hide); } // Temporarily block the multi-stream output function @@ -887,7 +908,8 @@ void hg_settingdialog::updateUIStatus() QWidget* w = m_list_widgets.at(i); int id = w->property("controls_id").toInt(); const SANE_Option_Descriptor* opt = reinterpret_cast(m_list_defaultOptions.at(id - 1).first); - if(strcmp(opt->title, "24位彩色图像-多流输出") == 0) +// if(strcmp(opt->title, "24位彩色图像-多流输出") == 0) + if(strcmp(opt->title, OPTION_TITLE_24WCSTX_DLSCCH) == 0) { QFormLayout* layout = reinterpret_cast(w->parentWidget()->layout()); QWidget* w_label = layout->labelForField(w); @@ -921,18 +943,11 @@ void hg_settingdialog::slot_checkedClicked() else if(method & SANE_INFO_INEXACT) checkBox->setCheckState(checkBoxcurrentState ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); - std::vector::iterator it = - std::find(changed_opts_.begin(), changed_opts_.end(), (int)id); - if(it == changed_opts_.end()) - { - CHANGEDOPT co; - co.opt = id; - co.val = QVariant((bool)checkBoxcurrentState); - changed_opts_.push_back(co); - } - else { - it->val = QVariant((bool)checkBoxcurrentState); - } + if(strcmp(opt->title, OPTION_TITLE_ZDYSMQY) == 0) + btn_cut_area_->setEnabled(checkBoxcurrentState); + else if (strcmp(opt->title, OPTION_TITLE_QYSDQX) == 0) + btn_gamma_->setEnabled(checkBoxcurrentState); + record_changed_option((int)id, checkBoxcurrentState); } void hg_settingdialog::slot_string_list_comboBoxClicked() @@ -1514,6 +1529,10 @@ int hg_settingdialog::get_changed_items(void) { return changed_count_; } +void hg_settingdialog::set_config_file(config* cfg) +{ + cfg_file_ = cfg; +} void hg_settingdialog::iniWrite(QString title, int id, QVariant value) { @@ -1660,6 +1679,10 @@ void hg_settingdialog::on_select_scheme(int scheme_ind, bool apply_to_dev) { OPTSCHEME *schm = NULL; + memset(&m_gammaData, 0, sizeof(m_gammaData)); + for(int i = 0; i < sizeof(m_gammaData.table) / sizeof(m_gammaData.table[0]); ++i) + m_gammaData.table[i] = i & 0x0ff; + changed_opts_.clear(); if(scheme_ind >= 0 && scheme_ind + 1 < (int)schemes_->schemes.size()) { @@ -1685,6 +1708,13 @@ void hg_settingdialog::on_select_scheme(int scheme_ind, bool apply_to_dev) if(ok) changed_opts_.push_back(co); } + else if(schm->opts[i].name == OPTION_TITLE_ZDYGM) + { + co.opt = (int)OPTION_ID_ZDYGM; + co.val = QVariant(QString::fromStdString(schm->opts[i].val)); + changed_opts_.push_back(co); + config::load_custom_gamma(schm->opts[i].val.c_str(), &m_gammaData); + } } } @@ -1730,6 +1760,8 @@ void hg_settingdialog::save_scheme(void) int names = 0; OPTVAL ov; OPTSCHEME os; + bool save_gamma = false; + QString gamma_file(""); const SANE_Option_Descriptor *opt = nullptr; if(cur_ind_ >= 0 && cur_ind_ + 1 < (int)schemes_->schemes.size()) @@ -1739,7 +1771,13 @@ void hg_settingdialog::save_scheme(void) { opt = (const SANE_Option_Descriptor*)find_option_description(changed_opts_[i].opt); if(!opt) + { + if(changed_opts_[i].opt == (int)OPTION_ID_ZDYGM) + { + gamma_file = changed_opts_[i].val.toString(); + } continue; + } if(is_equal_default_value(changed_opts_[i], opt->type)) continue; @@ -1774,9 +1812,15 @@ void hg_settingdialog::save_scheme(void) names++; } } + + // custom gamma ... + if(strcmp(opt->title, OPTION_TITLE_QYSDQX) == 0 && ov.val == "true") + { + save_gamma = true; + } } - if(os == src) + if(os == src && !save_gamma) { if(changed_count_ == 0) changed_count_ = schemes_->cur_scheme != cur_ind_; @@ -1816,11 +1860,44 @@ void hg_settingdialog::save_scheme(void) schemes_->schemes.erase(schemes_->schemes.begin() + cur_ind_ + 1); } else + { + gamma_file = ""; cur_ind_ = schemes_->schemes.size() - 1; + } } else cur_ind_ = find_covered_scheme(os); // schemes_->schemes.size() - 1; + if(save_gamma) + { + if(gamma_file.length() == 0) + { + time_t now = time(nullptr); + tm *ptm = localtime(&now); + char name[40] = {0}; + + sprintf(name, "/%04d%02d%02d%02d%02d%02d.gma", ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec); + if(cfg_file_) + { + std::string str(cfg_file_->get_file().toStdString()); + size_t pos = str.rfind('/'); + if(pos == std::string::npos) + pos = str.rfind('\\'); + if(pos != std::string::npos) + str.erase(pos); + gamma_file = QString::fromStdString(str); + } + else + gamma_file = config::self_path(); + gamma_file += QString::fromStdString(name); + } + config::save_2_file(gamma_file, &m_gammaData, sizeof(m_gammaData)); + ov.val = gamma_file.toStdString(); + ov.type = "file"; + ov.name = OPTION_TITLE_ZDYGM; + os.opts.push_back(ov); + } + schemes_->schemes.insert(schemes_->schemes.begin() + cur_ind_ + 1, os); schemes_->cur_scheme = cur_ind_; changed_count_++; @@ -2083,6 +2160,17 @@ void hg_settingdialog::slot_pushButton_scheme_management(void) break; } } + + OPTSCHEME* s = &schemes_->schemes[id + 1]; + for(size_t i = 0; i < s->opts.size(); ++i) + { + if(s->opts[i].name == OPTION_TITLE_ZDYGM) + { + SANE_Gamma gmma; + if(config::load_custom_gamma(s->opts[i].val.c_str(), &gmma)) + remove(s->opts[i].val.c_str()); + } + } schemes_->schemes.erase(schemes_->schemes.begin() + id + 1); if(top_menu_->actions().size() == 0) { @@ -2105,6 +2193,19 @@ void hg_settingdialog::slot_pushButton_scheme_management(void) if (msg.clickedButton() != msg.button(QMessageBox::Yes)) return; + for(size_t i = 1; i < schemes_->schemes.size(); ++i) + { + OPTSCHEME* s = &schemes_->schemes[i]; + for(size_t i = 0; i < s->opts.size(); ++i) + { + if(s->opts[i].name == OPTION_TITLE_ZDYGM) + { + SANE_Gamma gmma; + if(config::load_custom_gamma(s->opts[i].val.c_str(), &gmma)) + remove(s->opts[i].val.c_str()); + } + } + } schemes_->schemes.erase(schemes_->schemes.begin() + 1, schemes_->schemes.end()); QAction* acts = top_menu_->addAction(tr("No custom configuration was found")); acts->setEnabled(false); diff --git a/app/scanner/hg_settingdialog.h b/app/scanner/hg_settingdialog.h index dcca2cbc..5db3812f 100644 --- a/app/scanner/hg_settingdialog.h +++ b/app/scanner/hg_settingdialog.h @@ -29,6 +29,7 @@ class hg_settingdialog : public QDialog std::vector changed_opts_; // values which changed int changed_count_; bool save_; + config* cfg_file_; void refresh_control_value(int op_id); bool is_covered(std::vector& org, std::vector& now); // if all options in org are inclued in now, then return true @@ -40,6 +41,8 @@ class hg_settingdialog : public QDialog QPushButton *apply_; QPushButton *del_this_; QPushButton *del_all_; + QPushButton *btn_cut_area_; + QPushButton *btn_gamma_; QTextEdit *sketch_; void create_scheme_management_ui(QVBoxLayout* layout); QAction* find_current_scheme_menu(int *scheme_id = NULL); @@ -65,6 +68,7 @@ public: QVector find_control(int opt_num); void keyPressEvent(QKeyEvent *e); int get_changed_items(void); + void set_config_file(config* cfg); private: void *m_handle; diff --git a/app/scanner/mainwindow.cpp b/app/scanner/mainwindow.cpp index a6b7c49b..3f454403 100644 --- a/app/scanner/mainwindow.cpp +++ b/app/scanner/mainwindow.cpp @@ -2128,6 +2128,7 @@ void MainWindow::on_act_scannerSettings_triggered() dev_schemes_.erase(it); } hg_settingdialog dlg(cur_dev_.handle(), this, &cfg); + dlg.set_config_file(&m_config); dlg.exec(); int changes = dlg.get_changed_items(); dev_schemes_.insert(dev_schemes_.begin(), cfg); diff --git a/app/scanner/sane_device.cpp b/app/scanner/sane_device.cpp index c510712e..d0f7f8ca 100644 --- a/app/scanner/sane_device.cpp +++ b/app/scanner/sane_device.cpp @@ -20,22 +20,24 @@ bool sane_dev::apply(OPTSCHEME* schm) for(int i = 1; i < count; ++i) { const SANE_Option_Descriptor* desc = sane_get_option_descriptor(hdev_, i); + int extra = 0; + if(!desc) continue; if(desc->type == SANE_TYPE_GROUP || desc->type == SANE_TYPE_BUTTON) continue; - act_result result = apply(desc, i, schm->opts); + act_result result = apply(desc, i, schm->opts, &extra); if(result == ACT_RESULT_NO_NEED) continue; if(result == ACT_RESULT_SUCCESS) - applied++; + applied += extra + 1; else break; } - ret = schm->opts.size() == applied; + ret = schm->opts.size() <= applied; } if(ret) @@ -43,11 +45,13 @@ bool sane_dev::apply(OPTSCHEME* schm) return ret; } -sane_dev::act_result sane_dev::apply(const SANE_Option_Descriptor* desc, int opt, const std::vector& vals) +sane_dev::act_result sane_dev::apply(const SANE_Option_Descriptor* desc, int opt, const std::vector& vals, int *apply_extra) { act_result result = ACT_RESULT_NO_NEED; const OPTVAL *cfg = nullptr; + if(apply_extra) + *apply_extra = 0; for(size_t i = 0; i < vals.size(); ++i) { if(vals[i].name == desc->title) @@ -97,6 +101,23 @@ sane_dev::act_result sane_dev::apply(const SANE_Option_Descriptor* desc, int opt result = sane_control_option(hdev_, opt, SANE_ACTION_SET_VALUE, data, &afterdo) == SANE_STATUS_GOOD ? ACT_RESULT_SUCCESS : result; if(str) delete[] str; + + if(cfg->name == OPTION_TITLE_QYSDQX && cfg->val == "true") + { + for(size_t i = 0; i < vals.size(); ++i) + { + if(vals[i].name == OPTION_TITLE_ZDYGM) + { + SANE_Gamma gamma = {0}; + unsigned int l = 0; + if(config::load_custom_gamma(vals[i].val.c_str(), &gamma)) + sane_io_control(hdev_, IO_CTRL_CODE_SET_CUSTOM_GAMMA, &gamma, &l); + if(apply_extra) + *apply_extra = 1; + break; + } + } + } } return result; diff --git a/app/scanner/sane_device.h b/app/scanner/sane_device.h index 0453af8a..cb15e7d2 100644 --- a/app/scanner/sane_device.h +++ b/app/scanner/sane_device.h @@ -21,7 +21,7 @@ class sane_dev }; bool apply(OPTSCHEME* schm); - act_result apply(const SANE_Option_Descriptor* desc, int opt, const std::vector& vals); + act_result apply(const SANE_Option_Descriptor* desc, int opt, const std::vector& vals, int *apply_extra = nullptr); public: sane_dev();