kopia lustrzana https://gitlab.com/sane-project/backends
fujitsu backend v94, mostly changes to use less memory
- add side option to show which duplex image is being transferred - convert front and simplex buffers to use much less ram - add lowmemory option which makes duplex back buffer small too - refactor image handling code to track eof's instead of lengths - do color deinterlacing after reading from scanner, before bufferingmerge-requests/1/head
rodzic
75503aef19
commit
f56fc87ff9
|
@ -430,6 +430,12 @@
|
||||||
- ignore errors in scanner_control(),
|
- ignore errors in scanner_control(),
|
||||||
M3091 has not worked since sane 1.0.19, due to this.
|
M3091 has not worked since sane 1.0.19, due to this.
|
||||||
- copy_buffer needs to count lines, or M309[12] cannot duplex
|
- copy_buffer needs to count lines, or M309[12] cannot duplex
|
||||||
|
v94 2009-05-22, MAN
|
||||||
|
- add side option to show which duplex image is being transferred
|
||||||
|
- convert front and simplex buffers to use much less ram
|
||||||
|
- add lowmemory option which makes duplex back buffer small too
|
||||||
|
- refactor image handling code to track eof's instead of lengths
|
||||||
|
- do color deinterlacing after reading from scanner, before buffering
|
||||||
|
|
||||||
SANE FLOW DIAGRAM
|
SANE FLOW DIAGRAM
|
||||||
|
|
||||||
|
@ -3556,6 +3562,33 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
|
||||||
opt->cap = SANE_CAP_INACTIVE;
|
opt->cap = SANE_CAP_INACTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(option==OPT_LOW_MEM){
|
||||||
|
opt->name = "lowmemory";
|
||||||
|
opt->title = "Low Memory";
|
||||||
|
opt->desc = "Limit driver memory usage for use in embedded systems. Causes some duplex transfers to alternate sides on each call to sane_read. Value of option 'side' can be used to determine correct image. This option should only be used with custom front-end software.";
|
||||||
|
opt->type = SANE_TYPE_BOOL;
|
||||||
|
opt->unit = SANE_UNIT_NONE;
|
||||||
|
opt->size = sizeof(SANE_Word);
|
||||||
|
|
||||||
|
if (1)
|
||||||
|
opt->cap= SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
|
||||||
|
else
|
||||||
|
opt->cap = SANE_CAP_INACTIVE;
|
||||||
|
|
||||||
|
opt->constraint_type = SANE_CONSTRAINT_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(option==OPT_SIDE){
|
||||||
|
opt->name = "side";
|
||||||
|
opt->title = "Duplex side";
|
||||||
|
opt->desc = "Tells which side (0=front, 1=back) of a duplex scan the next call to sane_read will return.";
|
||||||
|
opt->type = SANE_TYPE_BOOL;
|
||||||
|
opt->unit = SANE_UNIT_NONE;
|
||||||
|
opt->size = sizeof(SANE_Word);
|
||||||
|
opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
|
||||||
|
opt->constraint_type = SANE_CONSTRAINT_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
/* "Endorser" group ------------------------------------------------------ */
|
/* "Endorser" group ------------------------------------------------------ */
|
||||||
if(option==OPT_ENDORSER_GROUP){
|
if(option==OPT_ENDORSER_GROUP){
|
||||||
opt->name = "endorser-options";
|
opt->name = "endorser-options";
|
||||||
|
@ -4433,6 +4466,14 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
|
||||||
*val_p = s->blue_offset;
|
*val_p = s->blue_offset;
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
|
|
||||||
|
case OPT_LOW_MEM:
|
||||||
|
*val_p = s->low_mem;
|
||||||
|
return SANE_STATUS_GOOD;
|
||||||
|
|
||||||
|
case OPT_SIDE:
|
||||||
|
*val_p = s->side;
|
||||||
|
return SANE_STATUS_GOOD;
|
||||||
|
|
||||||
/* Endorser Group */
|
/* Endorser Group */
|
||||||
case OPT_ENDORSER:
|
case OPT_ENDORSER:
|
||||||
*val_p = s->u_endorser;
|
*val_p = s->u_endorser;
|
||||||
|
@ -5026,6 +5067,10 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
|
||||||
s->blue_offset = val_c;
|
s->blue_offset = val_c;
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
|
|
||||||
|
case OPT_LOW_MEM:
|
||||||
|
s->low_mem = val_c;
|
||||||
|
return SANE_STATUS_GOOD;
|
||||||
|
|
||||||
/* Endorser Group */
|
/* Endorser Group */
|
||||||
case OPT_ENDORSER:
|
case OPT_ENDORSER:
|
||||||
s->u_endorser = val_c;
|
s->u_endorser = val_c;
|
||||||
|
@ -5868,11 +5913,18 @@ sane_start (SANE_Handle handle)
|
||||||
s->reading=1;
|
s->reading=1;
|
||||||
|
|
||||||
/* not finished with current side, error */
|
/* not finished with current side, error */
|
||||||
if (s->started && s->bytes_tx[s->side] != s->bytes_tot[s->side]) {
|
if (s->started && !s->eof_tx[s->side]) {
|
||||||
DBG(5,"sane_start: previous transfer not finished?");
|
DBG(5,"sane_start: previous transfer not finished?");
|
||||||
return SANE_STATUS_INVAL;
|
return SANE_STATUS_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* low mem mode messes up the side marker, reset it */
|
||||||
|
if(s->source == SOURCE_ADF_DUPLEX && s->low_mem
|
||||||
|
&& s->eof_tx[SIDE_FRONT] && s->eof_tx[SIDE_BACK]
|
||||||
|
){
|
||||||
|
s->side = SIDE_BACK;
|
||||||
|
}
|
||||||
|
|
||||||
/* batch start? inititalize struct and scanner */
|
/* batch start? inititalize struct and scanner */
|
||||||
if(!s->started){
|
if(!s->started){
|
||||||
|
|
||||||
|
@ -5948,9 +6000,18 @@ sane_start (SANE_Handle handle)
|
||||||
s->bytes_rx[1]=0;
|
s->bytes_rx[1]=0;
|
||||||
s->lines_rx[0]=0;
|
s->lines_rx[0]=0;
|
||||||
s->lines_rx[1]=0;
|
s->lines_rx[1]=0;
|
||||||
|
s->eof_rx[0]=0;
|
||||||
|
s->eof_rx[1]=0;
|
||||||
|
|
||||||
s->bytes_tx[0]=0;
|
s->bytes_tx[0]=0;
|
||||||
s->bytes_tx[1]=0;
|
s->bytes_tx[1]=0;
|
||||||
|
s->eof_tx[0]=0;
|
||||||
|
s->eof_tx[1]=0;
|
||||||
|
|
||||||
|
s->buff_rx[0]=0;
|
||||||
|
s->buff_rx[1]=0;
|
||||||
|
s->buff_tx[0]=0;
|
||||||
|
s->buff_tx[1]=0;
|
||||||
|
|
||||||
/* reset jpeg just in case... */
|
/* reset jpeg just in case... */
|
||||||
s->jpeg_stage = JPEG_STAGE_HEAD;
|
s->jpeg_stage = JPEG_STAGE_HEAD;
|
||||||
|
@ -5961,17 +6022,32 @@ sane_start (SANE_Handle handle)
|
||||||
/* store the number of front bytes */
|
/* store the number of front bytes */
|
||||||
if ( s->source != SOURCE_ADF_BACK ){
|
if ( s->source != SOURCE_ADF_BACK ){
|
||||||
s->bytes_tot[SIDE_FRONT] = s->params.bytes_per_line * s->params.lines;
|
s->bytes_tot[SIDE_FRONT] = s->params.bytes_per_line * s->params.lines;
|
||||||
|
s->buff_tot[SIDE_FRONT] = s->buffer_size;
|
||||||
|
|
||||||
|
/* the front buffer is normally very small, but some scanners or
|
||||||
|
* option combinations can't handle it, so we make a big one */
|
||||||
|
if(s->mode == MODE_COLOR && s->color_interlace == COLOR_INTERLACE_3091)
|
||||||
|
s->buff_tot[SIDE_FRONT] = s->bytes_tot[SIDE_FRONT];
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
s->bytes_tot[SIDE_FRONT] = 0;
|
s->bytes_tot[SIDE_FRONT] = 0;
|
||||||
|
s->buff_tot[SIDE_FRONT] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* store the number of back bytes */
|
/* store the number of back bytes */
|
||||||
if ( s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_ADF_BACK ){
|
if ( s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_ADF_BACK ){
|
||||||
s->bytes_tot[SIDE_BACK] = s->params.bytes_per_line * s->params.lines;
|
s->bytes_tot[SIDE_BACK] = s->params.bytes_per_line * s->params.lines;
|
||||||
|
s->buff_tot[SIDE_BACK] = s->bytes_tot[SIDE_BACK];
|
||||||
|
|
||||||
|
/* the back buffer is normally very large, but some scanners or
|
||||||
|
* option combinations dont need it, so we make a small one */
|
||||||
|
if(s->low_mem || s->source == SOURCE_ADF_BACK
|
||||||
|
|| s->duplex_interlace == DUPLEX_INTERLACE_NONE)
|
||||||
|
s->buff_tot[SIDE_BACK] = s->buffer_size;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
s->bytes_tot[SIDE_BACK] = 0;
|
s->bytes_tot[SIDE_BACK] = 0;
|
||||||
|
s->buff_tot[SIDE_BACK] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* first page of batch */
|
/* first page of batch */
|
||||||
|
@ -6205,8 +6281,9 @@ setup_buffers (struct fujitsu *s)
|
||||||
s->buffers[side] = NULL;
|
s->buffers[side] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(s->bytes_tot[side]){
|
if(s->buff_tot[side]){
|
||||||
s->buffers[side] = calloc (1,s->bytes_tot[side]);
|
s->buffers[side] = calloc (1,s->buff_tot[side]);
|
||||||
|
|
||||||
if (!s->buffers[side]) {
|
if (!s->buffers[side]) {
|
||||||
DBG (5, "setup_buffers: Error, no buffer %d.\n",side);
|
DBG (5, "setup_buffers: Error, no buffer %d.\n",side);
|
||||||
return SANE_STATUS_NO_MEM;
|
return SANE_STATUS_NO_MEM;
|
||||||
|
@ -6744,87 +6821,84 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sane_start required between sides */
|
/* sane_start required between sides */
|
||||||
if(s->bytes_tx[s->side] == s->bytes_tot[s->side]){
|
if(s->eof_rx[s->side] && s->bytes_tx[s->side] == s->bytes_rx[s->side]){
|
||||||
DBG (15, "sane_read: returning eof\n");
|
DBG (15, "sane_read: returning eof\n");
|
||||||
|
s->eof_tx[s->side] = 1;
|
||||||
|
|
||||||
|
/* swap sides if user asked for low-mem mode, we are duplexing,
|
||||||
|
* and there is data waiting on the other side */
|
||||||
|
if(s->low_mem && s->source == SOURCE_ADF_DUPLEX
|
||||||
|
&& (s->bytes_rx[!s->side] > s->bytes_tx[!s->side]
|
||||||
|
|| (s->eof_rx[!s->side] && !s->eof_tx[!s->side])
|
||||||
|
)
|
||||||
|
){
|
||||||
|
s->side = !s->side;
|
||||||
|
}
|
||||||
|
|
||||||
return SANE_STATUS_EOF;
|
return SANE_STATUS_EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* protect this block from sane_cancel */
|
/* protect this block from sane_cancel */
|
||||||
s->reading = 1;
|
s->reading = 1;
|
||||||
|
|
||||||
|
/* no bytes to send to caller, but no eof from scanner yet? get some */
|
||||||
|
if(s->buff_rx[s->side] == s->buff_tx[s->side]){
|
||||||
|
|
||||||
/* 3091/2 are on crack, get their own duplex reader function */
|
/* 3091/2 are on crack, get their own duplex reader function */
|
||||||
if(s->source == SOURCE_ADF_DUPLEX
|
if(s->source == SOURCE_ADF_DUPLEX
|
||||||
&& s->duplex_interlace == DUPLEX_INTERLACE_3091){
|
&& s->duplex_interlace == DUPLEX_INTERLACE_3091
|
||||||
|
|
||||||
if(s->bytes_tot[SIDE_FRONT] > s->bytes_rx[SIDE_FRONT]
|
|
||||||
|| s->bytes_tot[SIDE_BACK] > s->bytes_rx[SIDE_BACK]
|
|
||||||
){
|
){
|
||||||
ret = read_from_3091duplex(s);
|
ret = read_from_3091duplex(s);
|
||||||
if(ret){
|
if(ret){
|
||||||
DBG(5,"sane_read: 3091 returning %d\n",ret);
|
DBG(5,"sane_read: 3091 returning %d\n",ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
} /* end 3091 */
|
} /* end 3091 */
|
||||||
|
|
||||||
#ifdef SANE_FRAME_JPEG
|
#ifdef SANE_FRAME_JPEG
|
||||||
/* alternating jpeg duplex interlacing */
|
/* alternating jpeg duplex interlacing */
|
||||||
else if(s->source == SOURCE_ADF_DUPLEX
|
else if(s->source == SOURCE_ADF_DUPLEX
|
||||||
&& s->params.format == SANE_FRAME_JPEG
|
&& s->params.format == SANE_FRAME_JPEG
|
||||||
&& s->jpeg_interlace == JPEG_INTERLACE_ALT){
|
&& s->jpeg_interlace == JPEG_INTERLACE_ALT
|
||||||
|
|
||||||
/* read from front side if either side has remaining */
|
|
||||||
if ( s->bytes_tot[SIDE_FRONT] > s->bytes_rx[SIDE_FRONT]
|
|
||||||
|| s->bytes_tot[SIDE_BACK] > s->bytes_rx[SIDE_BACK]
|
|
||||||
){
|
){
|
||||||
ret = read_from_JPEGduplex(s);
|
ret = read_from_JPEGduplex(s);
|
||||||
if(ret){
|
if(ret){
|
||||||
DBG(5,"sane_read: jpeg duplex returning %d\n",ret);
|
DBG(5,"sane_read: jpeg duplex returning %d\n",ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
} /* end alt jpeg */
|
} /* end alt jpeg */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* alternating pnm duplex interlacing */
|
/* alternating pnm duplex interlacing */
|
||||||
else if(s->source == SOURCE_ADF_DUPLEX
|
else if(s->source == SOURCE_ADF_DUPLEX
|
||||||
&& s->params.format <= SANE_FRAME_RGB
|
&& s->params.format <= SANE_FRAME_RGB
|
||||||
&& s->duplex_interlace == DUPLEX_INTERLACE_ALT){
|
&& s->duplex_interlace == DUPLEX_INTERLACE_ALT
|
||||||
|
){
|
||||||
|
|
||||||
/* buffer front side */
|
/* buffer front side */
|
||||||
if(s->bytes_tot[SIDE_FRONT] > s->bytes_rx[SIDE_FRONT]){
|
|
||||||
ret = read_from_scanner(s, SIDE_FRONT);
|
ret = read_from_scanner(s, SIDE_FRONT);
|
||||||
if(ret){
|
if(ret){
|
||||||
DBG(5,"sane_read: front returning %d\n",ret);
|
DBG(5,"sane_read: front returning %d\n",ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* buffer back side */
|
/* buffer back side */
|
||||||
if(s->bytes_tot[SIDE_BACK] > s->bytes_rx[SIDE_BACK] ){
|
|
||||||
ret = read_from_scanner(s, SIDE_BACK);
|
ret = read_from_scanner(s, SIDE_BACK);
|
||||||
if(ret){
|
if(ret){
|
||||||
DBG(5,"sane_read: back returning %d\n",ret);
|
DBG(5,"sane_read: back returning %d\n",ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
} /* end alt pnm */
|
} /* end alt pnm */
|
||||||
|
|
||||||
/* simplex or non-alternating duplex */
|
/* simplex or non-alternating duplex */
|
||||||
else{
|
else{
|
||||||
|
|
||||||
if(s->bytes_tot[s->side] > s->bytes_rx[s->side] ){
|
|
||||||
ret = read_from_scanner(s, s->side);
|
ret = read_from_scanner(s, s->side);
|
||||||
if(ret){
|
if(ret){
|
||||||
DBG(5,"sane_read: side %d returning %d\n",s->side,ret);
|
DBG(5,"sane_read: side %d returning %d\n",s->side,ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
} /*end simplex*/
|
||||||
|
} /*end get more from scanner*/
|
||||||
}
|
|
||||||
|
|
||||||
/* copy a block from buffer to frontend */
|
/* copy a block from buffer to frontend */
|
||||||
ret = read_from_buffer(s,buf,max_len,len,s->side);
|
ret = read_from_buffer(s,buf,max_len,len,s->side);
|
||||||
|
@ -6832,6 +6906,16 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len
|
||||||
/* check if user cancelled during this read */
|
/* check if user cancelled during this read */
|
||||||
ret = check_for_cancel(s);
|
ret = check_for_cancel(s);
|
||||||
|
|
||||||
|
/* swap sides if user asked for low-mem mode, we are duplexing,
|
||||||
|
* and there is data waiting on the other side */
|
||||||
|
if(s->low_mem && s->source == SOURCE_ADF_DUPLEX
|
||||||
|
&& (s->bytes_rx[!s->side] > s->bytes_tx[!s->side]
|
||||||
|
|| (s->eof_rx[!s->side] && !s->eof_tx[!s->side])
|
||||||
|
)
|
||||||
|
){
|
||||||
|
s->side = !s->side;
|
||||||
|
}
|
||||||
|
|
||||||
/* unprotect this block from sane_cancel */
|
/* unprotect this block from sane_cancel */
|
||||||
s->reading = 0;
|
s->reading = 0;
|
||||||
|
|
||||||
|
@ -7008,9 +7092,11 @@ read_from_JPEGduplex(struct fujitsu *s)
|
||||||
|
|
||||||
/* clear what is already in the back */
|
/* clear what is already in the back */
|
||||||
s->bytes_rx[SIDE_BACK]=0;
|
s->bytes_rx[SIDE_BACK]=0;
|
||||||
|
s->lines_rx[SIDE_BACK]=0;
|
||||||
|
s->buff_rx[SIDE_BACK]=0;
|
||||||
|
|
||||||
/* and put the high-order width byte into front unchanged */
|
/* and put the high-order width byte into front unchanged */
|
||||||
s->buffers[SIDE_FRONT][ s->bytes_rx[SIDE_FRONT] ] = s->jpeg_x_byte;
|
s->buffers[SIDE_FRONT][s->buff_rx[SIDE_FRONT]++] = s->jpeg_x_byte;
|
||||||
s->bytes_rx[SIDE_FRONT]++;
|
s->bytes_rx[SIDE_FRONT]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7020,13 +7106,11 @@ read_from_JPEGduplex(struct fujitsu *s)
|
||||||
s->params.pixels_per_line,width);
|
s->params.pixels_per_line,width);
|
||||||
|
|
||||||
/* put the high-order width byte into front side, shifted down */
|
/* put the high-order width byte into front side, shifted down */
|
||||||
s->buffers[SIDE_FRONT][ s->bytes_rx[SIDE_FRONT] ]
|
s->buffers[SIDE_FRONT][s->buff_rx[SIDE_FRONT]++] = width >> 9;
|
||||||
= width >> 9;
|
|
||||||
s->bytes_rx[SIDE_FRONT]++;
|
s->bytes_rx[SIDE_FRONT]++;
|
||||||
|
|
||||||
/* put the high-order width byte into back side, shifted down */
|
/* put the high-order width byte into back side, shifted down */
|
||||||
s->buffers[SIDE_BACK][ s->bytes_rx[SIDE_BACK] ]
|
s->buffers[SIDE_BACK][s->buff_rx[SIDE_BACK]++] = width >> 9;
|
||||||
= width >> 9;
|
|
||||||
s->bytes_rx[SIDE_BACK]++;
|
s->bytes_rx[SIDE_BACK]++;
|
||||||
|
|
||||||
/* shift down low order byte */
|
/* shift down low order byte */
|
||||||
|
@ -7043,10 +7127,10 @@ read_from_JPEGduplex(struct fujitsu *s)
|
||||||
){
|
){
|
||||||
/* first byte after ff, send the ff first */
|
/* first byte after ff, send the ff first */
|
||||||
if(s->jpeg_ff_offset == 1){
|
if(s->jpeg_ff_offset == 1){
|
||||||
s->buffers[SIDE_FRONT][ s->bytes_rx[SIDE_FRONT] ] = 0xff;
|
s->buffers[SIDE_FRONT][s->buff_rx[SIDE_FRONT]++] = 0xff;
|
||||||
s->bytes_rx[SIDE_FRONT]++;
|
s->bytes_rx[SIDE_FRONT]++;
|
||||||
}
|
}
|
||||||
s->buffers[SIDE_FRONT][ s->bytes_rx[SIDE_FRONT] ] = in[i];
|
s->buffers[SIDE_FRONT][s->buff_rx[SIDE_FRONT]++] = in[i];
|
||||||
s->bytes_rx[SIDE_FRONT]++;
|
s->bytes_rx[SIDE_FRONT]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7061,10 +7145,10 @@ read_from_JPEGduplex(struct fujitsu *s)
|
||||||
){
|
){
|
||||||
/* first byte after ff, send the ff first */
|
/* first byte after ff, send the ff first */
|
||||||
if(s->jpeg_ff_offset == 1){
|
if(s->jpeg_ff_offset == 1){
|
||||||
s->buffers[SIDE_BACK][ s->bytes_rx[SIDE_BACK] ] = 0xff;
|
s->buffers[SIDE_BACK][s->buff_rx[SIDE_BACK]++] = 0xff;
|
||||||
s->bytes_rx[SIDE_BACK]++;
|
s->bytes_rx[SIDE_BACK]++;
|
||||||
}
|
}
|
||||||
s->buffers[SIDE_BACK][ s->bytes_rx[SIDE_BACK] ] = in[i];
|
s->buffers[SIDE_BACK][s->buff_rx[SIDE_BACK]++] = in[i];
|
||||||
s->bytes_rx[SIDE_BACK]++;
|
s->bytes_rx[SIDE_BACK]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7075,8 +7159,8 @@ read_from_JPEGduplex(struct fujitsu *s)
|
||||||
|
|
||||||
/* last byte of file, update totals, bail out */
|
/* last byte of file, update totals, bail out */
|
||||||
if(s->jpeg_stage == JPEG_STAGE_EOI){
|
if(s->jpeg_stage == JPEG_STAGE_EOI){
|
||||||
s->bytes_tot[SIDE_FRONT] = s->bytes_rx[SIDE_FRONT];
|
s->eof_rx[SIDE_FRONT] = 1;
|
||||||
s->bytes_tot[SIDE_BACK] = s->bytes_rx[SIDE_BACK];
|
s->eof_rx[SIDE_BACK] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7155,7 +7239,6 @@ read_from_3091duplex(struct fujitsu *s)
|
||||||
|
|
||||||
if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_EOF) {
|
if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_EOF) {
|
||||||
DBG(15, "read_from_3091duplex: got GOOD/EOF, returning GOOD\n");
|
DBG(15, "read_from_3091duplex: got GOOD/EOF, returning GOOD\n");
|
||||||
ret = SANE_STATUS_GOOD;
|
|
||||||
}
|
}
|
||||||
else if (ret == SANE_STATUS_DEVICE_BUSY) {
|
else if (ret == SANE_STATUS_DEVICE_BUSY) {
|
||||||
DBG(5, "read_from_3091duplex: got BUSY, returning GOOD\n");
|
DBG(5, "read_from_3091duplex: got BUSY, returning GOOD\n");
|
||||||
|
@ -7176,7 +7259,7 @@ read_from_3091duplex(struct fujitsu *s)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* end is back */
|
/* end is back */
|
||||||
else if(s->bytes_rx[SIDE_FRONT] == s->bytes_tot[SIDE_FRONT]){
|
else if(s->eof_rx[SIDE_FRONT]){
|
||||||
side=SIDE_BACK;
|
side=SIDE_BACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7198,6 +7281,12 @@ read_from_3091duplex(struct fujitsu *s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(ret == SANE_STATUS_EOF){
|
||||||
|
s->eof_rx[SIDE_FRONT] = 1;
|
||||||
|
s->eof_rx[SIDE_BACK] = 1;
|
||||||
|
ret = SANE_STATUS_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
free(in);
|
free(in);
|
||||||
|
|
||||||
DBG (10, "read_from_3091duplex: finish\n");
|
DBG (10, "read_from_3091duplex: finish\n");
|
||||||
|
@ -7240,8 +7329,14 @@ read_from_scanner(struct fujitsu *s, int side)
|
||||||
ret = SANE_STATUS_INVAL;
|
ret = SANE_STATUS_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG(15, "read_from_scanner: si:%d to:%d rx:%d re:%d bu:%d pa:%d\n", side,
|
DBG(15, "read_from_scanner: si:%d re:%d bs:%d by:%d\n",
|
||||||
s->bytes_tot[side], s->bytes_rx[side], remain, s->buffer_size, bytes);
|
side, remain, s->buffer_size, bytes);
|
||||||
|
|
||||||
|
DBG(15, "read_from_scanner: img to:%d rx:%d tx:%d\n",
|
||||||
|
s->bytes_tot[side], s->bytes_rx[side], s->bytes_tx[side]);
|
||||||
|
|
||||||
|
DBG(15, "read_from_scanner: buf to:%d rx:%d tx:%d\n",
|
||||||
|
s->buff_tot[side], s->buff_rx[side], s->buff_tx[side]);
|
||||||
|
|
||||||
if(ret){
|
if(ret){
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -7312,7 +7407,7 @@ read_from_scanner(struct fujitsu *s, int side)
|
||||||
free(in);
|
free(in);
|
||||||
|
|
||||||
if(ret == SANE_STATUS_EOF){
|
if(ret == SANE_STATUS_EOF){
|
||||||
s->bytes_tot[side] = s->bytes_rx[side];
|
s->eof_rx[side] = 1;
|
||||||
ret = SANE_STATUS_GOOD;
|
ret = SANE_STATUS_GOOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7325,7 +7420,7 @@ static SANE_Status
|
||||||
copy_3091(struct fujitsu *s, unsigned char * buf, int len, int side)
|
copy_3091(struct fujitsu *s, unsigned char * buf, int len, int side)
|
||||||
{
|
{
|
||||||
SANE_Status ret=SANE_STATUS_GOOD;
|
SANE_Status ret=SANE_STATUS_GOOD;
|
||||||
int i, dest, boff, goff;
|
int i, j, dest, boff, goff;
|
||||||
|
|
||||||
DBG (10, "copy_3091: start\n");
|
DBG (10, "copy_3091: start\n");
|
||||||
|
|
||||||
|
@ -7341,30 +7436,33 @@ copy_3091(struct fujitsu *s, unsigned char * buf, int len, int side)
|
||||||
boff = (s->color_raster_offset+s->blue_offset) * s->resolution_y/300;
|
boff = (s->color_raster_offset+s->blue_offset) * s->resolution_y/300;
|
||||||
|
|
||||||
/* loop thru all lines in read buffer */
|
/* loop thru all lines in read buffer */
|
||||||
for(i=0;i<len/s->params.bytes_per_line;i++){
|
for(i=0;i<len/s->params.bytes_per_line;i+=s->params.bytes_per_line){
|
||||||
|
|
||||||
/* red at start of line */
|
/* red at start of line */
|
||||||
dest = s->lines_rx[side] * s->params.bytes_per_line;
|
dest = s->lines_rx[side] * s->params.bytes_per_line;
|
||||||
|
|
||||||
if(dest >= 0 && dest < s->bytes_tot[side]){
|
if(dest >= 0 && dest < s->bytes_tot[side]){
|
||||||
memcpy(s->buffers[side] + dest,
|
for (j=0; j<s->params.pixels_per_line; j++){
|
||||||
buf + i*s->params.bytes_per_line,
|
s->buffers[side][dest+j*3] = buf[i+j];
|
||||||
s->params.pixels_per_line);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* green is in middle of line */
|
/* green is in middle of line */
|
||||||
dest = (s->lines_rx[side] - goff) * s->params.bytes_per_line + s->params.pixels_per_line;
|
dest = (s->lines_rx[side] - goff) * s->params.bytes_per_line;
|
||||||
|
|
||||||
if(dest >= 0 && dest < s->bytes_tot[side]){
|
if(dest >= 0 && dest < s->bytes_tot[side]){
|
||||||
memcpy(s->buffers[side] + dest,
|
for (j=0; j<s->params.pixels_per_line; j++){
|
||||||
buf + i*s->params.bytes_per_line + s->params.pixels_per_line,
|
s->buffers[side][dest+j*3+1] = buf[i+s->params.pixels_per_line+j];
|
||||||
s->params.pixels_per_line);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* blue is at end of line */
|
/* blue is at end of line */
|
||||||
dest = (s->lines_rx[side] - boff) * s->params.bytes_per_line + s->params.pixels_per_line*2;
|
dest = (s->lines_rx[side] - boff) * s->params.bytes_per_line;
|
||||||
|
|
||||||
if(dest >= 0 && dest < s->bytes_tot[side]){
|
if(dest >= 0 && dest < s->bytes_tot[side]){
|
||||||
memcpy(s->buffers[side] + dest,
|
for (j=0; j<s->params.pixels_per_line; j++){
|
||||||
buf + i*s->params.bytes_per_line + s->params.pixels_per_line*2,
|
s->buffers[side][dest+j*3+2] = buf[i+2*s->params.pixels_per_line+j];
|
||||||
s->params.pixels_per_line);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s->lines_rx[side]++;
|
s->lines_rx[side]++;
|
||||||
|
@ -7377,6 +7475,11 @@ copy_3091(struct fujitsu *s, unsigned char * buf, int len, int side)
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
s->bytes_rx[side] = i;
|
s->bytes_rx[side] = i;
|
||||||
|
s->buff_rx[side] = i;
|
||||||
|
|
||||||
|
if(s->bytes_rx[side] == s->bytes_tot[side]){
|
||||||
|
s->eof_rx[side] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
DBG (10, "copy_3091: finish\n");
|
DBG (10, "copy_3091: finish\n");
|
||||||
|
|
||||||
|
@ -7387,13 +7490,67 @@ static SANE_Status
|
||||||
copy_buffer(struct fujitsu *s, unsigned char * buf, int len, int side)
|
copy_buffer(struct fujitsu *s, unsigned char * buf, int len, int side)
|
||||||
{
|
{
|
||||||
SANE_Status ret=SANE_STATUS_GOOD;
|
SANE_Status ret=SANE_STATUS_GOOD;
|
||||||
|
int i, j;
|
||||||
|
int bwidth = s->params.bytes_per_line;
|
||||||
|
int pwidth = s->params.pixels_per_line;
|
||||||
|
|
||||||
DBG (10, "copy_buffer: start\n");
|
DBG (10, "copy_buffer: start\n");
|
||||||
|
|
||||||
memcpy(s->buffers[side]+s->bytes_rx[side],buf,len);
|
/* invert image if scanner needs it for this mode */
|
||||||
|
/* jpeg data does not use inverting */
|
||||||
|
if(s->params.format <= SANE_FRAME_RGB && s->reverse_by_mode[s->mode]){
|
||||||
|
for(i=0; i<len; i++){
|
||||||
|
buf[i] ^= 0xff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* scanners interlace colors in many different ways */
|
||||||
|
if(s->params.format == SANE_FRAME_RGB){
|
||||||
|
|
||||||
|
switch (s->color_interlace) {
|
||||||
|
|
||||||
|
/* scanner returns pixel data as bgrbgr... */
|
||||||
|
case COLOR_INTERLACE_BGR:
|
||||||
|
for(i=0; i<len; i+=bwidth){
|
||||||
|
for (j=0; j<pwidth; j++){
|
||||||
|
s->buffers[side][s->buff_rx[side]++] = buf[i+j*3+2];
|
||||||
|
s->buffers[side][s->buff_rx[side]++] = buf[i+j*3+1];
|
||||||
|
s->buffers[side][s->buff_rx[side]++] = buf[i+j*3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* one line has the following format: rrr...rrrggg...gggbbb...bbb */
|
||||||
|
case COLOR_INTERLACE_RRGGBB:
|
||||||
|
for(i=0; i<len; i+=bwidth){
|
||||||
|
for (j=0; j<pwidth; j++){
|
||||||
|
s->buffers[side][s->buff_rx[side]++] = buf[i+j];
|
||||||
|
s->buffers[side][s->buff_rx[side]++] = buf[i+pwidth+j];
|
||||||
|
s->buffers[side][s->buff_rx[side]++] = buf[i+2*pwidth+j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
memcpy(s->buffers[side]+s->buff_rx[side],buf,len);
|
||||||
|
s->buff_rx[side] += len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* jpeg/gray/ht/binary */
|
||||||
|
else{
|
||||||
|
memcpy(s->buffers[side]+s->buff_rx[side],buf,len);
|
||||||
|
s->buff_rx[side] += len;
|
||||||
|
}
|
||||||
|
|
||||||
s->bytes_rx[side] += len;
|
s->bytes_rx[side] += len;
|
||||||
s->lines_rx[side] += len/s->params.bytes_per_line;
|
s->lines_rx[side] += len/s->params.bytes_per_line;
|
||||||
|
|
||||||
|
if(s->bytes_rx[side] == s->bytes_tot[side]){
|
||||||
|
s->eof_rx[side] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
DBG (10, "copy_buffer: finish\n");
|
DBG (10, "copy_buffer: finish\n");
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -7404,8 +7561,8 @@ read_from_buffer(struct fujitsu *s, SANE_Byte * buf,
|
||||||
SANE_Int max_len, SANE_Int * len, int side)
|
SANE_Int max_len, 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->buff_rx[side] - s->buff_tx[side];
|
||||||
|
|
||||||
DBG (10, "read_from_buffer: start\n");
|
DBG (10, "read_from_buffer: start\n");
|
||||||
|
|
||||||
|
@ -7416,8 +7573,14 @@ read_from_buffer(struct fujitsu *s, SANE_Byte * buf,
|
||||||
|
|
||||||
*len = bytes;
|
*len = bytes;
|
||||||
|
|
||||||
DBG(15, "read_from_buffer: si:%d to:%d tx:%d re:%d bu:%d pa:%d\n", side,
|
DBG(15, "read_from_buffer: si:%d re:%d ml:%d by:%d\n",
|
||||||
s->bytes_tot[side], s->bytes_tx[side], remain, max_len, bytes);
|
side, remain, max_len, bytes);
|
||||||
|
|
||||||
|
DBG(15, "read_from_buffer: img to:%d rx:%d tx:%d\n",
|
||||||
|
s->bytes_tot[side], s->bytes_rx[side], s->bytes_tx[side]);
|
||||||
|
|
||||||
|
DBG(15, "read_from_buffer: buf to:%d rx:%d tx:%d\n",
|
||||||
|
s->buff_tot[side], s->buff_rx[side], s->buff_tx[side]);
|
||||||
|
|
||||||
/*FIXME this needs to timeout eventually */
|
/*FIXME this needs to timeout eventually */
|
||||||
if(!bytes){
|
if(!bytes){
|
||||||
|
@ -7425,68 +7588,18 @@ read_from_buffer(struct fujitsu *s, SANE_Byte * buf,
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SANE_FRAME_JPEG
|
memcpy(buf,s->buffers[side]+s->buff_tx[side],bytes);
|
||||||
/* jpeg data does not use typical interlacing or inverting, just copy */
|
s->buff_tx[side] += bytes;
|
||||||
if(s->params.format == SANE_FRAME_JPEG){
|
s->bytes_tx[side] += bytes;
|
||||||
memcpy(buf,s->buffers[side]+s->bytes_tx[side],bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* not using jpeg, colors maybe interlaced, pixels maybe inverted */
|
/*finished sending small buffer, reset it*/
|
||||||
else {
|
if(s->buff_tx[side] == s->buff_rx[side]
|
||||||
#endif
|
&& s->buff_tot[side] < s->bytes_tot[side]
|
||||||
|
){
|
||||||
/* scanners interlace colors in many different ways */
|
DBG (15, "read_from_buffer: reset\n");
|
||||||
/* use separate code to convert to regular rgb */
|
s->buff_rx[side] = 0;
|
||||||
if(s->mode == MODE_COLOR){
|
s->buff_tx[side] = 0;
|
||||||
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_3091:
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef SANE_FRAME_JPEG
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
s->bytes_tx[side] += *len;
|
|
||||||
|
|
||||||
DBG (10, "read_from_buffer: finish\n");
|
DBG (10, "read_from_buffer: finish\n");
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,8 @@ enum fujitsu_Option
|
||||||
OPT_DUPLEX_OFFSET,
|
OPT_DUPLEX_OFFSET,
|
||||||
OPT_GREEN_OFFSET,
|
OPT_GREEN_OFFSET,
|
||||||
OPT_BLUE_OFFSET,
|
OPT_BLUE_OFFSET,
|
||||||
|
OPT_LOW_MEM,
|
||||||
|
OPT_SIDE,
|
||||||
|
|
||||||
OPT_ENDORSER_GROUP,
|
OPT_ENDORSER_GROUP,
|
||||||
OPT_ENDORSER,
|
OPT_ENDORSER,
|
||||||
|
@ -464,7 +466,7 @@ struct fujitsu
|
||||||
int duplex_offset;
|
int duplex_offset;
|
||||||
int green_offset;
|
int green_offset;
|
||||||
int blue_offset;
|
int blue_offset;
|
||||||
int use_temp_file;
|
int low_mem;
|
||||||
|
|
||||||
/*endorser group*/
|
/*endorser group*/
|
||||||
int u_endorser;
|
int u_endorser;
|
||||||
|
@ -504,9 +506,16 @@ struct fujitsu
|
||||||
/* how far we have read */
|
/* how far we have read */
|
||||||
int bytes_rx[2];
|
int bytes_rx[2];
|
||||||
int lines_rx[2]; /*only used by 3091*/
|
int lines_rx[2]; /*only used by 3091*/
|
||||||
|
int eof_rx[2];
|
||||||
|
|
||||||
/* how far we have written */
|
/* how far we have written */
|
||||||
int bytes_tx[2];
|
int bytes_tx[2];
|
||||||
|
int eof_tx[2];
|
||||||
|
|
||||||
|
/*size of buffers (can be smaller than above*/
|
||||||
|
int buff_tot[2];
|
||||||
|
int buff_rx[2];
|
||||||
|
int buff_tx[2];
|
||||||
|
|
||||||
unsigned char * buffers[2];
|
unsigned char * buffers[2];
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue