kopia lustrzana https://gitlab.com/sane-project/backends
genesys: Reduce duplication of scanner read methods on gl841
rodzic
67d3c134a9
commit
d74c4b6b68
|
@ -2325,8 +2325,6 @@ void CommandSetGl841::search_start_position(Genesys_Device* dev) const
|
||||||
// send to scanner
|
// send to scanner
|
||||||
dev->interface->write_registers(local_reg);
|
dev->interface->write_registers(local_reg);
|
||||||
|
|
||||||
std::vector<uint8_t> data(session.output_total_bytes);
|
|
||||||
|
|
||||||
dev->cmd_set->begin_scan(dev, sensor, &local_reg, true);
|
dev->cmd_set->begin_scan(dev, sensor, &local_reg, true);
|
||||||
|
|
||||||
if (is_testing_mode()) {
|
if (is_testing_mode()) {
|
||||||
|
@ -2339,11 +2337,10 @@ void CommandSetGl841::search_start_position(Genesys_Device* dev) const
|
||||||
wait_until_buffer_non_empty(dev);
|
wait_until_buffer_non_empty(dev);
|
||||||
|
|
||||||
// now we're on target, we can read data
|
// now we're on target, we can read data
|
||||||
sanei_genesys_read_data_from_scanner(dev, data.data(), session.output_total_bytes);
|
auto image = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes);
|
||||||
|
|
||||||
if (DBG_LEVEL >= DBG_data) {
|
if (DBG_LEVEL >= DBG_data) {
|
||||||
sanei_genesys_write_pnm_file("gl841_search_position.pnm", data.data(), 8, 1, pixels,
|
sanei_genesys_write_pnm_file("gl841_search_position.pnm", image);
|
||||||
dev->model->search_lines);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->cmd_set->end_scan(dev, &local_reg, true);
|
dev->cmd_set->end_scan(dev, &local_reg, true);
|
||||||
|
@ -2354,8 +2351,8 @@ void CommandSetGl841::search_start_position(Genesys_Device* dev) const
|
||||||
for (auto& sensor_update :
|
for (auto& sensor_update :
|
||||||
sanei_genesys_find_sensors_all_for_write(dev, dev->model->default_method))
|
sanei_genesys_find_sensors_all_for_write(dev, dev->model->default_method))
|
||||||
{
|
{
|
||||||
sanei_genesys_search_reference_point(dev, sensor_update, data.data(), 0, dpi, pixels,
|
sanei_genesys_search_reference_point(dev, sensor_update, image.get_row_ptr(0), 0, dpi,
|
||||||
dev->model->search_lines);
|
pixels, dev->model->search_lines);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2577,9 +2574,7 @@ SensorExposure CommandSetGl841::led_calibration(Genesys_Device* dev, const Genes
|
||||||
{
|
{
|
||||||
DBG_HELPER(dbg);
|
DBG_HELPER(dbg);
|
||||||
int num_pixels;
|
int num_pixels;
|
||||||
int i, j;
|
int i;
|
||||||
int val;
|
|
||||||
int channels;
|
|
||||||
int avg[3], avga, avge;
|
int avg[3], avga, avge;
|
||||||
int turn;
|
int turn;
|
||||||
uint16_t exp[3], target;
|
uint16_t exp[3], target;
|
||||||
|
@ -2598,7 +2593,7 @@ SensorExposure CommandSetGl841::led_calibration(Genesys_Device* dev, const Genes
|
||||||
}
|
}
|
||||||
|
|
||||||
/* offset calibration is always done in color mode */
|
/* offset calibration is always done in color mode */
|
||||||
channels = 3;
|
unsigned channels = 3;
|
||||||
|
|
||||||
unsigned resolution = sensor.get_logical_hwdpi(dev->settings.xres);
|
unsigned resolution = sensor.get_logical_hwdpi(dev->settings.xres);
|
||||||
unsigned factor = sensor.optical_res / resolution;
|
unsigned factor = sensor.optical_res / resolution;
|
||||||
|
@ -2677,33 +2672,21 @@ SensorExposure CommandSetGl841::led_calibration(Genesys_Device* dev, const Genes
|
||||||
return calib_sensor.exposure;
|
return calib_sensor.exposure;
|
||||||
}
|
}
|
||||||
|
|
||||||
sanei_genesys_read_data_from_scanner(dev, line.data(), session.output_line_bytes);
|
auto image = read_unshuffled_image_from_scanner(dev, session, session.output_line_bytes);
|
||||||
|
|
||||||
if (DBG_LEVEL >= DBG_data) {
|
if (DBG_LEVEL >= DBG_data) {
|
||||||
char fn[30];
|
char fn[30];
|
||||||
std::snprintf(fn, 30, "gl841_led_%d.pnm", turn);
|
std::snprintf(fn, 30, "gl841_led_%d.pnm", turn);
|
||||||
sanei_genesys_write_pnm_file(fn, line.data(), 16, channels, num_pixels, 1);
|
sanei_genesys_write_pnm_file(fn, image);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* compute average */
|
for (unsigned ch = 0; ch < channels; ch++) {
|
||||||
for (j = 0; j < channels; j++)
|
avg[ch] = 0;
|
||||||
{
|
for (std::size_t x = 0; x < image.get_width(); x++) {
|
||||||
avg[j] = 0;
|
avg[ch] += image.get_raw_channel(x, 0, ch);
|
||||||
for (i = 0; i < num_pixels; i++)
|
}
|
||||||
{
|
avg[ch] /= image.get_width();
|
||||||
if (dev->model->is_cis)
|
}
|
||||||
val =
|
|
||||||
line[i * 2 + j * 2 * num_pixels + 1] * 256 +
|
|
||||||
line[i * 2 + j * 2 * num_pixels];
|
|
||||||
else
|
|
||||||
val =
|
|
||||||
line[i * 2 * channels + 2 * j + 1] * 256 +
|
|
||||||
line[i * 2 * channels + 2 * j];
|
|
||||||
avg[j] += val;
|
|
||||||
}
|
|
||||||
|
|
||||||
avg[j] /= num_pixels;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG(DBG_info,"%s: average: %d,%d,%d\n", __func__, avg[0], avg[1], avg[2]);
|
DBG(DBG_info,"%s: average: %d,%d,%d\n", __func__, avg[0], avg[1], avg[2]);
|
||||||
|
|
||||||
|
@ -2917,12 +2900,9 @@ void CommandSetGl841::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
||||||
{
|
{
|
||||||
DBG_HELPER(dbg);
|
DBG_HELPER(dbg);
|
||||||
int num_pixels;
|
int num_pixels;
|
||||||
int i, j;
|
|
||||||
int val;
|
|
||||||
int channels;
|
|
||||||
int off[3],offh[3],offl[3],off1[3],off2[3];
|
int off[3],offh[3],offl[3],off1[3],off2[3];
|
||||||
int min1[3],min2[3];
|
int min1[3],min2[3];
|
||||||
int cmin[3],cmax[3];
|
unsigned cmin[3],cmax[3];
|
||||||
int turn;
|
int turn;
|
||||||
int mintgt = 0x400;
|
int mintgt = 0x400;
|
||||||
|
|
||||||
|
@ -2932,7 +2912,7 @@ void CommandSetGl841::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
||||||
}
|
}
|
||||||
|
|
||||||
/* offset calibration is always done in color mode */
|
/* offset calibration is always done in color mode */
|
||||||
channels = 3;
|
unsigned channels = 3;
|
||||||
|
|
||||||
unsigned resolution = sensor.get_logical_hwdpi(dev->settings.xres);
|
unsigned resolution = sensor.get_logical_hwdpi(dev->settings.xres);
|
||||||
unsigned factor = sensor.optical_res / resolution;
|
unsigned factor = sensor.optical_res / resolution;
|
||||||
|
@ -2963,9 +2943,6 @@ void CommandSetGl841::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
||||||
|
|
||||||
init_regs_for_scan_session(dev, calib_sensor, ®s, session);
|
init_regs_for_scan_session(dev, calib_sensor, ®s, session);
|
||||||
|
|
||||||
std::vector<uint8_t> first_line(session.output_total_bytes);
|
|
||||||
std::vector<uint8_t> second_line(session.output_total_bytes);
|
|
||||||
|
|
||||||
/* scan first line of data with no offset nor gain */
|
/* scan first line of data with no offset nor gain */
|
||||||
/*WM8199: gain=0.73; offset=-260mV*/
|
/*WM8199: gain=0.73; offset=-260mV*/
|
||||||
/*okay. the sensor black level is now at -260mV. we only get 0 from AFE...*/
|
/*okay. the sensor black level is now at -260mV. we only get 0 from AFE...*/
|
||||||
|
@ -2996,12 +2973,14 @@ void CommandSetGl841::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
||||||
offl[2] = 0x00;
|
offl[2] = 0x00;
|
||||||
turn = 0;
|
turn = 0;
|
||||||
|
|
||||||
|
Image first_line;
|
||||||
|
|
||||||
bool acceptable = false;
|
bool acceptable = false;
|
||||||
do {
|
do {
|
||||||
|
|
||||||
dev->interface->write_registers(regs);
|
dev->interface->write_registers(regs);
|
||||||
|
|
||||||
for (j=0; j < channels; j++) {
|
for (unsigned j = 0; j < channels; j++) {
|
||||||
off[j] = (offh[j]+offl[j])/2;
|
off[j] = (offh[j]+offl[j])/2;
|
||||||
dev->frontend.set_offset(j, off[j]);
|
dev->frontend.set_offset(j, off[j]);
|
||||||
}
|
}
|
||||||
|
@ -3016,57 +2995,51 @@ void CommandSetGl841::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sanei_genesys_read_data_from_scanner(dev, first_line.data(), session.output_total_bytes);
|
first_line = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes);
|
||||||
|
|
||||||
if (DBG_LEVEL >= DBG_data) {
|
if (DBG_LEVEL >= DBG_data) {
|
||||||
char fn[30];
|
char fn[30];
|
||||||
std::snprintf(fn, 30, "gl841_offset1_%02d.pnm", turn);
|
std::snprintf(fn, 30, "gl841_offset1_%02d.pnm", turn);
|
||||||
sanei_genesys_write_pnm_file(fn, first_line.data(), 16, channels, num_pixels, 1);
|
sanei_genesys_write_pnm_file(fn, first_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
acceptable = true;
|
acceptable = true;
|
||||||
|
|
||||||
for (j = 0; j < channels; j++)
|
for (unsigned ch = 0; ch < channels; ch++) {
|
||||||
{
|
cmin[ch] = 0;
|
||||||
cmin[j] = 0;
|
cmax[ch] = 0;
|
||||||
cmax[j] = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < num_pixels; i++)
|
for (std::size_t x = 0; x < first_line.get_width(); x++) {
|
||||||
{
|
auto value = first_line.get_raw_channel(x, 0, ch);
|
||||||
if (dev->model->is_cis)
|
if (value < 10) {
|
||||||
val =
|
cmin[ch]++;
|
||||||
first_line[i * 2 + j * 2 * num_pixels + 1] * 256 +
|
}
|
||||||
first_line[i * 2 + j * 2 * num_pixels];
|
if (value > 65525) {
|
||||||
else
|
cmax[ch]++;
|
||||||
val =
|
}
|
||||||
first_line[i * 2 * channels + 2 * j + 1] * 256 +
|
}
|
||||||
first_line[i * 2 * channels + 2 * j];
|
|
||||||
if (val < 10)
|
|
||||||
cmin[j]++;
|
|
||||||
if (val > 65525)
|
|
||||||
cmax[j]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO the DP685 has a black strip in the middle of the sensor
|
/* TODO the DP685 has a black strip in the middle of the sensor
|
||||||
* should be handled in a more elegant way , could be a bug */
|
* should be handled in a more elegant way , could be a bug */
|
||||||
if (dev->model->sensor_id == SensorId::CCD_DP685)
|
if (dev->model->sensor_id == SensorId::CCD_DP685) {
|
||||||
cmin[j] -= 20;
|
cmin[ch] -= 20;
|
||||||
|
}
|
||||||
|
|
||||||
if (cmin[j] > num_pixels/100) {
|
if (cmin[ch] > first_line.get_width() / 100) {
|
||||||
acceptable = false;
|
acceptable = false;
|
||||||
if (dev->model->is_cis)
|
if (dev->model->is_cis)
|
||||||
offl[0] = off[0];
|
offl[0] = off[0];
|
||||||
else
|
else
|
||||||
offl[j] = off[j];
|
offl[ch] = off[ch];
|
||||||
}
|
}
|
||||||
if (cmax[j] > num_pixels/100) {
|
if (cmax[ch] > first_line.get_width() / 100) {
|
||||||
acceptable = false;
|
acceptable = false;
|
||||||
if (dev->model->is_cis)
|
if (dev->model->is_cis)
|
||||||
offh[0] = off[0];
|
offh[0] = off[0];
|
||||||
else
|
else
|
||||||
offh[j] = off[j];
|
offh[ch] = off[ch];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG(DBG_info,"%s: black/white pixels: %d/%d,%d/%d,%d/%d\n", __func__, cmin[0], cmax[0],
|
DBG(DBG_info,"%s: black/white pixels: %d/%d,%d/%d,%d/%d\n", __func__, cmin[0], cmax[0],
|
||||||
cmin[1], cmax[1], cmin[2], cmax[2]);
|
cmin[1], cmax[1], cmin[2], cmax[2]);
|
||||||
|
@ -3084,26 +3057,19 @@ void CommandSetGl841::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
||||||
DBG(DBG_info,"%s: acceptable offsets: %d,%d,%d\n", __func__, off[0], off[1], off[2]);
|
DBG(DBG_info,"%s: acceptable offsets: %d,%d,%d\n", __func__, off[0], off[1], off[2]);
|
||||||
|
|
||||||
|
|
||||||
for (j = 0; j < channels; j++)
|
for (unsigned ch = 0; ch < channels; ch++) {
|
||||||
{
|
off1[ch] = off[ch];
|
||||||
off1[j] = off[j];
|
|
||||||
|
|
||||||
min1[j] = 65536;
|
min1[ch] = 65536;
|
||||||
|
|
||||||
for (i = 0; i < num_pixels; i++)
|
for (std::size_t x = 0; x < first_line.get_width(); x++) {
|
||||||
{
|
auto value = first_line.get_raw_channel(x, 0, ch);
|
||||||
if (dev->model->is_cis)
|
|
||||||
val =
|
if (min1[ch] > value && value >= 10) {
|
||||||
first_line[i * 2 + j * 2 * num_pixels + 1] * 256 +
|
min1[ch] = value;
|
||||||
first_line[i * 2 + j * 2 * num_pixels];
|
}
|
||||||
else
|
}
|
||||||
val =
|
}
|
||||||
first_line[i * 2 * channels + 2 * j + 1] * 256 +
|
|
||||||
first_line[i * 2 * channels + 2 * j];
|
|
||||||
if (min1[j] > val && val >= 10)
|
|
||||||
min1[j] = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
offl[0] = off[0];
|
offl[0] = off[0];
|
||||||
|
@ -3111,64 +3077,59 @@ void CommandSetGl841::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
||||||
offl[2] = off[0];
|
offl[2] = off[0];
|
||||||
turn = 0;
|
turn = 0;
|
||||||
|
|
||||||
|
Image second_line;
|
||||||
do {
|
do {
|
||||||
|
|
||||||
for (j=0; j < channels; j++) {
|
for (unsigned j=0; j < channels; j++) {
|
||||||
off[j] = (offh[j]+offl[j])/2;
|
off[j] = (offh[j]+offl[j])/2;
|
||||||
dev->frontend.set_offset(j, off[j]);
|
dev->frontend.set_offset(j, off[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->cmd_set->set_fe(dev, calib_sensor, AFE_SET);
|
dev->cmd_set->set_fe(dev, calib_sensor, AFE_SET);
|
||||||
|
|
||||||
DBG(DBG_info, "%s: starting second line reading\n", __func__);
|
DBG(DBG_info, "%s: starting second line reading\n", __func__);
|
||||||
dev->interface->write_registers(regs);
|
dev->interface->write_registers(regs);
|
||||||
dev->cmd_set->begin_scan(dev, calib_sensor, ®s, true);
|
dev->cmd_set->begin_scan(dev, calib_sensor, ®s, true);
|
||||||
sanei_genesys_read_data_from_scanner(dev, second_line.data(), session.output_total_bytes);
|
second_line = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes);
|
||||||
|
|
||||||
if (DBG_LEVEL >= DBG_data) {
|
if (DBG_LEVEL >= DBG_data) {
|
||||||
char fn[30];
|
char fn[30];
|
||||||
std::snprintf(fn, 30, "gl841_offset2_%02d.pnm", turn);
|
std::snprintf(fn, 30, "gl841_offset2_%02d.pnm", turn);
|
||||||
sanei_genesys_write_pnm_file(fn, second_line.data(), 16, channels, num_pixels, 1);
|
sanei_genesys_write_pnm_file(fn, second_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
acceptable = true;
|
acceptable = true;
|
||||||
|
|
||||||
for (j = 0; j < channels; j++)
|
for (unsigned ch = 0; ch < channels; ch++) {
|
||||||
{
|
cmin[ch] = 0;
|
||||||
cmin[j] = 0;
|
cmax[ch] = 0;
|
||||||
cmax[j] = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < num_pixels; i++)
|
for (std::size_t x = 0; x < second_line.get_width(); x++) {
|
||||||
{
|
auto value = second_line.get_raw_channel(x, 0, ch);
|
||||||
if (dev->model->is_cis)
|
|
||||||
val =
|
|
||||||
second_line[i * 2 + j * 2 * num_pixels + 1] * 256 +
|
|
||||||
second_line[i * 2 + j * 2 * num_pixels];
|
|
||||||
else
|
|
||||||
val =
|
|
||||||
second_line[i * 2 * channels + 2 * j + 1] * 256 +
|
|
||||||
second_line[i * 2 * channels + 2 * j];
|
|
||||||
if (val < 10)
|
|
||||||
cmin[j]++;
|
|
||||||
if (val > 65525)
|
|
||||||
cmax[j]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmin[j] > num_pixels/100) {
|
if (value < 10) {
|
||||||
|
cmin[ch]++;
|
||||||
|
}
|
||||||
|
if (value > 65525) {
|
||||||
|
cmax[ch]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmin[ch] > second_line.get_width() / 100) {
|
||||||
acceptable = false;
|
acceptable = false;
|
||||||
if (dev->model->is_cis)
|
if (dev->model->is_cis)
|
||||||
offl[0] = off[0];
|
offl[0] = off[0];
|
||||||
else
|
else
|
||||||
offl[j] = off[j];
|
offl[ch] = off[ch];
|
||||||
}
|
}
|
||||||
if (cmax[j] > num_pixels/100) {
|
if (cmax[ch] > second_line.get_width() / 100) {
|
||||||
acceptable = false;
|
acceptable = false;
|
||||||
if (dev->model->is_cis)
|
if (dev->model->is_cis)
|
||||||
offh[0] = off[0];
|
offh[0] = off[0];
|
||||||
else
|
else
|
||||||
offh[j] = off[j];
|
offh[ch] = off[ch];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG(DBG_info, "%s: black/white pixels: %d/%d,%d/%d,%d/%d\n", __func__, cmin[0], cmax[0],
|
DBG(DBG_info, "%s: black/white pixels: %d/%d,%d/%d,%d/%d\n", __func__, cmin[0], cmax[0],
|
||||||
cmin[1], cmax[1], cmin[2], cmax[2]);
|
cmin[1], cmax[1], cmin[2], cmax[2]);
|
||||||
|
@ -3187,26 +3148,19 @@ void CommandSetGl841::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
||||||
DBG(DBG_info, "%s: acceptable offsets: %d,%d,%d\n", __func__, off[0], off[1], off[2]);
|
DBG(DBG_info, "%s: acceptable offsets: %d,%d,%d\n", __func__, off[0], off[1], off[2]);
|
||||||
|
|
||||||
|
|
||||||
for (j = 0; j < channels; j++)
|
for (unsigned ch = 0; ch < channels; ch++) {
|
||||||
{
|
off2[ch] = off[ch];
|
||||||
off2[j] = off[j];
|
|
||||||
|
|
||||||
min2[j] = 65536;
|
min2[ch] = 65536;
|
||||||
|
|
||||||
for (i = 0; i < num_pixels; i++)
|
for (std::size_t x = 0; x < second_line.get_width(); x++) {
|
||||||
{
|
auto value = second_line.get_raw_channel(x, 0, ch);
|
||||||
if (dev->model->is_cis)
|
|
||||||
val =
|
if (min2[ch] > value && value != 0) {
|
||||||
second_line[i * 2 + j * 2 * num_pixels + 1] * 256 +
|
min2[ch] = value;
|
||||||
second_line[i * 2 + j * 2 * num_pixels];
|
}
|
||||||
else
|
}
|
||||||
val =
|
}
|
||||||
second_line[i * 2 * channels + 2 * j + 1] * 256 +
|
|
||||||
second_line[i * 2 * channels + 2 * j];
|
|
||||||
if (min2[j] > val && val != 0)
|
|
||||||
min2[j] = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG(DBG_info, "%s: first set: %d/%d,%d/%d,%d/%d\n", __func__, off1[0], min1[0], off1[1], min1[1],
|
DBG(DBG_info, "%s: first set: %d/%d,%d/%d,%d/%d\n", __func__, off1[0], min1[0], off1[1], min1[1],
|
||||||
off1[2], min1[2]);
|
off1[2], min1[2]);
|
||||||
|
@ -3232,22 +3186,25 @@ void CommandSetGl841::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
||||||
off=(min*(off1-off2)+min1*off2-off1*min2)/(min1-min2)
|
off=(min*(off1-off2)+min1*off2-off1*min2)/(min1-min2)
|
||||||
|
|
||||||
*/
|
*/
|
||||||
for (j = 0; j < channels; j++)
|
for (unsigned ch = 0; ch < channels; ch++) {
|
||||||
{
|
if (min2[ch] - min1[ch] == 0) {
|
||||||
if (min2[j]-min1[j] == 0) {
|
|
||||||
/*TODO: try to avoid this*/
|
/*TODO: try to avoid this*/
|
||||||
DBG(DBG_warn, "%s: difference too small\n", __func__);
|
DBG(DBG_warn, "%s: difference too small\n", __func__);
|
||||||
if (mintgt * (off1[j] - off2[j]) + min1[j] * off2[j] - min2[j] * off1[j] >= 0)
|
if (mintgt * (off1[ch] - off2[ch]) + min1[ch] * off2[ch] - min2[ch] * off1[ch] >= 0) {
|
||||||
off[j] = 0x0000;
|
off[ch] = 0x0000;
|
||||||
else
|
} else {
|
||||||
off[j] = 0xffff;
|
off[ch] = 0xffff;
|
||||||
} else
|
}
|
||||||
off[j] = (mintgt * (off1[j] - off2[j]) + min1[j] * off2[j] - min2[j] * off1[j])/(min1[j]-min2[j]);
|
} else {
|
||||||
if (off[j] > 255)
|
off[ch] = (mintgt * (off1[ch] - off2[ch]) + min1[ch] * off2[ch] - min2[ch] * off1[ch])/(min1[ch]-min2[ch]);
|
||||||
off[j] = 255;
|
}
|
||||||
if (off[j] < 0)
|
if (off[ch] > 255) {
|
||||||
off[j] = 0;
|
off[ch] = 255;
|
||||||
dev->frontend.set_offset(j, off[j]);
|
}
|
||||||
|
if (off[ch] < 0) {
|
||||||
|
off[ch] = 0;
|
||||||
|
}
|
||||||
|
dev->frontend.set_offset(ch, off[ch]);
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG(DBG_info, "%s: final offsets: %d,%d,%d\n", __func__, off[0], off[1], off[2]);
|
DBG(DBG_info, "%s: final offsets: %d,%d,%d\n", __func__, off[0], off[1], off[2]);
|
||||||
|
@ -3284,10 +3241,7 @@ void CommandSetGl841::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
||||||
{
|
{
|
||||||
DBG_HELPER_ARGS(dbg, "dpi=%d", dpi);
|
DBG_HELPER_ARGS(dbg, "dpi=%d", dpi);
|
||||||
int num_pixels;
|
int num_pixels;
|
||||||
int i, j, channels;
|
|
||||||
int max[3];
|
|
||||||
float gain[3];
|
float gain[3];
|
||||||
int val;
|
|
||||||
int lines=1;
|
int lines=1;
|
||||||
int move;
|
int move;
|
||||||
|
|
||||||
|
@ -3300,7 +3254,7 @@ void CommandSetGl841::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
||||||
}
|
}
|
||||||
|
|
||||||
/* coarse gain calibration is allways done in color mode */
|
/* coarse gain calibration is allways done in color mode */
|
||||||
channels = 3;
|
unsigned channels = 3;
|
||||||
|
|
||||||
unsigned resolution = sensor.get_logical_hwdpi(dev->settings.xres);
|
unsigned resolution = sensor.get_logical_hwdpi(dev->settings.xres);
|
||||||
unsigned factor = sensor.optical_res / resolution;
|
unsigned factor = sensor.optical_res / resolution;
|
||||||
|
@ -3343,7 +3297,7 @@ void CommandSetGl841::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sanei_genesys_read_data_from_scanner(dev, line.data(), session.output_total_bytes);
|
auto image = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes);
|
||||||
|
|
||||||
if (DBG_LEVEL >= DBG_data)
|
if (DBG_LEVEL >= DBG_data)
|
||||||
sanei_genesys_write_pnm_file("gl841_gain.pnm", line.data(), 16, channels, num_pixels, lines);
|
sanei_genesys_write_pnm_file("gl841_gain.pnm", line.data(), 16, channels, num_pixels, lines);
|
||||||
|
@ -3351,25 +3305,17 @@ void CommandSetGl841::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
||||||
/* average high level for each channel and compute gain
|
/* average high level for each channel and compute gain
|
||||||
to reach the target code
|
to reach the target code
|
||||||
we only use the central half of the CCD data */
|
we only use the central half of the CCD data */
|
||||||
for (j = 0; j < channels; j++)
|
|
||||||
{
|
|
||||||
max[j] = 0;
|
|
||||||
for (i = 0; i < num_pixels; i++)
|
|
||||||
{
|
|
||||||
if (dev->model->is_cis)
|
|
||||||
val =
|
|
||||||
line[i * 2 + j * 2 * num_pixels + 1] * 256 +
|
|
||||||
line[i * 2 + j * 2 * num_pixels];
|
|
||||||
else
|
|
||||||
val =
|
|
||||||
line[i * 2 * channels + 2 * j + 1] * 256 +
|
|
||||||
line[i * 2 * channels + 2 * j];
|
|
||||||
|
|
||||||
if (val > max[j])
|
for (unsigned ch = 0; ch < channels; ch++) {
|
||||||
max[j] = val;
|
unsigned max = 0;
|
||||||
}
|
for (std::size_t x = 0; x < image.get_width(); x++) {
|
||||||
|
auto value = image.get_raw_channel(x, 0, ch);
|
||||||
|
if (value > max) {
|
||||||
|
max = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gain[j] = 65535.0f / max[j];
|
gain[ch] = 65535.0f / max;
|
||||||
|
|
||||||
uint8_t out_gain = 0;
|
uint8_t out_gain = 0;
|
||||||
|
|
||||||
|
@ -3377,23 +3323,24 @@ void CommandSetGl841::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
||||||
dev->model->adc_id == AdcId::WOLFSON_XP300 ||
|
dev->model->adc_id == AdcId::WOLFSON_XP300 ||
|
||||||
dev->model->adc_id == AdcId::WOLFSON_DSM600)
|
dev->model->adc_id == AdcId::WOLFSON_DSM600)
|
||||||
{
|
{
|
||||||
gain[j] *= 0.69f; // seems we don't get the real maximum. empirically derived
|
gain[ch] *= 0.69f; // seems we don't get the real maximum. empirically derived
|
||||||
if (283 - 208/gain[j] > 255)
|
if (283 - 208 / gain[ch] > 255) {
|
||||||
out_gain = 255;
|
out_gain = 255;
|
||||||
else if (283 - 208/gain[j] < 0)
|
} else if (283 - 208 / gain[ch] < 0) {
|
||||||
out_gain = 0;
|
out_gain = 0;
|
||||||
else
|
} else {
|
||||||
out_gain = static_cast<std::uint8_t>(283 - 208 / gain[j]);
|
out_gain = static_cast<std::uint8_t>(283 - 208 / gain[ch]);
|
||||||
|
}
|
||||||
} else if (dev->model->adc_id == AdcId::CANON_LIDE_80) {
|
} else if (dev->model->adc_id == AdcId::CANON_LIDE_80) {
|
||||||
out_gain = static_cast<std::uint8_t>(gain[j] * 12);
|
out_gain = static_cast<std::uint8_t>(gain[ch] * 12);
|
||||||
}
|
}
|
||||||
dev->frontend.set_gain(j, out_gain);
|
dev->frontend.set_gain(ch, out_gain);
|
||||||
|
|
||||||
DBG(DBG_proc, "%s: channel %d, max=%d, gain = %f, setting:%d\n", __func__, j, max[j], gain[j],
|
DBG(DBG_proc, "%s: channel %d, max=%d, gain = %f, setting:%d\n", __func__, ch, max,
|
||||||
out_gain);
|
gain[ch], out_gain);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = 0; j < channels; j++)
|
for (unsigned j = 0; j < channels; j++)
|
||||||
{
|
{
|
||||||
if(gain[j] > 10)
|
if(gain[j] > 10)
|
||||||
{
|
{
|
||||||
|
@ -3670,7 +3617,7 @@ void CommandSetGl841::search_strip(Genesys_Device* dev, const Genesys_Sensor& se
|
||||||
DBG_HELPER_ARGS(dbg, "%s %s", black ? "black" : "white", forward ? "forward" : "reverse");
|
DBG_HELPER_ARGS(dbg, "%s %s", black ? "black" : "white", forward ? "forward" : "reverse");
|
||||||
unsigned int pixels, lines, channels;
|
unsigned int pixels, lines, channels;
|
||||||
Genesys_Register_Set local_reg;
|
Genesys_Register_Set local_reg;
|
||||||
unsigned int pass, count, found, x, y, length;
|
unsigned int pass, count, found, length;
|
||||||
char title[80];
|
char title[80];
|
||||||
GenesysRegister *r;
|
GenesysRegister *r;
|
||||||
uint8_t white_level=90; /**< default white level to detect white dots */
|
uint8_t white_level=90; /**< default white level to detect white dots */
|
||||||
|
@ -3721,8 +3668,6 @@ void CommandSetGl841::search_strip(Genesys_Device* dev, const Genesys_Sensor& se
|
||||||
session.params.flags = ScanFlag::DISABLE_SHADING | ScanFlag::DISABLE_GAMMA;
|
session.params.flags = ScanFlag::DISABLE_SHADING | ScanFlag::DISABLE_GAMMA;
|
||||||
compute_session(dev, session, sensor);
|
compute_session(dev, session, sensor);
|
||||||
|
|
||||||
std::vector<uint8_t> data(session.output_total_bytes);
|
|
||||||
|
|
||||||
init_regs_for_scan_session(dev, sensor, &local_reg, session);
|
init_regs_for_scan_session(dev, sensor, &local_reg, session);
|
||||||
|
|
||||||
/* set up for reverse or forward */
|
/* set up for reverse or forward */
|
||||||
|
@ -3747,17 +3692,15 @@ void CommandSetGl841::search_strip(Genesys_Device* dev, const Genesys_Sensor& se
|
||||||
wait_until_buffer_non_empty(dev);
|
wait_until_buffer_non_empty(dev);
|
||||||
|
|
||||||
// now we're on target, we can read data
|
// now we're on target, we can read data
|
||||||
sanei_genesys_read_data_from_scanner(dev, data.data(), session.output_total_bytes);
|
auto image = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes);
|
||||||
|
|
||||||
gl841_stop_action(dev);
|
gl841_stop_action(dev);
|
||||||
|
|
||||||
pass = 0;
|
pass = 0;
|
||||||
if (DBG_LEVEL >= DBG_data)
|
if (DBG_LEVEL >= DBG_data) {
|
||||||
{
|
|
||||||
std::sprintf(title, "gl841_search_strip_%s_%s%02u.pnm", black ? "black" : "white",
|
std::sprintf(title, "gl841_search_strip_%s_%s%02u.pnm", black ? "black" : "white",
|
||||||
forward ? "fwd" : "bwd", pass);
|
forward ? "fwd" : "bwd", pass);
|
||||||
sanei_genesys_write_pnm_file(title, data.data(), session.params.depth,
|
sanei_genesys_write_pnm_file(title, image);
|
||||||
channels, pixels, lines);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* loop until strip is found or maximum pass number done */
|
/* loop until strip is found or maximum pass number done */
|
||||||
|
@ -3773,94 +3716,81 @@ void CommandSetGl841::search_strip(Genesys_Device* dev, const Genesys_Sensor& se
|
||||||
wait_until_buffer_non_empty(dev);
|
wait_until_buffer_non_empty(dev);
|
||||||
|
|
||||||
// now we're on target, we can read data
|
// now we're on target, we can read data
|
||||||
sanei_genesys_read_data_from_scanner(dev, data.data(), session.output_total_bytes);
|
image = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes);
|
||||||
|
|
||||||
gl841_stop_action (dev);
|
gl841_stop_action (dev);
|
||||||
|
|
||||||
if (DBG_LEVEL >= DBG_data)
|
if (DBG_LEVEL >= DBG_data) {
|
||||||
{
|
|
||||||
std::sprintf(title, "gl841_search_strip_%s_%s%02u.pnm",
|
std::sprintf(title, "gl841_search_strip_%s_%s%02u.pnm",
|
||||||
black ? "black" : "white", forward ? "fwd" : "bwd", pass);
|
black ? "black" : "white", forward ? "fwd" : "bwd", pass);
|
||||||
sanei_genesys_write_pnm_file(title, data.data(), session.params.depth,
|
sanei_genesys_write_pnm_file(title, image);
|
||||||
channels, pixels, lines);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* search data to find black strip */
|
/* search data to find black strip */
|
||||||
/* when searching forward, we only need one line of the searched color since we
|
/* 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
|
* will scan forward. But when doing backward search, we need all the area of the
|
||||||
* same color */
|
* same color */
|
||||||
if (forward)
|
if (forward) {
|
||||||
{
|
for (std::size_t y = 0; y < image.get_height() && !found; y++) {
|
||||||
for (y = 0; y < lines && !found; y++)
|
count = 0;
|
||||||
{
|
|
||||||
count = 0;
|
// count of white/black pixels depending on the color searched
|
||||||
/* count of white/black pixels depending on the color searched */
|
for (std::size_t x = 0; x < image.get_width(); x++) {
|
||||||
for (x = 0; x < pixels; x++)
|
|
||||||
{
|
// when searching for black, detect white pixels
|
||||||
/* when searching for black, detect white pixels */
|
if (black && image.get_raw_channel(x, y, 0) > white_level) {
|
||||||
if (black && data[y * pixels + x] > white_level)
|
count++;
|
||||||
{
|
}
|
||||||
count++;
|
|
||||||
}
|
// when searching for white, detect black pixels
|
||||||
/* when searching for white, detect black pixels */
|
if (!black && image.get_raw_channel(x, y, 0) < black_level) {
|
||||||
if (!black && data[y * pixels + x] < black_level)
|
count++;
|
||||||
{
|
}
|
||||||
count++;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* at end of line, if count >= 3%, line is not fully of the desired color
|
/* 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 */
|
* so we must go to next line of the buffer */
|
||||||
/* count*100/pixels < 3 */
|
auto found_percentage = (count * 100 / image.get_width());
|
||||||
if ((count * 100) / pixels < 3)
|
if (found_percentage < 3) {
|
||||||
{
|
|
||||||
found = 1;
|
found = 1;
|
||||||
DBG(DBG_data, "%s: strip found forward during pass %d at line %d\n", __func__,
|
DBG(DBG_data, "%s: strip found forward during pass %d at line %zu\n", __func__,
|
||||||
pass, y);
|
pass, y);
|
||||||
}
|
} else {
|
||||||
else
|
DBG(DBG_data, "%s: pixels=%zu, count=%d (%zu%%)\n", __func__, image.get_width(),
|
||||||
{
|
count, found_percentage);
|
||||||
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
|
||||||
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 = 0;
|
/* count of white/black pixels depending on the color searched */
|
||||||
for (y = 0; y < lines; y++)
|
for (std::size_t x = 0; x < image.get_width(); x++) {
|
||||||
{
|
// when searching for black, detect white pixels
|
||||||
/* count of white/black pixels depending on the color searched */
|
if (black && image.get_raw_channel(x, y, 0) > white_level) {
|
||||||
for (x = 0; x < pixels; x++)
|
count++;
|
||||||
{
|
}
|
||||||
/* when searching for black, detect white pixels */
|
// when searching for white, detect black pixels
|
||||||
if (black && data[y * pixels + x] > white_level)
|
if (!black && image.get_raw_channel(x, y, 0) < black_level) {
|
||||||
{
|
count++;
|
||||||
count++;
|
}
|
||||||
}
|
}
|
||||||
/* when searching for white, detect black pixels */
|
}
|
||||||
if (!black && data[y * pixels + x] < black_level)
|
|
||||||
{
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* at end of area, if count >= 3%, area is not fully of the desired color
|
/* at end of area, if count >= 3%, area is not fully of the desired color
|
||||||
* so we must go to next buffer */
|
* so we must go to next buffer */
|
||||||
if ((count * 100) / (pixels * lines) < 3)
|
auto found_percentage = count * 100 / (image.get_width() * image.get_height());
|
||||||
{
|
if (found_percentage < 3) {
|
||||||
found = 1;
|
found = 1;
|
||||||
DBG(DBG_data, "%s: strip found backward during pass %d \n", __func__, pass);
|
DBG(DBG_data, "%s: strip found backward during pass %d \n", __func__, pass);
|
||||||
}
|
} else {
|
||||||
else
|
DBG(DBG_data, "%s: pixels=%zu, count=%d (%zu%%)\n", __func__, image.get_width(), count,
|
||||||
{
|
found_percentage);
|
||||||
DBG(DBG_data, "%s: pixels=%d, count=%d (%d%%)\n", __func__, pixels, count,
|
}
|
||||||
(100 * count) / pixels);
|
}
|
||||||
}
|
pass++;
|
||||||
}
|
|
||||||
pass++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found)
|
if (found)
|
||||||
|
|
Ładowanie…
Reference in New Issue