gl843 3 way dichotomy for offset calibration

merge-requests/1/head
Stphane Voltz 2011-09-20 21:56:01 +02:00
rodzic 85eade8436
commit c7e0cbd84c
1 zmienionych plików z 96 dodań i 71 usunięć

Wyświetl plik

@ -3059,18 +3059,19 @@ gl843_led_calibration (Genesys_Device * dev)
} }
/** /**
* average dark pixels of a 8 bits scan * average dark pixels of a 8 bits scan of a given channel
*/ */
static int static int
dark_average (uint8_t * data, unsigned int pixels, unsigned int lines, dark_average_channel (uint8_t * data, unsigned int pixels, unsigned int lines,
unsigned int channels, unsigned int black) unsigned int channels, unsigned int black, int channel)
{ {
unsigned int i, j, k, average, count; unsigned int i, j, k, count;
unsigned int avg[3]; unsigned int avg[3];
uint8_t val; uint8_t val;
/* computes average value on black margin */ /* computes average values on black margin */
for (k = 0; k < channels; k++) for (k = 0; k < channels; k++)
{ {
avg[k] = 0; avg[k] = 0;
@ -3079,21 +3080,17 @@ dark_average (uint8_t * data, unsigned int pixels, unsigned int lines,
{ {
for (j = 0; j < black; j++) for (j = 0; j < black; j++)
{ {
val = data[i * channels * pixels + j + k]; val = data[i * channels * pixels + j*channels + k];
avg[k] += val; avg[k] += val;
count++; count++;
} }
} }
if (count) if (count)
avg[k] /= count; avg[k] /= count;
DBG (DBG_info, "dark_average: avg[%d] = %d\n", k, avg[k]); DBG (DBG_info, "%s: avg[%d] = %d\n", __FUNCTION__, k, avg[k]);
} }
average = 0; DBG (DBG_info, "%s: average = %d\n", __FUNCTION__, avg[channel]);
for (i = 0; i < channels; i++) return avg[channel];
average += avg[i];
average /= channels;
DBG (DBG_info, "dark_average: average = %d\n", average);
return average;
} }
/** @brief calibrate AFE offset /** @brief calibrate AFE offset
@ -3108,22 +3105,22 @@ gl843_offset_calibration (Genesys_Device * dev)
uint8_t *first_line, *second_line; uint8_t *first_line, *second_line;
unsigned int channels, bpp; unsigned int channels, bpp;
char title[32]; char title[32];
int pass = 0, avg, total_size; int pass, total_size, i, resolution, lines;
int topavg, bottomavg, resolution, lines; int topavg[3], bottomavg[3], avg[3];
int top, bottom, black_pixels, pixels, factor, dpihw; int top[3], bottom[3], black_pixels, pixels, factor, dpihw;
DBGSTART; DBGSTART;
/* offset calibration is always done in color mode */ /* offset calibration is always done in color mode */
channels = 3; channels = 3;
lines=8; lines = 8;
bpp=8; bpp = 8;
/* compute divider factor to compute final pixels number */ /* compute divider factor to compute final pixels number */
dpihw=sanei_genesys_compute_dpihw(dev,dev->settings.xres); dpihw = sanei_genesys_compute_dpihw (dev, dev->settings.xres);
factor=dev->sensor.optical_res/dpihw; factor = dev->sensor.optical_res / dpihw;
resolution=dpihw; resolution = dpihw;
pixels = dev->sensor.sensor_pixels/factor; pixels = dev->sensor.sensor_pixels / factor;
black_pixels = dev->sensor.black_pixels / factor; black_pixels = dev->sensor.black_pixels / factor;
DBG (DBG_io, "gl843_offset_calibration: dpihw =%d\n", dpihw); DBG (DBG_io, "gl843_offset_calibration: dpihw =%d\n", dpihw);
DBG (DBG_io, "gl843_offset_calibration: factor =%d\n", factor); DBG (DBG_io, "gl843_offset_calibration: factor =%d\n", factor);
@ -3141,7 +3138,7 @@ gl843_offset_calibration (Genesys_Device * dev)
lines, lines,
bpp, bpp,
channels, channels,
SCAN_MODE_COLOR, SCAN_MODE_COLOR,
0, 0,
SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_SHADING |
SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_DISABLE_GAMMA |
@ -3149,15 +3146,14 @@ gl843_offset_calibration (Genesys_Device * dev)
SCAN_FLAG_IGNORE_LINE_DISTANCE); SCAN_FLAG_IGNORE_LINE_DISTANCE);
if (status != SANE_STATUS_GOOD) if (status != SANE_STATUS_GOOD)
{ {
DBG (DBG_error, DBG (DBG_error, "gl843_offset_calibration: failed to setup scan: %s\n",
"gl843_offset_calibration: failed to setup scan: %s\n",
sane_strstatus (status)); sane_strstatus (status));
return status; return status;
} }
gl843_set_motor_power (dev->calib_reg, SANE_FALSE); gl843_set_motor_power (dev->calib_reg, SANE_FALSE);
/* allocate memory for scans */ /* allocate memory for scans */
total_size = pixels * channels * lines * (bpp/8); /* colors * bytes_per_color * scan lines */ total_size = pixels * channels * lines * (bpp / 8); /* colors * bytes_per_color * scan lines */
first_line = malloc (total_size); first_line = malloc (total_size);
if (!first_line) if (!first_line)
@ -3170,57 +3166,75 @@ gl843_offset_calibration (Genesys_Device * dev)
return SANE_STATUS_NO_MEM; return SANE_STATUS_NO_MEM;
} }
/* init gain */ /* init gain and offset */
dev->frontend.gain[0] = 0; for (i = 0; i < 3; i++)
dev->frontend.gain[1] = 0; {
dev->frontend.gain[2] = 0; bottom[i] = 10;
dev->frontend.offset[i] = bottom[i];
dev->frontend.gain[i] = 0;
}
RIE (gl843_set_fe (dev, AFE_SET));
/* scan with no move */ /* scan with obttom AFE settings */
bottom = 10;
dev->frontend.offset[0] = bottom;
dev->frontend.offset[1] = bottom;
dev->frontend.offset[2] = bottom;
RIE (gl843_set_fe(dev, AFE_SET));
RIE (gl843_bulk_write_register (dev, dev->calib_reg, GENESYS_GL843_MAX_REGS)); RIE (gl843_bulk_write_register (dev, dev->calib_reg, GENESYS_GL843_MAX_REGS));
DBG (DBG_info, "gl843_offset_calibration: starting first line reading\n"); DBG (DBG_info, "gl843_offset_calibration: starting first line reading\n");
RIE (gl843_begin_scan (dev, dev->calib_reg, SANE_TRUE)); RIE (gl843_begin_scan (dev, dev->calib_reg, SANE_TRUE));
RIE (sanei_genesys_read_data_from_scanner (dev, first_line, total_size)); RIE (sanei_genesys_read_data_from_scanner (dev, first_line, total_size));
if (DBG_LEVEL >= DBG_data) if (DBG_LEVEL >= DBG_data)
{ {
snprintf(title,20,"offset%03d.pnm",bottom); for (i = 0; i < 3; i++)
sanei_genesys_write_pnm_file (title, first_line, bpp, channels, pixels, lines); {
} snprintf (title, 20, "offset_%d_%03d.pnm", i, bottom[i]);
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, "gl843_offset_calibration: bottom avg=%d\n", bottomavg); }
for (i = 0; i < 3; i++)
{
bottomavg[i] = dark_average_channel (first_line, pixels, lines, channels, black_pixels, i);
DBG (DBG_io2, "gl843_offset_calibration: bottom avg %d=%d\n", i, bottomavg[i]);
}
/* now top value */ /* now top value */
top = 255; for (i = 0; i < 3; i++)
dev->frontend.offset[0] = top; {
dev->frontend.offset[1] = top; top[i] = 255;
dev->frontend.offset[2] = top; dev->frontend.offset[i] = top[i];
RIE (gl843_set_fe(dev, AFE_SET)); }
RIE (gl843_set_fe (dev, AFE_SET));
/* scan with top AFE values */
RIE (gl843_bulk_write_register (dev, dev->calib_reg, GENESYS_GL843_MAX_REGS)); RIE (gl843_bulk_write_register (dev, dev->calib_reg, GENESYS_GL843_MAX_REGS));
DBG (DBG_info, "gl843_offset_calibration: starting second line reading\n"); DBG (DBG_info, "gl843_offset_calibration: starting second line reading\n");
RIE (gl843_begin_scan (dev, dev->calib_reg, SANE_TRUE)); RIE (gl843_begin_scan (dev, dev->calib_reg, SANE_TRUE));
RIE (sanei_genesys_read_data_from_scanner (dev, second_line, total_size)); RIE (sanei_genesys_read_data_from_scanner (dev, second_line, total_size));
topavg = dark_average (second_line, pixels, lines, channels, black_pixels); for (i = 0; i < 3; i++)
DBG (DBG_io2, "gl843_offset_calibration: top avg=%d\n", topavg); {
topavg[i] = dark_average_channel (second_line, pixels, lines, channels, black_pixels, i);
DBG (DBG_io2, "gl843_offset_calibration: top avg %d=%d\n", i, topavg[i]);
}
pass = 0;
/* loop until acceptable level */ /* loop until acceptable level */
while ((pass < 32) && (top - bottom > 1)) while ((pass < 32)
&& ((top[0] - bottom[0] > 1)
|| (top[1] - bottom[1] > 1) || (top[2] - bottom[2] > 1)))
{ {
pass++; pass++;
/* settings for new scan */ /* settings for new scan */
dev->frontend.offset[0] = (top + bottom) / 2; for (i = 0; i < 3; i++)
dev->frontend.offset[1] = (top + bottom) / 2; {
dev->frontend.offset[2] = (top + bottom) / 2; if (top[i] - bottom[i] > 1)
{
dev->frontend.offset[i] = (top[i] + bottom[i]) / 2;
}
}
RIE (gl843_set_fe (dev, AFE_SET));
/* scan with no move */ /* scan with no move */
RIE(gl843_set_fe(dev, AFE_SET));
RIE (gl843_bulk_write_register (dev, dev->calib_reg, GENESYS_GL843_MAX_REGS)); RIE (gl843_bulk_write_register (dev, dev->calib_reg, GENESYS_GL843_MAX_REGS));
DBG (DBG_info, "gl843_offset_calibration: starting second line reading\n"); DBG (DBG_info, "gl843_offset_calibration: starting second line reading\n");
RIE (gl843_begin_scan (dev, dev->calib_reg, SANE_TRUE)); RIE (gl843_begin_scan (dev, dev->calib_reg, SANE_TRUE));
@ -3228,27 +3242,38 @@ gl843_offset_calibration (Genesys_Device * dev)
if (DBG_LEVEL >= DBG_data) if (DBG_LEVEL >= DBG_data)
{ {
sprintf (title, "offset%03d.pnm", dev->frontend.offset[1]); for (i = 0; i < 3; i++)
sanei_genesys_write_pnm_file (title, second_line, bpp, channels, pixels, lines); {
sprintf (title, "offset_%d_%03d.pnm", i, dev->frontend.offset[i]);
sanei_genesys_write_pnm_file (title, second_line, bpp, channels, pixels, lines);
}
} }
avg = dark_average (second_line, pixels, lines, channels, black_pixels); for (i = 0; i < 3; i++)
DBG (DBG_info, "gl843_offset_calibration: avg=%d offset=%d\n", avg, {
dev->frontend.offset[1]); avg[i] = dark_average_channel (second_line, pixels, lines, channels, black_pixels, i);
DBG (DBG_info, "gl843_offset_calibration: avg[%d]=%d offset=%d\n", i, avg[i], dev->frontend.offset[i]);
}
/* compute new boundaries */ /* compute new boundaries */
if (topavg == avg) for (i = 0; i < 3; i++)
{ {
topavg = avg; if (topavg[i] >= avg[i])
top = dev->frontend.offset[1]; {
} topavg[i] = avg[i];
else top[i] = dev->frontend.offset[i];
{ }
bottomavg = avg; else
bottom = dev->frontend.offset[1]; {
bottomavg[i] = avg[i];
bottom[i] = dev->frontend.offset[i];
}
} }
} }
DBG (DBG_info, "gl843_offset_calibration: offset=(%d,%d,%d)\n", dev->frontend.offset[0], dev->frontend.offset[1], dev->frontend.offset[2]); DBG (DBG_info, "gl843_offset_calibration: offset=(%d,%d,%d)\n",
dev->frontend.offset[0],
dev->frontend.offset[1],
dev->frontend.offset[2]);
/* cleanup before return */ /* cleanup before return */
free (first_line); free (first_line);