| OLD | NEW |
| 1 /* | 1 /* |
| 2 * rdjpgcom.c | 2 * rdjpgcom.c |
| 3 * | 3 * |
| 4 * Copyright (C) 1994-1997, Thomas G. Lane. | 4 * Copyright (C) 1994-1997, Thomas G. Lane. |
| 5 * Modified 2009 by Bill Allombert, Guido Vollbeding. |
| 5 * This file is part of the Independent JPEG Group's software. | 6 * This file is part of the Independent JPEG Group's software. |
| 6 * For conditions of distribution and use, see the accompanying README file. | 7 * For conditions of distribution and use, see the accompanying README file. |
| 7 * | 8 * |
| 8 * This file contains a very simple stand-alone application that displays | 9 * This file contains a very simple stand-alone application that displays |
| 9 * the text in COM (comment) markers in a JFIF file. | 10 * the text in COM (comment) markers in a JFIF file. |
| 10 * This may be useful as an example of the minimum logic needed to parse | 11 * This may be useful as an example of the minimum logic needed to parse |
| 11 * JPEG markers. | 12 * JPEG markers. |
| 12 */ | 13 */ |
| 13 | 14 |
| 14 #define JPEG_CJPEG_DJPEG /* to get the command-line config symbols */ | 15 #define JPEG_CJPEG_DJPEG /* to get the command-line config symbols */ |
| 15 #include "jinclude.h" /* get auto-config symbols, <stdio.h> */ | 16 #include "jinclude.h" /* get auto-config symbols, <stdio.h> */ |
| 16 | 17 |
| 18 #ifdef HAVE_LOCALE_H |
| 19 #include <locale.h> /* Bill Allombert: use locale for isprint */ |
| 20 #endif |
| 17 #include <ctype.h> /* to declare isupper(), tolower() */ | 21 #include <ctype.h> /* to declare isupper(), tolower() */ |
| 18 #ifdef USE_SETMODE | 22 #ifdef USE_SETMODE |
| 19 #include <fcntl.h> /* to declare setmode()'s parameter macros */ | 23 #include <fcntl.h> /* to declare setmode()'s parameter macros */ |
| 20 /* If you have setmode() but not <io.h>, just delete this line: */ | 24 /* If you have setmode() but not <io.h>, just delete this line: */ |
| 21 #include <io.h> /* to declare setmode() */ | 25 #include <io.h> /* to declare setmode() */ |
| 22 #endif | 26 #endif |
| 23 | 27 |
| 24 #ifdef USE_CCOMMAND /* command-line reader for Macintosh */ | 28 #ifdef USE_CCOMMAND /* command-line reader for Macintosh */ |
| 25 #ifdef __MWERKS__ | 29 #ifdef __MWERKS__ |
| 26 #include <SIOUX.h> /* Metrowerks needs this */ | 30 #include <SIOUX.h> /* Metrowerks needs this */ |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 211 } | 215 } |
| 212 | 216 |
| 213 | 217 |
| 214 /* | 218 /* |
| 215 * Process a COM marker. | 219 * Process a COM marker. |
| 216 * We want to print out the marker contents as legible text; | 220 * We want to print out the marker contents as legible text; |
| 217 * we must guard against non-text junk and varying newline representations. | 221 * we must guard against non-text junk and varying newline representations. |
| 218 */ | 222 */ |
| 219 | 223 |
| 220 static void | 224 static void |
| 221 process_COM (void) | 225 process_COM (int raw) |
| 222 { | 226 { |
| 223 unsigned int length; | 227 unsigned int length; |
| 224 int ch; | 228 int ch; |
| 225 int lastch = 0; | 229 int lastch = 0; |
| 226 | 230 |
| 231 /* Bill Allombert: set locale properly for isprint */ |
| 232 #ifdef HAVE_LOCALE_H |
| 233 setlocale(LC_CTYPE, ""); |
| 234 #endif |
| 235 |
| 227 /* Get the marker parameter length count */ | 236 /* Get the marker parameter length count */ |
| 228 length = read_2_bytes(); | 237 length = read_2_bytes(); |
| 229 /* Length includes itself, so must be at least 2 */ | 238 /* Length includes itself, so must be at least 2 */ |
| 230 if (length < 2) | 239 if (length < 2) |
| 231 ERREXIT("Erroneous JPEG marker length"); | 240 ERREXIT("Erroneous JPEG marker length"); |
| 232 length -= 2; | 241 length -= 2; |
| 233 | 242 |
| 234 while (length > 0) { | 243 while (length > 0) { |
| 235 ch = read_1_byte(); | 244 ch = read_1_byte(); |
| 245 if (raw) { |
| 246 putc(ch, stdout); |
| 236 /* Emit the character in a readable form. | 247 /* Emit the character in a readable form. |
| 237 * Nonprintables are converted to \nnn form, | 248 * Nonprintables are converted to \nnn form, |
| 238 * while \ is converted to \\. | 249 * while \ is converted to \\. |
| 239 * Newlines in CR, CR/LF, or LF form will be printed as one newline. | 250 * Newlines in CR, CR/LF, or LF form will be printed as one newline. |
| 240 */ | 251 */ |
| 241 if (ch == '\r') { | 252 } else if (ch == '\r') { |
| 242 printf("\n"); | 253 printf("\n"); |
| 243 } else if (ch == '\n') { | 254 } else if (ch == '\n') { |
| 244 if (lastch != '\r') | 255 if (lastch != '\r') |
| 245 printf("\n"); | 256 printf("\n"); |
| 246 } else if (ch == '\\') { | 257 } else if (ch == '\\') { |
| 247 printf("\\\\"); | 258 printf("\\\\"); |
| 248 } else if (isprint(ch)) { | 259 } else if (isprint(ch)) { |
| 249 putc(ch, stdout); | 260 putc(ch, stdout); |
| 250 } else { | 261 } else { |
| 251 printf("\\%03o", ch); | 262 printf("\\%03o", ch); |
| 252 } | 263 } |
| 253 lastch = ch; | 264 lastch = ch; |
| 254 length--; | 265 length--; |
| 255 } | 266 } |
| 256 printf("\n"); | 267 printf("\n"); |
| 268 |
| 269 /* Bill Allombert: revert to C locale */ |
| 270 #ifdef HAVE_LOCALE_H |
| 271 setlocale(LC_CTYPE, "C"); |
| 272 #endif |
| 257 } | 273 } |
| 258 | 274 |
| 259 | 275 |
| 260 /* | 276 /* |
| 261 * Process a SOFn marker. | 277 * Process a SOFn marker. |
| 262 * This code is only needed if you want to know the image dimensions... | 278 * This code is only needed if you want to know the image dimensions... |
| 263 */ | 279 */ |
| 264 | 280 |
| 265 static void | 281 static void |
| 266 process_SOFn (int marker) | 282 process_SOFn (int marker) |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 * Parse the marker stream until SOS or EOI is seen; | 330 * Parse the marker stream until SOS or EOI is seen; |
| 315 * display any COM markers. | 331 * display any COM markers. |
| 316 * While the companion program wrjpgcom will always insert COM markers before | 332 * While the companion program wrjpgcom will always insert COM markers before |
| 317 * SOFn, other implementations might not, so we scan to SOS before stopping. | 333 * SOFn, other implementations might not, so we scan to SOS before stopping. |
| 318 * If we were only interested in the image dimensions, we would stop at SOFn. | 334 * If we were only interested in the image dimensions, we would stop at SOFn. |
| 319 * (Conversely, if we only cared about COM markers, there would be no need | 335 * (Conversely, if we only cared about COM markers, there would be no need |
| 320 * for special code to handle SOFn; we could treat it like other markers.) | 336 * for special code to handle SOFn; we could treat it like other markers.) |
| 321 */ | 337 */ |
| 322 | 338 |
| 323 static int | 339 static int |
| 324 scan_JPEG_header (int verbose) | 340 scan_JPEG_header (int verbose, int raw) |
| 325 { | 341 { |
| 326 int marker; | 342 int marker; |
| 327 | 343 |
| 328 /* Expect SOI at start of file */ | 344 /* Expect SOI at start of file */ |
| 329 if (first_marker() != M_SOI) | 345 if (first_marker() != M_SOI) |
| 330 ERREXIT("Expected SOI marker first"); | 346 ERREXIT("Expected SOI marker first"); |
| 331 | 347 |
| 332 /* Scan miscellaneous markers until we reach SOS. */ | 348 /* Scan miscellaneous markers until we reach SOS. */ |
| 333 for (;;) { | 349 for (;;) { |
| 334 marker = next_marker(); | 350 marker = next_marker(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 355 skip_variable(); | 371 skip_variable(); |
| 356 break; | 372 break; |
| 357 | 373 |
| 358 case M_SOS: /* stop before hitting compressed data */ | 374 case M_SOS: /* stop before hitting compressed data */ |
| 359 return marker; | 375 return marker; |
| 360 | 376 |
| 361 case M_EOI: /* in case it's a tables-only JPEG stream */ | 377 case M_EOI: /* in case it's a tables-only JPEG stream */ |
| 362 return marker; | 378 return marker; |
| 363 | 379 |
| 364 case M_COM: | 380 case M_COM: |
| 365 process_COM(); | 381 process_COM(raw); |
| 366 break; | 382 break; |
| 367 | 383 |
| 368 case M_APP12: | 384 case M_APP12: |
| 369 /* Some digital camera makers put useful textual information into | 385 /* Some digital camera makers put useful textual information into |
| 370 * APP12 markers, so we print those out too when in -verbose mode. | 386 * APP12 markers, so we print those out too when in -verbose mode. |
| 371 */ | 387 */ |
| 372 if (verbose) { | 388 if (verbose) { |
| 373 printf("APP12 contains:\n"); | 389 printf("APP12 contains:\n"); |
| 374 » process_COM(); | 390 » process_COM(raw); |
| 375 } else | 391 } else |
| 376 skip_variable(); | 392 skip_variable(); |
| 377 break; | 393 break; |
| 378 | 394 |
| 379 default: /* Anything else just gets skipped */ | 395 default: /* Anything else just gets skipped */ |
| 380 skip_variable(); /* we assume it has a parameter count... */ | 396 skip_variable(); /* we assume it has a parameter count... */ |
| 381 break; | 397 break; |
| 382 } | 398 } |
| 383 } /* end loop */ | 399 } /* end loop */ |
| 384 } | 400 } |
| 385 | 401 |
| 386 | 402 |
| 387 /* Command line parsing code */ | 403 /* Command line parsing code */ |
| 388 | 404 |
| 389 static const char * progname; /* program name for error messages */ | 405 static const char * progname; /* program name for error messages */ |
| 390 | 406 |
| 391 | 407 |
| 392 static void | 408 static void |
| 393 usage (void) | 409 usage (void) |
| 394 /* complain about bad command line */ | 410 /* complain about bad command line */ |
| 395 { | 411 { |
| 396 fprintf(stderr, "rdjpgcom displays any textual comments in a JPEG file.\n"); | 412 fprintf(stderr, "rdjpgcom displays any textual comments in a JPEG file.\n"); |
| 397 | 413 |
| 398 fprintf(stderr, "Usage: %s [switches] [inputfile]\n", progname); | 414 fprintf(stderr, "Usage: %s [switches] [inputfile]\n", progname); |
| 399 | 415 |
| 400 fprintf(stderr, "Switches (names may be abbreviated):\n"); | 416 fprintf(stderr, "Switches (names may be abbreviated):\n"); |
| 417 fprintf(stderr, " -raw Display non-printable characters in comments (u
nsafe)\n"); |
| 401 fprintf(stderr, " -verbose Also display dimensions of JPEG image\n"); | 418 fprintf(stderr, " -verbose Also display dimensions of JPEG image\n"); |
| 402 | 419 |
| 403 exit(EXIT_FAILURE); | 420 exit(EXIT_FAILURE); |
| 404 } | 421 } |
| 405 | 422 |
| 406 | 423 |
| 407 static int | 424 static int |
| 408 keymatch (char * arg, const char * keyword, int minchars) | 425 keymatch (char * arg, const char * keyword, int minchars) |
| 409 /* Case-insensitive matching of (possibly abbreviated) keyword switches. */ | 426 /* Case-insensitive matching of (possibly abbreviated) keyword switches. */ |
| 410 /* keyword is the constant keyword (must be lower case already), */ | 427 /* keyword is the constant keyword (must be lower case already), */ |
| (...skipping 20 matching lines...) Expand all Loading... |
| 431 | 448 |
| 432 /* | 449 /* |
| 433 * The main program. | 450 * The main program. |
| 434 */ | 451 */ |
| 435 | 452 |
| 436 int | 453 int |
| 437 main (int argc, char **argv) | 454 main (int argc, char **argv) |
| 438 { | 455 { |
| 439 int argn; | 456 int argn; |
| 440 char * arg; | 457 char * arg; |
| 441 int verbose = 0; | 458 int verbose = 0, raw = 0; |
| 442 | 459 |
| 443 /* On Mac, fetch a command line. */ | 460 /* On Mac, fetch a command line. */ |
| 444 #ifdef USE_CCOMMAND | 461 #ifdef USE_CCOMMAND |
| 445 argc = ccommand(&argv); | 462 argc = ccommand(&argv); |
| 446 #endif | 463 #endif |
| 447 | 464 |
| 448 progname = argv[0]; | 465 progname = argv[0]; |
| 449 if (progname == NULL || progname[0] == 0) | 466 if (progname == NULL || progname[0] == 0) |
| 450 progname = "rdjpgcom"; /* in case C library doesn't provide it */ | 467 progname = "rdjpgcom"; /* in case C library doesn't provide it */ |
| 451 | 468 |
| 452 /* Parse switches, if any */ | 469 /* Parse switches, if any */ |
| 453 for (argn = 1; argn < argc; argn++) { | 470 for (argn = 1; argn < argc; argn++) { |
| 454 arg = argv[argn]; | 471 arg = argv[argn]; |
| 455 if (arg[0] != '-') | 472 if (arg[0] != '-') |
| 456 break; /* not switch, must be file name */ | 473 break; /* not switch, must be file name */ |
| 457 arg++; /* advance over '-' */ | 474 arg++; /* advance over '-' */ |
| 458 if (keymatch(arg, "verbose", 1)) { | 475 if (keymatch(arg, "verbose", 1)) { |
| 459 verbose++; | 476 verbose++; |
| 477 } else if (keymatch(arg, "raw", 1)) { |
| 478 raw = 1; |
| 460 } else | 479 } else |
| 461 usage(); | 480 usage(); |
| 462 } | 481 } |
| 463 | 482 |
| 464 /* Open the input file. */ | 483 /* Open the input file. */ |
| 465 /* Unix style: expect zero or one file name */ | 484 /* Unix style: expect zero or one file name */ |
| 466 if (argn < argc-1) { | 485 if (argn < argc-1) { |
| 467 fprintf(stderr, "%s: only one input file\n", progname); | 486 fprintf(stderr, "%s: only one input file\n", progname); |
| 468 usage(); | 487 usage(); |
| 469 } | 488 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 481 if ((infile = fdopen(fileno(stdin), READ_BINARY)) == NULL) { | 500 if ((infile = fdopen(fileno(stdin), READ_BINARY)) == NULL) { |
| 482 fprintf(stderr, "%s: can't open stdin\n", progname); | 501 fprintf(stderr, "%s: can't open stdin\n", progname); |
| 483 exit(EXIT_FAILURE); | 502 exit(EXIT_FAILURE); |
| 484 } | 503 } |
| 485 #else | 504 #else |
| 486 infile = stdin; | 505 infile = stdin; |
| 487 #endif | 506 #endif |
| 488 } | 507 } |
| 489 | 508 |
| 490 /* Scan the JPEG headers. */ | 509 /* Scan the JPEG headers. */ |
| 491 (void) scan_JPEG_header(verbose); | 510 (void) scan_JPEG_header(verbose, raw); |
| 492 | 511 |
| 493 /* All done. */ | 512 /* All done. */ |
| 494 exit(EXIT_SUCCESS); | 513 exit(EXIT_SUCCESS); |
| 495 return 0; /* suppress no-return-value warnings */ | 514 return 0; /* suppress no-return-value warnings */ |
| 496 } | 515 } |
| OLD | NEW |