kopia lustrzana https://gitlab.com/sane-project/backends
genesys: Deduplicate strip searching functionality
rodzic
5854246e88
commit
d8f09656b2
|
@ -132,11 +132,6 @@ public:
|
||||||
|
|
||||||
/// eject document from scanner
|
/// eject document from scanner
|
||||||
virtual void eject_document(Genesys_Device* dev) const = 0;
|
virtual void eject_document(Genesys_Device* dev) const = 0;
|
||||||
/**
|
|
||||||
* search for an black or white area in forward or reverse
|
|
||||||
* direction */
|
|
||||||
virtual void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
|
||||||
bool forward, bool black) const = 0;
|
|
||||||
|
|
||||||
/// move scanning head to transparency adapter
|
/// move scanning head to transparency adapter
|
||||||
virtual void move_to_ta(Genesys_Device* dev) const = 0;
|
virtual void move_to_ta(Genesys_Device* dev) const = 0;
|
||||||
|
|
|
@ -1071,6 +1071,208 @@ void scanner_move_back_home_ta(Genesys_Device& dev)
|
||||||
throw SaneException("Timeout waiting for XPA lamp to park");
|
throw SaneException("Timeout waiting for XPA lamp to park");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace gl841 {
|
||||||
|
void gl841_stop_action(Genesys_Device* dev);
|
||||||
|
} // namespace gl841
|
||||||
|
|
||||||
|
void scanner_search_strip(Genesys_Device& dev, bool forward, bool black)
|
||||||
|
{
|
||||||
|
DBG_HELPER_ARGS(dbg, "%s %s", black ? "black" : "white", forward ? "forward" : "reverse");
|
||||||
|
|
||||||
|
if (dev.model->asic_type == AsicType::GL841 && !black && forward) {
|
||||||
|
dev.frontend.set_gain(0, 0xff);
|
||||||
|
dev.frontend.set_gain(1, 0xff);
|
||||||
|
dev.frontend.set_gain(2, 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set up for a gray scan at lowest dpi
|
||||||
|
const auto& resolution_settings = dev.model->get_resolution_settings(dev.settings.scan_method);
|
||||||
|
unsigned dpi = resolution_settings.get_min_resolution_x();
|
||||||
|
unsigned channels = 1;
|
||||||
|
|
||||||
|
auto& sensor = sanei_genesys_find_sensor(&dev, dpi, channels, dev.settings.scan_method);
|
||||||
|
dev.cmd_set->set_fe(&dev, sensor, AFE_SET);
|
||||||
|
scanner_stop_action(dev);
|
||||||
|
|
||||||
|
|
||||||
|
// shading calibration is done with dev.motor.base_ydpi
|
||||||
|
unsigned lines = static_cast<unsigned>(dev.model->y_size_calib_mm * dpi / MM_PER_INCH);
|
||||||
|
if (dev.model->asic_type == AsicType::GL841) {
|
||||||
|
lines = 10; // TODO: use dev.model->search_lines
|
||||||
|
lines = static_cast<unsigned>((lines * dpi) / MM_PER_INCH);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned pixels = dev.model->x_size_calib_mm * dpi / MM_PER_INCH;
|
||||||
|
|
||||||
|
dev.set_head_pos_zero(ScanHeadId::PRIMARY);
|
||||||
|
|
||||||
|
unsigned length = 20;
|
||||||
|
if (dev.model->asic_type == AsicType::GL841) {
|
||||||
|
// 20 cm max length for calibration sheet
|
||||||
|
length = static_cast<unsigned>(((200 * dpi) / MM_PER_INCH) / lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto local_reg = dev.reg;
|
||||||
|
|
||||||
|
ScanSession session;
|
||||||
|
session.params.xres = dpi;
|
||||||
|
session.params.yres = dpi;
|
||||||
|
session.params.startx = 0;
|
||||||
|
session.params.starty = 0;
|
||||||
|
session.params.pixels = pixels;
|
||||||
|
session.params.lines = lines;
|
||||||
|
session.params.depth = 8;
|
||||||
|
session.params.channels = channels;
|
||||||
|
session.params.scan_method = dev.settings.scan_method;
|
||||||
|
session.params.scan_mode = ScanColorMode::GRAY;
|
||||||
|
session.params.color_filter = ColorFilter::RED;
|
||||||
|
session.params.flags = ScanFlag::DISABLE_SHADING |
|
||||||
|
ScanFlag::DISABLE_GAMMA;
|
||||||
|
if (dev.model->asic_type != AsicType::GL841 && !forward) {
|
||||||
|
session.params.flags |= ScanFlag::REVERSE;
|
||||||
|
}
|
||||||
|
compute_session(&dev, session, sensor);
|
||||||
|
|
||||||
|
dev.cmd_set->init_regs_for_scan_session(&dev, sensor, &local_reg, session);
|
||||||
|
|
||||||
|
dev.interface->write_registers(local_reg);
|
||||||
|
|
||||||
|
dev.cmd_set->begin_scan(&dev, sensor, &local_reg, true);
|
||||||
|
|
||||||
|
if (is_testing_mode()) {
|
||||||
|
dev.interface->test_checkpoint("search_strip");
|
||||||
|
if (dev.model->asic_type == AsicType::GL841) {
|
||||||
|
gl841::gl841_stop_action(&dev);
|
||||||
|
} else {
|
||||||
|
scanner_stop_action(dev);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_until_buffer_non_empty(&dev);
|
||||||
|
|
||||||
|
// now we're on target, we can read data
|
||||||
|
auto image = read_unshuffled_image_from_scanner(&dev, session, session.output_total_bytes);
|
||||||
|
|
||||||
|
if (dev.model->asic_type == AsicType::GL841) {
|
||||||
|
gl841::gl841_stop_action(&dev);
|
||||||
|
} else {
|
||||||
|
scanner_stop_action(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned pass = 0;
|
||||||
|
if (DBG_LEVEL >= DBG_data) {
|
||||||
|
char title[80];
|
||||||
|
std::sprintf(title, "gl_search_strip_%s_%s%02d.pnm",
|
||||||
|
black ? "black" : "white", forward ? "fwd" : "bwd", pass);
|
||||||
|
sanei_genesys_write_pnm_file(title, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
// loop until strip is found or maximum pass number done
|
||||||
|
bool found = false;
|
||||||
|
while (pass < length && !found) {
|
||||||
|
dev.interface->write_registers(local_reg);
|
||||||
|
|
||||||
|
// now start scan
|
||||||
|
dev.cmd_set->begin_scan(&dev, sensor, &local_reg, true);
|
||||||
|
|
||||||
|
wait_until_buffer_non_empty(&dev);
|
||||||
|
|
||||||
|
// now we're on target, we can read data
|
||||||
|
image = read_unshuffled_image_from_scanner(&dev, session, session.output_total_bytes);
|
||||||
|
|
||||||
|
scanner_stop_action(dev);
|
||||||
|
|
||||||
|
if (DBG_LEVEL >= DBG_data) {
|
||||||
|
char title[80];
|
||||||
|
std::sprintf(title, "gl_search_strip_%s_%s%02d.pnm",
|
||||||
|
black ? "black" : "white",
|
||||||
|
forward ? "fwd" : "bwd", static_cast<int>(pass));
|
||||||
|
sanei_genesys_write_pnm_file(title, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned white_level = 90;
|
||||||
|
unsigned black_level = 60;
|
||||||
|
|
||||||
|
std::size_t count = 0;
|
||||||
|
// Search data to find black strip
|
||||||
|
// When searching forward, we only need one line of the searched color since we
|
||||||
|
// will scan forward. But when doing backward search, we need all the area of the ame color
|
||||||
|
if (forward) {
|
||||||
|
|
||||||
|
for (std::size_t y = 0; y < image.get_height() && !found; y++) {
|
||||||
|
count = 0;
|
||||||
|
|
||||||
|
// count of white/black pixels depending on the color searched
|
||||||
|
for (std::size_t x = 0; x < image.get_width(); x++) {
|
||||||
|
|
||||||
|
// when searching for black, detect white pixels
|
||||||
|
if (black && image.get_raw_channel(x, y, 0) > white_level) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// when searching for white, detect black pixels
|
||||||
|
if (!black && image.get_raw_channel(x, y, 0) < black_level) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// at end of line, if count >= 3%, line is not fully of the desired color
|
||||||
|
// so we must go to next line of the buffer */
|
||||||
|
// count*100/pixels < 3
|
||||||
|
|
||||||
|
auto found_percentage = (count * 100 / image.get_width());
|
||||||
|
if (found_percentage < 3) {
|
||||||
|
found = 1;
|
||||||
|
DBG(DBG_data, "%s: strip found forward during pass %d at line %zu\n", __func__,
|
||||||
|
pass, y);
|
||||||
|
} else {
|
||||||
|
DBG(DBG_data, "%s: pixels=%zu, count=%zu (%zu%%)\n", __func__,
|
||||||
|
image.get_width(), count, found_percentage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* since calibration scans are done forward, we need the whole area
|
||||||
|
to be of the required color when searching backward
|
||||||
|
*/
|
||||||
|
count = 0;
|
||||||
|
for (std::size_t y = 0; y < image.get_height(); y++) {
|
||||||
|
// count of white/black pixels depending on the color searched
|
||||||
|
for (std::size_t x = 0; x < image.get_width(); x++) {
|
||||||
|
// when searching for black, detect white pixels
|
||||||
|
if (black && image.get_raw_channel(x, y, 0) > white_level) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
// when searching for white, detect black pixels
|
||||||
|
if (!black && image.get_raw_channel(x, y, 0) < black_level) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// at end of area, if count >= 3%, area is not fully of the desired color
|
||||||
|
// so we must go to next buffer
|
||||||
|
auto found_percentage = count * 100 / (image.get_width() * image.get_height());
|
||||||
|
if (found_percentage < 3) {
|
||||||
|
found = 1;
|
||||||
|
DBG(DBG_data, "%s: strip found backward during pass %d \n", __func__, pass);
|
||||||
|
} else {
|
||||||
|
DBG(DBG_data, "%s: pixels=%zu, count=%zu (%zu%%)\n", __func__, image.get_width(),
|
||||||
|
count, found_percentage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pass++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
DBG(DBG_info, "%s: %s strip found\n", __func__, black ? "black" : "white");
|
||||||
|
} else {
|
||||||
|
throw SaneException(SANE_STATUS_UNSUPPORTED, "%s strip not found",
|
||||||
|
black ? "black" : "white");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void sanei_genesys_calculate_zmod(bool two_table,
|
void sanei_genesys_calculate_zmod(bool two_table,
|
||||||
uint32_t exposure_time,
|
uint32_t exposure_time,
|
||||||
const std::vector<uint16_t>& slope_table,
|
const std::vector<uint16_t>& slope_table,
|
||||||
|
@ -2514,7 +2716,7 @@ static void genesys_sheetfed_calibration(Genesys_Device* dev, Genesys_Sensor& se
|
||||||
|
|
||||||
/* go to a white area */
|
/* go to a white area */
|
||||||
try {
|
try {
|
||||||
dev->cmd_set->search_strip(dev, sensor, forward, false);
|
scanner_search_strip(*dev, forward, false);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
catch_all_exceptions(__func__, [&](){ dev->cmd_set->eject_document(dev); });
|
catch_all_exceptions(__func__, [&](){ dev->cmd_set->eject_document(dev); });
|
||||||
throw;
|
throw;
|
||||||
|
@ -2534,7 +2736,7 @@ static void genesys_sheetfed_calibration(Genesys_Device* dev, Genesys_Sensor& se
|
||||||
if (has_flag(dev->model->flags, ModelFlag::DARK_CALIBRATION)) {
|
if (has_flag(dev->model->flags, ModelFlag::DARK_CALIBRATION)) {
|
||||||
// seek black/white reverse/forward
|
// seek black/white reverse/forward
|
||||||
try {
|
try {
|
||||||
dev->cmd_set->search_strip(dev, sensor, forward, true);
|
scanner_search_strip(*dev, forward, true);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
catch_all_exceptions(__func__, [&](){ dev->cmd_set->eject_document(dev); });
|
catch_all_exceptions(__func__, [&](){ dev->cmd_set->eject_document(dev); });
|
||||||
throw;
|
throw;
|
||||||
|
@ -2552,7 +2754,7 @@ static void genesys_sheetfed_calibration(Genesys_Device* dev, Genesys_Sensor& se
|
||||||
|
|
||||||
/* go to a white area */
|
/* go to a white area */
|
||||||
try {
|
try {
|
||||||
dev->cmd_set->search_strip(dev, sensor, forward, false);
|
scanner_search_strip(*dev, forward, false);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
catch_all_exceptions(__func__, [&](){ dev->cmd_set->eject_document(dev); });
|
catch_all_exceptions(__func__, [&](){ dev->cmd_set->eject_document(dev); });
|
||||||
throw;
|
throw;
|
||||||
|
|
|
@ -2036,16 +2036,6 @@ void CommandSetGl124::eject_document(Genesys_Device* dev) const
|
||||||
throw SaneException("not implemented");
|
throw SaneException("not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandSetGl124::search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
|
||||||
bool forward, bool black) const
|
|
||||||
{
|
|
||||||
(void) dev;
|
|
||||||
(void) sensor;
|
|
||||||
(void) forward;
|
|
||||||
(void) black;
|
|
||||||
throw SaneException("not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
void CommandSetGl124::move_to_ta(Genesys_Device* dev) const
|
void CommandSetGl124::move_to_ta(Genesys_Device* dev) const
|
||||||
{
|
{
|
||||||
(void) dev;
|
(void) dev;
|
||||||
|
|
|
@ -171,9 +171,6 @@ public:
|
||||||
|
|
||||||
void eject_document(Genesys_Device* dev) const override;
|
void eject_document(Genesys_Device* dev) const override;
|
||||||
|
|
||||||
void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
|
||||||
bool forward, bool black) const override;
|
|
||||||
|
|
||||||
void move_to_ta(Genesys_Device* dev) const override;
|
void move_to_ta(Genesys_Device* dev) const override;
|
||||||
|
|
||||||
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
||||||
|
|
|
@ -3114,154 +3114,6 @@ static void write_control(Genesys_Device* dev, const Genesys_Sensor& sensor, int
|
||||||
dev->interface->write_buffer(0x3c, addr, control, 4);
|
dev->interface->write_buffer(0x3c, addr, control, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* search for a full width black or white strip.
|
|
||||||
* @param dev scanner device
|
|
||||||
* @param forward true if searching forward, false if searching backward
|
|
||||||
* @param black true if searching for a black strip, false for a white strip
|
|
||||||
*/
|
|
||||||
void CommandSetGl646::search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor, bool forward,
|
|
||||||
bool black) const
|
|
||||||
{
|
|
||||||
DBG_HELPER(dbg);
|
|
||||||
(void) sensor;
|
|
||||||
|
|
||||||
Genesys_Settings settings;
|
|
||||||
int res = get_closest_resolution(dev->model->sensor_id, 75, 1);
|
|
||||||
unsigned int pass, count, found, x, y;
|
|
||||||
char title[80];
|
|
||||||
|
|
||||||
const auto& calib_sensor = sanei_genesys_find_sensor(dev, res, 1, ScanMethod::FLATBED);
|
|
||||||
|
|
||||||
/* we set up for a lowest available resolution color grey scan, full width */
|
|
||||||
settings.scan_method = dev->model->default_method;
|
|
||||||
settings.scan_mode = ScanColorMode::GRAY;
|
|
||||||
settings.xres = res;
|
|
||||||
settings.yres = res;
|
|
||||||
settings.tl_x = 0;
|
|
||||||
settings.tl_y = 0;
|
|
||||||
settings.pixels = static_cast<unsigned>((dev->model->x_size * res) / MM_PER_INCH);
|
|
||||||
settings.pixels /= calib_sensor.get_ccd_size_divisor_for_dpi(res);
|
|
||||||
settings.requested_pixels = settings.pixels;
|
|
||||||
|
|
||||||
/* 15 mm at at time */
|
|
||||||
settings.lines = static_cast<unsigned>((15 * settings.yres) / MM_PER_INCH);
|
|
||||||
settings.depth = 8;
|
|
||||||
settings.color_filter = ColorFilter::RED;
|
|
||||||
|
|
||||||
settings.disable_interpolation = 0;
|
|
||||||
settings.threshold = 0;
|
|
||||||
|
|
||||||
/* signals if a strip of the given color has been found */
|
|
||||||
found = 0;
|
|
||||||
|
|
||||||
/* detection pass done */
|
|
||||||
pass = 0;
|
|
||||||
|
|
||||||
std::vector<uint8_t> data;
|
|
||||||
|
|
||||||
/* loop until strip is found or maximum pass number done */
|
|
||||||
while (pass < 20 && !found)
|
|
||||||
{
|
|
||||||
// scan a full width strip
|
|
||||||
simple_scan(dev, calib_sensor, settings, true, forward, false, data, "search_strip");
|
|
||||||
|
|
||||||
if (is_testing_mode()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DBG_LEVEL >= DBG_data)
|
|
||||||
{
|
|
||||||
std::sprintf(title, "gl646_search_strip_%s%02d.pnm", forward ? "fwd" : "bwd", pass);
|
|
||||||
sanei_genesys_write_pnm_file (title, data.data(), settings.depth, 1,
|
|
||||||
settings.pixels, settings.lines);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* search data to find black strip */
|
|
||||||
/* when searching forward, we only need one line of the searched color since we
|
|
||||||
* will scan forward. But when doing backward search, we need all the area of the
|
|
||||||
* same color */
|
|
||||||
if (forward)
|
|
||||||
{
|
|
||||||
for (y = 0; y < settings.lines && !found; y++)
|
|
||||||
{
|
|
||||||
count = 0;
|
|
||||||
/* count of white/black pixels depending on the color searched */
|
|
||||||
for (x = 0; x < settings.pixels; x++)
|
|
||||||
{
|
|
||||||
/* when searching for black, detect white pixels */
|
|
||||||
if (black && data[y * settings.pixels + x] > 90)
|
|
||||||
{
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
/* when searching for white, detect black pixels */
|
|
||||||
if (!black && data[y * settings.pixels + x] < 60)
|
|
||||||
{
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* at end of line, if count >= 3%, line is not fully of the desired color
|
|
||||||
* so we must go to next line of the buffer */
|
|
||||||
/* count*100/pixels < 3 */
|
|
||||||
if ((count * 100) / settings.pixels < 3)
|
|
||||||
{
|
|
||||||
found = 1;
|
|
||||||
DBG(DBG_data, "%s: strip found forward during pass %d at line %d\n", __func__,
|
|
||||||
pass, y);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DBG(DBG_data, "%s: pixels=%d, count=%d\n", __func__, settings.pixels, count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else /* since calibration scans are done forward, we need the whole area
|
|
||||||
to be of the required color when searching backward */
|
|
||||||
{
|
|
||||||
count = 0;
|
|
||||||
for (y = 0; y < settings.lines; y++)
|
|
||||||
{
|
|
||||||
/* count of white/black pixels depending on the color searched */
|
|
||||||
for (x = 0; x < settings.pixels; x++)
|
|
||||||
{
|
|
||||||
/* when searching for black, detect white pixels */
|
|
||||||
if (black && data[y * settings.pixels + x] > 60)
|
|
||||||
{
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
/* when searching for white, detect black pixels */
|
|
||||||
if (!black && data[y * settings.pixels + x] < 60)
|
|
||||||
{
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* at end of area, if count >= 3%, area is not fully of the desired color
|
|
||||||
* so we must go to next buffer */
|
|
||||||
if ((count * 100) / (settings.pixels * settings.lines) < 3)
|
|
||||||
{
|
|
||||||
found = 1;
|
|
||||||
DBG(DBG_data, "%s: strip found backward during pass %d \n", __func__, pass);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DBG(DBG_data, "%s: pixels=%d, count=%d\n", __func__, settings.pixels, count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pass++;
|
|
||||||
}
|
|
||||||
if (found)
|
|
||||||
{
|
|
||||||
DBG(DBG_info, "%s: strip found\n", __func__);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw SaneException(SANE_STATUS_UNSUPPORTED, "%s strip not found", black ? "black" : "white");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CommandSetGl646::wait_for_motor_stop(Genesys_Device* dev) const
|
void CommandSetGl646::wait_for_motor_stop(Genesys_Device* dev) const
|
||||||
{
|
{
|
||||||
(void) dev;
|
(void) dev;
|
||||||
|
|
|
@ -491,9 +491,6 @@ public:
|
||||||
|
|
||||||
void eject_document(Genesys_Device* dev) const override;
|
void eject_document(Genesys_Device* dev) const override;
|
||||||
|
|
||||||
void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
|
||||||
bool forward, bool black) const override;
|
|
||||||
|
|
||||||
void move_to_ta(Genesys_Device* dev) const override;
|
void move_to_ta(Genesys_Device* dev) const override;
|
||||||
|
|
||||||
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
||||||
|
|
|
@ -1819,7 +1819,7 @@ void CommandSetGl841::set_powersaving(Genesys_Device* dev, int delay /* in minut
|
||||||
dev->interface->write_registers(local_reg);
|
dev->interface->write_registers(local_reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gl841_stop_action(Genesys_Device* dev)
|
void gl841_stop_action(Genesys_Device* dev)
|
||||||
{
|
{
|
||||||
DBG_HELPER(dbg);
|
DBG_HELPER(dbg);
|
||||||
Genesys_Register_Set local_reg;
|
Genesys_Register_Set local_reg;
|
||||||
|
@ -3293,204 +3293,6 @@ void CommandSetGl841::update_hardware_sensors(Genesys_Scanner* s) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief search for a full width black or white strip.
|
|
||||||
* This function searches for a black or white stripe across the scanning area.
|
|
||||||
* When searching backward, the searched area must completely be of the desired
|
|
||||||
* color since this area will be used for calibration which scans forward.
|
|
||||||
* @param dev scanner device
|
|
||||||
* @param forward true if searching forward, false if searching backward
|
|
||||||
* @param black true if searching for a black strip, false for a white strip
|
|
||||||
*/
|
|
||||||
void CommandSetGl841::search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor, bool forward,
|
|
||||||
bool black) const
|
|
||||||
{
|
|
||||||
DBG_HELPER_ARGS(dbg, "%s %s", black ? "black" : "white", forward ? "forward" : "reverse");
|
|
||||||
unsigned lines, channels;
|
|
||||||
Genesys_Register_Set local_reg;
|
|
||||||
unsigned int pass, count, found, length;
|
|
||||||
char title[80];
|
|
||||||
GenesysRegister *r;
|
|
||||||
uint8_t white_level=90; /**< default white level to detect white dots */
|
|
||||||
uint8_t black_level=60; /**< default black level to detect black dots */
|
|
||||||
|
|
||||||
/* use maximum gain when doing forward white strip detection
|
|
||||||
* since we don't have calibrated the sensor yet */
|
|
||||||
if(!black && forward)
|
|
||||||
{
|
|
||||||
dev->frontend.set_gain(0, 0xff);
|
|
||||||
dev->frontend.set_gain(1, 0xff);
|
|
||||||
dev->frontend.set_gain(2, 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
dev->cmd_set->set_fe(dev, sensor, AFE_SET);
|
|
||||||
gl841_stop_action(dev);
|
|
||||||
|
|
||||||
// set up for a gray scan at lowest dpi
|
|
||||||
const auto& resolution_settings = dev->model->get_resolution_settings(dev->settings.scan_method);
|
|
||||||
unsigned dpi = resolution_settings.get_min_resolution_x();
|
|
||||||
channels = 1;
|
|
||||||
|
|
||||||
// shading calibation is done with dev->motor.base_ydpi
|
|
||||||
lines = 10; // TODO: use dev->model->search_lines
|
|
||||||
lines = static_cast<unsigned>((lines * dpi) / MM_PER_INCH);
|
|
||||||
|
|
||||||
/* 20 cm max length for calibration sheet */
|
|
||||||
length = static_cast<unsigned>(((200 * dpi) / MM_PER_INCH) / lines);
|
|
||||||
|
|
||||||
dev->set_head_pos_zero(ScanHeadId::PRIMARY);
|
|
||||||
|
|
||||||
local_reg = dev->reg;
|
|
||||||
|
|
||||||
ScanSession session;
|
|
||||||
session.params.xres = dpi;
|
|
||||||
session.params.yres = dpi;
|
|
||||||
session.params.startx = 0;
|
|
||||||
session.params.starty = 0;
|
|
||||||
session.params.pixels = dev->model->x_size_calib_mm * dpi / MM_PER_INCH;
|
|
||||||
session.params.lines = lines;
|
|
||||||
session.params.depth = 8;
|
|
||||||
session.params.channels = channels;
|
|
||||||
session.params.scan_method = dev->settings.scan_method;
|
|
||||||
session.params.scan_mode = ScanColorMode::GRAY;
|
|
||||||
session.params.color_filter = ColorFilter::RED;
|
|
||||||
session.params.flags = ScanFlag::DISABLE_SHADING | ScanFlag::DISABLE_GAMMA;
|
|
||||||
compute_session(dev, session, sensor);
|
|
||||||
|
|
||||||
init_regs_for_scan_session(dev, sensor, &local_reg, session);
|
|
||||||
|
|
||||||
/* set up for reverse or forward */
|
|
||||||
r = sanei_genesys_get_address(&local_reg, 0x02);
|
|
||||||
if (forward) {
|
|
||||||
r->value &= ~4;
|
|
||||||
} else {
|
|
||||||
r->value |= 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev->interface->write_registers(local_reg);
|
|
||||||
|
|
||||||
dev->cmd_set->begin_scan(dev, sensor, &local_reg, true);
|
|
||||||
|
|
||||||
if (is_testing_mode()) {
|
|
||||||
dev->interface->test_checkpoint("search_strip");
|
|
||||||
gl841_stop_action(dev);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// waits for valid data
|
|
||||||
wait_until_buffer_non_empty(dev);
|
|
||||||
|
|
||||||
// now we're on target, we can read data
|
|
||||||
auto image = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes);
|
|
||||||
|
|
||||||
gl841_stop_action(dev);
|
|
||||||
|
|
||||||
pass = 0;
|
|
||||||
if (DBG_LEVEL >= DBG_data) {
|
|
||||||
std::sprintf(title, "gl841_search_strip_%s_%s%02u.pnm", black ? "black" : "white",
|
|
||||||
forward ? "fwd" : "bwd", pass);
|
|
||||||
sanei_genesys_write_pnm_file(title, image);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* loop until strip is found or maximum pass number done */
|
|
||||||
found = 0;
|
|
||||||
while (pass < length && !found)
|
|
||||||
{
|
|
||||||
dev->interface->write_registers(local_reg);
|
|
||||||
|
|
||||||
//now start scan
|
|
||||||
dev->cmd_set->begin_scan(dev, sensor, &local_reg, true);
|
|
||||||
|
|
||||||
// waits for valid data
|
|
||||||
wait_until_buffer_non_empty(dev);
|
|
||||||
|
|
||||||
// now we're on target, we can read data
|
|
||||||
image = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes);
|
|
||||||
|
|
||||||
gl841_stop_action (dev);
|
|
||||||
|
|
||||||
if (DBG_LEVEL >= DBG_data) {
|
|
||||||
std::sprintf(title, "gl841_search_strip_%s_%s%02u.pnm",
|
|
||||||
black ? "black" : "white", forward ? "fwd" : "bwd", pass);
|
|
||||||
sanei_genesys_write_pnm_file(title, image);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* search data to find black strip */
|
|
||||||
/* when searching forward, we only need one line of the searched color since we
|
|
||||||
* will scan forward. But when doing backward search, we need all the area of the
|
|
||||||
* same color */
|
|
||||||
if (forward) {
|
|
||||||
for (std::size_t y = 0; y < image.get_height() && !found; y++) {
|
|
||||||
count = 0;
|
|
||||||
|
|
||||||
// count of white/black pixels depending on the color searched
|
|
||||||
for (std::size_t x = 0; x < image.get_width(); x++) {
|
|
||||||
|
|
||||||
// when searching for black, detect white pixels
|
|
||||||
if (black && image.get_raw_channel(x, y, 0) > white_level) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// when searching for white, detect black pixels
|
|
||||||
if (!black && image.get_raw_channel(x, y, 0) < black_level) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* at end of line, if count >= 3%, line is not fully of the desired color
|
|
||||||
* so we must go to next line of the buffer */
|
|
||||||
auto found_percentage = (count * 100 / image.get_width());
|
|
||||||
if (found_percentage < 3) {
|
|
||||||
found = 1;
|
|
||||||
DBG(DBG_data, "%s: strip found forward during pass %d at line %zu\n", __func__,
|
|
||||||
pass, y);
|
|
||||||
} else {
|
|
||||||
DBG(DBG_data, "%s: pixels=%zu, count=%d (%zu%%)\n", __func__, image.get_width(),
|
|
||||||
count, found_percentage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* since calibration scans are done forward, we need the whole area
|
|
||||||
to be of the required color when searching backward
|
|
||||||
*/
|
|
||||||
count = 0;
|
|
||||||
for (std::size_t y = 0; y < image.get_height(); y++) {
|
|
||||||
/* count of white/black pixels depending on the color searched */
|
|
||||||
for (std::size_t x = 0; x < image.get_width(); x++) {
|
|
||||||
// when searching for black, detect white pixels
|
|
||||||
if (black && image.get_raw_channel(x, y, 0) > white_level) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
// when searching for white, detect black pixels
|
|
||||||
if (!black && image.get_raw_channel(x, y, 0) < black_level) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* at end of area, if count >= 3%, area is not fully of the desired color
|
|
||||||
* so we must go to next buffer */
|
|
||||||
auto found_percentage = count * 100 / (image.get_width() * image.get_height());
|
|
||||||
if (found_percentage < 3) {
|
|
||||||
found = 1;
|
|
||||||
DBG(DBG_data, "%s: strip found backward during pass %d \n", __func__, pass);
|
|
||||||
} else {
|
|
||||||
DBG(DBG_data, "%s: pixels=%zu, count=%d (%zu%%)\n", __func__, image.get_width(), count,
|
|
||||||
found_percentage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pass++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found)
|
|
||||||
{
|
|
||||||
DBG(DBG_info, "%s: %s strip found\n", __func__, black ? "black" : "white");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw SaneException(SANE_STATUS_UNSUPPORTED, "%s strip not found", black ? "black" : "white");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send shading calibration data. The buffer is considered to always hold values
|
* Send shading calibration data. The buffer is considered to always hold values
|
||||||
* for all the channels.
|
* for all the channels.
|
||||||
|
|
|
@ -105,9 +105,6 @@ public:
|
||||||
|
|
||||||
void eject_document(Genesys_Device* dev) const override;
|
void eject_document(Genesys_Device* dev) const override;
|
||||||
|
|
||||||
void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
|
||||||
bool forward, bool black) const override;
|
|
||||||
|
|
||||||
void move_to_ta(Genesys_Device* dev) const override;
|
void move_to_ta(Genesys_Device* dev) const override;
|
||||||
|
|
||||||
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
||||||
|
|
|
@ -2405,198 +2405,6 @@ void CommandSetGl843::move_to_ta(Genesys_Device* dev) const
|
||||||
scanner_move(*dev, dev->model->default_method, feed, Direction::FORWARD);
|
scanner_move(*dev, dev->model->default_method, feed, Direction::FORWARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** @brief search for a full width black or white strip.
|
|
||||||
* This function searches for a black or white stripe across the scanning area.
|
|
||||||
* When searching backward, the searched area must completely be of the desired
|
|
||||||
* color since this area will be used for calibration which scans forward.
|
|
||||||
* @param dev scanner device
|
|
||||||
* @param forward true if searching forward, false if searching backward
|
|
||||||
* @param black true if searching for a black strip, false for a white strip
|
|
||||||
*/
|
|
||||||
void CommandSetGl843::search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
|
||||||
bool forward, bool black) const
|
|
||||||
{
|
|
||||||
DBG_HELPER_ARGS(dbg, "%s %s", black ? "black" : "white", forward ? "forward" : "reverse");
|
|
||||||
unsigned channels;
|
|
||||||
Genesys_Register_Set local_reg;
|
|
||||||
int dpi;
|
|
||||||
unsigned int pass, count, found, x, y;
|
|
||||||
|
|
||||||
dev->cmd_set->set_fe(dev, sensor, AFE_SET);
|
|
||||||
scanner_stop_action(*dev);
|
|
||||||
|
|
||||||
/* set up for a gray scan at lowest dpi */
|
|
||||||
dpi = sanei_genesys_get_lowest_dpi(dev);
|
|
||||||
channels = 1;
|
|
||||||
|
|
||||||
const auto& calib_sensor = sanei_genesys_find_sensor(dev, dpi, channels,
|
|
||||||
dev->settings.scan_method);
|
|
||||||
|
|
||||||
/* 10 MM */
|
|
||||||
/* lines = (10 * dpi) / MM_PER_INCH; */
|
|
||||||
/* shading calibation is done with dev->motor.base_ydpi */
|
|
||||||
unsigned lines = static_cast<unsigned>(dev->model->y_size_calib_mm * dpi / MM_PER_INCH);
|
|
||||||
unsigned pixels = dev->model->x_size_calib_mm * dpi / MM_PER_INCH;
|
|
||||||
|
|
||||||
dev->set_head_pos_zero(ScanHeadId::PRIMARY);
|
|
||||||
|
|
||||||
local_reg = dev->reg;
|
|
||||||
|
|
||||||
ScanSession session;
|
|
||||||
session.params.xres = dpi;
|
|
||||||
session.params.yres = dpi;
|
|
||||||
session.params.startx = 0;
|
|
||||||
session.params.starty = 0;
|
|
||||||
session.params.pixels = pixels;
|
|
||||||
session.params.lines = lines;
|
|
||||||
session.params.depth = 8;
|
|
||||||
session.params.channels = channels;
|
|
||||||
session.params.scan_method = dev->settings.scan_method;
|
|
||||||
session.params.scan_mode = ScanColorMode::GRAY;
|
|
||||||
session.params.color_filter = ColorFilter::RED;
|
|
||||||
session.params.flags = ScanFlag::DISABLE_SHADING | ScanFlag::DISABLE_SHADING;
|
|
||||||
if (!forward) {
|
|
||||||
session.params.flags = ScanFlag::REVERSE;
|
|
||||||
}
|
|
||||||
compute_session(dev, session, calib_sensor);
|
|
||||||
|
|
||||||
init_regs_for_scan_session(dev, calib_sensor, &local_reg, session);
|
|
||||||
|
|
||||||
dev->interface->write_registers(local_reg);
|
|
||||||
|
|
||||||
dev->cmd_set->begin_scan(dev, calib_sensor, &local_reg, true);
|
|
||||||
|
|
||||||
if (is_testing_mode()) {
|
|
||||||
dev->interface->test_checkpoint("search_strip");
|
|
||||||
scanner_stop_action(*dev);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wait_until_buffer_non_empty(dev);
|
|
||||||
|
|
||||||
// now we're on target, we can read data
|
|
||||||
auto data = read_unshuffled_image_from_scanner(dev, session,
|
|
||||||
session.output_total_bytes_raw);
|
|
||||||
|
|
||||||
scanner_stop_action(*dev);
|
|
||||||
|
|
||||||
pass = 0;
|
|
||||||
if (DBG_LEVEL >= DBG_data)
|
|
||||||
{
|
|
||||||
char fn[40];
|
|
||||||
std::snprintf(fn, 40, "gl843_search_strip_%s_%s%02d.pnm",
|
|
||||||
black ? "black" : "white", forward ? "fwd" : "bwd", pass);
|
|
||||||
sanei_genesys_write_pnm_file(fn, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* loop until strip is found or maximum pass number done */
|
|
||||||
found = 0;
|
|
||||||
while (pass < 20 && !found)
|
|
||||||
{
|
|
||||||
dev->interface->write_registers(local_reg);
|
|
||||||
|
|
||||||
// now start scan
|
|
||||||
dev->cmd_set->begin_scan(dev, calib_sensor, &local_reg, true);
|
|
||||||
|
|
||||||
wait_until_buffer_non_empty(dev);
|
|
||||||
|
|
||||||
// now we're on target, we can read data
|
|
||||||
data = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes_raw);
|
|
||||||
|
|
||||||
scanner_stop_action(*dev);
|
|
||||||
|
|
||||||
if (DBG_LEVEL >= DBG_data)
|
|
||||||
{
|
|
||||||
char fn[40];
|
|
||||||
std::snprintf(fn, 40, "gl843_search_strip_%s_%s%02d.pnm",
|
|
||||||
black ? "black" : "white", forward ? "fwd" : "bwd", pass);
|
|
||||||
sanei_genesys_write_pnm_file(fn, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* search data to find black strip */
|
|
||||||
/* when searching forward, we only need one line of the searched color since we
|
|
||||||
* will scan forward. But when doing backward search, we need all the area of the
|
|
||||||
* same color */
|
|
||||||
if (forward)
|
|
||||||
{
|
|
||||||
for (y = 0; y < lines && !found; y++)
|
|
||||||
{
|
|
||||||
count = 0;
|
|
||||||
/* count of white/black pixels depending on the color searched */
|
|
||||||
for (x = 0; x < pixels; x++)
|
|
||||||
{
|
|
||||||
/* when searching for black, detect white pixels */
|
|
||||||
if (black && data.get_raw_channel(x, y, 0) > 90) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
/* when searching for white, detect black pixels */
|
|
||||||
if (!black && data.get_raw_channel(x, y, 0) < 60) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* at end of line, if count >= 3%, line is not fully of the desired color
|
|
||||||
* so we must go to next line of the buffer */
|
|
||||||
/* count*100/pixels < 3 */
|
|
||||||
if ((count * 100) / pixels < 3)
|
|
||||||
{
|
|
||||||
found = 1;
|
|
||||||
DBG(DBG_data, "%s: strip found forward during pass %d at line %d\n", __func__,
|
|
||||||
pass, y);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DBG(DBG_data, "%s: pixels=%d, count=%d (%d%%)\n", __func__, pixels, count,
|
|
||||||
(100 * count) / pixels);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else /* since calibration scans are done forward, we need the whole area
|
|
||||||
to be of the required color when searching backward */
|
|
||||||
{
|
|
||||||
count = 0;
|
|
||||||
for (y = 0; y < lines; y++)
|
|
||||||
{
|
|
||||||
/* count of white/black pixels depending on the color searched */
|
|
||||||
for (x = 0; x < pixels; x++)
|
|
||||||
{
|
|
||||||
// when searching for black, detect white pixels
|
|
||||||
if (black && data.get_raw_channel(x, y, 0) > 90) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
// when searching for white, detect black pixels
|
|
||||||
if (!black && data.get_raw_channel(x, y, 0) < 60) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* at end of area, if count >= 3%, area is not fully of the desired color
|
|
||||||
* so we must go to next buffer */
|
|
||||||
if ((count * 100) / (pixels * lines) < 3)
|
|
||||||
{
|
|
||||||
found = 1;
|
|
||||||
DBG(DBG_data, "%s: strip found backward during pass %d \n", __func__, pass);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DBG(DBG_data, "%s: pixels=%d, count=%d (%d%%)\n", __func__, pixels, count,
|
|
||||||
(100 * count) / pixels);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pass++;
|
|
||||||
}
|
|
||||||
if (found)
|
|
||||||
{
|
|
||||||
DBG(DBG_info, "%s: %s strip found\n", __func__, black ? "black" : "white");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw SaneException(SANE_STATUS_UNSUPPORTED, "%s strip not found", black ? "black" : "white");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send shading calibration data. The buffer is considered to always hold values
|
* Send shading calibration data. The buffer is considered to always hold values
|
||||||
* for all the channels.
|
* for all the channels.
|
||||||
|
|
|
@ -105,9 +105,6 @@ public:
|
||||||
|
|
||||||
void eject_document(Genesys_Device* dev) const override;
|
void eject_document(Genesys_Device* dev) const override;
|
||||||
|
|
||||||
void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
|
||||||
bool forward, bool black) const override;
|
|
||||||
|
|
||||||
void move_to_ta(Genesys_Device* dev) const override;
|
void move_to_ta(Genesys_Device* dev) const override;
|
||||||
|
|
||||||
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
||||||
|
|
|
@ -1322,192 +1322,6 @@ void CommandSetGl846::update_home_sensor_gpio(Genesys_Device& dev) const
|
||||||
dev.interface->write_register(REG_0x6C, val);
|
dev.interface->write_register(REG_0x6C, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief search for a full width black or white strip.
|
|
||||||
* This function searches for a black or white stripe across the scanning area.
|
|
||||||
* When searching backward, the searched area must completely be of the desired
|
|
||||||
* color since this area will be used for calibration which scans forward.
|
|
||||||
* @param dev scanner device
|
|
||||||
* @param forward true if searching forward, false if searching backward
|
|
||||||
* @param black true if searching for a black strip, false for a white strip
|
|
||||||
*/
|
|
||||||
void CommandSetGl846::search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor, bool forward,
|
|
||||||
bool black) const
|
|
||||||
{
|
|
||||||
DBG_HELPER_ARGS(dbg, "%s %s", black ? "black" : "white", forward ? "forward" : "reverse");
|
|
||||||
unsigned channels;
|
|
||||||
Genesys_Register_Set local_reg;
|
|
||||||
unsigned int pass, count, found;
|
|
||||||
char title[80];
|
|
||||||
|
|
||||||
set_fe(dev, sensor, AFE_SET);
|
|
||||||
|
|
||||||
scanner_stop_action(*dev);
|
|
||||||
|
|
||||||
// set up for a gray scan at lowest dpi
|
|
||||||
const auto& resolution_settings = dev->model->get_resolution_settings(dev->settings.scan_method);
|
|
||||||
unsigned dpi = resolution_settings.get_min_resolution_x();
|
|
||||||
channels = 1;
|
|
||||||
/* 10 MM */
|
|
||||||
/* lines = (10 * dpi) / MM_PER_INCH; */
|
|
||||||
/* shading calibation is done with dev->motor.base_ydpi */
|
|
||||||
unsigned lines = static_cast<unsigned>(dev->model->y_size_calib_mm * dpi / MM_PER_INCH);
|
|
||||||
|
|
||||||
dev->set_head_pos_zero(ScanHeadId::PRIMARY);
|
|
||||||
|
|
||||||
local_reg = dev->reg;
|
|
||||||
|
|
||||||
ScanSession session;
|
|
||||||
session.params.xres = dpi;
|
|
||||||
session.params.yres = dpi;
|
|
||||||
session.params.startx = 0;
|
|
||||||
session.params.starty = 0;
|
|
||||||
session.params.pixels = dev->model->x_size_calib_mm * dpi / MM_PER_INCH;
|
|
||||||
session.params.lines = lines;
|
|
||||||
session.params.depth = 8;
|
|
||||||
session.params.channels = channels;
|
|
||||||
session.params.scan_mode = ScanColorMode::GRAY;
|
|
||||||
session.params.color_filter = ColorFilter::RED;
|
|
||||||
session.params.flags = ScanFlag::DISABLE_SHADING |
|
|
||||||
ScanFlag::DISABLE_GAMMA;
|
|
||||||
if (!forward) {
|
|
||||||
session.params.flags |= ScanFlag::REVERSE;
|
|
||||||
}
|
|
||||||
compute_session(dev, session, sensor);
|
|
||||||
|
|
||||||
init_regs_for_scan_session(dev, sensor, &local_reg, session);
|
|
||||||
|
|
||||||
dev->interface->write_registers(local_reg);
|
|
||||||
|
|
||||||
begin_scan(dev, sensor, &local_reg, true);
|
|
||||||
|
|
||||||
if (is_testing_mode()) {
|
|
||||||
dev->interface->test_checkpoint("search_strip");
|
|
||||||
scanner_stop_action(*dev);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wait_until_buffer_non_empty(dev);
|
|
||||||
|
|
||||||
// now we're on target, we can read data
|
|
||||||
auto image = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes);
|
|
||||||
|
|
||||||
scanner_stop_action(*dev);
|
|
||||||
|
|
||||||
pass = 0;
|
|
||||||
if (DBG_LEVEL >= DBG_data)
|
|
||||||
{
|
|
||||||
std::sprintf(title, "gl846_search_strip_%s_%s%02d.pnm",
|
|
||||||
black ? "black" : "white", forward ? "fwd" : "bwd", pass);
|
|
||||||
sanei_genesys_write_pnm_file(title, image);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* loop until strip is found or maximum pass number done */
|
|
||||||
found = 0;
|
|
||||||
while (pass < 20 && !found)
|
|
||||||
{
|
|
||||||
dev->interface->write_registers(local_reg);
|
|
||||||
|
|
||||||
// now start scan
|
|
||||||
begin_scan(dev, sensor, &local_reg, true);
|
|
||||||
|
|
||||||
wait_until_buffer_non_empty(dev);
|
|
||||||
|
|
||||||
// now we're on target, we can read data
|
|
||||||
image = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes);
|
|
||||||
|
|
||||||
scanner_stop_action(*dev);
|
|
||||||
|
|
||||||
if (DBG_LEVEL >= DBG_data)
|
|
||||||
{
|
|
||||||
std::sprintf(title, "gl846_search_strip_%s_%s%02d.pnm",
|
|
||||||
black ? "black" : "white", forward ? "fwd" : "bwd", pass);
|
|
||||||
sanei_genesys_write_pnm_file(title, image);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned white_level = 90;
|
|
||||||
unsigned black_level = 60;
|
|
||||||
|
|
||||||
/* search data to find black strip */
|
|
||||||
/* when searching forward, we only need one line of the searched color since we
|
|
||||||
* will scan forward. But when doing backward search, we need all the area of the
|
|
||||||
* same color */
|
|
||||||
if (forward) {
|
|
||||||
|
|
||||||
for (std::size_t y = 0; y < image.get_height() && !found; y++) {
|
|
||||||
count = 0;
|
|
||||||
|
|
||||||
// count of white/black pixels depending on the color searched
|
|
||||||
for (std::size_t x = 0; x < image.get_width(); x++) {
|
|
||||||
|
|
||||||
// when searching for black, detect white pixels
|
|
||||||
if (black && image.get_raw_channel(x, y, 0) > white_level) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// when searching for white, detect black pixels
|
|
||||||
if (!black && image.get_raw_channel(x, y, 0) < black_level) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* at end of line, if count >= 3%, line is not fully of the desired color
|
|
||||||
* so we must go to next line of the buffer */
|
|
||||||
auto found_percentage = (count * 100 / image.get_width());
|
|
||||||
if (found_percentage < 3) {
|
|
||||||
found = 1;
|
|
||||||
DBG(DBG_data, "%s: strip found forward during pass %d at line %zu\n", __func__,
|
|
||||||
pass, y);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DBG(DBG_data, "%s: pixels=%zu, count=%d (%zu%%)\n", __func__, image.get_width(),
|
|
||||||
count, found_percentage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* since calibration scans are done forward, we need the whole area
|
|
||||||
to be of the required color when searching backward
|
|
||||||
*/
|
|
||||||
|
|
||||||
count = 0;
|
|
||||||
for (std::size_t y = 0; y < image.get_height(); y++) {
|
|
||||||
// count of white/black pixels depending on the color searched
|
|
||||||
for (std::size_t x = 0; x < image.get_width(); x++) {
|
|
||||||
// when searching for black, detect white pixels
|
|
||||||
if (black && image.get_raw_channel(x, y, 0) > white_level) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
// when searching for white, detect black pixels
|
|
||||||
if (!black && image.get_raw_channel(x, y, 0) < black_level) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* at end of area, if count >= 3%, area is not fully of the desired color
|
|
||||||
* so we must go to next buffer */
|
|
||||||
auto found_percentage = count * 100 / (image.get_width() * image.get_height());
|
|
||||||
if (found_percentage < 3) {
|
|
||||||
found = 1;
|
|
||||||
DBG(DBG_data, "%s: strip found backward during pass %d \n", __func__, pass);
|
|
||||||
} else {
|
|
||||||
DBG(DBG_data, "%s: pixels=%zu, count=%d (%zu%%)\n", __func__, image.get_width(),
|
|
||||||
count, found_percentage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pass++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found)
|
|
||||||
{
|
|
||||||
DBG(DBG_info, "%s: %s strip found\n", __func__, black ? "black" : "white");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw SaneException(SANE_STATUS_UNSUPPORTED, "%s strip not found", black ? "black" : "white");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* average dark pixels of a 8 bits scan
|
* average dark pixels of a 8 bits scan
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -184,9 +184,6 @@ public:
|
||||||
|
|
||||||
void eject_document(Genesys_Device* dev) const override;
|
void eject_document(Genesys_Device* dev) const override;
|
||||||
|
|
||||||
void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
|
||||||
bool forward, bool black) const override;
|
|
||||||
|
|
||||||
void move_to_ta(Genesys_Device* dev) const override;
|
void move_to_ta(Genesys_Device* dev) const override;
|
||||||
|
|
||||||
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
||||||
|
|
|
@ -1363,187 +1363,6 @@ void CommandSetGl847::update_home_sensor_gpio(Genesys_Device& dev) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief search for a full width black or white strip.
|
|
||||||
* This function searches for a black or white stripe across the scanning area.
|
|
||||||
* When searching backward, the searched area must completely be of the desired
|
|
||||||
* color since this area will be used for calibration which scans forward.
|
|
||||||
* @param dev scanner device
|
|
||||||
* @param forward true if searching forward, false if searching backward
|
|
||||||
* @param black true if searching for a black strip, false for a white strip
|
|
||||||
*/
|
|
||||||
void CommandSetGl847::search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor, bool forward,
|
|
||||||
bool black) const
|
|
||||||
{
|
|
||||||
DBG_HELPER_ARGS(dbg, "%s %s", black ? "black" : "white", forward ? "forward" : "reverse");
|
|
||||||
Genesys_Register_Set local_reg;
|
|
||||||
unsigned int pass, count, found;
|
|
||||||
char title[80];
|
|
||||||
|
|
||||||
set_fe(dev, sensor, AFE_SET);
|
|
||||||
scanner_stop_action(*dev);
|
|
||||||
|
|
||||||
// set up for a gray scan at lowest dpi
|
|
||||||
const auto& resolution_settings = dev->model->get_resolution_settings(dev->settings.scan_method);
|
|
||||||
unsigned dpi = resolution_settings.get_min_resolution_x();
|
|
||||||
unsigned channels = 1;
|
|
||||||
|
|
||||||
unsigned lines = static_cast<unsigned>(dev->model->y_size_calib_mm * dpi / MM_PER_INCH);
|
|
||||||
dev->set_head_pos_zero(ScanHeadId::PRIMARY);
|
|
||||||
|
|
||||||
local_reg = dev->reg;
|
|
||||||
|
|
||||||
ScanSession session;
|
|
||||||
session.params.xres = dpi;
|
|
||||||
session.params.yres = dpi;
|
|
||||||
session.params.startx = 0;
|
|
||||||
session.params.starty = 0;
|
|
||||||
session.params.pixels = dev->model->x_size_calib_mm * dpi / MM_PER_INCH;
|
|
||||||
session.params.lines = lines;
|
|
||||||
session.params.depth = 8;
|
|
||||||
session.params.channels = channels;
|
|
||||||
session.params.scan_method = dev->settings.scan_method;
|
|
||||||
session.params.scan_mode = ScanColorMode::GRAY;
|
|
||||||
session.params.color_filter = ColorFilter::RED;
|
|
||||||
session.params.flags = ScanFlag::DISABLE_SHADING |
|
|
||||||
ScanFlag::DISABLE_GAMMA;
|
|
||||||
if (!forward) {
|
|
||||||
session.params.flags |= ScanFlag::REVERSE;
|
|
||||||
}
|
|
||||||
compute_session(dev, session, sensor);
|
|
||||||
|
|
||||||
init_regs_for_scan_session(dev, sensor, &local_reg, session);
|
|
||||||
|
|
||||||
dev->interface->write_registers(local_reg);
|
|
||||||
|
|
||||||
begin_scan(dev, sensor, &local_reg, true);
|
|
||||||
|
|
||||||
if (is_testing_mode()) {
|
|
||||||
dev->interface->test_checkpoint("search_strip");
|
|
||||||
scanner_stop_action(*dev);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wait_until_buffer_non_empty(dev);
|
|
||||||
|
|
||||||
// now we're on target, we can read data
|
|
||||||
auto image = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes);
|
|
||||||
|
|
||||||
scanner_stop_action(*dev);
|
|
||||||
|
|
||||||
pass = 0;
|
|
||||||
if (DBG_LEVEL >= DBG_data) {
|
|
||||||
std::sprintf(title, "gl847_search_strip_%s_%s%02d.pnm",
|
|
||||||
black ? "black" : "white", forward ? "fwd" : "bwd", pass);
|
|
||||||
sanei_genesys_write_pnm_file(title, image);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* loop until strip is found or maximum pass number done */
|
|
||||||
found = 0;
|
|
||||||
while (pass < 20 && !found)
|
|
||||||
{
|
|
||||||
dev->interface->write_registers(local_reg);
|
|
||||||
|
|
||||||
// now start scan
|
|
||||||
begin_scan(dev, sensor, &local_reg, true);
|
|
||||||
|
|
||||||
wait_until_buffer_non_empty(dev);
|
|
||||||
|
|
||||||
// now we're on target, we can read data
|
|
||||||
image = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes);
|
|
||||||
|
|
||||||
scanner_stop_action(*dev);
|
|
||||||
|
|
||||||
if (DBG_LEVEL >= DBG_data) {
|
|
||||||
std::sprintf(title, "gl847_search_strip_%s_%s%02d.pnm",
|
|
||||||
black ? "black" : "white",
|
|
||||||
forward ? "fwd" : "bwd", static_cast<int>(pass));
|
|
||||||
sanei_genesys_write_pnm_file(title, image);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned white_level = 90;
|
|
||||||
unsigned black_level = 60;
|
|
||||||
|
|
||||||
/* search data to find black strip */
|
|
||||||
/* when searching forward, we only need one line of the searched color since we
|
|
||||||
* will scan forward. But when doing backward search, we need all the area of the
|
|
||||||
* same color */
|
|
||||||
if (forward) {
|
|
||||||
for (std::size_t y = 0; y < image.get_height() && !found; y++) {
|
|
||||||
count = 0;
|
|
||||||
|
|
||||||
// count of white/black pixels depending on the color searched
|
|
||||||
for (std::size_t x = 0; x < image.get_width(); x++) {
|
|
||||||
|
|
||||||
// when searching for black, detect white pixels
|
|
||||||
if (black && image.get_raw_channel(x, y, 0) > white_level) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// when searching for white, detect black pixels
|
|
||||||
if (!black && image.get_raw_channel(x, y, 0) < black_level) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* at end of line, if count >= 3%, line is not fully of the desired color
|
|
||||||
* so we must go to next line of the buffer */
|
|
||||||
/* count*100/pixels < 3 */
|
|
||||||
auto found_percentage = (count * 100 / image.get_width());
|
|
||||||
if (found_percentage < 3) {
|
|
||||||
found = 1;
|
|
||||||
DBG(DBG_data, "%s: strip found forward during pass %d at line %zu\n", __func__,
|
|
||||||
pass, y);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DBG(DBG_data, "%s: pixels=%zu, count=%d (%zu%%)\n", __func__, image.get_width(),
|
|
||||||
count, found_percentage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* since calibration scans are done forward, we need the whole area
|
|
||||||
to be of the required color when searching backward
|
|
||||||
*/
|
|
||||||
|
|
||||||
count = 0;
|
|
||||||
for (std::size_t y = 0; y < image.get_height(); y++) {
|
|
||||||
// count of white/black pixels depending on the color searched
|
|
||||||
for (std::size_t x = 0; x < image.get_width(); x++) {
|
|
||||||
// when searching for black, detect white pixels
|
|
||||||
if (black && image.get_raw_channel(x, y, 0) > white_level) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
// when searching for white, detect black pixels
|
|
||||||
if (!black && image.get_raw_channel(x, y, 0) < black_level) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* at end of area, if count >= 3%, area is not fully of the desired color
|
|
||||||
* so we must go to next buffer */
|
|
||||||
auto found_percentage = count * 100 / (image.get_width() * image.get_height());
|
|
||||||
if (found_percentage < 3) {
|
|
||||||
found = 1;
|
|
||||||
DBG(DBG_data, "%s: strip found backward during pass %d \n", __func__, pass);
|
|
||||||
} else {
|
|
||||||
DBG(DBG_data, "%s: pixels=%zu, count=%d (%zu%%)\n", __func__, image.get_width(),
|
|
||||||
count, found_percentage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pass++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found)
|
|
||||||
{
|
|
||||||
DBG(DBG_info, "%s: %s strip found\n", __func__, black ? "black" : "white");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw SaneException(SANE_STATUS_UNSUPPORTED, "%s strip not found", black ? "black" : "white");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* average dark pixels of a 8 bits scan
|
* average dark pixels of a 8 bits scan
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -172,9 +172,6 @@ public:
|
||||||
|
|
||||||
void eject_document(Genesys_Device* dev) const override;
|
void eject_document(Genesys_Device* dev) const override;
|
||||||
|
|
||||||
void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
|
||||||
bool forward, bool black) const override;
|
|
||||||
|
|
||||||
void move_to_ta(Genesys_Device* dev) const override;
|
void move_to_ta(Genesys_Device* dev) const override;
|
||||||
|
|
||||||
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
||||||
|
|
|
@ -292,6 +292,17 @@ void scanner_move(Genesys_Device& dev, ScanMethod scan_method, unsigned steps, D
|
||||||
void scanner_move_back_home(Genesys_Device& dev, bool wait_until_home);
|
void scanner_move_back_home(Genesys_Device& dev, bool wait_until_home);
|
||||||
void scanner_move_back_home_ta(Genesys_Device& dev);
|
void scanner_move_back_home_ta(Genesys_Device& dev);
|
||||||
|
|
||||||
|
/** Search for a full width black or white strip.
|
||||||
|
This function searches for a black or white stripe across the scanning area.
|
||||||
|
When searching backward, the searched area must completely be of the desired
|
||||||
|
color since this area will be used for calibration which scans forward.
|
||||||
|
|
||||||
|
@param dev scanner device
|
||||||
|
@param forward true if searching forward, false if searching backward
|
||||||
|
@param black true if searching for a black strip, false for a white strip
|
||||||
|
*/
|
||||||
|
void scanner_search_strip(Genesys_Device& dev, bool forward, bool black);
|
||||||
|
|
||||||
void scanner_clear_scan_and_feed_counts(Genesys_Device& dev);
|
void scanner_clear_scan_and_feed_counts(Genesys_Device& dev);
|
||||||
|
|
||||||
extern void sanei_genesys_write_file(const char* filename, const std::uint8_t* data,
|
extern void sanei_genesys_write_file(const char* filename, const std::uint8_t* data,
|
||||||
|
|
Ładowanie…
Reference in New Issue