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
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.
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.
33 #define _CRT_SECURE_NO_DEPRECATE
37 #define JPEG_INTERNALS
39 #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
40 #include "jversion.h" /* for version message */
41 #include "jconfigint.h"
44 /* Create the add-on message string table. */
46 #define JMESSAGE(code, string) string,
48 static const char * const cdjpeg_message_table[] = {
55 * This routine determines what format the input file is,
56 * and selects the appropriate input-reading module.
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
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.
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.
80 static boolean is_targa; /* records user -targa switch */
83 LOCAL(cjpeg_source_ptr)
84 select_file_type(j_compress_ptr cinfo, FILE *infile)
89 #ifdef TARGA_SUPPORTED
90 return jinit_read_targa(cinfo);
92 ERREXIT(cinfo, JERR_TGA_NOTCOMP);
96 if ((c = getc(infile)) == EOF)
97 ERREXIT(cinfo, JERR_INPUT_EMPTY);
98 if (ungetc(c, infile) == EOF)
99 ERREXIT(cinfo, JERR_UNGETC_FAILED);
104 return jinit_read_bmp(cinfo, TRUE);
108 if (cinfo->data_precision == 16) {
109 #ifdef C_LOSSLESS_SUPPORTED
110 return j16init_read_gif(cinfo);
112 ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
115 } else if (cinfo->data_precision == 12)
116 return j12init_read_gif(cinfo);
118 return jinit_read_gif(cinfo);
122 if (cinfo->data_precision == 16) {
123 #ifdef C_LOSSLESS_SUPPORTED
124 return j16init_read_ppm(cinfo);
126 ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
129 } else if (cinfo->data_precision == 12)
130 return j12init_read_ppm(cinfo);
132 return jinit_read_ppm(cinfo);
134 #ifdef TARGA_SUPPORTED
136 return jinit_read_targa(cinfo);
139 ERREXIT(cinfo, JERR_UNKNOWN_FORMAT);
143 return NULL; /* suppress compiler warnings */
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...
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 */
168 struct my_error_mgr {
169 struct jpeg_error_mgr pub;
170 jmp_buf setjmp_buffer;
173 void my_error_exit(j_common_ptr cinfo)
175 struct my_error_mgr *myerr = (struct my_error_mgr *)cinfo->err;
177 longjmp(myerr->setjmp_buffer, 1);
180 static void my_emit_message_fuzzer(j_common_ptr cinfo, int msg_level)
183 cinfo->err->num_warnings++;
186 #define HANDLE_ERROR() { \
187 if (cinfo.global_state > CSTATE_START) { \
188 if (memdst && outbuffer) \
189 (*cinfo.dest->term_destination) (&cinfo); \
190 jpeg_abort_compress(&cinfo); \
192 jpeg_destroy_compress(&cinfo); \
193 if (input_file != stdin && input_file != NULL) \
194 fclose(input_file); \
197 return EXIT_FAILURE; \
205 /* complain about bad command line */
207 fprintf(stderr, "usage: %s [switches] ", progname);
208 #ifdef TWO_FILE_COMMANDLINE
209 fprintf(stderr, "inputfile outputfile\n");
211 fprintf(stderr, "[inputfile]\n");
214 fprintf(stderr, "Switches (names may be abbreviated):\n");
215 fprintf(stderr, " -quality N[,...] Compression quality (0..100; 5-95 is most useful range,\n");
216 fprintf(stderr, " default is 75)\n");
217 fprintf(stderr, " -grayscale Create monochrome JPEG file\n");
218 fprintf(stderr, " -rgb Create RGB JPEG file\n");
219 #ifdef ENTROPY_OPT_SUPPORTED
220 fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n");
222 #ifdef C_PROGRESSIVE_SUPPORTED
223 fprintf(stderr, " -progressive Create progressive JPEG file\n");
225 #ifdef TARGA_SUPPORTED
226 fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n");
228 fprintf(stderr, "Switches for advanced users:\n");
229 fprintf(stderr, " -precision N Create JPEG file with N-bit data precision\n");
230 #ifdef C_LOSSLESS_SUPPORTED
231 fprintf(stderr, " (N is 8, 12, or 16; default is 8; if N is 16, then -lossless\n");
232 fprintf(stderr, " must also be specified)\n");
234 fprintf(stderr, " (N is 8 or 12; default is 8)\n");
236 #ifdef C_LOSSLESS_SUPPORTED
237 fprintf(stderr, " -lossless psv[,Pt] Create lossless JPEG file\n");
239 #ifdef C_ARITH_CODING_SUPPORTED
240 fprintf(stderr, " -arithmetic Use arithmetic coding\n");
242 #ifdef DCT_ISLOW_SUPPORTED
243 fprintf(stderr, " -dct int Use accurate integer DCT method%s\n",
244 (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
246 #ifdef DCT_IFAST_SUPPORTED
247 fprintf(stderr, " -dct fast Use less accurate integer DCT method [legacy feature]%s\n",
248 (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
250 #ifdef DCT_FLOAT_SUPPORTED
251 fprintf(stderr, " -dct float Use floating-point DCT method [legacy feature]%s\n",
252 (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
254 fprintf(stderr, " -icc FILE Embed ICC profile contained in FILE\n");
255 fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n");
256 #ifdef INPUT_SMOOTHING_SUPPORTED
257 fprintf(stderr, " -smooth N Smooth dithered input (N=1..100 is strength)\n");
259 fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
260 fprintf(stderr, " -outfile name Specify name for output file\n");
261 fprintf(stderr, " -memdst Compress to memory instead of file (useful for benchmarking)\n");
262 fprintf(stderr, " -report Report compression progress\n");
263 fprintf(stderr, " -strict Treat all warnings as fatal\n");
264 fprintf(stderr, " -verbose or -debug Emit debug output\n");
265 fprintf(stderr, " -version Print version information and exit\n");
266 fprintf(stderr, "Switches for wizards:\n");
267 fprintf(stderr, " -baseline Force baseline quantization tables\n");
268 fprintf(stderr, " -qtables FILE Use quantization tables given in FILE\n");
269 fprintf(stderr, " -qslots N[,...] Set component quantization tables\n");
270 fprintf(stderr, " -sample HxV[,...] Set component sampling factors\n");
271 #ifdef C_MULTISCAN_FILES_SUPPORTED
272 fprintf(stderr, " -scans FILE Create multi-scan JPEG per script FILE\n");
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
292 #ifdef C_LOSSLESS_SUPPORTED
295 boolean force_baseline;
296 boolean simple_progressive;
297 char *qualityarg = NULL; /* saves -quality parm if any */
298 char *qtablefile = NULL; /* saves -qtables filename if any */
299 char *qslotsarg = NULL; /* saves -qslots parm if any */
300 char *samplearg = NULL; /* saves -sample parm if any */
301 char *scansarg = NULL; /* saves -scans parm if any */
303 /* Set up default JPEG parameters. */
305 force_baseline = FALSE; /* by default, allow 16-bit quantizers */
306 simple_progressive = FALSE;
313 cinfo->err->trace_level = 0;
315 /* Scan command line options, adjust parameters */
317 for (argn = 1; argn < argc; argn++) {
320 /* Not a switch, must be a file name argument */
321 if (argn <= last_file_arg_seen) {
322 outfilename = NULL; /* -outfile applies to just one input file */
323 continue; /* ignore this name if previously processed */
325 break; /* else done parsing switches */
327 arg++; /* advance past switch marker character */
329 if (keymatch(arg, "arithmetic", 1)) {
330 /* Use arithmetic coding. */
331 #ifdef C_ARITH_CODING_SUPPORTED
332 cinfo->arith_code = TRUE;
334 fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
339 } else if (keymatch(arg, "baseline", 1)) {
340 /* Force baseline-compatible output (8-bit quantizer values). */
341 force_baseline = TRUE;
343 } else if (keymatch(arg, "dct", 2)) {
344 /* Select DCT algorithm. */
345 if (++argn >= argc) /* advance to next argument */
347 if (keymatch(argv[argn], "int", 1)) {
348 cinfo->dct_method = JDCT_ISLOW;
349 } else if (keymatch(argv[argn], "fast", 2)) {
350 cinfo->dct_method = JDCT_IFAST;
351 } else if (keymatch(argv[argn], "float", 2)) {
352 cinfo->dct_method = JDCT_FLOAT;
356 } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
357 /* Enable debug printouts. */
358 /* On first -d, print version identification */
359 static boolean printed_version = FALSE;
361 if (!printed_version) {
362 fprintf(stderr, "%s version %s (build %s)\n",
363 PACKAGE_NAME, VERSION, BUILD);
364 fprintf(stderr, "%s\n\n", JCOPYRIGHT);
365 fprintf(stderr, "Emulating The Independent JPEG Group's software, version %s\n\n",
367 printed_version = TRUE;
369 cinfo->err->trace_level++;
371 } else if (keymatch(arg, "version", 4)) {
372 fprintf(stderr, "%s version %s (build %s)\n",
373 PACKAGE_NAME, VERSION, BUILD);
376 } else if (keymatch(arg, "grayscale", 2) ||
377 keymatch(arg, "greyscale", 2)) {
378 /* Force a monochrome JPEG file to be generated. */
379 jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
381 } else if (keymatch(arg, "rgb", 3)) {
382 /* Force an RGB JPEG file to be generated. */
383 jpeg_set_colorspace(cinfo, JCS_RGB);
385 } else if (keymatch(arg, "icc", 1)) {
386 /* Set ICC filename. */
387 if (++argn >= argc) /* advance to next argument */
389 icc_filename = argv[argn];
391 } else if (keymatch(arg, "lossless", 1)) {
392 /* Enable lossless mode. */
393 #ifdef C_LOSSLESS_SUPPORTED
396 if (++argn >= argc) /* advance to next argument */
398 if (sscanf(argv[argn], "%d%c", &psv, &ch) < 1 || ch != ',')
401 while (*ptr && *ptr++ != ','); /* advance to next segment of arg
404 sscanf(ptr, "%d", &pt);
405 jpeg_enable_lossless(cinfo, psv, pt);
407 fprintf(stderr, "%s: sorry, lossless output was not compiled\n",
412 } else if (keymatch(arg, "maxmemory", 3)) {
413 /* Maximum memory in Kb (or Mb with 'm'). */
417 if (++argn >= argc) /* advance to next argument */
419 if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
421 if (ch == 'm' || ch == 'M')
423 cinfo->mem->max_memory_to_use = lval * 1000L;
425 } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
426 /* Enable entropy parm optimization. */
427 #ifdef ENTROPY_OPT_SUPPORTED
428 cinfo->optimize_coding = TRUE;
430 fprintf(stderr, "%s: sorry, entropy optimization was not compiled in\n",
435 } else if (keymatch(arg, "outfile", 4)) {
436 /* Set output file name. */
437 if (++argn >= argc) /* advance to next argument */
439 outfilename = argv[argn]; /* save it away for later use */
441 } else if (keymatch(arg, "precision", 3)) {
442 /* Set data precision. */
445 if (++argn >= argc) /* advance to next argument */
447 if (sscanf(argv[argn], "%d", &val) != 1)
449 #ifdef C_LOSSLESS_SUPPORTED
450 if (val != 8 && val != 12 && val != 16)
452 if (val != 8 && val != 12)
455 cinfo->data_precision = val;
457 } else if (keymatch(arg, "progressive", 3)) {
458 /* Select simple progressive mode. */
459 #ifdef C_PROGRESSIVE_SUPPORTED
460 simple_progressive = TRUE;
461 /* We must postpone execution until num_components is known. */
463 fprintf(stderr, "%s: sorry, progressive output was not compiled in\n",
468 } else if (keymatch(arg, "memdst", 2)) {
469 /* Use in-memory destination manager */
472 } else if (keymatch(arg, "quality", 1)) {
473 /* Quality ratings (quantization table scaling factors). */
474 if (++argn >= argc) /* advance to next argument */
476 qualityarg = argv[argn];
478 } else if (keymatch(arg, "qslots", 2)) {
479 /* Quantization table slot numbers. */
480 if (++argn >= argc) /* advance to next argument */
482 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.
488 } else if (keymatch(arg, "qtables", 2)) {
489 /* Quantization tables fetched from file. */
490 if (++argn >= argc) /* advance to next argument */
492 qtablefile = argv[argn];
493 /* We postpone actually reading the file in case -quality comes later. */
495 } else if (keymatch(arg, "report", 3)) {
498 } else if (keymatch(arg, "restart", 1)) {
499 /* Restart interval in MCU rows (or in MCUs with 'b'). */
503 if (++argn >= argc) /* advance to next argument */
505 if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
507 if (lval < 0 || lval > 65535L)
509 if (ch == 'b' || ch == 'B') {
510 cinfo->restart_interval = (unsigned int)lval;
511 cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */
513 cinfo->restart_in_rows = (int)lval;
514 /* restart_interval will be computed during startup */
517 } else if (keymatch(arg, "sample", 2)) {
518 /* Set sampling factors. */
519 if (++argn >= argc) /* advance to next argument */
521 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.
527 } else if (keymatch(arg, "scans", 4)) {
528 /* Set scan script. */
529 #ifdef C_MULTISCAN_FILES_SUPPORTED
530 if (++argn >= argc) /* advance to next argument */
532 scansarg = argv[argn];
533 /* We must postpone reading the file in case -progressive appears. */
535 fprintf(stderr, "%s: sorry, multi-scan output was not compiled in\n",
540 } else if (keymatch(arg, "smooth", 2)) {
541 /* Set input smoothing factor. */
544 if (++argn >= argc) /* advance to next argument */
546 if (sscanf(argv[argn], "%d", &val) != 1)
548 if (val < 0 || val > 100)
550 cinfo->smoothing_factor = val;
552 } else if (keymatch(arg, "strict", 2)) {
555 } else if (keymatch(arg, "targa", 1)) {
556 /* Input file is Targa format. */
560 usage(); /* bogus switch */
564 /* Post-switch-scanning cleanup */
568 /* Set quantization tables for selected quality. */
569 /* Some or all may be overridden if -qtables is present. */
570 if (qualityarg != NULL) /* process -quality if it was present */
571 if (!set_quality_ratings(cinfo, qualityarg, force_baseline))
574 if (qtablefile != NULL) /* process -qtables if it was present */
575 if (!read_quant_tables(cinfo, qtablefile, force_baseline))
578 if (qslotsarg != NULL) /* process -qslots if it was present */
579 if (!set_quant_slots(cinfo, qslotsarg))
582 if (samplearg != NULL) /* process -sample if it was present */
583 if (!set_sample_factors(cinfo, samplearg))
586 #ifdef C_PROGRESSIVE_SUPPORTED
587 if (simple_progressive) /* process -progressive; -scans can override */
588 jpeg_simple_progression(cinfo);
591 #ifdef C_MULTISCAN_FILES_SUPPORTED
592 if (scansarg != NULL) /* process -scans if it was present */
593 if (!read_scan_script(cinfo, scansarg))
598 return argn; /* return index of next arg (file name) */
603 my_emit_message(j_common_ptr cinfo, int msg_level)
606 /* Treat warning as fatal */
607 cinfo->err->error_exit(cinfo);
609 if (cinfo->err->trace_level >= msg_level)
610 cinfo->err->output_message(cinfo);
620 main(int argc, char **argv)
622 struct jpeg_compress_struct cinfo;
624 struct my_error_mgr myerr;
625 struct jpeg_error_mgr &jerr = myerr.pub;
627 struct jpeg_error_mgr jerr;
629 struct cdjpeg_progress_mgr progress;
631 cjpeg_source_ptr src_mgr;
632 FILE *input_file = NULL;
634 JOCTET *icc_profile = NULL;
636 FILE *output_file = NULL;
637 unsigned char *outbuffer = NULL;
638 unsigned long outsize = 0;
639 JDIMENSION num_scanlines;
642 if (progname == NULL || progname[0] == 0)
643 progname = "cjpeg"; /* in case C library doesn't provide it */
645 /* Initialize the JPEG compression object with default error handling. */
646 cinfo.err = jpeg_std_error(&jerr);
647 jpeg_create_compress(&cinfo);
648 /* Add some application-specific error messages (from cderror.h) */
649 jerr.addon_message_table = cdjpeg_message_table;
650 jerr.first_addon_message = JMSG_FIRSTADDONCODE;
651 jerr.last_addon_message = JMSG_LASTADDONCODE;
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.
659 cinfo.in_color_space = JCS_RGB; /* arbitrary guess */
660 jpeg_set_defaults(&cinfo);
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
668 file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
671 jerr.emit_message = my_emit_message;
673 #ifdef TWO_FILE_COMMANDLINE
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",
682 outfilename = argv[file_index + 1];
684 if (file_index != argc - 1) {
685 fprintf(stderr, "%s: must name one input and one output file\n",
692 /* Unix style: expect zero or one file name */
693 if (file_index < argc - 1) {
694 fprintf(stderr, "%s: only one input file\n", progname);
697 #endif /* TWO_FILE_COMMANDLINE */
699 /* Open the input file. */
700 if (file_index < argc) {
701 if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
702 fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
706 /* default input file is stdin */
707 input_file = read_stdin();
710 /* Open the output file. */
711 if (outfilename != NULL) {
712 if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
713 fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
716 } else if (!memdst) {
717 /* default output file is stdout */
718 output_file = write_stdout();
721 if (icc_filename != NULL) {
722 if ((icc_file = fopen(icc_filename, READ_BINARY)) == NULL) {
723 fprintf(stderr, "%s: can't open %s\n", progname, icc_filename);
726 if (fseek(icc_file, 0, SEEK_END) < 0 ||
727 (icc_len = ftell(icc_file)) < 1 ||
728 fseek(icc_file, 0, SEEK_SET) < 0) {
729 fprintf(stderr, "%s: can't determine size of %s\n", progname,
733 if ((icc_profile = (JOCTET *)malloc(icc_len)) == NULL) {
734 fprintf(stderr, "%s: can't allocate memory for ICC profile\n", progname);
738 if (fread(icc_profile, icc_len, 1, icc_file) < 1) {
739 fprintf(stderr, "%s: can't read ICC profile from %s\n", progname,
749 jerr.error_exit = my_error_exit;
750 jerr.emit_message = my_emit_message_fuzzer;
751 if (setjmp(myerr.setjmp_buffer))
756 start_progress_monitor((j_common_ptr)&cinfo, &progress);
757 progress.report = report;
760 /* Figure out the input file format, and set up to read it. */
761 src_mgr = select_file_type(&cinfo, input_file);
762 src_mgr->input_file = input_file;
764 src_mgr->max_pixels = 1048576;
767 /* Read the input file header to obtain file size & colorspace. */
768 (*src_mgr->start_input) (&cinfo, src_mgr);
770 /* Now that we know input colorspace, fix colorspace-dependent defaults */
771 jpeg_default_colorspace(&cinfo);
773 /* Adjust default compression parameters by re-parsing the options */
774 file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
776 /* Specify data destination for compression */
778 jpeg_mem_dest(&cinfo, &outbuffer, &outsize);
780 jpeg_stdio_dest(&cinfo, output_file);
783 if (setjmp(myerr.setjmp_buffer))
787 /* Start compressor */
788 jpeg_start_compress(&cinfo, TRUE);
790 if (icc_profile != NULL)
791 jpeg_write_icc_profile(&cinfo, icc_profile, (unsigned int)icc_len);
794 if (cinfo.data_precision == 16) {
795 #ifdef C_LOSSLESS_SUPPORTED
796 while (cinfo.next_scanline < cinfo.image_height) {
797 num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr);
798 (void)jpeg16_write_scanlines(&cinfo, src_mgr->buffer16, num_scanlines);
801 ERREXIT1(&cinfo, JERR_BAD_PRECISION, cinfo.data_precision);
803 } else if (cinfo.data_precision == 12) {
804 while (cinfo.next_scanline < cinfo.image_height) {
805 num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr);
806 (void)jpeg12_write_scanlines(&cinfo, src_mgr->buffer12, num_scanlines);
809 while (cinfo.next_scanline < cinfo.image_height) {
810 num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr);
811 (void)jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines);
815 /* Finish compression and release memory */
816 (*src_mgr->finish_input) (&cinfo, src_mgr);
817 jpeg_finish_compress(&cinfo);
818 jpeg_destroy_compress(&cinfo);
820 /* Close files, if we opened them */
821 if (input_file != stdin)
823 if (output_file != stdout && output_file != NULL)
827 end_progress_monitor((j_common_ptr)&cinfo);
831 fprintf(stderr, "Compressed size: %lu bytes\n", outsize);
839 return (jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);