Merge branch '16-low-default-buffer-size-results-in-poor-scanner-performance' into 'master'

Resolve "Low default buffer size results in poor scanner performance"

Closes #16

See merge request sane-project/backends!773
666-epsonds-has-issues-with-saned
Ralph Little 2023-02-20 23:51:26 +00:00
commit 10b3345a1c
5 zmienionych plików z 348 dodań i 307 usunięć

Wyświetl plik

@ -24,6 +24,9 @@ saned \- SANE network daemon
.B ]
.B [ \-e ]
.B [ \-h ]
.B [ \-B
.I buffer-size
.B ]
.SH DESCRIPTION
.B saned
@ -114,6 +117,11 @@ will divert
.B saned
debug output to stderr instead of the syslog default.
.TP
.BR \-B ", " \-\-buffer-size=\fIbuffer\-size\fR
specifies the size of the read buffer used for communication with the backend in KB.
Default value is 1MB.
.TP
.BR \-h ", " \-\-help
displays a short help message.

Wyświetl plik

@ -4,36 +4,32 @@
scanimage \- scan an image
.SH SYNOPSIS
.B scanimage
.RB [ \-d | \-\-device\-name
.RB [ \-d
.IR dev ]
.RB [ \-\-format
.IR format ]
.RB [ \-i | \-\-icc\-profile
.RB [ \-\-format\fI=output-format ]
.RB [ \-i
.IR profile ]
.RB [ \-L | \-\-list\-devices ]
.RB [ \-f | \-\-formatted\-device\-list
.IR format ]
.RB [ \-b | \-\-batch
.RB [ \-L ]
.RB [ \-f
.IR device-format ]
.RB [ \-b
.RI [ format ]]
.RB [ \-\-batch\-start
.IR start ]
.RB [ \-\-batch\-count
.IR count ]
.RB [ \-\-batch\-increment
.IR increment ]
.RB [ \-\-batch\-start\fI=start ]
.RB [ \-\-batch\-count\fI=count ]
.RB [ \-\-batch\-increment\fI=increment ]
.RB [ \-\-batch\-double ]
.RB [ \-\-accept\-md5\-only ]
.RB [ \-p | \-\-progress ]
.RB [ \-o | \-\-output-file
.RB [ \-p]
.RB [ \-o
.IR path ]
.RB [ \-n | \-\-dont\-scan ]
.RB [ \-T | \-\-test ]
.RB [ \-A | \-\-all-options ]
.RB [ \-h | \-\-help ]
.RB [ \-v | \-\-verbose ]
.RB [ \-B | \-\-buffer-size
.RI [= size ]]
.RB [ \-V | \-\-version ]
.RB [ \-n ]
.RB [ \-T ]
.RB [ \-A ]
.RB [ \-h ]
.RB [ \-v ]
.RB [ \-B
.RI size ]
.RB [ \-V ]
.RI [ device\-specific\-options ]
.SH DESCRIPTION
.B scanimage
@ -117,12 +113,12 @@ If this variable is not set,
will attempt to open the first available device.
.TP
.BR \-\-format =\fIformat\fR
.BR \-\-format =\fIoutput-format\fR
selects how image data is written to standard output or the file specified by
the
.B \-\-output\-file
option.
.I format
.I output-format
can be
.BR pnm ,
.BR tiff ,
@ -150,8 +146,8 @@ by its full device name. You may need to consult your system administrator to
find out the names of such devices.
.TP
.BR \-f "\fI format\fR, " \-\-formatted\-device\-list =\fIformat\fR
works similar to
.BR \-f "\fI format\fR, " \-\-formatted\-device\-list =\fIdevice-format\fR
works similarly to
.BR \-\-list\-devices ,
but requires a format string.
.B scanimage
@ -306,12 +302,10 @@ The option may be specified repeatedly, each time increasing the verbosity
level.
.TP
.BR \-B " [\fIsize\fR], " \-\-buffer\-size =[\fIsize\fR]
changes input buffer size from the default of 32KB to
.BR \-B " [\fIsize\fR], " \-\-buffer\-size =\fIsize
changes input buffer size from the default of 1MB to
.I size
KB. If
.I size
is not specified then the buffer is set to 1 MB.
KB.
.TP
.BR \-V ", " \-\-version

Wyświetl plik

@ -53,6 +53,7 @@
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
@ -257,6 +258,7 @@ static int data_connect_timeout = 4000;
static Handle *handle;
static char *bind_addr;
static short bind_port = -1;
static size_t buffer_size = (1 * 1024 * 1024);
static union
{
int w;
@ -1651,168 +1653,186 @@ store_reclen (SANE_Byte * buf, size_t buf_size, int i, size_t reclen)
static void
do_scan (Wire * w, int h, int data_fd)
{
int num_fds, be_fd = -1, reader, writer, bytes_in_buf, status_dirty = 0;
int num_fds, be_fd = -1, reader, bytes_in_buf, status_dirty = 0;
size_t writer;
SANE_Handle be_handle = handle[h].handle;
struct timeval tv, *timeout = 0;
fd_set rd_set, rd_mask, wr_set, wr_mask;
SANE_Byte buf[8192];
SANE_Byte *buf = NULL;
SANE_Status status;
long int nwritten;
ssize_t nwritten;
SANE_Int length;
size_t nbytes;
DBG (3, "do_scan: start\n");
FD_ZERO (&rd_mask);
FD_SET (w->io.fd, &rd_mask);
num_fds = w->io.fd + 1;
FD_ZERO (&wr_mask);
FD_SET (data_fd, &wr_mask);
if (data_fd >= num_fds)
num_fds = data_fd + 1;
sane_set_io_mode (be_handle, SANE_TRUE);
if (sane_get_select_fd (be_handle, &be_fd) == SANE_STATUS_GOOD)
/*
* Allocate the read buffer.
*
*/
buf = malloc (buffer_size);
if (!buf)
{
FD_SET (be_fd, &rd_mask);
if (be_fd >= num_fds)
num_fds = be_fd + 1;
status = SANE_STATUS_NO_MEM;
DBG (DBG_ERR, "do_scan: failed to allocate read buffer (%zu bytes)\n",
buffer_size);
}
else
{
memset (&tv, 0, sizeof (tv));
timeout = &tv;
FD_ZERO(&rd_mask);
FD_SET(w->io.fd, &rd_mask);
num_fds = w->io.fd + 1;
FD_ZERO(&wr_mask);
FD_SET(data_fd, &wr_mask);
if (data_fd >= num_fds)
num_fds = data_fd + 1;
sane_set_io_mode (be_handle, SANE_TRUE);
if (sane_get_select_fd (be_handle, &be_fd) == SANE_STATUS_GOOD)
{
FD_SET(be_fd, &rd_mask);
if (be_fd >= num_fds)
num_fds = be_fd + 1;
}
else
{
memset (&tv, 0, sizeof(tv));
timeout = &tv;
}
status = SANE_STATUS_GOOD;
reader = writer = bytes_in_buf = 0;
do
{
rd_set = rd_mask;
wr_set = wr_mask;
if (select (num_fds, &rd_set, &wr_set, 0, timeout) < 0)
{
if (be_fd >= 0 && errno == EBADF)
{
/* This normally happens when a backend closes a select
filedescriptor when reaching the end of file. So
pass back this status to the client: */
FD_CLR(be_fd, &rd_mask);
be_fd = -1;
/* only set status_dirty if EOF hasn't been already detected */
if (status == SANE_STATUS_GOOD)
status_dirty = 1;
status = SANE_STATUS_EOF;
DBG (DBG_INFO, "do_scan: select_fd was closed --> EOF\n");
continue;
}
else
{
status = SANE_STATUS_IO_ERROR;
DBG (DBG_ERR, "do_scan: select failed (%s)\n",
strerror (errno));
break;
}
}
if (bytes_in_buf)
{
if (FD_ISSET(data_fd, &wr_set))
{
if (bytes_in_buf > 0)
{
/* write more input data */
nbytes = bytes_in_buf;
if (writer + nbytes > buffer_size)
nbytes = buffer_size - writer;
DBG (DBG_INFO,
"do_scan: trying to write %d bytes to client\n",
nbytes);
nwritten = write (data_fd, buf + writer, nbytes);
DBG (DBG_INFO, "do_scan: wrote %ld bytes to client\n",
nwritten);
if (nwritten < 0)
{
DBG (DBG_ERR, "do_scan: write failed (%s)\n",
strerror (errno));
status = SANE_STATUS_CANCELLED;
handle[h].docancel = 1;
break;
}
bytes_in_buf -= (size_t) nwritten;
writer += (size_t) nwritten;
if (writer == buffer_size)
writer = 0;
}
}
}
else if (status == SANE_STATUS_GOOD
&& (timeout || FD_ISSET(be_fd, &rd_set)))
{
int i;
/* get more input data */
/* reserve 4 bytes to store the length of the data record: */
i = reader;
reader += 4;
if (reader >= (int) buffer_size)
reader -= buffer_size;
assert(bytes_in_buf == 0);
nbytes = buffer_size - 4;
if (reader + nbytes > buffer_size)
nbytes = buffer_size - reader;
DBG (DBG_INFO, "do_scan: trying to read %d bytes from scanner\n",
nbytes);
status = sane_read (be_handle, buf + reader, nbytes, &length);
DBG (DBG_INFO, "do_scan: read %d bytes from scanner\n", length);
reset_watchdog ();
reader += length;
if (reader >= (int) buffer_size)
reader = 0;
bytes_in_buf += length + 4;
if (status != SANE_STATUS_GOOD)
{
reader = i; /* restore reader index */
status_dirty = 1;
DBG (DBG_MSG, "do_scan: status = `%s'\n",
sane_strstatus (status));
}
else
store_reclen (buf, buffer_size, i, length);
}
if (status_dirty && buffer_size - bytes_in_buf >= 5)
{
status_dirty = 0;
reader = store_reclen (buf, buffer_size, reader, 0xffffffff);
buf[reader] = status;
bytes_in_buf += 5;
DBG (DBG_MSG, "do_scan: statuscode `%s' was added to buffer\n",
sane_strstatus (status));
}
if (FD_ISSET(w->io.fd, &rd_set))
{
DBG (DBG_MSG, "do_scan: processing RPC request on fd %d\n",
w->io.fd);
if (process_request (w) < 0)
handle[h].docancel = 1;
if (handle[h].docancel)
break;
}
}
while (status == SANE_STATUS_GOOD || bytes_in_buf > 0 || status_dirty);
DBG (DBG_MSG, "do_scan: done, status=%s\n", sane_strstatus (status));
free (buf);
buf = NULL;
}
status = SANE_STATUS_GOOD;
reader = writer = bytes_in_buf = 0;
do
{
rd_set = rd_mask;
wr_set = wr_mask;
if (select (num_fds, &rd_set, &wr_set, 0, timeout) < 0)
{
if (be_fd >= 0 && errno == EBADF)
{
/* This normally happens when a backend closes a select
filedescriptor when reaching the end of file. So
pass back this status to the client: */
FD_CLR (be_fd, &rd_mask);
be_fd = -1;
/* only set status_dirty if EOF hasn't been already detected */
if (status == SANE_STATUS_GOOD)
status_dirty = 1;
status = SANE_STATUS_EOF;
DBG (DBG_INFO, "do_scan: select_fd was closed --> EOF\n");
continue;
}
else
{
status = SANE_STATUS_IO_ERROR;
DBG (DBG_ERR, "do_scan: select failed (%s)\n", strerror (errno));
break;
}
}
if (bytes_in_buf)
{
if (FD_ISSET (data_fd, &wr_set))
{
if (bytes_in_buf > 0)
{
/* write more input data */
nbytes = bytes_in_buf;
if (writer + nbytes > sizeof (buf))
nbytes = sizeof (buf) - writer;
DBG (DBG_INFO,
"do_scan: trying to write %d bytes to client\n",
nbytes);
nwritten = write (data_fd, buf + writer, nbytes);
DBG (DBG_INFO,
"do_scan: wrote %ld bytes to client\n", nwritten);
if (nwritten < 0)
{
DBG (DBG_ERR, "do_scan: write failed (%s)\n",
strerror (errno));
status = SANE_STATUS_CANCELLED;
handle[h].docancel = 1;
break;
}
bytes_in_buf -= nwritten;
writer += nwritten;
if (writer == sizeof (buf))
writer = 0;
}
}
}
else if (status == SANE_STATUS_GOOD
&& (timeout || FD_ISSET (be_fd, &rd_set)))
{
int i;
/* get more input data */
/* reserve 4 bytes to store the length of the data record: */
i = reader;
reader += 4;
if (reader >= (int) sizeof (buf))
reader -= sizeof(buf);
assert (bytes_in_buf == 0);
nbytes = sizeof (buf) - 4;
if (reader + nbytes > sizeof (buf))
nbytes = sizeof (buf) - reader;
DBG (DBG_INFO,
"do_scan: trying to read %d bytes from scanner\n", nbytes);
status = sane_read (be_handle, buf + reader, nbytes, &length);
DBG (DBG_INFO,
"do_scan: read %d bytes from scanner\n", length);
reset_watchdog ();
reader += length;
if (reader >= (int) sizeof (buf))
reader = 0;
bytes_in_buf += length + 4;
if (status != SANE_STATUS_GOOD)
{
reader = i; /* restore reader index */
status_dirty = 1;
DBG (DBG_MSG,
"do_scan: status = `%s'\n", sane_strstatus(status));
}
else
store_reclen (buf, sizeof (buf), i, length);
}
if (status_dirty && sizeof (buf) - bytes_in_buf >= 5)
{
status_dirty = 0;
reader = store_reclen (buf, sizeof (buf), reader, 0xffffffff);
buf[reader] = status;
bytes_in_buf += 5;
DBG (DBG_MSG, "do_scan: statuscode `%s' was added to buffer\n",
sane_strstatus(status));
}
if (FD_ISSET (w->io.fd, &rd_set))
{
DBG (DBG_MSG,
"do_scan: processing RPC request on fd %d\n", w->io.fd);
if(process_request (w) < 0)
handle[h].docancel = 1;
if (handle[h].docancel)
break;
}
}
while (status == SANE_STATUS_GOOD || bytes_in_buf > 0 || status_dirty);
DBG (DBG_MSG, "do_scan: done, status=%s\n", sane_strstatus (status));
if(handle[h].docancel)
if (handle[h].docancel)
sane_cancel (handle[h].handle);
handle[h].docancel = 0;
@ -3413,16 +3433,17 @@ static void usage(char *me, int err)
fprintf (stderr,
"Usage: %s [OPTIONS]\n\n"
" Options:\n\n"
" -a, --alone[=user] equal to `-l -D -u user'\n"
" -l, --listen run in standalone mode (listen for connection)\n"
" -u, --user=user run as `user'\n"
" -D, --daemonize run in background\n"
" -o, --once exit after first client disconnects\n"
" -d, --debug=level set debug level `level' (default is 2)\n"
" -e, --stderr output to stderr\n"
" -b, --bind=addr bind address `addr' (default all interfaces)\n"
" -p, --port=port bind port `port` (default sane-port or 6566)\n"
" -h, --help show this help message and exit\n", me);
" -a, --alone[=user] equal to `-l -D -u user'\n"
" -l, --listen run in standalone mode (listen for connection)\n"
" -u, --user=user run as `user'\n"
" -D, --daemonize run in background\n"
" -o, --once exit after first client disconnects\n"
" -d, --debug=level set debug level `level' (default is 2)\n"
" -e, --stderr output to stderr\n"
" -b, --bind=addr bind address `addr' (default all interfaces)\n"
" -p, --port=port bind port `port` (default sane-port or 6566)\n"
" -B, --buffer-size=size set size of read buffer in KB (default: 1024)\n"
" -h, --help show this help message and exit\n", me);
exit(err);
}
@ -3432,17 +3453,18 @@ static int debug;
static struct option long_options[] =
{
/* These options set a flag. */
{"help", no_argument, 0, 'h'},
{"alone", optional_argument, 0, 'a'},
{"listen", no_argument, 0, 'l'},
{"user", required_argument, 0, 'u'},
{"daemonize", no_argument, 0, 'D'},
{"once", no_argument, 0, 'o'},
{"debug", required_argument, 0, 'd'},
{"stderr", no_argument, 0, 'e'},
{"bind", required_argument, 0, 'b'},
{"port", required_argument, 0, 'p'},
{0, 0, 0, 0 }
{"help", no_argument, 0, 'h'},
{"alone", optional_argument, 0, 'a'},
{"listen", no_argument, 0, 'l'},
{"user", required_argument, 0, 'u'},
{"daemonize", no_argument, 0, 'D'},
{"once", no_argument, 0, 'o'},
{"debug", required_argument, 0, 'd'},
{"stderr", no_argument, 0, 'e'},
{"bind", required_argument, 0, 'b'},
{"port", required_argument, 0, 'p'},
{"buffer-size", required_argument, 0, 'B'},
{0, 0, 0, 0 }
};
int
@ -3467,7 +3489,7 @@ main (int argc, char *argv[])
run_foreground = SANE_TRUE;
run_once = SANE_FALSE;
while((c = getopt_long(argc, argv,"ha::lu:Dod:eb:p:", long_options, &long_index )) != -1)
while((c = getopt_long(argc, argv,"ha::lu:Dod:eb:p:B:", long_options, &long_index )) != -1)
{
switch(c) {
case 'a':
@ -3498,8 +3520,25 @@ main (int argc, char *argv[])
bind_addr = optarg;
break;
case 'p':
bind_port = atoi(optarg);
break;
bind_port = atoi(optarg);
break;
case 'B':
{
int buffer_arg = atoi(optarg);
if ((buffer_arg < 0) || ((size_t)buffer_arg > (SIZE_MAX / 1024)))
{
DBG (
DBG_ERR,
"saned: specified buffer size in KB is invalid. Default of %zuKB will be substituted.\n",
buffer_size / 1024);
}
else
{
buffer_size = 1024 * (size_t)buffer_arg;
}
break;
}
case 'h':
usage(argv[0], EXIT_SUCCESS);
break;

Wyświetl plik

@ -104,7 +104,7 @@ static struct option basic_options[] = {
{"test", no_argument, NULL, 'T'},
{"all-options", no_argument, NULL, 'A'},
{"version", no_argument, NULL, 'V'},
{"buffer-size", optional_argument, NULL, 'B'},
{"buffer-size", required_argument, NULL, 'B'},
{"batch", optional_argument, NULL, 'b'},
{"batch-count", required_argument, NULL, OPTION_BATCH_COUNT},
{"batch-start", required_argument, NULL, OPTION_BATCH_START_AT},
@ -126,29 +126,30 @@ static struct option basic_options[] = {
#define OUTPUT_JPEG 4
#define OUTPUT_PDF 5
#define BASE_OPTSTRING "d:hi:Lf:o:B::nvVTAbp"
#define BASE_OPTSTRING "d:hi:Lf:o:B:nvVTAbp"
#define STRIP_HEIGHT 256 /* # lines we increment image height */
static struct option *all_options;
static int option_number_len;
static int *option_number;
static SANE_Handle device;
static int verbose;
static struct option *all_options = NULL;
static int option_number_len = 0;
static int *option_number = 0;
static SANE_Handle device = 0;
static int verbose = 0;
static int progress = 0;
static const char* output_file = NULL;
static int test;
static int all;
static int test = 0;
static int all = 0;
static int output_format = OUTPUT_UNKNOWN;
static int help;
static int help = 0;
static int dont_scan = 0;
static const char *prog_name;
static const char *prog_name = NULL;
static int resolution_optind = -1, resolution_value = 0;
/* window (area) related options */
static SANE_Option_Descriptor window_option[4]; /*updated descs for x,y,l,t*/
static int window[4]; /*index into backend options for x,y,l,t*/
static SANE_Word window_val[2]; /*the value for x,y options*/
static int window_val_user[2]; /* is x,y user-specified? */
static SANE_Option_Descriptor window_option[4] = {0}; /*updated descs for x,y,l,t*/
static int window[4] = {0}; /*index into backend options for x,y,l,t*/
static SANE_Word window_val[2] = {0}; /*the value for x,y options*/
static int window_val_user[2] = {0}; /* is x,y user-specified? */
static char *full_optstring = NULL;
static int accept_only_md5_auth = 0;
static const char *icc_profile = NULL;
@ -160,18 +161,16 @@ static SANE_Word tl_x = 0;
static SANE_Word tl_y = 0;
static SANE_Word br_x = 0;
static SANE_Word br_y = 0;
static SANE_Byte *buffer;
static size_t buffer_size;
static SANE_Byte *buffer = NULL;
static size_t buffer_size = 0;
static void
auth_callback (SANE_String_Const resource,
SANE_Char * username, SANE_Char * password)
{
char tmp[3 + 128 + SANE_MAX_USERNAME_LEN + SANE_MAX_PASSWORD_LEN], *wipe;
unsigned char md5digest[16];
char tmp[3 + 128 + SANE_MAX_USERNAME_LEN + SANE_MAX_PASSWORD_LEN];
int md5mode = 0, len, query_user = 1;
FILE *pass_file;
struct stat stat_buf;
char * uname = NULL;
@ -195,6 +194,7 @@ auth_callback (SANE_String_Const resource,
}
else
{
FILE *pass_file;
if ((pass_file = fopen (tmp, "r")) != NULL)
{
@ -284,6 +284,7 @@ auth_callback (SANE_String_Const resource,
if (query_user == 1)
{
#ifdef HAVE_GETPASS
char *wipe;
strcpy (password, (wipe = getpass ("Enter password: ")));
memset (wipe, 0, strlen (password));
#else
@ -293,6 +294,7 @@ auth_callback (SANE_String_Const resource,
if (md5mode)
{
unsigned char md5digest[16];
sprintf (tmp, "%.128s%.*s", (strstr (resource, "$MD5$")) + 5,
SANE_MAX_PASSWORD_LEN - 1, password);
@ -316,10 +318,10 @@ auth_callback (SANE_String_Const resource,
static void
sighandler (int signum)
{
static SANE_Bool first_time = SANE_TRUE;
if (device)
{
static SANE_Bool first_time = SANE_TRUE;
fprintf (stderr, "%s: received signal %d\n", prog_name, signum);
if (first_time)
{
@ -1203,18 +1205,17 @@ write_png_header (SANE_Frame format, int width, int height, int depth, int dpi,
/* There are nominally 39.3700787401575 inches in a meter. */
const double pixels_per_meter = dpi * 39.3700787401575;
size_t icc_size = 0;
void *icc_buffer;
*png_ptr = png_create_write_struct
(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!*png_ptr) {
fprintf(stderr, "png_create_write_struct failed\n");
exit(1);
scanimage_exit (1);
}
*info_ptr = png_create_info_struct(*png_ptr);
if (!*info_ptr) {
fprintf(stderr, "png_create_info_struct failed\n");
exit(1);
scanimage_exit (1);
}
png_init_io(*png_ptr, ofp);
@ -1242,7 +1243,7 @@ write_png_header (SANE_Frame format, int width, int height, int depth, int dpi,
if (icc_profile)
{
icc_buffer = sanei_load_icc_profile(icc_profile, &icc_size);
void *icc_buffer = sanei_load_icc_profile(icc_profile, &icc_size);
if (icc_size > 0)
{
/* libpng will abort if the profile and image colour spaces do not match*/
@ -1632,11 +1633,11 @@ scan_it (FILE *ofp, void* pw)
#ifdef HAVE_LIBPNG
if (output_format == OUTPUT_PNG)
{
int i = 0;
int idx = 0;
int left = len;
while(pngrow + left >= parm.bytes_per_line)
{
memcpy(pngbuf + pngrow, buffer + i, parm.bytes_per_line - pngrow);
memcpy(pngbuf + pngrow, buffer + idx, parm.bytes_per_line - pngrow);
if(parm.depth == 1)
{
int j;
@ -1659,11 +1660,11 @@ scan_it (FILE *ofp, void* pw)
}
#endif
png_write_row(png_ptr, pngbuf);
i += parm.bytes_per_line - pngrow;
idx += parm.bytes_per_line - pngrow;
left -= parm.bytes_per_line - pngrow;
pngrow = 0;
}
memcpy(pngbuf + pngrow, buffer + i, left);
memcpy(pngbuf + pngrow, buffer + idx, left);
pngrow += left;
}
else
@ -1671,28 +1672,28 @@ scan_it (FILE *ofp, void* pw)
#ifdef HAVE_LIBJPEG
if (output_format == OUTPUT_JPEG || output_format == OUTPUT_PDF)
{
int i = 0;
int idx = 0;
int left = len;
while(jpegrow + left >= parm.bytes_per_line)
{
memcpy(jpegbuf + jpegrow, buffer + i, parm.bytes_per_line - jpegrow);
memcpy(jpegbuf + jpegrow, buffer + idx, parm.bytes_per_line - jpegrow);
if(parm.depth == 1)
{
int col1, col8;
JSAMPLE *buf8 = malloc(parm.bytes_per_line * 8);
for(col1 = 0; col1 < parm.bytes_per_line; col1++)
for(col8 = 0; col8 < 8; col8++)
buf8[col1 * 8 + col8] = jpegbuf[col1] & (1 << (8 - col8 - 1)) ? 0 : 0xff;
buf8[col1 * 8 + col8] = (jpegbuf[col1] & (1 << (8 - col8 - 1))) ? 0 : 0xff;
jpeg_write_scanlines(&cinfo, &buf8, 1);
free(buf8);
} else {
jpeg_write_scanlines(&cinfo, &jpegbuf, 1);
}
i += parm.bytes_per_line - jpegrow;
idx += parm.bytes_per_line - jpegrow;
left -= parm.bytes_per_line - jpegrow;
jpegrow = 0;
}
memcpy(jpegbuf + jpegrow, buffer + i, left);
memcpy(jpegbuf + jpegrow, buffer + idx, left);
jpegrow += left;
}
else
@ -1702,7 +1703,7 @@ scan_it (FILE *ofp, void* pw)
else
{
#if !defined(WORDS_BIGENDIAN)
int i, start = 0;
int start = 0;
/* check if we have saved one byte from the last sane_read */
if (hang_over > -1)
@ -1716,12 +1717,12 @@ scan_it (FILE *ofp, void* pw)
}
}
/* now do the byte-swapping */
for (i = start; i < (len - 1); i += 2)
for (int idx = start; idx < (len - 1); idx += 2)
{
unsigned char LSB;
LSB = buffer[i];
buffer[i] = buffer[i + 1];
buffer[i + 1] = LSB;
LSB = buffer[idx];
buffer[idx] = buffer[idx + 1];
buffer[idx + 1] = LSB;
}
/* check if we have an odd number of bytes */
if (((len - start) % 2) != 0)
@ -1790,13 +1791,12 @@ scan_it (FILE *ofp, void* pw)
/* FIXME: other bit depths? */
if (output_format != OUTPUT_TIFF && parm.depth == 16)
{
int i;
for (i = 0; i < image.height * image.width; i += 2)
for (int idx = 0; idx < image.height * image.width; idx += 2)
{
unsigned char LSB;
LSB = image.data[i];
image.data[i] = image.data[i + 1];
image.data[i + 1] = LSB;
LSB = image.data[idx];
image.data[idx] = image.data[idx + 1];
image.data[idx + 1] = LSB;
}
}
#endif
@ -2003,6 +2003,8 @@ scanimage_exit (int status)
fprintf (stderr, "Calling sane_exit\n");
sane_exit ();
if (full_optstring)
free(full_optstring);
if (all_options)
free (all_options);
if (option_number)
@ -2020,15 +2022,12 @@ scanimage_exit (int status)
*/
static void print_options(SANE_Device * device, SANE_Int num_dev_options, SANE_Bool ro)
{
int i, j;
const SANE_Option_Descriptor *opt;
for (i = 1; i < num_dev_options; ++i)
for (int i = 1; i < num_dev_options; ++i)
{
opt = 0;
const SANE_Option_Descriptor *opt = 0;
/* scan area uses modified option struct */
for (j = 0; j < 4; ++j)
for (int j = 0; j < 4; ++j)
if (i == window[j])
opt = window_option + j;
@ -2079,16 +2078,13 @@ static int guess_output_format(const char* output_file)
}
}
// it would be very confusing if user makes a typo in the filename and the output format changes.
// This is most likely not what the user wanted.
fprintf(stderr, "Could not guess output format from the given path and no --format given.\n");
exit(1);
return OUTPUT_UNKNOWN;
}
int
main (int argc, char **argv)
{
int ch, i, index, all_options_len;
int ch, index;
const SANE_Device **device_list;
SANE_Int num_dev_options = 0;
const char *devname = 0;
@ -2102,12 +2098,11 @@ main (int argc, char **argv)
int batch_increment = 1;
int promptc;
SANE_Status status;
char *full_optstring;
SANE_Int version_code;
void *pw = NULL;
FILE *ofp = NULL;
buffer_size = (32 * 1024); /* default size */
buffer_size = (1024 * 1024); /* default size */
prog_name = strrchr (argv[0], '/');
if (prog_name)
@ -2154,10 +2149,7 @@ main (int argc, char **argv)
output_file = optarg;
break;
case 'B':
if (optarg)
buffer_size = 1024 * atoi(optarg);
else
buffer_size = (1024 * 1024);
buffer_size = 1024 * atoi(optarg);
break;
case 'T':
test = 1;
@ -2196,7 +2188,7 @@ main (int argc, char **argv)
output_format = OUTPUT_PNG;
#else
fprintf(stderr, "PNG support not compiled in\n");
exit(1);
scanimage_exit (1);
#endif
}
else if (strcmp (optarg, "jpeg") == 0)
@ -2205,7 +2197,7 @@ main (int argc, char **argv)
output_format = OUTPUT_JPEG;
#else
fprintf(stderr, "JPEG support not compiled in\n");
exit(1);
scanimage_exit (1);
#endif
}
else if (strcmp (optarg, "pdf") == 0)
@ -2214,7 +2206,7 @@ main (int argc, char **argv)
output_format = OUTPUT_PDF;
#else
fprintf(stderr, "PDF support not compiled in\n");
exit(1);
scanimage_exit (1);
#endif
}
else if (strcmp (optarg, "pnm") == 0)
@ -2232,7 +2224,7 @@ main (int argc, char **argv)
fprintf(stderr, ", jpeg");
#endif
fprintf(stderr, ".\n");
exit(1);
scanimage_exit (1);
}
break;
case OPTION_MD5:
@ -2262,14 +2254,14 @@ main (int argc, char **argv)
}
else
{
int i = 0, int_arg = 0;
const char *percent, *start;
int int_arg = 0;
const char *percent;
const char *text_arg = 0;
char ftype;
for (i = 0; device_list[i]; ++i)
for (int dev_num = 0; device_list[dev_num]; ++dev_num)
{
start = optarg;
const char *start = optarg;
while (*start && (percent = strchr (start, '%')))
{
int start_len = percent - start;
@ -2279,23 +2271,23 @@ main (int argc, char **argv)
switch (*percent)
{
case 'd':
text_arg = device_list[i]->name;
text_arg = device_list[dev_num]->name;
ftype = 's';
break;
case 'v':
text_arg = device_list[i]->vendor;
text_arg = device_list[dev_num]->vendor;
ftype = 's';
break;
case 'm':
text_arg = device_list[i]->model;
text_arg = device_list[dev_num]->model;
ftype = 's';
break;
case 't':
text_arg = device_list[i]->type;
text_arg = device_list[dev_num]->type;
ftype = 's';
break;
case 'i':
int_arg = i;
int_arg = dev_num;
ftype = 'i';
break;
case 'n':
@ -2407,12 +2399,20 @@ Parameters are separated by a blank from single-character options (e.g.\n\
if (batch && output_file != NULL)
{
fprintf(stderr, "--batch and --output-file can't be used together.\n");
exit(1);
scanimage_exit (1);
}
if (output_format == OUTPUT_UNKNOWN)
output_format = guess_output_format(output_file);
{
output_format = guess_output_format(output_file);
if (output_format == OUTPUT_UNKNOWN)
{
// it would be very confusing if user makes a typo in the filename and the output format changes.
// This is most likely not what the user wanted.
fprintf(stderr, "Could not guess output format from the given path and no --format given.\n");
scanimage_exit (1);
}
}
if (!devname)
{
/* If no device name was specified explicitly, we look at the
@ -2480,7 +2480,7 @@ Parameters are separated by a blank from single-character options (e.g.\n\
}
/* malloc global option lists */
all_options_len = num_dev_options + NELEMS (basic_options) + 1;
int all_options_len = num_dev_options + NELEMS (basic_options) + 1;
all_options = malloc (all_options_len * sizeof (all_options[0]));
option_number_len = num_dev_options;
option_number = malloc (option_number_len * sizeof (option_number[0]));
@ -2585,6 +2585,7 @@ Parameters are separated by a blank from single-character options (e.g.\n\
}
free (full_optstring);
full_optstring = NULL;
/* convert x/y to br_x/br_y */
for (index = 0; index < 2; ++index)
@ -2630,7 +2631,7 @@ List of available devices:", prog_name);
{
int column = 80;
for (i = 0; device_list[i]; ++i)
for (int i = 0; device_list[i]; ++i)
{
if (column + strlen (device_list[i]->name) + 1 >= 80)
{
@ -2747,13 +2748,12 @@ List of available devices:", prog_name);
if (output_format != OUTPUT_PDF)
#endif
strcat (part_path, ".part");
}
if (batch)
{
if (batch_prompt)
{
char readbuf[2];
char *readbuf2;
fprintf (stderr, "Place document no. %d on the scanner.\n",
n);
fprintf (stderr, "Press <RETURN> to continue.\n");

Wyświetl plik

@ -57,11 +57,11 @@ sanei_w_space (Wire * w, size_t howmuch)
int fd = w->io.fd;
ssize_t nread, nwritten;
DBG (3, "sanei_w_space: %lu bytes for wire %d\n", (u_long) howmuch, fd);
DBG (3, "sanei_w_space: %zu bytes for wire %d\n", howmuch, fd);
if (howmuch > w->buffer.size)
DBG (2, "sanei_w_space: bigger than buffer (%lu bytes), "
"may be flush()\n", (u_long) w->buffer.size);
DBG (2, "sanei_w_space: bigger than buffer (%zu bytes), "
"may be flush()\n", w->buffer.size);
if (w->status != 0)
{
@ -72,15 +72,15 @@ sanei_w_space (Wire * w, size_t howmuch)
if (w->buffer.curr + howmuch > w->buffer.end)
{
DBG (4, "sanei_w_space: free buffer size is %lu\n",
(u_long) (w->buffer.end - w->buffer.curr));
DBG (4, "sanei_w_space: free buffer size is %zu\n",
(w->buffer.end - w->buffer.curr));
switch (w->direction)
{
case WIRE_ENCODE:
nbytes = w->buffer.curr - w->buffer.start;
w->buffer.curr = w->buffer.start;
DBG (4, "sanei_w_space: ENCODE: sending %lu bytes\n",
(u_long) nbytes);
DBG (4, "sanei_w_space: ENCODE: sending %zu bytes\n",
nbytes);
while (nbytes > 0)
{
nwritten = (*w->io.write) (fd, w->buffer.curr, nbytes);
@ -95,8 +95,8 @@ sanei_w_space (Wire * w, size_t howmuch)
}
w->buffer.curr = w->buffer.start;
w->buffer.end = w->buffer.start + w->buffer.size;
DBG (4, "sanei_w_space: ENCODE: free buffer is now %lu\n",
(u_long) w->buffer.size);
DBG (4, "sanei_w_space: ENCODE: free buffer is now %zu\n",
w->buffer.size);
break;
case WIRE_DECODE:
@ -110,8 +110,8 @@ sanei_w_space (Wire * w, size_t howmuch)
if (left_over)
{
DBG (4, "sanei_w_space: DECODE: %lu bytes left in buffer\n",
(u_long) left_over);
DBG (4, "sanei_w_space: DECODE: %zu bytes left in buffer\n",
left_over);
memmove (w->buffer.start, w->buffer.curr, left_over);
}
w->buffer.curr = w->buffer.start;
@ -135,8 +135,8 @@ sanei_w_space (Wire * w, size_t howmuch)
w->buffer.end += nread;
}
while (left_over < howmuch);
DBG (4, "sanei_w_space: DECODE: %lu bytes read\n",
(u_long) (w->buffer.end - w->buffer.start));
DBG (4, "sanei_w_space: DECODE: %zu bytes read\n",
(size_t)(w->buffer.end - w->buffer.start));
break;
case WIRE_FREE:
@ -161,8 +161,8 @@ sanei_w_array (Wire * w, SANE_Word * len_ptr, void **v,
char *val;
int i;
DBG (3, "sanei_w_array: wire %d, elements of size %lu\n", w->io.fd,
(u_long) element_size);
DBG (3, "sanei_w_array: wire %d, elements of size %zu\n", w->io.fd,
element_size);
if (w->direction == WIRE_FREE)
{
@ -250,8 +250,8 @@ sanei_w_ptr (Wire * w, void **v, WireCodecFunc w_value, size_t value_size)
{
SANE_Word is_null;
DBG (3, "sanei_w_ptr: wire %d, value pointer at is %lu bytes\n", w->io.fd,
(u_long) value_size);
DBG (3, "sanei_w_ptr: wire %d, value pointer at is %zu bytes\n", w->io.fd,
value_size);
if (w->direction == WIRE_FREE)
{
@ -583,8 +583,8 @@ sanei_w_set_dir (Wire * w, WireDirection dir)
w->direction == WIRE_ENCODE ? "ENCODE" :
(w->direction == WIRE_DECODE ? "DECODE" : "FREE"));
if (w->direction == WIRE_DECODE && w->buffer.curr != w->buffer.end)
DBG (1, "sanei_w_set_dir: WARNING: will delete %lu bytes from buffer\n",
(u_long) (w->buffer.end - w->buffer.curr));
DBG (1, "sanei_w_set_dir: WARNING: will delete %zu bytes from buffer\n",
(size_t) (w->buffer.end - w->buffer.curr));
flush (w);
w->direction = dir;
DBG (4, "sanei_w_set_dir: direction changed\n");