/src/libjpeg-turbo.main/cjpeg.c
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | /* | 
| 2 |  |  * cjpeg.c | 
| 3 |  |  * | 
| 4 |  |  * This file was part of the Independent JPEG Group's software: | 
| 5 |  |  * Copyright (C) 1991-1998, Thomas G. Lane. | 
| 6 |  |  * Modified 2003-2011 by Guido Vollbeding. | 
| 7 |  |  * Lossless JPEG Modifications: | 
| 8 |  |  * Copyright (C) 1999, Ken Murchison. | 
| 9 |  |  * libjpeg-turbo Modifications: | 
| 10 |  |  * Copyright (C) 2010, 2013-2014, 2017, 2019-2022, D. R. Commander. | 
| 11 |  |  * For conditions of distribution and use, see the accompanying README.ijg | 
| 12 |  |  * file. | 
| 13 |  |  * | 
| 14 |  |  * This file contains a command-line user interface for the JPEG compressor. | 
| 15 |  |  * It should work on any system with Unix- or MS-DOS-style command lines. | 
| 16 |  |  * | 
| 17 |  |  * Two different command line styles are permitted, depending on the | 
| 18 |  |  * compile-time switch TWO_FILE_COMMANDLINE: | 
| 19 |  |  *      cjpeg [options]  inputfile outputfile | 
| 20 |  |  *      cjpeg [options]  [inputfile] | 
| 21 |  |  * In the second style, output is always to standard output, which you'd | 
| 22 |  |  * normally redirect to a file or pipe to some other program.  Input is | 
| 23 |  |  * either from a named file or from standard input (typically redirected). | 
| 24 |  |  * The second style is convenient on Unix but is unhelpful on systems that | 
| 25 |  |  * don't support pipes.  Also, you MUST use the first style if your system | 
| 26 |  |  * doesn't do binary I/O to stdin/stdout. | 
| 27 |  |  * To simplify script writing, the "-outfile" switch is provided.  The syntax | 
| 28 |  |  *      cjpeg [options]  -outfile outputfile  inputfile | 
| 29 |  |  * works regardless of which command line style is used. | 
| 30 |  |  */ | 
| 31 |  |  | 
| 32 |  | #ifdef _MSC_VER | 
| 33 |  | #define _CRT_SECURE_NO_DEPRECATE | 
| 34 |  | #endif | 
| 35 |  |  | 
| 36 |  | #ifdef CJPEG_FUZZER | 
| 37 |  | #define JPEG_INTERNALS | 
| 38 |  | #endif | 
| 39 |  | #include "cdjpeg.h"             /* Common decls for cjpeg/djpeg applications */ | 
| 40 |  | #include "jversion.h"           /* for version message */ | 
| 41 |  | #include "jconfigint.h" | 
| 42 |  |  | 
| 43 |  |  | 
| 44 |  | /* Create the add-on message string table. */ | 
| 45 |  |  | 
| 46 |  | #define JMESSAGE(code, string)  string, | 
| 47 |  |  | 
| 48 |  | static const char * const cdjpeg_message_table[] = { | 
| 49 |  | #include "cderror.h" | 
| 50 |  |   NULL | 
| 51 |  | }; | 
| 52 |  |  | 
| 53 |  |  | 
| 54 |  | /* | 
| 55 |  |  * This routine determines what format the input file is, | 
| 56 |  |  * and selects the appropriate input-reading module. | 
| 57 |  |  * | 
| 58 |  |  * To determine which family of input formats the file belongs to, | 
| 59 |  |  * we may look only at the first byte of the file, since C does not | 
| 60 |  |  * guarantee that more than one character can be pushed back with ungetc. | 
| 61 |  |  * Looking at additional bytes would require one of these approaches: | 
| 62 |  |  *     1) assume we can fseek() the input file (fails for piped input); | 
| 63 |  |  *     2) assume we can push back more than one character (works in | 
| 64 |  |  *        some C implementations, but unportable); | 
| 65 |  |  *     3) provide our own buffering (breaks input readers that want to use | 
| 66 |  |  *        stdio directly); | 
| 67 |  |  * or  4) don't put back the data, and modify the input_init methods to assume | 
| 68 |  |  *        they start reading after the start of file. | 
| 69 |  |  * #1 is attractive for MS-DOS but is untenable on Unix. | 
| 70 |  |  * | 
| 71 |  |  * The most portable solution for file types that can't be identified by their | 
| 72 |  |  * first byte is to make the user tell us what they are.  This is also the | 
| 73 |  |  * only approach for "raw" file types that contain only arbitrary values. | 
| 74 |  |  * We presently apply this method for Targa files.  Most of the time Targa | 
| 75 |  |  * files start with 0x00, so we recognize that case.  Potentially, however, | 
| 76 |  |  * a Targa file could start with any byte value (byte 0 is the length of the | 
| 77 |  |  * seldom-used ID field), so we provide a switch to force Targa input mode. | 
| 78 |  |  */ | 
| 79 |  |  | 
| 80 |  | static boolean is_targa;        /* records user -targa switch */ | 
| 81 |  |  | 
| 82 |  |  | 
| 83 |  | LOCAL(cjpeg_source_ptr) | 
| 84 |  | select_file_type(j_compress_ptr cinfo, FILE *infile) | 
| 85 | 124 | { | 
| 86 | 124 |   int c; | 
| 87 |  |  | 
| 88 | 124 |   if (is_targa) { | 
| 89 |  | #ifdef TARGA_SUPPORTED | 
| 90 |  |     return jinit_read_targa(cinfo); | 
| 91 |  | #else | 
| 92 | 62 |     ERREXIT(cinfo, JERR_TGA_NOTCOMP); | 
| 93 | 62 | #endif | 
| 94 | 62 |   } | 
| 95 |  |  | 
| 96 | 124 |   if ((c = getc(infile)) == EOF) | 
| 97 | 0 |     ERREXIT(cinfo, JERR_INPUT_EMPTY); | 
| 98 | 124 |   if (ungetc(c, infile) == EOF) | 
| 99 | 0 |     ERREXIT(cinfo, JERR_UNGETC_FAILED); | 
| 100 |  |  | 
| 101 | 124 |   switch (c) { | 
| 102 |  | #ifdef BMP_SUPPORTED | 
| 103 |  |   case 'B': | 
| 104 |  |     return jinit_read_bmp(cinfo, TRUE); | 
| 105 |  | #endif | 
| 106 |  | #ifdef GIF_SUPPORTED | 
| 107 |  |   case 'G': | 
| 108 |  |     if (cinfo->data_precision == 16) { | 
| 109 |  | #ifdef C_LOSSLESS_SUPPORTED | 
| 110 |  |       return j16init_read_gif(cinfo); | 
| 111 |  | #else | 
| 112 |  |       ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); | 
| 113 |  |       break; | 
| 114 |  | #endif | 
| 115 |  |     } else if (cinfo->data_precision == 12) | 
| 116 |  |       return j12init_read_gif(cinfo); | 
| 117 |  |     else | 
| 118 |  |       return jinit_read_gif(cinfo); | 
| 119 |  | #endif | 
| 120 |  | #ifdef PPM_SUPPORTED | 
| 121 |  |   case 'P': | 
| 122 |  |     if (cinfo->data_precision == 16) { | 
| 123 |  | #ifdef C_LOSSLESS_SUPPORTED | 
| 124 |  |       return j16init_read_ppm(cinfo); | 
| 125 |  | #else | 
| 126 |  |       ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); | 
| 127 |  |       break; | 
| 128 |  | #endif | 
| 129 |  |     } else if (cinfo->data_precision == 12) | 
| 130 |  |       return j12init_read_ppm(cinfo); | 
| 131 |  |     else | 
| 132 |  |       return jinit_read_ppm(cinfo); | 
| 133 |  | #endif | 
| 134 |  | #ifdef TARGA_SUPPORTED | 
| 135 |  |   case 0x00: | 
| 136 |  |     return jinit_read_targa(cinfo); | 
| 137 |  | #endif | 
| 138 | 62 |   default: | 
| 139 | 62 |     ERREXIT(cinfo, JERR_UNKNOWN_FORMAT); | 
| 140 | 62 |     break; | 
| 141 | 124 |   } | 
| 142 |  |  | 
| 143 | 0 |   return NULL;                  /* suppress compiler warnings */ | 
| 144 | 124 | } | 
| 145 |  |  | 
| 146 |  |  | 
| 147 |  | /* | 
| 148 |  |  * Argument-parsing code. | 
| 149 |  |  * The switch parser is designed to be useful with DOS-style command line | 
| 150 |  |  * syntax, ie, intermixed switches and file names, where only the switches | 
| 151 |  |  * to the left of a given file name affect processing of that file. | 
| 152 |  |  * The main program in this file doesn't actually use this capability... | 
| 153 |  |  */ | 
| 154 |  |  | 
| 155 |  |  | 
| 156 |  | static const char *progname;    /* program name for error messages */ | 
| 157 |  | static char *icc_filename;      /* for -icc switch */ | 
| 158 |  | static char *outfilename;       /* for -outfile switch */ | 
| 159 |  | boolean memdst;                 /* for -memdst switch */ | 
| 160 |  | boolean report;                 /* for -report switch */ | 
| 161 |  | boolean strict;                 /* for -strict switch */ | 
| 162 |  |  | 
| 163 |  |  | 
| 164 |  | #ifdef CJPEG_FUZZER | 
| 165 |  |  | 
| 166 |  | #include <setjmp.h> | 
| 167 |  |  | 
| 168 |  | struct my_error_mgr { | 
| 169 |  |   struct jpeg_error_mgr pub; | 
| 170 |  |   jmp_buf setjmp_buffer; | 
| 171 |  | }; | 
| 172 |  |  | 
| 173 |  | void my_error_exit(j_common_ptr cinfo) | 
| 174 | 124 | { | 
| 175 | 124 |   struct my_error_mgr *myerr = (struct my_error_mgr *)cinfo->err; | 
| 176 |  |  | 
| 177 | 124 |   longjmp(myerr->setjmp_buffer, 1); | 
| 178 | 124 | } | 
| 179 |  |  | 
| 180 |  | static void my_emit_message_fuzzer(j_common_ptr cinfo, int msg_level) | 
| 181 | 0 | { | 
| 182 | 0 |   if (msg_level < 0) | 
| 183 | 0 |     cinfo->err->num_warnings++; | 
| 184 | 0 | } | 
| 185 |  |  | 
| 186 | 124 | #define HANDLE_ERROR() { \ | 
| 187 | 124 |   if (cinfo.global_state > CSTATE_START) { \ | 
| 188 | 0 |     if (memdst && outbuffer) \ | 
| 189 | 0 |       (*cinfo.dest->term_destination) (&cinfo); \ | 
| 190 | 0 |     jpeg_abort_compress(&cinfo); \ | 
| 191 | 0 |   } \ | 
| 192 | 124 |   jpeg_destroy_compress(&cinfo); \ | 
| 193 | 124 |   if (input_file != stdin && input_file != NULL) \ | 
| 194 | 124 |     fclose(input_file); \ | 
| 195 | 124 |   if (memdst) \ | 
| 196 | 124 |     free(outbuffer); \ | 
| 197 | 124 |   return EXIT_FAILURE; \ | 
| 198 | 124 | } | 
| 199 |  |  | 
| 200 |  | #endif | 
| 201 |  |  | 
| 202 |  |  | 
| 203 |  | LOCAL(void) | 
| 204 |  | usage(void) | 
| 205 |  | /* complain about bad command line */ | 
| 206 | 0 | { | 
| 207 | 0 |   fprintf(stderr, "usage: %s [switches] ", progname); | 
| 208 |  | #ifdef TWO_FILE_COMMANDLINE | 
| 209 |  |   fprintf(stderr, "inputfile outputfile\n"); | 
| 210 |  | #else | 
| 211 | 0 |   fprintf(stderr, "[inputfile]\n"); | 
| 212 | 0 | #endif | 
| 213 |  | 
 | 
| 214 | 0 |   fprintf(stderr, "Switches (names may be abbreviated):\n"); | 
| 215 | 0 |   fprintf(stderr, "  -quality N[,...]   Compression quality (0..100; 5-95 is most useful range,\n"); | 
| 216 | 0 |   fprintf(stderr, "                     default is 75)\n"); | 
| 217 | 0 |   fprintf(stderr, "  -grayscale     Create monochrome JPEG file\n"); | 
| 218 | 0 |   fprintf(stderr, "  -rgb           Create RGB JPEG file\n"); | 
| 219 | 0 | #ifdef ENTROPY_OPT_SUPPORTED | 
| 220 | 0 |   fprintf(stderr, "  -optimize      Optimize Huffman table (smaller file, but slow compression)\n"); | 
| 221 | 0 | #endif | 
| 222 | 0 | #ifdef C_PROGRESSIVE_SUPPORTED | 
| 223 | 0 |   fprintf(stderr, "  -progressive   Create progressive JPEG file\n"); | 
| 224 | 0 | #endif | 
| 225 |  | #ifdef TARGA_SUPPORTED | 
| 226 |  |   fprintf(stderr, "  -targa         Input file is Targa format (usually not needed)\n"); | 
| 227 |  | #endif | 
| 228 | 0 |   fprintf(stderr, "Switches for advanced users:\n"); | 
| 229 | 0 |   fprintf(stderr, "  -precision N   Create JPEG file with N-bit data precision\n"); | 
| 230 | 0 | #ifdef C_LOSSLESS_SUPPORTED | 
| 231 | 0 |   fprintf(stderr, "                 (N is 8, 12, or 16; default is 8; if N is 16, then -lossless\n"); | 
| 232 | 0 |   fprintf(stderr, "                 must also be specified)\n"); | 
| 233 |  | #else | 
| 234 |  |   fprintf(stderr, "                 (N is 8 or 12; default is 8)\n"); | 
| 235 |  | #endif | 
| 236 | 0 | #ifdef C_LOSSLESS_SUPPORTED | 
| 237 | 0 |   fprintf(stderr, "  -lossless psv[,Pt]  Create lossless JPEG file\n"); | 
| 238 | 0 | #endif | 
| 239 | 0 | #ifdef C_ARITH_CODING_SUPPORTED | 
| 240 | 0 |   fprintf(stderr, "  -arithmetic    Use arithmetic coding\n"); | 
| 241 | 0 | #endif | 
| 242 | 0 | #ifdef DCT_ISLOW_SUPPORTED | 
| 243 | 0 |   fprintf(stderr, "  -dct int       Use accurate integer DCT method%s\n", | 
| 244 | 0 |           (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : "")); | 
| 245 | 0 | #endif | 
| 246 | 0 | #ifdef DCT_IFAST_SUPPORTED | 
| 247 | 0 |   fprintf(stderr, "  -dct fast      Use less accurate integer DCT method [legacy feature]%s\n", | 
| 248 | 0 |           (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : "")); | 
| 249 | 0 | #endif | 
| 250 | 0 | #ifdef DCT_FLOAT_SUPPORTED | 
| 251 | 0 |   fprintf(stderr, "  -dct float     Use floating-point DCT method [legacy feature]%s\n", | 
| 252 | 0 |           (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : "")); | 
| 253 | 0 | #endif | 
| 254 | 0 |   fprintf(stderr, "  -icc FILE      Embed ICC profile contained in FILE\n"); | 
| 255 | 0 |   fprintf(stderr, "  -restart N     Set restart interval in rows, or in blocks with B\n"); | 
| 256 | 0 | #ifdef INPUT_SMOOTHING_SUPPORTED | 
| 257 | 0 |   fprintf(stderr, "  -smooth N      Smooth dithered input (N=1..100 is strength)\n"); | 
| 258 | 0 | #endif | 
| 259 | 0 |   fprintf(stderr, "  -maxmemory N   Maximum memory to use (in kbytes)\n"); | 
| 260 | 0 |   fprintf(stderr, "  -outfile name  Specify name for output file\n"); | 
| 261 | 0 |   fprintf(stderr, "  -memdst        Compress to memory instead of file (useful for benchmarking)\n"); | 
| 262 | 0 |   fprintf(stderr, "  -report        Report compression progress\n"); | 
| 263 | 0 |   fprintf(stderr, "  -strict        Treat all warnings as fatal\n"); | 
| 264 | 0 |   fprintf(stderr, "  -verbose  or  -debug   Emit debug output\n"); | 
| 265 | 0 |   fprintf(stderr, "  -version       Print version information and exit\n"); | 
| 266 | 0 |   fprintf(stderr, "Switches for wizards:\n"); | 
| 267 | 0 |   fprintf(stderr, "  -baseline      Force baseline quantization tables\n"); | 
| 268 | 0 |   fprintf(stderr, "  -qtables FILE  Use quantization tables given in FILE\n"); | 
| 269 | 0 |   fprintf(stderr, "  -qslots N[,...]    Set component quantization tables\n"); | 
| 270 | 0 |   fprintf(stderr, "  -sample HxV[,...]  Set component sampling factors\n"); | 
| 271 | 0 | #ifdef C_MULTISCAN_FILES_SUPPORTED | 
| 272 | 0 |   fprintf(stderr, "  -scans FILE    Create multi-scan JPEG per script FILE\n"); | 
| 273 | 0 | #endif | 
| 274 | 0 |   exit(EXIT_FAILURE); | 
| 275 | 0 | } | 
| 276 |  |  | 
| 277 |  |  | 
| 278 |  | LOCAL(int) | 
| 279 |  | parse_switches(j_compress_ptr cinfo, int argc, char **argv, | 
| 280 |  |                int last_file_arg_seen, boolean for_real) | 
| 281 |  | /* Parse optional switches. | 
| 282 |  |  * Returns argv[] index of first file-name argument (== argc if none). | 
| 283 |  |  * Any file names with indexes <= last_file_arg_seen are ignored; | 
| 284 |  |  * they have presumably been processed in a previous iteration. | 
| 285 |  |  * (Pass 0 for last_file_arg_seen on the first or only iteration.) | 
| 286 |  |  * for_real is FALSE on the first (dummy) pass; we may skip any expensive | 
| 287 |  |  * processing. | 
| 288 |  |  */ | 
| 289 | 124 | { | 
| 290 | 124 |   int argn; | 
| 291 | 124 |   char *arg; | 
| 292 | 124 | #ifdef C_LOSSLESS_SUPPORTED | 
| 293 | 124 |   int psv, pt = 0; | 
| 294 | 124 | #endif | 
| 295 | 124 |   boolean force_baseline; | 
| 296 | 124 |   boolean simple_progressive; | 
| 297 | 124 |   char *qualityarg = NULL;      /* saves -quality parm if any */ | 
| 298 | 124 |   char *qtablefile = NULL;      /* saves -qtables filename if any */ | 
| 299 | 124 |   char *qslotsarg = NULL;       /* saves -qslots parm if any */ | 
| 300 | 124 |   char *samplearg = NULL;       /* saves -sample parm if any */ | 
| 301 | 124 |   char *scansarg = NULL;        /* saves -scans parm if any */ | 
| 302 |  |  | 
| 303 |  |   /* Set up default JPEG parameters. */ | 
| 304 |  |  | 
| 305 | 124 |   force_baseline = FALSE;       /* by default, allow 16-bit quantizers */ | 
| 306 | 124 |   simple_progressive = FALSE; | 
| 307 | 124 |   is_targa = FALSE; | 
| 308 | 124 |   icc_filename = NULL; | 
| 309 | 124 |   outfilename = NULL; | 
| 310 | 124 |   memdst = FALSE; | 
| 311 | 124 |   report = FALSE; | 
| 312 | 124 |   strict = FALSE; | 
| 313 | 124 |   cinfo->err->trace_level = 0; | 
| 314 |  |  | 
| 315 |  |   /* Scan command line options, adjust parameters */ | 
| 316 |  |  | 
| 317 | 992 |   for (argn = 1; argn < argc; argn++) { | 
| 318 | 992 |     arg = argv[argn]; | 
| 319 | 992 |     if (*arg != '-') { | 
| 320 |  |       /* Not a switch, must be a file name argument */ | 
| 321 | 124 |       if (argn <= last_file_arg_seen) { | 
| 322 | 0 |         outfilename = NULL;     /* -outfile applies to just one input file */ | 
| 323 | 0 |         continue;               /* ignore this name if previously processed */ | 
| 324 | 0 |       } | 
| 325 | 124 |       break;                    /* else done parsing switches */ | 
| 326 | 124 |     } | 
| 327 | 868 |     arg++;                      /* advance past switch marker character */ | 
| 328 |  |  | 
| 329 | 868 |     if (keymatch(arg, "arithmetic", 1)) { | 
| 330 |  |       /* Use arithmetic coding. */ | 
| 331 | 62 | #ifdef C_ARITH_CODING_SUPPORTED | 
| 332 | 62 |       cinfo->arith_code = TRUE; | 
| 333 |  | #else | 
| 334 |  |       fprintf(stderr, "%s: sorry, arithmetic coding not supported\n", | 
| 335 |  |               progname); | 
| 336 |  |       exit(EXIT_FAILURE); | 
| 337 |  | #endif | 
| 338 |  |  | 
| 339 | 806 |     } else if (keymatch(arg, "baseline", 1)) { | 
| 340 |  |       /* Force baseline-compatible output (8-bit quantizer values). */ | 
| 341 | 0 |       force_baseline = TRUE; | 
| 342 |  | 
 | 
| 343 | 806 |     } else if (keymatch(arg, "dct", 2)) { | 
| 344 |  |       /* Select DCT algorithm. */ | 
| 345 | 124 |       if (++argn >= argc)       /* advance to next argument */ | 
| 346 | 0 |         usage(); | 
| 347 | 124 |       if (keymatch(argv[argn], "int", 1)) { | 
| 348 | 0 |         cinfo->dct_method = JDCT_ISLOW; | 
| 349 | 124 |       } else if (keymatch(argv[argn], "fast", 2)) { | 
| 350 | 0 |         cinfo->dct_method = JDCT_IFAST; | 
| 351 | 124 |       } else if (keymatch(argv[argn], "float", 2)) { | 
| 352 | 124 |         cinfo->dct_method = JDCT_FLOAT; | 
| 353 | 124 |       } else | 
| 354 | 0 |         usage(); | 
| 355 |  |  | 
| 356 | 682 |     } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) { | 
| 357 |  |       /* Enable debug printouts. */ | 
| 358 |  |       /* On first -d, print version identification */ | 
| 359 | 0 |       static boolean printed_version = FALSE; | 
| 360 |  | 
 | 
| 361 | 0 |       if (!printed_version) { | 
| 362 | 0 |         fprintf(stderr, "%s version %s (build %s)\n", | 
| 363 | 0 |                 PACKAGE_NAME, VERSION, BUILD); | 
| 364 | 0 |         fprintf(stderr, "%s\n\n", JCOPYRIGHT); | 
| 365 | 0 |         fprintf(stderr, "Emulating The Independent JPEG Group's software, version %s\n\n", | 
| 366 | 0 |                 JVERSION); | 
| 367 | 0 |         printed_version = TRUE; | 
| 368 | 0 |       } | 
| 369 | 0 |       cinfo->err->trace_level++; | 
| 370 |  | 
 | 
| 371 | 682 |     } else if (keymatch(arg, "version", 4)) { | 
| 372 | 0 |       fprintf(stderr, "%s version %s (build %s)\n", | 
| 373 | 0 |               PACKAGE_NAME, VERSION, BUILD); | 
| 374 | 0 |       exit(EXIT_SUCCESS); | 
| 375 |  | 
 | 
| 376 | 682 |     } else if (keymatch(arg, "grayscale", 2) || | 
| 377 | 682 |                keymatch(arg, "greyscale", 2)) { | 
| 378 |  |       /* Force a monochrome JPEG file to be generated. */ | 
| 379 | 0 |       jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); | 
| 380 |  | 
 | 
| 381 | 682 |     } else if (keymatch(arg, "rgb", 3)) { | 
| 382 |  |       /* Force an RGB JPEG file to be generated. */ | 
| 383 | 62 |       jpeg_set_colorspace(cinfo, JCS_RGB); | 
| 384 |  |  | 
| 385 | 620 |     } else if (keymatch(arg, "icc", 1)) { | 
| 386 |  |       /* Set ICC filename. */ | 
| 387 | 0 |       if (++argn >= argc)       /* advance to next argument */ | 
| 388 | 0 |         usage(); | 
| 389 | 0 |       icc_filename = argv[argn]; | 
| 390 |  | 
 | 
| 391 | 620 |     } else if (keymatch(arg, "lossless", 1)) { | 
| 392 |  |       /* Enable lossless mode. */ | 
| 393 | 0 | #ifdef C_LOSSLESS_SUPPORTED | 
| 394 | 0 |       char ch = ',', *ptr; | 
| 395 |  | 
 | 
| 396 | 0 |       if (++argn >= argc)       /* advance to next argument */ | 
| 397 | 0 |         usage(); | 
| 398 | 0 |       if (sscanf(argv[argn], "%d%c", &psv, &ch) < 1 || ch != ',') | 
| 399 | 0 |         usage(); | 
| 400 | 0 |       ptr = argv[argn]; | 
| 401 | 0 |       while (*ptr && *ptr++ != ','); /* advance to next segment of arg | 
| 402 |  |                                         string */ | 
| 403 | 0 |       if (*ptr) | 
| 404 | 0 |         sscanf(ptr, "%d", &pt); | 
| 405 | 0 |       jpeg_enable_lossless(cinfo, psv, pt); | 
| 406 |  | #else | 
| 407 |  |       fprintf(stderr, "%s: sorry, lossless output was not compiled\n", | 
| 408 |  |               progname); | 
| 409 |  |       exit(EXIT_FAILURE); | 
| 410 |  | #endif | 
| 411 |  | 
 | 
| 412 | 620 |     } else if (keymatch(arg, "maxmemory", 3)) { | 
| 413 |  |       /* Maximum memory in Kb (or Mb with 'm'). */ | 
| 414 | 0 |       long lval; | 
| 415 | 0 |       char ch = 'x'; | 
| 416 |  | 
 | 
| 417 | 0 |       if (++argn >= argc)       /* advance to next argument */ | 
| 418 | 0 |         usage(); | 
| 419 | 0 |       if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) | 
| 420 | 0 |         usage(); | 
| 421 | 0 |       if (ch == 'm' || ch == 'M') | 
| 422 | 0 |         lval *= 1000L; | 
| 423 | 0 |       cinfo->mem->max_memory_to_use = lval * 1000L; | 
| 424 |  | 
 | 
| 425 | 620 |     } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) { | 
| 426 |  |       /* Enable entropy parm optimization. */ | 
| 427 | 62 | #ifdef ENTROPY_OPT_SUPPORTED | 
| 428 | 62 |       cinfo->optimize_coding = TRUE; | 
| 429 |  | #else | 
| 430 |  |       fprintf(stderr, "%s: sorry, entropy optimization was not compiled in\n", | 
| 431 |  |               progname); | 
| 432 |  |       exit(EXIT_FAILURE); | 
| 433 |  | #endif | 
| 434 |  |  | 
| 435 | 558 |     } else if (keymatch(arg, "outfile", 4)) { | 
| 436 |  |       /* Set output file name. */ | 
| 437 | 0 |       if (++argn >= argc)       /* advance to next argument */ | 
| 438 | 0 |         usage(); | 
| 439 | 0 |       outfilename = argv[argn]; /* save it away for later use */ | 
| 440 |  | 
 | 
| 441 | 558 |     } else if (keymatch(arg, "precision", 3)) { | 
| 442 |  |       /* Set data precision. */ | 
| 443 | 0 |       int val; | 
| 444 |  | 
 | 
| 445 | 0 |       if (++argn >= argc)       /* advance to next argument */ | 
| 446 | 0 |         usage(); | 
| 447 | 0 |       if (sscanf(argv[argn], "%d", &val) != 1) | 
| 448 | 0 |         usage(); | 
| 449 | 0 | #ifdef C_LOSSLESS_SUPPORTED | 
| 450 | 0 |       if (val != 8 && val != 12 && val != 16) | 
| 451 |  | #else | 
| 452 |  |       if (val != 8 && val != 12) | 
| 453 |  | #endif | 
| 454 | 0 |         usage(); | 
| 455 | 0 |       cinfo->data_precision = val; | 
| 456 |  | 
 | 
| 457 | 558 |     } else if (keymatch(arg, "progressive", 3)) { | 
| 458 |  |       /* Select simple progressive mode. */ | 
| 459 | 0 | #ifdef C_PROGRESSIVE_SUPPORTED | 
| 460 | 0 |       simple_progressive = TRUE; | 
| 461 |  |       /* We must postpone execution until num_components is known. */ | 
| 462 |  | #else | 
| 463 |  |       fprintf(stderr, "%s: sorry, progressive output was not compiled in\n", | 
| 464 |  |               progname); | 
| 465 |  |       exit(EXIT_FAILURE); | 
| 466 |  | #endif | 
| 467 |  | 
 | 
| 468 | 558 |     } else if (keymatch(arg, "memdst", 2)) { | 
| 469 |  |       /* Use in-memory destination manager */ | 
| 470 | 124 |       memdst = TRUE; | 
| 471 |  |  | 
| 472 | 434 |     } else if (keymatch(arg, "quality", 1)) { | 
| 473 |  |       /* Quality ratings (quantization table scaling factors). */ | 
| 474 | 124 |       if (++argn >= argc)       /* advance to next argument */ | 
| 475 | 0 |         usage(); | 
| 476 | 124 |       qualityarg = argv[argn]; | 
| 477 |  |  | 
| 478 | 310 |     } else if (keymatch(arg, "qslots", 2)) { | 
| 479 |  |       /* Quantization table slot numbers. */ | 
| 480 | 0 |       if (++argn >= argc)       /* advance to next argument */ | 
| 481 | 0 |         usage(); | 
| 482 | 0 |       qslotsarg = argv[argn]; | 
| 483 |  |       /* Must delay setting qslots until after we have processed any | 
| 484 |  |        * colorspace-determining switches, since jpeg_set_colorspace sets | 
| 485 |  |        * default quant table numbers. | 
| 486 |  |        */ | 
| 487 |  | 
 | 
| 488 | 310 |     } else if (keymatch(arg, "qtables", 2)) { | 
| 489 |  |       /* Quantization tables fetched from file. */ | 
| 490 | 0 |       if (++argn >= argc)       /* advance to next argument */ | 
| 491 | 0 |         usage(); | 
| 492 | 0 |       qtablefile = argv[argn]; | 
| 493 |  |       /* We postpone actually reading the file in case -quality comes later. */ | 
| 494 |  | 
 | 
| 495 | 310 |     } else if (keymatch(arg, "report", 3)) { | 
| 496 | 0 |       report = TRUE; | 
| 497 |  | 
 | 
| 498 | 310 |     } else if (keymatch(arg, "restart", 1)) { | 
| 499 |  |       /* Restart interval in MCU rows (or in MCUs with 'b'). */ | 
| 500 | 62 |       long lval; | 
| 501 | 62 |       char ch = 'x'; | 
| 502 |  |  | 
| 503 | 62 |       if (++argn >= argc)       /* advance to next argument */ | 
| 504 | 0 |         usage(); | 
| 505 | 62 |       if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) | 
| 506 | 0 |         usage(); | 
| 507 | 62 |       if (lval < 0 || lval > 65535L) | 
| 508 | 0 |         usage(); | 
| 509 | 62 |       if (ch == 'b' || ch == 'B') { | 
| 510 | 0 |         cinfo->restart_interval = (unsigned int)lval; | 
| 511 | 0 |         cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */ | 
| 512 | 62 |       } else { | 
| 513 | 62 |         cinfo->restart_in_rows = (int)lval; | 
| 514 |  |         /* restart_interval will be computed during startup */ | 
| 515 | 62 |       } | 
| 516 |  |  | 
| 517 | 248 |     } else if (keymatch(arg, "sample", 2)) { | 
| 518 |  |       /* Set sampling factors. */ | 
| 519 | 124 |       if (++argn >= argc)       /* advance to next argument */ | 
| 520 | 0 |         usage(); | 
| 521 | 124 |       samplearg = argv[argn]; | 
| 522 |  |       /* Must delay setting sample factors until after we have processed any | 
| 523 |  |        * colorspace-determining switches, since jpeg_set_colorspace sets | 
| 524 |  |        * default sampling factors. | 
| 525 |  |        */ | 
| 526 |  |  | 
| 527 | 124 |     } else if (keymatch(arg, "scans", 4)) { | 
| 528 |  |       /* Set scan script. */ | 
| 529 | 0 | #ifdef C_MULTISCAN_FILES_SUPPORTED | 
| 530 | 0 |       if (++argn >= argc)       /* advance to next argument */ | 
| 531 | 0 |         usage(); | 
| 532 | 0 |       scansarg = argv[argn]; | 
| 533 |  |       /* We must postpone reading the file in case -progressive appears. */ | 
| 534 |  | #else | 
| 535 |  |       fprintf(stderr, "%s: sorry, multi-scan output was not compiled in\n", | 
| 536 |  |               progname); | 
| 537 |  |       exit(EXIT_FAILURE); | 
| 538 |  | #endif | 
| 539 |  | 
 | 
| 540 | 124 |     } else if (keymatch(arg, "smooth", 2)) { | 
| 541 |  |       /* Set input smoothing factor. */ | 
| 542 | 62 |       int val; | 
| 543 |  |  | 
| 544 | 62 |       if (++argn >= argc)       /* advance to next argument */ | 
| 545 | 0 |         usage(); | 
| 546 | 62 |       if (sscanf(argv[argn], "%d", &val) != 1) | 
| 547 | 0 |         usage(); | 
| 548 | 62 |       if (val < 0 || val > 100) | 
| 549 | 0 |         usage(); | 
| 550 | 62 |       cinfo->smoothing_factor = val; | 
| 551 |  |  | 
| 552 | 62 |     } else if (keymatch(arg, "strict", 2)) { | 
| 553 | 0 |       strict = TRUE; | 
| 554 |  | 
 | 
| 555 | 62 |     } else if (keymatch(arg, "targa", 1)) { | 
| 556 |  |       /* Input file is Targa format. */ | 
| 557 | 62 |       is_targa = TRUE; | 
| 558 |  |  | 
| 559 | 62 |     } else { | 
| 560 | 0 |       usage();                  /* bogus switch */ | 
| 561 | 0 |     } | 
| 562 | 868 |   } | 
| 563 |  |  | 
| 564 |  |   /* Post-switch-scanning cleanup */ | 
| 565 |  |  | 
| 566 | 124 |   if (for_real) { | 
| 567 |  |  | 
| 568 |  |     /* Set quantization tables for selected quality. */ | 
| 569 |  |     /* Some or all may be overridden if -qtables is present. */ | 
| 570 | 0 |     if (qualityarg != NULL)     /* process -quality if it was present */ | 
| 571 | 0 |       if (!set_quality_ratings(cinfo, qualityarg, force_baseline)) | 
| 572 | 0 |         usage(); | 
| 573 |  | 
 | 
| 574 | 0 |     if (qtablefile != NULL)     /* process -qtables if it was present */ | 
| 575 | 0 |       if (!read_quant_tables(cinfo, qtablefile, force_baseline)) | 
| 576 | 0 |         usage(); | 
| 577 |  | 
 | 
| 578 | 0 |     if (qslotsarg != NULL)      /* process -qslots if it was present */ | 
| 579 | 0 |       if (!set_quant_slots(cinfo, qslotsarg)) | 
| 580 | 0 |         usage(); | 
| 581 |  | 
 | 
| 582 | 0 |     if (samplearg != NULL)      /* process -sample if it was present */ | 
| 583 | 0 |       if (!set_sample_factors(cinfo, samplearg)) | 
| 584 | 0 |         usage(); | 
| 585 |  | 
 | 
| 586 | 0 | #ifdef C_PROGRESSIVE_SUPPORTED | 
| 587 | 0 |     if (simple_progressive)     /* process -progressive; -scans can override */ | 
| 588 | 0 |       jpeg_simple_progression(cinfo); | 
| 589 | 0 | #endif | 
| 590 |  | 
 | 
| 591 | 0 | #ifdef C_MULTISCAN_FILES_SUPPORTED | 
| 592 | 0 |     if (scansarg != NULL)       /* process -scans if it was present */ | 
| 593 | 0 |       if (!read_scan_script(cinfo, scansarg)) | 
| 594 | 0 |         usage(); | 
| 595 | 0 | #endif | 
| 596 | 0 |   } | 
| 597 |  |  | 
| 598 | 124 |   return argn;                  /* return index of next arg (file name) */ | 
| 599 | 124 | } | 
| 600 |  |  | 
| 601 |  |  | 
| 602 |  | METHODDEF(void) | 
| 603 |  | my_emit_message(j_common_ptr cinfo, int msg_level) | 
| 604 | 0 | { | 
| 605 | 0 |   if (msg_level < 0) { | 
| 606 |  |     /* Treat warning as fatal */ | 
| 607 | 0 |     cinfo->err->error_exit(cinfo); | 
| 608 | 0 |   } else { | 
| 609 | 0 |     if (cinfo->err->trace_level >= msg_level) | 
| 610 | 0 |       cinfo->err->output_message(cinfo); | 
| 611 | 0 |   } | 
| 612 | 0 | } | 
| 613 |  |  | 
| 614 |  |  | 
| 615 |  | /* | 
| 616 |  |  * The main program. | 
| 617 |  |  */ | 
| 618 |  |  | 
| 619 |  | int | 
| 620 |  | main(int argc, char **argv) | 
| 621 | 124 | { | 
| 622 | 124 |   struct jpeg_compress_struct cinfo; | 
| 623 | 124 | #ifdef CJPEG_FUZZER | 
| 624 | 124 |   struct my_error_mgr myerr; | 
| 625 | 124 |   struct jpeg_error_mgr &jerr = myerr.pub; | 
| 626 |  | #else | 
| 627 |  |   struct jpeg_error_mgr jerr; | 
| 628 |  | #endif | 
| 629 | 124 |   struct cdjpeg_progress_mgr progress; | 
| 630 | 124 |   int file_index; | 
| 631 | 124 |   cjpeg_source_ptr src_mgr; | 
| 632 | 124 |   FILE *input_file = NULL; | 
| 633 | 124 |   FILE *icc_file; | 
| 634 | 124 |   JOCTET *icc_profile = NULL; | 
| 635 | 124 |   long icc_len = 0; | 
| 636 | 124 |   FILE *output_file = NULL; | 
| 637 | 124 |   unsigned char *outbuffer = NULL; | 
| 638 | 124 |   unsigned long outsize = 0; | 
| 639 | 124 |   JDIMENSION num_scanlines; | 
| 640 |  |  | 
| 641 | 124 |   progname = argv[0]; | 
| 642 | 124 |   if (progname == NULL || progname[0] == 0) | 
| 643 | 0 |     progname = "cjpeg";         /* in case C library doesn't provide it */ | 
| 644 |  |  | 
| 645 |  |   /* Initialize the JPEG compression object with default error handling. */ | 
| 646 | 124 |   cinfo.err = jpeg_std_error(&jerr); | 
| 647 | 124 |   jpeg_create_compress(&cinfo); | 
| 648 |  |   /* Add some application-specific error messages (from cderror.h) */ | 
| 649 | 124 |   jerr.addon_message_table = cdjpeg_message_table; | 
| 650 | 124 |   jerr.first_addon_message = JMSG_FIRSTADDONCODE; | 
| 651 | 124 |   jerr.last_addon_message = JMSG_LASTADDONCODE; | 
| 652 |  |  | 
| 653 |  |   /* Initialize JPEG parameters. | 
| 654 |  |    * Much of this may be overridden later. | 
| 655 |  |    * In particular, we don't yet know the input file's color space, | 
| 656 |  |    * but we need to provide some value for jpeg_set_defaults() to work. | 
| 657 |  |    */ | 
| 658 |  |  | 
| 659 | 124 |   cinfo.in_color_space = JCS_RGB; /* arbitrary guess */ | 
| 660 | 124 |   jpeg_set_defaults(&cinfo); | 
| 661 |  |  | 
| 662 |  |   /* Scan command line to find file names. | 
| 663 |  |    * It is convenient to use just one switch-parsing routine, but the switch | 
| 664 |  |    * values read here are ignored; we will rescan the switches after opening | 
| 665 |  |    * the input file. | 
| 666 |  |    */ | 
| 667 |  |  | 
| 668 | 124 |   file_index = parse_switches(&cinfo, argc, argv, 0, FALSE); | 
| 669 |  |  | 
| 670 | 124 |   if (strict) | 
| 671 | 0 |     jerr.emit_message = my_emit_message; | 
| 672 |  |  | 
| 673 |  | #ifdef TWO_FILE_COMMANDLINE | 
| 674 |  |   if (!memdst) { | 
| 675 |  |     /* Must have either -outfile switch or explicit output file name */ | 
| 676 |  |     if (outfilename == NULL) { | 
| 677 |  |       if (file_index != argc - 2) { | 
| 678 |  |         fprintf(stderr, "%s: must name one input and one output file\n", | 
| 679 |  |                 progname); | 
| 680 |  |         usage(); | 
| 681 |  |       } | 
| 682 |  |       outfilename = argv[file_index + 1]; | 
| 683 |  |     } else { | 
| 684 |  |       if (file_index != argc - 1) { | 
| 685 |  |         fprintf(stderr, "%s: must name one input and one output file\n", | 
| 686 |  |                 progname); | 
| 687 |  |         usage(); | 
| 688 |  |       } | 
| 689 |  |     } | 
| 690 |  |   } | 
| 691 |  | #else | 
| 692 |  |   /* Unix style: expect zero or one file name */ | 
| 693 | 124 |   if (file_index < argc - 1) { | 
| 694 | 0 |     fprintf(stderr, "%s: only one input file\n", progname); | 
| 695 | 0 |     usage(); | 
| 696 | 0 |   } | 
| 697 | 124 | #endif /* TWO_FILE_COMMANDLINE */ | 
| 698 |  |  | 
| 699 |  |   /* Open the input file. */ | 
| 700 | 124 |   if (file_index < argc) { | 
| 701 | 124 |     if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) { | 
| 702 | 0 |       fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]); | 
| 703 | 0 |       exit(EXIT_FAILURE); | 
| 704 | 0 |     } | 
| 705 | 124 |   } else { | 
| 706 |  |     /* default input file is stdin */ | 
| 707 | 0 |     input_file = read_stdin(); | 
| 708 | 0 |   } | 
| 709 |  |  | 
| 710 |  |   /* Open the output file. */ | 
| 711 | 124 |   if (outfilename != NULL) { | 
| 712 | 0 |     if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) { | 
| 713 | 0 |       fprintf(stderr, "%s: can't open %s\n", progname, outfilename); | 
| 714 | 0 |       exit(EXIT_FAILURE); | 
| 715 | 0 |     } | 
| 716 | 124 |   } else if (!memdst) { | 
| 717 |  |     /* default output file is stdout */ | 
| 718 | 0 |     output_file = write_stdout(); | 
| 719 | 0 |   } | 
| 720 |  |  | 
| 721 | 124 |   if (icc_filename != NULL) { | 
| 722 | 0 |     if ((icc_file = fopen(icc_filename, READ_BINARY)) == NULL) { | 
| 723 | 0 |       fprintf(stderr, "%s: can't open %s\n", progname, icc_filename); | 
| 724 | 0 |       exit(EXIT_FAILURE); | 
| 725 | 0 |     } | 
| 726 | 0 |     if (fseek(icc_file, 0, SEEK_END) < 0 || | 
| 727 | 0 |         (icc_len = ftell(icc_file)) < 1 || | 
| 728 | 0 |         fseek(icc_file, 0, SEEK_SET) < 0) { | 
| 729 | 0 |       fprintf(stderr, "%s: can't determine size of %s\n", progname, | 
| 730 | 0 |               icc_filename); | 
| 731 | 0 |       exit(EXIT_FAILURE); | 
| 732 | 0 |     } | 
| 733 | 0 |     if ((icc_profile = (JOCTET *)malloc(icc_len)) == NULL) { | 
| 734 | 0 |       fprintf(stderr, "%s: can't allocate memory for ICC profile\n", progname); | 
| 735 | 0 |       fclose(icc_file); | 
| 736 | 0 |       exit(EXIT_FAILURE); | 
| 737 | 0 |     } | 
| 738 | 0 |     if (fread(icc_profile, icc_len, 1, icc_file) < 1) { | 
| 739 | 0 |       fprintf(stderr, "%s: can't read ICC profile from %s\n", progname, | 
| 740 | 0 |               icc_filename); | 
| 741 | 0 |       free(icc_profile); | 
| 742 | 0 |       fclose(icc_file); | 
| 743 | 0 |       exit(EXIT_FAILURE); | 
| 744 | 0 |     } | 
| 745 | 0 |     fclose(icc_file); | 
| 746 | 0 |   } | 
| 747 |  |  | 
| 748 | 124 | #ifdef CJPEG_FUZZER | 
| 749 | 124 |   jerr.error_exit = my_error_exit; | 
| 750 | 124 |   jerr.emit_message = my_emit_message_fuzzer; | 
| 751 | 124 |   if (setjmp(myerr.setjmp_buffer)) | 
| 752 | 124 |     HANDLE_ERROR() | 
| 753 | 0 | #endif | 
| 754 |  |  | 
| 755 | 0 |   if (report) { | 
| 756 | 0 |     start_progress_monitor((j_common_ptr)&cinfo, &progress); | 
| 757 | 0 |     progress.report = report; | 
| 758 | 0 |   } | 
| 759 |  |  | 
| 760 |  |   /* Figure out the input file format, and set up to read it. */ | 
| 761 | 0 |   src_mgr = select_file_type(&cinfo, input_file); | 
| 762 | 0 |   src_mgr->input_file = input_file; | 
| 763 | 0 | #ifdef CJPEG_FUZZER | 
| 764 | 0 |   src_mgr->max_pixels = 1048576; | 
| 765 | 0 | #endif | 
| 766 |  |  | 
| 767 |  |   /* Read the input file header to obtain file size & colorspace. */ | 
| 768 | 0 |   (*src_mgr->start_input) (&cinfo, src_mgr); | 
| 769 |  |  | 
| 770 |  |   /* Now that we know input colorspace, fix colorspace-dependent defaults */ | 
| 771 | 0 |   jpeg_default_colorspace(&cinfo); | 
| 772 |  |  | 
| 773 |  |   /* Adjust default compression parameters by re-parsing the options */ | 
| 774 | 0 |   file_index = parse_switches(&cinfo, argc, argv, 0, TRUE); | 
| 775 |  |  | 
| 776 |  |   /* Specify data destination for compression */ | 
| 777 | 0 |   if (memdst) | 
| 778 | 0 |     jpeg_mem_dest(&cinfo, &outbuffer, &outsize); | 
| 779 | 0 |   else | 
| 780 | 0 |     jpeg_stdio_dest(&cinfo, output_file); | 
| 781 |  | 
 | 
| 782 | 0 | #ifdef CJPEG_FUZZER | 
| 783 | 0 |   if (setjmp(myerr.setjmp_buffer)) | 
| 784 | 0 |     HANDLE_ERROR() | 
| 785 | 0 | #endif | 
| 786 |  |  | 
| 787 |  |   /* Start compressor */ | 
| 788 | 0 |   jpeg_start_compress(&cinfo, TRUE); | 
| 789 |  | 
 | 
| 790 | 0 |   if (icc_profile != NULL) | 
| 791 | 0 |     jpeg_write_icc_profile(&cinfo, icc_profile, (unsigned int)icc_len); | 
| 792 |  |  | 
| 793 |  |   /* Process data */ | 
| 794 | 0 |   if (cinfo.data_precision == 16) { | 
| 795 | 0 | #ifdef C_LOSSLESS_SUPPORTED | 
| 796 | 0 |     while (cinfo.next_scanline < cinfo.image_height) { | 
| 797 | 0 |       num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr); | 
| 798 | 0 |       (void)jpeg16_write_scanlines(&cinfo, src_mgr->buffer16, num_scanlines); | 
| 799 | 0 |     } | 
| 800 |  | #else | 
| 801 |  |     ERREXIT1(&cinfo, JERR_BAD_PRECISION, cinfo.data_precision); | 
| 802 |  | #endif | 
| 803 | 0 |   } else if (cinfo.data_precision == 12) { | 
| 804 | 0 |     while (cinfo.next_scanline < cinfo.image_height) { | 
| 805 | 0 |       num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr); | 
| 806 | 0 |       (void)jpeg12_write_scanlines(&cinfo, src_mgr->buffer12, num_scanlines); | 
| 807 | 0 |     } | 
| 808 | 0 |   } else { | 
| 809 | 0 |     while (cinfo.next_scanline < cinfo.image_height) { | 
| 810 | 0 |       num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr); | 
| 811 | 0 |       (void)jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines); | 
| 812 | 0 |     } | 
| 813 | 0 |   } | 
| 814 |  |  | 
| 815 |  |   /* Finish compression and release memory */ | 
| 816 | 0 |   (*src_mgr->finish_input) (&cinfo, src_mgr); | 
| 817 | 0 |   jpeg_finish_compress(&cinfo); | 
| 818 | 0 |   jpeg_destroy_compress(&cinfo); | 
| 819 |  |  | 
| 820 |  |   /* Close files, if we opened them */ | 
| 821 | 0 |   if (input_file != stdin) | 
| 822 | 0 |     fclose(input_file); | 
| 823 | 0 |   if (output_file != stdout && output_file != NULL) | 
| 824 | 0 |     fclose(output_file); | 
| 825 |  | 
 | 
| 826 | 0 |   if (report) | 
| 827 | 0 |     end_progress_monitor((j_common_ptr)&cinfo); | 
| 828 |  | 
 | 
| 829 | 0 |   if (memdst) { | 
| 830 |  | #ifndef CJPEG_FUZZER | 
| 831 |  |     fprintf(stderr, "Compressed size:  %lu bytes\n", outsize); | 
| 832 |  | #endif | 
| 833 | 0 |     free(outbuffer); | 
| 834 | 0 |   } | 
| 835 |  | 
 | 
| 836 | 0 |   free(icc_profile); | 
| 837 |  |  | 
| 838 |  |   /* All done. */ | 
| 839 | 0 |   return (jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS); | 
| 840 | 0 | } |