kopia lustrzana https://gitlab.com/sane-project/backends
fujitsu backend v116
add swskip option add sanei_magic_isBlank2merge-requests/1/head
rodzic
120e303732
commit
9fc683d883
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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....
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Ładowanie…
Reference in New Issue