home *** CD-ROM | disk | FTP | other *** search
/ Shareware 1 2 the Maxx / sw_1.zip / sw_1 / OS2 / JPEG3OS2.ZIP / JCMAIN.C < prev    next >
Text File  |  1992-04-29  |  11KB  |  388 lines

  1. /*
  2.  * jcmain.c
  3.  *
  4.  * Copyright (C) 1991, 1992, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains a trivial test user interface for the JPEG compressor.
  9.  * It should work on any system with Unix- or MS-DOS-style command lines.
  10.  *
  11.  * Two different command line styles are permitted, depending on the
  12.  * compile-time switch TWO_FILE_COMMANDLINE:
  13.  *    cjpeg [options]  inputfile outputfile
  14.  *    cjpeg [options]  [inputfile]
  15.  * In the second style, output is always to standard output, which you'd
  16.  * normally redirect to a file or pipe to some other program.  Input is
  17.  * either from a named file or from standard input (typically redirected).
  18.  * The second style is convenient on Unix but is unhelpful on systems that
  19.  * don't support pipes.  Also, you MUST use the first style if your system
  20.  * doesn't do binary I/O to stdin/stdout.
  21.  */
  22.  
  23. #include "jinclude.h"
  24. #ifdef INCLUDES_ARE_ANSI
  25. #include <stdlib.h>        /* to declare exit() */
  26. #endif
  27. #ifdef NEED_SIGNAL_CATCHER
  28. #include <signal.h>        /* to declare signal() */
  29. #endif
  30.  
  31. #ifdef THINK_C
  32. #include <console.h>        /* command-line reader for Macintosh */
  33. #endif
  34.  
  35. #ifdef DONT_USE_B_MODE        /* define mode parameters for fopen() */
  36. #define READ_BINARY    "r"
  37. #define WRITE_BINARY    "w"
  38. #else
  39. #define READ_BINARY    "rb"
  40. #define WRITE_BINARY    "wb"
  41. #endif
  42.  
  43. #ifndef EXIT_FAILURE        /* define exit() codes if not provided */
  44. #define EXIT_FAILURE  1
  45. #endif
  46. #ifndef EXIT_SUCCESS
  47. #ifdef VMS
  48. #define EXIT_SUCCESS  1        /* VMS is very nonstandard */
  49. #else
  50. #define EXIT_SUCCESS  0
  51. #endif
  52. #endif
  53.  
  54.  
  55. #include "jversion.h"        /* for version message */
  56.  
  57.  
  58. /*
  59.  * PD version of getopt(3).
  60.  */
  61.  
  62. #include "egetopt.c"
  63.  
  64.  
  65. /*
  66.  * This routine determines what format the input file is,
  67.  * and selects the appropriate input-reading module.
  68.  *
  69.  * To determine which family of input formats the file belongs to,
  70.  * we may look only at the first byte of the file, since C does not
  71.  * guarantee that more than one character can be pushed back with ungetc.
  72.  * Looking at additional bytes would require one of these approaches:
  73.  *     1) assume we can fseek() the input file (fails for piped input);
  74.  *     2) assume we can push back more than one character (works in
  75.  *        some C implementations, but unportable);
  76.  *     3) provide our own buffering as is done in djpeg (breaks input readers
  77.  *        that want to use stdio directly, such as the RLE library);
  78.  * or  4) don't put back the data, and modify the input_init methods to assume
  79.  *        they start reading after the start of file (also breaks RLE library).
  80.  * #1 is attractive for MS-DOS but is untenable on Unix.
  81.  *
  82.  * The most portable solution for file types that can't be identified by their
  83.  * first byte is to make the user tell us what they are.  This is also the
  84.  * only approach for "raw" file types that contain only arbitrary values.
  85.  * We presently apply this method for Targa files.  Most of the time Targa
  86.  * files start with 0x00, so we recognize that case.  Potentially, however,
  87.  * a Targa file could start with any byte value (byte 0 is the length of the
  88.  * seldom-used ID field), so we accept a -T switch to force Targa input mode.
  89.  */
  90.  
  91. static boolean is_targa;    /* records user -T switch */
  92.  
  93.  
  94. LOCAL void
  95. select_file_type (compress_info_ptr cinfo)
  96. {
  97.   int c;
  98.  
  99.   if (is_targa) {
  100. #ifdef TARGA_SUPPORTED
  101.     jselrtarga(cinfo);
  102. #else
  103.     ERREXIT(cinfo->emethods, "Targa support was not compiled");
  104. #endif
  105.     return;
  106.   }
  107.  
  108.   if ((c = getc(cinfo->input_file)) == EOF)
  109.     ERREXIT(cinfo->emethods, "Empty input file");
  110.  
  111.   switch (c) {
  112. #ifdef GIF_SUPPORTED
  113.   case 'G':
  114.     jselrgif(cinfo);
  115.     break;
  116. #endif
  117. #ifdef PPM_SUPPORTED
  118.   case 'P':
  119.     jselrppm(cinfo);
  120.     break;
  121. #endif
  122. #ifdef RLE_SUPPORTED
  123.   case 'R':
  124.     jselrrle(cinfo);
  125.     break;
  126. #endif
  127. #ifdef TARGA_SUPPORTED
  128.   case 0x00:
  129.     jselrtarga(cinfo);
  130.     break;
  131. #endif
  132.   default:
  133. #ifdef TARGA_SUPPORTED
  134.     ERREXIT(cinfo->emethods, "Unrecognized input file format --- did you forget -T ?");
  135. #else
  136.     ERREXIT(cinfo->emethods, "Unrecognized input file format");
  137. #endif
  138.     break;
  139.   }
  140.  
  141.   if (ungetc(c, cinfo->input_file) == EOF)
  142.     ERREXIT(cinfo->emethods, "ungetc failed");
  143. }
  144.  
  145.  
  146. /*
  147.  * This routine gets control after the input file header has been read.
  148.  * It must determine what output JPEG file format is to be written,
  149.  * and make any other compression parameter changes that are desirable.
  150.  */
  151.  
  152. METHODDEF void
  153. c_ui_method_selection (compress_info_ptr cinfo)
  154. {
  155.   /* If the input is gray scale, generate a monochrome JPEG file. */
  156.   if (cinfo->in_color_space == CS_GRAYSCALE)
  157.     j_monochrome_default(cinfo);
  158.   /* For now, always select JFIF output format. */
  159. #ifdef JFIF_SUPPORTED
  160.   jselwjfif(cinfo);
  161. #else
  162.   You shoulda defined JFIF_SUPPORTED.   /* deliberate syntax error */
  163. #endif
  164. }
  165.  
  166.  
  167. /*
  168.  * Signal catcher to ensure that temporary files are removed before aborting.
  169.  * NB: for Amiga Manx C this is actually a global routine named _abort();
  170.  * see -Dsignal_catcher=_abort in CFLAGS.  Talk about bogus...
  171.  */
  172.  
  173. #ifdef NEED_SIGNAL_CATCHER
  174.  
  175. static external_methods_ptr emethods; /* for access to free_all */
  176.  
  177. GLOBAL void
  178. signal_catcher (int signum)
  179. {
  180.   emethods->trace_level = 0;    /* turn off trace output */
  181.   (*emethods->free_all) ();    /* clean up memory allocation & temp files */
  182.   exit(EXIT_FAILURE);
  183. }
  184.  
  185. #endif
  186.  
  187. /* Display progress report */
  188.  
  189. METHODDEF void
  190. progress_monitor (compress_info_ptr cinfo, long loopcounter, long looplimit)
  191. {
  192.   if (cinfo->total_passes > 1) {
  193.     fprintf(stderr, "\rPass %d/%d: %3d%% ",
  194.         cinfo->completed_passes+1, cinfo->total_passes,
  195.         (int) (loopcounter*100L/looplimit));
  196.   } else {
  197.     fprintf(stderr, "\r %3d%% ",
  198.         (int) (loopcounter*100L/looplimit));
  199.   }
  200.   fflush(stderr);
  201. }
  202.  
  203. LOCAL void
  204. usage (char * progname)
  205. /* complain about bad command line */
  206. {
  207.   fprintf(stderr, "Usage: cjpeg [switches] inputfile outputfile\n");
  208.   fprintf(stderr, "Optional switches:\n");
  209.   fprintf(stderr, "  -Q quality  Image quality (0..100; 5-95 is useful range)\n");
  210.   fprintf(stderr, "  -o          Optimize Huffman table (smaller file, but slow)\n");
  211. #ifdef TARGA_SUPPORTED
  212.   fprintf(stderr, "  -T          Input file is Targa format (usually not needed)\n");
  213. #endif
  214. #ifndef FREE_MEM_ESTIMATE
  215.   fprintf(stderr, "  -m memory   Maximum memory to use (default infinite); see USAGE\n");
  216. #endif
  217.   fprintf(stderr, "  -d          Generate debug output\n");
  218.   exit(EXIT_FAILURE);
  219. }
  220.  
  221.  
  222. /*
  223.  * The main program.
  224.  */
  225.  
  226. GLOBAL int
  227. main (int argc, char **argv)
  228. {
  229.   struct compress_info_struct cinfo;
  230.   struct compress_methods_struct c_methods;
  231.   struct external_methods_struct e_methods;
  232.   int c;
  233.  
  234.   /* On Mac, fetch a command line. */
  235. #ifdef THINK_C
  236.   argc = ccommand(&argv);
  237. #endif
  238.  
  239.   /* Initialize the system-dependent method pointers. */
  240.   cinfo.methods = &c_methods;
  241.   cinfo.emethods = &e_methods;
  242.   jselerror(&e_methods);    /* error/trace message routines */
  243.   jselmemmgr(&e_methods);    /* memory allocation routines */
  244.   c_methods.c_ui_method_selection = c_ui_method_selection;
  245.  
  246.   /* Now OK to enable signal catcher. */
  247. #ifdef NEED_SIGNAL_CATCHER
  248.   emethods = &e_methods;
  249.   signal(SIGINT, signal_catcher);
  250. #ifdef SIGTERM            /* not all systems have SIGTERM */
  251.   signal(SIGTERM, signal_catcher);
  252. #endif
  253. #endif
  254.  
  255.   /* Set up default JPEG parameters. */
  256.   j_c_defaults(&cinfo, 75, FALSE); /* default quality level = 75 */
  257.   is_targa = FALSE;
  258.  
  259.   /* Scan command line options, adjust parameters */
  260.   
  261.   while ((c = egetopt(argc, argv, "IQ:Taom:d")) != EOF)
  262.     switch (c) {
  263.     case 'I':            /* Create noninterleaved file. */
  264. #ifdef MULTISCAN_FILES_SUPPORTED
  265.       cinfo.interleave = FALSE;
  266. #else
  267.       fprintf(stderr, "%s: sorry, multiple-scan support was not compiled\n",
  268.           argv[0]);
  269.       exit(EXIT_FAILURE);
  270. #endif
  271.       break;
  272.     case 'Q':            /* Quality factor. */
  273.       { int val;
  274.     if (optarg == NULL)
  275.       usage(argv[0]);
  276.     if (sscanf(optarg, "%d", &val) != 1)
  277.       usage(argv[0]);
  278.     /* Note: for now, we make force_baseline FALSE.
  279.      * This means non-baseline JPEG files can be created with low Q values.
  280.      * To ensure only baseline files are generated, pass TRUE instead.
  281.      */
  282.     j_set_quality(&cinfo, val, FALSE);
  283.       }
  284.       break;
  285.     case 'T':            /* Input file is Targa format. */
  286.       is_targa = TRUE;
  287.       break;
  288.     case 'a':            /* Use arithmetic coding. */
  289. #ifdef ARITH_CODING_SUPPORTED
  290.       cinfo.arith_code = TRUE;
  291. #else
  292.       fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
  293.           argv[0]);
  294.       exit(EXIT_FAILURE);
  295. #endif
  296.       break;
  297.     case 'o':            /* Enable entropy parm optimization. */
  298. #ifdef ENTROPY_OPT_SUPPORTED
  299.       cinfo.optimize_coding = TRUE;
  300. #else
  301.       fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
  302.           argv[0]);
  303.       exit(EXIT_FAILURE);
  304. #endif
  305.       break;
  306.     case 'm':            /* Maximum memory in Kb (or Mb with 'm'). */
  307.       { long lval;
  308.     char ch = 'x';
  309.  
  310.     if (optarg == NULL)
  311.       usage(argv[0]);
  312.     if (sscanf(optarg, "%ld%c", &lval, &ch) < 1)
  313.       usage(argv[0]);
  314.     if (ch == 'm' || ch == 'M')
  315.       lval *= 1000L;
  316.     e_methods.max_memory_to_use = lval * 1000L;
  317.       }
  318.       break;
  319.     case 'd':            /* Debugging. */
  320.       e_methods.trace_level++;
  321.       break;
  322.     case '?':
  323.     default:
  324.       usage(argv[0]);
  325.       break;
  326.     }
  327.  
  328.   /* If -d appeared, print version identification */
  329.   if (e_methods.trace_level > 0)
  330.     fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n",
  331.         JVERSION, JCOPYRIGHT);
  332.  
  333.   /* Select the input and output files */
  334.  
  335. #ifdef TWO_FILE_COMMANDLINE
  336.  
  337.   if (optind != argc-2) {
  338.     fprintf(stderr, "%s: must name one input and one output file\n", argv[0]);
  339.     usage(argv[0]);
  340.   }
  341.   if ((cinfo.input_file = fopen(argv[optind], READ_BINARY)) == NULL) {
  342.     fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind]);
  343.     exit(EXIT_FAILURE);
  344.   }
  345.   if ((cinfo.output_file = fopen(argv[optind+1], WRITE_BINARY)) == NULL) {
  346.     fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind+1]);
  347.     exit(EXIT_FAILURE);
  348.   }
  349.  
  350. #else /* not TWO_FILE_COMMANDLINE -- use Unix style */
  351.  
  352.   cinfo.input_file = stdin;    /* default input file */
  353.   cinfo.output_file = stdout;    /* always the output file */
  354.  
  355.   if (optind < argc-1) {
  356.     fprintf(stderr, "%s: only one input file\n", argv[0]);
  357.     usage(argv[0]);
  358.   }
  359.   if (optind < argc) {
  360.     if ((cinfo.input_file = fopen(argv[optind], READ_BINARY)) == NULL) {
  361.       fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind]);
  362.       exit(EXIT_FAILURE);
  363.     }
  364.   }
  365.  
  366. #endif /* TWO_FILE_COMMANDLINE */
  367.  
  368.  /* Start up progress display, unless trace output is on */
  369.   fprintf(stderr, "Compressing\n");
  370.   if (e_methods.trace_level == 0)
  371.     c_methods.progress_monitor = progress_monitor;
  372.  
  373.   /* Figure out the input file format, and set up to read it. */
  374.   select_file_type(&cinfo);
  375.  
  376.   /* Do it to it! */
  377.   jpeg_compress(&cinfo);
  378.  
  379.  /* Clear away progress display */
  380.   if (e_methods.trace_level == 0)
  381.     fprintf(stderr, "\r                \r");
  382.   fflush(stderr);
  383.  
  384.   /* All done. */
  385.   exit(EXIT_SUCCESS);
  386.   return 0;            /* suppress no-return-value warnings */
  387. }
  388.