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
|
||||
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
|
||||
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");
|
||||
}
|
||||
|
||||
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,
|
||||
uint32_t exposure_time,
|
||||
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 */
|
||||
try {
|
||||
dev->cmd_set->search_strip(dev, sensor, forward, false);
|
||||
scanner_search_strip(*dev, forward, false);
|
||||
} catch (...) {
|
||||
catch_all_exceptions(__func__, [&](){ dev->cmd_set->eject_document(dev); });
|
||||
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)) {
|
||||
// seek black/white reverse/forward
|
||||
try {
|
||||
dev->cmd_set->search_strip(dev, sensor, forward, true);
|
||||
scanner_search_strip(*dev, forward, true);
|
||||
} catch (...) {
|
||||
catch_all_exceptions(__func__, [&](){ dev->cmd_set->eject_document(dev); });
|
||||
throw;
|
||||
|
@ -2552,7 +2754,7 @@ static void genesys_sheetfed_calibration(Genesys_Device* dev, Genesys_Sensor& se
|
|||
|
||||
/* go to a white area */
|
||||
try {
|
||||
dev->cmd_set->search_strip(dev, sensor, forward, false);
|
||||
scanner_search_strip(*dev, forward, false);
|
||||
} catch (...) {
|
||||
catch_all_exceptions(__func__, [&](){ dev->cmd_set->eject_document(dev); });
|
||||
throw;
|
||||
|
|
|
@ -2036,16 +2036,6 @@ void CommandSetGl124::eject_document(Genesys_Device* dev) const
|
|||
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) dev;
|
||||
|
|
|
@ -171,9 +171,6 @@ public:
|
|||
|
||||
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 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) dev;
|
||||
|
|
|
@ -491,9 +491,6 @@ public:
|
|||
|
||||
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 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);
|
||||
}
|
||||
|
||||
static void gl841_stop_action(Genesys_Device* dev)
|
||||
void gl841_stop_action(Genesys_Device* dev)
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
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
|
||||
* for all the channels.
|
||||
|
|
|
@ -105,9 +105,6 @@ public:
|
|||
|
||||
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 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);
|
||||
}
|
||||
|
||||
|
||||
/** @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
|
||||
* for all the channels.
|
||||
|
|
|
@ -105,9 +105,6 @@ public:
|
|||
|
||||
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 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);
|
||||
}
|
||||
|
||||
/** @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
|
||||
*/
|
||||
|
|
|
@ -184,9 +184,6 @@ public:
|
|||
|
||||
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 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
|
||||
*/
|
||||
|
|
|
@ -172,9 +172,6 @@ public:
|
|||
|
||||
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 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_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);
|
||||
|
||||
extern void sanei_genesys_write_file(const char* filename, const std::uint8_t* data,
|
||||
|
|
Ładowanie…
Reference in New Issue