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