* backend/canon_dr.[ch], backend/canon_dr-cmd.h: backend v23

- rewrite all image data processing code
- handle more image interlacing formats
- re-enable binary mode on some scanners
- limit some machines to full-width scanning
* doc/desciptions/canon_dr.desc: v23, improved comments
merge-requests/1/head
m. allan noah 2009-03-28 01:04:02 +00:00
rodzic 009c5cd33d
commit a4561362b0
5 zmienionych plików z 282 dodań i 380 usunięć

Wyświetl plik

@ -1,3 +1,11 @@
2009-03-27 m. allan noah <kitno455 a t gmail d o t com>
* backend/canon_dr.[ch], backend/canon_dr-cmd.h: backend v23
- rewrite all image data processing code
- handle more image interlacing formats
- re-enable binary mode on some scanners
- limit some machines to full-width scanning
* doc/desciptions/canon_dr.desc: v23, improved comments
2009-03-25 m. allan noah <kitno455 a t gmail d o t com> 2009-03-25 m. allan noah <kitno455 a t gmail d o t com>
* backend/canon_dr.[ch]: backend v22 * backend/canon_dr.[ch]: backend v22
- add deinterlacing code for DR-2510C in duplex and color - add deinterlacing code for DR-2510C in duplex and color

Wyświetl plik

@ -93,7 +93,7 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
#define get_RS_ILI(b) getbitfield(b + 0x02, 1, 5) #define get_RS_ILI(b) getbitfield(b + 0x02, 1, 5)
#define get_RS_sense_key(b) getbitfield(b + 0x02, 0x0f, 0) #define get_RS_sense_key(b) getbitfield(b + 0x02, 0x0f, 0)
#define get_RS_information(b) getnbyte(b+0x03, 4) /* normally 0 */ #define get_RS_information(b) getnbyte(b+0x03, 4) /* normally 0 */
#define get_RS_additional_length(b) b[0x07] /* always 10 */ #define get_RS_additional_length(b) b[0x07] /* always 6? */
#define get_RS_ASC(b) b[0x0c] #define get_RS_ASC(b) b[0x0c]
#define get_RS_ASCQ(b) b[0x0d] #define get_RS_ASCQ(b) b[0x0d]
#define get_RS_SKSV(b) getbitfield(b+0x0f,1,7) /* valid=0 */ #define get_RS_SKSV(b) getbitfield(b+0x0f,1,7) /* valid=0 */

Wyświetl plik

@ -161,6 +161,11 @@
- skip send_panel and ssm_df commands for DR-20xx scanners - skip send_panel and ssm_df commands for DR-20xx scanners
v22 2009-03-25, MAN v22 2009-03-25, MAN
- add deinterlacing code for DR-2510C in duplex and color - add deinterlacing code for DR-2510C in duplex and color
v23 2009-03-27, MAN
- rewrite all image data processing code
- handle more image interlacing formats
- re-enable binary mode on some scanners
- limit some machines to full-width scanning
SANE FLOW DIAGRAM SANE FLOW DIAGRAM
@ -221,7 +226,7 @@
#include "canon_dr.h" #include "canon_dr.h"
#define DEBUG 1 #define DEBUG 1
#define BUILD 22 #define BUILD 23
/* values for SANE_DEBUG_CANON_DR env var: /* values for SANE_DEBUG_CANON_DR env var:
- errors 5 - errors 5
@ -1037,14 +1042,6 @@ init_model (struct scanner *s)
if (strstr (s->model_name,"C")){ if (strstr (s->model_name,"C")){
s->can_color = 1; s->can_color = 1;
} }
if (strstr (s->model_name,"DR-1")
|| strstr (s->model_name,"DR-2")
){
s->color_interlace = COLOR_INTERLACE_RRGGBB;
s->duplex_interlace = DUPLEX_INTERLACE_BYTE;
s->can_halftone = 0;
s->can_monochrome = 0;
}
/* specific settings missing from vpd */ /* specific settings missing from vpd */
if (strstr (s->model_name,"DR-9080") if (strstr (s->model_name,"DR-9080")
@ -1056,16 +1053,20 @@ init_model (struct scanner *s)
else if (strstr (s->model_name,"DR-2580")){ else if (strstr (s->model_name,"DR-2580")){
s->invert_tly = 1; s->invert_tly = 1;
s->rgb_format = 1; s->rgb_format = 1;
s->has_counter = 1; s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_RRGGBB;
s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_rRgGbB;
s->duplex_interlace = DUPLEX_INTERLACE_FBFB;
} }
else if (strstr (s->model_name,"DR-2510")){ else if (strstr (s->model_name,"DR-2510")){
s->rgb_format = 1; s->rgb_format = 1;
s->unknown_byte2 = 0x80; s->unknown_byte2 = 0x80;
s->has_counter = 1;
s->head_interlace = HEAD_INTERLACE_2510;
s->color_interlace = COLOR_INTERLACE_RGB;
s->fixed_width = 1; s->fixed_width = 1;
s->gray_interlace[SIDE_FRONT] = GRAY_INTERLACE_2510;
s->gray_interlace[SIDE_BACK] = GRAY_INTERLACE_2510;
s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_2510;
s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_2510;
s->duplex_interlace = DUPLEX_INTERLACE_2510;
} }
else if (strstr (s->model_name,"DR-2050") else if (strstr (s->model_name,"DR-2050")
@ -1073,6 +1074,10 @@ init_model (struct scanner *s)
){ ){
s->can_write_panel = 0; s->can_write_panel = 0;
s->has_df = 0; s->has_df = 0;
s->fixed_width = 1;
s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_RRGGBB;
s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_RRGGBB;
s->duplex_interlace = DUPLEX_INTERLACE_FBFB;
} }
DBG (10, "init_model: finish\n"); DBG (10, "init_model: finish\n");
@ -1136,7 +1141,7 @@ init_user (struct scanner *s)
/* page width US-Letter */ /* page width US-Letter */
s->page_width = 8.5 * 1200; s->page_width = 8.5 * 1200;
if(s->page_width > s->max_x){ if(s->page_width > s->max_x || s->fixed_width){
s->page_width = s->max_x; s->page_width = s->max_x;
} }
@ -2352,6 +2357,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
if (s->tl_x == FIXED_MM_TO_SCANNER_UNIT(val_c)) if (s->tl_x == FIXED_MM_TO_SCANNER_UNIT(val_c))
return SANE_STATUS_GOOD; return SANE_STATUS_GOOD;
if(!s->fixed_width)
s->tl_x = FIXED_MM_TO_SCANNER_UNIT(val_c); s->tl_x = FIXED_MM_TO_SCANNER_UNIT(val_c);
*info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
@ -2370,6 +2376,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
if (s->br_x == FIXED_MM_TO_SCANNER_UNIT(val_c)) if (s->br_x == FIXED_MM_TO_SCANNER_UNIT(val_c))
return SANE_STATUS_GOOD; return SANE_STATUS_GOOD;
if(!s->fixed_width)
s->br_x = FIXED_MM_TO_SCANNER_UNIT(val_c); s->br_x = FIXED_MM_TO_SCANNER_UNIT(val_c);
*info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
@ -2388,7 +2395,9 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
if (s->page_width == FIXED_MM_TO_SCANNER_UNIT(val_c)) if (s->page_width == FIXED_MM_TO_SCANNER_UNIT(val_c))
return SANE_STATUS_GOOD; return SANE_STATUS_GOOD;
if(!s->fixed_width)
s->page_width = FIXED_MM_TO_SCANNER_UNIT(val_c); s->page_width = FIXED_MM_TO_SCANNER_UNIT(val_c);
*info |= SANE_INFO_RELOAD_OPTIONS; *info |= SANE_INFO_RELOAD_OPTIONS;
return SANE_STATUS_GOOD; return SANE_STATUS_GOOD;
@ -2822,16 +2831,7 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
/* this backend only sends single frame images */ /* this backend only sends single frame images */
params->last_frame = 1; params->last_frame = 1;
/* dumb scanner, always scans full width */ params->pixels_per_line = (s->br_x - s->tl_x) * s->resolution_x / 1200;
/*FIXME: move this elsewhere*/
if(s->fixed_width){
s->tl_x = 0;
params->pixels_per_line = s->max_x * s->resolution_x / 1200;
}
else{
params->pixels_per_line
= (s->br_x - s->tl_x) * s->resolution_x / 1200;
}
params->lines = s->resolution_y * (s->br_y - s->tl_y) / 1200; params->lines = s->resolution_y * (s->br_y - s->tl_y) / 1200;
@ -3369,35 +3369,11 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len
return SANE_STATUS_EOF; return SANE_STATUS_EOF;
} }
/* alternating pnm interlacing */ /* double width pnm interlacing */
if(s->source == SOURCE_ADF_DUPLEX if(s->source == SOURCE_ADF_DUPLEX
&& s->params.format != SANE_FRAME_JPEG && s->params.format != SANE_FRAME_JPEG
&& s->duplex_interlace == DUPLEX_INTERLACE_ALT){ && s->duplex_interlace != DUPLEX_INTERLACE_NONE
){
/* buffer front side */
if(s->bytes_tot[SIDE_FRONT] > s->bytes_rx[SIDE_FRONT]){
ret = read_from_scanner(s, SIDE_FRONT);
if(ret){
DBG(5,"sane_read: front returning %d\n",ret);
return ret;
}
}
/* buffer back side */
if(s->bytes_tot[SIDE_BACK] > s->bytes_rx[SIDE_BACK] ){
ret = read_from_scanner(s, SIDE_BACK);
if(ret){
DBG(5,"sane_read: back returning %d\n",ret);
return ret;
}
}
} /* end alt pnm */
/* byte-level pnm interlacing */
else if(s->source == SOURCE_ADF_DUPLEX
&& s->params.format != SANE_FRAME_JPEG
&& s->duplex_interlace == DUPLEX_INTERLACE_BYTE){
/* buffer both sides */ /* buffer both sides */
if ( s->bytes_tot[SIDE_FRONT] > s->bytes_rx[SIDE_FRONT] if ( s->bytes_tot[SIDE_FRONT] > s->bytes_rx[SIDE_FRONT]
@ -3583,18 +3559,9 @@ read_from_scanner(struct scanner *s, int side)
} }
} }
/* we've got some data, descramble and store it */
if(inLen && !extra){ if(inLen && !extra){
copy_simplex(s,in,inLen,side);
/*non-jpeg, scrambled read-heads*/
if(s->params.format != SANE_FRAME_JPEG
&& s->head_interlace == HEAD_INTERLACE_2510){
copy_buffer_2510 (s, in, inLen, side);
}
/*jpeg or normal data*/
else {
copy_buffer (s, in, inLen, side);
}
} }
free(in); free(in);
@ -3686,18 +3653,9 @@ read_from_scanner_duplex(struct scanner *s)
inLen = 0; inLen = 0;
} }
/* we've got some data, descramble and store it */
if(inLen && !extra){ if(inLen && !extra){
copy_duplex(s,in,inLen);
/*non-jpeg, scrambled read-heads*/
if(s->params.format != SANE_FRAME_JPEG
&& s->head_interlace == HEAD_INTERLACE_2510){
copy_buffer_duplex_2510(s,in,inLen);
}
/*jpeg or normal data*/
else {
copy_buffer_duplex(s,in,inLen);
}
} }
free(in); free(in);
@ -3713,35 +3671,107 @@ read_from_scanner_duplex(struct scanner *s)
return ret; return ret;
} }
/* these functions copy image data from input buffer to scanner struct
* descrambling it, and putting it in the right side buffer */
/* NOTE: they assume buffer is scanline aligned */
static SANE_Status static SANE_Status
copy_buffer(struct scanner *s, unsigned char * buf, int len, int side) copy_simplex(struct scanner *s, unsigned char * buf, int len, int side)
{
SANE_Status ret=SANE_STATUS_GOOD;
DBG (10, "copy_buffer: start\n");
memcpy(s->buffers[side]+s->bytes_rx[side],buf,len);
s->bytes_rx[side] += len;
DBG (10, "copy_buffer: finish\n");
return ret;
}
/* NOTE: this code assumes buffer is scanline aligned */
static SANE_Status
copy_buffer_2510(struct scanner *s, unsigned char * buf, int len, int side)
{ {
SANE_Status ret=SANE_STATUS_GOOD; SANE_Status ret=SANE_STATUS_GOOD;
int i, j; int i, j;
int bwidth = s->params.bytes_per_line; int bwidth = s->params.bytes_per_line;
int pwidth = s->params.pixels_per_line;
int t = bwidth/3; int t = bwidth/3;
int f = bwidth/4; int f = bwidth/4;
int tw = bwidth/12; int tw = bwidth/12;
DBG (10, "copy_buffer_2510: start\n"); /* invert image if scanner needs it for this mode */
/* jpeg data does not use inverting */
if(s->params.format != SANE_FRAME_JPEG && s->reverse_by_mode[s->mode]){
for(i=0; i<len; i++){
buf[i] ^= 0xff;
}
}
if(s->mode == MODE_COLOR){ if(s->params.format == SANE_FRAME_GRAY){
switch (s->gray_interlace[side]) {
case GRAY_INTERLACE_2510:
DBG (10, "copy_simplex: gray, 2510\n");
for(i=0; i<len; i+=bwidth){
/* first read head (third byte of every three) */
for(j=bwidth-1;j>=0;j-=3){
s->buffers[side][s->bytes_rx[side]++] = buf[i+j];
}
/* second read head (first byte of every three) */
for(j=bwidth*3/4-3;j>=0;j-=3){
s->buffers[side][s->bytes_rx[side]++] = buf[i+j];
}
/* third read head (second byte of every three) */
for(j=bwidth-2;j>=0;j-=3){
s->buffers[side][s->bytes_rx[side]++] = buf[i+j];
}
/* padding */
for(j=0;j<tw;j++){
s->buffers[side][s->bytes_rx[side]++] = 0;
}
}
break;
default:
DBG (10, "copy_simplex: gray, default\n");
memcpy(s->buffers[side]+s->bytes_rx[side],buf,len);
s->bytes_rx[side] += len;
break;
}
}
else if (s->params.format == SANE_FRAME_RGB){
switch (s->color_interlace[side]) {
/* scanner returns color data as bgrbgr... */
case COLOR_INTERLACE_BGR:
DBG (10, "copy_simplex: color, BGR\n");
for(i=0; i<len; i+=bwidth){
for (j=0; j<pwidth; j++){
s->buffers[side][s->bytes_rx[side]++] = buf[i+j*3+2];
s->buffers[side][s->bytes_rx[side]++] = buf[i+j*3+1];
s->buffers[side][s->bytes_rx[side]++] = buf[i+j*3];
}
}
break;
/* one line has the following format: rrr...rrrggg...gggbbb...bbb */
case COLOR_INTERLACE_RRGGBB:
DBG (10, "copy_simplex: color, RRGGBB\n");
for(i=0; i<len; i+=bwidth){
for (j=0; j<pwidth; j++){
s->buffers[side][s->bytes_rx[side]++] = buf[i+j];
s->buffers[side][s->bytes_rx[side]++] = buf[i+pwidth+j];
s->buffers[side][s->bytes_rx[side]++] = buf[i+2*pwidth+j];
}
}
break;
/* one line has the following format: rrr...RRRggg...GGGbbb...BBB
* where the 'capital' letters are the beginning of the line */
case COLOR_INTERLACE_rRgGbB:
DBG (10, "copy_simplex: color, rRgGbB\n");
for(i=0; i<len; i+=bwidth){
for (j=pwidth-1; j>=0; j--){
s->buffers[side][s->bytes_rx[side]++] = buf[i+j];
s->buffers[side][s->bytes_rx[side]++] = buf[i+pwidth+j];
s->buffers[side][s->bytes_rx[side]++] = buf[i+2*pwidth+j];
}
}
break;
case COLOR_INTERLACE_2510:
DBG (10, "copy_simplex: color, 2510\n");
for(i=0; i<len; i+=bwidth){ for(i=0; i<len; i+=bwidth){
@ -3768,202 +3798,121 @@ copy_buffer_2510(struct scanner *s, unsigned char * buf, int len, int side)
s->buffers[side][s->bytes_rx[side]++] = 0; s->buffers[side][s->bytes_rx[side]++] = 0;
} }
} }
break;
default:
DBG (10, "copy_simplex: color, default\n");
memcpy(s->buffers[side]+s->bytes_rx[side],buf,len);
s->bytes_rx[side] += len;
break;
}
} }
/* only used by jpeg data? */
else{ else{
DBG (10, "copy_simplex: default\n");
for(i=0; i<len; i+=bwidth){ memcpy(s->buffers[side]+s->bytes_rx[side],buf,len);
s->bytes_rx[side] += len;
/* first read head (third byte of every three) */
for(j=bwidth-1;j>=0;j-=3){
s->buffers[side][s->bytes_rx[side]++] = buf[i+j];
}
/* second read head (first byte of every three) */
for(j=bwidth*3/4-3;j>=0;j-=3){
s->buffers[side][s->bytes_rx[side]++] = buf[i+j];
}
/* third read head (second byte of every three) */
for(j=bwidth-2;j>=0;j-=3){
s->buffers[side][s->bytes_rx[side]++] = buf[i+j];
}
/* padding */
for(j=0;j<tw;j++){
s->buffers[side][s->bytes_rx[side]++] = 0;
}
}
} }
DBG (10, "copy_buffer_2510: finish\n"); DBG (10, "copy_simplex: finished\n");
return ret; return ret;
} }
/* split the data between two buffers /* split the data between two buffers, hand them to copy_simplex()
* assumes that first byte of buffer is frontside data * assumes that the buffer aligns to a double-wide line boundary */
* and that the buffer starts/ends on a wide line boundary */
static SANE_Status static SANE_Status
copy_buffer_duplex(struct scanner *s, unsigned char * buf, int len) copy_duplex(struct scanner *s, unsigned char * buf, int len)
{ {
SANE_Status ret=SANE_STATUS_GOOD; SANE_Status ret=SANE_STATUS_GOOD;
int i,j; int i,j;
DBG (10, "copy_buffer_duplex: start\n");
/*frontside, just copy*/
for(i=0; i<len; i+=2*s->params.bytes_per_line){
for(j=0; j<2*s->params.bytes_per_line; j+=2){
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+j];
}
}
/*backside color: channels are in RGB order, but each is mirrored*/
if(s->mode == MODE_COLOR){
for(i=0; i<len; i+=2*s->params.bytes_per_line){
for(j=s->params.pixels_per_line; j>0; j--){
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+j*2-1];
}
for(j=s->params.pixels_per_line; j>0; j--){
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++]
= buf[i+2*s->params.pixels_per_line+j*2-1];
}
for(j=s->params.pixels_per_line; j>0; j--){
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++]
= buf[i+4*s->params.pixels_per_line+j*2-1];
}
}
}
/*backside gray: single mirrored channel*/
else{
for(i=0; i<len; i+=2*s->params.bytes_per_line){
for(j=2*s->params.bytes_per_line; j>0; j-=2){
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+j-1];
}
}
}
DBG (10, "copy_buffer_duplex: finish\n");
return ret;
}
/* NOTE: this code assumes buffer is scanline aligned */
static SANE_Status
copy_buffer_duplex_2510(struct scanner *s, unsigned char * buf, int len)
{
SANE_Status ret=SANE_STATUS_GOOD;
int i, j;
int bwidth = s->params.bytes_per_line; int bwidth = s->params.bytes_per_line;
int tq = bwidth*3/4; int dbwidth = 2*bwidth;
int t = bwidth/3; unsigned char * front;
int f = bwidth/4; unsigned char * back;
int tf = bwidth/24; int flen=0, blen=0;
DBG (10, "copy_buffer_duplex_2510: start\n"); DBG (10, "copy_duplex: start\n");
if(s->mode == MODE_COLOR){ /*split the input into two simplex output buffers*/
front = calloc(1,len/2);
for(i=0; i<len; i+=bwidth){ if(!front){
DBG (5, "copy_duplex: no front mem\n");
/* first read head */ return SANE_STATUS_NO_MEM;
for(j=t-5;j>=0;j-=6){
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+j];
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+t+j];
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+2*t+j];
} }
/* second read head */ back = calloc(1,len/2);
for(j=f-3;j>=0;j-=6){ if(!back){
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+j]; DBG (5, "copy_duplex: no back mem\n");
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+t+j]; free(front);
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+2*t+j]; return SANE_STATUS_NO_MEM;
}
/* third read head */
for(j=t-6;j>=0;j-=6){
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+j];
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+t+j];
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+2*t+j];
}
/* padding */
for(j=0;j<tf;j++){
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = 0;
} }
/* first read head */ if(s->duplex_interlace == DUPLEX_INTERLACE_2510){
for(j=t-1;j>=0;j-=6){
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+j]; DBG (10, "copy_duplex: 2510\n");
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+t+j];
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+2*t+j]; for(i=0; i<len; i+=dbwidth){
}
/* second read head */ for(j=0;j<dbwidth;j+=6){
for(j=f-4;j>=0;j-=6){
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+j]; /* we are actually only partially descrambling,
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+t+j]; * copy_simplex() does the rest */
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+2*t+j];
} /* front */
/* third read head */ /* 2nd head: 3rd byte -> 1st byte */
for(j=t-2;j>=0;j-=6){ /* 3rd head: 0th byte -> 2nd byte */
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+j]; /* 1st head: 1st byte -> 3rd byte */
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+t+j]; front[flen++] = buf[j+3];
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+2*t+j]; front[flen++] = buf[j];
} front[flen++] = buf[j+1];
/* padding */
for(j=0;j<tf;j++){ /* back */
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = 0; /* 2nd head: 2nd byte -> 1st byte */
/* 3rd head: 4th byte -> 2nd byte */
/* 1st head: 5th byte -> 3rd byte */
back[blen++] = buf[j+2];
back[blen++] = buf[j+4];
back[blen++] = buf[j+5];
} }
} }
} }
/* no scanners use this? */
else if(s->duplex_interlace == DUPLEX_INTERLACE_FFBB){
for(i=0; i<len; i+=dbwidth){
memcpy(front+flen,buf+i,bwidth);
flen+=bwidth;
memcpy(back+blen,buf+i+bwidth,bwidth);
blen+=bwidth;
}
}
/*just alternating bytes, FBFBFB*/
else { else {
for(i=0; i<len; i+=2){
for(i=0; i<len; i+=bwidth){ front[flen++] = buf[i];
back[blen++] = buf[i+1];
/* first read head */
for(j=bwidth-5;j>=0;j-=6){
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+j];
}
/* second read head */
for(j=tq-3;j>=0;j-=6){
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+j];
}
/* third read head */
for(j=bwidth-6;j>=0;j-=6){
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+j];
}
/* padding */
for(j=0;j<tf;j++){
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = 0;
}
/* first read head */
for(j=bwidth-1;j>=0;j-=6){
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+j];
}
/* second read head */
for(j=tq-4;j>=0;j-=6){
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+j];
}
/* third read head */
for(j=bwidth-2;j>=0;j-=6){
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+j];
}
/* padding */
for(j=0;j<tf;j++){
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = 0;
}
} }
} }
DBG (10, "copy_buffer_duplex_2510: finish\n"); copy_simplex(s,front,flen,SIDE_FRONT);
copy_simplex(s,back,blen,SIDE_BACK);
free(front);
free(back);
DBG (10, "copy_duplex: finished\n");
return ret; return ret;
} }
static SANE_Status static SANE_Status
read_from_buffer(struct scanner *s, SANE_Byte * buf, read_from_buffer(struct scanner *s, SANE_Byte * buf, SANE_Int max_len,
SANE_Int max_len, SANE_Int * len, int side) SANE_Int * len, int side)
{ {
SANE_Status ret=SANE_STATUS_GOOD; SANE_Status ret=SANE_STATUS_GOOD;
int bytes = max_len, i=0; int bytes = max_len;
int remain = s->bytes_rx[side] - s->bytes_tx[side]; int remain = s->bytes_rx[side] - s->bytes_tx[side];
DBG (10, "read_from_buffer: start\n"); DBG (10, "read_from_buffer: start\n");
@ -3984,63 +3933,9 @@ read_from_buffer(struct scanner *s, SANE_Byte * buf,
return SANE_STATUS_GOOD; return SANE_STATUS_GOOD;
} }
/* jpeg data does not use typical interlacing or inverting, just copy */ /* copy to caller */
if(s->params.format == SANE_FRAME_JPEG){
memcpy(buf,s->buffers[side]+s->bytes_tx[side],bytes); memcpy(buf,s->buffers[side]+s->bytes_tx[side],bytes);
} s->bytes_tx[side] += bytes;
/* not using jpeg, colors maybe interlaced, pixels maybe inverted */
else {
/* scanners interlace colors in many different ways */
/* use separate code to convert to regular rgb */
if(s->mode == MODE_COLOR){
int byteOff, lineOff;
switch (s->color_interlace) {
/* scanner returns pixel data as bgrbgr... */
case COLOR_INTERLACE_BGR:
for (i=0; i < bytes; i++){
byteOff = s->bytes_tx[side] + i;
buf[i] = s->buffers[side][ byteOff-((byteOff%3)-1)*2 ];
}
break;
/* one line has the following format:
* rrr...rrrggg...gggbbb...bbb */
case COLOR_INTERLACE_RRGGBB:
for (i=0; i < bytes; i++){
byteOff = s->bytes_tx[side] + i;
lineOff = byteOff % s->params.bytes_per_line;
buf[i] = s->buffers[side][
byteOff - lineOff /* line */
+ (lineOff%3)*s->params.pixels_per_line /* color */
+ (lineOff/3) /* pixel */
];
}
break;
default:
memcpy(buf,s->buffers[side]+s->bytes_tx[side],bytes);
break;
}
}
/* gray/ht/binary */
else{
memcpy(buf,s->buffers[side]+s->bytes_tx[side],bytes);
}
/* invert image if scanner needs it for this mode */
if (s->reverse_by_mode[s->mode]){
for ( i = 0; i < *len; i++ ) {
buf[i] ^= 0xff;
}
}
}
s->bytes_tx[side] += *len;
DBG (10, "read_from_buffer: finish\n"); DBG (10, "read_from_buffer: finish\n");

Wyświetl plik

@ -153,9 +153,9 @@ struct scanner
int padded_read; /* some machines need extra 12 bytes on reads */ int padded_read; /* some machines need extra 12 bytes on reads */
int fixed_width; /* some machines always scan full width */ int fixed_width; /* some machines always scan full width */
int color_interlace; /* different models interlace colors differently */ int gray_interlace[2]; /* different models interlace heads differently */
int color_interlace[2]; /* different models interlace colors differently */
int duplex_interlace; /* different models interlace sides differently */ int duplex_interlace; /* different models interlace sides differently */
int head_interlace; /* different models interlace heads differently */
int jpeg_interlace; /* different models interlace jpeg sides differently */ int jpeg_interlace; /* different models interlace jpeg sides differently */
int reverse_by_mode[6]; /* mode specific */ int reverse_by_mode[6]; /* mode specific */
@ -332,16 +332,19 @@ enum {
#define COLOR_WHITE 1 #define COLOR_WHITE 1
#define COLOR_BLACK 2 #define COLOR_BLACK 2
#define HEAD_INTERLACE_NONE 0 #define GRAY_INTERLACE_NONE 0
#define HEAD_INTERLACE_2510 1 #define GRAY_INTERLACE_2510 1
#define COLOR_INTERLACE_RGB 0 #define COLOR_INTERLACE_RGB 0
#define COLOR_INTERLACE_BGR 1 #define COLOR_INTERLACE_BGR 1
#define COLOR_INTERLACE_RRGGBB 2 #define COLOR_INTERLACE_RRGGBB 2
#define COLOR_INTERLACE_rRgGbB 3
#define COLOR_INTERLACE_2510 4
#define DUPLEX_INTERLACE_NONE 0 #define DUPLEX_INTERLACE_NONE 0
#define DUPLEX_INTERLACE_ALT 1 #define DUPLEX_INTERLACE_FFBB 1
#define DUPLEX_INTERLACE_BYTE 2 #define DUPLEX_INTERLACE_FBFB 2
#define DUPLEX_INTERLACE_2510 3
#define JPEG_INTERLACE_ALT 0 #define JPEG_INTERLACE_ALT 0
#define JPEG_INTERLACE_NONE 1 #define JPEG_INTERLACE_NONE 1
@ -470,11 +473,9 @@ static SANE_Status cancel(struct scanner *s);
static SANE_Status read_from_scanner(struct scanner *s, int side); static SANE_Status read_from_scanner(struct scanner *s, int side);
static SANE_Status read_from_scanner_duplex(struct scanner *s); static SANE_Status read_from_scanner_duplex(struct scanner *s);
static SANE_Status copy_buffer(struct scanner *s, unsigned char * buf, int len, int side); static SANE_Status copy_simplex(struct scanner *s, unsigned char * buf, int len, int side);
static SANE_Status copy_buffer_2510(struct scanner *s, unsigned char * buf, int len, int side);
static SANE_Status copy_buffer_duplex(struct scanner *s, unsigned char * buf, int len); static SANE_Status copy_duplex(struct scanner *s, unsigned char * buf, int len);
static SANE_Status copy_buffer_duplex_2510(struct scanner *s, unsigned char * buf, int len);
static SANE_Status read_from_buffer(struct scanner *s, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len, int side); static SANE_Status read_from_buffer(struct scanner *s, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len, int side);

Wyświetl plik

@ -11,7 +11,7 @@
:backend "canon_dr" ; name of backend :backend "canon_dr" ; name of backend
:url "http://www.thebility.com/canon/" :url "http://www.thebility.com/canon/"
:version "19" ; version of backend :version "23" ; version of backend
:manpage "sane-canon_dr" ; name of manpage (if it exists) :manpage "sane-canon_dr" ; name of manpage (if it exists)
:comment "New backend as of SANE release 1.1.0, testers needed, see manpage" :comment "New backend as of SANE release 1.1.0, testers needed, see manpage"
:devicetype :scanner ; start of a list of devices.... :devicetype :scanner ; start of a list of devices....
@ -62,8 +62,7 @@
:model "DR-2050C" :model "DR-2050C"
:interface "USB" :interface "USB"
:usbid "0x04a9" "0x160a" :usbid "0x04a9" "0x160a"
:status :basic :comment "Gray/Color, Simplex/Duplex working. Poor calibration, only full-width scans."
:comment ""
:model "DR-2050SP" :model "DR-2050SP"
:interface "USB" :interface "USB"
@ -74,20 +73,19 @@
:model "DR-2080C" :model "DR-2080C"
:interface "USB SCSI" :interface "USB SCSI"
:usbid "0x04a9" "0x1601" :usbid "0x04a9" "0x1601"
:status :basic :comment "Gray/Color, Simplex/Duplex working. Poor calibration, only full-width scans."
:comment ""
:model "DR-2510C" :model "DR-2510C"
:interface "USB" :interface "USB"
:usbid "0x1083" "0x1617" :usbid "0x1083" "0x1617"
:status :basic :status :basic
:comment "Only simplex gray works, always scans full-width." :comment "Gray/Color, Simplex/Duplex working. Poor calibration, only full-width scans."
:model "DR-2580C" :model "DR-2580C"
:interface "USB SCSI" :interface "USB SCSI"
:usbid "0x04a9" "0x1608" :usbid "0x04a9" "0x1608"
:status :basic :status :basic
:comment "Gray and color, simplex and duplex working. Poor calibration." :comment "Gray/Color, Simplex/Duplex working. Poor calibration."
:model "DR-3010C" :model "DR-3010C"
:interface "USB" :interface "USB"
@ -125,7 +123,7 @@
:interface "USB" :interface "USB"
:usbid "0x1083" "0x1614" :usbid "0x1083" "0x1614"
:status :good :status :good
:comment "Multistream unsupported" :comment "Binary/HT/Gray/Color, Simplex/Duplex working. Multistream unsupported."
:model "DR4080U" :model "DR4080U"
:interface "USB" :interface "USB"
@ -164,7 +162,7 @@
:interface "USB SCSI" :interface "USB SCSI"
:usbid "0x04a9" "0x1607" :usbid "0x04a9" "0x1607"
:status :good :status :good
:comment "" :comment "Simplex, duplex, all resolutions, binary/ht/gray, async mode, dropout-color, multifeed/staple detection, deskew, buttons and JPEG working. Imprinter, barcode, custom gamma and multistream unsupported"
:model "DR-7080C" :model "DR-7080C"
:interface "USB SCSI" :interface "USB SCSI"