diff options
Diffstat (limited to 'frontend/scanimage.c')
| -rw-r--r-- | frontend/scanimage.c | 212 | 
1 files changed, 149 insertions, 63 deletions
| diff --git a/frontend/scanimage.c b/frontend/scanimage.c index fe02750..ae65ebf 100644 --- a/frontend/scanimage.c +++ b/frontend/scanimage.c @@ -2,7 +2,7 @@     Uses the SANE library.     Copyright (C) 2015 Rolf Bensch <rolf at bensch hyphen online dot de>     Copyright (C) 1996, 1997, 1998 Andreas Beck and David Mosberger -    +     Copyright (C) 1999 - 2009 by the SANE Project -- See AUTHORS and ChangeLog     for details. @@ -32,6 +32,7 @@  #include <assert.h>  #include "lgetopt.h" +#include <inttypes.h>  #include <signal.h>  #include <stdio.h>  #include <stdlib.h> @@ -93,6 +94,7 @@ static struct option basic_options[] = {    {"help", no_argument, NULL, 'h'},    {"verbose", no_argument, NULL, 'v'},    {"progress", no_argument, NULL, 'p'}, +  {"output-file", required_argument, NULL, 'o'},    {"test", no_argument, NULL, 'T'},    {"all-options", no_argument, NULL, 'A'},    {"version", no_argument, NULL, 'V'}, @@ -111,12 +113,13 @@ static struct option basic_options[] = {    {0, 0, NULL, 0}  }; -#define OUTPUT_PNM      0 -#define OUTPUT_TIFF     1 -#define OUTPUT_PNG      2 -#define OUTPUT_JPEG     3 +#define OUTPUT_UNKNOWN  0 +#define OUTPUT_PNM      1 +#define OUTPUT_TIFF     2 +#define OUTPUT_PNG      3 +#define OUTPUT_JPEG     4 -#define BASE_OPTSTRING	"d:hi:Lf: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; @@ -125,9 +128,10 @@ static int *option_number;  static SANE_Handle device;  static int verbose;  static int progress = 0; +static const char* output_file = NULL;  static int test;  static int all; -static int output_format = OUTPUT_PNM; +static int output_format = OUTPUT_UNKNOWN;  static int help;  static int dont_scan = 0;  static const char *prog_name; @@ -201,51 +205,30 @@ auth_callback (SANE_String_Const resource,  		  if ((strlen (tmp) > 0) && (tmp[strlen (tmp) - 1] == '\r'))  		    tmp[strlen (tmp) - 1] = 0; -		  if (strchr (tmp, ':') != NULL) +		  char *colon1 = strchr (tmp, ':'); +		  if (colon1 != NULL)  		    { +		      char *tmp_username = tmp; +		      *colon1 = '\0'; -		      if (strchr (strchr (tmp, ':') + 1, ':') != NULL) +		      char *colon2 = strchr (colon1 + 1, ':'); +		      if (colon2 != NULL)  			{ +			  char *tmp_password = colon1 + 1; +			  *colon2 = '\0'; -			  if ((strncmp -			       (strchr (strchr (tmp, ':') + 1, ':') + 1, -				resource, len) == 0) -			      && -			      ((int) strlen -			       (strchr (strchr (tmp, ':') + 1, ':') + 1) == -			       len)) +			  if ((strncmp (colon2 + 1, resource, len) == 0) +			      && ((int) strlen (colon2 + 1) == len))  			    { - -			      if ((strchr (tmp, ':') - tmp) < -				  SANE_MAX_USERNAME_LEN) -				{ - -				  if ((strchr (strchr (tmp, ':') + 1, ':') - -				       (strchr (tmp, ':') + 1)) < -				      SANE_MAX_PASSWORD_LEN) -				    { - -				      strncpy (username, tmp, -					       strchr (tmp, ':') - tmp); - -				      username[strchr (tmp, ':') - tmp] = 0; - -				      strncpy (password, -					       strchr (tmp, ':') + 1, -					       strchr (strchr (tmp, ':') + 1, -						       ':') - -					       (strchr (tmp, ':') + 1)); -				      password[strchr -					       (strchr (tmp, ':') + 1, -						':') - (strchr (tmp, -								':') + 1)] = -					0; - -				      query_user = 0; -				      break; -				    } -				} - +			      if ((strlen (tmp_username) < SANE_MAX_USERNAME_LEN) && +                                  (strlen (tmp_password) < SANE_MAX_PASSWORD_LEN)) +                                { +                                  strncpy (username, tmp_username, SANE_MAX_USERNAME_LEN); +                                  strncpy (password, tmp_password, SANE_MAX_PASSWORD_LEN); + +                                  query_user = 0; +                                  break; +                                }  			    }  			}  		    } @@ -403,7 +386,7 @@ print_option (SANE_Device * device, int opt_num, const SANE_Option_Descriptor *o    }*/    /* if one of these three is not set, option is useless, skip it */ -  if(!(opt->cap &  +  if(!(opt->cap &     (SANE_CAP_SOFT_SELECT | SANE_CAP_HARD_SELECT | SANE_CAP_SOFT_DETECT)    )){      return; @@ -462,7 +445,7 @@ print_option (SANE_Device * device, int opt_num, const SANE_Option_Descriptor *o  	      if (!strcmp (opt->name, "x"))  		{  		  printf ("%d..%d", -                          opt->constraint.range->min,  +                          opt->constraint.range->min,                            opt->constraint.range->max - tl_x);  		}  	      else if (!strcmp (opt->name, "y")) @@ -1011,7 +994,7 @@ set_option (SANE_Handle device, int optnum, void *valuep)  		 prog_name, opt->name);        return;      } -     +    if (opt->size == sizeof (SANE_Word) && opt->type != SANE_TYPE_STRING)      orig = *(SANE_Word *) valuep; @@ -1314,7 +1297,8 @@ advance (Image * image)  static SANE_Status  scan_it (FILE *ofp)  { -  int i, len, first_frame = 1, offset = 0, must_buffer = 0, hundred_percent; +  int i, len, first_frame = 1, offset = 0, must_buffer = 0; +  uint64_t hundred_percent = 0;    SANE_Byte min = 0xff, max = 0;    SANE_Parameters parm;    SANE_Status status; @@ -1322,7 +1306,7 @@ scan_it (FILE *ofp)    static const char *format_name[] = {      "gray", "RGB", "red", "green", "blue"    }; -  SANE_Word total_bytes = 0, expected_bytes; +  uint64_t total_bytes = 0, expected_bytes;    SANE_Int hang_over = -1;  #ifdef HAVE_LIBPNG    int pngrow = 0; @@ -1483,7 +1467,7 @@ scan_it (FILE *ofp)  	  offset = parm.format - SANE_FRAME_RED;  	  image.x = image.y = 0;  	} -      hundred_percent = parm.bytes_per_line * parm.lines  +      hundred_percent = ((uint64_t)parm.bytes_per_line) * parm.lines  	* ((parm.format == SANE_FRAME_RGB || parm.format == SANE_FRAME_GRAY) ? 1:3);        while (1) @@ -1495,7 +1479,12 @@ scan_it (FILE *ofp)            if (progr > 100.)  	    progr = 100.;            if (progress) -	    fprintf (stderr, "Progress: %3.1f%%\r", progr); +            { +              if (parm.lines >= 0) +                fprintf(stderr, "Progress: %3.1f%%\r", progr); +              else +                fprintf(stderr, "Progress: (unknown)\r"); +            }  	  if (status != SANE_STATUS_GOOD)  	    { @@ -1757,7 +1746,7 @@ cleanup:      free (image.data); -  expected_bytes = parm.bytes_per_line * parm.lines * +  expected_bytes = ((uint64_t)parm.bytes_per_line) * parm.lines *      ((parm.format == SANE_FRAME_RGB        || parm.format == SANE_FRAME_GRAY) ? 1 : 3);    if (parm.lines < 0) @@ -1766,10 +1755,10 @@ cleanup:      {        fprintf (stderr,  	       "%s: WARNING: read more data than announced by backend " -	       "(%u/%u)\n", prog_name, total_bytes, expected_bytes); +               "(%" PRIu64 "/%" PRIu64 ")\n", prog_name, total_bytes, expected_bytes);      }    else if (verbose) -    fprintf (stderr, "%s: read %u bytes in total\n", prog_name, total_bytes); +    fprintf (stderr, "%s: read %" PRIu64 " bytes in total\n", prog_name, total_bytes);    return status;  } @@ -1968,6 +1957,43 @@ static void print_options(SANE_Device * device, SANE_Int num_dev_options, SANE_B      fputc ('\n', stdout);  } +static int guess_output_format(const char* output_file) +{ +  if (output_file == NULL) +    { +      fprintf(stderr, "Output format is not set, using pnm as a default.\n"); +      return OUTPUT_PNM; +    } + +  // if the user passes us a path with a known extension then he won't be surprised if we figure +  // out correct --format option. No warning is necessary in that case. +  const char* extension = strrchr(output_file, '.'); +  if (extension != NULL) +    { +      struct { +        const char* extension; +        int output_format; +      } formats[] = { +        { ".pnm", OUTPUT_PNM }, +        { ".png", OUTPUT_PNG }, +        { ".jpg", OUTPUT_JPEG }, +        { ".jpeg", OUTPUT_JPEG }, +        { ".tiff", OUTPUT_TIFF }, +        { ".tif", OUTPUT_TIFF } +      }; +      for (unsigned i = 0; i < sizeof(formats) / sizeof(formats[0]); ++i) +        { +          if (strcmp(extension, formats[i].extension) == 0) +            return formats[i].output_format; +        } +    } + +  // 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); +} +  int  main (int argc, char **argv)  { @@ -2033,6 +2059,9 @@ main (int argc, char **argv)  	case 'p':            progress = 1;  	  break; +        case 'o': +          output_file = optarg; +          break;  	case 'B':            if (optarg)  	    buffer_size = 1024 * atoi(optarg); @@ -2088,8 +2117,23 @@ main (int argc, char **argv)  	      exit(1);  #endif  	    } -	  else -	    output_format = OUTPUT_PNM; +          else if (strcmp (optarg, "pnm") == 0) +            { +              output_format = OUTPUT_PNM; +            } +          else +            { +              fprintf(stderr, "Unknown output image format '%s'.\n", optarg); +              fprintf(stderr, "Supported formats: pnm, tiff"); +#ifdef HAVE_LIBPNG +              fprintf(stderr, ", png"); +#endif +#ifdef HAVE_LIBJPEG +              fprintf(stderr, ", jpeg"); +#endif +              fprintf(stderr, ".\n"); +              exit(1); +            }  	  break;  	case OPTION_MD5:  	  accept_only_md5_auth = 1; @@ -2202,15 +2246,15 @@ main (int argc, char **argv)  	    if (defdevname)  	      printf ("default device is `%s'\n", defdevname);  	    scanimage_exit (0); +	    break;  	  } -  	case 'V':  	  printf ("scanimage (%s) %s; backend version %d.%d.%d\n", PACKAGE,  		  VERSION, SANE_VERSION_MAJOR (version_code),  		  SANE_VERSION_MINOR (version_code),  		  SANE_VERSION_BUILD (version_code));  	  scanimage_exit (0); - +	  break;  	default:  	  break;		/* ignore device specific options for now */  	} @@ -2235,7 +2279,8 @@ Parameters are separated by a blank from single-character options (e.g.\n\                             %%m (model), %%t (type), %%i (index number), and\n\                             %%n (newline)\n\  -b, --batch[=FORMAT]       working in batch mode, FORMAT is `out%%d.pnm' `out%%d.tif'\n\ -                           `out%%d.png' or `out%%d.jpg' by default depending on --format\n"); +                           `out%%d.png' or `out%%d.jpg' by default depending on --format\n\ +                           This option is incompatible with --output-file.");        printf ("\      --batch-start=#        page number to start naming files with\n\      --batch-count=#        how many pages to scan in batch mode\n\ @@ -2247,6 +2292,8 @@ Parameters are separated by a blank from single-character options (e.g.\n\        printf ("\      --accept-md5-only      only accept authorization requests using md5\n\  -p, --progress             print progress messages\n\ +-o, --output-file=PATH     save output to the given file instead of stdout.\n\ +                           This option is incompatible with --batch.\n\  -n, --dont-scan            only set options, don't actually scan\n\  -T, --test                 test backend thoroughly\n\  -A, --all-options          list all available backend options\n\ @@ -2257,6 +2304,15 @@ Parameters are separated by a blank from single-character options (e.g.\n\  -V, --version              print version information\n");      } +  if (batch && output_file != NULL) +    { +      fprintf(stderr, "--batch and --output-file can't be used together.\n"); +      exit(1); +    } + +  if (output_format == OUTPUT_UNKNOWN) +    output_format = guess_output_format(output_file); +    if (!devname)      {        /* If no device name was specified explicitly, we look at the @@ -2389,6 +2445,7 @@ Parameters are separated by a blank from single-character options (e.g.\n\  	    case 'd':  	    case 'h':  	    case 'p': +            case 'o':  	    case 'v':  	    case 'V':  	    case 'T': @@ -2535,7 +2592,19 @@ List of available devices:", prog_name);  	}        if (!batch) -        ofp = stdout; +        { +          ofp = stdout; +          if (output_file != NULL) +            { +              ofp = fopen(output_file, "w"); +              if (ofp == NULL) +                { +                  fprintf(stderr, "%s: could not open input file '%s', " +                          "exiting\n", prog_name, output_file); +                  scanimage_exit(1); +                } +            } +        }        if (batch)  	{ @@ -2662,6 +2731,14 @@ List of available devices:", prog_name);  			}  		    }  		} +              else +                { +                  if (output_file && ofp) +                    { +                      fclose(ofp); +                      ofp = NULL; +                    } +                }  	      break;  	    default:  	      if (batch) @@ -2673,6 +2750,15 @@ List of available devices:", prog_name);  		    }  		  unlink (part_path);  		} +              else +                { +                  if (output_file && ofp) +                    { +                      fclose(ofp); +                      ofp = NULL; +                    } +                  unlink (output_file); +                }  	      break;  	    }			/* switch */  	  n += batch_increment; | 
