1*dfc6aa5cSAndroid Build Coastguard Worker /*
2*dfc6aa5cSAndroid Build Coastguard Worker * jpegtran.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) 1995-2019, Thomas G. Lane, Guido Vollbeding.
6*dfc6aa5cSAndroid Build Coastguard Worker * libjpeg-turbo Modifications:
7*dfc6aa5cSAndroid Build Coastguard Worker * Copyright (C) 2010, 2014, 2017, 2019-2022, D. R. Commander.
8*dfc6aa5cSAndroid Build Coastguard Worker * For conditions of distribution and use, see the accompanying README.ijg
9*dfc6aa5cSAndroid Build Coastguard Worker * file.
10*dfc6aa5cSAndroid Build Coastguard Worker *
11*dfc6aa5cSAndroid Build Coastguard Worker * This file contains a command-line user interface for JPEG transcoding.
12*dfc6aa5cSAndroid Build Coastguard Worker * It is very similar to cjpeg.c, and partly to djpeg.c, but provides
13*dfc6aa5cSAndroid Build Coastguard Worker * lossless transcoding between different JPEG file formats. It also
14*dfc6aa5cSAndroid Build Coastguard Worker * provides some lossless and sort-of-lossless transformations of JPEG data.
15*dfc6aa5cSAndroid Build Coastguard Worker */
16*dfc6aa5cSAndroid Build Coastguard Worker
17*dfc6aa5cSAndroid Build Coastguard Worker #ifdef _MSC_VER
18*dfc6aa5cSAndroid Build Coastguard Worker #define _CRT_SECURE_NO_DEPRECATE
19*dfc6aa5cSAndroid Build Coastguard Worker #endif
20*dfc6aa5cSAndroid Build Coastguard Worker
21*dfc6aa5cSAndroid Build Coastguard Worker #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
22*dfc6aa5cSAndroid Build Coastguard Worker #include "transupp.h" /* Support routines for jpegtran */
23*dfc6aa5cSAndroid Build Coastguard Worker #include "jversion.h" /* for version message */
24*dfc6aa5cSAndroid Build Coastguard Worker #include "jconfigint.h"
25*dfc6aa5cSAndroid Build Coastguard Worker
26*dfc6aa5cSAndroid Build Coastguard Worker
27*dfc6aa5cSAndroid Build Coastguard Worker /*
28*dfc6aa5cSAndroid Build Coastguard Worker * Argument-parsing code.
29*dfc6aa5cSAndroid Build Coastguard Worker * The switch parser is designed to be useful with DOS-style command line
30*dfc6aa5cSAndroid Build Coastguard Worker * syntax, ie, intermixed switches and file names, where only the switches
31*dfc6aa5cSAndroid Build Coastguard Worker * to the left of a given file name affect processing of that file.
32*dfc6aa5cSAndroid Build Coastguard Worker * The main program in this file doesn't actually use this capability...
33*dfc6aa5cSAndroid Build Coastguard Worker */
34*dfc6aa5cSAndroid Build Coastguard Worker
35*dfc6aa5cSAndroid Build Coastguard Worker
36*dfc6aa5cSAndroid Build Coastguard Worker static const char *progname; /* program name for error messages */
37*dfc6aa5cSAndroid Build Coastguard Worker static char *icc_filename; /* for -icc switch */
38*dfc6aa5cSAndroid Build Coastguard Worker static JDIMENSION max_scans; /* for -maxscans switch */
39*dfc6aa5cSAndroid Build Coastguard Worker static char *outfilename; /* for -outfile switch */
40*dfc6aa5cSAndroid Build Coastguard Worker static char *dropfilename; /* for -drop switch */
41*dfc6aa5cSAndroid Build Coastguard Worker static boolean report; /* for -report switch */
42*dfc6aa5cSAndroid Build Coastguard Worker static boolean strict; /* for -strict switch */
43*dfc6aa5cSAndroid Build Coastguard Worker static JCOPY_OPTION copyoption; /* -copy switch */
44*dfc6aa5cSAndroid Build Coastguard Worker static jpeg_transform_info transformoption; /* image transformation options */
45*dfc6aa5cSAndroid Build Coastguard Worker
46*dfc6aa5cSAndroid Build Coastguard Worker
47*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
usage(void)48*dfc6aa5cSAndroid Build Coastguard Worker usage(void)
49*dfc6aa5cSAndroid Build Coastguard Worker /* complain about bad command line */
50*dfc6aa5cSAndroid Build Coastguard Worker {
51*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "usage: %s [switches] ", progname);
52*dfc6aa5cSAndroid Build Coastguard Worker #ifdef TWO_FILE_COMMANDLINE
53*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "inputfile outputfile\n");
54*dfc6aa5cSAndroid Build Coastguard Worker #else
55*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "[inputfile]\n");
56*dfc6aa5cSAndroid Build Coastguard Worker #endif
57*dfc6aa5cSAndroid Build Coastguard Worker
58*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "Switches (names may be abbreviated):\n");
59*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -copy none Copy no extra markers from source file\n");
60*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -copy comments Copy only comment markers (default)\n");
61*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -copy icc Copy only ICC profile markers\n");
62*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -copy all Copy all extra markers\n");
63*dfc6aa5cSAndroid Build Coastguard Worker #ifdef ENTROPY_OPT_SUPPORTED
64*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n");
65*dfc6aa5cSAndroid Build Coastguard Worker #endif
66*dfc6aa5cSAndroid Build Coastguard Worker #ifdef C_PROGRESSIVE_SUPPORTED
67*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -progressive Create progressive JPEG file\n");
68*dfc6aa5cSAndroid Build Coastguard Worker #endif
69*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "Switches for modifying the image:\n");
70*dfc6aa5cSAndroid Build Coastguard Worker #if TRANSFORMS_SUPPORTED
71*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -crop WxH+X+Y Crop to a rectangular region\n");
72*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -drop +X+Y filename Drop (insert) another image\n");
73*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -flip [horizontal|vertical] Mirror image (left-right or top-bottom)\n");
74*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -grayscale Reduce to grayscale (omit color data)\n");
75*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -perfect Fail if there is non-transformable edge blocks\n");
76*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -rotate [90|180|270] Rotate image (degrees clockwise)\n");
77*dfc6aa5cSAndroid Build Coastguard Worker #endif
78*dfc6aa5cSAndroid Build Coastguard Worker #if TRANSFORMS_SUPPORTED
79*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -transpose Transpose image\n");
80*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -transverse Transverse transpose image\n");
81*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -trim Drop non-transformable edge blocks\n");
82*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " with -drop: Requantize drop file to match source file\n");
83*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -wipe WxH+X+Y Wipe (gray out) a rectangular region\n");
84*dfc6aa5cSAndroid Build Coastguard Worker #endif
85*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "Switches for advanced users:\n");
86*dfc6aa5cSAndroid Build Coastguard Worker #ifdef C_ARITH_CODING_SUPPORTED
87*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -arithmetic Use arithmetic coding\n");
88*dfc6aa5cSAndroid Build Coastguard Worker #endif
89*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -icc FILE Embed ICC profile contained in FILE\n");
90*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n");
91*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
92*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -maxscans N Maximum number of scans to allow in input file\n");
93*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -outfile name Specify name for output file\n");
94*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -report Report transformation progress\n");
95*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -strict Treat all warnings as fatal\n");
96*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -verbose or -debug Emit debug output\n");
97*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -version Print version information and exit\n");
98*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "Switches for wizards:\n");
99*dfc6aa5cSAndroid Build Coastguard Worker #ifdef C_MULTISCAN_FILES_SUPPORTED
100*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, " -scans FILE Create multi-scan JPEG per script FILE\n");
101*dfc6aa5cSAndroid Build Coastguard Worker #endif
102*dfc6aa5cSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
103*dfc6aa5cSAndroid Build Coastguard Worker }
104*dfc6aa5cSAndroid Build Coastguard Worker
105*dfc6aa5cSAndroid Build Coastguard Worker
106*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
select_transform(JXFORM_CODE transform)107*dfc6aa5cSAndroid Build Coastguard Worker select_transform(JXFORM_CODE transform)
108*dfc6aa5cSAndroid Build Coastguard Worker /* Silly little routine to detect multiple transform options,
109*dfc6aa5cSAndroid Build Coastguard Worker * which we can't handle.
110*dfc6aa5cSAndroid Build Coastguard Worker */
111*dfc6aa5cSAndroid Build Coastguard Worker {
112*dfc6aa5cSAndroid Build Coastguard Worker #if TRANSFORMS_SUPPORTED
113*dfc6aa5cSAndroid Build Coastguard Worker if (transformoption.transform == JXFORM_NONE ||
114*dfc6aa5cSAndroid Build Coastguard Worker transformoption.transform == transform) {
115*dfc6aa5cSAndroid Build Coastguard Worker transformoption.transform = transform;
116*dfc6aa5cSAndroid Build Coastguard Worker } else {
117*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "%s: can only do one image transformation at a time\n",
118*dfc6aa5cSAndroid Build Coastguard Worker progname);
119*dfc6aa5cSAndroid Build Coastguard Worker usage();
120*dfc6aa5cSAndroid Build Coastguard Worker }
121*dfc6aa5cSAndroid Build Coastguard Worker #else
122*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "%s: sorry, image transformation was not compiled\n",
123*dfc6aa5cSAndroid Build Coastguard Worker progname);
124*dfc6aa5cSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
125*dfc6aa5cSAndroid Build Coastguard Worker #endif
126*dfc6aa5cSAndroid Build Coastguard Worker }
127*dfc6aa5cSAndroid Build Coastguard Worker
128*dfc6aa5cSAndroid Build Coastguard Worker
129*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(int)
parse_switches(j_compress_ptr cinfo,int argc,char ** argv,int last_file_arg_seen,boolean for_real)130*dfc6aa5cSAndroid Build Coastguard Worker parse_switches(j_compress_ptr cinfo, int argc, char **argv,
131*dfc6aa5cSAndroid Build Coastguard Worker int last_file_arg_seen, boolean for_real)
132*dfc6aa5cSAndroid Build Coastguard Worker /* Parse optional switches.
133*dfc6aa5cSAndroid Build Coastguard Worker * Returns argv[] index of first file-name argument (== argc if none).
134*dfc6aa5cSAndroid Build Coastguard Worker * Any file names with indexes <= last_file_arg_seen are ignored;
135*dfc6aa5cSAndroid Build Coastguard Worker * they have presumably been processed in a previous iteration.
136*dfc6aa5cSAndroid Build Coastguard Worker * (Pass 0 for last_file_arg_seen on the first or only iteration.)
137*dfc6aa5cSAndroid Build Coastguard Worker * for_real is FALSE on the first (dummy) pass; we may skip any expensive
138*dfc6aa5cSAndroid Build Coastguard Worker * processing.
139*dfc6aa5cSAndroid Build Coastguard Worker */
140*dfc6aa5cSAndroid Build Coastguard Worker {
141*dfc6aa5cSAndroid Build Coastguard Worker int argn;
142*dfc6aa5cSAndroid Build Coastguard Worker char *arg;
143*dfc6aa5cSAndroid Build Coastguard Worker boolean simple_progressive;
144*dfc6aa5cSAndroid Build Coastguard Worker char *scansarg = NULL; /* saves -scans parm if any */
145*dfc6aa5cSAndroid Build Coastguard Worker
146*dfc6aa5cSAndroid Build Coastguard Worker /* Set up default JPEG parameters. */
147*dfc6aa5cSAndroid Build Coastguard Worker simple_progressive = FALSE;
148*dfc6aa5cSAndroid Build Coastguard Worker icc_filename = NULL;
149*dfc6aa5cSAndroid Build Coastguard Worker max_scans = 0;
150*dfc6aa5cSAndroid Build Coastguard Worker outfilename = NULL;
151*dfc6aa5cSAndroid Build Coastguard Worker report = FALSE;
152*dfc6aa5cSAndroid Build Coastguard Worker strict = FALSE;
153*dfc6aa5cSAndroid Build Coastguard Worker copyoption = JCOPYOPT_DEFAULT;
154*dfc6aa5cSAndroid Build Coastguard Worker transformoption.transform = JXFORM_NONE;
155*dfc6aa5cSAndroid Build Coastguard Worker transformoption.perfect = FALSE;
156*dfc6aa5cSAndroid Build Coastguard Worker transformoption.trim = FALSE;
157*dfc6aa5cSAndroid Build Coastguard Worker transformoption.force_grayscale = FALSE;
158*dfc6aa5cSAndroid Build Coastguard Worker transformoption.crop = FALSE;
159*dfc6aa5cSAndroid Build Coastguard Worker transformoption.slow_hflip = FALSE;
160*dfc6aa5cSAndroid Build Coastguard Worker cinfo->err->trace_level = 0;
161*dfc6aa5cSAndroid Build Coastguard Worker
162*dfc6aa5cSAndroid Build Coastguard Worker /* Scan command line options, adjust parameters */
163*dfc6aa5cSAndroid Build Coastguard Worker
164*dfc6aa5cSAndroid Build Coastguard Worker for (argn = 1; argn < argc; argn++) {
165*dfc6aa5cSAndroid Build Coastguard Worker arg = argv[argn];
166*dfc6aa5cSAndroid Build Coastguard Worker if (*arg != '-') {
167*dfc6aa5cSAndroid Build Coastguard Worker /* Not a switch, must be a file name argument */
168*dfc6aa5cSAndroid Build Coastguard Worker if (argn <= last_file_arg_seen) {
169*dfc6aa5cSAndroid Build Coastguard Worker outfilename = NULL; /* -outfile applies to just one input file */
170*dfc6aa5cSAndroid Build Coastguard Worker continue; /* ignore this name if previously processed */
171*dfc6aa5cSAndroid Build Coastguard Worker }
172*dfc6aa5cSAndroid Build Coastguard Worker break; /* else done parsing switches */
173*dfc6aa5cSAndroid Build Coastguard Worker }
174*dfc6aa5cSAndroid Build Coastguard Worker arg++; /* advance past switch marker character */
175*dfc6aa5cSAndroid Build Coastguard Worker
176*dfc6aa5cSAndroid Build Coastguard Worker if (keymatch(arg, "arithmetic", 1)) {
177*dfc6aa5cSAndroid Build Coastguard Worker /* Use arithmetic coding. */
178*dfc6aa5cSAndroid Build Coastguard Worker #ifdef C_ARITH_CODING_SUPPORTED
179*dfc6aa5cSAndroid Build Coastguard Worker cinfo->arith_code = TRUE;
180*dfc6aa5cSAndroid Build Coastguard Worker #else
181*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
182*dfc6aa5cSAndroid Build Coastguard Worker progname);
183*dfc6aa5cSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
184*dfc6aa5cSAndroid Build Coastguard Worker #endif
185*dfc6aa5cSAndroid Build Coastguard Worker
186*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(arg, "copy", 2)) {
187*dfc6aa5cSAndroid Build Coastguard Worker /* Select which extra markers to copy. */
188*dfc6aa5cSAndroid Build Coastguard Worker if (++argn >= argc) /* advance to next argument */
189*dfc6aa5cSAndroid Build Coastguard Worker usage();
190*dfc6aa5cSAndroid Build Coastguard Worker if (keymatch(argv[argn], "none", 1)) {
191*dfc6aa5cSAndroid Build Coastguard Worker copyoption = JCOPYOPT_NONE;
192*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(argv[argn], "comments", 1)) {
193*dfc6aa5cSAndroid Build Coastguard Worker copyoption = JCOPYOPT_COMMENTS;
194*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(argv[argn], "icc", 1)) {
195*dfc6aa5cSAndroid Build Coastguard Worker copyoption = JCOPYOPT_ICC;
196*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(argv[argn], "all", 1)) {
197*dfc6aa5cSAndroid Build Coastguard Worker copyoption = JCOPYOPT_ALL;
198*dfc6aa5cSAndroid Build Coastguard Worker } else
199*dfc6aa5cSAndroid Build Coastguard Worker usage();
200*dfc6aa5cSAndroid Build Coastguard Worker
201*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(arg, "crop", 2)) {
202*dfc6aa5cSAndroid Build Coastguard Worker /* Perform lossless cropping. */
203*dfc6aa5cSAndroid Build Coastguard Worker #if TRANSFORMS_SUPPORTED
204*dfc6aa5cSAndroid Build Coastguard Worker if (++argn >= argc) /* advance to next argument */
205*dfc6aa5cSAndroid Build Coastguard Worker usage();
206*dfc6aa5cSAndroid Build Coastguard Worker if (transformoption.crop /* reject multiple crop/drop/wipe requests */ ||
207*dfc6aa5cSAndroid Build Coastguard Worker !jtransform_parse_crop_spec(&transformoption, argv[argn])) {
208*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "%s: bogus -crop argument '%s'\n",
209*dfc6aa5cSAndroid Build Coastguard Worker progname, argv[argn]);
210*dfc6aa5cSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
211*dfc6aa5cSAndroid Build Coastguard Worker }
212*dfc6aa5cSAndroid Build Coastguard Worker #else
213*dfc6aa5cSAndroid Build Coastguard Worker select_transform(JXFORM_NONE); /* force an error */
214*dfc6aa5cSAndroid Build Coastguard Worker #endif
215*dfc6aa5cSAndroid Build Coastguard Worker
216*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(arg, "drop", 2)) {
217*dfc6aa5cSAndroid Build Coastguard Worker #if TRANSFORMS_SUPPORTED
218*dfc6aa5cSAndroid Build Coastguard Worker if (++argn >= argc) /* advance to next argument */
219*dfc6aa5cSAndroid Build Coastguard Worker usage();
220*dfc6aa5cSAndroid Build Coastguard Worker if (transformoption.crop /* reject multiple crop/drop/wipe requests */ ||
221*dfc6aa5cSAndroid Build Coastguard Worker !jtransform_parse_crop_spec(&transformoption, argv[argn]) ||
222*dfc6aa5cSAndroid Build Coastguard Worker transformoption.crop_width_set != JCROP_UNSET ||
223*dfc6aa5cSAndroid Build Coastguard Worker transformoption.crop_height_set != JCROP_UNSET) {
224*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "%s: bogus -drop argument '%s'\n",
225*dfc6aa5cSAndroid Build Coastguard Worker progname, argv[argn]);
226*dfc6aa5cSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
227*dfc6aa5cSAndroid Build Coastguard Worker }
228*dfc6aa5cSAndroid Build Coastguard Worker if (++argn >= argc) /* advance to next argument */
229*dfc6aa5cSAndroid Build Coastguard Worker usage();
230*dfc6aa5cSAndroid Build Coastguard Worker dropfilename = argv[argn];
231*dfc6aa5cSAndroid Build Coastguard Worker select_transform(JXFORM_DROP);
232*dfc6aa5cSAndroid Build Coastguard Worker #else
233*dfc6aa5cSAndroid Build Coastguard Worker select_transform(JXFORM_NONE); /* force an error */
234*dfc6aa5cSAndroid Build Coastguard Worker #endif
235*dfc6aa5cSAndroid Build Coastguard Worker
236*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
237*dfc6aa5cSAndroid Build Coastguard Worker /* Enable debug printouts. */
238*dfc6aa5cSAndroid Build Coastguard Worker /* On first -d, print version identification */
239*dfc6aa5cSAndroid Build Coastguard Worker static boolean printed_version = FALSE;
240*dfc6aa5cSAndroid Build Coastguard Worker
241*dfc6aa5cSAndroid Build Coastguard Worker if (!printed_version) {
242*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "%s version %s (build %s)\n",
243*dfc6aa5cSAndroid Build Coastguard Worker PACKAGE_NAME, VERSION, BUILD);
244*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "%s\n\n", JCOPYRIGHT);
245*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "Emulating The Independent JPEG Group's software, version %s\n\n",
246*dfc6aa5cSAndroid Build Coastguard Worker JVERSION);
247*dfc6aa5cSAndroid Build Coastguard Worker printed_version = TRUE;
248*dfc6aa5cSAndroid Build Coastguard Worker }
249*dfc6aa5cSAndroid Build Coastguard Worker cinfo->err->trace_level++;
250*dfc6aa5cSAndroid Build Coastguard Worker
251*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(arg, "version", 4)) {
252*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "%s version %s (build %s)\n",
253*dfc6aa5cSAndroid Build Coastguard Worker PACKAGE_NAME, VERSION, BUILD);
254*dfc6aa5cSAndroid Build Coastguard Worker exit(EXIT_SUCCESS);
255*dfc6aa5cSAndroid Build Coastguard Worker
256*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(arg, "flip", 1)) {
257*dfc6aa5cSAndroid Build Coastguard Worker /* Mirror left-right or top-bottom. */
258*dfc6aa5cSAndroid Build Coastguard Worker if (++argn >= argc) /* advance to next argument */
259*dfc6aa5cSAndroid Build Coastguard Worker usage();
260*dfc6aa5cSAndroid Build Coastguard Worker if (keymatch(argv[argn], "horizontal", 1))
261*dfc6aa5cSAndroid Build Coastguard Worker select_transform(JXFORM_FLIP_H);
262*dfc6aa5cSAndroid Build Coastguard Worker else if (keymatch(argv[argn], "vertical", 1))
263*dfc6aa5cSAndroid Build Coastguard Worker select_transform(JXFORM_FLIP_V);
264*dfc6aa5cSAndroid Build Coastguard Worker else
265*dfc6aa5cSAndroid Build Coastguard Worker usage();
266*dfc6aa5cSAndroid Build Coastguard Worker
267*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(arg, "grayscale", 1) ||
268*dfc6aa5cSAndroid Build Coastguard Worker keymatch(arg, "greyscale", 1)) {
269*dfc6aa5cSAndroid Build Coastguard Worker /* Force to grayscale. */
270*dfc6aa5cSAndroid Build Coastguard Worker #if TRANSFORMS_SUPPORTED
271*dfc6aa5cSAndroid Build Coastguard Worker transformoption.force_grayscale = TRUE;
272*dfc6aa5cSAndroid Build Coastguard Worker #else
273*dfc6aa5cSAndroid Build Coastguard Worker select_transform(JXFORM_NONE); /* force an error */
274*dfc6aa5cSAndroid Build Coastguard Worker #endif
275*dfc6aa5cSAndroid Build Coastguard Worker
276*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(arg, "icc", 1)) {
277*dfc6aa5cSAndroid Build Coastguard Worker /* Set ICC filename. */
278*dfc6aa5cSAndroid Build Coastguard Worker if (++argn >= argc) /* advance to next argument */
279*dfc6aa5cSAndroid Build Coastguard Worker usage();
280*dfc6aa5cSAndroid Build Coastguard Worker icc_filename = argv[argn];
281*dfc6aa5cSAndroid Build Coastguard Worker
282*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(arg, "maxmemory", 3)) {
283*dfc6aa5cSAndroid Build Coastguard Worker /* Maximum memory in Kb (or Mb with 'm'). */
284*dfc6aa5cSAndroid Build Coastguard Worker long lval;
285*dfc6aa5cSAndroid Build Coastguard Worker char ch = 'x';
286*dfc6aa5cSAndroid Build Coastguard Worker
287*dfc6aa5cSAndroid Build Coastguard Worker if (++argn >= argc) /* advance to next argument */
288*dfc6aa5cSAndroid Build Coastguard Worker usage();
289*dfc6aa5cSAndroid Build Coastguard Worker if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
290*dfc6aa5cSAndroid Build Coastguard Worker usage();
291*dfc6aa5cSAndroid Build Coastguard Worker if (ch == 'm' || ch == 'M')
292*dfc6aa5cSAndroid Build Coastguard Worker lval *= 1000L;
293*dfc6aa5cSAndroid Build Coastguard Worker cinfo->mem->max_memory_to_use = lval * 1000L;
294*dfc6aa5cSAndroid Build Coastguard Worker
295*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(arg, "maxscans", 4)) {
296*dfc6aa5cSAndroid Build Coastguard Worker if (++argn >= argc) /* advance to next argument */
297*dfc6aa5cSAndroid Build Coastguard Worker usage();
298*dfc6aa5cSAndroid Build Coastguard Worker if (sscanf(argv[argn], "%u", &max_scans) != 1)
299*dfc6aa5cSAndroid Build Coastguard Worker usage();
300*dfc6aa5cSAndroid Build Coastguard Worker
301*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
302*dfc6aa5cSAndroid Build Coastguard Worker /* Enable entropy parm optimization. */
303*dfc6aa5cSAndroid Build Coastguard Worker #ifdef ENTROPY_OPT_SUPPORTED
304*dfc6aa5cSAndroid Build Coastguard Worker cinfo->optimize_coding = TRUE;
305*dfc6aa5cSAndroid Build Coastguard Worker #else
306*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
307*dfc6aa5cSAndroid Build Coastguard Worker progname);
308*dfc6aa5cSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
309*dfc6aa5cSAndroid Build Coastguard Worker #endif
310*dfc6aa5cSAndroid Build Coastguard Worker
311*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(arg, "outfile", 4)) {
312*dfc6aa5cSAndroid Build Coastguard Worker /* Set output file name. */
313*dfc6aa5cSAndroid Build Coastguard Worker if (++argn >= argc) /* advance to next argument */
314*dfc6aa5cSAndroid Build Coastguard Worker usage();
315*dfc6aa5cSAndroid Build Coastguard Worker outfilename = argv[argn]; /* save it away for later use */
316*dfc6aa5cSAndroid Build Coastguard Worker
317*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(arg, "perfect", 2)) {
318*dfc6aa5cSAndroid Build Coastguard Worker /* Fail if there is any partial edge MCUs that the transform can't
319*dfc6aa5cSAndroid Build Coastguard Worker * handle. */
320*dfc6aa5cSAndroid Build Coastguard Worker transformoption.perfect = TRUE;
321*dfc6aa5cSAndroid Build Coastguard Worker
322*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(arg, "progressive", 2)) {
323*dfc6aa5cSAndroid Build Coastguard Worker /* Select simple progressive mode. */
324*dfc6aa5cSAndroid Build Coastguard Worker #ifdef C_PROGRESSIVE_SUPPORTED
325*dfc6aa5cSAndroid Build Coastguard Worker simple_progressive = TRUE;
326*dfc6aa5cSAndroid Build Coastguard Worker /* We must postpone execution until num_components is known. */
327*dfc6aa5cSAndroid Build Coastguard Worker #else
328*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "%s: sorry, progressive output was not compiled\n",
329*dfc6aa5cSAndroid Build Coastguard Worker progname);
330*dfc6aa5cSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
331*dfc6aa5cSAndroid Build Coastguard Worker #endif
332*dfc6aa5cSAndroid Build Coastguard Worker
333*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(arg, "report", 3)) {
334*dfc6aa5cSAndroid Build Coastguard Worker report = TRUE;
335*dfc6aa5cSAndroid Build Coastguard Worker
336*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(arg, "restart", 1)) {
337*dfc6aa5cSAndroid Build Coastguard Worker /* Restart interval in MCU rows (or in MCUs with 'b'). */
338*dfc6aa5cSAndroid Build Coastguard Worker long lval;
339*dfc6aa5cSAndroid Build Coastguard Worker char ch = 'x';
340*dfc6aa5cSAndroid Build Coastguard Worker
341*dfc6aa5cSAndroid Build Coastguard Worker if (++argn >= argc) /* advance to next argument */
342*dfc6aa5cSAndroid Build Coastguard Worker usage();
343*dfc6aa5cSAndroid Build Coastguard Worker if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
344*dfc6aa5cSAndroid Build Coastguard Worker usage();
345*dfc6aa5cSAndroid Build Coastguard Worker if (lval < 0 || lval > 65535L)
346*dfc6aa5cSAndroid Build Coastguard Worker usage();
347*dfc6aa5cSAndroid Build Coastguard Worker if (ch == 'b' || ch == 'B') {
348*dfc6aa5cSAndroid Build Coastguard Worker cinfo->restart_interval = (unsigned int)lval;
349*dfc6aa5cSAndroid Build Coastguard Worker cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */
350*dfc6aa5cSAndroid Build Coastguard Worker } else {
351*dfc6aa5cSAndroid Build Coastguard Worker cinfo->restart_in_rows = (int)lval;
352*dfc6aa5cSAndroid Build Coastguard Worker /* restart_interval will be computed during startup */
353*dfc6aa5cSAndroid Build Coastguard Worker }
354*dfc6aa5cSAndroid Build Coastguard Worker
355*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(arg, "rotate", 2)) {
356*dfc6aa5cSAndroid Build Coastguard Worker /* Rotate 90, 180, or 270 degrees (measured clockwise). */
357*dfc6aa5cSAndroid Build Coastguard Worker if (++argn >= argc) /* advance to next argument */
358*dfc6aa5cSAndroid Build Coastguard Worker usage();
359*dfc6aa5cSAndroid Build Coastguard Worker if (keymatch(argv[argn], "90", 2))
360*dfc6aa5cSAndroid Build Coastguard Worker select_transform(JXFORM_ROT_90);
361*dfc6aa5cSAndroid Build Coastguard Worker else if (keymatch(argv[argn], "180", 3))
362*dfc6aa5cSAndroid Build Coastguard Worker select_transform(JXFORM_ROT_180);
363*dfc6aa5cSAndroid Build Coastguard Worker else if (keymatch(argv[argn], "270", 3))
364*dfc6aa5cSAndroid Build Coastguard Worker select_transform(JXFORM_ROT_270);
365*dfc6aa5cSAndroid Build Coastguard Worker else
366*dfc6aa5cSAndroid Build Coastguard Worker usage();
367*dfc6aa5cSAndroid Build Coastguard Worker
368*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(arg, "scans", 1)) {
369*dfc6aa5cSAndroid Build Coastguard Worker /* Set scan script. */
370*dfc6aa5cSAndroid Build Coastguard Worker #ifdef C_MULTISCAN_FILES_SUPPORTED
371*dfc6aa5cSAndroid Build Coastguard Worker if (++argn >= argc) /* advance to next argument */
372*dfc6aa5cSAndroid Build Coastguard Worker usage();
373*dfc6aa5cSAndroid Build Coastguard Worker scansarg = argv[argn];
374*dfc6aa5cSAndroid Build Coastguard Worker /* We must postpone reading the file in case -progressive appears. */
375*dfc6aa5cSAndroid Build Coastguard Worker #else
376*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "%s: sorry, multi-scan output was not compiled\n",
377*dfc6aa5cSAndroid Build Coastguard Worker progname);
378*dfc6aa5cSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
379*dfc6aa5cSAndroid Build Coastguard Worker #endif
380*dfc6aa5cSAndroid Build Coastguard Worker
381*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(arg, "strict", 2)) {
382*dfc6aa5cSAndroid Build Coastguard Worker strict = TRUE;
383*dfc6aa5cSAndroid Build Coastguard Worker
384*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(arg, "transpose", 1)) {
385*dfc6aa5cSAndroid Build Coastguard Worker /* Transpose (across UL-to-LR axis). */
386*dfc6aa5cSAndroid Build Coastguard Worker select_transform(JXFORM_TRANSPOSE);
387*dfc6aa5cSAndroid Build Coastguard Worker
388*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(arg, "transverse", 6)) {
389*dfc6aa5cSAndroid Build Coastguard Worker /* Transverse transpose (across UR-to-LL axis). */
390*dfc6aa5cSAndroid Build Coastguard Worker select_transform(JXFORM_TRANSVERSE);
391*dfc6aa5cSAndroid Build Coastguard Worker
392*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(arg, "trim", 3)) {
393*dfc6aa5cSAndroid Build Coastguard Worker /* Trim off any partial edge MCUs that the transform can't handle. */
394*dfc6aa5cSAndroid Build Coastguard Worker transformoption.trim = TRUE;
395*dfc6aa5cSAndroid Build Coastguard Worker
396*dfc6aa5cSAndroid Build Coastguard Worker } else if (keymatch(arg, "wipe", 1)) {
397*dfc6aa5cSAndroid Build Coastguard Worker #if TRANSFORMS_SUPPORTED
398*dfc6aa5cSAndroid Build Coastguard Worker if (++argn >= argc) /* advance to next argument */
399*dfc6aa5cSAndroid Build Coastguard Worker usage();
400*dfc6aa5cSAndroid Build Coastguard Worker if (transformoption.crop /* reject multiple crop/drop/wipe requests */ ||
401*dfc6aa5cSAndroid Build Coastguard Worker !jtransform_parse_crop_spec(&transformoption, argv[argn])) {
402*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "%s: bogus -wipe argument '%s'\n",
403*dfc6aa5cSAndroid Build Coastguard Worker progname, argv[argn]);
404*dfc6aa5cSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
405*dfc6aa5cSAndroid Build Coastguard Worker }
406*dfc6aa5cSAndroid Build Coastguard Worker select_transform(JXFORM_WIPE);
407*dfc6aa5cSAndroid Build Coastguard Worker #else
408*dfc6aa5cSAndroid Build Coastguard Worker select_transform(JXFORM_NONE); /* force an error */
409*dfc6aa5cSAndroid Build Coastguard Worker #endif
410*dfc6aa5cSAndroid Build Coastguard Worker
411*dfc6aa5cSAndroid Build Coastguard Worker } else {
412*dfc6aa5cSAndroid Build Coastguard Worker usage(); /* bogus switch */
413*dfc6aa5cSAndroid Build Coastguard Worker }
414*dfc6aa5cSAndroid Build Coastguard Worker }
415*dfc6aa5cSAndroid Build Coastguard Worker
416*dfc6aa5cSAndroid Build Coastguard Worker /* Post-switch-scanning cleanup */
417*dfc6aa5cSAndroid Build Coastguard Worker
418*dfc6aa5cSAndroid Build Coastguard Worker if (for_real) {
419*dfc6aa5cSAndroid Build Coastguard Worker
420*dfc6aa5cSAndroid Build Coastguard Worker #ifdef C_PROGRESSIVE_SUPPORTED
421*dfc6aa5cSAndroid Build Coastguard Worker if (simple_progressive) /* process -progressive; -scans can override */
422*dfc6aa5cSAndroid Build Coastguard Worker jpeg_simple_progression(cinfo);
423*dfc6aa5cSAndroid Build Coastguard Worker #endif
424*dfc6aa5cSAndroid Build Coastguard Worker
425*dfc6aa5cSAndroid Build Coastguard Worker #ifdef C_MULTISCAN_FILES_SUPPORTED
426*dfc6aa5cSAndroid Build Coastguard Worker if (scansarg != NULL) /* process -scans if it was present */
427*dfc6aa5cSAndroid Build Coastguard Worker if (!read_scan_script(cinfo, scansarg))
428*dfc6aa5cSAndroid Build Coastguard Worker usage();
429*dfc6aa5cSAndroid Build Coastguard Worker #endif
430*dfc6aa5cSAndroid Build Coastguard Worker }
431*dfc6aa5cSAndroid Build Coastguard Worker
432*dfc6aa5cSAndroid Build Coastguard Worker return argn; /* return index of next arg (file name) */
433*dfc6aa5cSAndroid Build Coastguard Worker }
434*dfc6aa5cSAndroid Build Coastguard Worker
435*dfc6aa5cSAndroid Build Coastguard Worker
436*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(void)
my_emit_message(j_common_ptr cinfo,int msg_level)437*dfc6aa5cSAndroid Build Coastguard Worker my_emit_message(j_common_ptr cinfo, int msg_level)
438*dfc6aa5cSAndroid Build Coastguard Worker {
439*dfc6aa5cSAndroid Build Coastguard Worker if (msg_level < 0) {
440*dfc6aa5cSAndroid Build Coastguard Worker /* Treat warning as fatal */
441*dfc6aa5cSAndroid Build Coastguard Worker cinfo->err->error_exit(cinfo);
442*dfc6aa5cSAndroid Build Coastguard Worker } else {
443*dfc6aa5cSAndroid Build Coastguard Worker if (cinfo->err->trace_level >= msg_level)
444*dfc6aa5cSAndroid Build Coastguard Worker cinfo->err->output_message(cinfo);
445*dfc6aa5cSAndroid Build Coastguard Worker }
446*dfc6aa5cSAndroid Build Coastguard Worker }
447*dfc6aa5cSAndroid Build Coastguard Worker
448*dfc6aa5cSAndroid Build Coastguard Worker
449*dfc6aa5cSAndroid Build Coastguard Worker /*
450*dfc6aa5cSAndroid Build Coastguard Worker * The main program.
451*dfc6aa5cSAndroid Build Coastguard Worker */
452*dfc6aa5cSAndroid Build Coastguard Worker
453*dfc6aa5cSAndroid Build Coastguard Worker int
454*dfc6aa5cSAndroid Build Coastguard Worker #ifdef GTEST
jpegtran(int argc,char ** argv)455*dfc6aa5cSAndroid Build Coastguard Worker jpegtran(int argc, char **argv)
456*dfc6aa5cSAndroid Build Coastguard Worker #else
457*dfc6aa5cSAndroid Build Coastguard Worker main(int argc, char **argv)
458*dfc6aa5cSAndroid Build Coastguard Worker #endif
459*dfc6aa5cSAndroid Build Coastguard Worker {
460*dfc6aa5cSAndroid Build Coastguard Worker struct jpeg_decompress_struct srcinfo;
461*dfc6aa5cSAndroid Build Coastguard Worker #if TRANSFORMS_SUPPORTED
462*dfc6aa5cSAndroid Build Coastguard Worker struct jpeg_decompress_struct dropinfo;
463*dfc6aa5cSAndroid Build Coastguard Worker struct jpeg_error_mgr jdroperr;
464*dfc6aa5cSAndroid Build Coastguard Worker FILE *drop_file;
465*dfc6aa5cSAndroid Build Coastguard Worker #endif
466*dfc6aa5cSAndroid Build Coastguard Worker struct jpeg_compress_struct dstinfo;
467*dfc6aa5cSAndroid Build Coastguard Worker struct jpeg_error_mgr jsrcerr, jdsterr;
468*dfc6aa5cSAndroid Build Coastguard Worker struct cdjpeg_progress_mgr src_progress, dst_progress;
469*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *src_coef_arrays;
470*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *dst_coef_arrays;
471*dfc6aa5cSAndroid Build Coastguard Worker int file_index;
472*dfc6aa5cSAndroid Build Coastguard Worker /* We assume all-in-memory processing and can therefore use only a
473*dfc6aa5cSAndroid Build Coastguard Worker * single file pointer for sequential input and output operation.
474*dfc6aa5cSAndroid Build Coastguard Worker */
475*dfc6aa5cSAndroid Build Coastguard Worker FILE *fp;
476*dfc6aa5cSAndroid Build Coastguard Worker FILE *icc_file;
477*dfc6aa5cSAndroid Build Coastguard Worker JOCTET *icc_profile = NULL;
478*dfc6aa5cSAndroid Build Coastguard Worker long icc_len = 0;
479*dfc6aa5cSAndroid Build Coastguard Worker
480*dfc6aa5cSAndroid Build Coastguard Worker progname = argv[0];
481*dfc6aa5cSAndroid Build Coastguard Worker if (progname == NULL || progname[0] == 0)
482*dfc6aa5cSAndroid Build Coastguard Worker progname = "jpegtran"; /* in case C library doesn't provide it */
483*dfc6aa5cSAndroid Build Coastguard Worker
484*dfc6aa5cSAndroid Build Coastguard Worker /* Initialize the JPEG decompression object with default error handling. */
485*dfc6aa5cSAndroid Build Coastguard Worker srcinfo.err = jpeg_std_error(&jsrcerr);
486*dfc6aa5cSAndroid Build Coastguard Worker jpeg_create_decompress(&srcinfo);
487*dfc6aa5cSAndroid Build Coastguard Worker /* Initialize the JPEG compression object with default error handling. */
488*dfc6aa5cSAndroid Build Coastguard Worker dstinfo.err = jpeg_std_error(&jdsterr);
489*dfc6aa5cSAndroid Build Coastguard Worker jpeg_create_compress(&dstinfo);
490*dfc6aa5cSAndroid Build Coastguard Worker
491*dfc6aa5cSAndroid Build Coastguard Worker /* Scan command line to find file names.
492*dfc6aa5cSAndroid Build Coastguard Worker * It is convenient to use just one switch-parsing routine, but the switch
493*dfc6aa5cSAndroid Build Coastguard Worker * values read here are mostly ignored; we will rescan the switches after
494*dfc6aa5cSAndroid Build Coastguard Worker * opening the input file. Also note that most of the switches affect the
495*dfc6aa5cSAndroid Build Coastguard Worker * destination JPEG object, so we parse into that and then copy over what
496*dfc6aa5cSAndroid Build Coastguard Worker * needs to affect the source too.
497*dfc6aa5cSAndroid Build Coastguard Worker */
498*dfc6aa5cSAndroid Build Coastguard Worker
499*dfc6aa5cSAndroid Build Coastguard Worker file_index = parse_switches(&dstinfo, argc, argv, 0, FALSE);
500*dfc6aa5cSAndroid Build Coastguard Worker jsrcerr.trace_level = jdsterr.trace_level;
501*dfc6aa5cSAndroid Build Coastguard Worker srcinfo.mem->max_memory_to_use = dstinfo.mem->max_memory_to_use;
502*dfc6aa5cSAndroid Build Coastguard Worker
503*dfc6aa5cSAndroid Build Coastguard Worker if (strict)
504*dfc6aa5cSAndroid Build Coastguard Worker jsrcerr.emit_message = my_emit_message;
505*dfc6aa5cSAndroid Build Coastguard Worker
506*dfc6aa5cSAndroid Build Coastguard Worker #ifdef TWO_FILE_COMMANDLINE
507*dfc6aa5cSAndroid Build Coastguard Worker /* Must have either -outfile switch or explicit output file name */
508*dfc6aa5cSAndroid Build Coastguard Worker if (outfilename == NULL) {
509*dfc6aa5cSAndroid Build Coastguard Worker if (file_index != argc - 2) {
510*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "%s: must name one input and one output file\n",
511*dfc6aa5cSAndroid Build Coastguard Worker progname);
512*dfc6aa5cSAndroid Build Coastguard Worker usage();
513*dfc6aa5cSAndroid Build Coastguard Worker }
514*dfc6aa5cSAndroid Build Coastguard Worker outfilename = argv[file_index + 1];
515*dfc6aa5cSAndroid Build Coastguard Worker } else {
516*dfc6aa5cSAndroid Build Coastguard Worker if (file_index != argc - 1) {
517*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "%s: must name one input and one output file\n",
518*dfc6aa5cSAndroid Build Coastguard Worker progname);
519*dfc6aa5cSAndroid Build Coastguard Worker usage();
520*dfc6aa5cSAndroid Build Coastguard Worker }
521*dfc6aa5cSAndroid Build Coastguard Worker }
522*dfc6aa5cSAndroid Build Coastguard Worker #else
523*dfc6aa5cSAndroid Build Coastguard Worker /* Unix style: expect zero or one file name */
524*dfc6aa5cSAndroid Build Coastguard Worker if (file_index < argc - 1) {
525*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "%s: only one input file\n", progname);
526*dfc6aa5cSAndroid Build Coastguard Worker usage();
527*dfc6aa5cSAndroid Build Coastguard Worker }
528*dfc6aa5cSAndroid Build Coastguard Worker #endif /* TWO_FILE_COMMANDLINE */
529*dfc6aa5cSAndroid Build Coastguard Worker
530*dfc6aa5cSAndroid Build Coastguard Worker /* Open the input file. */
531*dfc6aa5cSAndroid Build Coastguard Worker if (file_index < argc) {
532*dfc6aa5cSAndroid Build Coastguard Worker if ((fp = fopen(argv[file_index], READ_BINARY)) == NULL) {
533*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "%s: can't open %s for reading\n", progname,
534*dfc6aa5cSAndroid Build Coastguard Worker argv[file_index]);
535*dfc6aa5cSAndroid Build Coastguard Worker return EXIT_FAILURE;
536*dfc6aa5cSAndroid Build Coastguard Worker }
537*dfc6aa5cSAndroid Build Coastguard Worker } else {
538*dfc6aa5cSAndroid Build Coastguard Worker /* default input file is stdin */
539*dfc6aa5cSAndroid Build Coastguard Worker fp = read_stdin();
540*dfc6aa5cSAndroid Build Coastguard Worker }
541*dfc6aa5cSAndroid Build Coastguard Worker
542*dfc6aa5cSAndroid Build Coastguard Worker if (icc_filename != NULL) {
543*dfc6aa5cSAndroid Build Coastguard Worker if ((icc_file = fopen(icc_filename, READ_BINARY)) == NULL) {
544*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "%s: can't open %s\n", progname, icc_filename);
545*dfc6aa5cSAndroid Build Coastguard Worker return EXIT_FAILURE;
546*dfc6aa5cSAndroid Build Coastguard Worker }
547*dfc6aa5cSAndroid Build Coastguard Worker if (fseek(icc_file, 0, SEEK_END) < 0 ||
548*dfc6aa5cSAndroid Build Coastguard Worker (icc_len = ftell(icc_file)) < 1 ||
549*dfc6aa5cSAndroid Build Coastguard Worker fseek(icc_file, 0, SEEK_SET) < 0) {
550*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "%s: can't determine size of %s\n", progname,
551*dfc6aa5cSAndroid Build Coastguard Worker icc_filename);
552*dfc6aa5cSAndroid Build Coastguard Worker return EXIT_FAILURE;
553*dfc6aa5cSAndroid Build Coastguard Worker }
554*dfc6aa5cSAndroid Build Coastguard Worker if ((icc_profile = (JOCTET *)malloc(icc_len)) == NULL) {
555*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "%s: can't allocate memory for ICC profile\n", progname);
556*dfc6aa5cSAndroid Build Coastguard Worker fclose(icc_file);
557*dfc6aa5cSAndroid Build Coastguard Worker return EXIT_FAILURE;
558*dfc6aa5cSAndroid Build Coastguard Worker }
559*dfc6aa5cSAndroid Build Coastguard Worker if (fread(icc_profile, icc_len, 1, icc_file) < 1) {
560*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "%s: can't read ICC profile from %s\n", progname,
561*dfc6aa5cSAndroid Build Coastguard Worker icc_filename);
562*dfc6aa5cSAndroid Build Coastguard Worker free(icc_profile);
563*dfc6aa5cSAndroid Build Coastguard Worker fclose(icc_file);
564*dfc6aa5cSAndroid Build Coastguard Worker return EXIT_FAILURE;
565*dfc6aa5cSAndroid Build Coastguard Worker }
566*dfc6aa5cSAndroid Build Coastguard Worker fclose(icc_file);
567*dfc6aa5cSAndroid Build Coastguard Worker if (copyoption == JCOPYOPT_ALL)
568*dfc6aa5cSAndroid Build Coastguard Worker copyoption = JCOPYOPT_ALL_EXCEPT_ICC;
569*dfc6aa5cSAndroid Build Coastguard Worker if (copyoption == JCOPYOPT_ICC)
570*dfc6aa5cSAndroid Build Coastguard Worker copyoption = JCOPYOPT_NONE;
571*dfc6aa5cSAndroid Build Coastguard Worker }
572*dfc6aa5cSAndroid Build Coastguard Worker
573*dfc6aa5cSAndroid Build Coastguard Worker if (report) {
574*dfc6aa5cSAndroid Build Coastguard Worker start_progress_monitor((j_common_ptr)&dstinfo, &dst_progress);
575*dfc6aa5cSAndroid Build Coastguard Worker dst_progress.report = report;
576*dfc6aa5cSAndroid Build Coastguard Worker }
577*dfc6aa5cSAndroid Build Coastguard Worker if (report || max_scans != 0) {
578*dfc6aa5cSAndroid Build Coastguard Worker start_progress_monitor((j_common_ptr)&srcinfo, &src_progress);
579*dfc6aa5cSAndroid Build Coastguard Worker src_progress.report = report;
580*dfc6aa5cSAndroid Build Coastguard Worker src_progress.max_scans = max_scans;
581*dfc6aa5cSAndroid Build Coastguard Worker }
582*dfc6aa5cSAndroid Build Coastguard Worker #if TRANSFORMS_SUPPORTED
583*dfc6aa5cSAndroid Build Coastguard Worker /* Open the drop file. */
584*dfc6aa5cSAndroid Build Coastguard Worker if (dropfilename != NULL) {
585*dfc6aa5cSAndroid Build Coastguard Worker if ((drop_file = fopen(dropfilename, READ_BINARY)) == NULL) {
586*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "%s: can't open %s for reading\n", progname,
587*dfc6aa5cSAndroid Build Coastguard Worker dropfilename);
588*dfc6aa5cSAndroid Build Coastguard Worker return EXIT_FAILURE;
589*dfc6aa5cSAndroid Build Coastguard Worker }
590*dfc6aa5cSAndroid Build Coastguard Worker dropinfo.err = jpeg_std_error(&jdroperr);
591*dfc6aa5cSAndroid Build Coastguard Worker jpeg_create_decompress(&dropinfo);
592*dfc6aa5cSAndroid Build Coastguard Worker jpeg_stdio_src(&dropinfo, drop_file);
593*dfc6aa5cSAndroid Build Coastguard Worker } else {
594*dfc6aa5cSAndroid Build Coastguard Worker drop_file = NULL;
595*dfc6aa5cSAndroid Build Coastguard Worker }
596*dfc6aa5cSAndroid Build Coastguard Worker #endif
597*dfc6aa5cSAndroid Build Coastguard Worker
598*dfc6aa5cSAndroid Build Coastguard Worker /* Specify data source for decompression */
599*dfc6aa5cSAndroid Build Coastguard Worker jpeg_stdio_src(&srcinfo, fp);
600*dfc6aa5cSAndroid Build Coastguard Worker
601*dfc6aa5cSAndroid Build Coastguard Worker /* Enable saving of extra markers that we want to copy */
602*dfc6aa5cSAndroid Build Coastguard Worker jcopy_markers_setup(&srcinfo, copyoption);
603*dfc6aa5cSAndroid Build Coastguard Worker
604*dfc6aa5cSAndroid Build Coastguard Worker /* Read file header */
605*dfc6aa5cSAndroid Build Coastguard Worker (void)jpeg_read_header(&srcinfo, TRUE);
606*dfc6aa5cSAndroid Build Coastguard Worker
607*dfc6aa5cSAndroid Build Coastguard Worker #if TRANSFORMS_SUPPORTED
608*dfc6aa5cSAndroid Build Coastguard Worker if (dropfilename != NULL) {
609*dfc6aa5cSAndroid Build Coastguard Worker (void)jpeg_read_header(&dropinfo, TRUE);
610*dfc6aa5cSAndroid Build Coastguard Worker transformoption.crop_width = dropinfo.image_width;
611*dfc6aa5cSAndroid Build Coastguard Worker transformoption.crop_width_set = JCROP_POS;
612*dfc6aa5cSAndroid Build Coastguard Worker transformoption.crop_height = dropinfo.image_height;
613*dfc6aa5cSAndroid Build Coastguard Worker transformoption.crop_height_set = JCROP_POS;
614*dfc6aa5cSAndroid Build Coastguard Worker transformoption.drop_ptr = &dropinfo;
615*dfc6aa5cSAndroid Build Coastguard Worker }
616*dfc6aa5cSAndroid Build Coastguard Worker #endif
617*dfc6aa5cSAndroid Build Coastguard Worker
618*dfc6aa5cSAndroid Build Coastguard Worker /* Any space needed by a transform option must be requested before
619*dfc6aa5cSAndroid Build Coastguard Worker * jpeg_read_coefficients so that memory allocation will be done right.
620*dfc6aa5cSAndroid Build Coastguard Worker */
621*dfc6aa5cSAndroid Build Coastguard Worker #if TRANSFORMS_SUPPORTED
622*dfc6aa5cSAndroid Build Coastguard Worker /* Fail right away if -perfect is given and transformation is not perfect.
623*dfc6aa5cSAndroid Build Coastguard Worker */
624*dfc6aa5cSAndroid Build Coastguard Worker if (!jtransform_request_workspace(&srcinfo, &transformoption)) {
625*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "%s: transformation is not perfect\n", progname);
626*dfc6aa5cSAndroid Build Coastguard Worker return EXIT_FAILURE;
627*dfc6aa5cSAndroid Build Coastguard Worker }
628*dfc6aa5cSAndroid Build Coastguard Worker #endif
629*dfc6aa5cSAndroid Build Coastguard Worker
630*dfc6aa5cSAndroid Build Coastguard Worker /* Read source file as DCT coefficients */
631*dfc6aa5cSAndroid Build Coastguard Worker src_coef_arrays = jpeg_read_coefficients(&srcinfo);
632*dfc6aa5cSAndroid Build Coastguard Worker
633*dfc6aa5cSAndroid Build Coastguard Worker #if TRANSFORMS_SUPPORTED
634*dfc6aa5cSAndroid Build Coastguard Worker if (dropfilename != NULL) {
635*dfc6aa5cSAndroid Build Coastguard Worker transformoption.drop_coef_arrays = jpeg_read_coefficients(&dropinfo);
636*dfc6aa5cSAndroid Build Coastguard Worker }
637*dfc6aa5cSAndroid Build Coastguard Worker #endif
638*dfc6aa5cSAndroid Build Coastguard Worker
639*dfc6aa5cSAndroid Build Coastguard Worker /* Initialize destination compression parameters from source values */
640*dfc6aa5cSAndroid Build Coastguard Worker jpeg_copy_critical_parameters(&srcinfo, &dstinfo);
641*dfc6aa5cSAndroid Build Coastguard Worker
642*dfc6aa5cSAndroid Build Coastguard Worker /* Adjust destination parameters if required by transform options;
643*dfc6aa5cSAndroid Build Coastguard Worker * also find out which set of coefficient arrays will hold the output.
644*dfc6aa5cSAndroid Build Coastguard Worker */
645*dfc6aa5cSAndroid Build Coastguard Worker #if TRANSFORMS_SUPPORTED
646*dfc6aa5cSAndroid Build Coastguard Worker dst_coef_arrays = jtransform_adjust_parameters(&srcinfo, &dstinfo,
647*dfc6aa5cSAndroid Build Coastguard Worker src_coef_arrays,
648*dfc6aa5cSAndroid Build Coastguard Worker &transformoption);
649*dfc6aa5cSAndroid Build Coastguard Worker #else
650*dfc6aa5cSAndroid Build Coastguard Worker dst_coef_arrays = src_coef_arrays;
651*dfc6aa5cSAndroid Build Coastguard Worker #endif
652*dfc6aa5cSAndroid Build Coastguard Worker
653*dfc6aa5cSAndroid Build Coastguard Worker /* Close input file, if we opened it.
654*dfc6aa5cSAndroid Build Coastguard Worker * Note: we assume that jpeg_read_coefficients consumed all input
655*dfc6aa5cSAndroid Build Coastguard Worker * until JPEG_REACHED_EOI, and that jpeg_finish_decompress will
656*dfc6aa5cSAndroid Build Coastguard Worker * only consume more while (!cinfo->inputctl->eoi_reached).
657*dfc6aa5cSAndroid Build Coastguard Worker * We cannot call jpeg_finish_decompress here since we still need the
658*dfc6aa5cSAndroid Build Coastguard Worker * virtual arrays allocated from the source object for processing.
659*dfc6aa5cSAndroid Build Coastguard Worker */
660*dfc6aa5cSAndroid Build Coastguard Worker if (fp != stdin)
661*dfc6aa5cSAndroid Build Coastguard Worker fclose(fp);
662*dfc6aa5cSAndroid Build Coastguard Worker
663*dfc6aa5cSAndroid Build Coastguard Worker /* Open the output file. */
664*dfc6aa5cSAndroid Build Coastguard Worker if (outfilename != NULL) {
665*dfc6aa5cSAndroid Build Coastguard Worker if ((fp = fopen(outfilename, WRITE_BINARY)) == NULL) {
666*dfc6aa5cSAndroid Build Coastguard Worker fprintf(stderr, "%s: can't open %s for writing\n", progname,
667*dfc6aa5cSAndroid Build Coastguard Worker outfilename);
668*dfc6aa5cSAndroid Build Coastguard Worker return EXIT_FAILURE;
669*dfc6aa5cSAndroid Build Coastguard Worker }
670*dfc6aa5cSAndroid Build Coastguard Worker } else {
671*dfc6aa5cSAndroid Build Coastguard Worker /* default output file is stdout */
672*dfc6aa5cSAndroid Build Coastguard Worker fp = write_stdout();
673*dfc6aa5cSAndroid Build Coastguard Worker }
674*dfc6aa5cSAndroid Build Coastguard Worker
675*dfc6aa5cSAndroid Build Coastguard Worker /* Adjust default compression parameters by re-parsing the options */
676*dfc6aa5cSAndroid Build Coastguard Worker file_index = parse_switches(&dstinfo, argc, argv, 0, TRUE);
677*dfc6aa5cSAndroid Build Coastguard Worker
678*dfc6aa5cSAndroid Build Coastguard Worker /* Specify data destination for compression */
679*dfc6aa5cSAndroid Build Coastguard Worker jpeg_stdio_dest(&dstinfo, fp);
680*dfc6aa5cSAndroid Build Coastguard Worker
681*dfc6aa5cSAndroid Build Coastguard Worker /* Start compressor (note no image data is actually written here) */
682*dfc6aa5cSAndroid Build Coastguard Worker jpeg_write_coefficients(&dstinfo, dst_coef_arrays);
683*dfc6aa5cSAndroid Build Coastguard Worker
684*dfc6aa5cSAndroid Build Coastguard Worker /* Copy to the output file any extra markers that we want to preserve */
685*dfc6aa5cSAndroid Build Coastguard Worker jcopy_markers_execute(&srcinfo, &dstinfo, copyoption);
686*dfc6aa5cSAndroid Build Coastguard Worker
687*dfc6aa5cSAndroid Build Coastguard Worker if (icc_profile != NULL)
688*dfc6aa5cSAndroid Build Coastguard Worker jpeg_write_icc_profile(&dstinfo, icc_profile, (unsigned int)icc_len);
689*dfc6aa5cSAndroid Build Coastguard Worker
690*dfc6aa5cSAndroid Build Coastguard Worker /* Execute image transformation, if any */
691*dfc6aa5cSAndroid Build Coastguard Worker #if TRANSFORMS_SUPPORTED
692*dfc6aa5cSAndroid Build Coastguard Worker jtransform_execute_transformation(&srcinfo, &dstinfo, src_coef_arrays,
693*dfc6aa5cSAndroid Build Coastguard Worker &transformoption);
694*dfc6aa5cSAndroid Build Coastguard Worker #endif
695*dfc6aa5cSAndroid Build Coastguard Worker
696*dfc6aa5cSAndroid Build Coastguard Worker /* Finish compression and release memory */
697*dfc6aa5cSAndroid Build Coastguard Worker jpeg_finish_compress(&dstinfo);
698*dfc6aa5cSAndroid Build Coastguard Worker jpeg_destroy_compress(&dstinfo);
699*dfc6aa5cSAndroid Build Coastguard Worker #if TRANSFORMS_SUPPORTED
700*dfc6aa5cSAndroid Build Coastguard Worker if (dropfilename != NULL) {
701*dfc6aa5cSAndroid Build Coastguard Worker (void)jpeg_finish_decompress(&dropinfo);
702*dfc6aa5cSAndroid Build Coastguard Worker jpeg_destroy_decompress(&dropinfo);
703*dfc6aa5cSAndroid Build Coastguard Worker }
704*dfc6aa5cSAndroid Build Coastguard Worker #endif
705*dfc6aa5cSAndroid Build Coastguard Worker (void)jpeg_finish_decompress(&srcinfo);
706*dfc6aa5cSAndroid Build Coastguard Worker jpeg_destroy_decompress(&srcinfo);
707*dfc6aa5cSAndroid Build Coastguard Worker
708*dfc6aa5cSAndroid Build Coastguard Worker /* Close output file, if we opened it */
709*dfc6aa5cSAndroid Build Coastguard Worker if (fp != stdout)
710*dfc6aa5cSAndroid Build Coastguard Worker fclose(fp);
711*dfc6aa5cSAndroid Build Coastguard Worker #if TRANSFORMS_SUPPORTED
712*dfc6aa5cSAndroid Build Coastguard Worker if (drop_file != NULL)
713*dfc6aa5cSAndroid Build Coastguard Worker fclose(drop_file);
714*dfc6aa5cSAndroid Build Coastguard Worker #endif
715*dfc6aa5cSAndroid Build Coastguard Worker
716*dfc6aa5cSAndroid Build Coastguard Worker if (report)
717*dfc6aa5cSAndroid Build Coastguard Worker end_progress_monitor((j_common_ptr)&dstinfo);
718*dfc6aa5cSAndroid Build Coastguard Worker if (report || max_scans != 0)
719*dfc6aa5cSAndroid Build Coastguard Worker end_progress_monitor((j_common_ptr)&srcinfo);
720*dfc6aa5cSAndroid Build Coastguard Worker
721*dfc6aa5cSAndroid Build Coastguard Worker free(icc_profile);
722*dfc6aa5cSAndroid Build Coastguard Worker
723*dfc6aa5cSAndroid Build Coastguard Worker /* All done. */
724*dfc6aa5cSAndroid Build Coastguard Worker #if TRANSFORMS_SUPPORTED
725*dfc6aa5cSAndroid Build Coastguard Worker if (dropfilename != NULL)
726*dfc6aa5cSAndroid Build Coastguard Worker return (jsrcerr.num_warnings + jdroperr.num_warnings +
727*dfc6aa5cSAndroid Build Coastguard Worker jdsterr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
728*dfc6aa5cSAndroid Build Coastguard Worker #endif
729*dfc6aa5cSAndroid Build Coastguard Worker return (jsrcerr.num_warnings + jdsterr.num_warnings ?
730*dfc6aa5cSAndroid Build Coastguard Worker EXIT_WARNING : EXIT_SUCCESS);
731*dfc6aa5cSAndroid Build Coastguard Worker }
732