first working version of sheetfed scanners shading calibration

- added a function to build planar shading data
- improved sheetfed_calibration function
merge-requests/1/head
Stéphane Voltz 2009-07-02 22:15:01 +02:00 zatwierdzone przez Stphane Voltz
rodzic d522b2c2f7
commit 247b585de7
4 zmienionych plików z 208 dodań i 154 usunięć

Wyświetl plik

@ -1290,7 +1290,10 @@ sanei_genesys_exposure_time (Genesys_Device * dev, Genesys_Register_Set * reg,
The data needs to be of size "size", and in little endian byte order.
*/
static SANE_Status
#ifndef UNIT_TESTING
static
#endif
SANE_Status
genesys_send_offset_and_shading (Genesys_Device * dev, uint8_t * data,
int size)
{
@ -2924,62 +2927,66 @@ compute_coefficients (Genesys_Device * dev,
* @shading_data memory area where to store the computed shading coefficients
* @param pixels_per_line number of pixels per line
* @param channels number of color channels (actually 1 or 3)
* @param avgpixels number of pixels to average
* @param cmat transcoding matrix for color channel order
* @param offset shading coefficients left offset
* @param coeff 4000h or 2000h depending on fast scan mode or not
* @param target white target value
*/
static void
compute_planar_coefficients (Genesys_Device * dev,
uint8_t * shading_data,
unsigned int pixels_per_line,
unsigned int words_per_color,
unsigned int channels,
unsigned int avgpixels,
int cmat[3],
unsigned int offset,
unsigned int coeff, unsigned int target_code)
unsigned int coeff, unsigned int target)
{
uint8_t *ptr; /*contain 16bit words in little endian */
uint8_t *ptr; /* contains 16bit words in little endian */
unsigned int x, j, c;
unsigned int val, dk;
unsigned int val, dk, br;
DBG (DBG_io,
"compute_planar_coefficients: pixels_per_line=%d, words=%d, coeff=0x%04x\n",
pixels_per_line, words_per_color, coeff);
for (c = 0; c < channels; c++)
{
for (x = 0; x < pixels_per_line - offset - avgpixels - 1;
x += avgpixels)
/* shading data is larger than pixels_per_line so offset can be neglected */
for (x = 0; x < pixels_per_line; x++)
{
/* x2 because of 16 bit values, and x2 since one coeff for dark
* and another for white */
ptr = shading_data + pixels_per_line * c + (x + offset) * 2 * 2;
ptr =
shading_data + words_per_color * cmat[c] * 2 + (x + offset) * 4;
/* dark data */
/* we only handle deletion and not average */
dk = 0;
for (j = 0; j < avgpixels; j++)
br = 0;
dk +=
256 * dev->dark_average_data[(x + pixels_per_line * c) * 2 + 1];
dk += dev->dark_average_data[(x + pixels_per_line * c) * 2];
br +=
256 * dev->white_average_data[(x + pixels_per_line * c) * 2 + 1];
br += dev->white_average_data[(x + pixels_per_line * c) * 2];
if (br - dk > 0)
{
dk += 256 * dev->dark_average_data[(x + j) * 2 + 1];
dk += dev->dark_average_data[(x + j) * 2];
val = (coeff * target) / (br - dk);
if (val >= 65535)
{
val = 65535;
}
}
dk /= j;
if (dk > 65535)
dk = 65535;
for (j = 0; j < avgpixels; j++)
else
{
ptr[0 + j * 2] = dk & 255;
ptr[1 + j * 2] = dk / 256;
}
/* white data */
val = 0;
for (j = 0; j < avgpixels; j++)
{
val += 256 * dev->white_average_data[(x + j) * 2 + 1];
val += dev->white_average_data[(x + j) * 2];
}
val /= j;
val -= (256 * ptr[1] + ptr[0]);
val = compute_coefficient (coeff, target_code, val);
for (j = 0; j < avgpixels; j++)
{
ptr[2 + j * 2] = val & 0xff;
ptr[3 + j * 2] = val / 256;
val = coeff;
}
ptr[0] = dk & 255;
ptr[1] = dk / 256;
ptr[2] = val & 0xff;
ptr[3] = val / 256;
}
}
}
@ -2992,8 +2999,9 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
uint8_t *shading_data; /**> contains 16bit words in little endian */
uint8_t channels;
unsigned int x, j, o;
unsigned int length; /**> number of shading calibration data words */
unsigned int length; /**> number of shading calibration data words */
unsigned int i, res;
int cmat[3]; /**> matrix of color channels */
unsigned int coeff, target_code, val, avgpixels, dk, words_per_color = 0;
unsigned int target_dark, target_bright, br;
@ -3020,10 +3028,10 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
words_per_color = 0x15400;
break;
}
length=0x1fe00;
length = 0x1fe00;
}
else /* GL646 case */
{ /* DPIHW */
{ /* DPIHW */
/* we make the shading data such that each color channel data line is contiguous
* to the next one, which allow to write thes 3 channels in 1 write
* during genesys_send_shading_coefficient, some values are words, other bytes
@ -3032,35 +3040,37 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
{
/* 600 dpi */
case 0:
words_per_color = 0x2A00 * 2;
length=0x2A00 * 3;
/* 5376 * 2 max */
words_per_color = 0x2a00;
break;
/* 1200 dpi */
case 1:
words_per_color = 0x5500 * 2;
length=0x5500 * 3;
words_per_color = 0x5500;
break;
/* 2400 dpi */
case 2:
words_per_color = 0xA800 * 2;
length=0xA800 * 3;
words_per_color = 0xa800;
break;
}
/* 3 channels, 2 bytes a word */
length = words_per_color * 3 * 2;
}
shading_data = malloc (words_per_color * 3); /* 16 bit black, 16 bit white */
memset (shading_data, 0, words_per_color * 3);
shading_data = malloc (length); /* 16 bit black, 16 bit white */
}
else
else /* chunky calibration data case */
{
length=pixels_per_line * 2 * 3;
shading_data = malloc (length*2); /* 16 bit black, 16 bit white */
length = pixels_per_line * 2 * 2 * 3; /* 16 bit black, 16 bit white */
}
/* allocate computed size */
shading_data = malloc (length);
if (!shading_data)
{
DBG (DBG_error,
"genesys_send_shading_coefficient: failed to allocate memory\n");
return SANE_STATUS_NO_MEM;
}
memset (shading_data, 0, length);
/* TARGET/(Wn-Dn) = white gain -> ~1.xxx then it is multiplied by 0x2000
or 0x4000 to give an integer
@ -3081,20 +3091,19 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
switch (dev->model->ccd_type)
{
case CIS_XP200:
target_code = 0xf000;
memset (shading_data, 0x00, pixels_per_line * 4 * 3);
o = 0;
/* XXX STEF XXX : TODO compute avgpixels on scan settings */
avgpixels = 1;
target_code = 0xdc00;
o = 2;
cmat[0] = 2; /* red is last */
cmat[1] = 0; /* green is first */
cmat[2] = 1; /* blue is second */
compute_planar_coefficients (dev,
shading_data,
pixels_per_line,
channels, avgpixels, o, coeff,
target_code);
words_per_color,
channels, cmat, o, coeff, target_code);
break;
case CCD_5345:
target_code = 0xfa00;
memset (shading_data, 0x00, pixels_per_line * 4 * channels);
o = 4;
avgpixels = 1;
compute_coefficients (dev,
@ -3106,7 +3115,6 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
case CCD_HP2400:
case CCD_HP3670:
target_code = 0xfa00;
memset (shading_data, 0x00, pixels_per_line * 4 * channels);
o = 2;
avgpixels = 1;
compute_coefficients (dev,
@ -3689,6 +3697,7 @@ static SANE_Status
genesys_sheetfed_calibration (Genesys_Device * dev)
{
SANE_Status status = SANE_STATUS_GOOD;
SANE_Bool forward = SANE_TRUE;
DBG (DBG_proc, "genesys_sheetfed_calibration: start\n");
if (dev->model->cmd_set->search_strip == NULL)
@ -3708,39 +3717,26 @@ genesys_sheetfed_calibration (Genesys_Device * dev)
return status;
}
/* we set up for shading calibration, start scan and then scan lines by lines until
* we find a black strip crossing the calibration sheet */
/* seek black/white reverse/forward */
status = dev->model->cmd_set->search_strip (dev, SANE_TRUE, SANE_TRUE);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"genesys_sheetfed_calibration: failed to find black strip: %s\n",
sane_strstatus (status));
dev->model->cmd_set->eject_document (dev);
return status;
}
/******************* shading calibration ***************************/
/* send default shading data */
/* XXX STEF XXX status = sanei_genesys_init_shading_data (dev, pixels_per_line);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"genesys_sheetfed_calibration: failed to init shading process: %s\n",
sane_strstatus (status));
return status;
} */
/* we know we hare on a black area */
/* search for a full width black strip and then do a 16 bit scan to
* gather black shading data */
if (dev->model->flags & GENESYS_FLAG_DARK_CALIBRATION)
{
/* seek black/white reverse/forward */
status = dev->model->cmd_set->search_strip (dev, forward, SANE_TRUE);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"genesys_sheetfed_calibration: failed to find black strip: %s\n",
sane_strstatus (status));
dev->model->cmd_set->eject_document (dev);
return status;
}
status = dev->model->cmd_set->init_regs_for_shading (dev);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"genesys_sheetfed_calibration: failed to do wset up registers for shading calibration: %s\n",
"genesys_sheetfed_calibration: failed to do set up registers for shading calibration: %s\n",
sane_strstatus (status));
return status;
}
@ -3753,14 +3749,16 @@ genesys_sheetfed_calibration (Genesys_Device * dev)
sane_strstatus (status));
return status;
}
forward = SANE_FALSE;
}
/* go back to a white area */
status = dev->model->cmd_set->search_strip (dev, SANE_FALSE, SANE_FALSE);
/* go to a white area */
status = dev->model->cmd_set->search_strip (dev, forward, SANE_FALSE);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"genesys_sheetfed_calibration: failed to find black strip: %s\n",
"genesys_sheetfed_calibration: failed to find white strip: %s\n",
sane_strstatus (status));
dev->model->cmd_set->eject_document (dev);
return status;
@ -3770,7 +3768,7 @@ genesys_sheetfed_calibration (Genesys_Device * dev)
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"genesys_sheetfed_calibration: failed to do wset up registers for shading calibration: %s\n",
"genesys_sheetfed_calibration: failed to do set up registers for shading calibration: %s\n",
sane_strstatus (status));
return status;
}
@ -3779,10 +3777,17 @@ genesys_sheetfed_calibration (Genesys_Device * dev)
{
dev->model->cmd_set->eject_document (dev);
DBG (DBG_error,
"genesys_sheetfed_calibration: failed to do white shading calibration: %s\n",
"genesys_sheetfed_calibration: failed eject target: %s\n",
sane_strstatus (status));
return status;
}
/* in case we haven't black shading data, build it from black pixels
* of white calibration */
if (!(dev->model->flags & GENESYS_FLAG_DARK_CALIBRATION))
{
/* XXX STEF TODO XXX */
}
/* send the shading coefficient */
status = genesys_send_shading_coefficient (dev);

Wyświetl plik

@ -104,8 +104,8 @@ static Genesys_Frontend Wolfson[] = {
, /* 6: CANONLIDE35 */
{DAC_AD_XP200,{0x58, 0x00, 0x00, 0x00} /* TODO create an AnalogDevice struct */
, {0x00, 0x00, 0x00}
, {0x0a, 0x00, 0x00} /* offset */
, {0x20, 0x00, 0x00} /* gain */
, {0x05, 0x00, 0x00} /* offset */ /* 0A */
, {0x0d, 0x00, 0x00} /* gain */ /* 20 */
, {0x00, 0x00, 0x00}
}
,
@ -251,7 +251,7 @@ static Genesys_Sensor Sensor[] = {
/* 7: Strobe XP200 */
{CIS_XP200, 600,
48,
38, 0, 5454, 210, 200,
38, 0, 5200, 210, 200, /* 5125 */
{0x16, 0x00, 0x01, 0x03}
,
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x0a, 0x20, 0x2a, 0x6a, 0x8a,
@ -977,7 +977,7 @@ Genesys_Model visioneer_xp200_model = {
| GENESYS_FLAG_DARK_CALIBRATION
| GENESYS_FLAG_NO_CALIBRATION,
GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE,
20,
120,
132
};

Wyświetl plik

@ -159,6 +159,8 @@ gl646_bulk_write_register (Genesys_Device * dev,
{
DBG (DBG_io2, "DPISET =%d\n",
gl646_get_double_reg (reg, REG_DPISET));
DBG (DBG_io2, "DUMMY =%d\n",
sanei_genesys_get_address (reg, REG_DUMMY)->value);
DBG (DBG_io2, "STRPIXEL =%d\n",
gl646_get_double_reg (reg, REG_STRPIXEL));
DBG (DBG_io2, "ENDPIXEL =%d\n",
@ -886,9 +888,15 @@ gl646_setup_registers (Genesys_Device * dev,
else
regs[reg_0x05].value &= ~REG05_GMMENB;
/* true CIS gray */
/* true CIS gray if needed */
if (dev->model->is_cis == SANE_TRUE && color == SANE_FALSE)
regs[reg_0x05].value |= REG05_LEDADD;
{
regs[reg_0x05].value |= REG05_LEDADD;
}
else
{
regs[reg_0x05].value &= ~REG05_LEDADD;
}
/* cktoggle, ckdelay and cksel at once, cktdelay=2 => half_ccd for md5345 */
regs[reg_0x18].value = sensor->reg_0x18;
@ -1510,7 +1518,7 @@ gl646_init_regs (Genesys_Device * dev)
dev->reg[reg_0x2e].value = 0x78; /* set black&white threshold high level */
dev->reg[reg_0x2f].value = 0x7f; /* set black&white threshold low level */
dev->reg[reg_0x30].value = 0x00; /* begin pixel positon (16) */
dev->reg[reg_0x30].value = 0x00; /* begin pixel position (16) */
dev->reg[reg_0x31].value = dev->sensor.dummy_pixel /*0x10 */ ; /* TGW + 2*TG_SHLD + x */
dev->reg[reg_0x32].value = 0x2a /*0x15 */ ; /* end pixel position (5390) */
dev->reg[reg_0x33].value = 0xf8 /*0x0e */ ; /* TGW + 2*TG_SHLD + y */
@ -2011,7 +2019,10 @@ gl646_set_powersaving (Genesys_Device * dev, int delay /* in minutes */ )
* HOMESNR becomes 1 ->document left sensor
* paper event -> document is out
*/
static SANE_Status
#ifndef UNIT_TESTING
static
#endif
SANE_Status
gl646_load_document (Genesys_Device * dev)
{
SANE_Status status = SANE_STATUS_GOOD;
@ -2262,12 +2273,12 @@ gl646_eject_document (Genesys_Device * dev)
Genesys_Register_Set regs[11];
unsigned int used, vfinal, count;
uint16_t slope_table[255];
uint8_t val;
uint8_t gpio, state;
DBG (DBG_proc, "gl646_eject_document: start\n");
/* first check for document event */
status = gl646_gpio_read (dev->dn, &val);
status = gl646_gpio_read (dev->dn, &gpio);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
@ -2275,19 +2286,10 @@ gl646_eject_document (Genesys_Device * dev)
sane_strstatus (status));
return status;
}
DBG (DBG_info, "gl646_eject_document: GPIO=0x%02x\n", val);
/* no need for eject if document left during regular scan */
if (val != 0)
{
dev->document = SANE_FALSE;
DBG (DBG_info, "gl646_eject_document: no more document to eject\n");
DBG (DBG_proc, "gl646_eject_document: end\n");
return status;
}
DBG (DBG_info, "gl646_eject_document: GPIO=0x%02x\n", gpio);
/* test status : paper event + HOMESNR -> no more doc ? */
status = sanei_genesys_get_status (dev, &val);
status = sanei_genesys_get_status (dev, &state);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
@ -2295,7 +2297,22 @@ gl646_eject_document (Genesys_Device * dev)
sane_strstatus (status));
return status;
}
DBG (DBG_info, "gl646_eject_document: state=0x%02x\n", state);
if (DBG_LEVEL > DBG_info)
{
print_status (state);
}
/* HOMSNR=0 if no document inserted */
if ((state & REG41_HOMESNR) != 0)
{
dev->document = SANE_FALSE;
DBG (DBG_info, "gl646_eject_document: no more document to eject\n");
DBG (DBG_proc, "gl646_eject_document: end\n");
return status;
}
/* there is a document inserted, eject it */
status = sanei_genesys_write_register (dev, 0x01, 0xb0);
if (status != SANE_STATUS_GOOD)
{
@ -2309,7 +2326,7 @@ gl646_eject_document (Genesys_Device * dev)
do
{
usleep (200000UL);
status = sanei_genesys_get_status (dev, &val);
status = sanei_genesys_get_status (dev, &state);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
@ -2318,7 +2335,7 @@ gl646_eject_document (Genesys_Device * dev)
return status;
}
}
while (val & REG41_MOTMFLG);
while (state & REG41_MOTMFLG);
/* set up to fast move before scan then move until document is detected */
regs[0].address = 0x01;
@ -2397,8 +2414,8 @@ gl646_eject_document (Genesys_Device * dev)
count = 0;
do
{
status = sanei_genesys_get_status (dev, &val);
print_status (val);
status = sanei_genesys_get_status (dev, &state);
print_status (state);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
@ -2409,7 +2426,18 @@ gl646_eject_document (Genesys_Device * dev)
usleep (200000UL); /* sleep 200 ms */
count++;
}
while (((val & REG41_HOMESNR) == 0) && (count < 150));
while (((state & REG41_HOMESNR) == 0) && (count < 150));
/* read GPIO on exit */
status = gl646_gpio_read (dev->dn, &gpio);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"gl646_eject_document: failed to read paper sensor %s\n",
sane_strstatus (status));
return status;
}
DBG (DBG_info, "gl646_eject_document: GPIO=0x%02x\n", gpio);
DBG (DBG_proc, "gl646_eject_document: end\n");
return status;
@ -2758,7 +2786,7 @@ gl646_search_start_position (Genesys_Device * dev)
settings.exposure_time = 0;
/* scan the desired area */
status = simple_scan (dev, settings, SANE_TRUE, SANE_TRUE, &data);
status = simple_scan (dev, settings, SANE_TRUE, SANE_TRUE, SANE_FALSE, &data);
/* process data if scan is OK */
if (status == SANE_STATUS_GOOD)
@ -2899,7 +2927,15 @@ gl646_init_regs_for_shading (Genesys_Device * dev)
/* TODO another flag to setup regs ? */
/* enforce needed LINCNT, getting rid of extra lines for color reordering */
gl646_set_triple_reg (dev->reg, REG_LINCNT, dev->model->shading_lines);
if (dev->model->is_cis == SANE_FALSE)
{
gl646_set_triple_reg (dev->reg, REG_LINCNT, dev->model->shading_lines);
}
else
{
gl646_set_triple_reg (dev->reg, REG_LINCNT,
dev->model->shading_lines * 3);
}
/* copy reg to calib_reg */
memcpy (dev->calib_reg, dev->reg,
@ -2938,6 +2974,7 @@ gl646_init_regs_for_scan (Genesys_Device * dev)
}
dev->scanhead_position_in_steps = 0;
}
return setup_for_scan (dev, dev->settings, SANE_FALSE, SANE_TRUE,
SANE_TRUE);
}
@ -3346,7 +3383,7 @@ gl646_offset_calibration (Genesys_Device * dev)
dev->frontend.offset[0] = bottom;
dev->frontend.offset[1] = bottom;
dev->frontend.offset[2] = bottom;
status = simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, &first_line);
status = simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, SANE_FALSE, &first_line);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
@ -3372,7 +3409,7 @@ gl646_offset_calibration (Genesys_Device * dev)
dev->frontend.offset[0] = top;
dev->frontend.offset[1] = top;
dev->frontend.offset[2] = top;
status = simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, &second_line);
status = simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, SANE_FALSE, &second_line);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
@ -3403,7 +3440,7 @@ gl646_offset_calibration (Genesys_Device * dev)
/* scan with no move */
status =
simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, &second_line);
simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, SANE_FALSE, &second_line);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
@ -3442,7 +3479,7 @@ gl646_offset_calibration (Genesys_Device * dev)
if (DBG_LEVEL >= DBG_data)
{
status =
simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, &second_line);
simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, SANE_FALSE, &second_line);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
@ -3542,7 +3579,7 @@ gl646_coarse_gain_calibration (Genesys_Device * dev, int dpi)
|| (average[2] < dev->sensor.gain_white_ref)) && (pass < 30))
{
/* scan with no move */
status = simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, &line);
status = simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, SANE_FALSE,&line);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
@ -4053,9 +4090,12 @@ gl646_init (Genesys_Device * dev)
* @param move SANE_TRUE if moving forward during scan
* @param data pointer for the data
*/
static SANE_Status
#ifndef UNIT_TESTING
static
#endif
SANE_Status
simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move,
SANE_Bool forward, unsigned char **data)
SANE_Bool forward, SANE_Bool shading, unsigned char **data)
{
SANE_Status status = SANE_STATUS_INVAL;
unsigned int size, lines, x, y, bpp;
@ -4093,7 +4133,7 @@ simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move,
else
bpp = 1;
size *= bpp;
if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */
if (settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */
size *= 3;
*data = malloc (size);
if (!*data)
@ -4103,6 +4143,9 @@ simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move,
return SANE_STATUS_NO_MEM;
}
/* put back real line number in settings */
settings.lines = lines;
/* initialize frontend */
status = gl646_set_fe (dev, AFE_SET);
if (status != SANE_STATUS_GOOD)
@ -4116,6 +4159,10 @@ simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move,
/* no shading correction and not watch dog for simple scan */
dev->reg[reg_0x01].value &= ~(REG01_DVDSET | REG01_DOGENB);
if(shading==SANE_TRUE)
{
dev->reg[reg_0x01].value |= REG01_DVDSET;
}
/* one table movement for simple scan */
dev->reg[reg_0x02].value &= ~REG02_FASTFED;
@ -4181,59 +4228,50 @@ simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move,
&& settings.scan_mode == SCAN_MODE_COLOR)
{
/* alloc one line sized working buffer */
size = size / settings.lines;
buffer = (unsigned char *) malloc (size);
buffer = (unsigned char *) malloc (settings.pixels * 3 * bpp);
if (buffer == NULL)
{
DBG (DBG_error,
"simple_scan: failed to allocate %d bytes of memory\n", size);
"simple_scan: failed to allocate %d bytes of memory\n", settings.pixels * 3);
return SANE_STATUS_NO_MEM;
}
/* reorder one line of data and put it back to buffer */
if (bpp == 1)
{
for (y = 0; y < settings.lines; y++)
for (y = 0; y < lines; y++)
{
/* reorder line */
for (x = 0; x < settings.pixels; x++)
{
buffer[x * 3] = (*data)[y * size + x];
buffer[x * 3 + 1] = (*data)[y * size + settings.pixels + x];
buffer[x * 3 + 2] =
(*data)[y * size + 2 * settings.pixels + x];
buffer[x * 3 ] = (*data)[y * settings.pixels * 3 + x];
buffer[x * 3 + 1] = (*data)[y * settings.pixels * 3 + settings.pixels + x];
buffer[x * 3 + 2] = (*data)[y * settings.pixels * 3 + 2 * settings.pixels + x];
}
/* copy line back */
memcpy ((*data) + size * y, buffer, size);
memcpy ((*data) + settings.pixels * 3 * y, buffer, settings.pixels * 3);
}
}
else
{
for (y = 0; y < settings.lines; y++)
for (y = 0; y < lines; y++)
{
/* reorder line */
for (x = 0; x < settings.pixels; x++)
{
buffer[x * 6] = (*data)[y * size + x];
buffer[x * 6 + 1] = (*data)[y * size + x + 1];
buffer[x * 6 + 2] = (*data)[y * size + settings.pixels + x];
buffer[x * 6 + 3] =
(*data)[y * size + settings.pixels + x + 1];
buffer[x * 6 + 4] =
(*data)[y * size + 2 * settings.pixels + x];
buffer[x * 6 + 5] =
(*data)[y * size + 2 * settings.pixels + x + 1];
buffer[x * 6 ] = (*data)[y * settings.pixels * 6 + x * 2 ];
buffer[x * 6 + 1] = (*data)[y * settings.pixels * 6 + x * 2 + 1];
buffer[x * 6 + 2] = (*data)[y * settings.pixels * 6 + 2 * settings.pixels + x * 2 ];
buffer[x * 6 + 3] = (*data)[y * settings.pixels * 6 + 2 * settings.pixels + x * 2 + 1];
buffer[x * 6 + 4] = (*data)[y * settings.pixels * 6 + 4 * settings.pixels + x * 2 ];
buffer[x * 6 + 5] = (*data)[y * settings.pixels * 6 + 4 * settings.pixels + x * 2 + 1];
}
/* copy line back */
memcpy ((*data) + size * y, buffer, size);
memcpy ((*data) + settings.pixels * 6 * y, buffer, settings.pixels * 6);
}
}
free (buffer);
}
/* put back real line number in settings */
/* XXX STEF XXX */
settings.lines = lines;
/* end scan , waiting the motor to stop if needed (if moving), but without ejecting doc */
status = end_scan (dev, dev->reg, SANE_TRUE, SANE_FALSE);
@ -4523,7 +4561,7 @@ gl646_search_strip (Genesys_Device * dev, SANE_Bool forward, SANE_Bool black)
settings.yres = res;
settings.tl_x = 0;
settings.tl_y = 0;
settings.pixels = (SANE_UNFIX (dev->model->x_size) * res) / MM_PER_INCH;
settings.pixels = (SANE_UNFIX (dev->model->x_size) * res) / MM_PER_INCH;
if (half_ccd == SANE_TRUE)
{
settings.pixels /= 2;
@ -4548,7 +4586,7 @@ gl646_search_strip (Genesys_Device * dev, SANE_Bool forward, SANE_Bool black)
while (pass < 20 && !found)
{
/* scan a full width strip */
status = simple_scan (dev, settings, SANE_TRUE, forward, &data);
status = simple_scan (dev, settings, SANE_TRUE, forward, SANE_FALSE, &data);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "gl646_search_strip: simple_scan failed\n");
@ -4557,7 +4595,8 @@ gl646_search_strip (Genesys_Device * dev, SANE_Bool forward, SANE_Bool black)
}
if (DBG_LEVEL >= DBG_data)
{
sprintf (title, "search_strip_%s%02d.pnm", forward ? "fwd" : "bwd", pass);
sprintf (title, "search_strip_%s%02d.pnm", forward ? "fwd" : "bwd",
pass);
sanei_genesys_write_pnm_file (title, data, settings.depth, 1,
settings.pixels, settings.lines);
}

Wyświetl plik

@ -173,6 +173,7 @@
#define REG_DPISET 0x2c
#define REG_STRPIXEL 0x30
#define REG_ENDPIXEL 0x32
#define REG_DUMMY 0x34
#define REG_MAXWD 0x35
#define REG_LPERIOD 0x38
#define REG_FEEDL 0x3d
@ -316,11 +317,15 @@ gl646_setup_registers (Genesys_Device * dev,
* @param settings settings of the scan
* @param move flag to enable scanhead to move
* @param forward flag to tell movement direction
* @param shading flag to tell if shading correction should be done
* @param data pointer that will point to the scanned data
*/
static SANE_Status
#ifndef UNIT_TESTING
static
#endif
SANE_Status
simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move, SANE_Bool forward,
unsigned char **data);
SANE_Bool shading, unsigned char **data);
/**
* Send the stop scan command
@ -339,6 +344,11 @@ static SANE_Status write_control (Genesys_Device * dev, int resolution);
*/
static void gl646_init_regs (Genesys_Device * dev);
#ifndef UNIT_TESTING
static
#endif
SANE_Status gl646_load_document (Genesys_Device * dev);
#define FULL_STEP 0
#define HALF_STEP 1