xref: /aosp_15_r20/external/libjpeg-turbo/djpeg.c (revision dfc6aa5c1cfd4bc4e2018dc74aa96e29ee49c6da)
1*dfc6aa5cSAndroid Build Coastguard Worker /*
2*dfc6aa5cSAndroid Build Coastguard Worker  * djpeg.c
3*dfc6aa5cSAndroid Build Coastguard Worker  *
4*dfc6aa5cSAndroid Build Coastguard Worker  * This file was part of the Independent JPEG Group's software:
5*dfc6aa5cSAndroid Build Coastguard Worker  * Copyright (C) 1991-1997, Thomas G. Lane.
6*dfc6aa5cSAndroid Build Coastguard Worker  * Modified 2013-2019 by Guido Vollbeding.
7*dfc6aa5cSAndroid Build Coastguard Worker  * libjpeg-turbo Modifications:
8*dfc6aa5cSAndroid Build Coastguard Worker  * Copyright (C) 2010-2011, 2013-2017, 2019-2020, 2022, D. R. Commander.
9*dfc6aa5cSAndroid Build Coastguard Worker  * Copyright (C) 2015, Google, Inc.
10*dfc6aa5cSAndroid Build Coastguard Worker  * For conditions of distribution and use, see the accompanying README.ijg
11*dfc6aa5cSAndroid Build Coastguard Worker  * file.
12*dfc6aa5cSAndroid Build Coastguard Worker  *
13*dfc6aa5cSAndroid Build Coastguard Worker  * This file contains a command-line user interface for the JPEG decompressor.
14*dfc6aa5cSAndroid Build Coastguard Worker  * It should work on any system with Unix- or MS-DOS-style command lines.
15*dfc6aa5cSAndroid Build Coastguard Worker  *
16*dfc6aa5cSAndroid Build Coastguard Worker  * Two different command line styles are permitted, depending on the
17*dfc6aa5cSAndroid Build Coastguard Worker  * compile-time switch TWO_FILE_COMMANDLINE:
18*dfc6aa5cSAndroid Build Coastguard Worker  *      djpeg [options]  inputfile outputfile
19*dfc6aa5cSAndroid Build Coastguard Worker  *      djpeg [options]  [inputfile]
20*dfc6aa5cSAndroid Build Coastguard Worker  * In the second style, output is always to standard output, which you'd
21*dfc6aa5cSAndroid Build Coastguard Worker  * normally redirect to a file or pipe to some other program.  Input is
22*dfc6aa5cSAndroid Build Coastguard Worker  * either from a named file or from standard input (typically redirected).
23*dfc6aa5cSAndroid Build Coastguard Worker  * The second style is convenient on Unix but is unhelpful on systems that
24*dfc6aa5cSAndroid Build Coastguard Worker  * don't support pipes.  Also, you MUST use the first style if your system
25*dfc6aa5cSAndroid Build Coastguard Worker  * doesn't do binary I/O to stdin/stdout.
26*dfc6aa5cSAndroid Build Coastguard Worker  * To simplify script writing, the "-outfile" switch is provided.  The syntax
27*dfc6aa5cSAndroid Build Coastguard Worker  *      djpeg [options]  -outfile outputfile  inputfile
28*dfc6aa5cSAndroid Build Coastguard Worker  * works regardless of which command line style is used.
29*dfc6aa5cSAndroid Build Coastguard Worker  */
30*dfc6aa5cSAndroid Build Coastguard Worker 
31*dfc6aa5cSAndroid Build Coastguard Worker #ifdef _MSC_VER
32*dfc6aa5cSAndroid Build Coastguard Worker #define _CRT_SECURE_NO_DEPRECATE
33*dfc6aa5cSAndroid Build Coastguard Worker #endif
34*dfc6aa5cSAndroid Build Coastguard Worker 
35*dfc6aa5cSAndroid Build Coastguard Worker #include "cdjpeg.h"             /* Common decls for cjpeg/djpeg applications */
36*dfc6aa5cSAndroid Build Coastguard Worker #include "jversion.h"           /* for version message */
37*dfc6aa5cSAndroid Build Coastguard Worker #include "jconfigint.h"
38*dfc6aa5cSAndroid Build Coastguard Worker 
39*dfc6aa5cSAndroid Build Coastguard Worker #include <ctype.h>              /* to declare isprint() */
40*dfc6aa5cSAndroid Build Coastguard Worker 
41*dfc6aa5cSAndroid Build Coastguard Worker 
42*dfc6aa5cSAndroid Build Coastguard Worker /* Create the add-on message string table. */
43*dfc6aa5cSAndroid Build Coastguard Worker 
44*dfc6aa5cSAndroid Build Coastguard Worker #define JMESSAGE(code, string)  string,
45*dfc6aa5cSAndroid Build Coastguard Worker 
46*dfc6aa5cSAndroid Build Coastguard Worker static const char * const cdjpeg_message_table[] = {
47*dfc6aa5cSAndroid Build Coastguard Worker #include "cderror.h"
48*dfc6aa5cSAndroid Build Coastguard Worker   NULL
49*dfc6aa5cSAndroid Build Coastguard Worker };
50*dfc6aa5cSAndroid Build Coastguard Worker 
51*dfc6aa5cSAndroid Build Coastguard Worker 
52*dfc6aa5cSAndroid Build Coastguard Worker /*
53*dfc6aa5cSAndroid Build Coastguard Worker  * This list defines the known output image formats
54*dfc6aa5cSAndroid Build Coastguard Worker  * (not all of which need be supported by a given version).
55*dfc6aa5cSAndroid Build Coastguard Worker  * You can change the default output format by defining DEFAULT_FMT;
56*dfc6aa5cSAndroid Build Coastguard Worker  * indeed, you had better do so if you undefine PPM_SUPPORTED.
57*dfc6aa5cSAndroid Build Coastguard Worker  */
58*dfc6aa5cSAndroid Build Coastguard Worker 
59*dfc6aa5cSAndroid Build Coastguard Worker typedef enum {
60*dfc6aa5cSAndroid Build Coastguard Worker   FMT_BMP,                      /* BMP format (Windows flavor) */
61*dfc6aa5cSAndroid Build Coastguard Worker   FMT_GIF,                      /* GIF format (LZW-compressed) */
62*dfc6aa5cSAndroid Build Coastguard Worker   FMT_GIF0,                     /* GIF format (uncompressed) */
63*dfc6aa5cSAndroid Build Coastguard Worker   FMT_OS2,                      /* BMP format (OS/2 flavor) */
64*dfc6aa5cSAndroid Build Coastguard Worker   FMT_PPM,                      /* PPM/PGM (PBMPLUS formats) */
65*dfc6aa5cSAndroid Build Coastguard Worker   FMT_TARGA,                    /* Targa format */
66*dfc6aa5cSAndroid Build Coastguard Worker   FMT_TIFF                      /* TIFF format */
67*dfc6aa5cSAndroid Build Coastguard Worker } IMAGE_FORMATS;
68*dfc6aa5cSAndroid Build Coastguard Worker 
69*dfc6aa5cSAndroid Build Coastguard Worker #ifndef DEFAULT_FMT             /* so can override from CFLAGS in Makefile */
70*dfc6aa5cSAndroid Build Coastguard Worker #define DEFAULT_FMT     FMT_PPM
71*dfc6aa5cSAndroid Build Coastguard Worker #endif
72*dfc6aa5cSAndroid Build Coastguard Worker 
73*dfc6aa5cSAndroid Build Coastguard Worker static IMAGE_FORMATS requested_fmt;
74*dfc6aa5cSAndroid Build Coastguard Worker 
75*dfc6aa5cSAndroid Build Coastguard Worker 
76*dfc6aa5cSAndroid Build Coastguard Worker /*
77*dfc6aa5cSAndroid Build Coastguard Worker  * Argument-parsing code.
78*dfc6aa5cSAndroid Build Coastguard Worker  * The switch parser is designed to be useful with DOS-style command line
79*dfc6aa5cSAndroid Build Coastguard Worker  * syntax, ie, intermixed switches and file names, where only the switches
80*dfc6aa5cSAndroid Build Coastguard Worker  * to the left of a given file name affect processing of that file.
81*dfc6aa5cSAndroid Build Coastguard Worker  * The main program in this file doesn't actually use this capability...
82*dfc6aa5cSAndroid Build Coastguard Worker  */
83*dfc6aa5cSAndroid Build Coastguard Worker 
84*dfc6aa5cSAndroid Build Coastguard Worker 
85*dfc6aa5cSAndroid Build Coastguard Worker static const char *progname;    /* program name for error messages */
86*dfc6aa5cSAndroid Build Coastguard Worker static char *icc_filename;      /* for -icc switch */
87*dfc6aa5cSAndroid Build Coastguard Worker static JDIMENSION max_scans;    /* for -maxscans switch */
88*dfc6aa5cSAndroid Build Coastguard Worker static char *outfilename;       /* for -outfile switch */
89*dfc6aa5cSAndroid Build Coastguard Worker static boolean memsrc;          /* for -memsrc switch */
90*dfc6aa5cSAndroid Build Coastguard Worker static boolean report;          /* for -report switch */
91*dfc6aa5cSAndroid Build Coastguard Worker boolean skip, crop;
92*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION skip_start, skip_end;
93*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION crop_x, crop_y, crop_width, crop_height;
94*dfc6aa5cSAndroid Build Coastguard Worker static boolean strict;          /* for -strict switch */
95*dfc6aa5cSAndroid Build Coastguard Worker #define INPUT_BUF_SIZE  4096
96*dfc6aa5cSAndroid Build Coastguard Worker 
97*dfc6aa5cSAndroid Build Coastguard Worker 
98*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
usage(void)99*dfc6aa5cSAndroid Build Coastguard Worker usage(void)
100*dfc6aa5cSAndroid Build Coastguard Worker /* complain about bad command line */
101*dfc6aa5cSAndroid Build Coastguard Worker {
102*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "usage: %s [switches] ", progname);
103*dfc6aa5cSAndroid Build Coastguard Worker #ifdef TWO_FILE_COMMANDLINE
104*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "inputfile outputfile\n");
105*dfc6aa5cSAndroid Build Coastguard Worker #else
106*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "[inputfile]\n");
107*dfc6aa5cSAndroid Build Coastguard Worker #endif
108*dfc6aa5cSAndroid Build Coastguard Worker 
109*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "Switches (names may be abbreviated):\n");
110*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -colors N      Reduce image to no more than N colors\n");
111*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -fast          Fast, low-quality processing\n");
112*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -grayscale     Force grayscale output\n");
113*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -rgb           Force RGB output\n");
114*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -rgb565        Force RGB565 output\n");
115*dfc6aa5cSAndroid Build Coastguard Worker #ifdef IDCT_SCALING_SUPPORTED
116*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -scale M/N     Scale output image by fraction M/N, eg, 1/8\n");
117*dfc6aa5cSAndroid Build Coastguard Worker #endif
118*dfc6aa5cSAndroid Build Coastguard Worker #ifdef BMP_SUPPORTED
119*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -bmp           Select BMP output format (Windows style)%s\n",
120*dfc6aa5cSAndroid Build Coastguard Worker           (DEFAULT_FMT == FMT_BMP ? " (default)" : ""));
121*dfc6aa5cSAndroid Build Coastguard Worker #endif
122*dfc6aa5cSAndroid Build Coastguard Worker #ifdef GIF_SUPPORTED
123*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -gif           Select GIF output format (LZW-compressed)%s\n",
124*dfc6aa5cSAndroid Build Coastguard Worker           (DEFAULT_FMT == FMT_GIF ? " (default)" : ""));
125*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -gif0          Select GIF output format (uncompressed)%s\n",
126*dfc6aa5cSAndroid Build Coastguard Worker           (DEFAULT_FMT == FMT_GIF0 ? " (default)" : ""));
127*dfc6aa5cSAndroid Build Coastguard Worker #endif
128*dfc6aa5cSAndroid Build Coastguard Worker #ifdef BMP_SUPPORTED
129*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -os2           Select BMP output format (OS/2 style)%s\n",
130*dfc6aa5cSAndroid Build Coastguard Worker           (DEFAULT_FMT == FMT_OS2 ? " (default)" : ""));
131*dfc6aa5cSAndroid Build Coastguard Worker #endif
132*dfc6aa5cSAndroid Build Coastguard Worker #ifdef PPM_SUPPORTED
133*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -pnm           Select PBMPLUS (PPM/PGM) output format%s\n",
134*dfc6aa5cSAndroid Build Coastguard Worker           (DEFAULT_FMT == FMT_PPM ? " (default)" : ""));
135*dfc6aa5cSAndroid Build Coastguard Worker #endif
136*dfc6aa5cSAndroid Build Coastguard Worker #ifdef TARGA_SUPPORTED
137*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -targa         Select Targa output format%s\n",
138*dfc6aa5cSAndroid Build Coastguard Worker           (DEFAULT_FMT == FMT_TARGA ? " (default)" : ""));
139*dfc6aa5cSAndroid Build Coastguard Worker #endif
140*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "Switches for advanced users:\n");
141*dfc6aa5cSAndroid Build Coastguard Worker #ifdef DCT_ISLOW_SUPPORTED
142*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -dct int       Use accurate integer DCT method%s\n",
143*dfc6aa5cSAndroid Build Coastguard Worker           (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
144*dfc6aa5cSAndroid Build Coastguard Worker #endif
145*dfc6aa5cSAndroid Build Coastguard Worker #ifdef DCT_IFAST_SUPPORTED
146*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -dct fast      Use less accurate integer DCT method [legacy feature]%s\n",
147*dfc6aa5cSAndroid Build Coastguard Worker           (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
148*dfc6aa5cSAndroid Build Coastguard Worker #endif
149*dfc6aa5cSAndroid Build Coastguard Worker #ifdef DCT_FLOAT_SUPPORTED
150*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -dct float     Use floating-point DCT method [legacy feature]%s\n",
151*dfc6aa5cSAndroid Build Coastguard Worker           (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
152*dfc6aa5cSAndroid Build Coastguard Worker #endif
153*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -dither fs     Use F-S dithering (default)\n");
154*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -dither none   Don't use dithering in quantization\n");
155*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -dither ordered  Use ordered dither (medium speed, quality)\n");
156*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -icc FILE      Extract ICC profile to FILE\n");
157*dfc6aa5cSAndroid Build Coastguard Worker #ifdef QUANT_2PASS_SUPPORTED
158*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -map FILE      Map to colors used in named image file\n");
159*dfc6aa5cSAndroid Build Coastguard Worker #endif
160*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -nosmooth      Don't use high-quality upsampling\n");
161*dfc6aa5cSAndroid Build Coastguard Worker #ifdef QUANT_1PASS_SUPPORTED
162*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -onepass       Use 1-pass quantization (fast, low quality)\n");
163*dfc6aa5cSAndroid Build Coastguard Worker #endif
164*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -maxmemory N   Maximum memory to use (in kbytes)\n");
165*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -maxscans N    Maximum number of scans to allow in input file\n");
166*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -outfile name  Specify name for output file\n");
167*dfc6aa5cSAndroid Build Coastguard Worker #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
168*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -memsrc        Load input file into memory before decompressing\n");
169*dfc6aa5cSAndroid Build Coastguard Worker #endif
170*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -report        Report decompression progress\n");
171*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -skip Y0,Y1    Decompress all rows except those between Y0 and Y1 (inclusive)\n");
172*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -crop WxH+X+Y  Decompress only a rectangular subregion of the image\n");
173*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "                 [requires PBMPLUS (PPM/PGM), GIF, or Targa output format]\n");
174*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -strict        Treat all warnings as fatal\n");
175*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -verbose  or  -debug   Emit debug output\n");
176*dfc6aa5cSAndroid Build Coastguard Worker   fprintf(stderr, "  -version       Print version information and exit\n");
177*dfc6aa5cSAndroid Build Coastguard Worker   exit(EXIT_FAILURE);
178*dfc6aa5cSAndroid Build Coastguard Worker }
179*dfc6aa5cSAndroid Build Coastguard Worker 
180*dfc6aa5cSAndroid Build Coastguard Worker 
181*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(int)
parse_switches(j_decompress_ptr cinfo,int argc,char ** argv,int last_file_arg_seen,boolean for_real)182*dfc6aa5cSAndroid Build Coastguard Worker parse_switches(j_decompress_ptr cinfo, int argc, char **argv,
183*dfc6aa5cSAndroid Build Coastguard Worker                int last_file_arg_seen, boolean for_real)
184*dfc6aa5cSAndroid Build Coastguard Worker /* Parse optional switches.
185*dfc6aa5cSAndroid Build Coastguard Worker  * Returns argv[] index of first file-name argument (== argc if none).
186*dfc6aa5cSAndroid Build Coastguard Worker  * Any file names with indexes <= last_file_arg_seen are ignored;
187*dfc6aa5cSAndroid Build Coastguard Worker  * they have presumably been processed in a previous iteration.
188*dfc6aa5cSAndroid Build Coastguard Worker  * (Pass 0 for last_file_arg_seen on the first or only iteration.)
189*dfc6aa5cSAndroid Build Coastguard Worker  * for_real is FALSE on the first (dummy) pass; we may skip any expensive
190*dfc6aa5cSAndroid Build Coastguard Worker  * processing.
191*dfc6aa5cSAndroid Build Coastguard Worker  */
192*dfc6aa5cSAndroid Build Coastguard Worker {
193*dfc6aa5cSAndroid Build Coastguard Worker   int argn;
194*dfc6aa5cSAndroid Build Coastguard Worker   char *arg;
195*dfc6aa5cSAndroid Build Coastguard Worker 
196*dfc6aa5cSAndroid Build Coastguard Worker   /* Set up default JPEG parameters. */
197*dfc6aa5cSAndroid Build Coastguard Worker   requested_fmt = DEFAULT_FMT;  /* set default output file format */
198*dfc6aa5cSAndroid Build Coastguard Worker   icc_filename = NULL;
199*dfc6aa5cSAndroid Build Coastguard Worker   max_scans = 0;
200*dfc6aa5cSAndroid Build Coastguard Worker   outfilename = NULL;
201*dfc6aa5cSAndroid Build Coastguard Worker   memsrc = FALSE;
202*dfc6aa5cSAndroid Build Coastguard Worker   report = FALSE;
203*dfc6aa5cSAndroid Build Coastguard Worker   skip = FALSE;
204*dfc6aa5cSAndroid Build Coastguard Worker   crop = FALSE;
205*dfc6aa5cSAndroid Build Coastguard Worker   strict = FALSE;
206*dfc6aa5cSAndroid Build Coastguard Worker   cinfo->err->trace_level = 0;
207*dfc6aa5cSAndroid Build Coastguard Worker 
208*dfc6aa5cSAndroid Build Coastguard Worker   /* Scan command line options, adjust parameters */
209*dfc6aa5cSAndroid Build Coastguard Worker 
210*dfc6aa5cSAndroid Build Coastguard Worker   for (argn = 1; argn < argc; argn++) {
211*dfc6aa5cSAndroid Build Coastguard Worker     arg = argv[argn];
212*dfc6aa5cSAndroid Build Coastguard Worker     if (*arg != '-') {
213*dfc6aa5cSAndroid Build Coastguard Worker       /* Not a switch, must be a file name argument */
214*dfc6aa5cSAndroid Build Coastguard Worker       if (argn <= last_file_arg_seen) {
215*dfc6aa5cSAndroid Build Coastguard Worker         outfilename = NULL;     /* -outfile applies to just one input file */
216*dfc6aa5cSAndroid Build Coastguard Worker         continue;               /* ignore this name if previously processed */
217*dfc6aa5cSAndroid Build Coastguard Worker       }
218*dfc6aa5cSAndroid Build Coastguard Worker       break;                    /* else done parsing switches */
219*dfc6aa5cSAndroid Build Coastguard Worker     }
220*dfc6aa5cSAndroid Build Coastguard Worker     arg++;                      /* advance past switch marker character */
221*dfc6aa5cSAndroid Build Coastguard Worker 
222*dfc6aa5cSAndroid Build Coastguard Worker     if (keymatch(arg, "bmp", 1)) {
223*dfc6aa5cSAndroid Build Coastguard Worker       /* BMP output format (Windows flavor). */
224*dfc6aa5cSAndroid Build Coastguard Worker       requested_fmt = FMT_BMP;
225*dfc6aa5cSAndroid Build Coastguard Worker 
226*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) ||
227*dfc6aa5cSAndroid Build Coastguard Worker                keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) {
228*dfc6aa5cSAndroid Build Coastguard Worker       /* Do color quantization. */
229*dfc6aa5cSAndroid Build Coastguard Worker       int val;
230*dfc6aa5cSAndroid Build Coastguard Worker 
231*dfc6aa5cSAndroid Build Coastguard Worker       if (++argn >= argc)       /* advance to next argument */
232*dfc6aa5cSAndroid Build Coastguard Worker         usage();
233*dfc6aa5cSAndroid Build Coastguard Worker       if (sscanf(argv[argn], "%d", &val) != 1)
234*dfc6aa5cSAndroid Build Coastguard Worker         usage();
235*dfc6aa5cSAndroid Build Coastguard Worker       cinfo->desired_number_of_colors = val;
236*dfc6aa5cSAndroid Build Coastguard Worker       cinfo->quantize_colors = TRUE;
237*dfc6aa5cSAndroid Build Coastguard Worker 
238*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "dct", 2)) {
239*dfc6aa5cSAndroid Build Coastguard Worker       /* Select IDCT algorithm. */
240*dfc6aa5cSAndroid Build Coastguard Worker       if (++argn >= argc)       /* advance to next argument */
241*dfc6aa5cSAndroid Build Coastguard Worker         usage();
242*dfc6aa5cSAndroid Build Coastguard Worker       if (keymatch(argv[argn], "int", 1)) {
243*dfc6aa5cSAndroid Build Coastguard Worker         cinfo->dct_method = JDCT_ISLOW;
244*dfc6aa5cSAndroid Build Coastguard Worker       } else if (keymatch(argv[argn], "fast", 2)) {
245*dfc6aa5cSAndroid Build Coastguard Worker         cinfo->dct_method = JDCT_IFAST;
246*dfc6aa5cSAndroid Build Coastguard Worker       } else if (keymatch(argv[argn], "float", 2)) {
247*dfc6aa5cSAndroid Build Coastguard Worker         cinfo->dct_method = JDCT_FLOAT;
248*dfc6aa5cSAndroid Build Coastguard Worker       } else
249*dfc6aa5cSAndroid Build Coastguard Worker         usage();
250*dfc6aa5cSAndroid Build Coastguard Worker 
251*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "dither", 2)) {
252*dfc6aa5cSAndroid Build Coastguard Worker       /* Select dithering algorithm. */
253*dfc6aa5cSAndroid Build Coastguard Worker       if (++argn >= argc)       /* advance to next argument */
254*dfc6aa5cSAndroid Build Coastguard Worker         usage();
255*dfc6aa5cSAndroid Build Coastguard Worker       if (keymatch(argv[argn], "fs", 2)) {
256*dfc6aa5cSAndroid Build Coastguard Worker         cinfo->dither_mode = JDITHER_FS;
257*dfc6aa5cSAndroid Build Coastguard Worker       } else if (keymatch(argv[argn], "none", 2)) {
258*dfc6aa5cSAndroid Build Coastguard Worker         cinfo->dither_mode = JDITHER_NONE;
259*dfc6aa5cSAndroid Build Coastguard Worker       } else if (keymatch(argv[argn], "ordered", 2)) {
260*dfc6aa5cSAndroid Build Coastguard Worker         cinfo->dither_mode = JDITHER_ORDERED;
261*dfc6aa5cSAndroid Build Coastguard Worker       } else
262*dfc6aa5cSAndroid Build Coastguard Worker         usage();
263*dfc6aa5cSAndroid Build Coastguard Worker 
264*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
265*dfc6aa5cSAndroid Build Coastguard Worker       /* Enable debug printouts. */
266*dfc6aa5cSAndroid Build Coastguard Worker       /* On first -d, print version identification */
267*dfc6aa5cSAndroid Build Coastguard Worker       static boolean printed_version = FALSE;
268*dfc6aa5cSAndroid Build Coastguard Worker 
269*dfc6aa5cSAndroid Build Coastguard Worker       if (!printed_version) {
270*dfc6aa5cSAndroid Build Coastguard Worker         fprintf(stderr, "%s version %s (build %s)\n",
271*dfc6aa5cSAndroid Build Coastguard Worker                 PACKAGE_NAME, VERSION, BUILD);
272*dfc6aa5cSAndroid Build Coastguard Worker         fprintf(stderr, "%s\n\n", JCOPYRIGHT);
273*dfc6aa5cSAndroid Build Coastguard Worker         fprintf(stderr, "Emulating The Independent JPEG Group's software, version %s\n\n",
274*dfc6aa5cSAndroid Build Coastguard Worker                 JVERSION);
275*dfc6aa5cSAndroid Build Coastguard Worker         printed_version = TRUE;
276*dfc6aa5cSAndroid Build Coastguard Worker       }
277*dfc6aa5cSAndroid Build Coastguard Worker       cinfo->err->trace_level++;
278*dfc6aa5cSAndroid Build Coastguard Worker 
279*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "version", 4)) {
280*dfc6aa5cSAndroid Build Coastguard Worker       fprintf(stderr, "%s version %s (build %s)\n",
281*dfc6aa5cSAndroid Build Coastguard Worker               PACKAGE_NAME, VERSION, BUILD);
282*dfc6aa5cSAndroid Build Coastguard Worker       exit(EXIT_SUCCESS);
283*dfc6aa5cSAndroid Build Coastguard Worker 
284*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "fast", 1)) {
285*dfc6aa5cSAndroid Build Coastguard Worker       /* Select recommended processing options for quick-and-dirty output. */
286*dfc6aa5cSAndroid Build Coastguard Worker       cinfo->two_pass_quantize = FALSE;
287*dfc6aa5cSAndroid Build Coastguard Worker       cinfo->dither_mode = JDITHER_ORDERED;
288*dfc6aa5cSAndroid Build Coastguard Worker       if (!cinfo->quantize_colors) /* don't override an earlier -colors */
289*dfc6aa5cSAndroid Build Coastguard Worker         cinfo->desired_number_of_colors = 216;
290*dfc6aa5cSAndroid Build Coastguard Worker       cinfo->dct_method = JDCT_FASTEST;
291*dfc6aa5cSAndroid Build Coastguard Worker       cinfo->do_fancy_upsampling = FALSE;
292*dfc6aa5cSAndroid Build Coastguard Worker 
293*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "gif", 1)) {
294*dfc6aa5cSAndroid Build Coastguard Worker       /* GIF output format (LZW-compressed). */
295*dfc6aa5cSAndroid Build Coastguard Worker       requested_fmt = FMT_GIF;
296*dfc6aa5cSAndroid Build Coastguard Worker 
297*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "gif0", 4)) {
298*dfc6aa5cSAndroid Build Coastguard Worker       /* GIF output format (uncompressed). */
299*dfc6aa5cSAndroid Build Coastguard Worker       requested_fmt = FMT_GIF0;
300*dfc6aa5cSAndroid Build Coastguard Worker 
301*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "grayscale", 2) ||
302*dfc6aa5cSAndroid Build Coastguard Worker                keymatch(arg, "greyscale", 2)) {
303*dfc6aa5cSAndroid Build Coastguard Worker       /* Force monochrome output. */
304*dfc6aa5cSAndroid Build Coastguard Worker       cinfo->out_color_space = JCS_GRAYSCALE;
305*dfc6aa5cSAndroid Build Coastguard Worker 
306*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "rgb", 2)) {
307*dfc6aa5cSAndroid Build Coastguard Worker       /* Force RGB output. */
308*dfc6aa5cSAndroid Build Coastguard Worker       cinfo->out_color_space = JCS_RGB;
309*dfc6aa5cSAndroid Build Coastguard Worker 
310*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "rgb565", 2)) {
311*dfc6aa5cSAndroid Build Coastguard Worker       /* Force RGB565 output. */
312*dfc6aa5cSAndroid Build Coastguard Worker       cinfo->out_color_space = JCS_RGB565;
313*dfc6aa5cSAndroid Build Coastguard Worker 
314*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "icc", 1)) {
315*dfc6aa5cSAndroid Build Coastguard Worker       /* Set ICC filename. */
316*dfc6aa5cSAndroid Build Coastguard Worker       if (++argn >= argc)       /* advance to next argument */
317*dfc6aa5cSAndroid Build Coastguard Worker         usage();
318*dfc6aa5cSAndroid Build Coastguard Worker       icc_filename = argv[argn];
319*dfc6aa5cSAndroid Build Coastguard Worker #ifdef SAVE_MARKERS_SUPPORTED
320*dfc6aa5cSAndroid Build Coastguard Worker       jpeg_save_markers(cinfo, JPEG_APP0 + 2, 0xFFFF);
321*dfc6aa5cSAndroid Build Coastguard Worker #endif
322*dfc6aa5cSAndroid Build Coastguard Worker 
323*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "map", 3)) {
324*dfc6aa5cSAndroid Build Coastguard Worker       /* Quantize to a color map taken from an input file. */
325*dfc6aa5cSAndroid Build Coastguard Worker       if (++argn >= argc)       /* advance to next argument */
326*dfc6aa5cSAndroid Build Coastguard Worker         usage();
327*dfc6aa5cSAndroid Build Coastguard Worker       if (for_real) {           /* too expensive to do twice! */
328*dfc6aa5cSAndroid Build Coastguard Worker #ifdef QUANT_2PASS_SUPPORTED    /* otherwise can't quantize to supplied map */
329*dfc6aa5cSAndroid Build Coastguard Worker         FILE *mapfile;
330*dfc6aa5cSAndroid Build Coastguard Worker 
331*dfc6aa5cSAndroid Build Coastguard Worker         if ((mapfile = fopen(argv[argn], READ_BINARY)) == NULL) {
332*dfc6aa5cSAndroid Build Coastguard Worker           fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
333*dfc6aa5cSAndroid Build Coastguard Worker           exit(EXIT_FAILURE);
334*dfc6aa5cSAndroid Build Coastguard Worker         }
335*dfc6aa5cSAndroid Build Coastguard Worker         read_color_map(cinfo, mapfile);
336*dfc6aa5cSAndroid Build Coastguard Worker         fclose(mapfile);
337*dfc6aa5cSAndroid Build Coastguard Worker         cinfo->quantize_colors = TRUE;
338*dfc6aa5cSAndroid Build Coastguard Worker #else
339*dfc6aa5cSAndroid Build Coastguard Worker         ERREXIT(cinfo, JERR_NOT_COMPILED);
340*dfc6aa5cSAndroid Build Coastguard Worker #endif
341*dfc6aa5cSAndroid Build Coastguard Worker       }
342*dfc6aa5cSAndroid Build Coastguard Worker 
343*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "maxmemory", 3)) {
344*dfc6aa5cSAndroid Build Coastguard Worker       /* Maximum memory in Kb (or Mb with 'm'). */
345*dfc6aa5cSAndroid Build Coastguard Worker       long lval;
346*dfc6aa5cSAndroid Build Coastguard Worker       char ch = 'x';
347*dfc6aa5cSAndroid Build Coastguard Worker 
348*dfc6aa5cSAndroid Build Coastguard Worker       if (++argn >= argc)       /* advance to next argument */
349*dfc6aa5cSAndroid Build Coastguard Worker         usage();
350*dfc6aa5cSAndroid Build Coastguard Worker       if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
351*dfc6aa5cSAndroid Build Coastguard Worker         usage();
352*dfc6aa5cSAndroid Build Coastguard Worker       if (ch == 'm' || ch == 'M')
353*dfc6aa5cSAndroid Build Coastguard Worker         lval *= 1000L;
354*dfc6aa5cSAndroid Build Coastguard Worker       cinfo->mem->max_memory_to_use = lval * 1000L;
355*dfc6aa5cSAndroid Build Coastguard Worker 
356*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "maxscans", 4)) {
357*dfc6aa5cSAndroid Build Coastguard Worker       if (++argn >= argc)       /* advance to next argument */
358*dfc6aa5cSAndroid Build Coastguard Worker         usage();
359*dfc6aa5cSAndroid Build Coastguard Worker       if (sscanf(argv[argn], "%u", &max_scans) != 1)
360*dfc6aa5cSAndroid Build Coastguard Worker         usage();
361*dfc6aa5cSAndroid Build Coastguard Worker 
362*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "nosmooth", 3)) {
363*dfc6aa5cSAndroid Build Coastguard Worker       /* Suppress fancy upsampling */
364*dfc6aa5cSAndroid Build Coastguard Worker       cinfo->do_fancy_upsampling = FALSE;
365*dfc6aa5cSAndroid Build Coastguard Worker 
366*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "onepass", 3)) {
367*dfc6aa5cSAndroid Build Coastguard Worker       /* Use fast one-pass quantization. */
368*dfc6aa5cSAndroid Build Coastguard Worker       cinfo->two_pass_quantize = FALSE;
369*dfc6aa5cSAndroid Build Coastguard Worker 
370*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "os2", 3)) {
371*dfc6aa5cSAndroid Build Coastguard Worker       /* BMP output format (OS/2 flavor). */
372*dfc6aa5cSAndroid Build Coastguard Worker       requested_fmt = FMT_OS2;
373*dfc6aa5cSAndroid Build Coastguard Worker 
374*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "outfile", 4)) {
375*dfc6aa5cSAndroid Build Coastguard Worker       /* Set output file name. */
376*dfc6aa5cSAndroid Build Coastguard Worker       if (++argn >= argc)       /* advance to next argument */
377*dfc6aa5cSAndroid Build Coastguard Worker         usage();
378*dfc6aa5cSAndroid Build Coastguard Worker       outfilename = argv[argn]; /* save it away for later use */
379*dfc6aa5cSAndroid Build Coastguard Worker 
380*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "memsrc", 2)) {
381*dfc6aa5cSAndroid Build Coastguard Worker       /* Use in-memory source manager */
382*dfc6aa5cSAndroid Build Coastguard Worker #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
383*dfc6aa5cSAndroid Build Coastguard Worker       memsrc = TRUE;
384*dfc6aa5cSAndroid Build Coastguard Worker #else
385*dfc6aa5cSAndroid Build Coastguard Worker       fprintf(stderr, "%s: sorry, in-memory source manager was not compiled in\n",
386*dfc6aa5cSAndroid Build Coastguard Worker               progname);
387*dfc6aa5cSAndroid Build Coastguard Worker       exit(EXIT_FAILURE);
388*dfc6aa5cSAndroid Build Coastguard Worker #endif
389*dfc6aa5cSAndroid Build Coastguard Worker 
390*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) {
391*dfc6aa5cSAndroid Build Coastguard Worker       /* PPM/PGM output format. */
392*dfc6aa5cSAndroid Build Coastguard Worker       requested_fmt = FMT_PPM;
393*dfc6aa5cSAndroid Build Coastguard Worker 
394*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "report", 2)) {
395*dfc6aa5cSAndroid Build Coastguard Worker       report = TRUE;
396*dfc6aa5cSAndroid Build Coastguard Worker 
397*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "scale", 2)) {
398*dfc6aa5cSAndroid Build Coastguard Worker       /* Scale the output image by a fraction M/N. */
399*dfc6aa5cSAndroid Build Coastguard Worker       if (++argn >= argc)       /* advance to next argument */
400*dfc6aa5cSAndroid Build Coastguard Worker         usage();
401*dfc6aa5cSAndroid Build Coastguard Worker       if (sscanf(argv[argn], "%u/%u",
402*dfc6aa5cSAndroid Build Coastguard Worker                  &cinfo->scale_num, &cinfo->scale_denom) != 2)
403*dfc6aa5cSAndroid Build Coastguard Worker         usage();
404*dfc6aa5cSAndroid Build Coastguard Worker 
405*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "skip", 2)) {
406*dfc6aa5cSAndroid Build Coastguard Worker       if (++argn >= argc)
407*dfc6aa5cSAndroid Build Coastguard Worker         usage();
408*dfc6aa5cSAndroid Build Coastguard Worker       if (sscanf(argv[argn], "%u,%u", &skip_start, &skip_end) != 2 ||
409*dfc6aa5cSAndroid Build Coastguard Worker           skip_start > skip_end)
410*dfc6aa5cSAndroid Build Coastguard Worker         usage();
411*dfc6aa5cSAndroid Build Coastguard Worker       skip = TRUE;
412*dfc6aa5cSAndroid Build Coastguard Worker 
413*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "crop", 2)) {
414*dfc6aa5cSAndroid Build Coastguard Worker       char c;
415*dfc6aa5cSAndroid Build Coastguard Worker       if (++argn >= argc)
416*dfc6aa5cSAndroid Build Coastguard Worker         usage();
417*dfc6aa5cSAndroid Build Coastguard Worker       if (sscanf(argv[argn], "%u%c%u+%u+%u", &crop_width, &c, &crop_height,
418*dfc6aa5cSAndroid Build Coastguard Worker                  &crop_x, &crop_y) != 5 ||
419*dfc6aa5cSAndroid Build Coastguard Worker           (c != 'X' && c != 'x') || crop_width < 1 || crop_height < 1)
420*dfc6aa5cSAndroid Build Coastguard Worker         usage();
421*dfc6aa5cSAndroid Build Coastguard Worker       crop = TRUE;
422*dfc6aa5cSAndroid Build Coastguard Worker 
423*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "strict", 2)) {
424*dfc6aa5cSAndroid Build Coastguard Worker       strict = TRUE;
425*dfc6aa5cSAndroid Build Coastguard Worker 
426*dfc6aa5cSAndroid Build Coastguard Worker     } else if (keymatch(arg, "targa", 1)) {
427*dfc6aa5cSAndroid Build Coastguard Worker       /* Targa output format. */
428*dfc6aa5cSAndroid Build Coastguard Worker       requested_fmt = FMT_TARGA;
429*dfc6aa5cSAndroid Build Coastguard Worker 
430*dfc6aa5cSAndroid Build Coastguard Worker     } else {
431*dfc6aa5cSAndroid Build Coastguard Worker       usage();                  /* bogus switch */
432*dfc6aa5cSAndroid Build Coastguard Worker     }
433*dfc6aa5cSAndroid Build Coastguard Worker   }
434*dfc6aa5cSAndroid Build Coastguard Worker 
435*dfc6aa5cSAndroid Build Coastguard Worker   return argn;                  /* return index of next arg (file name) */
436*dfc6aa5cSAndroid Build Coastguard Worker }
437*dfc6aa5cSAndroid Build Coastguard Worker 
438*dfc6aa5cSAndroid Build Coastguard Worker 
439*dfc6aa5cSAndroid Build Coastguard Worker /*
440*dfc6aa5cSAndroid Build Coastguard Worker  * Marker processor for COM and interesting APPn markers.
441*dfc6aa5cSAndroid Build Coastguard Worker  * This replaces the library's built-in processor, which just skips the marker.
442*dfc6aa5cSAndroid Build Coastguard Worker  * We want to print out the marker as text, to the extent possible.
443*dfc6aa5cSAndroid Build Coastguard Worker  * Note this code relies on a non-suspending data source.
444*dfc6aa5cSAndroid Build Coastguard Worker  */
445*dfc6aa5cSAndroid Build Coastguard Worker 
446*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(unsigned int)
jpeg_getc(j_decompress_ptr cinfo)447*dfc6aa5cSAndroid Build Coastguard Worker jpeg_getc(j_decompress_ptr cinfo)
448*dfc6aa5cSAndroid Build Coastguard Worker /* Read next byte */
449*dfc6aa5cSAndroid Build Coastguard Worker {
450*dfc6aa5cSAndroid Build Coastguard Worker   struct jpeg_source_mgr *datasrc = cinfo->src;
451*dfc6aa5cSAndroid Build Coastguard Worker 
452*dfc6aa5cSAndroid Build Coastguard Worker   if (datasrc->bytes_in_buffer == 0) {
453*dfc6aa5cSAndroid Build Coastguard Worker     if (!(*datasrc->fill_input_buffer) (cinfo))
454*dfc6aa5cSAndroid Build Coastguard Worker       ERREXIT(cinfo, JERR_CANT_SUSPEND);
455*dfc6aa5cSAndroid Build Coastguard Worker   }
456*dfc6aa5cSAndroid Build Coastguard Worker   datasrc->bytes_in_buffer--;
457*dfc6aa5cSAndroid Build Coastguard Worker   return *datasrc->next_input_byte++;
458*dfc6aa5cSAndroid Build Coastguard Worker }
459*dfc6aa5cSAndroid Build Coastguard Worker 
460*dfc6aa5cSAndroid Build Coastguard Worker 
461*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(boolean)
print_text_marker(j_decompress_ptr cinfo)462*dfc6aa5cSAndroid Build Coastguard Worker print_text_marker(j_decompress_ptr cinfo)
463*dfc6aa5cSAndroid Build Coastguard Worker {
464*dfc6aa5cSAndroid Build Coastguard Worker   boolean traceit = (cinfo->err->trace_level >= 1);
465*dfc6aa5cSAndroid Build Coastguard Worker   long length;
466*dfc6aa5cSAndroid Build Coastguard Worker   unsigned int ch;
467*dfc6aa5cSAndroid Build Coastguard Worker   unsigned int lastch = 0;
468*dfc6aa5cSAndroid Build Coastguard Worker 
469*dfc6aa5cSAndroid Build Coastguard Worker   length = jpeg_getc(cinfo) << 8;
470*dfc6aa5cSAndroid Build Coastguard Worker   length += jpeg_getc(cinfo);
471*dfc6aa5cSAndroid Build Coastguard Worker   length -= 2;                  /* discount the length word itself */
472*dfc6aa5cSAndroid Build Coastguard Worker 
473*dfc6aa5cSAndroid Build Coastguard Worker   if (traceit) {
474*dfc6aa5cSAndroid Build Coastguard Worker     if (cinfo->unread_marker == JPEG_COM)
475*dfc6aa5cSAndroid Build Coastguard Worker       fprintf(stderr, "Comment, length %ld:\n", (long)length);
476*dfc6aa5cSAndroid Build Coastguard Worker     else                        /* assume it is an APPn otherwise */
477*dfc6aa5cSAndroid Build Coastguard Worker       fprintf(stderr, "APP%d, length %ld:\n",
478*dfc6aa5cSAndroid Build Coastguard Worker               cinfo->unread_marker - JPEG_APP0, (long)length);
479*dfc6aa5cSAndroid Build Coastguard Worker   }
480*dfc6aa5cSAndroid Build Coastguard Worker 
481*dfc6aa5cSAndroid Build Coastguard Worker   while (--length >= 0) {
482*dfc6aa5cSAndroid Build Coastguard Worker     ch = jpeg_getc(cinfo);
483*dfc6aa5cSAndroid Build Coastguard Worker     if (traceit) {
484*dfc6aa5cSAndroid Build Coastguard Worker       /* Emit the character in a readable form.
485*dfc6aa5cSAndroid Build Coastguard Worker        * Nonprintables are converted to \nnn form,
486*dfc6aa5cSAndroid Build Coastguard Worker        * while \ is converted to \\.
487*dfc6aa5cSAndroid Build Coastguard Worker        * Newlines in CR, CR/LF, or LF form will be printed as one newline.
488*dfc6aa5cSAndroid Build Coastguard Worker        */
489*dfc6aa5cSAndroid Build Coastguard Worker       if (ch == '\r') {
490*dfc6aa5cSAndroid Build Coastguard Worker         fprintf(stderr, "\n");
491*dfc6aa5cSAndroid Build Coastguard Worker       } else if (ch == '\n') {
492*dfc6aa5cSAndroid Build Coastguard Worker         if (lastch != '\r')
493*dfc6aa5cSAndroid Build Coastguard Worker           fprintf(stderr, "\n");
494*dfc6aa5cSAndroid Build Coastguard Worker       } else if (ch == '\\') {
495*dfc6aa5cSAndroid Build Coastguard Worker         fprintf(stderr, "\\\\");
496*dfc6aa5cSAndroid Build Coastguard Worker       } else if (isprint(ch)) {
497*dfc6aa5cSAndroid Build Coastguard Worker         putc(ch, stderr);
498*dfc6aa5cSAndroid Build Coastguard Worker       } else {
499*dfc6aa5cSAndroid Build Coastguard Worker         fprintf(stderr, "\\%03o", ch);
500*dfc6aa5cSAndroid Build Coastguard Worker       }
501*dfc6aa5cSAndroid Build Coastguard Worker       lastch = ch;
502*dfc6aa5cSAndroid Build Coastguard Worker     }
503*dfc6aa5cSAndroid Build Coastguard Worker   }
504*dfc6aa5cSAndroid Build Coastguard Worker 
505*dfc6aa5cSAndroid Build Coastguard Worker   if (traceit)
506*dfc6aa5cSAndroid Build Coastguard Worker     fprintf(stderr, "\n");
507*dfc6aa5cSAndroid Build Coastguard Worker 
508*dfc6aa5cSAndroid Build Coastguard Worker   return TRUE;
509*dfc6aa5cSAndroid Build Coastguard Worker }
510*dfc6aa5cSAndroid Build Coastguard Worker 
511*dfc6aa5cSAndroid Build Coastguard Worker 
512*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(void)
my_emit_message(j_common_ptr cinfo,int msg_level)513*dfc6aa5cSAndroid Build Coastguard Worker my_emit_message(j_common_ptr cinfo, int msg_level)
514*dfc6aa5cSAndroid Build Coastguard Worker {
515*dfc6aa5cSAndroid Build Coastguard Worker   if (msg_level < 0) {
516*dfc6aa5cSAndroid Build Coastguard Worker     /* Treat warning as fatal */
517*dfc6aa5cSAndroid Build Coastguard Worker     cinfo->err->error_exit(cinfo);
518*dfc6aa5cSAndroid Build Coastguard Worker   } else {
519*dfc6aa5cSAndroid Build Coastguard Worker     if (cinfo->err->trace_level >= msg_level)
520*dfc6aa5cSAndroid Build Coastguard Worker       cinfo->err->output_message(cinfo);
521*dfc6aa5cSAndroid Build Coastguard Worker   }
522*dfc6aa5cSAndroid Build Coastguard Worker }
523*dfc6aa5cSAndroid Build Coastguard Worker 
524*dfc6aa5cSAndroid Build Coastguard Worker 
525*dfc6aa5cSAndroid Build Coastguard Worker /*
526*dfc6aa5cSAndroid Build Coastguard Worker  * The main program.
527*dfc6aa5cSAndroid Build Coastguard Worker  */
528*dfc6aa5cSAndroid Build Coastguard Worker 
529*dfc6aa5cSAndroid Build Coastguard Worker int
530*dfc6aa5cSAndroid Build Coastguard Worker #ifdef GTEST
djpeg(int argc,char ** argv)531*dfc6aa5cSAndroid Build Coastguard Worker djpeg(int argc, char **argv)
532*dfc6aa5cSAndroid Build Coastguard Worker #else
533*dfc6aa5cSAndroid Build Coastguard Worker main(int argc, char **argv)
534*dfc6aa5cSAndroid Build Coastguard Worker #endif
535*dfc6aa5cSAndroid Build Coastguard Worker {
536*dfc6aa5cSAndroid Build Coastguard Worker   struct jpeg_decompress_struct cinfo;
537*dfc6aa5cSAndroid Build Coastguard Worker   struct jpeg_error_mgr jerr;
538*dfc6aa5cSAndroid Build Coastguard Worker   struct cdjpeg_progress_mgr progress;
539*dfc6aa5cSAndroid Build Coastguard Worker   int file_index;
540*dfc6aa5cSAndroid Build Coastguard Worker   djpeg_dest_ptr dest_mgr = NULL;
541*dfc6aa5cSAndroid Build Coastguard Worker   FILE *input_file;
542*dfc6aa5cSAndroid Build Coastguard Worker   FILE *output_file;
543*dfc6aa5cSAndroid Build Coastguard Worker   unsigned char *inbuffer = NULL;
544*dfc6aa5cSAndroid Build Coastguard Worker #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
545*dfc6aa5cSAndroid Build Coastguard Worker   unsigned long insize = 0;
546*dfc6aa5cSAndroid Build Coastguard Worker #endif
547*dfc6aa5cSAndroid Build Coastguard Worker   JDIMENSION num_scanlines;
548*dfc6aa5cSAndroid Build Coastguard Worker 
549*dfc6aa5cSAndroid Build Coastguard Worker   progname = argv[0];
550*dfc6aa5cSAndroid Build Coastguard Worker   if (progname == NULL || progname[0] == 0)
551*dfc6aa5cSAndroid Build Coastguard Worker     progname = "djpeg";         /* in case C library doesn't provide it */
552*dfc6aa5cSAndroid Build Coastguard Worker 
553*dfc6aa5cSAndroid Build Coastguard Worker   /* Initialize the JPEG decompression object with default error handling. */
554*dfc6aa5cSAndroid Build Coastguard Worker   cinfo.err = jpeg_std_error(&jerr);
555*dfc6aa5cSAndroid Build Coastguard Worker   jpeg_create_decompress(&cinfo);
556*dfc6aa5cSAndroid Build Coastguard Worker   /* Add some application-specific error messages (from cderror.h) */
557*dfc6aa5cSAndroid Build Coastguard Worker   jerr.addon_message_table = cdjpeg_message_table;
558*dfc6aa5cSAndroid Build Coastguard Worker   jerr.first_addon_message = JMSG_FIRSTADDONCODE;
559*dfc6aa5cSAndroid Build Coastguard Worker   jerr.last_addon_message = JMSG_LASTADDONCODE;
560*dfc6aa5cSAndroid Build Coastguard Worker 
561*dfc6aa5cSAndroid Build Coastguard Worker   /* Insert custom marker processor for COM and APP12.
562*dfc6aa5cSAndroid Build Coastguard Worker    * APP12 is used by some digital camera makers for textual info,
563*dfc6aa5cSAndroid Build Coastguard Worker    * so we provide the ability to display it as text.
564*dfc6aa5cSAndroid Build Coastguard Worker    * If you like, additional APPn marker types can be selected for display,
565*dfc6aa5cSAndroid Build Coastguard Worker    * but don't try to override APP0 or APP14 this way (see libjpeg.txt).
566*dfc6aa5cSAndroid Build Coastguard Worker    */
567*dfc6aa5cSAndroid Build Coastguard Worker   jpeg_set_marker_processor(&cinfo, JPEG_COM, print_text_marker);
568*dfc6aa5cSAndroid Build Coastguard Worker   jpeg_set_marker_processor(&cinfo, JPEG_APP0 + 12, print_text_marker);
569*dfc6aa5cSAndroid Build Coastguard Worker 
570*dfc6aa5cSAndroid Build Coastguard Worker   /* Scan command line to find file names. */
571*dfc6aa5cSAndroid Build Coastguard Worker   /* It is convenient to use just one switch-parsing routine, but the switch
572*dfc6aa5cSAndroid Build Coastguard Worker    * values read here are ignored; we will rescan the switches after opening
573*dfc6aa5cSAndroid Build Coastguard Worker    * the input file.
574*dfc6aa5cSAndroid Build Coastguard Worker    * (Exception: tracing level set here controls verbosity for COM markers
575*dfc6aa5cSAndroid Build Coastguard Worker    * found during jpeg_read_header...)
576*dfc6aa5cSAndroid Build Coastguard Worker    */
577*dfc6aa5cSAndroid Build Coastguard Worker 
578*dfc6aa5cSAndroid Build Coastguard Worker   file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
579*dfc6aa5cSAndroid Build Coastguard Worker 
580*dfc6aa5cSAndroid Build Coastguard Worker   if (strict)
581*dfc6aa5cSAndroid Build Coastguard Worker     jerr.emit_message = my_emit_message;
582*dfc6aa5cSAndroid Build Coastguard Worker 
583*dfc6aa5cSAndroid Build Coastguard Worker #ifdef TWO_FILE_COMMANDLINE
584*dfc6aa5cSAndroid Build Coastguard Worker   /* Must have either -outfile switch or explicit output file name */
585*dfc6aa5cSAndroid Build Coastguard Worker   if (outfilename == NULL) {
586*dfc6aa5cSAndroid Build Coastguard Worker     if (file_index != argc - 2) {
587*dfc6aa5cSAndroid Build Coastguard Worker       fprintf(stderr, "%s: must name one input and one output file\n",
588*dfc6aa5cSAndroid Build Coastguard Worker               progname);
589*dfc6aa5cSAndroid Build Coastguard Worker       usage();
590*dfc6aa5cSAndroid Build Coastguard Worker     }
591*dfc6aa5cSAndroid Build Coastguard Worker     outfilename = argv[file_index + 1];
592*dfc6aa5cSAndroid Build Coastguard Worker   } else {
593*dfc6aa5cSAndroid Build Coastguard Worker     if (file_index != argc - 1) {
594*dfc6aa5cSAndroid Build Coastguard Worker       fprintf(stderr, "%s: must name one input and one output file\n",
595*dfc6aa5cSAndroid Build Coastguard Worker               progname);
596*dfc6aa5cSAndroid Build Coastguard Worker       usage();
597*dfc6aa5cSAndroid Build Coastguard Worker     }
598*dfc6aa5cSAndroid Build Coastguard Worker   }
599*dfc6aa5cSAndroid Build Coastguard Worker #else
600*dfc6aa5cSAndroid Build Coastguard Worker   /* Unix style: expect zero or one file name */
601*dfc6aa5cSAndroid Build Coastguard Worker   if (file_index < argc - 1) {
602*dfc6aa5cSAndroid Build Coastguard Worker     fprintf(stderr, "%s: only one input file\n", progname);
603*dfc6aa5cSAndroid Build Coastguard Worker     usage();
604*dfc6aa5cSAndroid Build Coastguard Worker   }
605*dfc6aa5cSAndroid Build Coastguard Worker #endif /* TWO_FILE_COMMANDLINE */
606*dfc6aa5cSAndroid Build Coastguard Worker 
607*dfc6aa5cSAndroid Build Coastguard Worker   /* Open the input file. */
608*dfc6aa5cSAndroid Build Coastguard Worker   if (file_index < argc) {
609*dfc6aa5cSAndroid Build Coastguard Worker     if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
610*dfc6aa5cSAndroid Build Coastguard Worker       fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
611*dfc6aa5cSAndroid Build Coastguard Worker       return EXIT_FAILURE;
612*dfc6aa5cSAndroid Build Coastguard Worker     }
613*dfc6aa5cSAndroid Build Coastguard Worker   } else {
614*dfc6aa5cSAndroid Build Coastguard Worker     /* default input file is stdin */
615*dfc6aa5cSAndroid Build Coastguard Worker     input_file = read_stdin();
616*dfc6aa5cSAndroid Build Coastguard Worker   }
617*dfc6aa5cSAndroid Build Coastguard Worker 
618*dfc6aa5cSAndroid Build Coastguard Worker   /* Open the output file. */
619*dfc6aa5cSAndroid Build Coastguard Worker   if (outfilename != NULL) {
620*dfc6aa5cSAndroid Build Coastguard Worker     if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
621*dfc6aa5cSAndroid Build Coastguard Worker       fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
622*dfc6aa5cSAndroid Build Coastguard Worker       return EXIT_FAILURE;
623*dfc6aa5cSAndroid Build Coastguard Worker     }
624*dfc6aa5cSAndroid Build Coastguard Worker   } else {
625*dfc6aa5cSAndroid Build Coastguard Worker     /* default output file is stdout */
626*dfc6aa5cSAndroid Build Coastguard Worker     output_file = write_stdout();
627*dfc6aa5cSAndroid Build Coastguard Worker   }
628*dfc6aa5cSAndroid Build Coastguard Worker 
629*dfc6aa5cSAndroid Build Coastguard Worker   if (report || max_scans != 0) {
630*dfc6aa5cSAndroid Build Coastguard Worker     start_progress_monitor((j_common_ptr)&cinfo, &progress);
631*dfc6aa5cSAndroid Build Coastguard Worker     progress.report = report;
632*dfc6aa5cSAndroid Build Coastguard Worker     progress.max_scans = max_scans;
633*dfc6aa5cSAndroid Build Coastguard Worker   }
634*dfc6aa5cSAndroid Build Coastguard Worker 
635*dfc6aa5cSAndroid Build Coastguard Worker   /* Specify data source for decompression */
636*dfc6aa5cSAndroid Build Coastguard Worker #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
637*dfc6aa5cSAndroid Build Coastguard Worker   if (memsrc) {
638*dfc6aa5cSAndroid Build Coastguard Worker     size_t nbytes;
639*dfc6aa5cSAndroid Build Coastguard Worker     do {
640*dfc6aa5cSAndroid Build Coastguard Worker       inbuffer = (unsigned char *)realloc(inbuffer, insize + INPUT_BUF_SIZE);
641*dfc6aa5cSAndroid Build Coastguard Worker       if (inbuffer == NULL) {
642*dfc6aa5cSAndroid Build Coastguard Worker         fprintf(stderr, "%s: memory allocation failure\n", progname);
643*dfc6aa5cSAndroid Build Coastguard Worker         return EXIT_FAILURE;
644*dfc6aa5cSAndroid Build Coastguard Worker       }
645*dfc6aa5cSAndroid Build Coastguard Worker       nbytes = fread(&inbuffer[insize], 1, INPUT_BUF_SIZE, input_file);
646*dfc6aa5cSAndroid Build Coastguard Worker       if (nbytes < INPUT_BUF_SIZE && ferror(input_file)) {
647*dfc6aa5cSAndroid Build Coastguard Worker         if (file_index < argc)
648*dfc6aa5cSAndroid Build Coastguard Worker           fprintf(stderr, "%s: can't read from %s\n", progname,
649*dfc6aa5cSAndroid Build Coastguard Worker                   argv[file_index]);
650*dfc6aa5cSAndroid Build Coastguard Worker         else
651*dfc6aa5cSAndroid Build Coastguard Worker           fprintf(stderr, "%s: can't read from stdin\n", progname);
652*dfc6aa5cSAndroid Build Coastguard Worker       }
653*dfc6aa5cSAndroid Build Coastguard Worker       insize += (unsigned long)nbytes;
654*dfc6aa5cSAndroid Build Coastguard Worker     } while (nbytes == INPUT_BUF_SIZE);
655*dfc6aa5cSAndroid Build Coastguard Worker     fprintf(stderr, "Compressed size:  %lu bytes\n", insize);
656*dfc6aa5cSAndroid Build Coastguard Worker     jpeg_mem_src(&cinfo, inbuffer, insize);
657*dfc6aa5cSAndroid Build Coastguard Worker   } else
658*dfc6aa5cSAndroid Build Coastguard Worker #endif
659*dfc6aa5cSAndroid Build Coastguard Worker     jpeg_stdio_src(&cinfo, input_file);
660*dfc6aa5cSAndroid Build Coastguard Worker 
661*dfc6aa5cSAndroid Build Coastguard Worker   /* Read file header, set default decompression parameters */
662*dfc6aa5cSAndroid Build Coastguard Worker   (void)jpeg_read_header(&cinfo, TRUE);
663*dfc6aa5cSAndroid Build Coastguard Worker 
664*dfc6aa5cSAndroid Build Coastguard Worker   /* Adjust default decompression parameters by re-parsing the options */
665*dfc6aa5cSAndroid Build Coastguard Worker   file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
666*dfc6aa5cSAndroid Build Coastguard Worker 
667*dfc6aa5cSAndroid Build Coastguard Worker   /* Initialize the output module now to let it override any crucial
668*dfc6aa5cSAndroid Build Coastguard Worker    * option settings (for instance, GIF wants to force color quantization).
669*dfc6aa5cSAndroid Build Coastguard Worker    */
670*dfc6aa5cSAndroid Build Coastguard Worker   switch (requested_fmt) {
671*dfc6aa5cSAndroid Build Coastguard Worker #ifdef BMP_SUPPORTED
672*dfc6aa5cSAndroid Build Coastguard Worker   case FMT_BMP:
673*dfc6aa5cSAndroid Build Coastguard Worker     dest_mgr = jinit_write_bmp(&cinfo, FALSE, TRUE);
674*dfc6aa5cSAndroid Build Coastguard Worker     break;
675*dfc6aa5cSAndroid Build Coastguard Worker   case FMT_OS2:
676*dfc6aa5cSAndroid Build Coastguard Worker     dest_mgr = jinit_write_bmp(&cinfo, TRUE, TRUE);
677*dfc6aa5cSAndroid Build Coastguard Worker     break;
678*dfc6aa5cSAndroid Build Coastguard Worker #endif
679*dfc6aa5cSAndroid Build Coastguard Worker #ifdef GIF_SUPPORTED
680*dfc6aa5cSAndroid Build Coastguard Worker   case FMT_GIF:
681*dfc6aa5cSAndroid Build Coastguard Worker     dest_mgr = jinit_write_gif(&cinfo, TRUE);
682*dfc6aa5cSAndroid Build Coastguard Worker     break;
683*dfc6aa5cSAndroid Build Coastguard Worker   case FMT_GIF0:
684*dfc6aa5cSAndroid Build Coastguard Worker     dest_mgr = jinit_write_gif(&cinfo, FALSE);
685*dfc6aa5cSAndroid Build Coastguard Worker     break;
686*dfc6aa5cSAndroid Build Coastguard Worker #endif
687*dfc6aa5cSAndroid Build Coastguard Worker #ifdef PPM_SUPPORTED
688*dfc6aa5cSAndroid Build Coastguard Worker   case FMT_PPM:
689*dfc6aa5cSAndroid Build Coastguard Worker     dest_mgr = jinit_write_ppm(&cinfo);
690*dfc6aa5cSAndroid Build Coastguard Worker     break;
691*dfc6aa5cSAndroid Build Coastguard Worker #endif
692*dfc6aa5cSAndroid Build Coastguard Worker #ifdef TARGA_SUPPORTED
693*dfc6aa5cSAndroid Build Coastguard Worker   case FMT_TARGA:
694*dfc6aa5cSAndroid Build Coastguard Worker     dest_mgr = jinit_write_targa(&cinfo);
695*dfc6aa5cSAndroid Build Coastguard Worker     break;
696*dfc6aa5cSAndroid Build Coastguard Worker #endif
697*dfc6aa5cSAndroid Build Coastguard Worker   default:
698*dfc6aa5cSAndroid Build Coastguard Worker     ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT);
699*dfc6aa5cSAndroid Build Coastguard Worker     break;
700*dfc6aa5cSAndroid Build Coastguard Worker   }
701*dfc6aa5cSAndroid Build Coastguard Worker   dest_mgr->output_file = output_file;
702*dfc6aa5cSAndroid Build Coastguard Worker 
703*dfc6aa5cSAndroid Build Coastguard Worker   /* Start decompressor */
704*dfc6aa5cSAndroid Build Coastguard Worker   (void)jpeg_start_decompress(&cinfo);
705*dfc6aa5cSAndroid Build Coastguard Worker 
706*dfc6aa5cSAndroid Build Coastguard Worker   /* Skip rows */
707*dfc6aa5cSAndroid Build Coastguard Worker   if (skip) {
708*dfc6aa5cSAndroid Build Coastguard Worker     JDIMENSION tmp;
709*dfc6aa5cSAndroid Build Coastguard Worker 
710*dfc6aa5cSAndroid Build Coastguard Worker     /* Check for valid skip_end.  We cannot check this value until after
711*dfc6aa5cSAndroid Build Coastguard Worker      * jpeg_start_decompress() is called.  Note that we have already verified
712*dfc6aa5cSAndroid Build Coastguard Worker      * that skip_start <= skip_end.
713*dfc6aa5cSAndroid Build Coastguard Worker      */
714*dfc6aa5cSAndroid Build Coastguard Worker     if (skip_end > cinfo.output_height - 1) {
715*dfc6aa5cSAndroid Build Coastguard Worker       fprintf(stderr, "%s: skip region exceeds image height %u\n", progname,
716*dfc6aa5cSAndroid Build Coastguard Worker               cinfo.output_height);
717*dfc6aa5cSAndroid Build Coastguard Worker       return EXIT_FAILURE;
718*dfc6aa5cSAndroid Build Coastguard Worker     }
719*dfc6aa5cSAndroid Build Coastguard Worker 
720*dfc6aa5cSAndroid Build Coastguard Worker     /* Write output file header.  This is a hack to ensure that the destination
721*dfc6aa5cSAndroid Build Coastguard Worker      * manager creates an output image of the proper size.
722*dfc6aa5cSAndroid Build Coastguard Worker      */
723*dfc6aa5cSAndroid Build Coastguard Worker     tmp = cinfo.output_height;
724*dfc6aa5cSAndroid Build Coastguard Worker     cinfo.output_height -= (skip_end - skip_start + 1);
725*dfc6aa5cSAndroid Build Coastguard Worker     (*dest_mgr->start_output) (&cinfo, dest_mgr);
726*dfc6aa5cSAndroid Build Coastguard Worker     cinfo.output_height = tmp;
727*dfc6aa5cSAndroid Build Coastguard Worker 
728*dfc6aa5cSAndroid Build Coastguard Worker     /* Process data */
729*dfc6aa5cSAndroid Build Coastguard Worker     while (cinfo.output_scanline < skip_start) {
730*dfc6aa5cSAndroid Build Coastguard Worker       num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
731*dfc6aa5cSAndroid Build Coastguard Worker                                           dest_mgr->buffer_height);
732*dfc6aa5cSAndroid Build Coastguard Worker       (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
733*dfc6aa5cSAndroid Build Coastguard Worker     }
734*dfc6aa5cSAndroid Build Coastguard Worker     if ((tmp = jpeg_skip_scanlines(&cinfo, skip_end - skip_start + 1)) !=
735*dfc6aa5cSAndroid Build Coastguard Worker         skip_end - skip_start + 1) {
736*dfc6aa5cSAndroid Build Coastguard Worker       fprintf(stderr, "%s: jpeg_skip_scanlines() returned %u rather than %u\n",
737*dfc6aa5cSAndroid Build Coastguard Worker               progname, tmp, skip_end - skip_start + 1);
738*dfc6aa5cSAndroid Build Coastguard Worker       return EXIT_FAILURE;
739*dfc6aa5cSAndroid Build Coastguard Worker     }
740*dfc6aa5cSAndroid Build Coastguard Worker     while (cinfo.output_scanline < cinfo.output_height) {
741*dfc6aa5cSAndroid Build Coastguard Worker       num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
742*dfc6aa5cSAndroid Build Coastguard Worker                                           dest_mgr->buffer_height);
743*dfc6aa5cSAndroid Build Coastguard Worker       (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
744*dfc6aa5cSAndroid Build Coastguard Worker     }
745*dfc6aa5cSAndroid Build Coastguard Worker 
746*dfc6aa5cSAndroid Build Coastguard Worker   /* Decompress a subregion */
747*dfc6aa5cSAndroid Build Coastguard Worker   } else if (crop) {
748*dfc6aa5cSAndroid Build Coastguard Worker     JDIMENSION tmp;
749*dfc6aa5cSAndroid Build Coastguard Worker 
750*dfc6aa5cSAndroid Build Coastguard Worker     /* Check for valid crop dimensions.  We cannot check these values until
751*dfc6aa5cSAndroid Build Coastguard Worker      * after jpeg_start_decompress() is called.
752*dfc6aa5cSAndroid Build Coastguard Worker      */
753*dfc6aa5cSAndroid Build Coastguard Worker     if (crop_x + crop_width > cinfo.output_width ||
754*dfc6aa5cSAndroid Build Coastguard Worker         crop_y + crop_height > cinfo.output_height) {
755*dfc6aa5cSAndroid Build Coastguard Worker       fprintf(stderr, "%s: crop dimensions exceed image dimensions %u x %u\n",
756*dfc6aa5cSAndroid Build Coastguard Worker               progname, cinfo.output_width, cinfo.output_height);
757*dfc6aa5cSAndroid Build Coastguard Worker       return EXIT_FAILURE;
758*dfc6aa5cSAndroid Build Coastguard Worker     }
759*dfc6aa5cSAndroid Build Coastguard Worker 
760*dfc6aa5cSAndroid Build Coastguard Worker     jpeg_crop_scanline(&cinfo, &crop_x, &crop_width);
761*dfc6aa5cSAndroid Build Coastguard Worker     if (dest_mgr->calc_buffer_dimensions)
762*dfc6aa5cSAndroid Build Coastguard Worker       (*dest_mgr->calc_buffer_dimensions) (&cinfo, dest_mgr);
763*dfc6aa5cSAndroid Build Coastguard Worker     else
764*dfc6aa5cSAndroid Build Coastguard Worker       ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT);
765*dfc6aa5cSAndroid Build Coastguard Worker 
766*dfc6aa5cSAndroid Build Coastguard Worker     /* Write output file header.  This is a hack to ensure that the destination
767*dfc6aa5cSAndroid Build Coastguard Worker      * manager creates an output image of the proper size.
768*dfc6aa5cSAndroid Build Coastguard Worker      */
769*dfc6aa5cSAndroid Build Coastguard Worker     tmp = cinfo.output_height;
770*dfc6aa5cSAndroid Build Coastguard Worker     cinfo.output_height = crop_height;
771*dfc6aa5cSAndroid Build Coastguard Worker     (*dest_mgr->start_output) (&cinfo, dest_mgr);
772*dfc6aa5cSAndroid Build Coastguard Worker     cinfo.output_height = tmp;
773*dfc6aa5cSAndroid Build Coastguard Worker 
774*dfc6aa5cSAndroid Build Coastguard Worker     /* Process data */
775*dfc6aa5cSAndroid Build Coastguard Worker     if ((tmp = jpeg_skip_scanlines(&cinfo, crop_y)) != crop_y) {
776*dfc6aa5cSAndroid Build Coastguard Worker       fprintf(stderr, "%s: jpeg_skip_scanlines() returned %u rather than %u\n",
777*dfc6aa5cSAndroid Build Coastguard Worker               progname, tmp, crop_y);
778*dfc6aa5cSAndroid Build Coastguard Worker       return EXIT_FAILURE;
779*dfc6aa5cSAndroid Build Coastguard Worker     }
780*dfc6aa5cSAndroid Build Coastguard Worker     while (cinfo.output_scanline < crop_y + crop_height) {
781*dfc6aa5cSAndroid Build Coastguard Worker       num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
782*dfc6aa5cSAndroid Build Coastguard Worker                                           dest_mgr->buffer_height);
783*dfc6aa5cSAndroid Build Coastguard Worker       (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
784*dfc6aa5cSAndroid Build Coastguard Worker     }
785*dfc6aa5cSAndroid Build Coastguard Worker     if ((tmp =
786*dfc6aa5cSAndroid Build Coastguard Worker          jpeg_skip_scanlines(&cinfo,
787*dfc6aa5cSAndroid Build Coastguard Worker                              cinfo.output_height - crop_y - crop_height)) !=
788*dfc6aa5cSAndroid Build Coastguard Worker         cinfo.output_height - crop_y - crop_height) {
789*dfc6aa5cSAndroid Build Coastguard Worker       fprintf(stderr, "%s: jpeg_skip_scanlines() returned %u rather than %u\n",
790*dfc6aa5cSAndroid Build Coastguard Worker               progname, tmp, cinfo.output_height - crop_y - crop_height);
791*dfc6aa5cSAndroid Build Coastguard Worker       return EXIT_FAILURE;
792*dfc6aa5cSAndroid Build Coastguard Worker     }
793*dfc6aa5cSAndroid Build Coastguard Worker 
794*dfc6aa5cSAndroid Build Coastguard Worker   /* Normal full-image decompress */
795*dfc6aa5cSAndroid Build Coastguard Worker   } else {
796*dfc6aa5cSAndroid Build Coastguard Worker     /* Write output file header */
797*dfc6aa5cSAndroid Build Coastguard Worker     (*dest_mgr->start_output) (&cinfo, dest_mgr);
798*dfc6aa5cSAndroid Build Coastguard Worker 
799*dfc6aa5cSAndroid Build Coastguard Worker     /* Process data */
800*dfc6aa5cSAndroid Build Coastguard Worker     while (cinfo.output_scanline < cinfo.output_height) {
801*dfc6aa5cSAndroid Build Coastguard Worker       num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
802*dfc6aa5cSAndroid Build Coastguard Worker                                           dest_mgr->buffer_height);
803*dfc6aa5cSAndroid Build Coastguard Worker       (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
804*dfc6aa5cSAndroid Build Coastguard Worker     }
805*dfc6aa5cSAndroid Build Coastguard Worker   }
806*dfc6aa5cSAndroid Build Coastguard Worker 
807*dfc6aa5cSAndroid Build Coastguard Worker   /* Hack: count final pass as done in case finish_output does an extra pass.
808*dfc6aa5cSAndroid Build Coastguard Worker    * The library won't have updated completed_passes.
809*dfc6aa5cSAndroid Build Coastguard Worker    */
810*dfc6aa5cSAndroid Build Coastguard Worker   if (report || max_scans != 0)
811*dfc6aa5cSAndroid Build Coastguard Worker     progress.pub.completed_passes = progress.pub.total_passes;
812*dfc6aa5cSAndroid Build Coastguard Worker 
813*dfc6aa5cSAndroid Build Coastguard Worker   if (icc_filename != NULL) {
814*dfc6aa5cSAndroid Build Coastguard Worker     FILE *icc_file;
815*dfc6aa5cSAndroid Build Coastguard Worker     JOCTET *icc_profile;
816*dfc6aa5cSAndroid Build Coastguard Worker     unsigned int icc_len;
817*dfc6aa5cSAndroid Build Coastguard Worker 
818*dfc6aa5cSAndroid Build Coastguard Worker     if ((icc_file = fopen(icc_filename, WRITE_BINARY)) == NULL) {
819*dfc6aa5cSAndroid Build Coastguard Worker       fprintf(stderr, "%s: can't open %s\n", progname, icc_filename);
820*dfc6aa5cSAndroid Build Coastguard Worker       return EXIT_FAILURE;
821*dfc6aa5cSAndroid Build Coastguard Worker     }
822*dfc6aa5cSAndroid Build Coastguard Worker     if (jpeg_read_icc_profile(&cinfo, &icc_profile, &icc_len)) {
823*dfc6aa5cSAndroid Build Coastguard Worker       if (fwrite(icc_profile, icc_len, 1, icc_file) < 1) {
824*dfc6aa5cSAndroid Build Coastguard Worker         fprintf(stderr, "%s: can't read ICC profile from %s\n", progname,
825*dfc6aa5cSAndroid Build Coastguard Worker                 icc_filename);
826*dfc6aa5cSAndroid Build Coastguard Worker         free(icc_profile);
827*dfc6aa5cSAndroid Build Coastguard Worker         fclose(icc_file);
828*dfc6aa5cSAndroid Build Coastguard Worker         return EXIT_FAILURE;
829*dfc6aa5cSAndroid Build Coastguard Worker       }
830*dfc6aa5cSAndroid Build Coastguard Worker       free(icc_profile);
831*dfc6aa5cSAndroid Build Coastguard Worker       fclose(icc_file);
832*dfc6aa5cSAndroid Build Coastguard Worker     } else if (cinfo.err->msg_code != JWRN_BOGUS_ICC)
833*dfc6aa5cSAndroid Build Coastguard Worker       fprintf(stderr, "%s: no ICC profile data in JPEG file\n", progname);
834*dfc6aa5cSAndroid Build Coastguard Worker   }
835*dfc6aa5cSAndroid Build Coastguard Worker 
836*dfc6aa5cSAndroid Build Coastguard Worker   /* Finish decompression and release memory.
837*dfc6aa5cSAndroid Build Coastguard Worker    * I must do it in this order because output module has allocated memory
838*dfc6aa5cSAndroid Build Coastguard Worker    * of lifespan JPOOL_IMAGE; it needs to finish before releasing memory.
839*dfc6aa5cSAndroid Build Coastguard Worker    */
840*dfc6aa5cSAndroid Build Coastguard Worker   (*dest_mgr->finish_output) (&cinfo, dest_mgr);
841*dfc6aa5cSAndroid Build Coastguard Worker   (void)jpeg_finish_decompress(&cinfo);
842*dfc6aa5cSAndroid Build Coastguard Worker   jpeg_destroy_decompress(&cinfo);
843*dfc6aa5cSAndroid Build Coastguard Worker 
844*dfc6aa5cSAndroid Build Coastguard Worker   /* Close files, if we opened them */
845*dfc6aa5cSAndroid Build Coastguard Worker   if (input_file != stdin)
846*dfc6aa5cSAndroid Build Coastguard Worker     fclose(input_file);
847*dfc6aa5cSAndroid Build Coastguard Worker   if (output_file != stdout)
848*dfc6aa5cSAndroid Build Coastguard Worker     fclose(output_file);
849*dfc6aa5cSAndroid Build Coastguard Worker 
850*dfc6aa5cSAndroid Build Coastguard Worker   if (report || max_scans != 0)
851*dfc6aa5cSAndroid Build Coastguard Worker     end_progress_monitor((j_common_ptr)&cinfo);
852*dfc6aa5cSAndroid Build Coastguard Worker 
853*dfc6aa5cSAndroid Build Coastguard Worker   if (memsrc)
854*dfc6aa5cSAndroid Build Coastguard Worker     free(inbuffer);
855*dfc6aa5cSAndroid Build Coastguard Worker 
856*dfc6aa5cSAndroid Build Coastguard Worker   /* All done. */
857*dfc6aa5cSAndroid Build Coastguard Worker   return (jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
858*dfc6aa5cSAndroid Build Coastguard Worker }
859