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 }