align offset/gain calibration of gl847 on gl124 code

merge-requests/1/head
Stphane Voltz 2011-11-20 10:47:20 +01:00
rodzic d0931a27c8
commit b7a62c1d54
3 zmienionych plików z 354 dodań i 4 usunięć

Wyświetl plik

@ -1394,6 +1394,7 @@ static Genesys_Model canon_lide_100_model = {
| GENESYS_FLAG_SIS_SENSOR
| GENESYS_FLAG_MUST_WAIT
| GENESYS_FLAG_DARK_CALIBRATION
| GENESYS_FLAG_OFFSET_CALIBRATION
| GENESYS_FLAG_CUSTOM_GAMMA,
GENESYS_HAS_SCAN_SW | GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_FILE_SW,
40,
@ -1550,6 +1551,7 @@ static Genesys_Model canon_5600f_model = {
| GENESYS_FLAG_SKIP_WARMUP
| GENESYS_FLAG_SIS_SENSOR
| GENESYS_FLAG_DARK_CALIBRATION
| GENESYS_FLAG_OFFSET_CALIBRATION
| GENESYS_FLAG_CUSTOM_GAMMA,
GENESYS_HAS_SCAN_SW | GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_FILE_SW,
60,

Wyświetl plik

@ -766,7 +766,7 @@ gl847_set_fe (Genesys_Device * dev, uint8_t set)
return gl847_set_ad_fe (dev, set);
}
/* for now ther is no support for wolfson fe */
/* for now there is no support yet for wolfson fe */
DBG (DBG_proc, "gl847_set_fe(): unsupported frontend type %d\n",
dev->reg[reg_0x04].value & REG04_FESET);
@ -3695,6 +3695,354 @@ gl847_search_strip (Genesys_Device * dev, SANE_Bool forward, SANE_Bool black)
return status;
}
/**
* average dark pixels of a 8 bits scan
*/
static int
dark_average (uint8_t * data, unsigned int pixels, unsigned int lines,
unsigned int channels, unsigned int black)
{
unsigned int i, j, k, average, count;
unsigned int avg[3];
uint8_t val;
/* computes average value on black margin */
for (k = 0; k < channels; k++)
{
avg[k] = 0;
count = 0;
for (i = 0; i < lines; i++)
{
for (j = 0; j < black; j++)
{
val = data[i * channels * pixels + j + k];
avg[k] += val;
count++;
}
}
if (count)
avg[k] /= count;
DBG (DBG_info, "dark_average: avg[%d] = %d\n", k, avg[k]);
}
average = 0;
for (i = 0; i < channels; i++)
average += avg[i];
average /= channels;
DBG (DBG_info, "dark_average: average = %d\n", average);
return average;
}
static SANE_Status
gl847_offset_calibration (Genesys_Device * dev)
{
SANE_Status status = SANE_STATUS_GOOD;
uint8_t *first_line, *second_line, reg04;
unsigned int channels, bpp;
char title[32];
int pass = 0, avg, total_size;
int topavg, bottomavg, resolution, lines;
int top, bottom, black_pixels, pixels;
DBGSTART;
/* no gain nor offset for AKM AFE */
RIE (sanei_genesys_read_register (dev, REG04, &reg04));
if ((reg04 & REG04_FESET) == 0x02)
{
DBGCOMPLETED;
return status;
}
/* offset calibration is always done in color mode */
channels = 3;
resolution=dev->sensor.optical_res;
dev->calib_pixels = dev->sensor.sensor_pixels;
lines=1;
bpp=8;
pixels= (dev->sensor.sensor_pixels*resolution) / dev->sensor.optical_res;
black_pixels = (dev->sensor.black_pixels * resolution) / dev->sensor.optical_res;
DBG (DBG_io2, "gl847_offset_calibration: black_pixels=%d\n", black_pixels);
status = gl847_init_scan_regs (dev,
dev->calib_reg,
resolution,
resolution,
0,
0,
pixels,
lines,
bpp,
channels,
dev->settings.color_filter,
SCAN_FLAG_DISABLE_SHADING |
SCAN_FLAG_DISABLE_GAMMA |
SCAN_FLAG_SINGLE_LINE |
SCAN_FLAG_IGNORE_LINE_DISTANCE);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"gl847_offset_calibration: failed to setup scan: %s\n",
sane_strstatus (status));
return status;
}
gl847_set_motor_power (dev->calib_reg, SANE_FALSE);
/* allocate memory for scans */
total_size = pixels * channels * lines * (bpp/8); /* colors * bytes_per_color * scan lines */
first_line = malloc (total_size);
if (!first_line)
return SANE_STATUS_NO_MEM;
second_line = malloc (total_size);
if (!second_line)
{
free (first_line);
return SANE_STATUS_NO_MEM;
}
/* init gain */
dev->frontend.gain[0] = 0;
dev->frontend.gain[1] = 0;
dev->frontend.gain[2] = 0;
/* scan with no move */
bottom = 10;
dev->frontend.offset[0] = bottom;
dev->frontend.offset[1] = bottom;
dev->frontend.offset[2] = bottom;
RIE (gl847_set_fe(dev, AFE_SET));
RIE (gl847_bulk_write_register (dev, dev->calib_reg, GENESYS_GL847_MAX_REGS));
DBG (DBG_info, "gl847_offset_calibration: starting first line reading\n");
RIE (gl847_begin_scan (dev, dev->calib_reg, SANE_TRUE));
RIE (sanei_genesys_read_data_from_scanner (dev, first_line, total_size));
if (DBG_LEVEL >= DBG_data)
{
snprintf(title,20,"offset%03d.pnm",bottom);
sanei_genesys_write_pnm_file (title, first_line, bpp, channels, pixels, lines);
}
bottomavg = dark_average (first_line, pixels, lines, channels, black_pixels);
DBG (DBG_io2, "gl847_offset_calibration: bottom avg=%d\n", bottomavg);
/* now top value */
top = 255;
dev->frontend.offset[0] = top;
dev->frontend.offset[1] = top;
dev->frontend.offset[2] = top;
RIE (gl847_set_fe(dev, AFE_SET));
RIE (gl847_bulk_write_register (dev, dev->calib_reg, GENESYS_GL847_MAX_REGS));
DBG (DBG_info, "gl847_offset_calibration: starting second line reading\n");
RIE (gl847_begin_scan (dev, dev->calib_reg, SANE_TRUE));
RIE (sanei_genesys_read_data_from_scanner (dev, second_line, total_size));
topavg = dark_average (second_line, pixels, lines, channels, black_pixels);
DBG (DBG_io2, "gl847_offset_calibration: top avg=%d\n", topavg);
/* loop until acceptable level */
while ((pass < 32) && (top - bottom > 1))
{
pass++;
/* settings for new scan */
dev->frontend.offset[0] = (top + bottom) / 2;
dev->frontend.offset[1] = (top + bottom) / 2;
dev->frontend.offset[2] = (top + bottom) / 2;
/* scan with no move */
RIE(gl847_set_fe(dev, AFE_SET));
RIE (gl847_bulk_write_register (dev, dev->calib_reg, GENESYS_GL847_MAX_REGS));
DBG (DBG_info, "gl847_offset_calibration: starting second line reading\n");
RIE (gl847_begin_scan (dev, dev->calib_reg, SANE_TRUE));
RIE (sanei_genesys_read_data_from_scanner (dev, second_line, total_size));
if (DBG_LEVEL >= DBG_data)
{
sprintf (title, "offset%03d.pnm", dev->frontend.offset[1]);
sanei_genesys_write_pnm_file (title, second_line, bpp, channels, pixels, lines);
}
avg = dark_average (second_line, pixels, lines, channels, black_pixels);
DBG (DBG_info, "gl847_offset_calibration: avg=%d offset=%d\n", avg,
dev->frontend.offset[1]);
/* compute new boundaries */
if (topavg == avg)
{
topavg = avg;
top = dev->frontend.offset[1];
}
else
{
bottomavg = avg;
bottom = dev->frontend.offset[1];
}
}
DBG (DBG_info, "gl847_offset_calibration: offset=(%d,%d,%d)\n", dev->frontend.offset[0], dev->frontend.offset[1], dev->frontend.offset[2]);
/* cleanup before return */
free (first_line);
free (second_line);
DBGCOMPLETED;
return SANE_STATUS_GOOD;
}
static SANE_Status
gl847_coarse_gain_calibration (Genesys_Device * dev, int dpi)
{
int pixels;
int total_size;
uint8_t *line, reg04;
int i, j, channels;
SANE_Status status = SANE_STATUS_GOOD;
int max[3];
float gain[3],coeff;
int val, code, lines;
int resolution;
int bpp;
DBG (DBG_proc, "gl847_coarse_gain_calibration: dpi = %d\n", dpi);
/* no gain nor offset for AKM AFE */
RIE (sanei_genesys_read_register (dev, REG04, &reg04));
if ((reg04 & REG04_FESET) == 0x02)
{
DBGCOMPLETED;
return status;
}
/* coarse gain calibration is always done in color mode */
channels = 3;
/* follow CKSEL */
if(dev->settings.xres<dev->sensor.optical_res)
{
coeff=0.9;
resolution=dev->sensor.optical_res/2;
resolution=dev->sensor.optical_res;
}
else
{
resolution=dev->sensor.optical_res;
coeff=1.0;
}
lines=10;
bpp=8;
pixels = (dev->sensor.sensor_pixels * resolution) / dev->sensor.optical_res;
status = gl847_init_scan_regs (dev,
dev->calib_reg,
resolution,
resolution,
0,
0,
pixels,
lines,
bpp,
channels,
dev->settings.color_filter,
SCAN_FLAG_DISABLE_SHADING |
SCAN_FLAG_DISABLE_GAMMA |
SCAN_FLAG_SINGLE_LINE |
SCAN_FLAG_IGNORE_LINE_DISTANCE);
gl847_set_motor_power (dev->calib_reg, SANE_FALSE);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"gl847_coarse_calibration: failed to setup scan: %s\n",
sane_strstatus (status));
return status;
}
RIE (gl847_bulk_write_register
(dev, dev->calib_reg, GENESYS_GL847_MAX_REGS));
total_size = pixels * channels * (16/bpp) * lines;
line = malloc (total_size);
if (!line)
return SANE_STATUS_NO_MEM;
RIE (gl847_set_fe(dev, AFE_SET));
RIE (gl847_begin_scan (dev, dev->calib_reg, SANE_TRUE));
RIE (sanei_genesys_read_data_from_scanner (dev, line, total_size));
if (DBG_LEVEL >= DBG_data)
sanei_genesys_write_pnm_file ("coarse.pnm", line, bpp, channels, pixels, lines);
/* average value on each channel */
for (j = 0; j < channels; j++)
{
max[j] = 0;
for (i = pixels/4; i < (pixels*3/4); i++)
{
if(bpp==16)
{
if (dev->model->is_cis)
val =
line[i * 2 + j * 2 * pixels + 1] * 256 +
line[i * 2 + j * 2 * pixels];
else
val =
line[i * 2 * channels + 2 * j + 1] * 256 +
line[i * 2 * channels + 2 * j];
}
else
{
if (dev->model->is_cis)
val = line[i + j * pixels];
else
val = line[i * channels + j];
}
max[j] += val;
}
max[j] = max[j] / (pixels/2);
gain[j] = ((float) dev->sensor.gain_white_ref*coeff) / max[j];
/* turn logical gain value into gain code, checking for overflow */
code = 283 - 208 / gain[j];
if (code > 255)
code = 255;
else if (code < 0)
code = 0;
dev->frontend.gain[j] = code;
DBG (DBG_proc,
"gl847_coarse_gain_calibration: channel %d, max=%d, gain = %f, setting:%d\n",
j, max[j], gain[j], dev->frontend.gain[j]);
}
if (dev->model->is_cis)
{
if (dev->frontend.gain[0] > dev->frontend.gain[1])
dev->frontend.gain[0] = dev->frontend.gain[1];
if (dev->frontend.gain[0] > dev->frontend.gain[2])
dev->frontend.gain[0] = dev->frontend.gain[2];
dev->frontend.gain[2] = dev->frontend.gain[1] = dev->frontend.gain[0];
}
if (channels == 1)
{
dev->frontend.gain[0] = dev->frontend.gain[1];
dev->frontend.gain[2] = dev->frontend.gain[1];
}
free (line);
RIE (gl847_stop_action (dev));
gl847_slow_back_home (dev, SANE_TRUE);
DBGCOMPLETED;
return SANE_STATUS_GOOD;
}
/** the gl847 command set */
static Genesys_Command_Set gl847_cmd_set = {
"gl847-generic", /* the name of this set */
@ -3729,8 +4077,8 @@ static Genesys_Command_Set gl847_cmd_set = {
gl847_search_start_position,
NULL, /*gl847_offset_calibration*/
NULL, /*gl847_coarse_gain_calibration*/
gl847_offset_calibration,
gl847_coarse_gain_calibration,
gl847_led_calibration,
gl847_slow_back_home,

Wyświetl plik

@ -3,7 +3,7 @@
Copyright (C) 2003 Oliver Rauch
Copyright (C) 2003, 2004 Henning Meier-Geinitz <henning@meier-geinitz.de>
Copyright (C) 2004, 2005 Gerhard Jaeger <gerhard@gjaeger.de>
Copyright (C) 2004-2011 St<EFBFBD>phane Voltz <stef.dev@free.fr>
Copyright (C) 2004-2011 Stéphane Voltz <stef.dev@free.fr>
Copyright (C) 2005-2009 Pierre Willenbrock <pierre@pirsoft.dnsalias.org>
Copyright (C) 2006 Laurent Charpentier <laurent_pubs@yahoo.com>
Parts of the structs have been taken from the gt68xx backend by