Add calibration cache

The calibration data is stored in the directory $HOME/.sane
merge-requests/1/head
Pierre Willenbrock 2009-03-25 12:57:24 +00:00
rodzic 93b880cbd1
commit ce2fdfbfbe
5 zmienionych plików z 742 dodań i 37 usunięć

Wyświetl plik

@ -1,3 +1,7 @@
2009-03-25 Pierre Willenbrock <pierre@pirsoft.dnsalias.org>
* backend/genesys.c, backend/genesys_gl646.c,
backend/genesys_gl841.c, backend/genesys_low.h: Add calibration cache
2009-03-24 m. allan noah <kitno455 a t gmail d o t com>
* backend/canon_dr.[ch], backend/canon_dr-cmd.h: backend v21
- correct rgb padding macro

Wyświetl plik

@ -2247,7 +2247,9 @@ genesys_dark_shading_calibration (Genesys_Device * dev)
FREE_IFNOT_NULL (dev->dark_average_data);
dev->dark_average_data = malloc (channels * 2 * pixels_per_line);
dev->average_size = channels * 2 * pixels_per_line;
dev->dark_average_data = malloc (dev->average_size);
if (!dev->dark_average_data)
{
DBG (DBG_error,
@ -2378,7 +2380,8 @@ genesys_dummy_dark_shading (Genesys_Device * dev)
FREE_IFNOT_NULL (dev->dark_average_data);
dev->dark_average_data = malloc (channels * 2 * pixels_per_line);
dev->average_size = channels * 2 * pixels_per_line;
dev->dark_average_data = malloc (dev->average_size);
if (!dev->dark_average_data)
{
DBG (DBG_error,
@ -2605,7 +2608,9 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev)
if (dev->white_average_data)
free (dev->white_average_data);
dev->white_average_data = malloc (channels * 2 * pixels_per_line);
dev->average_size = channels * 2 * pixels_per_line;
dev->white_average_data = malloc (dev->average_size);
if (!dev->white_average_data)
{
DBG (DBG_error,
@ -2783,9 +2788,7 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
DBG (DBG_proc, "genesys_send_shading_coefficient\n");
pixels_per_line =
(genesys_pixels_per_line (dev->calib_reg)
* genesys_dpiset (dev->calib_reg)) / dev->sensor.optical_res;
pixels_per_line = dev->calib_pixels;
if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */
channels = 3;
@ -3281,6 +3284,158 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
return SANE_STATUS_GOOD;
}
static SANE_Status
genesys_restore_calibration (Genesys_Device * dev)
{
SANE_Status status;
Genesys_Calibration_Cache *cache;
DBG (DBG_proc, "genesys_restore_calibration\n");
if (!dev->model->cmd_set->is_compatible_calibration)
return SANE_STATUS_UNSUPPORTED;
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;
}
memcpy(&dev->frontend, &cache->frontend, sizeof(dev->frontend));
/* don't restore the gamma fields */
memcpy(&dev->sensor, &cache->sensor,
offsetof(Genesys_Sensor,red_gamma));
free(dev->dark_average_data);
free(dev->white_average_data);
dev->average_size = cache->average_size;
dev->calib_pixels = cache->calib_pixels;
dev->dark_average_data = (uint8_t*)malloc(cache->average_size);
dev->white_average_data = (uint8_t*)malloc(cache->average_size);
if (!dev->dark_average_data || !dev->white_average_data)
return SANE_STATUS_NO_MEM;
memcpy(dev->dark_average_data,
cache->dark_average_data, dev->average_size);
memcpy(dev->white_average_data,
cache->white_average_data, dev->average_size);
status = genesys_send_shading_coefficient (dev);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"genesys_send_shading_coefficient: failed to send shading data: %s\n",
sane_strstatus (status));
return status;
}
DBG (DBG_proc, "genesys_restore_calibration: restored\n");
return SANE_STATUS_GOOD;
}
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;
Genesys_Calibration_Cache *cache;
uint8_t *tmp;
DBG (DBG_proc, "genesys_save_calibration\n");
if (!dev->model->cmd_set->is_compatible_calibration)
return SANE_STATUS_UNSUPPORTED;
for(cache = dev->calibration_cache; cache; cache = cache->next)
{
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;
}
if(cache)
{
if(dev->average_size > cache->average_size)
{
cache->average_size = dev->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);
if (!tmp)
return SANE_STATUS_NO_MEM;
cache->white_average_data = tmp;
}
}
else
{
cache = malloc(sizeof(*cache));
if (!cache)
return SANE_STATUS_NO_MEM;
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);
if (!cache->dark_average_data)
return SANE_STATUS_NO_MEM;
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->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);
DBG (DBG_proc, "genesys_save_calibration: completed\n");
return SANE_STATUS_GOOD;
}
static SANE_Status
genesys_flatbed_calibration (Genesys_Device * dev)
{
@ -3445,6 +3600,10 @@ genesys_flatbed_calibration (Genesys_Device * dev)
return status;
}
dev->calib_pixels =
(genesys_pixels_per_line (dev->calib_reg)
* genesys_dpiset (dev->calib_reg)) / dev->sensor.optical_res;
if (dev->model->flags & GENESYS_FLAG_DARK_WHITE_CALIBRATION)
{
status = genesys_dark_white_shading_calibration (dev);
@ -3769,44 +3928,57 @@ genesys_start_scan (Genesys_Device * dev)
}
}
/* calibration : sheetfed scanners can't calibrate before each scan */
/* so we use a NO_CALIBRATION flags for those scanners */
if (dev->model->flags & GENESYS_FLAG_NO_CALIBRATION)
status = genesys_restore_calibration (dev);
if(status == SANE_STATUS_UNSUPPORTED)
{
/* TODO send predefined calibration values from default
* values or built from a calibration scan */
/* send custom or generic gamma tables depending on flag */
if (dev->model->flags & GENESYS_FLAG_CUSTOM_GAMMA)
/* calibration : sheetfed scanners can't calibrate before each scan */
/* so we use a NO_CALIBRATION flags for those scanners */
if (dev->model->flags & GENESYS_FLAG_NO_CALIBRATION)
{
/* use custom gamma table */
status = dev->model->cmd_set->send_gamma_table (dev, 0);
/* TODO send predefined calibration values from default
* values or built from a calibration scan */
/* send custom or generic gamma tables depending on flag */
if (dev->model->flags & GENESYS_FLAG_CUSTOM_GAMMA)
{
/* use custom gamma table */
status = dev->model->cmd_set->send_gamma_table (dev, 0);
}
else
{
/* send default gamma table if no custom gamma */
status = dev->model->cmd_set->send_gamma_table (dev, 1);
}
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"genesys_start_scan: failed to init gamma table: %s\n",
sane_strstatus (status));
return status;
}
/* head hasn't moved */
dev->scanhead_position_in_steps = 0;
}
else
{
/* send default gamma table if no custom gamma */
status = dev->model->cmd_set->send_gamma_table (dev, 1);
}
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"genesys_start_scan: failed to init gamma table: %s\n",
sane_strstatus (status));
return status;
}
/* head hasn't moved */
dev->scanhead_position_in_steps = 0;
status = genesys_flatbed_calibration (dev);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"genesys_start_scan: failed to do flatbed calibration: %s\n",
sane_strstatus (status));
return status;
}
genesys_save_calibration(dev);
}
}
else
else if(status != SANE_STATUS_GOOD)
{
status = genesys_flatbed_calibration (dev);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"genesys_start_scan: failed to do flatbed calibration: %s\n",
sane_strstatus (status));
return status;
}
DBG (DBG_error,
"genesys_start_scan: failed to restore calibration: %s\n",
sane_strstatus (status));
return status;
}
status = dev->model->cmd_set->init_regs_for_scan (dev);
@ -5312,6 +5484,167 @@ probe_genesys_devices (void)
return status;
}
/* this should be changed if one of the substructures of
Genesys_Calibration_Cache change, but it must be changed if there are
changes that don't change size -- at least for now, as we store most
of Genesys_Calibration_Cache as is.
*/
#define CALIBRATION_VERSION 1
static void
read_calibration(Genesys_Device * dev)
{
FILE *fp;
uint8_t vers = 0;
uint32_t size = 0;
struct Genesys_Calibration_Cache *cache;
DBG (DBG_proc, "read_calibration: enter\n");
fp = fopen(dev->calib_file,"rb");
if (!fp)
{
DBG ( DBG_info, "Calibration: Cannot open %s\n", dev->calib_file );
DBG (DBG_proc, "read_calibration: exit\n");
return;
}
/* these two checks ensure that most bad things cannot happen */
fread(&vers,1,1,fp);
if (vers != CALIBRATION_VERSION)
{
DBG ( DBG_info, "Calibration: Bad version\n" );
fclose(fp);
DBG (DBG_proc, "read_calibration: exit\n");
return;
}
fread(&size,4,1,fp);
if (size != sizeof(struct Genesys_Calibration_Cache))
{
DBG ( DBG_info, "Calibration: Size of calibration cache struct differs\n" );
fclose(fp);
DBG (DBG_proc, "read_calibration: exit\n");
return;
}
while(!feof(fp))
{
DBG (DBG_info, "read_calibration: reading one record\n");
cache = (struct Genesys_Calibration_Cache *)malloc(sizeof(*cache));
if (!cache)
{
DBG (DBG_error, "read_calibration: could not allocate cache struct\n");
break;
}
#define BILT1( x ) \
do \
{ \
if ((x) < 1) \
{ \
free(cache); \
DBG (DBG_warn, "read_calibration: partial calibration record\n"); \
break; \
} \
} while(0)
if (fread(&cache->used_setup,sizeof(cache->used_setup),1,fp) < 1)
{ /* eof is only detected here */
free(cache);
break;
}
BILT1(fread(&cache->last_calibration,sizeof(cache->last_calibration),1,fp));
BILT1(fread(&cache->frontend,sizeof(cache->frontend),1,fp));
/* the gamma (and later) fields are not stored */
BILT1(fread(&cache->sensor,offsetof(Genesys_Sensor,red_gamma),1,fp));
BILT1(fread(&cache->calib_pixels,sizeof(cache->calib_pixels),1,fp));
BILT1(fread(&cache->average_size,sizeof(cache->average_size),1,fp));
/* Make sure we don't do bad things if someone feeds us a forged/
sufficiently corrupted calibration file.
gl843 can do up to 0x5800 pixels. add some slack for the
dummy/blank pixel mess */
if (cache->average_size > 0xb000+0x100)
{
DBG (DBG_error, "read_calibration: bad size of calibration data\n");
free(cache);
break;
}
cache->white_average_data = (uint8_t*)malloc(cache->average_size);
cache->dark_average_data = (uint8_t*)malloc(cache->average_size);
if (!cache->white_average_data || !cache->dark_average_data)
{
FREE_IFNOT_NULL(cache->white_average_data);
FREE_IFNOT_NULL(cache->dark_average_data);
free(cache);
DBG (DBG_error, "read_calibration: could not allocate space for average data\n");
break;
}
if (fread(cache->white_average_data,cache->average_size,1,fp) < 1)
{
DBG (DBG_warn, "read_calibration: partial calibration record\n");
free(cache->white_average_data);
free(cache->dark_average_data);
free(cache);
break;
}
if (fread(cache->dark_average_data,cache->average_size,1,fp) < 1)
{
DBG (DBG_warn, "read_calibration: partial calibration record\n");
free(cache->white_average_data);
free(cache->dark_average_data);
free(cache);
break;
}
#undef BILT1
DBG (DBG_info, "read_calibration: adding record to list\n");
cache->next = dev->calibration_cache;
dev->calibration_cache = cache;
}
fclose(fp);
DBG (DBG_proc, "read_calibration: exit\n");
}
static void
write_calibration(Genesys_Device * dev)
{
FILE *fp;
uint8_t vers = 0;
uint32_t size = 0;
struct Genesys_Calibration_Cache *cache;
fp = fopen(dev->calib_file,"wb");
if (!fp)
{
DBG ( DBG_info, "Calibration: Cannot open %s\n", dev->calib_file );
return;
}
vers = CALIBRATION_VERSION;
fwrite(&vers,1,1,fp);
size = sizeof(struct Genesys_Calibration_Cache);
fwrite(&size,4,1,fp);
for(cache = dev->calibration_cache; cache; cache = cache->next)
{
fwrite(&cache->used_setup,sizeof(cache->used_setup),1,fp);
fwrite(&cache->last_calibration,sizeof(cache->last_calibration),1,fp);
fwrite(&cache->frontend,sizeof(cache->frontend),1,fp);
/* the gamma (and later) fields are not stored */
fwrite(&cache->sensor,offsetof(Genesys_Sensor,red_gamma),1,fp);
fwrite(&cache->calib_pixels,sizeof(cache->calib_pixels),1,fp);
fwrite(&cache->average_size,sizeof(cache->average_size),1,fp);
fwrite(cache->white_average_data,cache->average_size,1,fp);
fwrite(cache->dark_average_data,cache->average_size,1,fp);
}
fclose(fp);
}
/* -------------------------- SANE API functions ------------------------- */
SANE_Status
@ -5424,6 +5757,8 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle)
Genesys_Device *dev;
SANE_Status status;
Genesys_Scanner *s;
char tmp_str[PATH_MAX];
char *ptr;
DBG (DBG_proc, "sane_open: start (devicename = `%s')\n", devicename);
@ -5499,6 +5834,7 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle)
s->dev->read_active = SANE_FALSE;
s->dev->white_average_data = NULL;
s->dev->dark_average_data = NULL;
s->dev->calibration_cache = NULL;
/* insert newly opened handle into list of open handles: */
s->next = first_handle;
@ -5518,6 +5854,31 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle)
RIE (dev->model->cmd_set->init (dev));
/* here is the place to fetch a stored calibration cache */
/* create calibration-filename
lifted from plustek-usb.c
*/
/* we should add a unique identifying feature to the file name
to support multiple scanners of the same model, but to my
knowledge, there is no such thing in these scanners.
(At least the usb serial is always "0".)
*/
ptr = getenv ("HOME");
if( NULL == ptr ) {
sprintf( tmp_str, "/tmp/%s.cal", s->dev->model->name );
} else {
sprintf( tmp_str, "%s/.sane/%s.cal", ptr, s->dev->model->name );
}
s->dev->calib_file = strdup( tmp_str );
DBG( DBG_info, "Calibration filename set to:\n" );
DBG( DBG_info, ">%s<\n", s->dev->calib_file );
/* now open file, fetch calibration records */
read_calibration(s->dev);
DBG (DBG_proc, "sane_open: exit\n");
return SANE_STATUS_GOOD;
}
@ -5526,6 +5887,7 @@ void
sane_close (SANE_Handle handle)
{
Genesys_Scanner *prev, *s;
Genesys_Calibration_Cache *cache, *next_cache;
DBG (DBG_proc, "sane_close: start\n");
@ -5543,6 +5905,17 @@ sane_close (SANE_Handle handle)
return; /* oops, not a handle we know about */
}
/* here is the place to store calibration cache */
write_calibration(s->dev);
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);
}
sanei_genesys_buffer_free (&(s->dev->read_buffer));
sanei_genesys_buffer_free (&(s->dev->lines_buffer));
sanei_genesys_buffer_free (&(s->dev->shrink_buffer));

Wyświetl plik

@ -4821,10 +4821,14 @@ static Genesys_Command_Set gl646_cmd_set = {
gl646_bulk_write_register,
gl646_bulk_write_data,
gl646_bulk_read_data,
gl646_update_hardware_sensors,
gl646_load_document,
gl646_detect_document_end,
gl646_eject_document,
NULL,/*is_compatible_calibration*/
};
SANE_Status

Wyświetl plik

@ -3077,6 +3077,273 @@ dummy \ scanned lines
return SANE_STATUS_GOOD;
}
static SANE_Status
gl841_calculate_current_setup (Genesys_Device * dev)
{
int channels;
int depth;
int start;
float xres;/*dpi*/
float yres;/*dpi*/
float startx;/*optical_res, from dummy_pixel+1*/
float pixels;
float lines;
int color_filter;
int used_res;
int used_pixels;
unsigned int lincnt;
int exposure_time, exposure_time2, led_exposure;
int i;
int stagger;
int slope_dpi = 0;
int dummy = 0;
int scan_step_type = 1;
int scan_power_mode = 0;
int max_shift;
SANE_Bool half_ccd; /* false: full CCD res is used, true, half max CCD res is used */
int optical_res;
DBG (DBG_info,
"gl841_calculate_current_setup settings:\n"
"Resolution: %uDPI\n"
"Lines : %u\n"
"PPL : %u\n"
"Startpos : %.3f/%.3f\n"
"Scan mode : %d\n\n",
dev->settings.yres, dev->settings.lines, dev->settings.pixels,
dev->settings.tl_x, dev->settings.tl_y, dev->settings.scan_mode);
/* channels */
if (dev->settings.scan_mode == 4) /* single pass color */
channels = 3;
else
channels = 1;
/* depth */
depth = dev->settings.depth;
if (dev->settings.scan_mode == 0)
depth = 1;
/* start */
start = SANE_UNFIX (dev->model->x_offset);
start += dev->settings.tl_x;
start = (start * dev->sensor.optical_res) / MM_PER_INCH;
xres = dev->settings.xres;/*dpi*/
yres = dev->settings.yres;/*dpi*/
startx = start;/*optical_res, from dummy_pixel+1*/
pixels = dev->settings.pixels;
lines = dev->settings.lines;
color_filter = dev->settings.color_filter;
DBG (DBG_info,
"gl841_calculate_current_setup settings:\n"
"Resolution : %gDPI/%gDPI\n"
"Lines : %g\n"
"PPL : %g\n"
"Startpos : %g\n"
"Depth/Channels: %u/%u\n\n",
xres, yres, lines, pixels,
startx,
depth, channels);
/* half_ccd */
/* we have 2 domains for ccd: xres below or above half ccd max dpi */
if (dev->sensor.optical_res < 2 * xres) {
half_ccd = SANE_FALSE;
} else {
half_ccd = SANE_TRUE;
}
/* optical_res */
optical_res = dev->sensor.optical_res;
if (half_ccd)
optical_res /= 2;
/* stagger */
if ((!half_ccd) && (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE))
stagger = (4 * yres) / dev->motor.base_ydpi;
else
stagger = 0;
DBG (DBG_info, "gl841_calculate_current_setup: stagger=%d lines\n",
stagger);
/* used_res */
i = optical_res / xres;
/* gl841 supports 1/1 1/2 1/3 1/4 1/5 1/6 1/8 1/10 1/12 1/15 averaging */
if (i < 2) /* optical_res >= xres > optical_res/2 */
used_res = optical_res;
else if (i < 3) /* optical_res/2 >= xres > optical_res/3 */
used_res = optical_res/2;
else if (i < 4) /* optical_res/3 >= xres > optical_res/4 */
used_res = optical_res/3;
else if (i < 5) /* optical_res/4 >= xres > optical_res/5 */
used_res = optical_res/4;
else if (i < 6) /* optical_res/5 >= xres > optical_res/6 */
used_res = optical_res/5;
else if (i < 8) /* optical_res/6 >= xres > optical_res/8 */
used_res = optical_res/6;
else if (i < 10) /* optical_res/8 >= xres > optical_res/10 */
used_res = optical_res/8;
else if (i < 12) /* optical_res/10 >= xres > optical_res/12 */
used_res = optical_res/10;
else if (i < 15) /* optical_res/12 >= xres > optical_res/15 */
used_res = optical_res/12;
else
used_res = optical_res/15;
/* compute scan parameters values */
/* pixels are allways given at half or full CCD optical resolution */
/* use detected left margin and fixed value */
/* start */
/* add x coordinates */
start =
((dev->sensor.CCD_start_xoffset + startx) * used_res) /
dev->sensor.optical_res;
/* needs to be aligned for used_res */
start = (start * optical_res) / used_res;
start += dev->sensor.dummy_pixel + 1;
if (stagger > 0)
start |= 1;
/* compute correct pixels number */
/* pixels */
used_pixels =
(pixels * optical_res) / xres;
/* round up pixels number if needed */
if (used_pixels * xres < pixels * optical_res)
used_pixels++;
/* dummy */
/* dummy lines: may not be usefull, for instance 250 dpi works with 0 or 1
dummy line. Maybe the dummy line adds correctness since the motor runs
slower (higher dpi)
*/
/* for cis this creates better aligned color lines:
dummy \ scanned lines
0: R G B R ...
1: R G B - R ...
2: R G B - - R ...
3: R G B - - - R ...
4: R G B - - - - R ...
5: R G B - - - - - R ...
6: R G B - - - - - - R ...
7: R G B - - - - - - - R ...
8: R G B - - - - - - - - R ...
9: R G B - - - - - - - - - R ...
10: R G B - - - - - - - - - - R ...
11: R G B - - - - - - - - - - - R ...
12: R G B - - - - - - - - - - - - R ...
13: R G B - - - - - - - - - - - - - R ...
14: R G B - - - - - - - - - - - - - - R ...
15: R G B - - - - - - - - - - - - - - - R ...
-- pierre
*/
dummy = 0;
/* slope_dpi */
/* cis color scan is effectively a gray scan with 3 gray lines per color
line and a FILTER of 0 */
if (dev->model->is_cis)
slope_dpi = yres*channels;
else
slope_dpi = yres;
slope_dpi = slope_dpi * (1 + dummy);
/* scan_step_type */
/* Try to do at least 4 steps per line. if that is impossible we will have to
live with that
*/
if (yres*4 < dev->motor.base_ydpi
|| dev->motor.max_step_type <= 0)
scan_step_type = 0;
else if (yres*4 < dev->motor.base_ydpi*2
|| dev->motor.max_step_type <= 1)
scan_step_type = 1;
else
scan_step_type = 2;
led_exposure = gl841_get_led_exposure(dev);
/* exposure_time */
exposure_time = sanei_genesys_exposure_time2(
dev,
slope_dpi,
scan_step_type,
start+used_pixels,/*+tgtime? currently done in sanei_genesys_exposure_time2 with tgtime = 32 pixel*/
led_exposure,
scan_power_mode);
while(scan_power_mode + 1 < dev->motor.power_mode_count) {
exposure_time2 = sanei_genesys_exposure_time2(
dev,
slope_dpi,
scan_step_type,
start+used_pixels,/*+tgtime? currently done in sanei_genesys_exposure_time2 with tgtime = 32 pixel*/
led_exposure,
scan_power_mode + 1);
if (exposure_time < exposure_time2)
break;
exposure_time = exposure_time2;
scan_power_mode++;
}
DBG (DBG_info, "gl841_calculate_current_setup : exposure_time=%d pixels\n",
exposure_time);
/* max_shift */
/* scanned area must be enlarged by max color shift needed */
/* all values are assumed >= 0 */
if (channels > 1)
{
max_shift = dev->model->ld_shift_r;
if (dev->model->ld_shift_b > max_shift)
max_shift = dev->model->ld_shift_b;
if (dev->model->ld_shift_g > max_shift)
max_shift = dev->model->ld_shift_g;
max_shift =
(max_shift * yres) / dev->motor.base_ydpi;
}
else
{
max_shift = 0;
}
/* lincnt */
lincnt = lines + max_shift + stagger;
dev->current_setup.pixels = (used_pixels * used_res)/optical_res;
dev->current_setup.lines = lincnt;
dev->current_setup.depth = depth;
dev->current_setup.channels = channels;
dev->current_setup.exposure_time = exposure_time;
dev->current_setup.xres = used_res;
dev->current_setup.yres = yres;
dev->current_setup.half_ccd = half_ccd;
dev->current_setup.stagger = stagger;
dev->current_setup.max_shift = max_shift + stagger;
DBG (DBG_proc, "gl841_calculate_current_setup: completed\n");
return SANE_STATUS_GOOD;
}
static void
gl841_set_motor_power (Genesys_Register_Set * regs, SANE_Bool set)
{
@ -5290,7 +5557,36 @@ sanei_gl841_repark_head (Genesys_Device * dev)
return status;
}
static SANE_Status
gl841_is_compatible_calibration (Genesys_Device * dev,
Genesys_Calibration_Cache *cache,
int for_overwrite)
{
SANE_Status status;
DBG (DBG_proc, "gl841_is_compatible_calibration\n");
status = gl841_calculate_current_setup (dev);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"gl841_is_compatible_calibration: failed to calculate current setup: %s\n",
sane_strstatus (status));
return status;
}
DBG (DBG_proc, "gl841_is_compatible_calibration: checking\n");
if (dev->current_setup.channels != cache->used_setup.channels)
return SANE_STATUS_UNSUPPORTED;
if (dev->current_setup.half_ccd != cache->used_setup.half_ccd)
return SANE_STATUS_UNSUPPORTED;
DBG (DBG_proc, "gl841_is_compatible_calibration: completed\n");
return SANE_STATUS_GOOD;
}
/*
* initialize ASIC : registers, motor tables, and gamma tables
@ -5560,6 +5856,7 @@ static Genesys_Command_Set gl841_cmd_set = {
gl841_detect_document_end,
gl841_eject_document,
gl841_is_compatible_calibration,
};
SANE_Status

Wyświetl plik

@ -294,6 +294,7 @@ Genesys_Color_Order;
/* Forward typedefs */
typedef struct Genesys_Device Genesys_Device;
struct Genesys_Scanner;
typedef struct Genesys_Calibration_Cache Genesys_Calibration_Cache;
/**
* Scanner command set description.
@ -392,6 +393,11 @@ typedef struct Genesys_Command_Set
* eject document from scanner
*/
SANE_Status (*eject_document) (Genesys_Device * dev);
SANE_Status (*is_compatible_calibration) (
Genesys_Device * dev,
Genesys_Calibration_Cache *cache,
SANE_Bool for_overwrite);
} Genesys_Command_Set;
typedef struct Genesys_Model
@ -508,10 +514,27 @@ typedef struct Genesys_Buffer
size_t avail; /* data bytes currently in buffer */
} Genesys_Buffer;
struct Genesys_Calibration_Cache
{
Genesys_Current_Setup used_setup;/* used to check if entry is compatible */
time_t last_calibration;
Genesys_Frontend frontend;
Genesys_Sensor sensor;
size_t calib_pixels;
size_t average_size;
uint8_t *white_average_data;
uint8_t *dark_average_data;
struct Genesys_Calibration_Cache *next;
};
struct Genesys_Device
{
SANE_Int dn;
SANE_String file_name;
SANE_String calib_file;
Genesys_Model *model;
Genesys_Register_Set reg[GENESYS_MAX_REGS];
@ -526,6 +549,8 @@ struct Genesys_Device
uint8_t control[6];
time_t init_date;
size_t average_size;
size_t calib_pixels;
uint8_t *white_average_data;
uint8_t *dark_average_data;
uint16_t dark[3];
@ -551,6 +576,8 @@ struct Genesys_Device
Genesys_Current_Setup current_setup; /* contains the real used values */
Genesys_Calibration_Cache *calibration_cache;
struct Genesys_Device *next;
};