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(),
|
||||
M3091 has not worked since sane 1.0.19, due to this.
|
||||
- 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
|
||||
|
||||
|
@ -3556,6 +3562,33 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
|
|||
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 ------------------------------------------------------ */
|
||||
if(option==OPT_ENDORSER_GROUP){
|
||||
opt->name = "endorser-options";
|
||||
|
@ -4433,6 +4466,14 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
|
|||
*val_p = s->blue_offset;
|
||||
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 */
|
||||
case OPT_ENDORSER:
|
||||
*val_p = s->u_endorser;
|
||||
|
@ -5026,6 +5067,10 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
|
|||
s->blue_offset = val_c;
|
||||
return SANE_STATUS_GOOD;
|
||||
|
||||
case OPT_LOW_MEM:
|
||||
s->low_mem = val_c;
|
||||
return SANE_STATUS_GOOD;
|
||||
|
||||
/* Endorser Group */
|
||||
case OPT_ENDORSER:
|
||||
s->u_endorser = val_c;
|
||||
|
@ -5868,11 +5913,18 @@ sane_start (SANE_Handle handle)
|
|||
s->reading=1;
|
||||
|
||||
/* 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?");
|
||||
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 */
|
||||
if(!s->started){
|
||||
|
||||
|
@ -5948,9 +6000,18 @@ sane_start (SANE_Handle handle)
|
|||
s->bytes_rx[1]=0;
|
||||
s->lines_rx[0]=0;
|
||||
s->lines_rx[1]=0;
|
||||
s->eof_rx[0]=0;
|
||||
s->eof_rx[1]=0;
|
||||
|
||||
s->bytes_tx[0]=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... */
|
||||
s->jpeg_stage = JPEG_STAGE_HEAD;
|
||||
|
@ -5961,17 +6022,32 @@ sane_start (SANE_Handle handle)
|
|||
/* store the number of front bytes */
|
||||
if ( s->source != SOURCE_ADF_BACK ){
|
||||
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{
|
||||
s->bytes_tot[SIDE_FRONT] = 0;
|
||||
s->buff_tot[SIDE_FRONT] = 0;
|
||||
}
|
||||
|
||||
/* store the number of back bytes */
|
||||
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->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{
|
||||
s->bytes_tot[SIDE_BACK] = 0;
|
||||
s->buff_tot[SIDE_BACK] = 0;
|
||||
}
|
||||
|
||||
/* first page of batch */
|
||||
|
@ -6205,8 +6281,9 @@ setup_buffers (struct fujitsu *s)
|
|||
s->buffers[side] = NULL;
|
||||
}
|
||||
|
||||
if(s->bytes_tot[side]){
|
||||
s->buffers[side] = calloc (1,s->bytes_tot[side]);
|
||||
if(s->buff_tot[side]){
|
||||
s->buffers[side] = calloc (1,s->buff_tot[side]);
|
||||
|
||||
if (!s->buffers[side]) {
|
||||
DBG (5, "setup_buffers: Error, no buffer %d.\n",side);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
|
@ -6739,92 +6816,89 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len
|
|||
|
||||
/* maybe cancelled? */
|
||||
if(!s->started){
|
||||
DBG (5, "sane_read: not started, call sane_start\n");
|
||||
return SANE_STATUS_CANCELLED;
|
||||
DBG (5, "sane_read: not started, call sane_start\n");
|
||||
return SANE_STATUS_CANCELLED;
|
||||
}
|
||||
|
||||
/* sane_start required between sides */
|
||||
if(s->bytes_tx[s->side] == s->bytes_tot[s->side]){
|
||||
DBG (15, "sane_read: returning eof\n");
|
||||
return SANE_STATUS_EOF;
|
||||
if(s->eof_rx[s->side] && s->bytes_tx[s->side] == s->bytes_rx[s->side]){
|
||||
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;
|
||||
}
|
||||
|
||||
/* protect this block from sane_cancel */
|
||||
s->reading = 1;
|
||||
|
||||
/* 3091/2 are on crack, get their own duplex reader function */
|
||||
if(s->source == SOURCE_ADF_DUPLEX
|
||||
&& s->duplex_interlace == DUPLEX_INTERLACE_3091){
|
||||
/* 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]){
|
||||
|
||||
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);
|
||||
if(ret){
|
||||
DBG(5,"sane_read: 3091 returning %d\n",ret);
|
||||
return ret;
|
||||
}
|
||||
/* 3091/2 are on crack, get their own duplex reader function */
|
||||
if(s->source == SOURCE_ADF_DUPLEX
|
||||
&& s->duplex_interlace == DUPLEX_INTERLACE_3091
|
||||
){
|
||||
ret = read_from_3091duplex(s);
|
||||
if(ret){
|
||||
DBG(5,"sane_read: 3091 returning %d\n",ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
} /* end 3091 */
|
||||
} /* end 3091 */
|
||||
|
||||
#ifdef SANE_FRAME_JPEG
|
||||
/* alternating jpeg duplex interlacing */
|
||||
else if(s->source == SOURCE_ADF_DUPLEX
|
||||
&& s->params.format == SANE_FRAME_JPEG
|
||||
&& 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);
|
||||
if(ret){
|
||||
DBG(5,"sane_read: jpeg duplex returning %d\n",ret);
|
||||
return ret;
|
||||
}
|
||||
/* alternating jpeg duplex interlacing */
|
||||
else if(s->source == SOURCE_ADF_DUPLEX
|
||||
&& s->params.format == SANE_FRAME_JPEG
|
||||
&& s->jpeg_interlace == JPEG_INTERLACE_ALT
|
||||
){
|
||||
ret = read_from_JPEGduplex(s);
|
||||
if(ret){
|
||||
DBG(5,"sane_read: jpeg duplex returning %d\n",ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
} /* end alt jpeg */
|
||||
} /* end alt jpeg */
|
||||
#endif
|
||||
|
||||
/* alternating pnm duplex interlacing */
|
||||
else if(s->source == SOURCE_ADF_DUPLEX
|
||||
&& s->params.format <= SANE_FRAME_RGB
|
||||
&& s->duplex_interlace == DUPLEX_INTERLACE_ALT){
|
||||
/* alternating pnm duplex interlacing */
|
||||
else if(s->source == SOURCE_ADF_DUPLEX
|
||||
&& s->params.format <= SANE_FRAME_RGB
|
||||
&& s->duplex_interlace == DUPLEX_INTERLACE_ALT
|
||||
){
|
||||
|
||||
/* 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
ret = read_from_scanner(s, SIDE_BACK);
|
||||
if(ret){
|
||||
DBG(5,"sane_read: back returning %d\n",ret);
|
||||
return ret;
|
||||
}
|
||||
} /* end alt pnm */
|
||||
|
||||
} /* end alt pnm */
|
||||
|
||||
/* simplex or non-alternating duplex */
|
||||
else{
|
||||
|
||||
if(s->bytes_tot[s->side] > s->bytes_rx[s->side] ){
|
||||
/* simplex or non-alternating duplex */
|
||||
else{
|
||||
ret = read_from_scanner(s, s->side);
|
||||
if(ret){
|
||||
DBG(5,"sane_read: side %d returning %d\n",s->side,ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} /*end simplex*/
|
||||
} /*end get more from scanner*/
|
||||
|
||||
/* copy a block from buffer to frontend */
|
||||
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 */
|
||||
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 */
|
||||
s->reading = 0;
|
||||
|
||||
|
@ -7008,9 +7092,11 @@ read_from_JPEGduplex(struct fujitsu *s)
|
|||
|
||||
/* clear what is already in the back */
|
||||
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 */
|
||||
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]++;
|
||||
}
|
||||
|
||||
|
@ -7020,13 +7106,11 @@ read_from_JPEGduplex(struct fujitsu *s)
|
|||
s->params.pixels_per_line,width);
|
||||
|
||||
/* put the high-order width byte into front side, shifted down */
|
||||
s->buffers[SIDE_FRONT][ s->bytes_rx[SIDE_FRONT] ]
|
||||
= width >> 9;
|
||||
s->buffers[SIDE_FRONT][s->buff_rx[SIDE_FRONT]++] = width >> 9;
|
||||
s->bytes_rx[SIDE_FRONT]++;
|
||||
|
||||
/* put the high-order width byte into back side, shifted down */
|
||||
s->buffers[SIDE_BACK][ s->bytes_rx[SIDE_BACK] ]
|
||||
= width >> 9;
|
||||
s->buffers[SIDE_BACK][s->buff_rx[SIDE_BACK]++] = width >> 9;
|
||||
s->bytes_rx[SIDE_BACK]++;
|
||||
|
||||
/* shift down low order byte */
|
||||
|
@ -7043,10 +7127,10 @@ read_from_JPEGduplex(struct fujitsu *s)
|
|||
){
|
||||
/* first byte after ff, send the ff first */
|
||||
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->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]++;
|
||||
}
|
||||
|
||||
|
@ -7061,10 +7145,10 @@ read_from_JPEGduplex(struct fujitsu *s)
|
|||
){
|
||||
/* first byte after ff, send the ff first */
|
||||
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->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]++;
|
||||
}
|
||||
|
||||
|
@ -7075,8 +7159,8 @@ read_from_JPEGduplex(struct fujitsu *s)
|
|||
|
||||
/* last byte of file, update totals, bail out */
|
||||
if(s->jpeg_stage == JPEG_STAGE_EOI){
|
||||
s->bytes_tot[SIDE_FRONT] = s->bytes_rx[SIDE_FRONT];
|
||||
s->bytes_tot[SIDE_BACK] = s->bytes_rx[SIDE_BACK];
|
||||
s->eof_rx[SIDE_FRONT] = 1;
|
||||
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) {
|
||||
DBG(15, "read_from_3091duplex: got GOOD/EOF, returning GOOD\n");
|
||||
ret = SANE_STATUS_GOOD;
|
||||
}
|
||||
else if (ret == SANE_STATUS_DEVICE_BUSY) {
|
||||
DBG(5, "read_from_3091duplex: got BUSY, returning GOOD\n");
|
||||
|
@ -7176,7 +7259,7 @@ read_from_3091duplex(struct fujitsu *s)
|
|||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
DBG (10, "read_from_3091duplex: finish\n");
|
||||
|
@ -7240,8 +7329,14 @@ read_from_scanner(struct fujitsu *s, int side)
|
|||
ret = SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
DBG(15, "read_from_scanner: si:%d to:%d rx:%d re:%d bu:%d pa:%d\n", side,
|
||||
s->bytes_tot[side], s->bytes_rx[side], remain, s->buffer_size, bytes);
|
||||
DBG(15, "read_from_scanner: si:%d re:%d bs:%d by:%d\n",
|
||||
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){
|
||||
return ret;
|
||||
|
@ -7312,7 +7407,7 @@ read_from_scanner(struct fujitsu *s, int side)
|
|||
free(in);
|
||||
|
||||
if(ret == SANE_STATUS_EOF){
|
||||
s->bytes_tot[side] = s->bytes_rx[side];
|
||||
s->eof_rx[side] = 1;
|
||||
ret = SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
@ -7325,7 +7420,7 @@ static SANE_Status
|
|||
copy_3091(struct fujitsu *s, unsigned char * buf, int len, int side)
|
||||
{
|
||||
SANE_Status ret=SANE_STATUS_GOOD;
|
||||
int i, dest, boff, goff;
|
||||
int i, j, dest, boff, goff;
|
||||
|
||||
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;
|
||||
|
||||
/* 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 */
|
||||
dest = s->lines_rx[side] * s->params.bytes_per_line;
|
||||
|
||||
if(dest >= 0 && dest < s->bytes_tot[side]){
|
||||
memcpy(s->buffers[side] + dest,
|
||||
buf + i*s->params.bytes_per_line,
|
||||
s->params.pixels_per_line);
|
||||
for (j=0; j<s->params.pixels_per_line; j++){
|
||||
s->buffers[side][dest+j*3] = buf[i+j];
|
||||
}
|
||||
}
|
||||
|
||||
/* 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]){
|
||||
memcpy(s->buffers[side] + dest,
|
||||
buf + i*s->params.bytes_per_line + s->params.pixels_per_line,
|
||||
s->params.pixels_per_line);
|
||||
for (j=0; j<s->params.pixels_per_line; j++){
|
||||
s->buffers[side][dest+j*3+1] = buf[i+s->params.pixels_per_line+j];
|
||||
}
|
||||
}
|
||||
|
||||
/* 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]){
|
||||
memcpy(s->buffers[side] + dest,
|
||||
buf + i*s->params.bytes_per_line + s->params.pixels_per_line*2,
|
||||
s->params.pixels_per_line);
|
||||
for (j=0; j<s->params.pixels_per_line; j++){
|
||||
s->buffers[side][dest+j*3+2] = buf[i+2*s->params.pixels_per_line+j];
|
||||
}
|
||||
}
|
||||
|
||||
s->lines_rx[side]++;
|
||||
|
@ -7377,6 +7475,11 @@ copy_3091(struct fujitsu *s, unsigned char * buf, int len, int side)
|
|||
i = 0;
|
||||
}
|
||||
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");
|
||||
|
||||
|
@ -7387,13 +7490,67 @@ static SANE_Status
|
|||
copy_buffer(struct fujitsu *s, unsigned char * buf, int len, int side)
|
||||
{
|
||||
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");
|
||||
|
||||
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->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");
|
||||
|
||||
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_Status ret=SANE_STATUS_GOOD;
|
||||
int bytes = max_len, i=0;
|
||||
int remain = s->bytes_rx[side] - s->bytes_tx[side];
|
||||
int bytes = max_len;
|
||||
int remain = s->buff_rx[side] - s->buff_tx[side];
|
||||
|
||||
DBG (10, "read_from_buffer: start\n");
|
||||
|
||||
|
@ -7416,8 +7573,14 @@ read_from_buffer(struct fujitsu *s, SANE_Byte * buf,
|
|||
|
||||
*len = bytes;
|
||||
|
||||
DBG(15, "read_from_buffer: si:%d to:%d tx:%d re:%d bu:%d pa:%d\n", side,
|
||||
s->bytes_tot[side], s->bytes_tx[side], remain, max_len, bytes);
|
||||
DBG(15, "read_from_buffer: si:%d re:%d ml:%d by:%d\n",
|
||||
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 */
|
||||
if(!bytes){
|
||||
|
@ -7425,69 +7588,19 @@ read_from_buffer(struct fujitsu *s, SANE_Byte * buf,
|
|||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
#ifdef SANE_FRAME_JPEG
|
||||
/* jpeg data does not use typical interlacing or inverting, just copy */
|
||||
if(s->params.format == SANE_FRAME_JPEG){
|
||||
memcpy(buf,s->buffers[side]+s->bytes_tx[side],bytes);
|
||||
}
|
||||
|
||||
/* not using jpeg, colors maybe interlaced, pixels maybe inverted */
|
||||
else {
|
||||
#endif
|
||||
memcpy(buf,s->buffers[side]+s->buff_tx[side],bytes);
|
||||
s->buff_tx[side] += bytes;
|
||||
s->bytes_tx[side] += bytes;
|
||||
|
||||
/* 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_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
|
||||
/*finished sending small buffer, reset it*/
|
||||
if(s->buff_tx[side] == s->buff_rx[side]
|
||||
&& s->buff_tot[side] < s->bytes_tot[side]
|
||||
){
|
||||
DBG (15, "read_from_buffer: reset\n");
|
||||
s->buff_rx[side] = 0;
|
||||
s->buff_tx[side] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
s->bytes_tx[side] += *len;
|
||||
|
||||
|
||||
DBG (10, "read_from_buffer: finish\n");
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -78,6 +78,8 @@ enum fujitsu_Option
|
|||
OPT_DUPLEX_OFFSET,
|
||||
OPT_GREEN_OFFSET,
|
||||
OPT_BLUE_OFFSET,
|
||||
OPT_LOW_MEM,
|
||||
OPT_SIDE,
|
||||
|
||||
OPT_ENDORSER_GROUP,
|
||||
OPT_ENDORSER,
|
||||
|
@ -464,7 +466,7 @@ struct fujitsu
|
|||
int duplex_offset;
|
||||
int green_offset;
|
||||
int blue_offset;
|
||||
int use_temp_file;
|
||||
int low_mem;
|
||||
|
||||
/*endorser group*/
|
||||
int u_endorser;
|
||||
|
@ -504,9 +506,16 @@ struct fujitsu
|
|||
/* how far we have read */
|
||||
int bytes_rx[2];
|
||||
int lines_rx[2]; /*only used by 3091*/
|
||||
int eof_rx[2];
|
||||
|
||||
/* how far we have written */
|
||||
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];
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue