123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591 |
- #define JPEG_CJPEG_DJPEG
- #include "jinclude.h"
- #ifndef HAVE_STDLIB_H
- extern void *malloc();
- #endif
- #include <ctype.h> /* to declare isupper(), tolower() */
- #ifdef USE_SETMODE
- #include <fcntl.h> /* to declare setmode()'s parameter macros */
- #include <io.h> /* to declare setmode() */
- #endif
- #ifdef USE_CCOMMAND
- #ifdef __MWERKS__
- #include <SIOUX.h> /* Metrowerks needs this */
- #include <console.h> /* ... and this */
- #endif
- #ifdef THINK_C
- #include <console.h> /* Think declares it here */
- #endif
- #endif
- #ifdef DONT_USE_B_MODE
- #define READ_BINARY "r"
- #define WRITE_BINARY "w"
- #else
- #define READ_BINARY "rb"
- #define WRITE_BINARY "wb"
- #endif
- #ifndef EXIT_FAILURE
- #define EXIT_FAILURE 1
- #endif
- #ifndef EXIT_SUCCESS
- #define EXIT_SUCCESS 0
- #endif
- #ifndef MAX_COM_LENGTH
- #define MAX_COM_LENGTH 65000L
- #endif
- static FILE *infile;
- #define NEXTBYTE() getc(infile)
- static FILE *outfile;
- #define PUTBYTE(x) putc((x), outfile)
- #define ERREXIT(msg) (fprintf(stderr, "%s\n", msg), exit(EXIT_FAILURE))
- static int
- read_1_byte(void)
- {
- int c;
- c = NEXTBYTE();
- if (c == EOF)
- ERREXIT("Premature EOF in JPEG file");
- return c;
- }
- static unsigned int
- read_2_bytes(void)
- {
- int c1, c2;
- c1 = NEXTBYTE();
- if (c1 == EOF)
- ERREXIT("Premature EOF in JPEG file");
- c2 = NEXTBYTE();
- if (c2 == EOF)
- ERREXIT("Premature EOF in JPEG file");
- return (((unsigned int)c1) << 8) + ((unsigned int)c2);
- }
- static void
- write_1_byte(int c)
- {
- PUTBYTE(c);
- }
- static void
- write_2_bytes(unsigned int val)
- {
- PUTBYTE((val >> 8) & 0xFF);
- PUTBYTE(val & 0xFF);
- }
- static void
- write_marker(int marker)
- {
- PUTBYTE(0xFF);
- PUTBYTE(marker);
- }
- static void
- copy_rest_of_file(void)
- {
- int c;
- while ((c = NEXTBYTE()) != EOF)
- PUTBYTE(c);
- }
- #define M_SOF0 0xC0
- #define M_SOF1 0xC1
- #define M_SOF2 0xC2
- #define M_SOF3 0xC3
- #define M_SOF5 0xC5
- #define M_SOF6 0xC6
- #define M_SOF7 0xC7
- #define M_SOF9 0xC9
- #define M_SOF10 0xCA
- #define M_SOF11 0xCB
- #define M_SOF13 0xCD
- #define M_SOF14 0xCE
- #define M_SOF15 0xCF
- #define M_SOI 0xD8
- #define M_EOI 0xD9
- #define M_SOS 0xDA
- #define M_COM 0xFE
- static int
- next_marker(void)
- {
- int c;
- int discarded_bytes = 0;
-
- c = read_1_byte();
- while (c != 0xFF) {
- discarded_bytes++;
- c = read_1_byte();
- }
-
- do {
- c = read_1_byte();
- } while (c == 0xFF);
- if (discarded_bytes != 0) {
- fprintf(stderr, "Warning: garbage data found in JPEG file\n");
- }
- return c;
- }
- static int
- first_marker(void)
- {
- int c1, c2;
- c1 = NEXTBYTE();
- c2 = NEXTBYTE();
- if (c1 != 0xFF || c2 != M_SOI)
- ERREXIT("Not a JPEG file");
- return c2;
- }
- static void
- copy_variable(void)
- {
- unsigned int length;
-
- length = read_2_bytes();
- write_2_bytes(length);
-
- if (length < 2)
- ERREXIT("Erroneous JPEG marker length");
- length -= 2;
-
- while (length > 0) {
- write_1_byte(read_1_byte());
- length--;
- }
- }
- static void
- skip_variable(void)
- {
- unsigned int length;
-
- length = read_2_bytes();
-
- if (length < 2)
- ERREXIT("Erroneous JPEG marker length");
- length -= 2;
-
- while (length > 0) {
- (void)read_1_byte();
- length--;
- }
- }
- static int
- scan_JPEG_header(int keep_COM)
- {
- int marker;
-
- if (first_marker() != M_SOI)
- ERREXIT("Expected SOI marker first");
- write_marker(M_SOI);
-
- for (;;) {
- marker = next_marker();
- switch (marker) {
-
- case M_SOF0:
- case M_SOF1:
- case M_SOF2:
- case M_SOF3:
- case M_SOF5:
- case M_SOF6:
- case M_SOF7:
- case M_SOF9:
- case M_SOF10:
- case M_SOF11:
- case M_SOF13:
- case M_SOF14:
- case M_SOF15:
- return marker;
- case M_SOS:
- ERREXIT("SOS without prior SOFn");
- break;
- case M_EOI:
- return marker;
- case M_COM:
- if (keep_COM) {
- write_marker(marker);
- copy_variable();
- } else {
- skip_variable();
- }
- break;
- default:
- write_marker(marker);
- copy_variable();
- break;
- }
- }
- }
- static const char *progname;
- static void
- usage(void)
- {
- fprintf(stderr, "wrjpgcom inserts a textual comment in a JPEG file.\n");
- fprintf(stderr, "You can add to or replace any existing comment(s).\n");
- fprintf(stderr, "Usage: %s [switches] ", progname);
- #ifdef TWO_FILE_COMMANDLINE
- fprintf(stderr, "inputfile outputfile\n");
- #else
- fprintf(stderr, "[inputfile]\n");
- #endif
- fprintf(stderr, "Switches (names may be abbreviated):\n");
- fprintf(stderr, " -replace Delete any existing comments\n");
- fprintf(stderr, " -comment \"text\" Insert comment with given text\n");
- fprintf(stderr, " -cfile name Read comment from named file\n");
- fprintf(stderr, "Notice that you must put quotes around the comment text\n");
- fprintf(stderr, "when you use -comment.\n");
- fprintf(stderr, "If you do not give either -comment or -cfile on the command line,\n");
- fprintf(stderr, "then the comment text is read from standard input.\n");
- fprintf(stderr, "It can be multiple lines, up to %u characters total.\n",
- (unsigned int)MAX_COM_LENGTH);
- #ifndef TWO_FILE_COMMANDLINE
- fprintf(stderr, "You must specify an input JPEG file name when supplying\n");
- fprintf(stderr, "comment text from standard input.\n");
- #endif
- exit(EXIT_FAILURE);
- }
- static int
- keymatch(char *arg, const char *keyword, int minchars)
- {
- register int ca, ck;
- register int nmatched = 0;
- while ((ca = *arg++) != '\0') {
- if ((ck = *keyword++) == '\0')
- return 0;
- if (isupper(ca))
- ca = tolower(ca);
- if (ca != ck)
- return 0;
- nmatched++;
- }
-
- if (nmatched < minchars)
- return 0;
- return 1;
- }
- int
- main(int argc, char **argv)
- {
- int argn;
- char *arg;
- int keep_COM = 1;
- char *comment_arg = NULL;
- FILE *comment_file = NULL;
- unsigned int comment_length = 0;
- int marker;
-
- #ifdef USE_CCOMMAND
- argc = ccommand(&argv);
- #endif
- progname = argv[0];
- if (progname == NULL || progname[0] == 0)
- progname = "wrjpgcom";
-
- for (argn = 1; argn < argc; argn++) {
- arg = argv[argn];
- if (arg[0] != '-')
- break;
- arg++;
- if (keymatch(arg, "replace", 1)) {
- keep_COM = 0;
- } else if (keymatch(arg, "cfile", 2)) {
- if (++argn >= argc) usage();
- if ((comment_file = fopen(argv[argn], "r")) == NULL) {
- fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
- exit(EXIT_FAILURE);
- }
- } else if (keymatch(arg, "comment", 1)) {
- if (++argn >= argc) usage();
- comment_arg = argv[argn];
-
- if (comment_arg[0] == '"') {
- comment_arg = (char *)malloc((size_t)MAX_COM_LENGTH);
- if (comment_arg == NULL)
- ERREXIT("Insufficient memory");
- if (strlen(argv[argn]) + 2 >= (size_t)MAX_COM_LENGTH) {
- fprintf(stderr, "Comment text may not exceed %u bytes\n",
- (unsigned int)MAX_COM_LENGTH);
- exit(EXIT_FAILURE);
- }
- strcpy(comment_arg, argv[argn] + 1);
- for (;;) {
- comment_length = (unsigned int)strlen(comment_arg);
- if (comment_length > 0 && comment_arg[comment_length - 1] == '"') {
- comment_arg[comment_length - 1] = '\0';
- break;
- }
- if (++argn >= argc)
- ERREXIT("Missing ending quote mark");
- if (strlen(comment_arg) + strlen(argv[argn]) + 2 >=
- (size_t)MAX_COM_LENGTH) {
- fprintf(stderr, "Comment text may not exceed %u bytes\n",
- (unsigned int)MAX_COM_LENGTH);
- exit(EXIT_FAILURE);
- }
- strcat(comment_arg, " ");
- strcat(comment_arg, argv[argn]);
- }
- } else if (strlen(argv[argn]) >= (size_t)MAX_COM_LENGTH) {
- fprintf(stderr, "Comment text may not exceed %u bytes\n",
- (unsigned int)MAX_COM_LENGTH);
- exit(EXIT_FAILURE);
- }
- comment_length = (unsigned int)strlen(comment_arg);
- } else
- usage();
- }
-
- if (comment_arg != NULL && comment_file != NULL)
- usage();
-
- if (comment_arg == NULL && comment_file == NULL && argn >= argc)
- usage();
-
- if (argn < argc) {
- if ((infile = fopen(argv[argn], READ_BINARY)) == NULL) {
- fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
- exit(EXIT_FAILURE);
- }
- } else {
-
- #ifdef USE_SETMODE
- setmode(fileno(stdin), O_BINARY);
- #endif
- #ifdef USE_FDOPEN
- if ((infile = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
- fprintf(stderr, "%s: can't open stdin\n", progname);
- exit(EXIT_FAILURE);
- }
- #else
- infile = stdin;
- #endif
- }
-
- #ifdef TWO_FILE_COMMANDLINE
-
- if (argn != argc - 2) {
- fprintf(stderr, "%s: must name one input and one output file\n", progname);
- usage();
- }
- if ((outfile = fopen(argv[argn + 1], WRITE_BINARY)) == NULL) {
- fprintf(stderr, "%s: can't open %s\n", progname, argv[argn + 1]);
- exit(EXIT_FAILURE);
- }
- #else
-
- if (argn < argc - 1) {
- fprintf(stderr, "%s: only one input file\n", progname);
- usage();
- }
-
- #ifdef USE_SETMODE
- setmode(fileno(stdout), O_BINARY);
- #endif
- #ifdef USE_FDOPEN
- if ((outfile = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) {
- fprintf(stderr, "%s: can't open stdout\n", progname);
- exit(EXIT_FAILURE);
- }
- #else
- outfile = stdout;
- #endif
- #endif
-
- if (comment_arg == NULL) {
- FILE *src_file;
- int c;
- comment_arg = (char *)malloc((size_t)MAX_COM_LENGTH);
- if (comment_arg == NULL)
- ERREXIT("Insufficient memory");
- comment_length = 0;
- src_file = (comment_file != NULL ? comment_file : stdin);
- while ((c = getc(src_file)) != EOF) {
- if (comment_length >= (unsigned int)MAX_COM_LENGTH) {
- fprintf(stderr, "Comment text may not exceed %u bytes\n",
- (unsigned int)MAX_COM_LENGTH);
- exit(EXIT_FAILURE);
- }
- comment_arg[comment_length++] = (char)c;
- }
- if (comment_file != NULL)
- fclose(comment_file);
- }
-
- marker = scan_JPEG_header(keep_COM);
-
- if (comment_length > 0) {
- write_marker(M_COM);
- write_2_bytes(comment_length + 2);
- while (comment_length > 0) {
- write_1_byte(*comment_arg++);
- comment_length--;
- }
- }
-
- write_marker(marker);
- copy_rest_of_file();
-
- exit(EXIT_SUCCESS);
- return 0;
- }
|