From f56fc87ff9fe6f94c51f6c9a99f5a554f686836c Mon Sep 17 00:00:00 2001 From: "m. allan noah" Date: Mon, 25 May 2009 22:04:57 -0400 Subject: [PATCH] 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 buffering --- backend/fujitsu.c | 429 +++++++++++++++++++++++++++++----------------- backend/fujitsu.h | 11 +- 2 files changed, 281 insertions(+), 159 deletions(-) diff --git a/backend/fujitsu.c b/backend/fujitsu.c index 0227ca3b6..4a49587e1 100644 --- a/backend/fujitsu.c +++ b/backend/fujitsu.c @@ -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;iparams.bytes_per_line;i++){ + for(i=0;iparams.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; jparams.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; jparams.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; jparams.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; iparams.format == SANE_FRAME_RGB){ + + switch (s->color_interlace) { + + /* scanner returns pixel data as bgrbgr... */ + case COLOR_INTERLACE_BGR: + for(i=0; ibuffers[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; ibuffers[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; diff --git a/backend/fujitsu.h b/backend/fujitsu.h index fdc595047..6bff688ac 100644 --- a/backend/fujitsu.h +++ b/backend/fujitsu.h @@ -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];