mirror of
https://github.com/openharmony/third_party_backends.git
synced 2026-07-19 19:44:20 -04:00
Merge branch 'genesys-gl841-fixes' into 'master'
genesys: Various fixes for GL841 scanners Closes #357 See merge request sane-project/backends!673
This commit is contained in:
@@ -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,
|
||||
|
||||
|
||||
+16
-109
@@ -673,9 +673,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);
|
||||
}
|
||||
|
||||
@@ -1884,7 +1884,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<std::uint16_t> values;
|
||||
@@ -1900,18 +1901,6 @@ void scanner_coarse_gain_calibration(Genesys_Device& dev, const Genesys_Sensor&
|
||||
curr_output = static_cast<float>(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();
|
||||
@@ -2009,7 +1998,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)
|
||||
@@ -2017,14 +2007,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;
|
||||
@@ -2045,27 +2030,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] = {};
|
||||
|
||||
@@ -2101,16 +2073,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");
|
||||
@@ -2121,15 +2083,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);
|
||||
@@ -2155,57 +2115,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]) {
|
||||
@@ -2238,7 +2149,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) {
|
||||
@@ -4370,12 +4283,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;
|
||||
|
||||
@@ -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;
|
||||
std::uint32_t z1, z2;
|
||||
@@ -467,9 +466,6 @@ static void gl124_init_motor_regs_scan(Genesys_Device* dev,
|
||||
feed_steps, static_cast<unsigned>(scan_mode),
|
||||
static_cast<unsigned>(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 */
|
||||
std::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(),
|
||||
|
||||
@@ -606,7 +606,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;
|
||||
|
||||
+29
-169
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -598,7 +569,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<unsigned>(flags));
|
||||
unsigned step_multiplier = 2;
|
||||
int use_fast_fed = 0;
|
||||
unsigned int feedl;
|
||||
/*number of scan lines to add in a scan_lines line*/
|
||||
|
||||
@@ -629,10 +599,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);
|
||||
@@ -647,10 +613,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)) {
|
||||
@@ -697,9 +659,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;
|
||||
|
||||
@@ -736,54 +695,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<unsigned>(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<unsigned>(fast_profile->step_type)) / 4 *
|
||||
(feed_steps - fast_table.table.size()*2 -
|
||||
(slow_table.table.size() >> static_cast<unsigned>(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<unsigned>(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<unsigned>(motor_profile.step_type));
|
||||
} else if ((feed_steps << static_cast<unsigned>(motor_profile.step_type)) < slow_table.table.size()) {
|
||||
if ((feed_steps << static_cast<unsigned>(motor_profile.step_type)) < slow_table.table.size()) {
|
||||
feedl = 0;
|
||||
} else {
|
||||
feedl = (feed_steps << static_cast<unsigned>(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);
|
||||
@@ -800,9 +716,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))
|
||||
@@ -876,7 +789,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);
|
||||
std::uint16_t expavg, expr, expb, expg;
|
||||
|
||||
dev->cmd_set->set_fe(dev, sensor, AFE_SET);
|
||||
|
||||
@@ -933,11 +845,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:
|
||||
@@ -967,23 +875,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)) {
|
||||
@@ -1003,27 +894,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
|
||||
*/
|
||||
@@ -1032,9 +902,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);
|
||||
@@ -1126,6 +1000,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);
|
||||
}
|
||||
@@ -1163,19 +1040,6 @@ ScanSession CommandSetGl841::calculate_scan_session(const Genesys_Device* dev,
|
||||
start += dev->settings.tl_x;
|
||||
start = static_cast<float>((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;
|
||||
@@ -1191,7 +1055,7 @@ ScanSession CommandSetGl841::calculate_scan_session(const Genesys_Device* dev,
|
||||
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;
|
||||
session.params.flags = ScanFlag::NONE;
|
||||
compute_session(dev, session, sensor);
|
||||
|
||||
return session;
|
||||
@@ -1823,14 +1687,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
|
||||
|
||||
@@ -375,25 +375,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;
|
||||
@@ -447,18 +435,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<unsigned>(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<unsigned>(motor_profile.step_type);
|
||||
dist = scan_table.table.size();
|
||||
if (has_flag(flags, ScanFlag::FEEDING)) {
|
||||
dist *= 2;
|
||||
}
|
||||
|
||||
feedl <<= static_cast<unsigned>(motor_profile.step_type);
|
||||
dist = scan_table.table.size();
|
||||
if (has_flag(flags, ScanFlag::FEEDING)) {
|
||||
dist *= 2;
|
||||
}
|
||||
|
||||
// check for overflow
|
||||
@@ -514,7 +495,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(),
|
||||
|
||||
@@ -339,25 +339,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;
|
||||
@@ -403,19 +391,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<unsigned>(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<unsigned>(motor_profile.step_type);
|
||||
dist = scan_table.table.size();
|
||||
if (has_flag(flags, ScanFlag::FEEDING)) {
|
||||
dist *= 2;
|
||||
}
|
||||
|
||||
feedl <<= static_cast<unsigned>(motor_profile.step_type);
|
||||
dist = scan_table.table.size();
|
||||
if (has_flag(flags, ScanFlag::FEEDING)) {
|
||||
dist *= 2;
|
||||
}
|
||||
|
||||
// check for overflow
|
||||
@@ -457,7 +437,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(),
|
||||
|
||||
@@ -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<unsigned>(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<std::uint16_t>(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<unsigned>(input_format));
|
||||
}
|
||||
|
||||
ImagePipelineNodeComponentShiftLines::ImagePipelineNodeComponentShiftLines(
|
||||
ImagePipelineNode& source, unsigned shift_r, unsigned shift_g, unsigned shift_b) :
|
||||
source_(source),
|
||||
|
||||
@@ -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<std::uint8_t> temp_buffer_;
|
||||
};
|
||||
|
||||
// A pipeline node that shifts colors across lines by the given offsets
|
||||
class ImagePipelineNodeComponentShiftLines : public ImagePipelineNode
|
||||
{
|
||||
|
||||
+25
-4
@@ -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<ImagePipelineNodeMergeMonoLines>(dev->model->line_mode_color_order);
|
||||
pipeline.push_node<ImagePipelineNodeMergeMonoLinesToColor>(dev->model->line_mode_color_order);
|
||||
}
|
||||
|
||||
if (session.use_host_side_gray) {
|
||||
pipeline.push_node<ImagePipelineNodeMergeColorToGray>();
|
||||
}
|
||||
|
||||
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<ImagePipelineNodeMergeMonoLines>(dev->model->line_mode_color_order);
|
||||
pipeline.push_node<ImagePipelineNodeMergeMonoLinesToColor>(dev->model->line_mode_color_order);
|
||||
}
|
||||
|
||||
if (pipeline.get_output_format() == PixelFormat::BGR888) {
|
||||
@@ -954,6 +958,14 @@ void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Se
|
||||
s.output_startx = static_cast<unsigned>(
|
||||
static_cast<int>(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;
|
||||
|
||||
@@ -1119,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;
|
||||
@@ -1217,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<ImagePipelineNodeMergeMonoLines>(dev.model->line_mode_color_order);
|
||||
pipeline.push_node<ImagePipelineNodeMergeMonoLinesToColor>(dev.model->line_mode_color_order);
|
||||
|
||||
if (log_image_data) {
|
||||
pipeline.push_node<ImagePipelineNodeDebug>(debug_prefix + "_4_after_merge_mono.tiff");
|
||||
@@ -1279,6 +1292,14 @@ ImagePipelineStack build_image_pipeline(const Genesys_Device& dev, const ScanSes
|
||||
}
|
||||
}
|
||||
|
||||
if (session.use_host_side_gray) {
|
||||
pipeline.push_node<ImagePipelineNodeMergeColorToGray>();
|
||||
|
||||
if (log_image_data) {
|
||||
pipeline.push_node<ImagePipelineNodeDebug>(debug_prefix + "_10_after_nogray.tiff");
|
||||
}
|
||||
}
|
||||
|
||||
if (pipeline.get_output_width() != session.params.get_requested_pixels()) {
|
||||
pipeline.push_node<ImagePipelineNodeScaleRows>(session.params.get_requested_pixels());
|
||||
}
|
||||
|
||||
@@ -129,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)
|
||||
@@ -166,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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -327,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) {
|
||||
@@ -378,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);
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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<std::uint8_t>;
|
||||
|
||||
@@ -481,7 +481,7 @@ void test_node_merge_mono_lines()
|
||||
ImagePipelineStack stack;
|
||||
stack.push_first_node<ImagePipelineNodeArraySource>(8, 3, PixelFormat::I8,
|
||||
std::move(in_data));
|
||||
stack.push_node<ImagePipelineNodeMergeMonoLines>(ColorOrder::RGB);
|
||||
stack.push_node<ImagePipelineNodeMergeMonoLinesToColor>(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<std::uint8_t>;
|
||||
|
||||
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<ImagePipelineNodeArraySource>(8, 1, PixelFormat::RGB888,
|
||||
std::move(in_data));
|
||||
stack.push_node<ImagePipelineNodeMergeColorToGray>();
|
||||
|
||||
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<std::uint8_t>;
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user