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--

Reply via email to