kopia lustrzana https://gitlab.com/sane-project/backends
working version for KV-SS080
- offset and gain calibration are tunedmerge-requests/1/head
rodzic
bee968b93d
commit
e72d6c1007
|
@ -1511,7 +1511,7 @@ genesys_send_offset_and_shading (Genesys_Device * dev, uint8_t * data,
|
|||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
status = dev->model->cmd_set->bulk_write_data (dev, 0x3c, data, size);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
|
@ -2548,14 +2548,8 @@ genesys_dummy_dark_shading (Genesys_Device * dev)
|
|||
|
||||
DBG (DBG_proc, "genesys_dummy_dark_shading \n");
|
||||
|
||||
pixels_per_line =
|
||||
(genesys_pixels_per_line (dev->calib_reg)
|
||||
* genesys_dpiset (dev->calib_reg)) / dev->sensor.optical_res;
|
||||
|
||||
if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */
|
||||
channels = 3;
|
||||
else
|
||||
channels = 1;
|
||||
pixels_per_line = dev->calib_pixels;
|
||||
channels = dev->calib_channels;
|
||||
|
||||
FREE_IFNOT_NULL (dev->dark_average_data);
|
||||
|
||||
|
@ -2583,8 +2577,8 @@ genesys_dummy_dark_shading (Genesys_Device * dev)
|
|||
}
|
||||
if(dev->model->ccd_type==CCD_KVSS080)
|
||||
{
|
||||
skip = 0;
|
||||
xend = 40;
|
||||
skip = 2;
|
||||
xend = dev->sensor.black_pixels;
|
||||
}
|
||||
|
||||
/* average each channels on half left margin */
|
||||
|
@ -3102,7 +3096,6 @@ compute_averaged_planar (Genesys_Device * dev,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Computes shading coefficient using formula in data sheet. 16bit data values
|
||||
* manipulated here are little endian. For now we assume deletion scanning type
|
||||
|
@ -3135,7 +3128,7 @@ compute_coefficients (Genesys_Device * dev,
|
|||
|
||||
DBG (DBG_io,
|
||||
"compute_coefficients: pixels_per_line=%d, coeff=0x%04x\n", pixels_per_line, coeff);
|
||||
|
||||
|
||||
/* compute start & end values depending of the offset */
|
||||
if (offset < 0)
|
||||
{
|
||||
|
@ -3171,6 +3164,7 @@ compute_coefficients (Genesys_Device * dev,
|
|||
ptr[1] = dk / 256;
|
||||
ptr[2] = val & 0xff;
|
||||
ptr[3] = val / 256;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3268,9 +3262,10 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
|
|||
{
|
||||
SANE_Status status;
|
||||
uint16_t pixels_per_line;
|
||||
uint16_t *fixup,*shading;
|
||||
uint8_t *shading_data; /**> contains 16bit words in little endian */
|
||||
uint8_t channels;
|
||||
unsigned int x, j;
|
||||
unsigned int x, j, src, dst;
|
||||
int o;
|
||||
unsigned int length; /**> number of shading calibration data words */
|
||||
unsigned int i, res, factor;
|
||||
|
@ -3459,11 +3454,32 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
|
|||
compute_coefficients (dev,
|
||||
shading_data,
|
||||
pixels_per_line,
|
||||
3,
|
||||
3,
|
||||
cmat,
|
||||
o,
|
||||
coeff,
|
||||
target_code);
|
||||
/* shading data fixup */
|
||||
shading=(uint16_t *)shading_data;
|
||||
fixup = malloc ((length*256)/252+512);
|
||||
if (!shading_data)
|
||||
{
|
||||
DBG (DBG_error, "%s: failed to allocate memory for shading fixup\n",__FUNCTION__);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
src=0;
|
||||
dst=0;
|
||||
while(src<length/2)
|
||||
{
|
||||
fixup[dst]=shading[src];
|
||||
if((dst%256)==252)
|
||||
dst+=4;
|
||||
dst++;
|
||||
src++;
|
||||
}
|
||||
free(shading_data);
|
||||
shading_data=fixup;
|
||||
length = ((length*256)/252+512);
|
||||
break;
|
||||
case CIS_CANONLIDE100:
|
||||
case CIS_CANONLIDE200:
|
||||
|
@ -6397,6 +6413,7 @@ static SANE_Status
|
|||
check_present (SANE_String_Const devname)
|
||||
{
|
||||
present=SANE_TRUE;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
static SANE_Status
|
||||
|
@ -6460,7 +6477,6 @@ attach (SANE_String_Const devname, Genesys_Device ** devp, SANE_Bool may_wait)
|
|||
sanei_usb_find_devices (vendor, 0x1006, check_present);
|
||||
sanei_usb_find_devices (vendor, 0x1007, check_present);
|
||||
sanei_usb_find_devices (vendor, 0x1010, check_present);
|
||||
sanei_usb_find_devices (vendor, 0x100f, check_present);
|
||||
if(present==SANE_FALSE)
|
||||
{
|
||||
DBG (DBG_error,"attach: master device not present\n");
|
||||
|
|
|
@ -470,12 +470,12 @@ static Genesys_Sensor Sensor[] = {
|
|||
,
|
||||
{CCD_KVSS080,
|
||||
600,
|
||||
64, /* 48 */
|
||||
36,
|
||||
38, /* black pixels on left */
|
||||
38, /* 36 dummy pixels */
|
||||
152,
|
||||
5100,
|
||||
210,
|
||||
230,
|
||||
5200, /* 5100 */
|
||||
160, /* TAU white ref */
|
||||
160, /* gain white ref */
|
||||
/* 08 09 0a 0b */
|
||||
{0x00, 0x00, 0x00, 0x6a} ,
|
||||
/* 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d */
|
||||
|
@ -1009,11 +1009,11 @@ static Genesys_Model panasonic_kvss080_model = {
|
|||
{16, 8, 0}, /* possible depths in color mode */
|
||||
|
||||
SANE_FIX (7.6), /* Start of scan area in mm (x) */
|
||||
SANE_FIX (12.6), /* Start of scan area in mm (y) */
|
||||
SANE_FIX (12.5), /* Start of scan area in mm (y) */
|
||||
SANE_FIX (218.5), /* Size of scan area in mm (x) */
|
||||
SANE_FIX (297.0), /* Size of scan area in mm (y) */
|
||||
|
||||
SANE_FIX (0.0), /* Start of white strip in mm (y) */
|
||||
SANE_FIX (9.0), /* Start of white strip in mm (y) */
|
||||
SANE_FIX (0.0), /* Start of black mark in mm (x) */
|
||||
|
||||
SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */
|
||||
|
@ -1039,12 +1039,14 @@ static Genesys_Model panasonic_kvss080_model = {
|
|||
GPO_KVSS080,
|
||||
MOTOR_KVSS080,
|
||||
GENESYS_FLAG_LAZY_INIT |
|
||||
GENESYS_FLAG_NO_CALIBRATION |
|
||||
GENESYS_FLAG_SKIP_WARMUP |
|
||||
/* GENESYS_FLAG_NO_CALIBRATION | */
|
||||
/* GENESYS_FLAG_DARK_CALIBRATION | */
|
||||
GENESYS_FLAG_OFFSET_CALIBRATION |
|
||||
GENESYS_FLAG_CUSTOM_GAMMA,
|
||||
GENESYS_HAS_SCAN_SW ,
|
||||
280,
|
||||
400
|
||||
100,
|
||||
100
|
||||
};
|
||||
|
||||
static Genesys_Model hpg4050_model = {
|
||||
|
|
|
@ -148,6 +148,8 @@ gl843_bulk_write_data (Genesys_Device * dev, uint8_t addr,
|
|||
return status;
|
||||
}
|
||||
|
||||
/* recreate data buffer to take care of memory layout */
|
||||
|
||||
status = sanei_usb_write_bulk (dev->dn, data, &size);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
|
@ -979,7 +981,6 @@ gl843_init_motor_regs_scan (Genesys_Device * dev,
|
|||
{
|
||||
dist += fast_steps*2;
|
||||
}
|
||||
/* dist <<= scan_step_type; */
|
||||
DBG (DBG_io2, "%s: acceleration distance=%d\n", __FUNCTION__, dist);
|
||||
|
||||
/* get sure when don't insane value */
|
||||
|
@ -1068,7 +1069,7 @@ gl843_get_dpihw (Genesys_Device * dev)
|
|||
/** @brief setup optical related registers
|
||||
* start and pixels are expressed in optical sensor resolution coordinate
|
||||
* space. To handle odd/even case we double the resolution and
|
||||
* use only first logival half the sensor whic maps to effectice CCD.
|
||||
* use only first logival half the sensor whic maps to effective CCD.
|
||||
* @param start logical start pixel coordinate
|
||||
* @param pixels logical number of pixels to use
|
||||
* @return SANE_STATUS_GOOD if OK
|
||||
|
@ -1133,6 +1134,7 @@ gl843_init_optical_regs_scan (Genesys_Device * dev,
|
|||
{
|
||||
r->value |= REG01_DVDSET;
|
||||
}
|
||||
r->value &= ~REG01_DVDSET;
|
||||
|
||||
r = sanei_genesys_get_address (reg, REG03);
|
||||
r->value &= ~REG03_AVEENB;
|
||||
|
@ -2291,8 +2293,7 @@ gl843_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home)
|
|||
SCAN_FLAG_DISABLE_SHADING |
|
||||
SCAN_FLAG_DISABLE_GAMMA |
|
||||
SCAN_FLAG_SINGLE_LINE |
|
||||
SCAN_FLAG_IGNORE_LINE_DISTANCE |
|
||||
SCAN_FLAG_USE_OPTICAL_RES);
|
||||
SCAN_FLAG_IGNORE_LINE_DISTANCE);
|
||||
gl843_init_motor_regs_scan (dev,
|
||||
local_reg,
|
||||
8000,
|
||||
|
@ -2480,10 +2481,9 @@ gl843_init_regs_for_coarse_calibration (Genesys_Device * dev)
|
|||
SANE_Status status;
|
||||
uint8_t channels;
|
||||
uint8_t cksel;
|
||||
Genesys_Register_Set *r;
|
||||
|
||||
DBG (DBG_proc, "gl843_init_regs_for_coarse_calibration\n");
|
||||
|
||||
|
||||
DBGSTART;
|
||||
cksel = (dev->calib_reg[reg_0x18].value & REG18_CKSEL) + 1; /* clock speed = 1..4 clocks */
|
||||
|
||||
/* set line size */
|
||||
|
@ -2510,10 +2510,12 @@ gl843_init_regs_for_coarse_calibration (Genesys_Device * dev)
|
|||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"gl843_init_register_for_coarse_calibration: Failed to setup scan: %s\n",
|
||||
"gl843_init_register_for_coarse_calibration: failed to setup scan: %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
r = sanei_genesys_get_address (dev->calib_reg, REG02);
|
||||
r->value &= ~REG02_MTRPWR;
|
||||
|
||||
DBG (DBG_info,
|
||||
"gl843_init_register_for_coarse_calibration: optical sensor res: %d dpi, actual res: %d\n",
|
||||
|
@ -2524,17 +2526,12 @@ gl843_init_regs_for_coarse_calibration (Genesys_Device * dev)
|
|||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"gl843_init_register_for_coarse_calibration: Failed to bulk write registers: %s\n",
|
||||
"gl843_init_register_for_coarse_calibration: failed to bulk write registers: %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
|
||||
DBG (DBG_proc, "gl843_init_register_for_coarse_calibration: completed\n");
|
||||
|
||||
/* if (DBG_LEVEL >= DBG_info)
|
||||
sanei_gl843_print_registers (dev->calib_reg);*/
|
||||
|
||||
|
||||
DBGCOMPLETED;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
@ -2544,24 +2541,33 @@ static SANE_Status
|
|||
gl843_init_regs_for_shading (Genesys_Device * dev)
|
||||
{
|
||||
SANE_Status status;
|
||||
int move,resolution;
|
||||
|
||||
DBG (DBG_proc, "gl843_init_regs_for_shading: lines = %d\n",
|
||||
dev->model->shading_lines);
|
||||
|
||||
dev->calib_channels = 3;
|
||||
|
||||
|
||||
/* initial calibration reg values */
|
||||
memcpy (dev->calib_reg, dev->reg,
|
||||
GENESYS_GL843_MAX_REGS * sizeof (Genesys_Register_Set));
|
||||
|
||||
dev->calib_channels = 3;
|
||||
/* follow CKSEL */
|
||||
if(dev->settings.xres<dev->sensor.optical_res)
|
||||
resolution=dev->sensor.optical_res/2;
|
||||
else
|
||||
resolution=dev->sensor.optical_res;
|
||||
dev->calib_pixels = dev->sensor.sensor_pixels;
|
||||
|
||||
/* distance to move to reach white target */
|
||||
move = SANE_UNFIX (dev->model->y_offset_calib);
|
||||
move = (move * dev->sensor.optical_res) / MM_PER_INCH;
|
||||
|
||||
status = gl843_init_scan_regs (dev,
|
||||
dev->calib_reg,
|
||||
resolution,
|
||||
dev->sensor.optical_res,
|
||||
dev->motor.base_ydpi,
|
||||
0,
|
||||
0,
|
||||
move,
|
||||
dev->calib_pixels,
|
||||
dev->model->shading_lines,
|
||||
16,
|
||||
|
@ -2570,32 +2576,34 @@ gl843_init_regs_for_shading (Genesys_Device * dev)
|
|||
SCAN_FLAG_DISABLE_SHADING |
|
||||
SCAN_FLAG_DISABLE_GAMMA |
|
||||
SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE |
|
||||
SCAN_FLAG_IGNORE_LINE_DISTANCE |
|
||||
SCAN_FLAG_USE_OPTICAL_RES);
|
||||
|
||||
SCAN_FLAG_IGNORE_LINE_DISTANCE);
|
||||
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"gl843_init_registers_for_shading: Failed to setup scan: %s\n",
|
||||
"gl843_init_registers_for_shading: failed to setup scan: %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
|
||||
dev->scanhead_position_in_steps += dev->model->shading_lines;
|
||||
dev->scanhead_position_in_steps += dev->model->shading_lines + move;
|
||||
|
||||
status =
|
||||
gl843_bulk_write_register (dev, dev->calib_reg, GENESYS_GL843_MAX_REGS);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"gl843_init_registers_for_shading: Failed to bulk write registers: %s\n",
|
||||
"gl843_init_registers_for_shading: failed to bulk write registers: %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
|
||||
DBG (DBG_proc, "gl843_init_regs_for_shading: completed\n");
|
||||
/* this is an hack to make calibration cache working .... */
|
||||
/* if we don't do this, cache will be identified at the shading calibration
|
||||
* dpi which is diferent from calibration one */
|
||||
dev->current_setup.xres = resolution;
|
||||
|
||||
DBGCOMPLETED;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
@ -2619,8 +2627,11 @@ gl843_init_regs_for_scan (Genesys_Device * dev)
|
|||
dev->settings.yres, dev->settings.lines, dev->settings.pixels,
|
||||
dev->settings.tl_x, dev->settings.tl_y, dev->settings.scan_mode);
|
||||
|
||||
/* ensure head is parked in case of calibration */
|
||||
gl843_slow_back_home (dev, SANE_TRUE);
|
||||
|
||||
/* channels */
|
||||
if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */
|
||||
if (dev->settings.scan_mode == SCAN_MODE_COLOR)
|
||||
channels = 3;
|
||||
else
|
||||
channels = 1;
|
||||
|
@ -2871,8 +2882,7 @@ gl843_led_calibration (Genesys_Device * dev)
|
|||
SCAN_FLAG_DISABLE_SHADING |
|
||||
SCAN_FLAG_DISABLE_GAMMA |
|
||||
SCAN_FLAG_SINGLE_LINE |
|
||||
SCAN_FLAG_IGNORE_LINE_DISTANCE |
|
||||
SCAN_FLAG_USE_OPTICAL_RES);
|
||||
SCAN_FLAG_IGNORE_LINE_DISTANCE);
|
||||
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
|
@ -3017,19 +3027,198 @@ gl843_led_calibration (Genesys_Device * dev)
|
|||
return status;
|
||||
}
|
||||
|
||||
/* this function does the offset calibration by scanning one line of the calibration
|
||||
area below scanner's top. There is a black margin and the remaining is white.
|
||||
sanei_genesys_search_start() must have been called so that the offsets and margins
|
||||
are allready known.
|
||||
|
||||
this function expects the slider to be where?
|
||||
*/
|
||||
/**
|
||||
* 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
|
||||
gl843_offset_calibration (Genesys_Device * dev)
|
||||
{
|
||||
DBG (DBG_proc, "%s: not implemented \n", __FUNCTION__);
|
||||
if (dev == NULL)
|
||||
return SANE_STATUS_INVAL;
|
||||
Genesys_Register_Set *r;
|
||||
SANE_Status status = SANE_STATUS_GOOD;
|
||||
uint8_t *first_line, *second_line;
|
||||
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;
|
||||
|
||||
/* offset calibration is always done in color mode */
|
||||
channels = 3;
|
||||
/* follow CKSEL */
|
||||
if(dev->settings.xres<dev->sensor.optical_res)
|
||||
resolution=dev->sensor.optical_res/2;
|
||||
else
|
||||
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, "gl843_offset_calibration: black_pixels=%d\n", black_pixels);
|
||||
|
||||
status = gl843_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,
|
||||
"gl843_offset_calibration: failed to setup scan: %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
r = sanei_genesys_get_address (dev->calib_reg, REG02);
|
||||
r->value &= ~REG02_MTRPWR;
|
||||
|
||||
/* 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 (gl843_set_fe(dev, AFE_SET));
|
||||
RIE (gl843_bulk_write_register (dev, dev->calib_reg, GENESYS_GL843_MAX_REGS));
|
||||
DBG (DBG_info, "gl843_offset_calibration: starting first line reading\n");
|
||||
RIE (gl843_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, "gl843_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 (gl843_set_fe(dev, AFE_SET));
|
||||
RIE (gl843_bulk_write_register (dev, dev->calib_reg, GENESYS_GL843_MAX_REGS));
|
||||
DBG (DBG_info, "gl843_offset_calibration: starting second line reading\n");
|
||||
RIE (gl843_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, "gl843_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(gl843_set_fe(dev, AFE_SET));
|
||||
RIE (gl843_bulk_write_register (dev, dev->calib_reg, GENESYS_GL843_MAX_REGS));
|
||||
DBG (DBG_info, "gl843_offset_calibration: starting second line reading\n");
|
||||
RIE (gl843_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, "gl843_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, "gl843_offset_calibration: offset=(%d,%d,%d)\n", dev->frontend.offset[0], dev->frontend.offset[1], dev->frontend.offset[2]);
|
||||
top = dev->frontend.offset[1];
|
||||
|
||||
/* cleanup before return */
|
||||
free (first_line);
|
||||
free (second_line);
|
||||
|
||||
DBGCOMPLETED;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
@ -3046,10 +3235,145 @@ gl843_offset_calibration (Genesys_Device * dev)
|
|||
static SANE_Status
|
||||
gl843_coarse_gain_calibration (Genesys_Device * dev, int dpi)
|
||||
{
|
||||
int pixels;
|
||||
int total_size;
|
||||
uint8_t *line;
|
||||
int i, j, channels;
|
||||
SANE_Status status = SANE_STATUS_GOOD;
|
||||
int max[3];
|
||||
float gain[3],coeff;
|
||||
int val, code, lines;
|
||||
int resolution;
|
||||
Genesys_Register_Set *r;
|
||||
int bpp;
|
||||
|
||||
DBG (DBG_proc, "gl843_coarse_gain_calibration: dpi = %d\n", dpi);
|
||||
DBG (DBG_proc, "%s: not implemented \n", __FUNCTION__);
|
||||
if (dev == NULL)
|
||||
return SANE_STATUS_INVAL;
|
||||
|
||||
/* 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 = gl843_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);
|
||||
r = sanei_genesys_get_address (dev->calib_reg, REG02);
|
||||
r->value &= ~REG02_MTRPWR;
|
||||
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"gl843_coarse_calibration: failed to setup scan: %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
|
||||
RIE (gl843_bulk_write_register
|
||||
(dev, dev->calib_reg, GENESYS_GL843_MAX_REGS));
|
||||
|
||||
total_size = pixels * channels * (16/bpp) * lines;
|
||||
|
||||
line = malloc (total_size);
|
||||
if (!line)
|
||||
return SANE_STATUS_NO_MEM;
|
||||
|
||||
RIE (gl843_set_fe(dev, AFE_SET));
|
||||
RIE (gl843_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,
|
||||
"gl843_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 (gl843_stop_action (dev));
|
||||
|
||||
gl843_slow_back_home (dev, SANE_TRUE);
|
||||
|
||||
DBGCOMPLETED;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
@ -3088,9 +3412,7 @@ gl843_init_regs_for_warmup (Genesys_Device * dev,
|
|||
SCAN_FLAG_DISABLE_SHADING |
|
||||
SCAN_FLAG_DISABLE_GAMMA |
|
||||
SCAN_FLAG_SINGLE_LINE |
|
||||
SCAN_FLAG_IGNORE_LINE_DISTANCE |
|
||||
SCAN_FLAG_USE_OPTICAL_RES
|
||||
);
|
||||
SCAN_FLAG_IGNORE_LINE_DISTANCE);
|
||||
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
|
@ -3117,12 +3439,18 @@ gl843_is_compatible_calibration (Genesys_Device * dev,
|
|||
Genesys_Calibration_Cache * cache,
|
||||
int for_overwrite)
|
||||
{
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
struct timeval time;
|
||||
#endif
|
||||
int compatible = 1, resolution;
|
||||
SANE_Status status;
|
||||
|
||||
DBG (DBG_proc, "gl843_is_compatible_calibration\n");
|
||||
DBGSTART;
|
||||
|
||||
if (cache == NULL || for_overwrite)
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
|
||||
status = gl843_calculate_current_setup (dev);
|
||||
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
|
@ -3130,14 +3458,51 @@ gl843_is_compatible_calibration (Genesys_Device * dev,
|
|||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
if(dev->settings.xres<dev->sensor.optical_res)
|
||||
resolution=dev->sensor.optical_res/2;
|
||||
else
|
||||
resolution=dev->sensor.optical_res;
|
||||
dev->current_setup.scan_method = dev->settings.scan_method;
|
||||
|
||||
DBG (DBG_proc, "gl843_is_compatible_calibration: checking\n");
|
||||
|
||||
/* a calibration cache is compatible if color mode and x dpi match the user
|
||||
* requested scan. In the case of CIS scanners, dpi isn't a criteria */
|
||||
if (dev->model->is_cis == SANE_FALSE)
|
||||
{
|
||||
compatible = (resolution == ((int) cache->used_setup.xres));
|
||||
compatible = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
compatible = (dev->current_setup.channels == cache->used_setup.channels);
|
||||
}
|
||||
if (dev->current_setup.scan_method != cache->used_setup.scan_method)
|
||||
{
|
||||
DBG (DBG_io,
|
||||
"gl843_is_compatible_calibration: current method=%d, used=%d\n",
|
||||
dev->current_setup.scan_method, cache->used_setup.scan_method);
|
||||
compatible = 0;
|
||||
}
|
||||
if (!compatible)
|
||||
{
|
||||
DBG (DBG_proc,
|
||||
"gl843_is_compatible_calibration: completed, non compatible cache\n");
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (dev->current_setup.half_ccd != cache->used_setup.half_ccd)
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
|
||||
if (for_overwrite)
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
/* a cache entry expires after 30 minutes for non CIS scanners */
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
gettimeofday (&time, NULL);
|
||||
if ((time.tv_sec - cache->last_calibration > 30 * 60)
|
||||
&& (dev->model->is_cis == SANE_FALSE)
|
||||
&& (dev->settings.scan_method == SCAN_METHOD_FLATBED))
|
||||
{
|
||||
DBG (DBG_proc,
|
||||
"gl843_is_compatible_calibration: expired entry, non compatible cache\n");
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
}
|
||||
#endif
|
||||
|
||||
DBGCOMPLETED;
|
||||
return SANE_STATUS_GOOD;
|
||||
|
@ -3579,7 +3944,7 @@ gl843_search_strip (Genesys_Device * dev, SANE_Bool forward, SANE_Bool black)
|
|||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"gl843_search_strip: Failed to bulk write registers: %s\n",
|
||||
"gl843_search_strip: failed to bulk write registers: %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue