- y scan position fixes for gl646 scanners

- added a 'clear calibration cache button'
merge-requests/1/head
Stéphane Voltz 2009-04-16 18:39:23 +00:00
rodzic d32f758ce3
commit 4f526dbb24
5 zmienionych plików z 197 dodań i 92 usunięć

Wyświetl plik

@ -1,6 +1,11 @@
2009-04-16 Stéphane Voltz <stef.dev@free.fr>
* backend/genesys.h backend/genesys.c backend/genesys_gl646.c
backend/genesys_devices.c: y scan position fixes
- added a 'clear calibration cache button'
2009-04-15 Stéphane Voltz <stef.dev@free.fr>
* backend/genesys.c backend/genesys_gl646.c: calibration cache
activation for gl646 based scanners
activation for gl646 based scanners
2009-04-15 m. allan noah <kitno455 a t gmail d o t com>
* backend/fujitsu.c, doc/descriptions/fujitsu.desc: backend v93

Wyświetl plik

@ -2224,6 +2224,12 @@ genesys_average_data (uint8_t * average_data,
}
}
/**
* scans a white area with motor and lamp off to get the per CCD pixel offset
* that will be used to compute shading coefficient
* @param dev scanner's device
* @return SANE_STATUS_GOOD if OK, else an error
*/
static SANE_Status
genesys_dark_shading_calibration (Genesys_Device * dev)
{
@ -2235,9 +2241,16 @@ genesys_dark_shading_calibration (Genesys_Device * dev)
DBG (DBG_proc, "genesys_dark_shading_calibration\n");
/* end pixel - start pixel */
if (dev->model->asic_type != GENESYS_GL646)
{
pixels_per_line =
(genesys_pixels_per_line (dev->calib_reg)
* genesys_dpiset (dev->calib_reg)) / dev->sensor.optical_res;
}
else
{
pixels_per_line = dev->calib_pixels;
}
if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */
channels = 3;
@ -2286,7 +2299,7 @@ genesys_dark_shading_calibration (Genesys_Device * dev)
usleep (200 * 1000); /* wait 200 ms: lamp needs some time to get dark */
status = dev->model->cmd_set->begin_scan (dev, dev->calib_reg, SANE_TRUE);
status = dev->model->cmd_set->begin_scan (dev, dev->calib_reg, SANE_FALSE);
if (status != SANE_STATUS_GOOD)
{
free (calibration_data);
@ -2449,11 +2462,16 @@ genesys_white_shading_calibration (Genesys_Device * dev)
DBG (DBG_proc, "genesys_white_shading_calibration (lines = %d)\n",
dev->model->shading_lines);
if (dev->model->asic_type != GENESYS_GL646)
{
pixels_per_line =
(genesys_pixels_per_line (dev->calib_reg)
* genesys_dpiset (dev->calib_reg)) / dev->sensor.optical_res;
/* XXX STEF XXX */
pixels_per_line = dev->calib_pixels;
}
else
{
pixels_per_line = dev->calib_pixels;
}
if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */
channels = 3;
@ -3184,6 +3202,14 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
return SANE_STATUS_GOOD;
}
/**
* search calibration cache list for an entry matching required scan.
* If one is found, set device calibration with it
* @param dev scanner's device
* @return SANE_STATUS_UNSUPPORTED if no matching cache entry has been
* found, SANE_STATUS_GOOD if one has been found and used.
*/
static SANE_Status
genesys_restore_calibration (Genesys_Device * dev)
{
@ -3192,25 +3218,21 @@ genesys_restore_calibration (Genesys_Device * dev)
DBG (DBG_proc, "genesys_restore_calibration\n");
if (!dev->model->cmd_set->is_compatible_calibration)
/* if no cache or no function to evaluate cache entry ther can be no match */
if (!dev->model->cmd_set->is_compatible_calibration || dev->calibration_cache==NULL)
return SANE_STATUS_UNSUPPORTED;
/* we walk the link list of calibration cache in search for a
* matching one */
for(cache = dev->calibration_cache; cache; cache = cache->next)
{
status = dev->model->cmd_set->is_compatible_calibration(dev, cache,
SANE_FALSE);
if (status == SANE_STATUS_UNSUPPORTED)
{
continue;
}
else if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"genesys_restore_calibration: fail while checking compatibility: %s\n",
sane_strstatus (status));
return status;
}
/* SANE_STATUS_GOOD, a matching cache has been found
* so we use it to populate calibration data
*/
if(status==SANE_STATUS_GOOD)
{
memcpy(&dev->frontend, &cache->frontend, sizeof(dev->frontend));
/* don't restore the gamma fields */
memcpy(&dev->sensor, &cache->sensor,
@ -3238,7 +3260,7 @@ genesys_restore_calibration (Genesys_Device * dev)
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"genesys_send_shading_coefficient: failed to send shading data: %s\n",
"genesys_restore_calibration: failed to send shading data: %s\n",
sane_strstatus (status));
return status;
}
@ -3246,15 +3268,27 @@ genesys_restore_calibration (Genesys_Device * dev)
DBG (DBG_proc, "genesys_restore_calibration: restored\n");
return SANE_STATUS_GOOD;
}
/* here status is either SANE_STATUS_UNSUPPORTED which mean tested cache
* entry doesn't match, or an fatal error */
if (status != SANE_STATUS_UNSUPPORTED)
{
DBG (DBG_error,
"genesys_restore_calibration: fail while checking compatibility: %s\n",
sane_strstatus (status));
return status;
}
}
DBG (DBG_proc, "genesys_restore_calibration: completed(nothing found)\n");
return SANE_STATUS_UNSUPPORTED;
}
static SANE_Status
genesys_save_calibration (Genesys_Device * dev)
{
SANE_Status status=SANE_STATUS_UNSUPPORTED;
Genesys_Calibration_Cache *cache;
{
SANE_Status status = SANE_STATUS_UNSUPPORTED;
Genesys_Calibration_Cache *cache = NULL;
uint8_t *tmp;
DBG (DBG_proc, "genesys_save_calibration\n");
@ -3262,38 +3296,41 @@ genesys_save_calibration (Genesys_Device * dev)
if (!dev->model->cmd_set->is_compatible_calibration)
return SANE_STATUS_UNSUPPORTED;
for(cache = dev->calibration_cache; cache; cache = cache->next)
if (dev->calibration_cache != NULL)
{
status = dev->model->cmd_set->is_compatible_calibration(dev, cache,
SANE_TRUE);
if (status == SANE_STATUS_UNSUPPORTED)
{
continue;
}
else if (status != SANE_STATUS_GOOD)
for (cache = dev->calibration_cache; cache; cache = cache->next)
{
DBG (DBG_error,
"genesys_save_calibration: fail while checking compatibility: %s\n",
sane_strstatus (status));
return status;
status = dev->model->cmd_set->is_compatible_calibration (dev, cache,
SANE_TRUE);
if (status == SANE_STATUS_UNSUPPORTED)
{
continue;
}
else if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"genesys_save_calibration: fail while checking compatibility: %s\n",
sane_strstatus (status));
return status;
}
break;
}
break;
}
if(cache)
if (cache)
{
if(dev->average_size > cache->average_size)
{
if (dev->average_size > cache->average_size)
{
cache->average_size = dev->average_size;
tmp = (uint8_t*)realloc(cache->dark_average_data,
cache->average_size);
tmp = (uint8_t *) realloc (cache->dark_average_data,
cache->average_size);
if (!tmp)
return SANE_STATUS_NO_MEM;
cache->dark_average_data = tmp;
tmp = (uint8_t*)realloc(cache->white_average_data,
cache->average_size);
tmp = (uint8_t *) realloc (cache->white_average_data,
cache->average_size);
if (!tmp)
return SANE_STATUS_NO_MEM;
cache->white_average_data = tmp;
@ -3301,36 +3338,36 @@ genesys_save_calibration (Genesys_Device * dev)
}
else
{
cache = malloc(sizeof(*cache));
cache = malloc (sizeof (*cache));
if (!cache)
return SANE_STATUS_NO_MEM;
memset(cache, 0, sizeof(*cache));
memset (cache, 0, sizeof (*cache));
cache->next = dev->calibration_cache;
dev->calibration_cache = cache;
cache->average_size = dev->average_size;
cache->dark_average_data = (uint8_t*)malloc(cache->average_size);
cache->dark_average_data = (uint8_t *) malloc (cache->average_size);
if (!cache->dark_average_data)
return SANE_STATUS_NO_MEM;
cache->white_average_data = (uint8_t*)malloc(cache->average_size);
cache->white_average_data = (uint8_t *) malloc (cache->average_size);
if (!cache->white_average_data)
return SANE_STATUS_NO_MEM;
memcpy(&cache->used_setup, &dev->current_setup,
sizeof(cache->used_setup));
memcpy (&cache->used_setup, &dev->current_setup,
sizeof (cache->used_setup));
}
memcpy(&cache->frontend, &dev->frontend, sizeof(cache->frontend));
memcpy(&cache->sensor, &dev->sensor, sizeof(cache->sensor));
memcpy (&cache->frontend, &dev->frontend, sizeof (cache->frontend));
memcpy (&cache->sensor, &dev->sensor, sizeof (cache->sensor));
cache->calib_pixels = dev->calib_pixels;
memcpy(cache->dark_average_data, dev->dark_average_data,
cache->average_size);
memcpy(cache->white_average_data, dev->white_average_data,
cache->average_size);
memcpy (cache->dark_average_data, dev->dark_average_data,
cache->average_size);
memcpy (cache->white_average_data, dev->white_average_data,
cache->average_size);
DBG (DBG_proc, "genesys_save_calibration: completed\n");
return SANE_STATUS_GOOD;
@ -5212,6 +5249,16 @@ init_options (Genesys_Scanner * s)
s->val[OPT_CALIBRATE].b = 0;
s->last_val[OPT_CALIBRATE].b = 0;
/* clear calibration cache button */
s->opt[OPT_CLEAR_CALIBRATION].name = "clear";
s->opt[OPT_CLEAR_CALIBRATION].title = SANE_I18N("Clear calibration");
s->opt[OPT_CLEAR_CALIBRATION].desc = SANE_I18N("Clear calibration cache");
s->opt[OPT_CLEAR_CALIBRATION].type = SANE_TYPE_BUTTON;
s->opt[OPT_CLEAR_CALIBRATION].unit = SANE_UNIT_NONE;
s->opt[OPT_CLEAR_CALIBRATION].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED | SANE_CAP_AUTOMATIC;
s->val[OPT_CLEAR_CALIBRATION].b = 0;
s->last_val[OPT_CLEAR_CALIBRATION].b = 0;
RIE (calc_parameters (s));
DBG (DBG_proc, "init_options: exit\n");
@ -5967,6 +6014,7 @@ set_option_value (Genesys_Scanner * s, int option, void *val,
SANE_Status status;
SANE_Word *table;
unsigned int i;
Genesys_Calibration_Cache *cache, *next_cache;
switch (option)
{
@ -6057,8 +6105,8 @@ set_option_value (Genesys_Scanner * s, int option, void *val,
if (*(SANE_Word *) val != s->val[option].w)
{
s->val[option].w = *(SANE_Word *) val;
RIE (s->dev->model->cmd_set->
set_powersaving (s->dev, s->val[option].w));
RIE (s->dev->model->
cmd_set->set_powersaving (s->dev, s->val[option].w));
}
break;
@ -6095,26 +6143,38 @@ set_option_value (Genesys_Scanner * s, int option, void *val,
sanei_genesys_create_gamma_table (s->dev->sensor.red_gamma_table,
s->opt[OPT_GAMMA_VECTOR_R].size /
sizeof (SANE_Word),
s->opt[OPT_GAMMA_VECTOR_R].
constraint.range->max,
s->opt[OPT_GAMMA_VECTOR_R].
constraint.range->max,
s->
opt
[OPT_GAMMA_VECTOR_R].constraint.
range->max,
s->
opt
[OPT_GAMMA_VECTOR_R].constraint.
range->max,
s->dev->sensor.red_gamma);
sanei_genesys_create_gamma_table (s->dev->sensor.green_gamma_table,
s->opt[OPT_GAMMA_VECTOR_G].size /
sizeof (SANE_Word),
s->opt[OPT_GAMMA_VECTOR_G].
constraint.range->max,
s->opt[OPT_GAMMA_VECTOR_G].
constraint.range->max,
s->
opt
[OPT_GAMMA_VECTOR_G].constraint.
range->max,
s->
opt
[OPT_GAMMA_VECTOR_G].constraint.
range->max,
s->dev->sensor.red_gamma);
sanei_genesys_create_gamma_table (s->dev->sensor.blue_gamma_table,
s->opt[OPT_GAMMA_VECTOR_B].size /
sizeof (SANE_Word),
s->opt[OPT_GAMMA_VECTOR_B].
constraint.range->max,
s->opt[OPT_GAMMA_VECTOR_B].
constraint.range->max,
s->
opt
[OPT_GAMMA_VECTOR_B].constraint.
range->max,
s->
opt
[OPT_GAMMA_VECTOR_B].constraint.
range->max,
s->dev->sensor.red_gamma);
}
break;
@ -6152,6 +6212,22 @@ set_option_value (Genesys_Scanner * s, int option, void *val,
case OPT_CALIBRATE:
/* TODO call for calibration using special sheet here */
break;
case OPT_CLEAR_CALIBRATION:
/* clear calibration cache */
if(s->dev->calibration_cache!=NULL)
{
for (cache = s->dev->calibration_cache; cache; cache = next_cache)
{
next_cache = cache->next;
free (cache->dark_average_data);
free (cache->white_average_data);
free (cache);
}
}
s->dev->calibration_cache=NULL;
/* remove file */
unlink (s->dev->calib_file);
break;
default:
DBG (DBG_warn, "set_option_value: can't set unknown option %d\n",

Wyświetl plik

@ -105,6 +105,7 @@ enum Genesys_Option
OPT_POWER_SW,
OPT_BUTTON_GROUP,
OPT_CALIBRATE,
OPT_CLEAR_CALIBRATION,
/* must come last: */
NUM_OPTIONS

Wyświetl plik

@ -837,7 +837,7 @@ static Genesys_Model hp2300c_model = {
| GENESYS_FLAG_HALF_CCD_MODE
| GENESYS_FLAG_CUSTOM_GAMMA,
GENESYS_HAS_SCAN_SW | GENESYS_HAS_COPY_SW,
9,
18,
132
};

Wyświetl plik

@ -1359,8 +1359,9 @@ gl646_setup_registers (Genesys_Device * dev,
else
dev->reg[reg_0x02].value |= REG02_ACDCDIS;
/* setup motor power */
/* setup motor power and direction */
regs[reg_0x02].value |= REG02_MTRPWR;
regs[reg_0x02].value &= ~REG02_MTRREV;
/* fastfed enabled (2 motor slope tables) */
if (motor->fastfed)
@ -1542,9 +1543,15 @@ gl646_setup_registers (Genesys_Device * dev,
/*
feedl = feed_steps - fast_slope_steps*2 -
(slow_slope_steps >> scan_step_type); */
/* but head has moved due to shading calibration => y_position_in_steps */
/* but head has moved due to shading calibration => dev->scanhead_position_in_steps */
if (feedl > 0)
{
/* take into account the distance moved during calibration */
/* feedl -= dev->scanhead_position_in_steps; */
DBG (DBG_info, "gl646_setup_registers: initial move=%d\n", feedl);
DBG (DBG_info, "gl646_setup_registers: scanhead_position_in_steps=%d\n",
dev->scanhead_position_in_steps);
/* TODO clean up this when I'll fully understand.
* for now, special casing each motor */
switch (dev->model->motor_type)
@ -1561,7 +1568,7 @@ gl646_setup_registers (Genesys_Device * dev,
break;
case 2400:
break;
default: /* 255 steps at half steps */
default:
break;
}
break;
@ -1569,16 +1576,19 @@ gl646_setup_registers (Genesys_Device * dev,
switch (motor->ydpi)
{
case 75:
feedl -= 300; /*440 > 280, 240 */
feedl -= 180;
break;
case 150:
feedl -= 134;
feedl += 0;
break;
case 300:
feedl -= 156; /* 200, 165 > 155, 150 */
feedl += 30;
break;
case 600:
feedl -= 6;
feedl += 35;
break;
case 1200:
feedl += 45;
break;
default:
break;
@ -3377,6 +3387,7 @@ gl646_init_regs_for_shading (Genesys_Device * dev)
half_ccd = 2;
}
/* fill settings for scan */
settings.scan_method = SCAN_METHOD_FLATBED;
settings.scan_mode = dev->settings.scan_mode;
@ -3385,7 +3396,7 @@ gl646_init_regs_for_shading (Genesys_Device * dev)
settings.tl_x = 0;
settings.tl_y = 0;
settings.pixels = dev->sensor.sensor_pixels / half_ccd;
settings.lines = dev->model->shading_lines;
settings.lines = dev->model->shading_lines * (3 - half_ccd);
settings.depth = 16;
settings.color_filter = dev->settings.color_filter;
@ -3393,6 +3404,9 @@ gl646_init_regs_for_shading (Genesys_Device * dev)
settings.threshold = dev->settings.threshold;
settings.exposure_time = dev->settings.exposure_time;
/* keep account of the movement for final scan move */
dev->scanhead_position_in_steps += settings.lines;
/* we don't want top offset, but we need right margin to be the same
* than the one for the final scan */
status = setup_for_scan (dev, settings, SANE_TRUE, SANE_FALSE, SANE_FALSE);
@ -3415,12 +3429,13 @@ gl646_init_regs_for_shading (Genesys_Device * dev)
memcpy (dev->calib_reg, dev->reg,
GENESYS_GL646_MAX_REGS * sizeof (Genesys_Register_Set));
/* this is an hack to make calibration cache working ....*/
/* 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 = dev->settings.xres;
DBG (DBG_info,
"gl646_init_register_for_shading:\n\tdev->settings.xres=%d\n\tdev->settings.yres=%d\n",dev->settings.xres,dev->settings.yres);
"gl646_init_register_for_shading:\n\tdev->settings.xres=%d\n\tdev->settings.yres=%d\n",
dev->settings.xres, dev->settings.yres);
DBG (DBG_proc, "gl646_init_register_for_shading: end\n");
return status;
@ -3434,6 +3449,19 @@ gl646_init_regs_for_shading (Genesys_Device * dev)
static SANE_Status
gl646_init_regs_for_scan (Genesys_Device * dev)
{
SANE_Status status;
/* park head after calibration if needed */
if (dev->scanhead_position_in_steps > 0)
{
status = gl646_slow_back_home (dev, SANE_TRUE);
if (status != SANE_STATUS_GOOD)
{
return status;
}
dev->scanhead_position_in_steps = 0;
}
return setup_for_scan (dev, dev->settings, SANE_FALSE, SANE_TRUE,
SANE_TRUE);
}
@ -3786,7 +3814,7 @@ gl646_offset_calibration (Genesys_Device * dev)
uint8_t *first_line, *second_line;
unsigned int channels;
char title[32];
int pass = 0, avg, direction;
int pass = 0, avg;
SANE_Int resolution;
Genesys_Settings settings;
int topavg, bottomavg;
@ -4924,10 +4952,11 @@ gl646_is_compatible_calibration (Genesys_Device * dev,
Genesys_Calibration_Cache * cache,
int for_overwrite)
{
SANE_Int channels;
DBG (DBG_proc, "gl646_is_compatible_calibration: start\n");
if (cache == NULL)
return SANE_STATUS_UNSUPPORTED;
/* build minimal current_setup for calibration cache use only, it will be better
* computed when during setup for scan
*/
@ -4941,14 +4970,8 @@ gl646_is_compatible_calibration (Genesys_Device * dev,
}
dev->current_setup.xres = dev->settings.xres;
DBG (DBG_info,
"gl646_is_compatible_calibration:\n\tdev->settings.xres=%d\n\tdev->settings.yres=%d\n",dev->settings.xres,dev->settings.yres);
DBG (DBG_info,
"gl646_is_compatible_calibration:\n\tcache->used_setup.channels=%d\n\tcache->used_setup.xres=%f\n",
cache->used_setup.channels, cache->used_setup.xres);
DBG (DBG_info,
"gl646_is_compatible_calibration:\n\tdev->current_setup.channels=%d\n\tdev->current_setup.xres=%f\n",
dev->current_setup.channels, dev->current_setup.xres);
/* a calibration cache is compatible if color mode and x dpi match the user
* requested scan */
if ((dev->current_setup.channels != cache->used_setup.channels)
|| (dev->current_setup.xres != cache->used_setup.xres))
{