fujitsu backend v116

add swskip option
add sanei_magic_isBlank2
merge-requests/1/head
m. allan noah 2013-04-03 21:52:21 -04:00
rodzic 120e303732
commit 9fc683d883
6 zmienionych plików z 193 dodań i 6 usunięć

Wyświetl plik

@ -532,6 +532,7 @@
- generate grayscale and binary in software if required (iX500)
v116 2013-03-23, MAN
- call set_mode() in init_interlace
- add swskip option
SANE FLOW DIAGRAM
@ -3295,7 +3296,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
if(option==OPT_VARIANCE){
opt->name = "variance";
opt->title = "Variance";
opt->desc = "Set SDTC variance rate (sensitivity), 0=127";
opt->desc = "Set SDTC variance rate (sensitivity), 0 equals 127";
opt->type = SANE_TYPE_INT;
opt->unit = SANE_UNIT_NONE;
@ -3839,6 +3840,24 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
opt->cap = SANE_CAP_INACTIVE;
}
/* Software blank page skip */
if(option==OPT_SWSKIP){
opt->name = "swskip";
opt->title = SANE_I18N ("Software blank skip percentage");
opt->desc = SANE_I18N("Request driver to discard pages with low percentage of dark pixels");
opt->type = SANE_TYPE_FIXED;
opt->unit = SANE_UNIT_PERCENT;
opt->constraint_type = SANE_CONSTRAINT_RANGE;
opt->constraint.range = &s->swskip_range;
s->swskip_range.quant=1;
s->swskip_range.min=SANE_FIX(0);
s->swskip_range.max=SANE_FIX(100);
opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
}
/* "Endorser" group ------------------------------------------------------ */
if(option==OPT_ENDORSER_GROUP){
opt->name = "endorser-options";
@ -4786,6 +4805,10 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
*val_p = s->swcrop;
return SANE_STATUS_GOOD;
case OPT_SWSKIP:
*val_p = SANE_FIX(s->swskip);
return SANE_STATUS_GOOD;
/* Endorser Group */
case OPT_ENDORSER:
*val_p = s->u_endorser;
@ -5401,6 +5424,10 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
s->swcrop = val_c;
return SANE_STATUS_GOOD;
case OPT_SWSKIP:
s->swskip = SANE_UNFIX(val_c);
return SANE_STATUS_GOOD;
/* Endorser Group */
case OPT_ENDORSER:
s->u_endorser = val_c;
@ -6855,6 +6882,17 @@ sane_start (SANE_Handle handle)
if(s->swdespeck){
buffer_despeck(s,s->side);
}
if(s->swskip){
/* Skipping means throwing out this image.
* Pretend the user read the whole thing
* and call sane_start again.
* This assumes we are running in batch mode. */
if(buffer_isblank(s,s->side)){
s->bytes_tx[s->side] = s->bytes_rx[s->side];
s->eof_tx[s->side] = 1;
return sane_start(handle);
}
}
}
@ -9341,7 +9379,7 @@ must_fully_buffer(struct fujitsu *s)
}
if(
(s->swdeskew || s->swdespeck || s->swcrop)
(s->swdeskew || s->swdespeck || s->swcrop || s->swskip)
#ifdef SANE_FRAME_JPEG
&& s->s_params.format != SANE_FRAME_JPEG
#endif
@ -9659,3 +9697,27 @@ buffer_despeck(struct fujitsu *s, int side)
return ret;
}
/* Look if image has too few dark pixels.*/
static int
buffer_isblank(struct fujitsu *s, int side)
{
SANE_Status ret = SANE_STATUS_GOOD;
int status = 0;
DBG (10, "buffer_isblank: start\n");
ret = sanei_magic_isBlank2(&s->s_params, s->buffers[side],
s->resolution_x, s->resolution_y, s->swskip);
if(ret == SANE_STATUS_NO_DOCS){
DBG (5, "buffer_isblank: blank!\n");
status = 1;
}
else if(ret){
DBG (5, "buffer_isblank: error %d\n",ret);
}
DBG (10, "buffer_isblank: finished\n");
return status;
}

Wyświetl plik

@ -88,6 +88,7 @@ enum fujitsu_Option
OPT_SWDESKEW,
OPT_SWDESPECK,
OPT_SWCROP,
OPT_SWSKIP,
OPT_ENDORSER_GROUP,
OPT_ENDORSER,
@ -392,6 +393,7 @@ struct fujitsu
SANE_Range green_offset_range;
SANE_Range blue_offset_range;
SANE_Range swdespeck_range;
SANE_Range swskip_range;
/*endorser group*/
SANE_Range endorser_bits_range;
@ -423,7 +425,7 @@ struct fujitsu
/*enhancement group*/
int brightness;
int contrast;
int gamma;
double gamma;
int threshold;
/* ipc */
@ -480,6 +482,7 @@ struct fujitsu
int swdeskew;
int swdespeck;
int swcrop;
double swskip;
/*endorser group*/
int u_endorser;
@ -824,6 +827,7 @@ static SANE_Status get_hardware_status (struct fujitsu *s, SANE_Int option);
static SANE_Status buffer_deskew(struct fujitsu *s, int side);
static SANE_Status buffer_crop(struct fujitsu *s, int side);
static SANE_Status buffer_despeck(struct fujitsu *s, int side);
static int buffer_isblank(struct fujitsu *s, int side);
static void hexdump (int level, char *comment, unsigned char *p, int l);

Wyświetl plik

@ -12,7 +12,7 @@
:backend "fujitsu" ; name of backend
:url "http://www.thebility.com/fujitsu/"
:version "115" ; version of backend
:version "116" ; version of backend
:manpage "sane-fujitsu" ; name of manpage (if it exists)
:comment "Backend updated for SANE release 1.0.23, see sane-fujitsu manpage"
:devicetype :scanner ; start of a list of devices....

Wyświetl plik

@ -178,8 +178,6 @@ an override is added to the backend.
.PP
CCITT Fax compression used by older scanners is not supported.
.PP
Hardware automatic paper width detection (aka auto-cropping) is not supported.
.PP
JPEG output is supported by the backend, but not by the SANE protocol, so is
disabled in this release. It can be enabled if you rebuild from source.

Wyświetl plik

@ -169,6 +169,24 @@ extern SANE_Status
sanei_magic_isBlank(SANE_Parameters * params, SANE_Byte * buffer,
double thresh);
/** Determine if image is blank, enhanced version
*
* @param params describes image
* @param buffer contains image data
* @param dpiX horizontal resolution
* @param dpiY vertical resolution
* @param thresh maximum % density for blankness (0-100)
*
* @return
* - SANE_STATUS_GOOD - page is not blank
* - SANE_STATUS_NO_DOCS - page is blank
* - SANE_STATUS_NO_MEM - not enough memory
* - SANE_STATUS_INVAL - invalid image parameters
*/
extern SANE_Status
sanei_magic_isBlank2(SANE_Parameters * params, SANE_Byte * buffer,
int dpiX, int dpiY, double thresh);
/** Determine coarse image rotation (90 degree increments)
*
* @param params describes image

Wyświetl plik

@ -781,6 +781,111 @@ sanei_magic_isBlank (SANE_Parameters * params, SANE_Byte * buffer,
return ret;
}
/* Divide the image into 1/2 inch squares, skipping a 1/4 inch
* margin on all sides. If all squares are under the user's density,
* signal our caller to skip the image entirely, by returning
* SANE_STATUS_NO_DOCS */
SANE_Status
sanei_magic_isBlank2 (SANE_Parameters * params, SANE_Byte * buffer,
int dpiX, int dpiY, double thresh)
{
int xb,yb,x,y;
/* .25 inch, rounded down to 8 pixel */
int xquarter = dpiX/4/8*8;
int yquarter = dpiY/4/8*8;
int xhalf = xquarter*2;
int yhalf = yquarter*2;
int blockpix = xhalf*yhalf;
int xblocks = (params->pixels_per_line-xhalf)/xhalf;
int yblocks = (params->lines-yhalf)/yhalf;
/*convert thresh from percent (0-100) to 0-1 range*/
thresh /= 100;
DBG (10, "sanei_magic_isBlank2: start %d %d %f %d\n",xhalf,yhalf,thresh,blockpix);
if(params->depth == 8 &&
(params->format == SANE_FRAME_RGB || params->format == SANE_FRAME_GRAY)
){
int Bpp = params->format == SANE_FRAME_RGB ? 3 : 1;
for(yb=0; yb<yblocks; yb++){
for(xb=0; xb<xblocks; xb++){
/*count dark pix in this block*/
double blocksum = 0;
for(y=0; y<yhalf; y++){
/* skip the top and left 1/4 inch */
int offset = (yquarter + yb*yhalf + y) * params->bytes_per_line
+ (xquarter + xb*xhalf) * Bpp;
SANE_Byte * ptr = buffer + offset;
/*count darkness of pix in this row*/
int rowsum = 0;
for(x=0; x<xhalf*Bpp; x++){
rowsum += 255 - ptr[x];
}
blocksum += (double)rowsum/(xhalf*Bpp)/255;
}
/* block was darker than thresh, keep image */
if(blocksum/yhalf > thresh){
DBG (15, "sanei_magic_isBlank2: not blank %f %d %d\n", blocksum/yhalf, yb, xb);
return SANE_STATUS_GOOD;
}
DBG (20, "sanei_magic_isBlank2: block blank %f %d %d\n", blocksum/yhalf, yb, xb);
}
}
}
else if(params->format == SANE_FRAME_GRAY && params->depth == 1){
for(yb=0; yb<yblocks; yb++){
for(xb=0; xb<xblocks; xb++){
/*count dark pix in this block*/
double blocksum = 0;
for(y=0; y<yhalf; y++){
/* skip the top and left 1/4 inch */
int offset = (yquarter + yb*yhalf + y) * params->bytes_per_line
+ (xquarter + xb*xhalf) / 8;
SANE_Byte * ptr = buffer + offset;
/*count darkness of pix in this row*/
int rowsum = 0;
for(x=0; x<xhalf; x++){
rowsum += ptr[x/8] >> (7-(x%8)) & 1;
}
blocksum += (double)rowsum/xhalf;
}
/* block was darker than thresh, keep image */
if(blocksum/yhalf > thresh){
DBG (15, "sanei_magic_isBlank2: not blank %f %d %d\n", blocksum/yhalf, yb, xb);
return SANE_STATUS_GOOD;
}
DBG (20, "sanei_magic_isBlank2: block blank %f %d %d\n", blocksum/yhalf, yb, xb);
}
}
}
else{
DBG (5, "sanei_magic_isBlank2: unsupported format/depth\n");
return SANE_STATUS_INVAL;
}
DBG (10, "sanei_magic_isBlank2: returning blank\n");
return SANE_STATUS_NO_DOCS;
}
SANE_Status
sanei_magic_findTurn(SANE_Parameters * params, SANE_Byte * buffer,
int dpiX, int dpiY, int * angle)