/* * cjpeg.c * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1998, Thomas G. Lane. * Modified 2003-2011 by Guido Vollbeding. * libjpeg-turbo Modifications: * Copyright (C) 2010, 2013-2014, 2017, 2019-2022, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * * This file contains a command-line user interface for the JPEG compressor. * It should work on any system with Unix- or MS-DOS-style command lines. * * Two different command line styles are permitted, depending on the * compile-time switch TWO_FILE_COMMANDLINE: * cjpeg [options] inputfile outputfile * cjpeg [options] [inputfile] * In the second style, output is always to standard output, which you'd * normally redirect to a file or pipe to some other program. Input is * either from a named file or from standard input (typically redirected). * The second style is convenient on Unix but is unhelpful on systems that * don't support pipes. Also, you MUST use the first style if your system * doesn't do binary I/O to stdin/stdout. * To simplify script writing, the "-outfile" switch is provided. The syntax * cjpeg [options] -outfile outputfile inputfile * works regardless of which command line style is used. */ #ifdef _MSC_VER #define _CRT_SECURE_NO_DEPRECATE #endif #ifdef CJPEG_FUZZER #define JPEG_INTERNALS #endif #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ #include "jversion.h" /* for version message */ #include "jconfigint.h" /* Create the add-on message string table. */ #define JMESSAGE … static const char * const cdjpeg_message_table[] = …; /* * This routine determines what format the input file is, * and selects the appropriate input-reading module. * * To determine which family of input formats the file belongs to, * we may look only at the first byte of the file, since C does not * guarantee that more than one character can be pushed back with ungetc. * Looking at additional bytes would require one of these approaches: * 1) assume we can fseek() the input file (fails for piped input); * 2) assume we can push back more than one character (works in * some C implementations, but unportable); * 3) provide our own buffering (breaks input readers that want to use * stdio directly); * or 4) don't put back the data, and modify the input_init methods to assume * they start reading after the start of file. * #1 is attractive for MS-DOS but is untenable on Unix. * * The most portable solution for file types that can't be identified by their * first byte is to make the user tell us what they are. This is also the * only approach for "raw" file types that contain only arbitrary values. * We presently apply this method for Targa files. Most of the time Targa * files start with 0x00, so we recognize that case. Potentially, however, * a Targa file could start with any byte value (byte 0 is the length of the * seldom-used ID field), so we provide a switch to force Targa input mode. */ static boolean is_targa; /* records user -targa switch */ LOCAL(cjpeg_source_ptr) select_file_type(j_compress_ptr cinfo, FILE *infile) { … } /* * Argument-parsing code. * The switch parser is designed to be useful with DOS-style command line * syntax, ie, intermixed switches and file names, where only the switches * to the left of a given file name affect processing of that file. * The main program in this file doesn't actually use this capability... */ static const char *progname; /* program name for error messages */ static char *icc_filename; /* for -icc switch */ static char *outfilename; /* for -outfile switch */ boolean memdst; /* for -memdst switch */ boolean report; /* for -report switch */ boolean strict; /* for -strict switch */ #ifdef CJPEG_FUZZER #include <setjmp.h> struct my_error_mgr { struct jpeg_error_mgr pub; jmp_buf setjmp_buffer; }; void my_error_exit(j_common_ptr cinfo) { struct my_error_mgr *myerr = (struct my_error_mgr *)cinfo->err; longjmp(myerr->setjmp_buffer, 1); } static void my_emit_message_fuzzer(j_common_ptr cinfo, int msg_level) { if (msg_level < 0) cinfo->err->num_warnings++; } #define HANDLE_ERROR … #endif LOCAL(void) usage(void) /* complain about bad command line */ { … } LOCAL(int) parse_switches(j_compress_ptr cinfo, int argc, char **argv, int last_file_arg_seen, boolean for_real) /* Parse optional switches. * Returns argv[] index of first file-name argument (== argc if none). * Any file names with indexes <= last_file_arg_seen are ignored; * they have presumably been processed in a previous iteration. * (Pass 0 for last_file_arg_seen on the first or only iteration.) * for_real is FALSE on the first (dummy) pass; we may skip any expensive * processing. */ { … } METHODDEF(void) my_emit_message(j_common_ptr cinfo, int msg_level) { … } /* * The main program. */ int #ifdef GTEST cjpeg(int argc, char **argv) #else main(int argc, char **argv) #endif { … }