diff --git a/backend/genesys/enums.h b/backend/genesys/enums.h index 9d7034bcf..f506988f4 100644 --- a/backend/genesys/enums.h +++ b/backend/genesys/enums.h @@ -526,6 +526,9 @@ enum class ModelFlag : unsigned // disable fast feeding mode on this scanner DISABLE_FAST_FEEDING = 1 << 14, + // scan gray scans as color and combine on host side + HOST_SIDE_GRAY = 1 << 15, + // the scanner uses multi-segment sensors that must be handled during calibration SIS_SENSOR = 1 << 16, diff --git a/backend/genesys/genesys.cpp b/backend/genesys/genesys.cpp index 543a6289b..e1ff07139 100644 --- a/backend/genesys/genesys.cpp +++ b/backend/genesys/genesys.cpp @@ -674,9 +674,9 @@ void scanner_setup_sensor(Genesys_Device& dev, const Genesys_Sensor& sensor, regs.set8(custom_reg.address, custom_reg.value); } - if (dev.model->asic_type != AsicType::GL841 && - dev.model->asic_type != AsicType::GL843) + if (dev.model->asic_type != AsicType::GL843) { + // FIXME: remove the above check regs_set_exposure(dev.model->asic_type, regs, sensor.exposure); } @@ -795,6 +795,8 @@ void scanner_move(Genesys_Device& dev, ScanMethod scan_method, unsigned steps, D session.params.scan_method = scan_method; session.params.scan_mode = ScanColorMode::GRAY; session.params.color_filter = ColorFilter::GREEN; + session.params.contrast_adjustment = dev.settings.contrast; + session.params.brightness_adjustment = dev.settings.brightness; session.params.flags = ScanFlag::DISABLE_SHADING | ScanFlag::DISABLE_GAMMA | @@ -959,6 +961,8 @@ void scanner_move_back_home(Genesys_Device& dev, bool wait_until_home) session.params.scan_method = dev.settings.scan_method; session.params.scan_mode = ScanColorMode::GRAY; session.params.color_filter = ColorFilter::GREEN; + session.params.contrast_adjustment = dev.settings.contrast; + session.params.brightness_adjustment = dev.settings.brightness; session.params.flags = ScanFlag::DISABLE_SHADING | ScanFlag::DISABLE_GAMMA | @@ -1100,6 +1104,8 @@ void scanner_move_back_home_ta(Genesys_Device& dev) session.params.scan_method = scan_method; session.params.scan_mode = ScanColorMode::GRAY; session.params.color_filter = ColorFilter::GREEN; + session.params.contrast_adjustment = dev.settings.contrast; + session.params.brightness_adjustment = dev.settings.brightness; session.params.flags = ScanFlag::DISABLE_SHADING | ScanFlag::DISABLE_GAMMA | @@ -1210,6 +1216,8 @@ void scanner_search_strip(Genesys_Device& dev, bool forward, bool black) session.params.scan_method = dev.settings.scan_method; session.params.scan_mode = ScanColorMode::GRAY; session.params.color_filter = ColorFilter::RED; + session.params.contrast_adjustment = dev.settings.contrast; + session.params.brightness_adjustment = dev.settings.brightness; session.params.flags = ScanFlag::DISABLE_SHADING | ScanFlag::DISABLE_GAMMA; if (dev.model->asic_type != AsicType::GL841 && !forward) { @@ -1506,6 +1514,8 @@ void scanner_offset_calibration(Genesys_Device& dev, const Genesys_Sensor& senso session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; session.params.color_filter = dev.model->asic_type == AsicType::GL843 ? ColorFilter::RED : dev.settings.color_filter; + session.params.contrast_adjustment = dev.settings.contrast; + session.params.brightness_adjustment = dev.settings.brightness; session.params.flags = flags; compute_session(&dev, session, *calib_sensor); @@ -1815,6 +1825,8 @@ void scanner_coarse_gain_calibration(Genesys_Device& dev, const Genesys_Sensor& session.params.scan_method = dev.settings.scan_method; session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; session.params.color_filter = dev.settings.color_filter; + session.params.contrast_adjustment = dev.settings.contrast; + session.params.brightness_adjustment = dev.settings.brightness; session.params.flags = flags; compute_session(&dev, session, *calib_sensor); @@ -1873,7 +1885,8 @@ void scanner_coarse_gain_calibration(Genesys_Device& dev, const Genesys_Sensor& float curr_output = 0; float target_value = 0; - if (dev.model->asic_type == AsicType::GL842 || + if (dev.model->asic_type == AsicType::GL841 || + dev.model->asic_type == AsicType::GL842 || dev.model->asic_type == AsicType::GL843) { std::vector values; @@ -1889,18 +1902,6 @@ void scanner_coarse_gain_calibration(Genesys_Device& dev, const Genesys_Sensor& curr_output = static_cast(values[unsigned((values.size() - 1) * 0.95)]); target_value = calib_sensor->gain_white_ref * coeff; - } else if (dev.model->asic_type == AsicType::GL841) { - // FIXME: use the GL843 approach - unsigned max = 0; - for (std::size_t x = 0; x < image.get_width(); x++) { - auto value = image.get_raw_channel(x, 0, ch); - if (value > max) { - max = value; - } - } - - curr_output = max; - target_value = 65535.0f; } else { // FIXME: use the GL843 approach auto width = image.get_width(); @@ -1998,7 +1999,8 @@ SensorExposure scanner_led_calibration(Genesys_Device& dev, const Genesys_Sensor const auto& calib_sensor = sanei_genesys_find_sensor(&dev, resolution, channels, dev.settings.scan_method); - if (dev.model->asic_type == AsicType::GL845 || + if (dev.model->asic_type == AsicType::GL841 || + dev.model->asic_type == AsicType::GL845 || dev.model->asic_type == AsicType::GL846 || dev.model->asic_type == AsicType::GL847 || dev.model->asic_type == AsicType::GL124) @@ -2006,14 +2008,9 @@ SensorExposure scanner_led_calibration(Genesys_Device& dev, const Genesys_Sensor regs = dev.reg; // FIXME: apply this to all ASICs } - unsigned yres = resolution; - if (dev.model->asic_type == AsicType::GL841) { - yres = dev.settings.yres; // FIXME: remove this - } - ScanSession session; session.params.xres = resolution; - session.params.yres = yres; + session.params.yres = resolution; session.params.startx = 0; session.params.starty = 0; session.params.pixels = dev.model->x_size_calib_mm * resolution / MM_PER_INCH; @@ -2023,6 +2020,8 @@ SensorExposure scanner_led_calibration(Genesys_Device& dev, const Genesys_Sensor session.params.scan_method = dev.settings.scan_method; session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; session.params.color_filter = dev.settings.color_filter; + session.params.contrast_adjustment = dev.settings.contrast; + session.params.brightness_adjustment = dev.settings.brightness; session.params.flags = ScanFlag::DISABLE_SHADING | ScanFlag::DISABLE_GAMMA | ScanFlag::SINGLE_LINE | @@ -2032,27 +2031,14 @@ SensorExposure scanner_led_calibration(Genesys_Device& dev, const Genesys_Sensor dev.cmd_set->init_regs_for_scan_session(&dev, calib_sensor, ®s, session); - if (dev.model->asic_type == AsicType::GL841) { - dev.interface->write_registers(regs); // FIXME: remove this - } - std::uint16_t exp[3]; - if (dev.model->asic_type == AsicType::GL841) { - exp[0] = sensor.exposure.red; - exp[1] = sensor.exposure.green; - exp[2] = sensor.exposure.blue; - } else { - exp[0] = calib_sensor.exposure.red; - exp[1] = calib_sensor.exposure.green; - exp[2] = calib_sensor.exposure.blue; - } + exp[0] = calib_sensor.exposure.red; + exp[1] = calib_sensor.exposure.green; + exp[2] = calib_sensor.exposure.blue; std::uint16_t target = sensor.gain_white_ref * 256; - std::uint16_t min_exposure = 500; // only gl841 - std::uint16_t max_exposure = ((exp[0] + exp[1] + exp[2]) / 3) * 2; // only gl841 - std::uint16_t top[3] = {}; std::uint16_t bottom[3] = {}; @@ -2088,16 +2074,6 @@ SensorExposure scanner_led_calibration(Genesys_Device& dev, const Genesys_Sensor for (unsigned i_test = 0; i_test < 100 && !acceptable; ++i_test) { regs_set_exposure(dev.model->asic_type, regs, { exp[0], exp[1], exp[2] }); - if (dev.model->asic_type == AsicType::GL841) { - // FIXME: remove - dev.interface->write_register(0x10, (exp[0] >> 8) & 0xff); - dev.interface->write_register(0x11, exp[0] & 0xff); - dev.interface->write_register(0x12, (exp[1] >> 8) & 0xff); - dev.interface->write_register(0x13, exp[1] & 0xff); - dev.interface->write_register(0x14, (exp[2] >> 8) & 0xff); - dev.interface->write_register(0x15, exp[2] & 0xff); - } - dev.interface->write_registers(regs); dbg.log(DBG_info, "starting line reading"); @@ -2108,15 +2084,13 @@ SensorExposure scanner_led_calibration(Genesys_Device& dev, const Genesys_Sensor if (dev.model->asic_type == AsicType::GL841) { scanner_stop_action(dev); dev.cmd_set->move_back_home(&dev, true); - return { exp[0], exp[1], exp[2] }; } else if (dev.model->asic_type == AsicType::GL124) { scanner_stop_action(dev); - return calib_sensor.exposure; } else { scanner_stop_action(dev); dev.cmd_set->move_back_home(&dev, true); - return calib_sensor.exposure; } + return { exp[0], exp[1], exp[2] }; } auto image = read_unshuffled_image_from_scanner(&dev, session, session.output_line_bytes); @@ -2142,57 +2116,8 @@ SensorExposure scanner_led_calibration(Genesys_Device& dev, const Genesys_Sensor acceptable = true; - if (dev.model->asic_type == AsicType::GL841) { - if (avg[0] < avg[1] * 0.95 || avg[1] < avg[0] * 0.95 || - avg[0] < avg[2] * 0.95 || avg[2] < avg[0] * 0.95 || - avg[1] < avg[2] * 0.95 || avg[2] < avg[1] * 0.95) - { - acceptable = false; - } - - // led exposure is not acceptable if white level is too low. - // ~80 hardcoded value for white level - if (avg[0] < 20000 || avg[1] < 20000 || avg[2] < 20000) { - acceptable = false; - } - - // for scanners using target value - if (target > 0) { - acceptable = true; - for (unsigned i = 0; i < 3; i++) { - // we accept +- 2% delta from target - if (std::abs(avg[i] - target) > target / 50) { - exp[i] = (exp[i] * target) / avg[i]; - acceptable = false; - } - } - } else { - if (!acceptable) { - unsigned avga = (avg[0] + avg[1] + avg[2]) / 3; - exp[0] = (exp[0] * avga) / avg[0]; - exp[1] = (exp[1] * avga) / avg[1]; - exp[2] = (exp[2] * avga) / avg[2]; - /* Keep the resulting exposures below this value. Too long exposure drives - the ccd into saturation. We may fix this by relying on the fact that - we get a striped scan without shading, by means of statistical calculation - */ - unsigned avge = (exp[0] + exp[1] + exp[2]) / 3; - - if (avge > max_exposure) { - exp[0] = (exp[0] * max_exposure) / avge; - exp[1] = (exp[1] * max_exposure) / avge; - exp[2] = (exp[2] * max_exposure) / avge; - } - if (avge < min_exposure) { - exp[0] = (exp[0] * min_exposure) / avge; - exp[1] = (exp[1] * min_exposure) / avge; - exp[2] = (exp[2] * min_exposure) / avge; - } - - } - } - } else if (dev.model->asic_type == AsicType::GL845 || - dev.model->asic_type == AsicType::GL846) + if (dev.model->asic_type == AsicType::GL845 || + dev.model->asic_type == AsicType::GL846) { for (unsigned i = 0; i < 3; i++) { if (avg[i] < bottom[i]) { @@ -2225,7 +2150,9 @@ SensorExposure scanner_led_calibration(Genesys_Device& dev, const Genesys_Sensor acceptable = false; } } - } else if (dev.model->asic_type == AsicType::GL124) { + } else if (dev.model->asic_type == AsicType::GL841 || + dev.model->asic_type == AsicType::GL124) + { for (unsigned i = 0; i < 3; i++) { // we accept +- 2% delta from target if (std::abs(avg[i] - target) > target / 50) { @@ -4366,12 +4293,6 @@ static Genesys_Settings calculate_scan_settings(Genesys_Scanner* s) settings.color_filter = ColorFilter::NONE; } - if (s->color_filter == "None") { - settings.true_gray = 1; - } else { - settings.true_gray = 0; - } - // brightness and contrast only for for 8 bit scans if (s->bit_depth == 8) { settings.contrast = (s->contrast * 127) / 100; @@ -5243,7 +5164,7 @@ static void probe_genesys_devices() of Genesys_Calibration_Cache as is. */ static const char* CALIBRATION_IDENT = "sane_genesys"; -static const int CALIBRATION_VERSION = 31; +static const int CALIBRATION_VERSION = 32; bool read_calibration(std::istream& str, Genesys_Device::Calibration& calibration, const std::string& path) diff --git a/backend/genesys/gl124.cpp b/backend/genesys/gl124.cpp index 94a4fed4e..aac8fe6e8 100644 --- a/backend/genesys/gl124.cpp +++ b/backend/genesys/gl124.cpp @@ -453,7 +453,6 @@ static void gl124_init_motor_regs_scan(Genesys_Device* dev, ScanFlag flags) { DBG_HELPER(dbg); - int use_fast_fed; unsigned int lincnt, fast_dpi; unsigned int feedl,dist; uint32_t z1, z2; @@ -467,9 +466,6 @@ static void gl124_init_motor_regs_scan(Genesys_Device* dev, feed_steps, static_cast(scan_mode), static_cast(flags)); - /* we never use fast fed since we do manual feed for the scans */ - use_fast_fed=0; - /* enforce motor minimal scan speed * @TODO extend motor struct for this value */ if (scan_mode == ScanColorMode::COLOR_SINGLE_PASS) @@ -516,12 +512,6 @@ static void gl124_init_motor_regs_scan(Genesys_Device* dev, /* compute register 02 value */ uint8_t r02 = REG_0x02_NOTHOME; - if (use_fast_fed) { - r02 |= REG_0x02_FASTFED; - } else { - r02 &= ~REG_0x02_FASTFED; - } - if (has_flag(flags, ScanFlag::AUTO_GO_HOME)) { r02 |= REG_0x02_AGOHOME; } @@ -573,9 +563,6 @@ static void gl124_init_motor_regs_scan(Genesys_Device* dev, if (has_flag(flags, ScanFlag::FEEDING)) { dist *= 2; } - if (use_fast_fed) { - dist += fast_table.table.size() * 2; - } /* get sure we don't use insane value */ if (dist < feedl) { @@ -587,7 +574,7 @@ static void gl124_init_motor_regs_scan(Genesys_Device* dev, reg->set24(REG_FEEDL, feedl); /* doesn't seem to matter that much */ - sanei_genesys_calculate_zmod(use_fast_fed, + sanei_genesys_calculate_zmod(false, scan_exposure_time, scan_table.table, scan_table.table.size(), @@ -815,6 +802,8 @@ ScanSession CommandSetGl124::calculate_scan_session(const Genesys_Device* dev, session.params.scan_method = settings.scan_method; session.params.scan_mode = settings.scan_mode; session.params.color_filter = settings.color_filter; + session.params.contrast_adjustment = dev->settings.contrast; + session.params.brightness_adjustment = dev->settings.brightness; session.params.flags = ScanFlag::NONE; compute_session(dev, session, sensor); @@ -983,6 +972,8 @@ void CommandSetGl124::init_regs_for_shading(Genesys_Device* dev, const Genesys_S session.params.scan_method = dev->settings.scan_method; session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; session.params.color_filter = ColorFilter::RED; + session.params.contrast_adjustment = dev->settings.contrast; + session.params.brightness_adjustment = dev->settings.brightness; session.params.flags = ScanFlag::DISABLE_SHADING | ScanFlag::DISABLE_GAMMA | ScanFlag::DISABLE_BUFFER_FULL_MOVE; @@ -1116,6 +1107,8 @@ void move_to_calibration_area(Genesys_Device* dev, const Genesys_Sensor& sensor, session.params.scan_method = dev->settings.scan_method; session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; session.params.color_filter = dev->settings.color_filter; + session.params.contrast_adjustment = dev->settings.contrast; + session.params.brightness_adjustment = dev->settings.brightness; session.params.flags = ScanFlag::DISABLE_SHADING | ScanFlag::DISABLE_GAMMA | ScanFlag::SINGLE_LINE | @@ -1202,6 +1195,8 @@ void CommandSetGl124::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Se session.params.scan_method = dev->settings.scan_method; session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; session.params.color_filter = dev->settings.color_filter; + session.params.contrast_adjustment = dev->settings.contrast; + session.params.brightness_adjustment = dev->settings.brightness; session.params.flags = flags; compute_session(dev, session, sensor); diff --git a/backend/genesys/gl646.cpp b/backend/genesys/gl646.cpp index acc1a4b8d..db087f80e 100644 --- a/backend/genesys/gl646.cpp +++ b/backend/genesys/gl646.cpp @@ -605,7 +605,9 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene } /* true CIS gray if needed */ - if (dev->model->is_cis && session.params.channels == 1 && dev->settings.true_gray) { + if (dev->model->is_cis && session.params.channels == 1 && + session.params.color_filter == ColorFilter::NONE) + { regs->find_reg(0x05).value |= REG_0x05_LEDADD; } else { regs->find_reg(0x05).value &= ~REG_0x05_LEDADD; @@ -1707,6 +1709,8 @@ void CommandSetGl646::move_back_home(Genesys_Device* dev, bool wait_until_home) session.params.scan_method = dev->model->default_method; session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; session.params.color_filter = ColorFilter::RED; + session.params.contrast_adjustment = dev->settings.contrast; + session.params.brightness_adjustment = dev->settings.brightness; session.params.flags = ScanFlag::REVERSE | ScanFlag::AUTO_GO_HOME | ScanFlag::DISABLE_GAMMA; @@ -1823,6 +1827,8 @@ void CommandSetGl646::init_regs_for_shading(Genesys_Device* dev, const Genesys_S session.params.scan_method = dev->settings.scan_method; session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; session.params.color_filter = dev->settings.color_filter; + session.params.contrast_adjustment = dev->settings.contrast; + session.params.brightness_adjustment = dev->settings.brightness; session.params.flags = ScanFlag::DISABLE_SHADING | ScanFlag::DISABLE_GAMMA | ScanFlag::IGNORE_COLOR_OFFSET | @@ -1931,6 +1937,8 @@ SensorExposure CommandSetGl646::led_calibration(Genesys_Device* dev, const Genes session.params.scan_method = dev->settings.scan_method; session.params.scan_mode = scan_mode; session.params.color_filter = ColorFilter::RED; + session.params.contrast_adjustment = dev->settings.contrast; + session.params.brightness_adjustment = dev->settings.brightness; session.params.flags = ScanFlag::DISABLE_SHADING; if (dev->settings.scan_method == ScanMethod::TRANSPARENCY) { session.params.flags |= ScanFlag::USE_XPA; @@ -2110,6 +2118,8 @@ static void ad_fe_offset_calibration(Genesys_Device* dev, const Genesys_Sensor& session.params.scan_method = dev->settings.scan_method; session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; session.params.color_filter = ColorFilter::RED; + session.params.contrast_adjustment = dev->settings.contrast; + session.params.brightness_adjustment = dev->settings.brightness; session.params.flags = ScanFlag::DISABLE_SHADING; if (dev->settings.scan_method == ScanMethod::TRANSPARENCY) { session.params.flags |= ScanFlag::USE_XPA; @@ -2222,6 +2232,8 @@ void CommandSetGl646::offset_calibration(Genesys_Device* dev, const Genesys_Sens session.params.scan_method = dev->settings.scan_method; session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; session.params.color_filter = ColorFilter::RED; + session.params.contrast_adjustment = dev->settings.contrast; + session.params.brightness_adjustment = dev->settings.brightness; session.params.flags = ScanFlag::DISABLE_SHADING; if (dev->settings.scan_method == ScanMethod::TRANSPARENCY) { session.params.flags |= ScanFlag::USE_XPA; @@ -2373,6 +2385,8 @@ void CommandSetGl646::coarse_gain_calibration(Genesys_Device* dev, const Genesys session.params.scan_method = dev->settings.scan_method; session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; session.params.color_filter = ColorFilter::RED; + session.params.contrast_adjustment = dev->settings.contrast; + session.params.brightness_adjustment = dev->settings.brightness; session.params.flags = ScanFlag::DISABLE_SHADING; if (dev->settings.scan_method == ScanMethod::TRANSPARENCY) { session.params.flags |= ScanFlag::USE_XPA; @@ -2485,6 +2499,8 @@ void CommandSetGl646::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Se session.params.scan_method = dev->settings.scan_method; session.params.scan_mode = ScanColorMode::GRAY; session.params.color_filter = ColorFilter::RED; + session.params.contrast_adjustment = 0; + session.params.brightness_adjustment = 0; session.params.flags = ScanFlag::DISABLE_SHADING | ScanFlag::DISABLE_GAMMA; if (dev->settings.scan_method == ScanMethod::TRANSPARENCY) { @@ -2966,6 +2982,8 @@ ScanSession CommandSetGl646::calculate_scan_session(const Genesys_Device* dev, session.params.scan_method = dev->settings.scan_method; session.params.scan_mode = settings.scan_mode; session.params.color_filter = settings.color_filter; + session.params.contrast_adjustment = settings.contrast; + session.params.brightness_adjustment = settings.brightness; session.params.flags = ScanFlag::AUTO_GO_HOME; if (settings.scan_method == ScanMethod::TRANSPARENCY) { session.params.flags |= ScanFlag::USE_XPA; diff --git a/backend/genesys/gl841.cpp b/backend/genesys/gl841.cpp index 62e0e9d27..92623464e 100644 --- a/backend/genesys/gl841.cpp +++ b/backend/genesys/gl841.cpp @@ -149,15 +149,6 @@ gl841_init_registers (Genesys_Device * dev) dev->reg.init_reg(0x13, 0x00); // SENSOR_DEF dev->reg.init_reg(0x14, 0x00); // SENSOR_DEF dev->reg.init_reg(0x15, 0x00); // SENSOR_DEF - if (dev->model->model_id == ModelId::CANON_LIDE_80) { - dev->reg.init_reg(0x10, 0x40); - dev->reg.init_reg(0x11, 0x00); - dev->reg.init_reg(0x12, 0x40); - dev->reg.init_reg(0x13, 0x00); - dev->reg.init_reg(0x14, 0x40); - dev->reg.init_reg(0x15, 0x00); - } - dev->reg.init_reg(0x16, 0x00); // SENSOR_DEF, overwritten in scanner_setup_sensor() below dev->reg.init_reg(0x17, 0x00); // SENSOR_DEF, overwritten in scanner_setup_sensor() below dev->reg.init_reg(0x18, 0x00); // SENSOR_DEF, overwritten in scanner_setup_sensor() below @@ -184,36 +175,21 @@ gl841_init_registers (Genesys_Device * dev) dev->reg.init_reg(0x27, 0x00); dev->reg.init_reg(0x29, 0xff); - dev->reg.init_reg(0x2c, 0x00); - dev->reg.init_reg(0x2d, 0x00); - if (dev->model->model_id == ModelId::CANON_LIDE_80) { - dev->reg.init_reg(0x2c, sensor.full_resolution >> 8); - dev->reg.init_reg(0x2d, sensor.full_resolution & 0xff); - } + dev->reg.init_reg(0x2c, 0x02); // DPISET: overwritten during scanner setup + dev->reg.init_reg(0x2d, 0x58); // DPISET: overwritten during scanner setup dev->reg.init_reg(0x2e, 0x80); dev->reg.init_reg(0x2f, 0x80); - dev->reg.init_reg(0x30, 0x00); - dev->reg.init_reg(0x31, 0x00); - dev->reg.init_reg(0x32, 0x00); - dev->reg.init_reg(0x33, 0x00); - dev->reg.init_reg(0x34, 0x00); - dev->reg.init_reg(0x35, 0x00); - dev->reg.init_reg(0x36, 0x00); - dev->reg.init_reg(0x37, 0x00); - dev->reg.init_reg(0x38, 0x4f); - dev->reg.init_reg(0x39, 0xc1); - if (dev->model->model_id == ModelId::CANON_LIDE_80) { - dev->reg.init_reg(0x31, 0x10); - dev->reg.init_reg(0x32, 0x15); - dev->reg.init_reg(0x33, 0x0e); - dev->reg.init_reg(0x34, 0x40); - dev->reg.init_reg(0x35, 0x00); - dev->reg.init_reg(0x36, 0x2a); - dev->reg.init_reg(0x37, 0x30); - dev->reg.init_reg(0x38, 0x2a); - dev->reg.init_reg(0x39, 0xf8); - } + dev->reg.init_reg(0x30, 0x00); // STRPIXEL: overwritten during scanner setup + dev->reg.init_reg(0x31, 0x00); // STRPIXEL: overwritten during scanner setup + dev->reg.init_reg(0x32, 0x00); // ENDPIXEL: overwritten during scanner setup + dev->reg.init_reg(0x33, 0x00); // ENDPIXEL: overwritten during scanner setup + dev->reg.init_reg(0x34, 0x00); // DUMMY: overwritten during scanner setup + dev->reg.init_reg(0x35, 0x00); // MAXWD: overwritten during scanner setup + dev->reg.init_reg(0x36, 0x00); // MAXWD: overwritten during scanner setup + dev->reg.init_reg(0x37, 0x00); // MAXWD: overwritten during scanner setup + dev->reg.init_reg(0x38, 0x4f); // LPERIOD: overwritten during scanner setup + dev->reg.init_reg(0x39, 0xc1); // LPERIOD: overwritten during scanner setup dev->reg.init_reg(0x3d, 0x00); dev->reg.init_reg(0x3e, 0x00); @@ -330,11 +306,6 @@ gl841_init_registers (Genesys_Device * dev) dev->interface->write_0x8c(0x10, 0x94); dev->interface->write_register(0x09, 0x10); - - // FIXME: the following code originally changed 0x6b, but due to bug the 0x6c register was - // effectively changed. The current behavior matches the old code, but should probably be fixed. - dev->reg.find_reg(0x6c).value |= REG_0x6B_GPO18; - dev->reg.find_reg(0x6c).value &= ~REG_0x6B_GPO17; } } @@ -541,7 +512,6 @@ static void gl841_init_motor_regs_feed(Genesys_Device* dev, const Genesys_Sensor { DBG_HELPER_ARGS(dbg, "feed_steps=%d, flags=%x", feed_steps, static_cast(flags)); unsigned step_multiplier = 2; - int use_fast_fed = 0; unsigned int feedl; /*number of scan lines to add in a scan_lines line*/ @@ -572,10 +542,6 @@ static void gl841_init_motor_regs_feed(Genesys_Device* dev, const Genesys_Sensor // BUG: fast table is counted in base_ydpi / 4 feedl = feed_steps - fast_table.table.size() * 2; - use_fast_fed = 1; - if (has_flag(dev->model->flags, ModelFlag::DISABLE_FAST_FEEDING)) { - use_fast_fed = false; - } reg->set8(0x3d, (feedl >> 16) & 0xf); reg->set8(0x3e, (feedl >> 8) & 0xff); @@ -590,10 +556,6 @@ static void gl841_init_motor_regs_feed(Genesys_Device* dev, const Genesys_Sensor reg->find_reg(0x02).value &= ~0x80; /*NOT_HOME OFF*/ reg->find_reg(0x02).value |= REG_0x02_MTRPWR; - - if (use_fast_fed) - reg->find_reg(0x02).value |= 0x08; - else reg->find_reg(0x02).value &= ~0x08; if (has_flag(flags, ScanFlag::AUTO_GO_HOME)) { @@ -640,9 +602,6 @@ static void gl841_init_motor_regs_scan(Genesys_Device* dev, const Genesys_Sensor unsigned step_multiplier = 2; - int use_fast_fed = 0; - unsigned int fast_time; - unsigned int slow_time; unsigned int feedl; unsigned int min_restep = 0x20; @@ -679,54 +638,11 @@ static void gl841_init_motor_regs_scan(Genesys_Device* dev, const Genesys_Sensor fast_table.slice_steps(max_fast_slope_steps_count, step_multiplier); } - /* fast fed special cases handling */ - if (dev->model->gpio_id == GpioId::XP300 - || dev->model->gpio_id == GpioId::DP685) - { - /* quirk: looks like at least this scanner is unable to use - 2-feed mode */ - use_fast_fed = 0; - } - else if (feed_steps < fast_table.table.size() * 2 + - (slow_table.table.size() >> static_cast(motor_profile.step_type))) - { - use_fast_fed = 0; - DBG(DBG_info, "%s: feed too short, slow move forced.\n", __func__); - } else { -/* for deciding whether we should use fast mode we need to check how long we - need for (fast)accelerating, moving, decelerating, (TODO: stopping?) - (slow)accelerating again versus (slow)accelerating and moving. we need - fast and slow tables here. -*/ -/*NOTE: scan_exposure_time is per scan_yres*/ -/*NOTE: fast_exposure is per base_ydpi/4*/ -/*we use full steps as base unit here*/ - fast_time = - (fast_table.table.back() << static_cast(fast_profile->step_type)) / 4 * - (feed_steps - fast_table.table.size()*2 - - (slow_table.table.size() >> static_cast(motor_profile.step_type))) - + fast_table.pixeltime_sum() * 2 + slow_table.pixeltime_sum(); - slow_time = - (scan_exposure_time * scan_yres) / dev->motor.base_ydpi * - (feed_steps - (slow_table.table.size() >> static_cast(motor_profile.step_type))) - + slow_table.pixeltime_sum(); - - use_fast_fed = fast_time < slow_time; - } - - if (has_flag(dev->model->flags, ModelFlag::DISABLE_FAST_FEEDING)) { - use_fast_fed = false; - } - - if (use_fast_fed) { - feedl = feed_steps - fast_table.table.size() * 2 - - (slow_table.table.size() >> static_cast(motor_profile.step_type)); - } else if ((feed_steps << static_cast(motor_profile.step_type)) < slow_table.table.size()) { + if ((feed_steps << static_cast(motor_profile.step_type)) < slow_table.table.size()) { feedl = 0; } else { feedl = (feed_steps << static_cast(motor_profile.step_type)) - slow_table.table.size(); } - DBG(DBG_info, "%s: Decided to use %s mode\n", __func__, use_fast_fed?"fast feed":"slow feed"); reg->set8(0x3d, (feedl >> 16) & 0xf); reg->set8(0x3e, (feedl >> 8) & 0xff); @@ -743,9 +659,6 @@ static void gl841_init_motor_regs_scan(Genesys_Device* dev, const Genesys_Sensor reg->find_reg(0x02).value &= ~REG_0x02_MTRREV; } - if (use_fast_fed) - reg->find_reg(0x02).value |= 0x08; - else reg->find_reg(0x02).value &= ~0x08; if (has_flag(flags, ScanFlag::AUTO_GO_HOME)) @@ -819,8 +732,6 @@ static void gl841_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens const ScanSession& session) { DBG_HELPER_ARGS(dbg, "exposure_time=%d", exposure_time); - uint16_t expavg, expr, expb, expg; - dev->cmd_set->set_fe(dev, sensor, AFE_SET); /* gpio part.*/ @@ -876,11 +787,7 @@ static void gl841_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens /* AFEMOD should depend on FESET, and we should set these * bits separately */ reg->find_reg(0x04).value &= ~(REG_0x04_FILTER | REG_0x04_AFEMOD); - if (has_flag(session.params.flags, ScanFlag::ENABLE_LEDADD)) { - reg->find_reg(0x04).value |= 0x10; /* no filter */ - } - else if (session.params.channels == 1) - { + if (session.params.channels == 1) { switch (session.params.color_filter) { case ColorFilter::RED: @@ -910,23 +817,6 @@ static void gl841_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens /* CIS scanners can do true gray by setting LEDADD */ reg->find_reg(0x87).value &= ~REG_0x87_LEDADD; - if (has_flag(session.params.flags, ScanFlag::ENABLE_LEDADD)) { - reg->find_reg(0x87).value |= REG_0x87_LEDADD; - expr = reg->get16(REG_EXPR); - expg = reg->get16(REG_EXPG); - expb = reg->get16(REG_EXPB); - - /* use minimal exposure for best image quality */ - expavg = expg; - if (expr < expg) - expavg = expr; - if (expb < expavg) - expavg = expb; - - dev->reg.set16(REG_EXPR, expavg); - dev->reg.set16(REG_EXPG, expavg); - dev->reg.set16(REG_EXPB, expavg); - } // enable gamma tables if (should_enable_gamma(session, sensor)) { @@ -946,27 +836,6 @@ static void gl841_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens reg->set8(0x34, sensor.dummy_pixel); } -static int -gl841_get_led_exposure(Genesys_Device * dev, const Genesys_Sensor& sensor) -{ - int d,r,g,b,m; - if (!dev->model->is_cis) - return 0; - d = dev->reg.find_reg(0x19).value; - - r = sensor.exposure.red; - g = sensor.exposure.green; - b = sensor.exposure.blue; - - m = r; - if (m < g) - m = g; - if (m < b) - m = b; - - return m + d; -} - /** @brief compute exposure time * Compute exposure time for the device and the given scan resolution */ @@ -975,9 +844,13 @@ static int gl841_exposure_time(Genesys_Device *dev, const Genesys_Sensor& sensor int start, int used_pixels) { -int led_exposure; - - led_exposure=gl841_get_led_exposure(dev, sensor); + int led_exposure = 0; + if (dev->model->is_cis) { + unsigned dummy = dev->reg.find_reg(0x19).value; + unsigned max_sensor_exposure = std::max({sensor.exposure.red, sensor.exposure.green, + sensor.exposure.blue}); + led_exposure = dummy + max_sensor_exposure; + } return sanei_genesys_exposure_time2(dev, profile, slope_dpi, start + used_pixels,/*+tgtime? currently done in sanei_genesys_exposure_time2 with tgtime = 32 pixel*/ led_exposure); @@ -1069,6 +942,9 @@ dummy \ scanned lines dev->total_bytes_read = 0; dev->total_bytes_to_read = session.output_line_bytes_requested * session.params.lines; + if (session.use_host_side_gray) { + dev->total_bytes_to_read /= 3; + } DBG(DBG_info, "%s: total bytes to send = %zu\n", __func__, dev->total_bytes_to_read); } @@ -1106,19 +982,6 @@ ScanSession CommandSetGl841::calculate_scan_session(const Genesys_Device* dev, start += dev->settings.tl_x; start = static_cast((start * dev->settings.xres) / MM_PER_INCH); - // we enable true gray for cis scanners only, and just when doing - // scan since color calibration is OK for this mode - ScanFlag flags = ScanFlag::NONE; - - // true gray (led add for cis scanners) - if (dev->model->is_cis && dev->settings.true_gray && - dev->settings.scan_mode != ScanColorMode::COLOR_SINGLE_PASS && - dev->model->sensor_id != SensorId::CIS_CANON_LIDE_80) - { - // on Lide 80 the LEDADD bit results in only red LED array being lit - flags |= ScanFlag::ENABLE_LEDADD; - } - ScanSession session; session.params.xres = dev->settings.xres; session.params.yres = dev->settings.yres; @@ -1132,7 +995,9 @@ ScanSession CommandSetGl841::calculate_scan_session(const Genesys_Device* dev, session.params.scan_method = dev->settings.scan_method; session.params.scan_mode = dev->settings.scan_mode; session.params.color_filter = dev->settings.color_filter; - session.params.flags = flags; + session.params.contrast_adjustment = dev->settings.contrast; + session.params.brightness_adjustment = dev->settings.brightness; + session.params.flags = ScanFlag::NONE; compute_session(dev, session, sensor); return session; @@ -1613,6 +1478,8 @@ void CommandSetGl841::init_regs_for_shading(Genesys_Device* dev, const Genesys_S session.params.scan_method = dev->settings.scan_method; session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; session.params.color_filter = dev->settings.color_filter; + session.params.contrast_adjustment = dev->settings.contrast; + session.params.brightness_adjustment = dev->settings.brightness; session.params.flags = ScanFlag::DISABLE_SHADING | ScanFlag::DISABLE_GAMMA; compute_session(dev, session, calib_sensor); @@ -1690,6 +1557,8 @@ static void ad_fe_offset_calibration(Genesys_Device* dev, const Genesys_Sensor& session.params.scan_method = dev->settings.scan_method; session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; session.params.color_filter = dev->settings.color_filter; + session.params.contrast_adjustment = dev->settings.contrast; + session.params.brightness_adjustment = dev->settings.brightness; session.params.flags = ScanFlag::DISABLE_SHADING | ScanFlag::DISABLE_GAMMA | ScanFlag::SINGLE_LINE | @@ -1760,14 +1629,10 @@ static void ad_fe_offset_calibration(Genesys_Device* dev, const Genesys_Sensor& turn++; } while ((top-bottom)>1 && turn < 100); - // FIXME: don't overwrite the calibrated values - dev->frontend.set_offset(0, 0); - dev->frontend.set_offset(1, 0); - dev->frontend.set_offset(2, 0); - DBG(DBG_info, "%s: offset=(%d,%d,%d)\n", __func__, - dev->frontend.get_offset(0), - dev->frontend.get_offset(1), - dev->frontend.get_offset(2)); + DBG(DBG_info, "%s: offset=(%d,%d,%d)\n", __func__, + dev->frontend.get_offset(0), + dev->frontend.get_offset(1), + dev->frontend.get_offset(2)); } /* this function does the offset calibration by scanning one line of the calibration @@ -1811,6 +1676,8 @@ void CommandSetGl841::offset_calibration(Genesys_Device* dev, const Genesys_Sens session.params.scan_method = dev->settings.scan_method; session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; session.params.color_filter = dev->settings.color_filter; + session.params.contrast_adjustment = dev->settings.contrast; + session.params.brightness_adjustment = dev->settings.brightness; session.params.flags = ScanFlag::DISABLE_SHADING | ScanFlag::DISABLE_GAMMA | ScanFlag::SINGLE_LINE | @@ -2160,6 +2027,8 @@ void CommandSetGl841::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Se session.params.scan_method = dev->settings.scan_method; session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; session.params.color_filter = dev->settings.color_filter; + session.params.contrast_adjustment = 0; + session.params.brightness_adjustment = 0; session.params.flags = flags; compute_session(dev, session, sensor); diff --git a/backend/genesys/gl842.cpp b/backend/genesys/gl842.cpp index 9d3da67e1..2ad58d4e9 100644 --- a/backend/genesys/gl842.cpp +++ b/backend/genesys/gl842.cpp @@ -629,6 +629,8 @@ ScanSession CommandSetGl842::calculate_scan_session(const Genesys_Device* dev, session.params.scan_method = settings.scan_method; session.params.scan_mode = settings.scan_mode; session.params.color_filter = settings.color_filter; + session.params.contrast_adjustment = settings.contrast; + session.params.brightness_adjustment = settings.brightness; session.params.flags = flags; compute_session(dev, session, sensor); @@ -823,6 +825,8 @@ void CommandSetGl842::init_regs_for_shading(Genesys_Device* dev, const Genesys_S session.params.scan_method = dev->settings.scan_method; session.params.scan_mode = dev->settings.scan_mode; session.params.color_filter = dev->settings.color_filter; + session.params.contrast_adjustment = dev->settings.contrast; + session.params.brightness_adjustment = dev->settings.brightness; session.params.flags = flags; compute_session(dev, session, calib_sensor); @@ -916,6 +920,8 @@ void CommandSetGl842::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Se session.params.scan_method = dev->settings.scan_method; session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; session.params.color_filter = dev->settings.color_filter; + session.params.contrast_adjustment = 0; + session.params.brightness_adjustment = 0; session.params.flags = flags; compute_session(dev, session, calib_sensor); diff --git a/backend/genesys/gl843.cpp b/backend/genesys/gl843.cpp index f63f67545..86a08cac9 100644 --- a/backend/genesys/gl843.cpp +++ b/backend/genesys/gl843.cpp @@ -1122,6 +1122,8 @@ ScanSession CommandSetGl843::calculate_scan_session(const Genesys_Device* dev, session.params.scan_method = settings.scan_method; session.params.scan_mode = settings.scan_mode; session.params.color_filter = settings.color_filter; + session.params.contrast_adjustment = settings.contrast; + session.params.brightness_adjustment = settings.brightness; session.params.flags = flags; compute_session(dev, session, sensor); @@ -1433,6 +1435,8 @@ void CommandSetGl843::init_regs_for_shading(Genesys_Device* dev, const Genesys_S session.params.scan_method = dev->settings.scan_method; session.params.scan_mode = dev->settings.scan_mode; session.params.color_filter = dev->settings.color_filter; + session.params.contrast_adjustment = dev->settings.contrast; + session.params.brightness_adjustment = dev->settings.brightness; session.params.flags = flags; compute_session(dev, session, calib_sensor); @@ -1536,6 +1540,8 @@ void CommandSetGl843::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Se session.params.scan_method = dev->settings.scan_method; session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; session.params.color_filter = dev->settings.color_filter; + session.params.contrast_adjustment = 0; + session.params.brightness_adjustment = 0; session.params.flags = flags; compute_session(dev, session, calib_sensor); diff --git a/backend/genesys/gl846.cpp b/backend/genesys/gl846.cpp index c8907b26c..ee820928b 100644 --- a/backend/genesys/gl846.cpp +++ b/backend/genesys/gl846.cpp @@ -374,25 +374,13 @@ static void gl846_init_motor_regs_scan(Genesys_Device* dev, unsigned step_multiplier = gl846_get_step_multiplier(reg); - bool use_fast_fed = false; - if (dev->settings.yres == 4444 && feed_steps > 100 && !has_flag(flags, ScanFlag::FEEDING)) { - use_fast_fed = true; - } - if (has_flag(dev->model->flags, ModelFlag::DISABLE_FAST_FEEDING)) { - use_fast_fed = false; - } - reg->set24(REG_LINCNT, scan_lines); reg->set8(REG_0x02, 0); sanei_genesys_set_motor_power(*reg, true); std::uint8_t reg02 = reg->get8(REG_0x02); - if (use_fast_fed) { - reg02 |= REG_0x02_FASTFED; - } else { - reg02 &= ~REG_0x02_FASTFED; - } + reg02 &= ~REG_0x02_FASTFED; if (has_flag(flags, ScanFlag::AUTO_GO_HOME)) { reg02 |= REG_0x02_AGOHOME | REG_0x02_NOTHOME; @@ -446,18 +434,11 @@ static void gl846_init_motor_regs_scan(Genesys_Device* dev, unsigned feedl = feed_steps; unsigned dist = 0; - if (use_fast_fed) { - feedl <<= static_cast(fast_profile->step_type); - dist = (scan_table.table.size() + 2 * fast_table.table.size()); - // TODO read and decode REG_0xAB - dist += (reg->get8(0x5e) & 31); - dist += reg->get8(REG_FEDCNT); - } else { - feedl <<= static_cast(motor_profile.step_type); - dist = scan_table.table.size(); - if (has_flag(flags, ScanFlag::FEEDING)) { - dist *= 2; - } + + feedl <<= static_cast(motor_profile.step_type); + dist = scan_table.table.size(); + if (has_flag(flags, ScanFlag::FEEDING)) { + dist *= 2; } // check for overflow @@ -513,7 +494,7 @@ static void gl846_init_motor_regs_scan(Genesys_Device* dev, reg->set8(REG_BWDSTEP, min_restep); std::uint32_t z1, z2; - sanei_genesys_calculate_zmod(use_fast_fed, + sanei_genesys_calculate_zmod(false, scan_exposure_time * ccdlmt * tgtime, scan_table.table, scan_table.table.size(), @@ -759,6 +740,8 @@ ScanSession CommandSetGl846::calculate_scan_session(const Genesys_Device* dev, session.params.scan_method = settings.scan_method; session.params.scan_mode = settings.scan_mode; session.params.color_filter = settings.color_filter; + session.params.contrast_adjustment = settings.contrast; + session.params.brightness_adjustment = settings.brightness; // backtracking isn't handled well, so don't enable it session.params.flags = flags; @@ -882,6 +865,8 @@ void CommandSetGl846::init_regs_for_shading(Genesys_Device* dev, const Genesys_S session.params.scan_method = dev->settings.scan_method; session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; session.params.color_filter = dev->settings.color_filter; + session.params.contrast_adjustment = dev->settings.contrast; + session.params.brightness_adjustment = dev->settings.brightness; session.params.flags = flags; compute_session(dev, session, calib_sensor); diff --git a/backend/genesys/gl847.cpp b/backend/genesys/gl847.cpp index 91ac4ebce..18b1e42bd 100644 --- a/backend/genesys/gl847.cpp +++ b/backend/genesys/gl847.cpp @@ -338,25 +338,13 @@ static void gl847_init_motor_regs_scan(Genesys_Device* dev, unsigned step_multiplier = gl847_get_step_multiplier (reg); - bool use_fast_fed = false; - if (dev->settings.yres == 4444 && feed_steps > 100 && !has_flag(flags, ScanFlag::FEEDING)) { - use_fast_fed = true; - } - if (has_flag(dev->model->flags, ModelFlag::DISABLE_FAST_FEEDING)) { - use_fast_fed = false; - } - reg->set24(REG_LINCNT, scan_lines); reg->set8(REG_0x02, 0); sanei_genesys_set_motor_power(*reg, true); std::uint8_t reg02 = reg->get8(REG_0x02); - if (use_fast_fed) { - reg02 |= REG_0x02_FASTFED; - } else { - reg02 &= ~REG_0x02_FASTFED; - } + reg02 &= ~REG_0x02_FASTFED; if (has_flag(flags, ScanFlag::AUTO_GO_HOME)) { reg02 |= REG_0x02_AGOHOME | REG_0x02_NOTHOME; @@ -402,19 +390,11 @@ static void gl847_init_motor_regs_scan(Genesys_Device* dev, // correct move distance by acceleration and deceleration amounts unsigned feedl = feed_steps; unsigned dist = 0; - if (use_fast_fed) - { - feedl <<= static_cast(fast_step_type); - dist = (scan_table.table.size() + 2 * fast_table.table.size()); - // TODO read and decode REG_0xAB - dist += (reg->get8(0x5e) & 31); - dist += reg->get8(REG_FEDCNT); - } else { - feedl <<= static_cast(motor_profile.step_type); - dist = scan_table.table.size(); - if (has_flag(flags, ScanFlag::FEEDING)) { - dist *= 2; - } + + feedl <<= static_cast(motor_profile.step_type); + dist = scan_table.table.size(); + if (has_flag(flags, ScanFlag::FEEDING)) { + dist *= 2; } // check for overflow @@ -456,7 +436,7 @@ static void gl847_init_motor_regs_scan(Genesys_Device* dev, reg->set8(REG_BWDSTEP, min_restep); std::uint32_t z1, z2; - sanei_genesys_calculate_zmod(use_fast_fed, + sanei_genesys_calculate_zmod(false, scan_exposure_time * ccdlmt * tgtime, scan_table.table, scan_table.table.size(), @@ -735,6 +715,8 @@ ScanSession CommandSetGl847::calculate_scan_session(const Genesys_Device* dev, session.params.scan_method = settings.scan_method; session.params.scan_mode = settings.scan_mode; session.params.color_filter = settings.color_filter; + session.params.contrast_adjustment = settings.contrast; + session.params.brightness_adjustment = settings.brightness; session.params.flags = flags; compute_session(dev, session, sensor); @@ -900,6 +882,8 @@ void CommandSetGl847::init_regs_for_shading(Genesys_Device* dev, const Genesys_S session.params.scan_method = dev->settings.scan_method; session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; session.params.color_filter = dev->settings.color_filter; + session.params.contrast_adjustment = dev->settings.contrast; + session.params.brightness_adjustment = dev->settings.brightness; session.params.flags = flags; compute_session(dev, session, calib_sensor); diff --git a/backend/genesys/image_pipeline.cpp b/backend/genesys/image_pipeline.cpp index 14e2f8de6..6c178eda7 100644 --- a/backend/genesys/image_pipeline.cpp +++ b/backend/genesys/image_pipeline.cpp @@ -304,8 +304,8 @@ bool ImagePipelineNodeInvert::get_next_row_data(std::uint8_t* out_data) return got_data; } -ImagePipelineNodeMergeMonoLines::ImagePipelineNodeMergeMonoLines(ImagePipelineNode& source, - ColorOrder color_order) : +ImagePipelineNodeMergeMonoLinesToColor::ImagePipelineNodeMergeMonoLinesToColor( + ImagePipelineNode& source, ColorOrder color_order) : source_(source), buffer_(source_.get_row_bytes()) { @@ -314,7 +314,7 @@ ImagePipelineNodeMergeMonoLines::ImagePipelineNodeMergeMonoLines(ImagePipelineNo output_format_ = get_output_format(source_.get_format(), color_order); } -bool ImagePipelineNodeMergeMonoLines::get_next_row_data(std::uint8_t* out_data) +bool ImagePipelineNodeMergeMonoLinesToColor::get_next_row_data(std::uint8_t* out_data) { bool got_data = true; @@ -341,8 +341,8 @@ bool ImagePipelineNodeMergeMonoLines::get_next_row_data(std::uint8_t* out_data) return got_data; } -PixelFormat ImagePipelineNodeMergeMonoLines::get_output_format(PixelFormat input_format, - ColorOrder order) +PixelFormat ImagePipelineNodeMergeMonoLinesToColor::get_output_format(PixelFormat input_format, + ColorOrder order) { switch (input_format) { case PixelFormat::I1: { @@ -417,6 +417,75 @@ PixelFormat ImagePipelineNodeSplitMonoLines::get_output_format(PixelFormat input throw SaneException("Unsupported input format %d", static_cast(input_format)); } + +ImagePipelineNodeMergeColorToGray::ImagePipelineNodeMergeColorToGray(ImagePipelineNode& source) : + source_(source) +{ + + output_format_ = get_output_format(source_.get_format()); + float red_mult = 0.2125f; + float green_mult = 0.7154f; + float blue_mult = 0.0721f; + + switch (get_pixel_format_color_order(source_.get_format())) { + case ColorOrder::RGB: { + ch0_mult_ = red_mult; + ch1_mult_ = green_mult; + ch2_mult_ = blue_mult; + break; + } + case ColorOrder::BGR: { + ch0_mult_ = blue_mult; + ch1_mult_ = green_mult; + ch2_mult_ = red_mult; + break; + } + case ColorOrder::GBR: { + ch0_mult_ = green_mult; + ch1_mult_ = blue_mult; + ch2_mult_ = red_mult; + break; + } + default: + throw SaneException("Unknown color order"); + } + temp_buffer_.resize(source_.get_row_bytes()); +} + +bool ImagePipelineNodeMergeColorToGray::get_next_row_data(std::uint8_t* out_data) +{ + auto* src_data = temp_buffer_.data(); + + bool got_data = source_.get_next_row_data(src_data); + + auto src_format = source_.get_format(); + + for (std::size_t x = 0, width = get_width(); x < width; ++x) { + std::uint16_t ch0 = get_raw_channel_from_row(src_data, x, 0, src_format); + std::uint16_t ch1 = get_raw_channel_from_row(src_data, x, 1, src_format); + std::uint16_t ch2 = get_raw_channel_from_row(src_data, x, 2, src_format); + float mono = ch0 * ch0_mult_ + ch1 * ch1_mult_ + ch2 * ch2_mult_; + set_raw_channel_to_row(out_data, x, 0, static_cast(mono), output_format_); + } + return got_data; +} + +PixelFormat ImagePipelineNodeMergeColorToGray::get_output_format(PixelFormat input_format) +{ + switch (input_format) { + case PixelFormat::RGB111: + return PixelFormat::I1; + case PixelFormat::RGB888: + case PixelFormat::BGR888: + return PixelFormat::I8; + case PixelFormat::RGB161616: + case PixelFormat::BGR161616: + return PixelFormat::I16; + default: break; + } + throw SaneException("Unsupported format %d", static_cast(input_format)); +} + ImagePipelineNodeComponentShiftLines::ImagePipelineNodeComponentShiftLines( ImagePipelineNode& source, unsigned shift_r, unsigned shift_g, unsigned shift_b) : source_(source), diff --git a/backend/genesys/image_pipeline.h b/backend/genesys/image_pipeline.h index 3632b36eb..8e4915514 100644 --- a/backend/genesys/image_pipeline.h +++ b/backend/genesys/image_pipeline.h @@ -295,11 +295,11 @@ private: }; // A pipeline node that merges 3 mono lines into a color channel -class ImagePipelineNodeMergeMonoLines : public ImagePipelineNode +class ImagePipelineNodeMergeMonoLinesToColor : public ImagePipelineNode { public: - ImagePipelineNodeMergeMonoLines(ImagePipelineNode& source, - ColorOrder color_order); + ImagePipelineNodeMergeMonoLinesToColor(ImagePipelineNode& source, + ColorOrder color_order); std::size_t get_width() const override { return source_.get_width(); } std::size_t get_height() const override { return source_.get_height() / 3; } @@ -342,6 +342,33 @@ private: unsigned next_channel_ = 0; }; + +// A pipeline node that merges 3 mono lines into a gray channel +class ImagePipelineNodeMergeColorToGray : public ImagePipelineNode +{ +public: + ImagePipelineNodeMergeColorToGray(ImagePipelineNode& source); + + std::size_t get_width() const override { return source_.get_width(); } + std::size_t get_height() const override { return source_.get_height(); } + PixelFormat get_format() const override { return output_format_; } + + bool eof() const override { return source_.eof(); } + + bool get_next_row_data(std::uint8_t* out_data) override; + +private: + static PixelFormat get_output_format(PixelFormat input_format); + + ImagePipelineNode& source_; + PixelFormat output_format_ = PixelFormat::UNKNOWN; + float ch0_mult_ = 0; + float ch1_mult_ = 0; + float ch2_mult_ = 0; + + std::vector temp_buffer_; +}; + // A pipeline node that shifts colors across lines by the given offsets class ImagePipelineNodeComponentShiftLines : public ImagePipelineNode { diff --git a/backend/genesys/low.cpp b/backend/genesys/low.cpp index ddd2c88f6..fb4660b40 100644 --- a/backend/genesys/low.cpp +++ b/backend/genesys/low.cpp @@ -442,7 +442,11 @@ Image read_unshuffled_image_from_scanner(Genesys_Device* dev, const ScanSession& } if (dev->model->is_cis && session.params.channels == 3) { - pipeline.push_node(dev->model->line_mode_color_order); + pipeline.push_node(dev->model->line_mode_color_order); + } + + if (session.use_host_side_gray) { + pipeline.push_node(); } if (pipeline.get_output_format() == PixelFormat::BGR888) { @@ -540,7 +544,7 @@ Image read_shuffled_image_from_scanner(Genesys_Device* dev, const ScanSession& s } if (dev->model->is_cis && session.params.channels == 3) { - pipeline.push_node(dev->model->line_mode_color_order); + pipeline.push_node(dev->model->line_mode_color_order); } if (pipeline.get_output_format() == PixelFormat::BGR888) { @@ -638,11 +642,16 @@ bool should_enable_gamma(const ScanSession& session, const Genesys_Sensor& senso if ((session.params.flags & ScanFlag::DISABLE_GAMMA) != ScanFlag::NONE) { return false; } + if (session.params.depth == 16) { + return false; + } + if (session.params.brightness_adjustment != 0 || session.params.contrast_adjustment != 0) { + return true; + } + if (sensor.gamma[0] == 1.0f || sensor.gamma[1] == 1.0f || sensor.gamma[2] == 1.0f) { return false; } - if (session.params.depth == 16) - return false; return true; } @@ -949,6 +958,14 @@ void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Se s.output_startx = static_cast( static_cast(s.params.startx) + sensor.output_pixel_offset); + if (has_flag(dev->model->flags, ModelFlag::HOST_SIDE_GRAY) && s.params.channels == 1 && + s.params.color_filter == ColorFilter::NONE) + { + s.use_host_side_gray = true; + s.params.channels = 3; + s.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; + } + s.stagger_x = sensor.stagger_x; s.stagger_y = sensor.stagger_y; @@ -1114,7 +1131,8 @@ void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Se dev->model->asic_type == AsicType::GL845 || dev->model->asic_type == AsicType::GL846) { - s.enable_ledadd = (s.params.channels == 1 && dev->model->is_cis && dev->settings.true_gray); + s.enable_ledadd = (s.params.channels == 1 && dev->model->is_cis && + s.params.color_filter == ColorFilter::NONE); } s.use_host_side_calib = sensor.use_host_side_calib; @@ -1212,7 +1230,7 @@ ImagePipelineStack build_image_pipeline(const Genesys_Device& dev, const ScanSes } if (dev.model->is_cis && session.params.channels == 3) { - pipeline.push_node(dev.model->line_mode_color_order); + pipeline.push_node(dev.model->line_mode_color_order); if (log_image_data) { pipeline.push_node(debug_prefix + "_4_after_merge_mono.tiff"); @@ -1274,6 +1292,14 @@ ImagePipelineStack build_image_pipeline(const Genesys_Device& dev, const ScanSes } } + if (session.use_host_side_gray) { + pipeline.push_node(); + + if (log_image_data) { + pipeline.push_node(debug_prefix + "_10_after_nogray.tiff"); + } + } + if (pipeline.get_output_width() != session.params.get_requested_pixels()) { pipeline.push_node(session.params.get_requested_pixels()); } diff --git a/backend/genesys/settings.cpp b/backend/genesys/settings.cpp index 7f6479815..8eb06c819 100644 --- a/backend/genesys/settings.cpp +++ b/backend/genesys/settings.cpp @@ -86,6 +86,8 @@ std::ostream& operator<<(std::ostream& out, const SetupParams& params) << " channels: " << params.channels << '\n' << " scan_mode: " << params.scan_mode << '\n' << " color_filter: " << params.color_filter << '\n' + << " contrast_adjustment: " << params.contrast_adjustment << '\n' + << " brightness_adjustment: " << params.brightness_adjustment << '\n' << " flags: " << params.flags << '\n' << "}"; return out; @@ -127,7 +129,8 @@ bool ScanSession::operator==(const ScanSession& other) const shading_pixel_offset == other.shading_pixel_offset && buffer_size_read == other.buffer_size_read && enable_ledadd == other.enable_ledadd && - use_host_side_calib == other.use_host_side_calib; + use_host_side_calib == other.use_host_side_calib && + use_host_side_gray == other.use_host_side_gray; } std::ostream& operator<<(std::ostream& out, const ScanSession& session) @@ -164,6 +167,7 @@ std::ostream& operator<<(std::ostream& out, const ScanSession& session) << " buffer_size_read: " << session.buffer_size_read << '\n' << " enable_ledadd: " << session.enable_ledadd << '\n' << " use_host_side_calib: " << session.use_host_side_calib << '\n' + << " use_host_side_gray: " << session.use_host_side_gray << '\n' << " params: " << format_indent_braced_list(4, session.params) << '\n' << "}"; return out; diff --git a/backend/genesys/settings.h b/backend/genesys/settings.h index 4c834fa72..f92854442 100644 --- a/backend/genesys/settings.h +++ b/backend/genesys/settings.h @@ -76,9 +76,6 @@ struct Genesys_Settings ColorFilter color_filter = ColorFilter::NONE; - // true if scan is true gray, false if monochrome scan - int true_gray = 0; - // value for contrast enhancement in the [-100..100] range int contrast = 0; @@ -102,6 +99,7 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Settings& settings); struct SetupParams { static constexpr unsigned NOT_SET = std::numeric_limits::max(); + static constexpr unsigned NOT_SET_I = std::numeric_limits::max(); // resolution in x direction unsigned xres = NOT_SET; @@ -136,6 +134,10 @@ struct SetupParams { ColorFilter color_filter = static_cast(NOT_SET); + // the values for contrast and brightness adjustment in the range of [-100..100] + int contrast_adjustment = NOT_SET_I; + int brightness_adjustment = NOT_SET_I; + ScanFlag flags = ScanFlag::NONE; unsigned get_requested_pixels() const @@ -152,7 +154,8 @@ struct SetupParams { pixels == NOT_SET || lines == NOT_SET ||depth == NOT_SET || channels == NOT_SET || scan_method == static_cast(NOT_SET) || scan_mode == static_cast(NOT_SET) || - color_filter == static_cast(NOT_SET)) + color_filter == static_cast(NOT_SET) || + contrast_adjustment == NOT_SET_I || brightness_adjustment == NOT_SET_I) { throw std::runtime_error("SetupParams are not valid"); } @@ -172,6 +175,8 @@ struct SetupParams { scan_method == other.scan_method && scan_mode == other.scan_mode && color_filter == other.color_filter && + contrast_adjustment == other.contrast_adjustment && + brightness_adjustment == other.brightness_adjustment && flags == other.flags; } }; @@ -193,6 +198,8 @@ void serialize(Stream& str, SetupParams& x) serialize(str, x.scan_method); serialize(str, x.scan_mode); serialize(str, x.color_filter); + serialize(str, x.contrast_adjustment); + serialize(str, x.brightness_adjustment); serialize(str, x.flags); } @@ -317,6 +324,9 @@ struct ScanSession { // whether calibration should be performed host-side bool use_host_side_calib = false; + // whether gray scanning should be performed host-side (scan as color and merge to gray) + bool use_host_side_gray = false; + void assert_computed() const { if (!computed) { @@ -368,6 +378,7 @@ void serialize(Stream& str, ScanSession& x) serialize(str, x.buffer_size_read); serialize(str, x.enable_ledadd); serialize(str, x.use_host_side_calib); + serialize(str, x.use_host_side_gray); } std::ostream& operator<<(std::ostream& out, const SANE_Parameters& params); diff --git a/backend/genesys/tables_model.cpp b/backend/genesys/tables_model.cpp index acd933a89..7d77c6152 100644 --- a/backend/genesys/tables_model.cpp +++ b/backend/genesys/tables_model.cpp @@ -191,6 +191,7 @@ void genesys_init_usb_device_tables() model.gpio_id = GpioId::CANON_LIDE_35; model.motor_id = MotorId::CANON_LIDE_35; model.flags = ModelFlag::DARK_WHITE_CALIBRATION | + ModelFlag::HOST_SIDE_GRAY | ModelFlag::CUSTOM_GAMMA; model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_FILE_SW | @@ -1110,6 +1111,7 @@ void genesys_init_usb_device_tables() model.gpio_id = GpioId::CANON_LIDE_35; model.motor_id = MotorId::CANON_LIDE_60; model.flags = ModelFlag::DARK_WHITE_CALIBRATION | + ModelFlag::HOST_SIDE_GRAY | ModelFlag::CUSTOM_GAMMA; model.buttons = GENESYS_HAS_COPY_SW | @@ -1165,6 +1167,7 @@ void genesys_init_usb_device_tables() model.gpio_id = GpioId::CANON_LIDE_80; model.motor_id = MotorId::CANON_LIDE_80; model.flags = ModelFlag::DARK_WHITE_CALIBRATION | + ModelFlag::HOST_SIDE_GRAY | ModelFlag::CUSTOM_GAMMA; model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_FILE_SW | diff --git a/backend/genesys/tables_sensor.cpp b/backend/genesys/tables_sensor.cpp index d79a018ac..4f1753842 100644 --- a/backend/genesys/tables_sensor.cpp +++ b/backend/genesys/tables_sensor.cpp @@ -471,8 +471,8 @@ void genesys_init_sensor_tables() sensor.register_dpihw = 1200; sensor.black_pixels = 87; sensor.dummy_pixel = 87; - sensor.fau_gain_white_ref = 0; - sensor.gain_white_ref = 0; + sensor.fau_gain_white_ref = 100; + sensor.gain_white_ref = 100; sensor.exposure = { 0x0400, 0x0400, 0x0400 }; sensor.custom_regs = { { 0x16, 0x00 }, { 0x17, 0x02 }, { 0x18, 0x00 }, { 0x19, 0x50 }, @@ -519,8 +519,8 @@ void genesys_init_sensor_tables() sensor.register_dpihw = 1200; sensor.black_pixels = 87; sensor.dummy_pixel = 87; - sensor.fau_gain_white_ref = 0; - sensor.gain_white_ref = 0; + sensor.fau_gain_white_ref = 100; + sensor.gain_white_ref = 100; sensor.exposure = { 0x0400, 0x0400, 0x0400 }; sensor.custom_regs = { { 0x16, 0x00 }, { 0x17, 0x01 }, { 0x18, 0x00 }, { 0x19, 0x50 }, diff --git a/testsuite/backend/genesys/tests_image_pipeline.cpp b/testsuite/backend/genesys/tests_image_pipeline.cpp index 8edeff8ab..8c46e8d89 100644 --- a/testsuite/backend/genesys/tests_image_pipeline.cpp +++ b/testsuite/backend/genesys/tests_image_pipeline.cpp @@ -468,7 +468,7 @@ void test_node_invert_1_bits() ASSERT_EQ(out_data, expected_data); } -void test_node_merge_mono_lines() +void test_node_merge_mono_lines_to_color() { using Data = std::vector; @@ -481,7 +481,7 @@ void test_node_merge_mono_lines() ImagePipelineStack stack; stack.push_first_node(8, 3, PixelFormat::I8, std::move(in_data)); - stack.push_node(ColorOrder::RGB); + stack.push_node(ColorOrder::RGB); ASSERT_EQ(stack.get_output_width(), 8u); ASSERT_EQ(stack.get_output_height(), 1u); @@ -500,6 +500,37 @@ void test_node_merge_mono_lines() ASSERT_EQ(out_data, expected_data); } +void test_node_merge_color_to_gray() +{ + using Data = std::vector; + + Data in_data = { + 0x10, 0x20, 0x30, 0x11, 0x21, 0x31, + 0x12, 0x22, 0x32, 0x13, 0x23, 0x33, + 0x14, 0x24, 0x34, 0x15, 0x25, 0x35, + 0x16, 0x26, 0x36, 0x17, 0x27, 0x37, + }; + + ImagePipelineStack stack; + stack.push_first_node(8, 1, PixelFormat::RGB888, + std::move(in_data)); + stack.push_node(); + + ASSERT_EQ(stack.get_output_width(), 8u); + ASSERT_EQ(stack.get_output_height(), 1u); + ASSERT_EQ(stack.get_output_row_bytes(), 8u); + ASSERT_EQ(stack.get_output_format(), PixelFormat::I8); + + auto out_data = stack.get_all_data(); + + Data expected_data = { + 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24 + }; + + ASSERT_EQ(out_data, expected_data); +} + + void test_node_split_mono_lines() { using Data = std::vector; @@ -937,7 +968,8 @@ void test_image_pipeline() test_node_invert_16_bits(); test_node_invert_8_bits(); test_node_invert_1_bits(); - test_node_merge_mono_lines(); + test_node_merge_mono_lines_to_color(); + test_node_merge_color_to_gray(); test_node_split_mono_lines(); test_node_component_shift_lines(); test_node_pixel_shift_columns_no_switch();