00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #define JPEG_CJPEG_DJPEG
00015 #include "jinclude.h"
00016
00017 #include <ctype.h>
00018 #ifdef USE_SETMODE
00019 #include <fcntl.h>
00020
00021 #include <io.h>
00022 #endif
00023
00024 #ifdef USE_CCOMMAND
00025 #ifdef __MWERKS__
00026 #include <SIOUX.h>
00027 #include <console.h>
00028 #endif
00029 #ifdef THINK_C
00030 #include <console.h>
00031 #endif
00032 #endif
00033
00034 #ifdef DONT_USE_B_MODE
00035 #define READ_BINARY "r"
00036 #else
00037 #ifdef VMS
00038 #define READ_BINARY "rb", "ctx=stm"
00039 #else
00040 #define READ_BINARY "rb"
00041 #endif
00042 #endif
00043
00044 #ifndef EXIT_FAILURE
00045 #define EXIT_FAILURE 1
00046 #endif
00047 #ifndef EXIT_SUCCESS
00048 #ifdef VMS
00049 #define EXIT_SUCCESS 1
00050 #else
00051 #define EXIT_SUCCESS 0
00052 #endif
00053 #endif
00054
00055
00056
00057
00058
00059
00060
00061 static FILE * infile;
00062
00063
00064 #define NEXTBYTE() getc(infile)
00065
00066
00067
00068 #define ERREXIT(msg) (fprintf(stderr, "%s\n", msg), exit(EXIT_FAILURE))
00069
00070
00071
00072 static int
00073 read_1_byte (void)
00074 {
00075 int c;
00076
00077 c = NEXTBYTE();
00078 if (c == EOF)
00079 ERREXIT("Premature EOF in JPEG file");
00080 return c;
00081 }
00082
00083
00084
00085 static unsigned int
00086 read_2_bytes (void)
00087 {
00088 int c1, c2;
00089
00090 c1 = NEXTBYTE();
00091 if (c1 == EOF)
00092 ERREXIT("Premature EOF in JPEG file");
00093 c2 = NEXTBYTE();
00094 if (c2 == EOF)
00095 ERREXIT("Premature EOF in JPEG file");
00096 return (((unsigned int) c1) << 8) + ((unsigned int) c2);
00097 }
00098
00099
00100
00101
00102
00103
00104
00105
00106 #define M_SOF0 0xC0
00107 #define M_SOF1 0xC1
00108 #define M_SOF2 0xC2
00109 #define M_SOF3 0xC3
00110 #define M_SOF5 0xC5
00111 #define M_SOF6 0xC6
00112 #define M_SOF7 0xC7
00113 #define M_SOF9 0xC9
00114 #define M_SOF10 0xCA
00115 #define M_SOF11 0xCB
00116 #define M_SOF13 0xCD
00117 #define M_SOF14 0xCE
00118 #define M_SOF15 0xCF
00119 #define M_SOI 0xD8
00120 #define M_EOI 0xD9
00121 #define M_SOS 0xDA
00122 #define M_APP0 0xE0
00123 #define M_APP12 0xEC
00124 #define M_COM 0xFE
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 static int
00138 next_marker (void)
00139 {
00140 int c;
00141 int discarded_bytes = 0;
00142
00143
00144 c = read_1_byte();
00145 while (c != 0xFF) {
00146 discarded_bytes++;
00147 c = read_1_byte();
00148 }
00149
00150
00151
00152 do {
00153 c = read_1_byte();
00154 } while (c == 0xFF);
00155
00156 if (discarded_bytes != 0) {
00157 fprintf(stderr, "Warning: garbage data found in JPEG file\n");
00158 }
00159
00160 return c;
00161 }
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 static int
00173 first_marker (void)
00174 {
00175 int c1, c2;
00176
00177 c1 = NEXTBYTE();
00178 c2 = NEXTBYTE();
00179 if (c1 != 0xFF || c2 != M_SOI)
00180 ERREXIT("Not a JPEG file");
00181 return c2;
00182 }
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 static void
00195 skip_variable (void)
00196
00197 {
00198 unsigned int length;
00199
00200
00201 length = read_2_bytes();
00202
00203 if (length < 2)
00204 ERREXIT("Erroneous JPEG marker length");
00205 length -= 2;
00206
00207 while (length > 0) {
00208 (void) read_1_byte();
00209 length--;
00210 }
00211 }
00212
00213
00214
00215
00216
00217
00218
00219
00220 static void
00221 process_COM (void)
00222 {
00223 unsigned int length;
00224 int ch;
00225 int lastch = 0;
00226
00227
00228 length = read_2_bytes();
00229
00230 if (length < 2)
00231 ERREXIT("Erroneous JPEG marker length");
00232 length -= 2;
00233
00234 while (length > 0) {
00235 ch = read_1_byte();
00236
00237
00238
00239
00240
00241 if (ch == '\r') {
00242 printf("\n");
00243 } else if (ch == '\n') {
00244 if (lastch != '\r')
00245 printf("\n");
00246 } else if (ch == '\\') {
00247 printf("\\\\");
00248 } else if (isprint(ch)) {
00249 putc(ch, stdout);
00250 } else {
00251 printf("\\%03o", ch);
00252 }
00253 lastch = ch;
00254 length--;
00255 }
00256 printf("\n");
00257 }
00258
00259
00260
00261
00262
00263
00264
00265 static void
00266 process_SOFn (int marker)
00267 {
00268 unsigned int length;
00269 unsigned int image_height, image_width;
00270 int data_precision, num_components;
00271 const char * process;
00272 int ci;
00273
00274 length = read_2_bytes();
00275
00276 data_precision = read_1_byte();
00277 image_height = read_2_bytes();
00278 image_width = read_2_bytes();
00279 num_components = read_1_byte();
00280
00281 switch (marker) {
00282 case M_SOF0: process = "Baseline"; break;
00283 case M_SOF1: process = "Extended sequential"; break;
00284 case M_SOF2: process = "Progressive"; break;
00285 case M_SOF3: process = "Lossless"; break;
00286 case M_SOF5: process = "Differential sequential"; break;
00287 case M_SOF6: process = "Differential progressive"; break;
00288 case M_SOF7: process = "Differential lossless"; break;
00289 case M_SOF9: process = "Extended sequential, arithmetic coding"; break;
00290 case M_SOF10: process = "Progressive, arithmetic coding"; break;
00291 case M_SOF11: process = "Lossless, arithmetic coding"; break;
00292 case M_SOF13: process = "Differential sequential, arithmetic coding"; break;
00293 case M_SOF14: process = "Differential progressive, arithmetic coding"; break;
00294 case M_SOF15: process = "Differential lossless, arithmetic coding"; break;
00295 default: process = "Unknown"; break;
00296 }
00297
00298 printf("JPEG image is %uw * %uh, %d color components, %d bits per sample\n",
00299 image_width, image_height, num_components, data_precision);
00300 printf("JPEG process: %s\n", process);
00301
00302 if (length != (unsigned int) (8 + num_components * 3))
00303 ERREXIT("Bogus SOF marker length");
00304
00305 for (ci = 0; ci < num_components; ci++) {
00306 (void) read_1_byte();
00307 (void) read_1_byte();
00308 (void) read_1_byte();
00309 }
00310 }
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 static int
00324 scan_JPEG_header (int verbose)
00325 {
00326 int marker;
00327
00328
00329 if (first_marker() != M_SOI)
00330 ERREXIT("Expected SOI marker first");
00331
00332
00333 for (;;) {
00334 marker = next_marker();
00335 switch (marker) {
00336
00337
00338
00339 case M_SOF0:
00340 case M_SOF1:
00341 case M_SOF2:
00342 case M_SOF3:
00343 case M_SOF5:
00344 case M_SOF6:
00345 case M_SOF7:
00346 case M_SOF9:
00347 case M_SOF10:
00348 case M_SOF11:
00349 case M_SOF13:
00350 case M_SOF14:
00351 case M_SOF15:
00352 if (verbose)
00353 process_SOFn(marker);
00354 else
00355 skip_variable();
00356 break;
00357
00358 case M_SOS:
00359 return marker;
00360
00361 case M_EOI:
00362 return marker;
00363
00364 case M_COM:
00365 process_COM();
00366 break;
00367
00368 case M_APP12:
00369
00370
00371
00372 if (verbose) {
00373 printf("APP12 contains:\n");
00374 process_COM();
00375 } else
00376 skip_variable();
00377 break;
00378
00379 default:
00380 skip_variable();
00381 break;
00382 }
00383 }
00384 }
00385
00386
00387
00388
00389 static const char * progname;
00390
00391
00392 static void
00393 usage (void)
00394
00395 {
00396 fprintf(stderr, "rdjpgcom displays any textual comments in a JPEG file.\n");
00397
00398 fprintf(stderr, "Usage: %s [switches] [inputfile]\n", progname);
00399
00400 fprintf(stderr, "Switches (names may be abbreviated):\n");
00401 fprintf(stderr, " -verbose Also display dimensions of JPEG image\n");
00402
00403 exit(EXIT_FAILURE);
00404 }
00405
00406
00407 static int
00408 keymatch (char * arg, const char * keyword, int minchars)
00409
00410
00411
00412 {
00413 register int ca, ck;
00414 register int nmatched = 0;
00415
00416 while ((ca = *arg++) != '\0') {
00417 if ((ck = *keyword++) == '\0')
00418 return 0;
00419 if (isupper(ca))
00420 ca = tolower(ca);
00421 if (ca != ck)
00422 return 0;
00423 nmatched++;
00424 }
00425
00426 if (nmatched < minchars)
00427 return 0;
00428 return 1;
00429 }
00430
00431
00432
00433
00434
00435
00436 int
00437 main (int argc, char **argv)
00438 {
00439 int argn;
00440 char * arg;
00441 int verbose = 0;
00442
00443
00444 #ifdef USE_CCOMMAND
00445 argc = ccommand(&argv);
00446 #endif
00447
00448 progname = argv[0];
00449 if (progname == NULL || progname[0] == 0)
00450 progname = "rdjpgcom";
00451
00452
00453 for (argn = 1; argn < argc; argn++) {
00454 arg = argv[argn];
00455 if (arg[0] != '-')
00456 break;
00457 arg++;
00458 if (keymatch(arg, "verbose", 1)) {
00459 verbose++;
00460 } else
00461 usage();
00462 }
00463
00464
00465
00466 if (argn < argc-1) {
00467 fprintf(stderr, "%s: only one input file\n", progname);
00468 usage();
00469 }
00470 if (argn < argc) {
00471 if ((infile = fopen(argv[argn], READ_BINARY)) == NULL) {
00472 fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
00473 exit(EXIT_FAILURE);
00474 }
00475 } else {
00476
00477 #ifdef USE_SETMODE
00478 setmode(fileno(stdin), O_BINARY);
00479 #endif
00480 #ifdef USE_FDOPEN
00481 if ((infile = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
00482 fprintf(stderr, "%s: can't open stdin\n", progname);
00483 exit(EXIT_FAILURE);
00484 }
00485 #else
00486 infile = stdin;
00487 #endif
00488 }
00489
00490
00491 (void) scan_JPEG_header(verbose);
00492
00493
00494 exit(EXIT_SUCCESS);
00495 return 0;
00496 }