[sane-devel] [RFC] [PATCH] scanadf [ -p | --pipe ] option
Rene Rebe
rene@exactcode.de
Mon Jul 11 11:40:17 UTC 2005
This is a multi-part message in MIME format.
--------------020904010307030204030801
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 8bit
Hi all,
for some high-speed scanning with on-the-fly format conversion or other
post-processing it would be handy to pass the data to the scanadf script
thru a pipe.
The attached patch implements this.
It also changes to wait(pid) for the script in any case as well as not
ignore SIGCHLD - one of those interacted badly with my avision backend.
I'll review the details before a possible commit.
Any comments?
Yours,
--
René Rebe - Rubensstr. 64 - 12157 Berlin (Europe / Germany)
http://www.exactcode.de/ | http://www.t2-project.org/
+49 (0)30 255 897 45
--------------020904010307030204030801
Content-Type: text/plain;
name="scanadf.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="scanadf.patch"
diff -ur sane-frontends-1.0.13/doc/scanadf.man sane-frontends-1.0.13-adfmod/doc/scanadf.man
--- sane-frontends-1.0.13/doc/scanadf.man 2004-07-09 19:02:37.000000000 +0200
+++ sane-frontends-1.0.13-adfmod/doc/scanadf.man 2005-07-11 12:42:35.000000000 +0200
@@ -19,6 +19,7 @@
.IR num ]
.RB [ -e | --end-count
.IR num ]
+.RB [ -p | --pipe ]
.RB [ -r | --raw ]
.RI [ device-specific-options ]
.SH DESCRIPTION
@@ -191,6 +192,16 @@
optional frame types and the default handling of unrecognized
frametypes, this option becomes less and less useful.
+The
+.B -p
+or
+.B --pipe
+option allows passing the image date to the scan-script via a pipe
+rather than saving it to a file and executing the script thereafter.
+It might be useful for high-performance batch scans that should do
+post-processing, such as format convertion, on-the-fly.
+
+.PP
As you might imagine, much of the power of
.B scanadf
comes from the fact that it can control any SANE backend. Thus, the
@@ -242,6 +253,10 @@
work at this time are:
.RS
+.br
+.B sane-avision
+- Avision (and compatible) scanners. For batch scanning the --source "ADF",
+"ADF Rear" or "ADF Duplex" should be used.
.br
.B sane-bh
- Bell+Howell Copiscan II series scanners.
diff -ur sane-frontends-1.0.13/src/scanadf.c sane-frontends-1.0.13-adfmod/src/scanadf.c
--- sane-frontends-1.0.13/src/scanadf.c 2004-07-09 19:03:16.000000000 +0200
+++ sane-frontends-1.0.13-adfmod/src/scanadf.c 2005-07-11 12:33:58.000000000 +0200
@@ -4,6 +4,7 @@
scanimage by Andreas Beck and David Mosberger
Copyright (C) 1999 Tom Martone
+ Copyright (C) 2005 Rene Rebe ([ -p | --pipe] script option)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -39,6 +40,7 @@
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/wait.h>
#include "sane/sane.h"
#include "sane/sanei.h"
@@ -103,10 +105,11 @@
{ "end-count", required_argument, 0, 'e' },
{ "scan-script", required_argument, 0, 'S' },
{ "raw", no_argument, 0, 'r' },
+ { "pipe", no_argument, 0, 'p' },
{0, }
};
-#define BASE_OPTSTRING "d:hLvVNTo:s:e:S:r"
+#define BASE_OPTSTRING "d:hLvVNTo:s:e:S:pr"
#define STRIP_HEIGHT 256 /* # lines we increment image height */
static struct option * all_options;
@@ -872,8 +875,85 @@
return res;
}
+static int
+exec_script (const char *script, const char* fname, SANE_Bool use_pipe,
+ SANE_Parameters *parm, int *fd)
+{
+ static char cmd[PATH_MAX * 2];
+ static char env[6][PATH_MAX * 2];
+ int pid;
+ SANE_Int res;
+ SANE_Frame format;
+ extern char **environ;
+ int pipefd[2];
+
+ res = get_resolution(device);
+
+ format = parm->format;
+ if (format == SANE_FRAME_RED ||
+ format == SANE_FRAME_GREEN ||
+ format == SANE_FRAME_BLUE)
+ {
+ /* the resultant format is RGB */
+ format = SANE_FRAME_RGB;
+ }
+
+ sprintf(env[0], "SCAN_RES=%d", res);
+ if (putenv(env[0]))
+ fprintf(stderr, "putenv:failed\n");
+ sprintf(env[1], "SCAN_WIDTH=%d", parm->pixels_per_line);
+ if (putenv(env[1]))
+ fprintf(stderr, "putenv:failed\n");
+ sprintf(env[2], "SCAN_HEIGHT=%d", parm->lines);
+ if (putenv(env[2]))
+ fprintf(stderr, "putenv:failed\n");
+ sprintf(env[3], "SCAN_FORMAT_ID=%d", (int) parm->format);
+ if (putenv(env[3]))
+ fprintf(stderr, "putenv:failed\n");
+ sprintf(env[4], "SCAN_FORMAT=%s",
+ sane_strframe(parm->format));
+ if (putenv(env[4]))
+ fprintf(stderr, "putenv:failed\n");
+ sprintf(env[5], "SCAN_DEPTH=%d", parm->depth);
+ if (putenv(env[5]))
+ fprintf(stderr, "putenv:failed\n");
+
+ if (use_pipe) {
+ pipe(pipefd);
+ }
+
+ /*signal(SIGCHLD, SIG_IGN);*/
+ switch ((pid = fork()))
+ {
+ case -1:
+ /* fork failed */
+ fprintf(stderr, "Error forking: %s (%d)\n", strerror(errno), errno);
+ break;
+
+ case 0:
+ /* in child process */
+ if (use_pipe) {
+ dup2(pipefd[0],0); close(pipefd[0]); close(pipefd[1]);
+ }
+ sprintf(cmd, "%s '%s'", script, fname);
+ execle(script, script, fname, NULL, environ);
+ exit(0);
+
+ default:
+ if (verbose)
+ fprintf(stderr, "Started script `%s' as pid=%d\n", script, pid);
+ break;
+ }
+ if (use_pipe) {
+ close(pipefd[0]);
+ *fd = pipefd[1];
+ }
+ return pid;
+}
+
static SANE_Status
-scan_it_raw (const char *fname, SANE_Bool raw, const char *script)
+scan_it_raw (const char *fname, SANE_Bool raw, const char *script,
+ SANE_Bool use_pipe)
{
int i, len, first_frame = 1, offset = 0, must_buffer = 0;
SANE_Byte buffer[32*1024], min = 0xff, max = 0;
@@ -881,6 +961,7 @@
SANE_Status status;
Image image = {0, };
FILE *fp = NULL;
+ int pid = 0;
do
{
@@ -903,7 +984,15 @@
goto cleanup;
}
- fp = fopen(fname, "wb");
+ if (script && use_pipe)
+ {
+ int fd = 0;
+ pid = exec_script(script, fname, use_pipe, &parm, &fd);
+ fp = fdopen (fd, "wb");
+ }
+ else
+ fp = fopen(fname, "wb");
+
if (!fp) {
fprintf(stderr, "Error opening output `%s': %s (%d)\n",
fname, strerror(errno), errno);
@@ -1144,65 +1233,16 @@
fp = NULL;
}
- if (script)
- {
- static char cmd[PATH_MAX * 2];
- static char env[6][PATH_MAX * 2];
- int pid;
- SANE_Int res;
- SANE_Frame format;
- extern char **environ;
-
- res = get_resolution(device);
-
- format = parm.format;
- if (format == SANE_FRAME_RED ||
- format == SANE_FRAME_GREEN ||
- format == SANE_FRAME_BLUE)
- {
- /* the resultant format is RGB */
- format = SANE_FRAME_RGB;
- }
- sprintf(env[0], "SCAN_RES=%d", res);
- if (putenv(env[0]))
- fprintf(stderr, "putenv:failed\n");
- sprintf(env[1], "SCAN_WIDTH=%d", parm.pixels_per_line);
- if (putenv(env[1]))
- fprintf(stderr, "putenv:failed\n");
- sprintf(env[2], "SCAN_HEIGHT=%d", parm.lines);
- if (putenv(env[2]))
- fprintf(stderr, "putenv:failed\n");
- sprintf(env[3], "SCAN_FORMAT_ID=%d", (int) parm.format);
- if (putenv(env[3]))
- fprintf(stderr, "putenv:failed\n");
- sprintf(env[4], "SCAN_FORMAT=%s",
- sane_strframe(parm.format));
- if (putenv(env[4]))
- fprintf(stderr, "putenv:failed\n");
- sprintf(env[5], "SCAN_DEPTH=%d", parm.depth);
- if (putenv(env[5]))
- fprintf(stderr, "putenv:failed\n");
- signal(SIGCHLD, SIG_IGN);
- switch ((pid = fork()))
- {
- case -1:
- /* fork failed */
- fprintf(stderr, "Error forking: %s (%d)\n", strerror(errno), errno);
- break;
+ if (script && !use_pipe)
+ pid = exec_script (script, fname, use_pipe, &parm, NULL);
- case 0:
- /* in child process */
- sprintf(cmd, "%s '%s'", script, fname);
- /* system(cmd); */
- execle(script, script, fname, NULL, environ);
- exit(0);
-
- default:
- if (verbose)
- fprintf(stderr, "Started script `%s' as pid=%d\n", script, pid);
- break;
- }
- }
+ if (script) {
+ int exit_status = 0;
+ waitpid (pid, &exit_status, 0);
+ if (exit_status && verbose)
+ fprintf(stderr, "%s: WARNING: child exited with %d\n",
+ prog_name, exit_status);
+ }
cleanup:
if (image.data)
@@ -1213,7 +1253,8 @@
}
static SANE_Int
-scan_docs (int start, int end, int no_overwrite, SANE_Bool raw, const char *outfmt, const char *script)
+scan_docs (int start, int end, int no_overwrite, SANE_Bool raw,
+ const char *outfmt, const char *script, SANE_Bool use_pipe)
{
SANE_Status status = SANE_STATUS_GOOD;
SANE_Int scannedPages = 0;
@@ -1223,8 +1264,7 @@
while (end < 0 || start <= end)
{
- /*!!! buffer overflow; need protection */
- sprintf(fname, outfmt, start);
+ snprintf(fname, sizeof (fname), outfmt, start);
/* does the filename already exist? */
if (no_overwrite)
@@ -1239,7 +1279,7 @@
/* Scan the document */
if (status == SANE_STATUS_GOOD)
- status = scan_it_raw(fname, raw, script);
+ status = scan_it_raw(fname, raw, script, use_pipe);
/* Any scan errors? */
if (status == SANE_STATUS_NO_DOCS)
@@ -1280,6 +1320,7 @@
SANE_Status status;
char *full_optstring;
SANE_Bool raw = SANE_FALSE;
+ SANE_Bool use_pipe = SANE_FALSE;
const char *scanScript = NULL; /* script to run at end of scan */
const char *outputFile = "image-%04d"; /* file name(format) to write output to */
int startNum = 1, endNum = -1; /* start/end numbers of pages to scan */
@@ -1338,6 +1379,7 @@
case 's': startNum = atoi(optarg); break;
case 'e': endNum = atoi(optarg); break;
case 'r': raw = SANE_TRUE; break;
+ case 'p': use_pipe = SANE_TRUE; break;
case 'V':
printf ("scanadf (%s) %s\n", PACKAGE, VERSION);
@@ -1455,7 +1497,7 @@
exit (1); /* error message is printed by getopt_long() */
case 'd': case 'h': case 'v': case 'V': case 'T':
- case 'o': case 'S': case 's': case 'e': case 'r':
+ case 'o': case 'S': case 's': case 'e': case 'p': case 'r':
/* previously handled options */
break;
@@ -1569,7 +1611,8 @@
signal (SIGPIPE, sighandler);
signal (SIGTERM, sighandler);
- status = scan_docs (startNum, endNum, no_overwrite, raw, outputFile, scanScript);
+ status = scan_docs (startNum, endNum, no_overwrite, raw,
+ outputFile, scanScript, use_pipe);
sane_cancel (device);
sane_close (device);
--------------020904010307030204030801--
More information about the sane-devel
mailing list