kopia lustrzana https://gitlab.com/sane-project/backends
Merge branch 'genesys'
commit
00574ba699
|
@ -485,7 +485,7 @@ libgenesys_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=genesys
|
|||
nodist_libsane_genesys_la_SOURCES = genesys-s.c
|
||||
libsane_genesys_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=genesys
|
||||
libsane_genesys_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_genesys_la_LIBADD = $(COMMON_LIBS) libgenesys.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS)
|
||||
libsane_genesys_la_LIBADD = $(COMMON_LIBS) libgenesys.la ../sanei/sanei_magic.lo ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS)
|
||||
EXTRA_DIST += genesys.conf.in
|
||||
# TODO: Why are this distributed but not compiled?
|
||||
EXTRA_DIST += genesys_conv.c genesys_conv_hlp.c genesys_devices.c
|
||||
|
|
|
@ -574,7 +574,7 @@ libsane_fujitsu_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
|
|||
libsane_genesys_la_DEPENDENCIES = $(COMMON_LIBS) libgenesys.la \
|
||||
../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \
|
||||
../sanei/sanei_config.lo sane_strstatus.lo \
|
||||
../sanei/sanei_usb.lo $(am__DEPENDENCIES_1) \
|
||||
../sanei/sanei_usb.lo ../sanei/sanei_magic.lo $(am__DEPENDENCIES_1) \
|
||||
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
|
||||
nodist_libsane_genesys_la_OBJECTS = libsane_genesys_la-genesys-s.lo
|
||||
libsane_genesys_la_OBJECTS = $(nodist_libsane_genesys_la_OBJECTS)
|
||||
|
@ -1998,7 +1998,7 @@ libgenesys_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=genesys
|
|||
nodist_libsane_genesys_la_SOURCES = genesys-s.c
|
||||
libsane_genesys_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=genesys
|
||||
libsane_genesys_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_genesys_la_LIBADD = $(COMMON_LIBS) libgenesys.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS)
|
||||
libsane_genesys_la_LIBADD = $(COMMON_LIBS) libgenesys.la ../sanei/sanei_magic.lo ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS)
|
||||
libgphoto2_i_la_SOURCES = gphoto2.c gphoto2.h
|
||||
libgphoto2_i_la_CPPFLAGS = $(AM_CPPFLAGS) @GPHOTO2_CPPFLAGS@ -DBACKEND_NAME=gphoto2
|
||||
nodist_libsane_gphoto2_la_SOURCES = gphoto2-s.c
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
#include "../include/sane/sanei_usb.h"
|
||||
#include "../include/sane/sanei_config.h"
|
||||
#include "../include/_stdint.h"
|
||||
#include "../include/sane/sanei_magic.h"
|
||||
|
||||
#include "genesys.h"
|
||||
#include "genesys_devices.c"
|
||||
|
@ -117,6 +118,12 @@ static SANE_String_Const source_list[] = {
|
|||
0
|
||||
};
|
||||
|
||||
static SANE_Range swdespeck_range = {
|
||||
1,
|
||||
9,
|
||||
1
|
||||
};
|
||||
|
||||
static SANE_Range time_range = {
|
||||
0, /* minimum */
|
||||
60, /* maximum */
|
||||
|
@ -611,6 +618,7 @@ sanei_genesys_get_status (Genesys_Device * dev, uint8_t * status)
|
|||
return sanei_genesys_read_register (dev, 0x41, status);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* returns pixels per line from register set */
|
||||
/*candidate for moving into chip specific files?*/
|
||||
static int
|
||||
|
@ -643,6 +651,7 @@ genesys_dpiset (Genesys_Register_Set * reg)
|
|||
|
||||
return dpiset;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** read the number of valid words in scanner's RAM
|
||||
* ie registers 42-43-44
|
||||
|
@ -3108,57 +3117,63 @@ compute_gl843_coefficients (Genesys_Device * dev,
|
|||
unsigned int coeff,
|
||||
unsigned int target)
|
||||
{
|
||||
uint16_t *buffer=(uint16_t *)*shading_data,*darkptr,*whiteptr;
|
||||
uint16_t *buffer = (uint16_t *) * shading_data, *darkptr, *whiteptr;
|
||||
int size;
|
||||
int i, count;
|
||||
unsigned int i, count;
|
||||
uint16_t val;
|
||||
|
||||
darkptr=(uint16_t *)dev->dark_average_data;
|
||||
whiteptr=(uint16_t *)dev->white_average_data;
|
||||
darkptr = (uint16_t *) dev->dark_average_data;
|
||||
whiteptr = (uint16_t *) dev->white_average_data;
|
||||
|
||||
size=pixels*2*3*256/252*2+512;
|
||||
free(buffer);
|
||||
buffer= (unsigned short *)malloc(size);
|
||||
if (buffer == NULL)
|
||||
return 0;
|
||||
size = pixels * 2 * 3 * 256 / 252 * 2 + 512;
|
||||
free (buffer);
|
||||
buffer = (unsigned short *) malloc (size);
|
||||
if (buffer == NULL)
|
||||
return 0;
|
||||
|
||||
/* offset */
|
||||
buffer=buffer+12;
|
||||
count=12;
|
||||
for(i=0; i<pixels; i++)
|
||||
{
|
||||
/* red */
|
||||
*buffer = darkptr[3*i];
|
||||
buffer++;
|
||||
count++;
|
||||
val=compute_coefficient(coeff,target,whiteptr[3*i]-darkptr[3*i]);
|
||||
*buffer = val;
|
||||
buffer++;
|
||||
count++;
|
||||
/* offset */
|
||||
buffer = buffer + 12;
|
||||
count = 12;
|
||||
for (i = 0; i < pixels; i++)
|
||||
{
|
||||
/* red */
|
||||
*buffer = darkptr[3 * i];
|
||||
buffer++;
|
||||
count++;
|
||||
val =
|
||||
compute_coefficient (coeff, target, whiteptr[3 * i] - darkptr[3 * i]);
|
||||
*buffer = val;
|
||||
buffer++;
|
||||
count++;
|
||||
|
||||
/* green */
|
||||
*buffer = darkptr[3*i+1];
|
||||
buffer++;
|
||||
count++;
|
||||
val=compute_coefficient(coeff,target,whiteptr[3*i+1]-darkptr[3*i+1]);
|
||||
*buffer = val;
|
||||
buffer++;
|
||||
count++;
|
||||
/* green */
|
||||
*buffer = darkptr[3 * i + 1];
|
||||
buffer++;
|
||||
count++;
|
||||
val =
|
||||
compute_coefficient (coeff, target,
|
||||
whiteptr[3 * i + 1] - darkptr[3 * i + 1]);
|
||||
*buffer = val;
|
||||
buffer++;
|
||||
count++;
|
||||
|
||||
/* blue */
|
||||
*buffer = darkptr[3*i+2];
|
||||
buffer++;
|
||||
count++;
|
||||
val=compute_coefficient(coeff,target,whiteptr[3*i+2]-darkptr[3*i+2]);
|
||||
*buffer = val;
|
||||
buffer++;
|
||||
count++;
|
||||
/* blue */
|
||||
*buffer = darkptr[3 * i + 2];
|
||||
buffer++;
|
||||
count++;
|
||||
val =
|
||||
compute_coefficient (coeff, target,
|
||||
whiteptr[3 * i + 2] - darkptr[3 * i + 2]);
|
||||
*buffer = val;
|
||||
buffer++;
|
||||
count++;
|
||||
|
||||
if ((count % 256) == 252) {
|
||||
buffer += 4;
|
||||
count += 4;
|
||||
}
|
||||
if ((count % 256) == 252)
|
||||
{
|
||||
buffer += 4;
|
||||
count += 4;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
@ -3329,13 +3344,11 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
|
|||
{
|
||||
SANE_Status status;
|
||||
uint16_t pixels_per_line;
|
||||
uint16_t *fixup,*shading;
|
||||
uint8_t *shading_data; /**> contains 16bit words in little endian */
|
||||
uint8_t channels;
|
||||
unsigned int x, j, src, dst;
|
||||
int o;
|
||||
unsigned int length; /**> number of shading calibration data words */
|
||||
unsigned int i, res, factor;
|
||||
unsigned int x, j, i, res, factor;
|
||||
int cmat[3]; /**> matrix of color channels */
|
||||
unsigned int coeff, target_code, val, avgpixels, dk, words_per_color = 0;
|
||||
unsigned int target_dark, target_bright, br;
|
||||
|
@ -5353,10 +5366,10 @@ genesys_read_ordered_data (Genesys_Device * dev, SANE_Byte * destination,
|
|||
#endif
|
||||
|
||||
DBG (DBG_info, "genesys_read_ordered_data: %lu lines left by output\n",
|
||||
((dev->total_bytes_to_read - dev->total_bytes_read) * 8) /
|
||||
((dev->total_bytes_to_read - dev->total_bytes_read) * 8UL) /
|
||||
(dev->settings.pixels * channels * depth));
|
||||
DBG (DBG_info, "genesys_read_ordered_data: %lu lines left by input\n",
|
||||
((dev->read_bytes_left + dev->read_buffer.avail) * 8) /
|
||||
((dev->read_bytes_left + dev->read_buffer.avail) * 8UL) /
|
||||
(src_pixels * channels * depth));
|
||||
|
||||
if (channels == 1)
|
||||
|
@ -5913,6 +5926,18 @@ calc_parameters (Genesys_Scanner * s)
|
|||
else
|
||||
s->dev->settings.threshold_curve=0;
|
||||
|
||||
/* some digital processing requires the whole picture to be buffered */
|
||||
/* no digital processing takes place when doing preview */
|
||||
if ((s->val[OPT_SWDESPECK].b || s->val[OPT_SWCROP].b || s->val[OPT_SWDESKEW].b)
|
||||
&&(!s->val[OPT_PREVIEW].b))
|
||||
{
|
||||
s->dev->buffer_image=SANE_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
s->dev->buffer_image=SANE_FALSE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -6196,6 +6221,45 @@ init_options (Genesys_Scanner * s)
|
|||
DBG (DBG_info, "init_options: custom gamma disabled\n");
|
||||
}
|
||||
|
||||
/* software base image enhancements, these are consuming as many
|
||||
* memory than used by the full scanned image and may fail at high
|
||||
* resolution
|
||||
*/
|
||||
/* software deskew */
|
||||
s->opt[OPT_SWDESKEW].name = "swdeskew";
|
||||
s->opt[OPT_SWDESKEW].title = "Software deskew";
|
||||
s->opt[OPT_SWDESKEW].desc = "Request backend to rotate skewed pages digitally";
|
||||
s->opt[OPT_SWDESKEW].type = SANE_TYPE_BOOL;
|
||||
s->opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
|
||||
s->val[OPT_SWDESKEW].b = SANE_FALSE;
|
||||
|
||||
/* software deskew */
|
||||
s->opt[OPT_SWDESPECK].name = "swdespeck";
|
||||
s->opt[OPT_SWDESPECK].title = "Software despeck";
|
||||
s->opt[OPT_SWDESPECK].desc = "Request backend to remove lone dots digitally";
|
||||
s->opt[OPT_SWDESPECK].type = SANE_TYPE_BOOL;
|
||||
s->opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
|
||||
s->val[OPT_SWDESPECK].b = SANE_FALSE;
|
||||
|
||||
/* software despeckle radius */
|
||||
s->opt[OPT_DESPECK].name = "despeck";
|
||||
s->opt[OPT_DESPECK].title = "Software despeckle diameter";
|
||||
s->opt[OPT_DESPECK].desc = "Maximum diameter of lone dots to remove from scan";
|
||||
s->opt[OPT_DESPECK].type = SANE_TYPE_INT;
|
||||
s->opt[OPT_DESPECK].unit = SANE_UNIT_NONE;
|
||||
s->opt[OPT_DESPECK].constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
s->opt[OPT_DESPECK].constraint.range = &swdespeck_range;
|
||||
s->opt[OPT_DESPECK].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
|
||||
s->val[OPT_DESPECK].w = 1;
|
||||
|
||||
/* crop by software */
|
||||
s->opt[OPT_SWCROP].name = "swcrop";
|
||||
s->opt[OPT_SWCROP].title = "Software crop";
|
||||
s->opt[OPT_SWCROP].desc = "Request backend to remove border from pages digitally";
|
||||
s->opt[OPT_SWCROP].type = SANE_TYPE_BOOL;
|
||||
s->opt[OPT_SWCROP].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
|
||||
s->val[OPT_SWCROP].b = SANE_FALSE;
|
||||
|
||||
/* "Extras" group: */
|
||||
s->opt[OPT_EXTRAS_GROUP].title = SANE_I18N ("Extras");
|
||||
s->opt[OPT_EXTRAS_GROUP].desc = "";
|
||||
|
@ -6820,6 +6884,108 @@ write_calibration (Genesys_Device * dev)
|
|||
fclose (fp);
|
||||
}
|
||||
|
||||
/** @brief buffer scanned picture
|
||||
* In order to allow digital processing, we must be able to put all the
|
||||
* scanned picture in a buffer.
|
||||
*/
|
||||
static SANE_Status
|
||||
genesys_buffer_image(Genesys_Scanner *s)
|
||||
{
|
||||
SANE_Status status = SANE_STATUS_GOOD;
|
||||
size_t maximum; /**> maximum bytes size of the scan */
|
||||
size_t len; /**> length of scanned data read */
|
||||
size_t total; /**> total of butes read */
|
||||
size_t size; /**> size of image buffer */
|
||||
size_t read_size; /**> size of reads */
|
||||
int lines; /** number of lines of the scan */
|
||||
Genesys_Device *dev = s->dev;
|
||||
|
||||
/* compute maximum number of lines for the scan */
|
||||
if (s->params.lines > 0)
|
||||
{
|
||||
lines = s->params.lines;
|
||||
}
|
||||
else
|
||||
{
|
||||
lines =
|
||||
(SANE_UNFIX (dev->model->y_size) * dev->settings.yres) / MM_PER_INCH;
|
||||
}
|
||||
DBG (DBG_info, "%s: buffering %d lines of %d bytes\n", __FUNCTION__, lines,
|
||||
s->params.bytes_per_line);
|
||||
|
||||
/* maximum bytes to read */
|
||||
maximum = s->params.bytes_per_line * lines;
|
||||
|
||||
/* initial size of the read buffer */
|
||||
size =
|
||||
((2048 * 2048) / s->params.bytes_per_line) * s->params.bytes_per_line;
|
||||
|
||||
/* read size */
|
||||
read_size = size / 2;
|
||||
|
||||
/* allocate memory */
|
||||
dev->img_buffer = (SANE_Byte *) malloc (size);
|
||||
if (dev->img_buffer == NULL)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"%s: digital processing requires too much memory.\nConsider disabling it\n",
|
||||
__FUNCTION__);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
|
||||
/* loop reading data until we reach maximu or EOF */
|
||||
total = 0;
|
||||
while (total < maximum && status != SANE_STATUS_EOF)
|
||||
{
|
||||
len = size - maximum;
|
||||
if (len > read_size)
|
||||
{
|
||||
len = read_size;
|
||||
}
|
||||
status = genesys_read_ordered_data (dev, dev->img_buffer + total, &len);
|
||||
if (status != SANE_STATUS_EOF && status != SANE_STATUS_GOOD)
|
||||
{
|
||||
free (s->dev->img_buffer);
|
||||
DBG (DBG_error, "%s: %s buffering failed\n", __FUNCTION__,
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
total += len;
|
||||
|
||||
/* do we need to enlarge read buffer ? */
|
||||
if (total + read_size > size && status != SANE_STATUS_EOF)
|
||||
{
|
||||
size += read_size;
|
||||
dev->img_buffer = (SANE_Byte *) realloc (dev->img_buffer, size);
|
||||
if (dev->img_buffer == NULL)
|
||||
{
|
||||
DBG (DBG_error0,
|
||||
"%s: digital processing requires too much memory.\nConsider disabling it\n",
|
||||
__FUNCTION__);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* update counters */
|
||||
dev->total_bytes_to_read = total;
|
||||
dev->total_bytes_read = 0;
|
||||
|
||||
/* update params */
|
||||
s->params.lines = total / s->params.bytes_per_line;
|
||||
if (DBG_LEVEL >= DBG_io2)
|
||||
{
|
||||
sanei_genesys_write_pnm_file ("unprocessed.pnm",
|
||||
dev->img_buffer,
|
||||
s->params.depth,
|
||||
s->params.format==SANE_FRAME_RGB ? 3:1,
|
||||
s->params.pixels_per_line,
|
||||
s->params.lines);
|
||||
}
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/* -------------------------- SANE API functions ------------------------- */
|
||||
|
||||
SANE_Status
|
||||
|
@ -6839,6 +7005,9 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
|
|||
/* init usb use */
|
||||
sanei_usb_init ();
|
||||
|
||||
/* init sanei_magic */
|
||||
sanei_magic_init();
|
||||
|
||||
DBG (DBG_info, "sane_init: %s endian machine\n",
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
"big"
|
||||
|
@ -7010,6 +7179,7 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle)
|
|||
s->dev->white_average_data = NULL;
|
||||
s->dev->dark_average_data = NULL;
|
||||
s->dev->calibration_cache = NULL;
|
||||
s->dev->img_buffer = NULL;
|
||||
|
||||
/* insert newly opened handle into list of open handles: */
|
||||
s->next = first_handle;
|
||||
|
@ -7171,7 +7341,7 @@ get_option_value (Genesys_Scanner * s, int option, void *val)
|
|||
case OPT_BR_X:
|
||||
case OPT_BR_Y:
|
||||
*(SANE_Word *) val = s->val[option].w;
|
||||
/* switch coordinate tokeep them coherent */
|
||||
/* switch coordinate to keep them coherent */
|
||||
if (s->val[OPT_TL_X].w >= s->val[OPT_BR_X].w)
|
||||
{
|
||||
tmp=s->val[OPT_BR_X].w;
|
||||
|
@ -7195,6 +7365,10 @@ get_option_value (Genesys_Scanner * s, int option, void *val)
|
|||
case OPT_DISABLE_DYNAMIC_LINEART:
|
||||
case OPT_DISABLE_INTERPOLATION:
|
||||
case OPT_LAMP_OFF_TIME:
|
||||
case OPT_SWDESKEW:
|
||||
case OPT_SWCROP:
|
||||
case OPT_SWDESPECK:
|
||||
case OPT_DESPECK:
|
||||
*(SANE_Word *) val = s->val[option].w;
|
||||
break;
|
||||
case OPT_CUSTOM_GAMMA:
|
||||
|
@ -7307,12 +7481,28 @@ set_option_value (Genesys_Scanner * s, int option, void *val,
|
|||
case OPT_THRESHOLD:
|
||||
case OPT_THRESHOLD_CURVE:
|
||||
case OPT_DISABLE_DYNAMIC_LINEART:
|
||||
case OPT_SWCROP:
|
||||
case OPT_SWDESKEW:
|
||||
case OPT_DESPECK:
|
||||
case OPT_DISABLE_INTERPOLATION:
|
||||
case OPT_PREVIEW:
|
||||
s->val[option].w = *(SANE_Word *) val;
|
||||
RIE (calc_parameters (s));
|
||||
*myinfo |= SANE_INFO_RELOAD_PARAMS;
|
||||
break;
|
||||
case OPT_SWDESPECK:
|
||||
s->val[option].w = *(SANE_Word *) val;
|
||||
if (s->val[OPT_SWDESPECK].b == SANE_TRUE)
|
||||
{
|
||||
ENABLE(OPT_DESPECK);
|
||||
}
|
||||
else
|
||||
{
|
||||
DISABLE(OPT_DESPECK);
|
||||
}
|
||||
RIE (calc_parameters (s));
|
||||
*myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
|
||||
break;
|
||||
case OPT_SOURCE:
|
||||
if (strcmp (s->val[option].s, val) != 0)
|
||||
{ /* something changed */
|
||||
|
@ -7657,7 +7847,11 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
|
|||
|
||||
DBG (DBG_proc, "sane_get_parameters: start\n");
|
||||
|
||||
RIE (calc_parameters (s));
|
||||
/* don't recompute parameters once data reading is active, ie during scan */
|
||||
if(s->dev->read_active == SANE_FALSE)
|
||||
{
|
||||
RIE (calc_parameters (s));
|
||||
}
|
||||
if (params)
|
||||
{
|
||||
*params = s->params;
|
||||
|
@ -7667,6 +7861,7 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
|
|||
* don't know the real document height.
|
||||
*/
|
||||
if (s->dev->model->is_sheetfed == SANE_TRUE
|
||||
&& s->dev->read_active == SANE_FALSE
|
||||
&& s->val[OPT_BR_Y].w == s->opt[OPT_BR_Y].constraint.range->max)
|
||||
{
|
||||
params->lines = -1;
|
||||
|
@ -7682,7 +7877,7 @@ SANE_Status
|
|||
sane_start (SANE_Handle handle)
|
||||
{
|
||||
Genesys_Scanner *s = handle;
|
||||
SANE_Status status;
|
||||
SANE_Status status=SANE_STATUS_GOOD;
|
||||
|
||||
DBG (DBG_proc, "sane_start: start\n");
|
||||
|
||||
|
@ -7707,8 +7902,35 @@ sane_start (SANE_Handle handle)
|
|||
|
||||
s->scanning = SANE_TRUE;
|
||||
|
||||
/* if one of the software enhancement option is selected,
|
||||
* we do the scan internally, process picture then put it an internal
|
||||
* buffer. Since cropping may change scan parameters, we recompute them
|
||||
* at the end */
|
||||
if (s->dev->buffer_image)
|
||||
{
|
||||
RIE(genesys_buffer_image(s));
|
||||
|
||||
/* deskew image if required */
|
||||
if(s->val[OPT_SWDESKEW].b == SANE_TRUE)
|
||||
{
|
||||
RIE(genesys_deskew(s));
|
||||
}
|
||||
|
||||
/* despeck image if required */
|
||||
if(s->val[OPT_SWDESPECK].b == SANE_TRUE)
|
||||
{
|
||||
RIE(genesys_despeck(s));
|
||||
}
|
||||
|
||||
/* crop image if required */
|
||||
if(s->val[OPT_SWCROP].b == SANE_TRUE)
|
||||
{
|
||||
RIE(genesys_crop(s));
|
||||
}
|
||||
}
|
||||
|
||||
DBG (DBG_proc, "sane_start: exit\n");
|
||||
return SANE_STATUS_GOOD;
|
||||
return status;
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
|
@ -7716,7 +7938,8 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
|
|||
SANE_Int * len)
|
||||
{
|
||||
Genesys_Scanner *s = handle;
|
||||
SANE_Status status;
|
||||
Genesys_Device *dev=s->dev;
|
||||
SANE_Status status=SANE_STATUS_GOOD;
|
||||
size_t local_len;
|
||||
|
||||
if (!s)
|
||||
|
@ -7749,7 +7972,25 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
|
|||
DBG (DBG_proc, "sane_read: start, %d maximum bytes required\n", max_len);
|
||||
|
||||
local_len = max_len;
|
||||
status = genesys_read_ordered_data (s->dev, buf, &local_len);
|
||||
|
||||
/* if image hasn't been buffered, read data from scanner */
|
||||
if(!dev->buffer_image)
|
||||
{
|
||||
status = genesys_read_ordered_data (dev, buf, &local_len);
|
||||
}
|
||||
else /* read data from buffer */
|
||||
{
|
||||
if(dev->total_bytes_read+local_len>dev->total_bytes_to_read)
|
||||
{
|
||||
local_len=dev->total_bytes_to_read-dev->total_bytes_read;
|
||||
}
|
||||
memcpy(buf,dev->img_buffer+dev->total_bytes_read,local_len);
|
||||
dev->total_bytes_read+=local_len;
|
||||
if(dev->total_bytes_read>=dev->total_bytes_to_read)
|
||||
{
|
||||
status=SANE_STATUS_EOF;
|
||||
}
|
||||
}
|
||||
|
||||
*len = local_len;
|
||||
return status;
|
||||
|
@ -7765,11 +8006,16 @@ sane_cancel (SANE_Handle handle)
|
|||
|
||||
s->scanning = SANE_FALSE;
|
||||
s->dev->read_active = SANE_FALSE;
|
||||
if(s->dev->img_buffer!=NULL)
|
||||
{
|
||||
free(s->dev->img_buffer);
|
||||
s->dev->img_buffer=NULL;
|
||||
}
|
||||
|
||||
status = s->dev->model->cmd_set->end_scan (s->dev, s->dev->reg, SANE_TRUE);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error, "sane_cancel: Failed to end scan: %s\n",
|
||||
DBG (DBG_error, "sane_cancel: failed to end scan: %s\n",
|
||||
sane_strstatus (status));
|
||||
return;
|
||||
}
|
||||
|
@ -7797,7 +8043,7 @@ sane_cancel (SANE_Handle handle)
|
|||
}
|
||||
}
|
||||
|
||||
/*enable power saving mode */
|
||||
/* enable power saving mode */
|
||||
status = s->dev->model->cmd_set->save_power (s->dev, SANE_TRUE);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
|
|
|
@ -93,6 +93,10 @@ enum Genesys_Option
|
|||
OPT_GAMMA_VECTOR_R,
|
||||
OPT_GAMMA_VECTOR_G,
|
||||
OPT_GAMMA_VECTOR_B,
|
||||
OPT_SWDESKEW,
|
||||
OPT_SWCROP,
|
||||
OPT_SWDESPECK,
|
||||
OPT_DESPECK,
|
||||
|
||||
OPT_EXTRAS_GROUP,
|
||||
OPT_LAMP_OFF_TIME,
|
||||
|
|
|
@ -264,3 +264,123 @@ genesys_shrink_lines_1 (
|
|||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
/** Look in image for likely left/right/bottom paper edges, then crop image.
|
||||
* Since failing to crop isn't fatal, we always return SANE_STATUS_GOOD .
|
||||
*/
|
||||
static SANE_Status
|
||||
genesys_crop(Genesys_Scanner *s)
|
||||
{
|
||||
SANE_Status status = SANE_STATUS_GOOD;
|
||||
Genesys_Device *dev = s->dev;
|
||||
int top = 0;
|
||||
int bottom = 0;
|
||||
int left = 0;
|
||||
int right = 0;
|
||||
|
||||
DBG (DBG_proc, "%s: start\n", __FUNCTION__);
|
||||
|
||||
/* first find edges if any */
|
||||
status = sanei_magic_findEdges (&s->params,
|
||||
dev->img_buffer,
|
||||
dev->settings.xres,
|
||||
dev->settings.yres,
|
||||
&top,
|
||||
&bottom,
|
||||
&left,
|
||||
&right);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_info, "%s: bad or no edges, bailing\n", __FUNCTION__);
|
||||
goto cleanup;
|
||||
}
|
||||
DBG (DBG_io, "%s: t:%d b:%d l:%d r:%d\n", __FUNCTION__, top, bottom, left,
|
||||
right);
|
||||
|
||||
/* now crop the image */
|
||||
status =
|
||||
sanei_magic_crop (&(s->params), dev->img_buffer, top, bottom, left, right);
|
||||
if (status)
|
||||
{
|
||||
DBG (DBG_warn, "%s: failed to crop\n", __FUNCTION__);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* update counters to new image size */
|
||||
dev->total_bytes_to_read = s->params.bytes_per_line * s->params.lines;
|
||||
|
||||
cleanup:
|
||||
DBG (DBG_proc, "%s: completed\n", __FUNCTION__);
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/** Look in image for likely upper and left paper edges, then rotate
|
||||
* image so that upper left corner of paper is upper left of image.
|
||||
* @return since failure doens't prevent scanning, we always return
|
||||
* SANE_STATUS_GOOD
|
||||
*/
|
||||
static SANE_Status
|
||||
genesys_deskew(Genesys_Scanner *s)
|
||||
{
|
||||
SANE_Status status;
|
||||
Genesys_Device *dev = s->dev;
|
||||
|
||||
int x = 0, y = 0, bg;
|
||||
double slope = 0;
|
||||
|
||||
DBG (DBG_proc, "%s: start\n", __FUNCTION__);
|
||||
|
||||
bg=0;
|
||||
if(s->params.format==SANE_FRAME_GRAY && s->params.depth == 1)
|
||||
{
|
||||
bg=0xff;
|
||||
}
|
||||
status = sanei_magic_findSkew (&s->params,
|
||||
dev->img_buffer,
|
||||
dev->sensor.optical_res,
|
||||
dev->sensor.optical_res,
|
||||
&x,
|
||||
&y,
|
||||
&slope);
|
||||
if (status!=SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error, "%s: bad findSkew, bailing\n", __FUNCTION__);
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
DBG(DBG_info, "%s: slope=%f => %f\n",__FUNCTION__,slope, (slope/M_PI_2)*90);
|
||||
/* rotate image slope is in [-PI/2,PI/2]
|
||||
* positive values rotate trigonometric direction wise */
|
||||
status = sanei_magic_rotate (&s->params,
|
||||
dev->img_buffer,
|
||||
x,
|
||||
y,
|
||||
slope,
|
||||
bg);
|
||||
if (status!=SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error, "%s: rotate error: %s", __FUNCTION__, sane_strstatus(status));
|
||||
}
|
||||
|
||||
DBG (DBG_proc, "%s: completed\n", __FUNCTION__);
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/** remove lone dots
|
||||
* @return since failure doens't prevent scanning, we always return
|
||||
* SANE_STATUS_GOOD
|
||||
*/
|
||||
static SANE_Status
|
||||
genesys_despeck(Genesys_Scanner *s)
|
||||
{
|
||||
if(sanei_magic_despeck(&s->params,
|
||||
s->dev->img_buffer,
|
||||
s->val[OPT_DESPECK].w)!=SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error, "%s: bad despeck, bailing\n",__FUNCTION__);
|
||||
}
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
/* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */
|
||||
|
|
|
@ -650,6 +650,10 @@ struct Genesys_Device
|
|||
size_t len; /**> number of even pixels */
|
||||
size_t cur; /**> current pixel position within sub window */
|
||||
Genesys_Buffer oe_buffer; /**> buffer to handle even/odd data */
|
||||
|
||||
SANE_Bool buffer_image; /**> when true the scanned picture is first buffered
|
||||
* to a software image enhancements */
|
||||
SANE_Byte *img_buffer; /**> image buffer where the scanned picture is stored */
|
||||
};
|
||||
|
||||
typedef struct Genesys_USB_Device_Entry
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
.TH "sane\-genesys" "5" "18 Jun 2010" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy"
|
||||
.IX sane\-genesys
|
||||
.SH "NAME"
|
||||
sane\-genesys \- SANE backend for GL646, GL841 and GL847 based USB flatbed scanners
|
||||
sane\-genesys \- SANE backend for GL646, GL841, GL843 and GL847 based USB flatbed scanners
|
||||
.SH "DESCRIPTION"
|
||||
The
|
||||
.B sane\-genesys
|
||||
|
@ -41,7 +41,7 @@ or syslog) to the sane\-devel mailing list. Even if the scanner's name is only
|
|||
slightly different from the models mentioned above, please let me know.
|
||||
.PP
|
||||
If you own a scanner that isn't detected by the genesys backend but has a GL646,
|
||||
GL847 or GL847 chipset, you can try to add it to the backend.
|
||||
GL841, GL843 or GL847 chipset, you can try to add it to the backend.
|
||||
.PP
|
||||
.SH "CALIBRATION"
|
||||
To give correct image quality, sheet fed scanners need to be calibrated using the
|
||||
|
@ -55,21 +55,55 @@ will have to be redone.
|
|||
.SH EXTRAS SCAN OPTIONS
|
||||
|
||||
.B \-\-lamp\-off\-time number
|
||||
.RS
|
||||
The lamp will be turned off after the given time (in minutes). A value of 0 means that the lamp won't be turned off.
|
||||
.RE
|
||||
|
||||
.B \-\-threshold percent
|
||||
.RS
|
||||
0..100% (in steps of 1). Select minimum brightness to get a white point. Pixels
|
||||
whith brightness below that value will be scanned as black.
|
||||
.RE
|
||||
|
||||
.B \-\-disable-interpolation yes|no
|
||||
.RS
|
||||
When using high resolutions where the horizontal resolution is smaller than vertical resolution,
|
||||
data is expanded by software to preserve picture geometry. This can be disbled by this option to get
|
||||
real scanned data.
|
||||
.RE
|
||||
|
||||
.B \-\-color-filter None|Red|Green|Blue
|
||||
.RS
|
||||
When using gray or lineart this option selects the used color. Using a color filter
|
||||
will give a monochrome scan. CIS based scanners can to true gray when no filter (None value) is
|
||||
selected.
|
||||
.RE
|
||||
|
||||
.PP
|
||||
Additionally, several 'software' options are exposed by the backend. These
|
||||
are reimplementations of features provided natively by larger scanners, but
|
||||
running on the host computer. This enables smaller machines to have similar
|
||||
capabilites. Please note that these features are somewhat simplistic, and
|
||||
may not perform as well as the native implementations. Note also that these
|
||||
features all require that the driver cache the entire image in memory. This
|
||||
will almost certainly result in a reduction of scanning speed.
|
||||
.PP
|
||||
.B \-\-swcrop
|
||||
.RS
|
||||
Requests the driver to detect the extremities of the paper within the larger
|
||||
image, and crop the empty edges.
|
||||
.RE
|
||||
.PP
|
||||
.B \-\-swdeskew
|
||||
.RS
|
||||
Requests the driver to detect the rotation of the paper within the larger
|
||||
image, and counter the rotation.
|
||||
.RE
|
||||
.PP
|
||||
.B \-\-swdespeck \-\-despeck X
|
||||
.RS
|
||||
Requests the driver to find and remove dots of X diameter or smaller from the
|
||||
image, and fill the space with the average surrounding color.
|
||||
|
||||
.PP
|
||||
.SH "SYSTEM ISSUES"
|
||||
|
@ -138,8 +172,12 @@ part.
|
|||
This environment variable controls the debug level for the specific GL841 code
|
||||
part.
|
||||
.TP
|
||||
.B SANE_DEBUG_GENESYS_GL843
|
||||
This environment variable controls the debug level for the specific GL843 code
|
||||
part.
|
||||
.TP
|
||||
.B SANE_DEBUG_GENESYS_GL847
|
||||
This environment variable controls the debug level for the specific GL841 code
|
||||
This environment variable controls the debug level for the specific GL847 code
|
||||
part.
|
||||
|
||||
|
||||
|
|
|
@ -723,8 +723,8 @@ getTopEdge(int width, int height, int resolution,
|
|||
{
|
||||
SANE_Status ret = SANE_STATUS_GOOD;
|
||||
|
||||
int slopes = 11;
|
||||
int offsets = 11;
|
||||
int slopes = 31;
|
||||
int offsets = 31;
|
||||
double maxSlope = 1;
|
||||
double minSlope = -1;
|
||||
int maxOffset = resolution/6;
|
||||
|
@ -1340,7 +1340,7 @@ sanei_magic_getTransX (
|
|||
near += buffer[i*bwidth + j*depth + k];
|
||||
}
|
||||
|
||||
if(abs(near - far) > winLen*depth*9){
|
||||
if(abs(near - far) > 50*winLen*depth - near*40/255){
|
||||
buff[i] = j;
|
||||
break;
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue