Doxygen Source Code Documentation
Main Page Alphabetical List Data Structures File List Data Fields Globals Search
rdjpgcom.c
Go to the documentation of this file.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 }