rdjpgcom.c revision 70a18cd874a22452aca9e39e22275ed4538ed20b
170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* 270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * rdjpgcom.c 370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * 470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Copyright (C) 1994-1997, Thomas G. Lane. 570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * This file is part of the Independent JPEG Group's software. 670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * For conditions of distribution and use, see the accompanying README file. 770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * 870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * This file contains a very simple stand-alone application that displays 970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * the text in COM (comment) markers in a JFIF file. 1070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * This may be useful as an example of the minimum logic needed to parse 1170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * JPEG markers. 1270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */ 1370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 1470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define JPEG_CJPEG_DJPEG /* to get the command-line config symbols */ 1570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#include "jinclude.h" /* get auto-config symbols, <stdio.h> */ 1670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 1770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#include <ctype.h> /* to declare isupper(), tolower() */ 1870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef USE_SETMODE 1970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#include <fcntl.h> /* to declare setmode()'s parameter macros */ 2070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* If you have setmode() but not <io.h>, just delete this line: */ 2170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#include <io.h> /* to declare setmode() */ 2270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif 2370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 2470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef USE_CCOMMAND /* command-line reader for Macintosh */ 2570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef __MWERKS__ 2670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#include <SIOUX.h> /* Metrowerks needs this */ 2770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#include <console.h> /* ... and this */ 2870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif 2970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef THINK_C 3070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#include <console.h> /* Think declares it here */ 3170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif 3270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif 3370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 3470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ 3570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define READ_BINARY "r" 3670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#else 3770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef VMS /* VMS is very nonstandard */ 3870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define READ_BINARY "rb", "ctx=stm" 3970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#else /* standard ANSI-compliant case */ 4070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define READ_BINARY "rb" 4170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif 4270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif 4370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 4470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifndef EXIT_FAILURE /* define exit() codes if not provided */ 4570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define EXIT_FAILURE 1 4670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif 4770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifndef EXIT_SUCCESS 4870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef VMS 4970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define EXIT_SUCCESS 1 /* VMS is very nonstandard */ 5070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#else 5170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define EXIT_SUCCESS 0 5270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif 5370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif 5470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 5570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 5670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* 5770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * These macros are used to read the input file. 5870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * To reuse this code in another application, you might need to change these. 5970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */ 6070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 6170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinestatic FILE * infile; /* input JPEG file */ 6270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 6370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* Return next input byte, or EOF if no more */ 6470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define NEXTBYTE() getc(infile) 6570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 6670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 6770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* Error exit handler */ 6870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define ERREXIT(msg) (fprintf(stderr, "%s\n", msg), exit(EXIT_FAILURE)) 6970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 7070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 7170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* Read one byte, testing for EOF */ 7270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinestatic int 7370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkineread_1_byte (void) 7470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{ 7570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine int c; 7670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 7770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine c = NEXTBYTE(); 7870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (c == EOF) 7970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine ERREXIT("Premature EOF in JPEG file"); 8070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine return c; 8170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine} 8270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 8370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* Read 2 bytes, convert to unsigned int */ 8470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* All 2-byte quantities in JPEG markers are MSB first */ 8570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinestatic unsigned int 8670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkineread_2_bytes (void) 8770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{ 8870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine int c1, c2; 8970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 9070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine c1 = NEXTBYTE(); 9170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (c1 == EOF) 9270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine ERREXIT("Premature EOF in JPEG file"); 9370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine c2 = NEXTBYTE(); 9470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (c2 == EOF) 9570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine ERREXIT("Premature EOF in JPEG file"); 9670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine return (((unsigned int) c1) << 8) + ((unsigned int) c2); 9770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine} 9870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 9970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 10070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* 10170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * JPEG markers consist of one or more 0xFF bytes, followed by a marker 10270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * code byte (which is not an FF). Here are the marker codes of interest 10370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * in this program. (See jdmarker.c for a more complete list.) 10470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */ 10570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 10670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define M_SOF0 0xC0 /* Start Of Frame N */ 10770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define M_SOF1 0xC1 /* N indicates which compression process */ 10870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */ 10970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define M_SOF3 0xC3 11070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */ 11170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define M_SOF6 0xC6 11270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define M_SOF7 0xC7 11370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define M_SOF9 0xC9 11470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define M_SOF10 0xCA 11570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define M_SOF11 0xCB 11670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define M_SOF13 0xCD 11770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define M_SOF14 0xCE 11870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define M_SOF15 0xCF 11970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */ 12070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define M_EOI 0xD9 /* End Of Image (end of datastream) */ 12170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */ 12270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define M_APP0 0xE0 /* Application-specific marker, type N */ 12370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define M_APP12 0xEC /* (we don't bother to list all 16 APPn's) */ 12470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define M_COM 0xFE /* COMment */ 12570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 12670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 12770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* 12870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Find the next JPEG marker and return its marker code. 12970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * We expect at least one FF byte, possibly more if the compressor used FFs 13070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * to pad the file. 13170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * There could also be non-FF garbage between markers. The treatment of such 13270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * garbage is unspecified; we choose to skip over it but emit a warning msg. 13370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * NB: this routine must not be used after seeing SOS marker, since it will 13470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * not deal correctly with FF/00 sequences in the compressed image data... 13570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */ 13670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 13770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinestatic int 13870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinenext_marker (void) 13970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{ 14070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine int c; 14170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine int discarded_bytes = 0; 14270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 14370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* Find 0xFF byte; count and skip any non-FFs. */ 14470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine c = read_1_byte(); 14570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine while (c != 0xFF) { 14670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine discarded_bytes++; 14770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine c = read_1_byte(); 14870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } 14970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* Get marker code byte, swallowing any duplicate FF bytes. Extra FFs 15070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * are legal as pad bytes, so don't count them in discarded_bytes. 15170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */ 15270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine do { 15370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine c = read_1_byte(); 15470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } while (c == 0xFF); 15570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 15670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (discarded_bytes != 0) { 15770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine fprintf(stderr, "Warning: garbage data found in JPEG file\n"); 15870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } 15970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 16070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine return c; 16170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine} 16270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 16370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 16470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* 16570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Read the initial marker, which should be SOI. 16670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * For a JFIF file, the first two bytes of the file should be literally 16770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * 0xFF M_SOI. To be more general, we could use next_marker, but if the 16870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * input file weren't actually JPEG at all, next_marker might read the whole 16970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * file and then return a misleading error message... 17070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */ 17170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 17270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinestatic int 17370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinefirst_marker (void) 17470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{ 17570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine int c1, c2; 17670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 17770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine c1 = NEXTBYTE(); 17870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine c2 = NEXTBYTE(); 17970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (c1 != 0xFF || c2 != M_SOI) 18070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine ERREXIT("Not a JPEG file"); 18170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine return c2; 18270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine} 18370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 18470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 18570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* 18670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Most types of marker are followed by a variable-length parameter segment. 18770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * This routine skips over the parameters for any marker we don't otherwise 18870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * want to process. 18970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Note that we MUST skip the parameter segment explicitly in order not to 19070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * be fooled by 0xFF bytes that might appear within the parameter segment; 19170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * such bytes do NOT introduce new markers. 19270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */ 19370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 19470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinestatic void 19570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkineskip_variable (void) 19670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* Skip over an unknown or uninteresting variable-length marker */ 19770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{ 19870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine unsigned int length; 19970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 20070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* Get the marker parameter length count */ 20170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine length = read_2_bytes(); 20270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* Length includes itself, so must be at least 2 */ 20370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (length < 2) 20470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine ERREXIT("Erroneous JPEG marker length"); 20570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine length -= 2; 20670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* Skip over the remaining bytes */ 20770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine while (length > 0) { 20870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine (void) read_1_byte(); 20970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine length--; 21070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } 21170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine} 21270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 21370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 21470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* 21570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Process a COM marker. 21670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * We want to print out the marker contents as legible text; 21770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * we must guard against non-text junk and varying newline representations. 21870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */ 21970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 22070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinestatic void 22170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkineprocess_COM (void) 22270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{ 22370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine unsigned int length; 22470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine int ch; 22570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine int lastch = 0; 22670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 22770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* Get the marker parameter length count */ 22870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine length = read_2_bytes(); 22970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* Length includes itself, so must be at least 2 */ 23070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (length < 2) 23170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine ERREXIT("Erroneous JPEG marker length"); 23270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine length -= 2; 23370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 23470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine while (length > 0) { 23570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine ch = read_1_byte(); 23670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* Emit the character in a readable form. 23770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Nonprintables are converted to \nnn form, 23870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * while \ is converted to \\. 23970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Newlines in CR, CR/LF, or LF form will be printed as one newline. 24070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */ 24170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (ch == '\r') { 24270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine printf("\n"); 24370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } else if (ch == '\n') { 24470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (lastch != '\r') 24570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine printf("\n"); 24670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } else if (ch == '\\') { 24770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine printf("\\\\"); 24870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } else if (isprint(ch)) { 24970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine putc(ch, stdout); 25070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } else { 25170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine printf("\\%03o", ch); 25270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } 25370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine lastch = ch; 25470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine length--; 25570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } 25670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine printf("\n"); 25770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine} 25870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 25970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 26070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* 26170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Process a SOFn marker. 26270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * This code is only needed if you want to know the image dimensions... 26370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */ 26470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 26570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinestatic void 26670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkineprocess_SOFn (int marker) 26770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{ 26870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine unsigned int length; 26970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine unsigned int image_height, image_width; 27070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine int data_precision, num_components; 27170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine const char * process; 27270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine int ci; 27370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 27470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine length = read_2_bytes(); /* usual parameter length count */ 27570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 27670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine data_precision = read_1_byte(); 27770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine image_height = read_2_bytes(); 27870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine image_width = read_2_bytes(); 27970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine num_components = read_1_byte(); 28070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 28170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine switch (marker) { 28270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF0: process = "Baseline"; break; 28370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF1: process = "Extended sequential"; break; 28470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF2: process = "Progressive"; break; 28570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF3: process = "Lossless"; break; 28670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF5: process = "Differential sequential"; break; 28770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF6: process = "Differential progressive"; break; 28870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF7: process = "Differential lossless"; break; 28970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF9: process = "Extended sequential, arithmetic coding"; break; 29070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF10: process = "Progressive, arithmetic coding"; break; 29170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF11: process = "Lossless, arithmetic coding"; break; 29270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF13: process = "Differential sequential, arithmetic coding"; break; 29370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF14: process = "Differential progressive, arithmetic coding"; break; 29470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF15: process = "Differential lossless, arithmetic coding"; break; 29570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine default: process = "Unknown"; break; 29670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } 29770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 29870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine printf("JPEG image is %uw * %uh, %d color components, %d bits per sample\n", 29970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine image_width, image_height, num_components, data_precision); 30070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine printf("JPEG process: %s\n", process); 30170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 30270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (length != (unsigned int) (8 + num_components * 3)) 30370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine ERREXIT("Bogus SOF marker length"); 30470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 30570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine for (ci = 0; ci < num_components; ci++) { 30670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine (void) read_1_byte(); /* Component ID code */ 30770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine (void) read_1_byte(); /* H, V sampling factors */ 30870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine (void) read_1_byte(); /* Quantization table number */ 30970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } 31070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine} 31170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 31270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 31370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* 31470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Parse the marker stream until SOS or EOI is seen; 31570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * display any COM markers. 31670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * While the companion program wrjpgcom will always insert COM markers before 31770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * SOFn, other implementations might not, so we scan to SOS before stopping. 31870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * If we were only interested in the image dimensions, we would stop at SOFn. 31970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * (Conversely, if we only cared about COM markers, there would be no need 32070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * for special code to handle SOFn; we could treat it like other markers.) 32170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */ 32270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 32370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinestatic int 32470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinescan_JPEG_header (int verbose) 32570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{ 32670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine int marker; 32770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 32870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* Expect SOI at start of file */ 32970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (first_marker() != M_SOI) 33070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine ERREXIT("Expected SOI marker first"); 33170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 33270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* Scan miscellaneous markers until we reach SOS. */ 33370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine for (;;) { 33470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine marker = next_marker(); 33570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine switch (marker) { 33670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* Note that marker codes 0xC4, 0xC8, 0xCC are not, and must not be, 33770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * treated as SOFn. C4 in particular is actually DHT. 33870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */ 33970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF0: /* Baseline */ 34070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF1: /* Extended sequential, Huffman */ 34170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF2: /* Progressive, Huffman */ 34270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF3: /* Lossless, Huffman */ 34370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF5: /* Differential sequential, Huffman */ 34470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF6: /* Differential progressive, Huffman */ 34570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF7: /* Differential lossless, Huffman */ 34670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF9: /* Extended sequential, arithmetic */ 34770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF10: /* Progressive, arithmetic */ 34870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF11: /* Lossless, arithmetic */ 34970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF13: /* Differential sequential, arithmetic */ 35070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF14: /* Differential progressive, arithmetic */ 35170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOF15: /* Differential lossless, arithmetic */ 35270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (verbose) 35370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine process_SOFn(marker); 35470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine else 35570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine skip_variable(); 35670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine break; 35770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 35870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_SOS: /* stop before hitting compressed data */ 35970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine return marker; 36070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 36170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_EOI: /* in case it's a tables-only JPEG stream */ 36270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine return marker; 36370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 36470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_COM: 36570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine process_COM(); 36670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine break; 36770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 36870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine case M_APP12: 36970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* Some digital camera makers put useful textual information into 37070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * APP12 markers, so we print those out too when in -verbose mode. 37170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */ 37270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (verbose) { 37370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine printf("APP12 contains:\n"); 37470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine process_COM(); 37570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } else 37670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine skip_variable(); 37770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine break; 37870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 37970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine default: /* Anything else just gets skipped */ 38070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine skip_variable(); /* we assume it has a parameter count... */ 38170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine break; 38270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } 38370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } /* end loop */ 38470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine} 38570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 38670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 38770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* Command line parsing code */ 38870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 38970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinestatic const char * progname; /* program name for error messages */ 39070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 39170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 39270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinestatic void 39370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkineusage (void) 39470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* complain about bad command line */ 39570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{ 39670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine fprintf(stderr, "rdjpgcom displays any textual comments in a JPEG file.\n"); 39770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 39870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine fprintf(stderr, "Usage: %s [switches] [inputfile]\n", progname); 39970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 40070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine fprintf(stderr, "Switches (names may be abbreviated):\n"); 40170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine fprintf(stderr, " -verbose Also display dimensions of JPEG image\n"); 40270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 40370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine exit(EXIT_FAILURE); 40470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine} 40570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 40670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 40770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinestatic int 40870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinekeymatch (char * arg, const char * keyword, int minchars) 40970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* Case-insensitive matching of (possibly abbreviated) keyword switches. */ 41070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* keyword is the constant keyword (must be lower case already), */ 41170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* minchars is length of minimum legal abbreviation. */ 41270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{ 41370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine register int ca, ck; 41470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine register int nmatched = 0; 41570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 41670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine while ((ca = *arg++) != '\0') { 41770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if ((ck = *keyword++) == '\0') 41870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine return 0; /* arg longer than keyword, no good */ 41970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (isupper(ca)) /* force arg to lcase (assume ck is already) */ 42070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine ca = tolower(ca); 42170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (ca != ck) 42270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine return 0; /* no good */ 42370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine nmatched++; /* count matched characters */ 42470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } 42570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* reached end of argument; fail if it's too short for unique abbrev */ 42670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (nmatched < minchars) 42770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine return 0; 42870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine return 1; /* A-OK */ 42970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine} 43070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 43170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 43270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* 43370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * The main program. 43470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */ 43570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 43670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkineint 43770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinemain (int argc, char **argv) 43870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{ 43970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine int argn; 44070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine char * arg; 44170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine int verbose = 0; 44270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 44370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* On Mac, fetch a command line. */ 44470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef USE_CCOMMAND 44570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine argc = ccommand(&argv); 44670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif 44770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 44870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine progname = argv[0]; 44970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (progname == NULL || progname[0] == 0) 45070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine progname = "rdjpgcom"; /* in case C library doesn't provide it */ 45170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 45270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* Parse switches, if any */ 45370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine for (argn = 1; argn < argc; argn++) { 45470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine arg = argv[argn]; 45570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (arg[0] != '-') 45670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine break; /* not switch, must be file name */ 45770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine arg++; /* advance over '-' */ 45870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (keymatch(arg, "verbose", 1)) { 45970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine verbose++; 46070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } else 46170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine usage(); 46270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } 46370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 46470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* Open the input file. */ 46570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* Unix style: expect zero or one file name */ 46670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (argn < argc-1) { 46770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine fprintf(stderr, "%s: only one input file\n", progname); 46870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine usage(); 46970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } 47070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if (argn < argc) { 47170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if ((infile = fopen(argv[argn], READ_BINARY)) == NULL) { 47270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]); 47370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine exit(EXIT_FAILURE); 47470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } 47570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } else { 47670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* default input file is stdin */ 47770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef USE_SETMODE /* need to hack file mode? */ 47870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine setmode(fileno(stdin), O_BINARY); 47970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif 48070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef USE_FDOPEN /* need to re-open in binary mode? */ 48170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine if ((infile = fdopen(fileno(stdin), READ_BINARY)) == NULL) { 48270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine fprintf(stderr, "%s: can't open stdin\n", progname); 48370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine exit(EXIT_FAILURE); 48470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } 48570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#else 48670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine infile = stdin; 48770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif 48870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine } 48970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 49070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* Scan the JPEG headers. */ 49170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine (void) scan_JPEG_header(verbose); 49270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine 49370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine /* All done. */ 49470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine exit(EXIT_SUCCESS); 49570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine return 0; /* suppress no-return-value warnings */ 49670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine} 497