136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/*
236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * djpeg.c
336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane *
4a73e870ad02de20c2b34cb3a5382c2846c2afbe3DRC * This file was part of the Independent JPEG Group's software:
55ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * Copyright (C) 1991-1997, Thomas G. Lane.
6a6ef282a49f2d7d1b4d19cc89f63e81fd66b35b7DRC * libjpeg-turbo Modifications:
70ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC * Copyright (C) 2010-2011, 2013-2016, D. R. Commander.
8ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC * Copyright (C) 2015, Google, Inc.
936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * For conditions of distribution and use, see the accompanying README file.
1036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane *
1136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * This file contains a command-line user interface for the JPEG decompressor.
1236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * It should work on any system with Unix- or MS-DOS-style command lines.
1336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane *
1436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Two different command line styles are permitted, depending on the
1536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * compile-time switch TWO_FILE_COMMANDLINE:
16e5eaf37440b8e337ab150c017df7c03faf846c51DRC *      djpeg [options]  inputfile outputfile
17e5eaf37440b8e337ab150c017df7c03faf846c51DRC *      djpeg [options]  [inputfile]
1836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * In the second style, output is always to standard output, which you'd
1936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * normally redirect to a file or pipe to some other program.  Input is
2036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * either from a named file or from standard input (typically redirected).
2136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * The second style is convenient on Unix but is unhelpful on systems that
2236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * don't support pipes.  Also, you MUST use the first style if your system
2336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * doesn't do binary I/O to stdin/stdout.
2436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * To simplify script writing, the "-outfile" switch is provided.  The syntax
25e5eaf37440b8e337ab150c017df7c03faf846c51DRC *      djpeg [options]  -outfile outputfile  inputfile
2636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * works regardless of which command line style is used.
2736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane */
2836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
29e5eaf37440b8e337ab150c017df7c03faf846c51DRC#include "cdjpeg.h"             /* Common decls for cjpeg/djpeg applications */
30e5eaf37440b8e337ab150c017df7c03faf846c51DRC#include "jversion.h"           /* for version message */
31ff6961f3d22060adc13cc3e60d42fc480de007e5DRC#include "jconfigint.h"
320ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC#include "wrppm.h"
3336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
34e5eaf37440b8e337ab150c017df7c03faf846c51DRC#include <ctype.h>              /* to declare isprint() */
3536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
36e5eaf37440b8e337ab150c017df7c03faf846c51DRC#ifdef USE_CCOMMAND             /* command-line reader for Macintosh */
3736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef __MWERKS__
38489583f5165e05d37302e8eeec58104ea0109127Thomas G. Lane#include <SIOUX.h>              /* Metrowerks needs this */
39e5eaf37440b8e337ab150c017df7c03faf846c51DRC#include <console.h>            /* ... and this */
4036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
4136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef THINK_C
42e5eaf37440b8e337ab150c017df7c03faf846c51DRC#include <console.h>            /* Think declares it here */
4336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
4436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
4536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
4636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
479ba2f5ed3649fb6de83d3c16e4dba1443aaca983Thomas G. Lane/* Create the add-on message string table. */
489ba2f5ed3649fb6de83d3c16e4dba1443aaca983Thomas G. Lane
49e5eaf37440b8e337ab150c017df7c03faf846c51DRC#define JMESSAGE(code,string)   string ,
509ba2f5ed3649fb6de83d3c16e4dba1443aaca983Thomas G. Lane
519ba2f5ed3649fb6de83d3c16e4dba1443aaca983Thomas G. Lanestatic const char * const cdjpeg_message_table[] = {
529ba2f5ed3649fb6de83d3c16e4dba1443aaca983Thomas G. Lane#include "cderror.h"
539ba2f5ed3649fb6de83d3c16e4dba1443aaca983Thomas G. Lane  NULL
549ba2f5ed3649fb6de83d3c16e4dba1443aaca983Thomas G. Lane};
559ba2f5ed3649fb6de83d3c16e4dba1443aaca983Thomas G. Lane
569ba2f5ed3649fb6de83d3c16e4dba1443aaca983Thomas G. Lane
5736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/*
5836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * This list defines the known output image formats
5936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * (not all of which need be supported by a given version).
6036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * You can change the default output format by defining DEFAULT_FMT;
6136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * indeed, you had better do so if you undefine PPM_SUPPORTED.
6236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane */
6336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
6436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanetypedef enum {
65e5eaf37440b8e337ab150c017df7c03faf846c51DRC        FMT_BMP,                /* BMP format (Windows flavor) */
66e5eaf37440b8e337ab150c017df7c03faf846c51DRC        FMT_GIF,                /* GIF format */
67e5eaf37440b8e337ab150c017df7c03faf846c51DRC        FMT_OS2,                /* BMP format (OS/2 flavor) */
68e5eaf37440b8e337ab150c017df7c03faf846c51DRC        FMT_PPM,                /* PPM/PGM (PBMPLUS formats) */
69e5eaf37440b8e337ab150c017df7c03faf846c51DRC        FMT_RLE,                /* RLE format */
70e5eaf37440b8e337ab150c017df7c03faf846c51DRC        FMT_TARGA,              /* Targa format */
71e5eaf37440b8e337ab150c017df7c03faf846c51DRC        FMT_TIFF                /* TIFF format */
7236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane} IMAGE_FORMATS;
7336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
74e5eaf37440b8e337ab150c017df7c03faf846c51DRC#ifndef DEFAULT_FMT             /* so can override from CFLAGS in Makefile */
75e5eaf37440b8e337ab150c017df7c03faf846c51DRC#define DEFAULT_FMT     FMT_PPM
7636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
7736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
7836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanestatic IMAGE_FORMATS requested_fmt;
7936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
8036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
8136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/*
8236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Argument-parsing code.
8336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * The switch parser is designed to be useful with DOS-style command line
8436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * syntax, ie, intermixed switches and file names, where only the switches
8536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * to the left of a given file name affect processing of that file.
8636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * The main program in this file doesn't actually use this capability...
8736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane */
8836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
8936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
900ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRCstatic const char *progname;    /* program name for error messages */
910ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRCstatic char *outfilename;       /* for -outfile switch */
920ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRCboolean memsrc;                 /* for -memsrc switch */
930ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRCboolean skip, crop;
940ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRCJDIMENSION skip_start, skip_end;
950ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRCJDIMENSION crop_x, crop_y, crop_width, crop_height;
96ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC#define INPUT_BUF_SIZE  4096
9736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
9836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
99489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneLOCAL(void)
10036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Laneusage (void)
10136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/* complain about bad command line */
10236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane{
10336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "usage: %s [switches] ", progname);
10436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef TWO_FILE_COMMANDLINE
10536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "inputfile outputfile\n");
10636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#else
10736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "[inputfile]\n");
10836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
10936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
11036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "Switches (names may be abbreviated):\n");
11136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "  -colors N      Reduce image to no more than N colors\n");
11236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "  -fast          Fast, low-quality processing\n");
11336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "  -grayscale     Force grayscale output\n");
1146a833a8ee0433525b1261ef349dabd868b7f6448DRC  fprintf(stderr, "  -rgb           Force RGB output\n");
11578df2e6115b0e579432d01cb034132cd4402a1baDRC  fprintf(stderr, "  -rgb565        Force RGB565 output\n");
11636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef IDCT_SCALING_SUPPORTED
11736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "  -scale M/N     Scale output image by fraction M/N, eg, 1/8\n");
11836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
11936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef BMP_SUPPORTED
12036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "  -bmp           Select BMP output format (Windows style)%s\n",
121e5eaf37440b8e337ab150c017df7c03faf846c51DRC          (DEFAULT_FMT == FMT_BMP ? " (default)" : ""));
12236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
12336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef GIF_SUPPORTED
12436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "  -gif           Select GIF output format%s\n",
125e5eaf37440b8e337ab150c017df7c03faf846c51DRC          (DEFAULT_FMT == FMT_GIF ? " (default)" : ""));
12636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
12736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef BMP_SUPPORTED
12836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "  -os2           Select BMP output format (OS/2 style)%s\n",
129e5eaf37440b8e337ab150c017df7c03faf846c51DRC          (DEFAULT_FMT == FMT_OS2 ? " (default)" : ""));
13036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
13136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef PPM_SUPPORTED
13236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "  -pnm           Select PBMPLUS (PPM/PGM) output format%s\n",
133e5eaf37440b8e337ab150c017df7c03faf846c51DRC          (DEFAULT_FMT == FMT_PPM ? " (default)" : ""));
13436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
13536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef RLE_SUPPORTED
13636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "  -rle           Select Utah RLE output format%s\n",
137e5eaf37440b8e337ab150c017df7c03faf846c51DRC          (DEFAULT_FMT == FMT_RLE ? " (default)" : ""));
13836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
13936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef TARGA_SUPPORTED
14036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "  -targa         Select Targa output format%s\n",
141e5eaf37440b8e337ab150c017df7c03faf846c51DRC          (DEFAULT_FMT == FMT_TARGA ? " (default)" : ""));
14236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
14336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "Switches for advanced users:\n");
14436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef DCT_ISLOW_SUPPORTED
14536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "  -dct int       Use integer DCT method%s\n",
146e5eaf37440b8e337ab150c017df7c03faf846c51DRC          (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
14736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
14836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef DCT_IFAST_SUPPORTED
14936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "  -dct fast      Use fast integer DCT (less accurate)%s\n",
150e5eaf37440b8e337ab150c017df7c03faf846c51DRC          (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
15136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
15236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef DCT_FLOAT_SUPPORTED
15336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "  -dct float     Use floating-point DCT method%s\n",
154e5eaf37440b8e337ab150c017df7c03faf846c51DRC          (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
15536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
15636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "  -dither fs     Use F-S dithering (default)\n");
15736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "  -dither none   Don't use dithering in quantization\n");
15836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "  -dither ordered  Use ordered dither (medium speed, quality)\n");
15936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef QUANT_2PASS_SUPPORTED
16036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "  -map FILE      Map to colors used in named image file\n");
16136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
16236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "  -nosmooth      Don't use high-quality upsampling\n");
16336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef QUANT_1PASS_SUPPORTED
16436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "  -onepass       Use 1-pass quantization (fast, low quality)\n");
16536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
16636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "  -maxmemory N   Maximum memory to use (in kbytes)\n");
16736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "  -outfile name  Specify name for output file\n");
168ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
169ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC  fprintf(stderr, "  -memsrc        Load input file into memory before decompressing\n");
170ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC#endif
171ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC
1720ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC  fprintf(stderr, "  -skip Y0,Y1    Decompress all rows except those between Y0 and Y1 (inclusive)\n");
1730ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC  fprintf(stderr, "  -crop WxH+X+Y  Decompress only a rectangular subregion of the image\n");
17436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  fprintf(stderr, "  -verbose  or  -debug   Emit debug output\n");
1759665f5e3f9a73ae44f011a20d382af331fdfd594DRC  fprintf(stderr, "  -version       Print version information and exit\n");
17636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  exit(EXIT_FAILURE);
17736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane}
17836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
17936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
180489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneLOCAL(int)
18136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Laneparse_switches (j_decompress_ptr cinfo, int argc, char **argv,
182e5eaf37440b8e337ab150c017df7c03faf846c51DRC                int last_file_arg_seen, boolean for_real)
18336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/* Parse optional switches.
18436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Returns argv[] index of first file-name argument (== argc if none).
18536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Any file names with indexes <= last_file_arg_seen are ignored;
18636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * they have presumably been processed in a previous iteration.
18736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * (Pass 0 for last_file_arg_seen on the first or only iteration.)
18836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * for_real is FALSE on the first (dummy) pass; we may skip any expensive
18936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * processing.
19036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane */
19136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane{
19236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  int argn;
19336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  char * arg;
19436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
19536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Set up default JPEG parameters. */
196e5eaf37440b8e337ab150c017df7c03faf846c51DRC  requested_fmt = DEFAULT_FMT;  /* set default output file format */
19736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  outfilename = NULL;
198ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC  memsrc = FALSE;
19915884f48eb1a4acd9c6c24291db974c596e71934DRC  skip = FALSE;
2000ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC  crop = FALSE;
20136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  cinfo->err->trace_level = 0;
20236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
20336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Scan command line options, adjust parameters */
20436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
20536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  for (argn = 1; argn < argc; argn++) {
20636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    arg = argv[argn];
20736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    if (*arg != '-') {
20836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* Not a switch, must be a file name argument */
20936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      if (argn <= last_file_arg_seen) {
210e5eaf37440b8e337ab150c017df7c03faf846c51DRC        outfilename = NULL;     /* -outfile applies to just one input file */
211e5eaf37440b8e337ab150c017df7c03faf846c51DRC        continue;               /* ignore this name if previously processed */
21236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      }
213e5eaf37440b8e337ab150c017df7c03faf846c51DRC      break;                    /* else done parsing switches */
21436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    }
215e5eaf37440b8e337ab150c017df7c03faf846c51DRC    arg++;                      /* advance past switch marker character */
21636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
21736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    if (keymatch(arg, "bmp", 1)) {
21836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* BMP output format. */
21936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      requested_fmt = FMT_BMP;
22036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
22136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    } else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) ||
222e5eaf37440b8e337ab150c017df7c03faf846c51DRC               keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) {
22336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* Do color quantization. */
22436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      int val;
22536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
226e5eaf37440b8e337ab150c017df7c03faf846c51DRC      if (++argn >= argc)       /* advance to next argument */
227e5eaf37440b8e337ab150c017df7c03faf846c51DRC        usage();
22836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      if (sscanf(argv[argn], "%d", &val) != 1)
229e5eaf37440b8e337ab150c017df7c03faf846c51DRC        usage();
23036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      cinfo->desired_number_of_colors = val;
23136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      cinfo->quantize_colors = TRUE;
23236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
23336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    } else if (keymatch(arg, "dct", 2)) {
23436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* Select IDCT algorithm. */
235e5eaf37440b8e337ab150c017df7c03faf846c51DRC      if (++argn >= argc)       /* advance to next argument */
236e5eaf37440b8e337ab150c017df7c03faf846c51DRC        usage();
23736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      if (keymatch(argv[argn], "int", 1)) {
238e5eaf37440b8e337ab150c017df7c03faf846c51DRC        cinfo->dct_method = JDCT_ISLOW;
23936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      } else if (keymatch(argv[argn], "fast", 2)) {
240e5eaf37440b8e337ab150c017df7c03faf846c51DRC        cinfo->dct_method = JDCT_IFAST;
24136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      } else if (keymatch(argv[argn], "float", 2)) {
242e5eaf37440b8e337ab150c017df7c03faf846c51DRC        cinfo->dct_method = JDCT_FLOAT;
24336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      } else
244e5eaf37440b8e337ab150c017df7c03faf846c51DRC        usage();
24536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
24636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    } else if (keymatch(arg, "dither", 2)) {
24736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* Select dithering algorithm. */
248e5eaf37440b8e337ab150c017df7c03faf846c51DRC      if (++argn >= argc)       /* advance to next argument */
249e5eaf37440b8e337ab150c017df7c03faf846c51DRC        usage();
25036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      if (keymatch(argv[argn], "fs", 2)) {
251e5eaf37440b8e337ab150c017df7c03faf846c51DRC        cinfo->dither_mode = JDITHER_FS;
25236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      } else if (keymatch(argv[argn], "none", 2)) {
253e5eaf37440b8e337ab150c017df7c03faf846c51DRC        cinfo->dither_mode = JDITHER_NONE;
25436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      } else if (keymatch(argv[argn], "ordered", 2)) {
255e5eaf37440b8e337ab150c017df7c03faf846c51DRC        cinfo->dither_mode = JDITHER_ORDERED;
25636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      } else
257e5eaf37440b8e337ab150c017df7c03faf846c51DRC        usage();
25836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
25936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
26036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* Enable debug printouts. */
26136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* On first -d, print version identification */
26236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      static boolean printed_version = FALSE;
26336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
26436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      if (! printed_version) {
265e5eaf37440b8e337ab150c017df7c03faf846c51DRC        fprintf(stderr, "%s version %s (build %s)\n",
266e5eaf37440b8e337ab150c017df7c03faf846c51DRC                PACKAGE_NAME, VERSION, BUILD);
267e5eaf37440b8e337ab150c017df7c03faf846c51DRC        fprintf(stderr, "%s\n\n", JCOPYRIGHT);
268e5eaf37440b8e337ab150c017df7c03faf846c51DRC        fprintf(stderr, "Emulating The Independent JPEG Group's software, version %s\n\n",
269e5eaf37440b8e337ab150c017df7c03faf846c51DRC                JVERSION);
270e5eaf37440b8e337ab150c017df7c03faf846c51DRC        printed_version = TRUE;
27136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      }
27236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      cinfo->err->trace_level++;
27336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
2749665f5e3f9a73ae44f011a20d382af331fdfd594DRC    } else if (keymatch(arg, "version", 4)) {
2759665f5e3f9a73ae44f011a20d382af331fdfd594DRC      fprintf(stderr, "%s version %s (build %s)\n",
2769665f5e3f9a73ae44f011a20d382af331fdfd594DRC              PACKAGE_NAME, VERSION, BUILD);
277306add8b788c63590c476f693f95527f26909b62DRC      exit(EXIT_SUCCESS);
2789665f5e3f9a73ae44f011a20d382af331fdfd594DRC
27936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    } else if (keymatch(arg, "fast", 1)) {
28036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* Select recommended processing options for quick-and-dirty output. */
28136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      cinfo->two_pass_quantize = FALSE;
28236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      cinfo->dither_mode = JDITHER_ORDERED;
28336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      if (! cinfo->quantize_colors) /* don't override an earlier -colors */
284e5eaf37440b8e337ab150c017df7c03faf846c51DRC        cinfo->desired_number_of_colors = 216;
28536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      cinfo->dct_method = JDCT_FASTEST;
28636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      cinfo->do_fancy_upsampling = FALSE;
28736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
28836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    } else if (keymatch(arg, "gif", 1)) {
28936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* GIF output format. */
29036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      requested_fmt = FMT_GIF;
29136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
29236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
29336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* Force monochrome output. */
29436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      cinfo->out_color_space = JCS_GRAYSCALE;
29536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
2966a833a8ee0433525b1261ef349dabd868b7f6448DRC    } else if (keymatch(arg, "rgb", 2)) {
2976a833a8ee0433525b1261ef349dabd868b7f6448DRC      /* Force RGB output. */
2986a833a8ee0433525b1261ef349dabd868b7f6448DRC      cinfo->out_color_space = JCS_RGB;
2996a833a8ee0433525b1261ef349dabd868b7f6448DRC
30078df2e6115b0e579432d01cb034132cd4402a1baDRC    } else if (keymatch(arg, "rgb565", 2)) {
30178df2e6115b0e579432d01cb034132cd4402a1baDRC      /* Force RGB565 output. */
30278df2e6115b0e579432d01cb034132cd4402a1baDRC      cinfo->out_color_space = JCS_RGB565;
30378df2e6115b0e579432d01cb034132cd4402a1baDRC
30436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    } else if (keymatch(arg, "map", 3)) {
30536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* Quantize to a color map taken from an input file. */
306e5eaf37440b8e337ab150c017df7c03faf846c51DRC      if (++argn >= argc)       /* advance to next argument */
307e5eaf37440b8e337ab150c017df7c03faf846c51DRC        usage();
308e5eaf37440b8e337ab150c017df7c03faf846c51DRC      if (for_real) {           /* too expensive to do twice! */
309e5eaf37440b8e337ab150c017df7c03faf846c51DRC#ifdef QUANT_2PASS_SUPPORTED    /* otherwise can't quantize to supplied map */
310e5eaf37440b8e337ab150c017df7c03faf846c51DRC        FILE * mapfile;
311e5eaf37440b8e337ab150c017df7c03faf846c51DRC
312e5eaf37440b8e337ab150c017df7c03faf846c51DRC        if ((mapfile = fopen(argv[argn], READ_BINARY)) == NULL) {
313e5eaf37440b8e337ab150c017df7c03faf846c51DRC          fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
314e5eaf37440b8e337ab150c017df7c03faf846c51DRC          exit(EXIT_FAILURE);
315e5eaf37440b8e337ab150c017df7c03faf846c51DRC        }
316e5eaf37440b8e337ab150c017df7c03faf846c51DRC        read_color_map(cinfo, mapfile);
317e5eaf37440b8e337ab150c017df7c03faf846c51DRC        fclose(mapfile);
318e5eaf37440b8e337ab150c017df7c03faf846c51DRC        cinfo->quantize_colors = TRUE;
31936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#else
320e5eaf37440b8e337ab150c017df7c03faf846c51DRC        ERREXIT(cinfo, JERR_NOT_COMPILED);
32136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
32236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      }
32336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
32436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    } else if (keymatch(arg, "maxmemory", 3)) {
32536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* Maximum memory in Kb (or Mb with 'm'). */
32636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      long lval;
32736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      char ch = 'x';
32836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
329e5eaf37440b8e337ab150c017df7c03faf846c51DRC      if (++argn >= argc)       /* advance to next argument */
330e5eaf37440b8e337ab150c017df7c03faf846c51DRC        usage();
33136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
332e5eaf37440b8e337ab150c017df7c03faf846c51DRC        usage();
33336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      if (ch == 'm' || ch == 'M')
334e5eaf37440b8e337ab150c017df7c03faf846c51DRC        lval *= 1000L;
33536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      cinfo->mem->max_memory_to_use = lval * 1000L;
33636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
33736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    } else if (keymatch(arg, "nosmooth", 3)) {
33836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* Suppress fancy upsampling */
33936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      cinfo->do_fancy_upsampling = FALSE;
34036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
34136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    } else if (keymatch(arg, "onepass", 3)) {
34236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* Use fast one-pass quantization. */
34336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      cinfo->two_pass_quantize = FALSE;
34436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
34536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    } else if (keymatch(arg, "os2", 3)) {
34636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* BMP output format (OS/2 flavor). */
34736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      requested_fmt = FMT_OS2;
34836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
34936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    } else if (keymatch(arg, "outfile", 4)) {
35036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* Set output file name. */
351e5eaf37440b8e337ab150c017df7c03faf846c51DRC      if (++argn >= argc)       /* advance to next argument */
352e5eaf37440b8e337ab150c017df7c03faf846c51DRC        usage();
353e5eaf37440b8e337ab150c017df7c03faf846c51DRC      outfilename = argv[argn]; /* save it away for later use */
35436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
355ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC    } else if (keymatch(arg, "memsrc", 2)) {
356ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC      /* Use in-memory source manager */
357ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
358ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC      memsrc = TRUE;
359ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC#else
360ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC      fprintf(stderr, "%s: sorry, in-memory source manager was not compiled in\n",
361ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC              progname);
362ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC      exit(EXIT_FAILURE);
363ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC#endif
364ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC
36536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    } else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) {
36636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* PPM/PGM output format. */
36736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      requested_fmt = FMT_PPM;
36836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
36936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    } else if (keymatch(arg, "rle", 1)) {
37036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* RLE output format. */
37136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      requested_fmt = FMT_RLE;
37236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
373ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC    } else if (keymatch(arg, "scale", 2)) {
37436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* Scale the output image by a fraction M/N. */
375e5eaf37440b8e337ab150c017df7c03faf846c51DRC      if (++argn >= argc)       /* advance to next argument */
376e5eaf37440b8e337ab150c017df7c03faf846c51DRC        usage();
37736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      if (sscanf(argv[argn], "%d/%d",
378e5eaf37440b8e337ab150c017df7c03faf846c51DRC                 &cinfo->scale_num, &cinfo->scale_denom) != 2)
379e5eaf37440b8e337ab150c017df7c03faf846c51DRC        usage();
38036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
3810ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    } else if (keymatch(arg, "skip", 2)) {
382ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC      if (++argn >= argc)
383ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC        usage();
3840ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC      if (sscanf(argv[argn], "%u,%u", &skip_start, &skip_end) != 2 ||
3850ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC          skip_start > skip_end)
386ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC        usage();
3870ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC      skip = TRUE;
38815884f48eb1a4acd9c6c24291db974c596e71934DRC
3890ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    } else if (keymatch(arg, "crop", 2)) {
3900ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC      char c;
39115884f48eb1a4acd9c6c24291db974c596e71934DRC      if (++argn >= argc)
39215884f48eb1a4acd9c6c24291db974c596e71934DRC        usage();
3930ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC      if (sscanf(argv[argn], "%u%c%u+%u+%u", &crop_width, &c, &crop_height,
3940ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC                 &crop_x, &crop_y) != 5 ||
3950ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC          (c != 'X' && c != 'x') || crop_width < 1 || crop_height < 1)
39615884f48eb1a4acd9c6c24291db974c596e71934DRC        usage();
3970ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC      crop = TRUE;
39815884f48eb1a4acd9c6c24291db974c596e71934DRC
39936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    } else if (keymatch(arg, "targa", 1)) {
40036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* Targa output format. */
40136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      requested_fmt = FMT_TARGA;
40236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
40336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    } else {
404e5eaf37440b8e337ab150c017df7c03faf846c51DRC      usage();                  /* bogus switch */
40536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    }
40636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  }
40736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
408e5eaf37440b8e337ab150c017df7c03faf846c51DRC  return argn;                  /* return index of next arg (file name) */
40936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane}
41036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
41136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
41236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/*
4135ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * Marker processor for COM and interesting APPn markers.
41436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * This replaces the library's built-in processor, which just skips the marker.
4155ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane * We want to print out the marker as text, to the extent possible.
41636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Note this code relies on a non-suspending data source.
41736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane */
41836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
419489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneLOCAL(unsigned int)
42036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanejpeg_getc (j_decompress_ptr cinfo)
42136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/* Read next byte */
42236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane{
42336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  struct jpeg_source_mgr * datasrc = cinfo->src;
42436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
42536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  if (datasrc->bytes_in_buffer == 0) {
42636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    if (! (*datasrc->fill_input_buffer) (cinfo))
42736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      ERREXIT(cinfo, JERR_CANT_SUSPEND);
42836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  }
42936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  datasrc->bytes_in_buffer--;
43036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  return GETJOCTET(*datasrc->next_input_byte++);
43136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane}
43236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
43336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
434489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(boolean)
4355ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Laneprint_text_marker (j_decompress_ptr cinfo)
43636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane{
43736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  boolean traceit = (cinfo->err->trace_level >= 1);
43836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  INT32 length;
43936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  unsigned int ch;
44036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  unsigned int lastch = 0;
44136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
44236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  length = jpeg_getc(cinfo) << 8;
44336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  length += jpeg_getc(cinfo);
444e5eaf37440b8e337ab150c017df7c03faf846c51DRC  length -= 2;                  /* discount the length word itself */
44536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
4465ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  if (traceit) {
4475ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane    if (cinfo->unread_marker == JPEG_COM)
4485ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      fprintf(stderr, "Comment, length %ld:\n", (long) length);
449e5eaf37440b8e337ab150c017df7c03faf846c51DRC    else                        /* assume it is an APPn otherwise */
4505ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane      fprintf(stderr, "APP%d, length %ld:\n",
451e5eaf37440b8e337ab150c017df7c03faf846c51DRC              cinfo->unread_marker - JPEG_APP0, (long) length);
4525ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  }
45336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
45436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  while (--length >= 0) {
45536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    ch = jpeg_getc(cinfo);
45636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    if (traceit) {
45736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      /* Emit the character in a readable form.
45836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane       * Nonprintables are converted to \nnn form,
45936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane       * while \ is converted to \\.
46036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane       * Newlines in CR, CR/LF, or LF form will be printed as one newline.
46136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane       */
46236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      if (ch == '\r') {
463e5eaf37440b8e337ab150c017df7c03faf846c51DRC        fprintf(stderr, "\n");
46436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      } else if (ch == '\n') {
465e5eaf37440b8e337ab150c017df7c03faf846c51DRC        if (lastch != '\r')
466e5eaf37440b8e337ab150c017df7c03faf846c51DRC          fprintf(stderr, "\n");
46736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      } else if (ch == '\\') {
468e5eaf37440b8e337ab150c017df7c03faf846c51DRC        fprintf(stderr, "\\\\");
46936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      } else if (isprint(ch)) {
470e5eaf37440b8e337ab150c017df7c03faf846c51DRC        putc(ch, stderr);
47136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      } else {
472e5eaf37440b8e337ab150c017df7c03faf846c51DRC        fprintf(stderr, "\\%03o", ch);
47336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      }
47436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      lastch = ch;
47536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    }
47636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  }
47736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
47836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  if (traceit)
47936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    fprintf(stderr, "\n");
48036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
48136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  return TRUE;
48236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane}
48336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
48436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
48536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/*
48636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * The main program.
48736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane */
48836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
489489583f5165e05d37302e8eeec58104ea0109127Thomas G. Laneint
49036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanemain (int argc, char **argv)
49136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane{
49236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  struct jpeg_decompress_struct cinfo;
49336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  struct jpeg_error_mgr jerr;
49436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef PROGRESS_REPORT
49536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  struct cdjpeg_progress_mgr progress;
49636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
49736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  int file_index;
49836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  djpeg_dest_ptr dest_mgr = NULL;
49936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  FILE * input_file;
50036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  FILE * output_file;
501ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC  unsigned char *inbuffer = NULL;
502ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC  unsigned long insize = 0;
50336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  JDIMENSION num_scanlines;
50436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
50536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* On Mac, fetch a command line. */
50636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef USE_CCOMMAND
50736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  argc = ccommand(&argv);
50836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
50936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
51036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  progname = argv[0];
51136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  if (progname == NULL || progname[0] == 0)
512e5eaf37440b8e337ab150c017df7c03faf846c51DRC    progname = "djpeg";         /* in case C library doesn't provide it */
51336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
51436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Initialize the JPEG decompression object with default error handling. */
51536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  cinfo.err = jpeg_std_error(&jerr);
51636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  jpeg_create_decompress(&cinfo);
51736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Add some application-specific error messages (from cderror.h) */
5189ba2f5ed3649fb6de83d3c16e4dba1443aaca983Thomas G. Lane  jerr.addon_message_table = cdjpeg_message_table;
51936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  jerr.first_addon_message = JMSG_FIRSTADDONCODE;
52036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  jerr.last_addon_message = JMSG_LASTADDONCODE;
5215ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane
5225ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  /* Insert custom marker processor for COM and APP12.
5235ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   * APP12 is used by some digital camera makers for textual info,
5245ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   * so we provide the ability to display it as text.
5255ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   * If you like, additional APPn marker types can be selected for display,
52639ea562c074ec74785d68accf10f433849770d1fDRC   * but don't try to override APP0 or APP14 this way (see libjpeg.txt).
5275ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane   */
5285ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  jpeg_set_marker_processor(&cinfo, JPEG_COM, print_text_marker);
5295ead57a34a398aa798f35bd7a6abad19b2e453e2Thomas G. Lane  jpeg_set_marker_processor(&cinfo, JPEG_APP0+12, print_text_marker);
53036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
53136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Scan command line to find file names. */
53236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* It is convenient to use just one switch-parsing routine, but the switch
53336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   * values read here are ignored; we will rescan the switches after opening
53436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   * the input file.
53536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   * (Exception: tracing level set here controls verbosity for COM markers
53636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   * found during jpeg_read_header...)
53736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   */
53836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
53936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
54036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
54136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef TWO_FILE_COMMANDLINE
54236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Must have either -outfile switch or explicit output file name */
54336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  if (outfilename == NULL) {
54436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    if (file_index != argc-2) {
54536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      fprintf(stderr, "%s: must name one input and one output file\n",
546e5eaf37440b8e337ab150c017df7c03faf846c51DRC              progname);
54736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      usage();
54836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    }
54936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    outfilename = argv[file_index+1];
55036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  } else {
55136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    if (file_index != argc-1) {
55236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      fprintf(stderr, "%s: must name one input and one output file\n",
553e5eaf37440b8e337ab150c017df7c03faf846c51DRC              progname);
55436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      usage();
55536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    }
55636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  }
55736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#else
55836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Unix style: expect zero or one file name */
55936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  if (file_index < argc-1) {
56036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    fprintf(stderr, "%s: only one input file\n", progname);
56136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    usage();
56236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  }
56336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif /* TWO_FILE_COMMANDLINE */
56436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
56536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Open the input file. */
56636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  if (file_index < argc) {
56736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
56836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
56936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      exit(EXIT_FAILURE);
57036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    }
57136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  } else {
57236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    /* default input file is stdin */
573bc79e0680a45d1ca330d690dae0340c8e17ab5e3Thomas G. Lane    input_file = read_stdin();
57436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  }
57536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
57636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Open the output file. */
57736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  if (outfilename != NULL) {
57836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
57936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
58036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      exit(EXIT_FAILURE);
58136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    }
58236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  } else {
58336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    /* default output file is stdout */
584bc79e0680a45d1ca330d690dae0340c8e17ab5e3Thomas G. Lane    output_file = write_stdout();
58536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  }
58636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
58736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef PROGRESS_REPORT
588bc79e0680a45d1ca330d690dae0340c8e17ab5e3Thomas G. Lane  start_progress_monitor((j_common_ptr) &cinfo, &progress);
58936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
59036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
59136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Specify data source for decompression */
592ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
593ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC  if (memsrc) {
594ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC    size_t nbytes;
595ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC    do {
596ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC      inbuffer = (unsigned char *)realloc(inbuffer, insize + INPUT_BUF_SIZE);
597ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC      if (inbuffer == NULL) {
598ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC        fprintf(stderr, "%s: memory allocation failure\n", progname);
599ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC        exit(EXIT_FAILURE);
600ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC      }
601ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC      nbytes = JFREAD(input_file, &inbuffer[insize], INPUT_BUF_SIZE);
602c45653e471c496af8bf3c91c70c7ae4e207158c4DRC      if (nbytes < INPUT_BUF_SIZE && ferror(input_file)) {
603ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC        if (file_index < argc)
604ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC          fprintf(stderr, "%s: can't read from %s\n", progname,
605ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC                  argv[file_index]);
606ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC        else
607ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC          fprintf(stderr, "%s: can't read from stdin\n", progname);
608ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC      }
609736fb06278ec2f0f3cd2d30fa34f17ede47138c4DRC      insize += (unsigned long)nbytes;
610ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC    } while (nbytes == INPUT_BUF_SIZE);
611ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC    fprintf(stderr, "Compressed size:  %lu bytes\n", insize);
612ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC    jpeg_mem_src(&cinfo, inbuffer, insize);
613ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC  } else
614ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC#endif
615ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC    jpeg_stdio_src(&cinfo, input_file);
61636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
61736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Read file header, set default decompression parameters */
61836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  (void) jpeg_read_header(&cinfo, TRUE);
61936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
62036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Adjust default decompression parameters by re-parsing the options */
62136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
62236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
62336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Initialize the output module now to let it override any crucial
62436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   * option settings (for instance, GIF wants to force color quantization).
62536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   */
62636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  switch (requested_fmt) {
62736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef BMP_SUPPORTED
62836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  case FMT_BMP:
62936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    dest_mgr = jinit_write_bmp(&cinfo, FALSE);
63036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    break;
63136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  case FMT_OS2:
63236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    dest_mgr = jinit_write_bmp(&cinfo, TRUE);
63336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    break;
63436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
63536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef GIF_SUPPORTED
63636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  case FMT_GIF:
63736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    dest_mgr = jinit_write_gif(&cinfo);
63836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    break;
63936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
64036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef PPM_SUPPORTED
64136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  case FMT_PPM:
64236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    dest_mgr = jinit_write_ppm(&cinfo);
64336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    break;
64436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
64536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef RLE_SUPPORTED
64636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  case FMT_RLE:
64736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    dest_mgr = jinit_write_rle(&cinfo);
64836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    break;
64936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
65036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef TARGA_SUPPORTED
65136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  case FMT_TARGA:
65236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    dest_mgr = jinit_write_targa(&cinfo);
65336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    break;
65436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
65536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  default:
65636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT);
65736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    break;
65836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  }
65936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  dest_mgr->output_file = output_file;
66036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
66136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Start decompressor */
662bc79e0680a45d1ca330d690dae0340c8e17ab5e3Thomas G. Lane  (void) jpeg_start_decompress(&cinfo);
66336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
6640ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC  /* Skip rows */
6650ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC  if (skip) {
666ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC    JDIMENSION tmp;
667ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC
6680ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    /* Check for valid skip_end.  We cannot check this value until after
669ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC     * jpeg_start_decompress() is called.  Note that we have already verified
6700ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC     * that skip_start <= skip_end.
671ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC     */
6720ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    if (skip_end > cinfo.output_height - 1) {
6730ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC      fprintf(stderr, "%s: skip region exceeds image height %d\n", progname,
6740ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC              cinfo.output_height);
675ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC      exit(EXIT_FAILURE);
676ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC    }
67736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
678ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC    /* Write output file header.  This is a hack to ensure that the destination
6790ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC     * manager creates an output image of the proper size.
680ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC     */
681ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC    tmp = cinfo.output_height;
6820ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    cinfo.output_height -= (skip_end - skip_start + 1);
683ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC    (*dest_mgr->start_output) (&cinfo, dest_mgr);
684ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC    cinfo.output_height = tmp;
685ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC
686ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC    /* Process data */
6870ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    while (cinfo.output_scanline < skip_start) {
6880ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC      num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
6890ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC                                          dest_mgr->buffer_height);
6900ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC      (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
6910ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    }
6920ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    jpeg_skip_scanlines(&cinfo, skip_end - skip_start + 1);
6930ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    while (cinfo.output_scanline < cinfo.output_height) {
6940ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC      num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
6950ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC                                          dest_mgr->buffer_height);
6960ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC      (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
6970ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    }
6980ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC
6990ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC  /* Decompress a subregion */
7000ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC  } else if (crop) {
7010ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    JDIMENSION tmp;
7020ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC
7030ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    /* Check for valid crop dimensions.  We cannot check these values until
7040ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC     * after jpeg_start_decompress() is called.
7050ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC     */
7060ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    if (crop_x + crop_width > cinfo.output_width ||
7070ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC        crop_y + crop_height > cinfo.output_height) {
7080ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC      fprintf(stderr, "%s: crop dimensions exceed image dimensions %d x %d\n",
7090ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC              progname, cinfo.output_width, cinfo.output_height);
7100ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC      exit(EXIT_FAILURE);
7110ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    }
7120ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC
7130ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    jpeg_crop_scanline(&cinfo, &crop_x, &crop_width);
7140ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    ((ppm_dest_ptr) dest_mgr)->buffer_width = cinfo.output_width *
7150ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC                                              cinfo.out_color_components *
7160ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC                                              sizeof(JSAMPLE);
7170ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC
7180ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    /* Write output file header.  This is a hack to ensure that the destination
7190ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC     * manager creates an output image of the proper size.
7200ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC     */
7210ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    tmp = cinfo.output_height;
7220ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    cinfo.output_height = crop_height;
7230ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    (*dest_mgr->start_output) (&cinfo, dest_mgr);
7240ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    cinfo.output_height = tmp;
7250ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC
7260ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    /* Process data */
7270ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    jpeg_skip_scanlines(&cinfo, crop_y);
7280ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    while (cinfo.output_scanline < crop_y + crop_height) {
7290ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC      num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
7300ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC                                          dest_mgr->buffer_height);
7310ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC      (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
732ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC    }
7330ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC    jpeg_skip_scanlines(&cinfo, cinfo.output_height - crop_y - crop_height);
734ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC
7350ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4DRC  /* Normal full-image decompress */
736ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC  } else {
737ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC    /* Write output file header */
738ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC    (*dest_mgr->start_output) (&cinfo, dest_mgr);
739ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC
740ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC    /* Process data */
741ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC    while (cinfo.output_scanline < cinfo.output_height) {
742ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC      num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
743ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC                                          dest_mgr->buffer_height);
744ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC      (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
745ac30a1bf12751bd82e56158eb9456a28d9c086f3DRC    }
74636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  }
74736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
74836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef PROGRESS_REPORT
74936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Hack: count final pass as done in case finish_output does an extra pass.
75036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   * The library won't have updated completed_passes.
75136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   */
75236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  progress.pub.completed_passes = progress.pub.total_passes;
75336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
75436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
75536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Finish decompression and release memory.
75636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   * I must do it in this order because output module has allocated memory
75736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   * of lifespan JPOOL_IMAGE; it needs to finish before releasing memory.
75836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   */
75936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  (*dest_mgr->finish_output) (&cinfo, dest_mgr);
760bc79e0680a45d1ca330d690dae0340c8e17ab5e3Thomas G. Lane  (void) jpeg_finish_decompress(&cinfo);
76136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  jpeg_destroy_decompress(&cinfo);
76236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
7639ba2f5ed3649fb6de83d3c16e4dba1443aaca983Thomas G. Lane  /* Close files, if we opened them */
7649ba2f5ed3649fb6de83d3c16e4dba1443aaca983Thomas G. Lane  if (input_file != stdin)
7659ba2f5ed3649fb6de83d3c16e4dba1443aaca983Thomas G. Lane    fclose(input_file);
7669ba2f5ed3649fb6de83d3c16e4dba1443aaca983Thomas G. Lane  if (output_file != stdout)
7679ba2f5ed3649fb6de83d3c16e4dba1443aaca983Thomas G. Lane    fclose(output_file);
7689ba2f5ed3649fb6de83d3c16e4dba1443aaca983Thomas G. Lane
76936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#ifdef PROGRESS_REPORT
770bc79e0680a45d1ca330d690dae0340c8e17ab5e3Thomas G. Lane  end_progress_monitor((j_common_ptr) &cinfo);
77136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#endif
77236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
773ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC  if (memsrc && inbuffer != NULL)
774ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC    free(inbuffer);
775ab70623eb29e09e67222be5b9e1ea320fe5aa0e9DRC
77636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* All done. */
77736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
778e5eaf37440b8e337ab150c017df7c03faf846c51DRC  return 0;                     /* suppress no-return-value warnings */
77936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane}
780