epson2: fixed color shuffling bug for Perfection 610, added more debugging

merge-requests/1/head
Alessandro Zummo 2010-01-09 15:13:50 +01:00
rodzic 2482974b96
commit dd0e0dd7d4
3 zmienionych plików z 90 dodań i 198 usunięć

Wyświetl plik

@ -140,6 +140,8 @@ static const int color_params[] = {
void
e2_dev_init(Epson_Device *dev, const char *devname, int conntype)
{
DBG(5, "%s\n", __func__);
dev->name = NULL;
dev->model = NULL;
dev->connection = conntype;
@ -179,7 +181,9 @@ SANE_Status
e2_dev_post_init(struct Epson_Device *dev)
{
int i;
DBG(5, "%s\n", __func__);
/* find cct model id */
for (i = 0; epson_cct_models[i].name != NULL; i++) {
if (strcmp(epson_cct_models[i].name, dev->model) == 0) {
@ -974,11 +978,11 @@ e2_set_scanning_parameters(Epson_Scanner * s)
/*
* There is some undocumented special behavior with the TPU enable/disable.
* TPU power ESC e status
* on 0 NAK
* on 1 ACK
* off 0 ACK
* off 1 NAK
* TPU power ESC e status
* on 0 NAK
* on 1 ACK
* off 0 ACK
* off 1 NAK
*
* It makes no sense to scan with TPU powered on and source flatbed, because
* light will come from both sides.
@ -1167,9 +1171,31 @@ e2_set_scanning_parameters(Epson_Scanner * s)
/* not implemented */
/* ESC A, set scanning area */
status = esci_set_scan_area(s, s->left, s->top,
/*
* Modify the scan area: If the scanner requires color shuffling, then we try to
* scan more lines to compensate for the lines that will be removed from the scan
* due to the color shuffling algorithm.
*/
if (s->hw->color_shuffle == SANE_TRUE) {
unsigned int lines = s->params.lines + (2 * s->line_distance);
int top = s->top - (1 * s->line_distance);
if (top < 0)
top = 0;
status = esci_set_scan_area(s, s->left, top,
s->params.pixels_per_line,
lines);
} else {
status = esci_set_scan_area(s, s->left, s->top,
s->params.pixels_per_line,
s->params.lines);
}
if (status != SANE_STATUS_GOOD)
return status;
@ -1187,6 +1213,8 @@ e2_setup_block_mode(Epson_Scanner * s)
{
int maxreq;
DBG(5, "%s\n", __func__);
if (s->hw->connection == SANE_EPSON_SCSI)
maxreq = sanei_scsi_max_request_size;
else if (s->hw->connection == SANE_EPSON_USB)
@ -1218,6 +1246,7 @@ e2_setup_block_mode(Epson_Scanner * s)
* for bi-level scanning. If a bit depth of 1 is selected, then
* make sure the next lower even number is selected.
*/
if (s->lcount > 3 && s->lcount % 2)
s->lcount -= 1;
@ -1227,12 +1256,13 @@ e2_setup_block_mode(Epson_Scanner * s)
SANE_Status
e2_init_parameters(Epson_Scanner * s)
{
int dpi, max_y, max_x, bytes_per_pixel;
int dpi, bytes_per_pixel;
struct mode_param *mparam;
DBG(5, "%s\n", __func__);
memset(&s->params, 0, sizeof(SANE_Parameters));
max_x = max_y = 0;
dpi = s->val[OPT_RESOLUTION].w;
mparam = &mode_params[s->val[OPT_MODE].w];
@ -1241,36 +1271,22 @@ e2_init_parameters(Epson_Scanner * s)
SANE_UNFIX(s->val[OPT_BR_X].w) == 0)
return SANE_STATUS_INVAL;
s->left = SANE_UNFIX(s->val[OPT_TL_X].w) / MM_PER_INCH *
s->val[OPT_RESOLUTION].w + 0.5;
s->left = ((SANE_UNFIX(s->val[OPT_TL_X].w) / MM_PER_INCH) *
s->val[OPT_RESOLUTION].w) + 0.5;
s->top = SANE_UNFIX(s->val[OPT_TL_Y].w) / MM_PER_INCH *
s->val[OPT_RESOLUTION].w + 0.5;
s->top = ((SANE_UNFIX(s->val[OPT_TL_Y].w) / MM_PER_INCH) *
s->val[OPT_RESOLUTION].w) + 0.5;
/* XXX check this */
s->params.pixels_per_line =
SANE_UNFIX(s->val[OPT_BR_X].w -
s->val[OPT_TL_X].w) / MM_PER_INCH * dpi + 0.5;
((SANE_UNFIX(s->val[OPT_BR_X].w -
s->val[OPT_TL_X].w) / MM_PER_INCH) * dpi) + 0.5;
s->params.lines =
SANE_UNFIX(s->val[OPT_BR_Y].w -
s->val[OPT_TL_Y].w) / MM_PER_INCH * dpi + 0.5;
((SANE_UNFIX(s->val[OPT_BR_Y].w -
s->val[OPT_TL_Y].w) / MM_PER_INCH) * dpi) + 0.5;
/*
* Make sure that the number of lines is correct for color shuffling:
* The shuffling alghorithm produces 2xline_distance lines at the
* beginning and the same amount at the end of the scan that are not
* useable. If s->params.lines gets negative, 0 lines are reported
* back to the frontend.
*/
if (s->hw->color_shuffle) {
s->params.lines -= 4 * s->line_distance;
if (s->params.lines < 0) {
s->params.lines = 0;
}
DBG(1,
"adjusted params.lines for color_shuffle by %d to %d\n",
4 * s->line_distance, s->params.lines);
}
DBG(1, "%s: resolution = %d, preview = %d\n",
__func__, s->val[OPT_RESOLUTION].w, s->val[OPT_PREVIEW].w);
DBG(1, "%s: %p %p tlx %f tly %f brx %f bry %f [mm]\n",
__func__, (void *) s, (void *) s->val,
@ -1341,45 +1357,31 @@ e2_init_parameters(Epson_Scanner * s)
*/
s->hw->color_shuffle = SANE_FALSE;
s->current_output_line = 0;
s->lines_written = 0;
s->color_shuffle_line = 0;
s->current_output_line = 0;
if ((s->hw->optical_res != 0) && (mparam->depth == 8)
&& (mparam->flags != 0)) {
s->line_distance =
s->hw->max_line_distance * dpi / s->hw->optical_res;
if (s->line_distance != 0) {
s->hw->color_shuffle = SANE_TRUE;
} else
s->hw->color_shuffle = SANE_FALSE;
}
/*
* Modify the scan area: If the scanner requires color shuffling, then we try to
* scan more lines to compensate for the lines that will be removed from the scan
* due to the color shuffling alghorithm.
* At this time we add two times the line distance to the number of scan lines if
* this is possible - if not, then we try to calculate the number of additional
* lines according to the selected scan area.
*/
if (s->hw->color_shuffle == SANE_TRUE) {
/* start the scan 2 * line_distance earlier */
s->top -= 2 * s->line_distance;
if (s->top < 0) {
s->top = 0;
DBG(1, "%s: color shuffling required\n", __func__);
}
/* scan 4*line_distance lines more */
s->params.lines += 4 * s->line_distance;
}
/*
* If (s->top + s->params.lines) is larger than the max scan area, reset
* the number of scan lines:
* XXX: precalculate the maximum scanning area elsewhere (use dev max_y)
*/
if (SANE_UNFIX(s->val[OPT_BR_Y].w) / MM_PER_INCH * dpi <
(s->params.lines + s->top)) {
s->params.lines =
@ -1396,17 +1398,17 @@ e2_init_parameters(Epson_Scanner * s)
* 'D' and not for the actual numeric level.
*/
if ((s->hw->cmd->level[0] == 'B') && (s->hw->level >= 5))
e2_setup_block_mode(s);
else if ((s->hw->cmd->level[0] == 'B') && (s->hw->level == 4)
&& (!mode_params[s->val[OPT_MODE].w].color))
e2_setup_block_mode(s);
else if (s->hw->cmd->level[0] == 'D')
if ((s->hw->cmd->level[0] == 'B') && (s->hw->level >= 5)) /* >= B5 */
e2_setup_block_mode(s);
/* XXX call print_params here */
else if ((s->hw->cmd->level[0] == 'B') && (s->hw->level == 4) /* B4 !color */
&& (!mode_params[s->val[OPT_MODE].w].color))
e2_setup_block_mode(s);
return SANE_STATUS_GOOD;
else if (s->hw->cmd->level[0] == 'D') /* Dx */
e2_setup_block_mode(s);
return (s->params.lines > 0) ? SANE_STATUS_GOOD : SANE_STATUS_INVAL;
}
void
@ -1668,9 +1670,8 @@ e2_copy_image_data(Epson_Scanner * s, SANE_Byte * data, SANE_Int max_length,
}
SANE_Status
e2_ext_sane_read(SANE_Handle handle)
e2_ext_read(struct Epson_Scanner *s)
{
Epson_Scanner *s = (Epson_Scanner *) handle;
SANE_Status status = SANE_STATUS_GOOD;
ssize_t buf_len = 0, read;
@ -1978,9 +1979,8 @@ get_color(int status)
SANE_Status
e2_block_sane_read(SANE_Handle handle)
e2_block_read(struct Epson_Scanner *s)
{
Epson_Scanner *s = (Epson_Scanner *) handle;
SANE_Status status;
SANE_Bool reorder = SANE_FALSE;
SANE_Bool needStrangeReorder = SANE_FALSE;

Wyświetl plik

@ -48,5 +48,5 @@ extern SANE_Status e2_start_ext_scan(Epson_Scanner *s);
extern void e2_scan_finish(Epson_Scanner *s);
extern void e2_copy_image_data(Epson_Scanner *s, SANE_Byte *data, SANE_Int max_length,
SANE_Int *length);
extern SANE_Status e2_ext_sane_read(SANE_Handle handle);
extern SANE_Status e2_block_sane_read(SANE_Handle handle);
extern SANE_Status e2_ext_read(struct Epson_Scanner *s);
extern SANE_Status e2_block_read(struct Epson_Scanner *s);

Wyświetl plik

@ -2049,137 +2049,25 @@ SANE_Status
sane_get_parameters(SANE_Handle handle, SANE_Parameters *params)
{
Epson_Scanner *s = (Epson_Scanner *) handle;
int dpi, max_x, max_y;
int bytes_per_pixel;
DBG(5, "%s\n", __func__);
if (params == NULL)
DBG(1, "%s: params is NULL\n", __func__);
/*
* If sane_start was already called, then just retrieve the parameters
* from the scanner data structure
*/
if (!s->eof && s->ptr != NULL) {
DBG(5, "returning saved params structure\n");
if (params != NULL) {
DBG(1,
"restoring parameters from saved parameters\n");
*params = s->params;
}
DBG(5, "resolution = %d, preview = %d\n",
s->val[OPT_RESOLUTION].w, s->val[OPT_PREVIEW].w);
DBG(5, "get para tlx %f tly %f brx %f bry %f [mm]\n",
SANE_UNFIX(s->val[OPT_TL_X].w),
SANE_UNFIX(s->val[OPT_TL_Y].w),
SANE_UNFIX(s->val[OPT_BR_X].w),
SANE_UNFIX(s->val[OPT_BR_Y].w));
print_params(s->params);
return SANE_STATUS_GOOD;
DBG(5, "scan in progress, returning saved params structure\n");
} else {
/* otherwise initialize the params structure and gather the data */
e2_init_parameters(s);
}
/* otherwise initialize the params structure and gather the data */
memset(&s->params, 0, sizeof(SANE_Parameters));
dpi = s->val[OPT_RESOLUTION].w;
max_x = max_y = 0;
s->params.pixels_per_line =
((SANE_UNFIX(s->val[OPT_BR_X].w - s->val[OPT_TL_X].w)
/ MM_PER_INCH) * dpi) + 0.5;
s->params.lines =
((SANE_UNFIX(s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w)
/ MM_PER_INCH) * dpi) + 0.5;
/*
* Make sure that the number of lines is correct for color shuffling:
* The shuffling alghorithm produces 2xline_distance lines at the
* beginning and the same amount at the end of the scan that are not
* useable. If s->params.lines gets negative, 0 lines are reported
* back to the frontend.
*/
if (s->hw->color_shuffle) {
s->params.lines -= 4 * s->line_distance;
if (s->params.lines < 0)
s->params.lines = 0;
DBG(1, "adjusted params.lines for color_shuffle by %d to %d\n",
4 * s->line_distance, s->params.lines);
}
DBG(5, "resolution = %d, preview = %d\n",
s->val[OPT_RESOLUTION].w, s->val[OPT_PREVIEW].w);
DBG(5, "get para %p %p tlx %f tly %f brx %f bry %f [mm]\n",
(void *) s, (void *) s->val, SANE_UNFIX(s->val[OPT_TL_X].w),
SANE_UNFIX(s->val[OPT_TL_Y].w), SANE_UNFIX(s->val[OPT_BR_X].w),
SANE_UNFIX(s->val[OPT_BR_Y].w));
/*
* Calculate bytes_per_pixel and bytes_per_line for
* any color depths.
*
* The default color depth is stored in mode_params.depth:
*/
if (mode_params[s->val[OPT_MODE].w].depth == 1)
s->params.depth = 1;
else
s->params.depth = s->val[OPT_BIT_DEPTH].w;
if (s->params.depth > 8) {
s->params.depth = 16; /*
* The frontends can only handle 8 or 16 bits
* for gray or color - so if it's more than 8,
* it gets automatically set to 16. This works
* as long as EPSON does not come out with a
* scanner that can handle more than 16 bits
* per color channel.
*/
}
bytes_per_pixel = s->params.depth / 8; /* this works because it can only be set to 1, 8 or 16 */
if (s->params.depth % 8) { /* just in case ... */
bytes_per_pixel++;
}
/* pixels_per_line is rounded to the next 8bit boundary */
s->params.pixels_per_line = s->params.pixels_per_line & ~7;
s->params.last_frame = SANE_TRUE;
switch (s->val[OPT_MODE].w) {
case MODE_BINARY:
case MODE_GRAY:
s->params.format = SANE_FRAME_GRAY;
s->params.bytes_per_line =
s->params.pixels_per_line * s->params.depth / 8;
break;
case MODE_COLOR:
s->params.format = SANE_FRAME_RGB;
s->params.bytes_per_line =
3 * s->params.pixels_per_line * bytes_per_pixel;
break;
#ifdef SANE_FRAME_IR
case MODE_INFRARED:
s->params.format = SANE_FRAME_IR;
s->params.bytes_per_line =
s->params.pixels_per_line * s->params.depth / 8;
break;
#endif
}
if (NULL != params)
if (params != NULL)
*params = s->params;
print_params(s->params);
@ -2224,6 +2112,8 @@ sane_start(SANE_Handle handle)
if (status != SANE_STATUS_GOOD)
return status;
print_params(s->params);
/* enable infrared */
if (s->val[OPT_MODE].w == MODE_INFRARED)
esci_enable_infrared(handle);
@ -2284,11 +2174,6 @@ sane_start(SANE_Handle handle)
if (status != SANE_STATUS_GOOD)
return status;
/*
status = sane_get_parameters(handle, NULL);
if (status != SANE_STATUS_GOOD)
return status;
*/
/*
* If WAIT_FOR_BUTTON is active, then do just that:
* Wait until the button is pressed. If the button was already
@ -2408,13 +2293,20 @@ sane_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length,
*length = 0;
if (s->hw->extended_commands)
status = e2_ext_sane_read(handle);
status = e2_ext_read(s);
else
status = e2_block_sane_read(handle);
status = e2_block_read(s);
DBG(18, "moving data %p %p, %d (%d lines)\n",
s->ptr, s->end,
max_length, max_length / s->params.bytes_per_line);
DBG(18, "moving data %d %p %p\n", max_length, s->ptr, s->end);
e2_copy_image_data(s, data, max_length, length);
DBG(18, "%d lines read, eof: %d, status: %d\n",
*length / s->params.bytes_per_line,
s->eof, status);
/* continue reading if appropriate */
if (status == SANE_STATUS_GOOD)
return status;