diff options
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/jpeglib/rdjpgcom.c')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/jpeglib/rdjpgcom.c | 1030 |
1 files changed, 515 insertions, 515 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/jpeglib/rdjpgcom.c b/libraries/irrlicht-1.8/source/Irrlicht/jpeglib/rdjpgcom.c index ab09b44..3719154 100644 --- a/libraries/irrlicht-1.8/source/Irrlicht/jpeglib/rdjpgcom.c +++ b/libraries/irrlicht-1.8/source/Irrlicht/jpeglib/rdjpgcom.c | |||
@@ -1,515 +1,515 @@ | |||
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 | * Modified 2009 by Bill Allombert, Guido Vollbeding. |
6 | * This file is part of the Independent JPEG Group's software. | 6 | * This file is part of the Independent JPEG Group's software. |
7 | * For conditions of distribution and use, see the accompanying README file. | 7 | * For conditions of distribution and use, see the accompanying README file. |
8 | * | 8 | * |
9 | * This file contains a very simple stand-alone application that displays | 9 | * This file contains a very simple stand-alone application that displays |
10 | * the text in COM (comment) markers in a JFIF file. | 10 | * the text in COM (comment) markers in a JFIF file. |
11 | * 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 |
12 | * JPEG markers. | 12 | * JPEG markers. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #define JPEG_CJPEG_DJPEG /* to get the command-line config symbols */ | 15 | #define JPEG_CJPEG_DJPEG /* to get the command-line config symbols */ |
16 | #include "jinclude.h" /* get auto-config symbols, <stdio.h> */ | 16 | #include "jinclude.h" /* get auto-config symbols, <stdio.h> */ |
17 | 17 | ||
18 | #ifdef HAVE_LOCALE_H | 18 | #ifdef HAVE_LOCALE_H |
19 | #include <locale.h> /* Bill Allombert: use locale for isprint */ | 19 | #include <locale.h> /* Bill Allombert: use locale for isprint */ |
20 | #endif | 20 | #endif |
21 | #include <ctype.h> /* to declare isupper(), tolower() */ | 21 | #include <ctype.h> /* to declare isupper(), tolower() */ |
22 | #ifdef USE_SETMODE | 22 | #ifdef USE_SETMODE |
23 | #include <fcntl.h> /* to declare setmode()'s parameter macros */ | 23 | #include <fcntl.h> /* to declare setmode()'s parameter macros */ |
24 | /* 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: */ |
25 | #include <io.h> /* to declare setmode() */ | 25 | #include <io.h> /* to declare setmode() */ |
26 | #endif | 26 | #endif |
27 | 27 | ||
28 | #ifdef USE_CCOMMAND /* command-line reader for Macintosh */ | 28 | #ifdef USE_CCOMMAND /* command-line reader for Macintosh */ |
29 | #ifdef __MWERKS__ | 29 | #ifdef __MWERKS__ |
30 | #include <SIOUX.h> /* Metrowerks needs this */ | 30 | #include <SIOUX.h> /* Metrowerks needs this */ |
31 | #include <console.h> /* ... and this */ | 31 | #include <console.h> /* ... and this */ |
32 | #endif | 32 | #endif |
33 | #ifdef THINK_C | 33 | #ifdef THINK_C |
34 | #include <console.h> /* Think declares it here */ | 34 | #include <console.h> /* Think declares it here */ |
35 | #endif | 35 | #endif |
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | #ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ | 38 | #ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ |
39 | #define READ_BINARY "r" | 39 | #define READ_BINARY "r" |
40 | #else | 40 | #else |
41 | #ifdef VMS /* VMS is very nonstandard */ | 41 | #ifdef VMS /* VMS is very nonstandard */ |
42 | #define READ_BINARY "rb", "ctx=stm" | 42 | #define READ_BINARY "rb", "ctx=stm" |
43 | #else /* standard ANSI-compliant case */ | 43 | #else /* standard ANSI-compliant case */ |
44 | #define READ_BINARY "rb" | 44 | #define READ_BINARY "rb" |
45 | #endif | 45 | #endif |
46 | #endif | 46 | #endif |
47 | 47 | ||
48 | #ifndef EXIT_FAILURE /* define exit() codes if not provided */ | 48 | #ifndef EXIT_FAILURE /* define exit() codes if not provided */ |
49 | #define EXIT_FAILURE 1 | 49 | #define EXIT_FAILURE 1 |
50 | #endif | 50 | #endif |
51 | #ifndef EXIT_SUCCESS | 51 | #ifndef EXIT_SUCCESS |
52 | #ifdef VMS | 52 | #ifdef VMS |
53 | #define EXIT_SUCCESS 1 /* VMS is very nonstandard */ | 53 | #define EXIT_SUCCESS 1 /* VMS is very nonstandard */ |
54 | #else | 54 | #else |
55 | #define EXIT_SUCCESS 0 | 55 | #define EXIT_SUCCESS 0 |
56 | #endif | 56 | #endif |
57 | #endif | 57 | #endif |
58 | 58 | ||
59 | 59 | ||
60 | /* | 60 | /* |
61 | * These macros are used to read the input file. | 61 | * These macros are used to read the input file. |
62 | * To reuse this code in another application, you might need to change these. | 62 | * To reuse this code in another application, you might need to change these. |
63 | */ | 63 | */ |
64 | 64 | ||
65 | static FILE * infile; /* input JPEG file */ | 65 | static FILE * infile; /* input JPEG file */ |
66 | 66 | ||
67 | /* Return next input byte, or EOF if no more */ | 67 | /* Return next input byte, or EOF if no more */ |
68 | #define NEXTBYTE() getc(infile) | 68 | #define NEXTBYTE() getc(infile) |
69 | 69 | ||
70 | 70 | ||
71 | /* Error exit handler */ | 71 | /* Error exit handler */ |
72 | #define ERREXIT(msg) (fprintf(stderr, "%s\n", msg), exit(EXIT_FAILURE)) | 72 | #define ERREXIT(msg) (fprintf(stderr, "%s\n", msg), exit(EXIT_FAILURE)) |
73 | 73 | ||
74 | 74 | ||
75 | /* Read one byte, testing for EOF */ | 75 | /* Read one byte, testing for EOF */ |
76 | static int | 76 | static int |
77 | read_1_byte (void) | 77 | read_1_byte (void) |
78 | { | 78 | { |
79 | int c; | 79 | int c; |
80 | 80 | ||
81 | c = NEXTBYTE(); | 81 | c = NEXTBYTE(); |
82 | if (c == EOF) | 82 | if (c == EOF) |
83 | ERREXIT("Premature EOF in JPEG file"); | 83 | ERREXIT("Premature EOF in JPEG file"); |
84 | return c; | 84 | return c; |
85 | } | 85 | } |
86 | 86 | ||
87 | /* Read 2 bytes, convert to unsigned int */ | 87 | /* Read 2 bytes, convert to unsigned int */ |
88 | /* All 2-byte quantities in JPEG markers are MSB first */ | 88 | /* All 2-byte quantities in JPEG markers are MSB first */ |
89 | static unsigned int | 89 | static unsigned int |
90 | read_2_bytes (void) | 90 | read_2_bytes (void) |
91 | { | 91 | { |
92 | int c1, c2; | 92 | int c1, c2; |
93 | 93 | ||
94 | c1 = NEXTBYTE(); | 94 | c1 = NEXTBYTE(); |
95 | if (c1 == EOF) | 95 | if (c1 == EOF) |
96 | ERREXIT("Premature EOF in JPEG file"); | 96 | ERREXIT("Premature EOF in JPEG file"); |
97 | c2 = NEXTBYTE(); | 97 | c2 = NEXTBYTE(); |
98 | if (c2 == EOF) | 98 | if (c2 == EOF) |
99 | ERREXIT("Premature EOF in JPEG file"); | 99 | ERREXIT("Premature EOF in JPEG file"); |
100 | return (((unsigned int) c1) << 8) + ((unsigned int) c2); | 100 | return (((unsigned int) c1) << 8) + ((unsigned int) c2); |
101 | } | 101 | } |
102 | 102 | ||
103 | 103 | ||
104 | /* | 104 | /* |
105 | * JPEG markers consist of one or more 0xFF bytes, followed by a marker | 105 | * JPEG markers consist of one or more 0xFF bytes, followed by a marker |
106 | * code byte (which is not an FF). Here are the marker codes of interest | 106 | * code byte (which is not an FF). Here are the marker codes of interest |
107 | * in this program. (See jdmarker.c for a more complete list.) | 107 | * in this program. (See jdmarker.c for a more complete list.) |
108 | */ | 108 | */ |
109 | 109 | ||
110 | #define M_SOF0 0xC0 /* Start Of Frame N */ | 110 | #define M_SOF0 0xC0 /* Start Of Frame N */ |
111 | #define M_SOF1 0xC1 /* N indicates which compression process */ | 111 | #define M_SOF1 0xC1 /* N indicates which compression process */ |
112 | #define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */ | 112 | #define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */ |
113 | #define M_SOF3 0xC3 | 113 | #define M_SOF3 0xC3 |
114 | #define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */ | 114 | #define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */ |
115 | #define M_SOF6 0xC6 | 115 | #define M_SOF6 0xC6 |
116 | #define M_SOF7 0xC7 | 116 | #define M_SOF7 0xC7 |
117 | #define M_SOF9 0xC9 | 117 | #define M_SOF9 0xC9 |
118 | #define M_SOF10 0xCA | 118 | #define M_SOF10 0xCA |
119 | #define M_SOF11 0xCB | 119 | #define M_SOF11 0xCB |
120 | #define M_SOF13 0xCD | 120 | #define M_SOF13 0xCD |
121 | #define M_SOF14 0xCE | 121 | #define M_SOF14 0xCE |
122 | #define M_SOF15 0xCF | 122 | #define M_SOF15 0xCF |
123 | #define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */ | 123 | #define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */ |
124 | #define M_EOI 0xD9 /* End Of Image (end of datastream) */ | 124 | #define M_EOI 0xD9 /* End Of Image (end of datastream) */ |
125 | #define M_SOS 0xDA /* Start Of Scan (begins compressed data) */ | 125 | #define M_SOS 0xDA /* Start Of Scan (begins compressed data) */ |
126 | #define M_APP0 0xE0 /* Application-specific marker, type N */ | 126 | #define M_APP0 0xE0 /* Application-specific marker, type N */ |
127 | #define M_APP12 0xEC /* (we don't bother to list all 16 APPn's) */ | 127 | #define M_APP12 0xEC /* (we don't bother to list all 16 APPn's) */ |
128 | #define M_COM 0xFE /* COMment */ | 128 | #define M_COM 0xFE /* COMment */ |
129 | 129 | ||
130 | 130 | ||
131 | /* | 131 | /* |
132 | * Find the next JPEG marker and return its marker code. | 132 | * Find the next JPEG marker and return its marker code. |
133 | * We expect at least one FF byte, possibly more if the compressor used FFs | 133 | * We expect at least one FF byte, possibly more if the compressor used FFs |
134 | * to pad the file. | 134 | * to pad the file. |
135 | * There could also be non-FF garbage between markers. The treatment of such | 135 | * There could also be non-FF garbage between markers. The treatment of such |
136 | * garbage is unspecified; we choose to skip over it but emit a warning msg. | 136 | * garbage is unspecified; we choose to skip over it but emit a warning msg. |
137 | * NB: this routine must not be used after seeing SOS marker, since it will | 137 | * NB: this routine must not be used after seeing SOS marker, since it will |
138 | * not deal correctly with FF/00 sequences in the compressed image data... | 138 | * not deal correctly with FF/00 sequences in the compressed image data... |
139 | */ | 139 | */ |
140 | 140 | ||
141 | static int | 141 | static int |
142 | next_marker (void) | 142 | next_marker (void) |
143 | { | 143 | { |
144 | int c; | 144 | int c; |
145 | int discarded_bytes = 0; | 145 | int discarded_bytes = 0; |
146 | 146 | ||
147 | /* Find 0xFF byte; count and skip any non-FFs. */ | 147 | /* Find 0xFF byte; count and skip any non-FFs. */ |
148 | c = read_1_byte(); | 148 | c = read_1_byte(); |
149 | while (c != 0xFF) { | 149 | while (c != 0xFF) { |
150 | discarded_bytes++; | 150 | discarded_bytes++; |
151 | c = read_1_byte(); | 151 | c = read_1_byte(); |
152 | } | 152 | } |
153 | /* Get marker code byte, swallowing any duplicate FF bytes. Extra FFs | 153 | /* Get marker code byte, swallowing any duplicate FF bytes. Extra FFs |
154 | * are legal as pad bytes, so don't count them in discarded_bytes. | 154 | * are legal as pad bytes, so don't count them in discarded_bytes. |
155 | */ | 155 | */ |
156 | do { | 156 | do { |
157 | c = read_1_byte(); | 157 | c = read_1_byte(); |
158 | } while (c == 0xFF); | 158 | } while (c == 0xFF); |
159 | 159 | ||
160 | if (discarded_bytes != 0) { | 160 | if (discarded_bytes != 0) { |
161 | fprintf(stderr, "Warning: garbage data found in JPEG file\n"); | 161 | fprintf(stderr, "Warning: garbage data found in JPEG file\n"); |
162 | } | 162 | } |
163 | 163 | ||
164 | return c; | 164 | return c; |
165 | } | 165 | } |
166 | 166 | ||
167 | 167 | ||
168 | /* | 168 | /* |
169 | * Read the initial marker, which should be SOI. | 169 | * Read the initial marker, which should be SOI. |
170 | * For a JFIF file, the first two bytes of the file should be literally | 170 | * For a JFIF file, the first two bytes of the file should be literally |
171 | * 0xFF M_SOI. To be more general, we could use next_marker, but if the | 171 | * 0xFF M_SOI. To be more general, we could use next_marker, but if the |
172 | * input file weren't actually JPEG at all, next_marker might read the whole | 172 | * input file weren't actually JPEG at all, next_marker might read the whole |
173 | * file and then return a misleading error message... | 173 | * file and then return a misleading error message... |
174 | */ | 174 | */ |
175 | 175 | ||
176 | static int | 176 | static int |
177 | first_marker (void) | 177 | first_marker (void) |
178 | { | 178 | { |
179 | int c1, c2; | 179 | int c1, c2; |
180 | 180 | ||
181 | c1 = NEXTBYTE(); | 181 | c1 = NEXTBYTE(); |
182 | c2 = NEXTBYTE(); | 182 | c2 = NEXTBYTE(); |
183 | if (c1 != 0xFF || c2 != M_SOI) | 183 | if (c1 != 0xFF || c2 != M_SOI) |
184 | ERREXIT("Not a JPEG file"); | 184 | ERREXIT("Not a JPEG file"); |
185 | return c2; | 185 | return c2; |
186 | } | 186 | } |
187 | 187 | ||
188 | 188 | ||
189 | /* | 189 | /* |
190 | * Most types of marker are followed by a variable-length parameter segment. | 190 | * Most types of marker are followed by a variable-length parameter segment. |
191 | * This routine skips over the parameters for any marker we don't otherwise | 191 | * This routine skips over the parameters for any marker we don't otherwise |
192 | * want to process. | 192 | * want to process. |
193 | * Note that we MUST skip the parameter segment explicitly in order not to | 193 | * Note that we MUST skip the parameter segment explicitly in order not to |
194 | * be fooled by 0xFF bytes that might appear within the parameter segment; | 194 | * be fooled by 0xFF bytes that might appear within the parameter segment; |
195 | * such bytes do NOT introduce new markers. | 195 | * such bytes do NOT introduce new markers. |
196 | */ | 196 | */ |
197 | 197 | ||
198 | static void | 198 | static void |
199 | skip_variable (void) | 199 | skip_variable (void) |
200 | /* Skip over an unknown or uninteresting variable-length marker */ | 200 | /* Skip over an unknown or uninteresting variable-length marker */ |
201 | { | 201 | { |
202 | unsigned int length; | 202 | unsigned int length; |
203 | 203 | ||
204 | /* Get the marker parameter length count */ | 204 | /* Get the marker parameter length count */ |
205 | length = read_2_bytes(); | 205 | length = read_2_bytes(); |
206 | /* Length includes itself, so must be at least 2 */ | 206 | /* Length includes itself, so must be at least 2 */ |
207 | if (length < 2) | 207 | if (length < 2) |
208 | ERREXIT("Erroneous JPEG marker length"); | 208 | ERREXIT("Erroneous JPEG marker length"); |
209 | length -= 2; | 209 | length -= 2; |
210 | /* Skip over the remaining bytes */ | 210 | /* Skip over the remaining bytes */ |
211 | while (length > 0) { | 211 | while (length > 0) { |
212 | (void) read_1_byte(); | 212 | (void) read_1_byte(); |
213 | length--; | 213 | length--; |
214 | } | 214 | } |
215 | } | 215 | } |
216 | 216 | ||
217 | 217 | ||
218 | /* | 218 | /* |
219 | * Process a COM marker. | 219 | * Process a COM marker. |
220 | * We want to print out the marker contents as legible text; | 220 | * We want to print out the marker contents as legible text; |
221 | * we must guard against non-text junk and varying newline representations. | 221 | * we must guard against non-text junk and varying newline representations. |
222 | */ | 222 | */ |
223 | 223 | ||
224 | static void | 224 | static void |
225 | process_COM (int raw) | 225 | process_COM (int raw) |
226 | { | 226 | { |
227 | unsigned int length; | 227 | unsigned int length; |
228 | int ch; | 228 | int ch; |
229 | int lastch = 0; | 229 | int lastch = 0; |
230 | 230 | ||
231 | /* Bill Allombert: set locale properly for isprint */ | 231 | /* Bill Allombert: set locale properly for isprint */ |
232 | #ifdef HAVE_LOCALE_H | 232 | #ifdef HAVE_LOCALE_H |
233 | setlocale(LC_CTYPE, ""); | 233 | setlocale(LC_CTYPE, ""); |
234 | #endif | 234 | #endif |
235 | 235 | ||
236 | /* Get the marker parameter length count */ | 236 | /* Get the marker parameter length count */ |
237 | length = read_2_bytes(); | 237 | length = read_2_bytes(); |
238 | /* Length includes itself, so must be at least 2 */ | 238 | /* Length includes itself, so must be at least 2 */ |
239 | if (length < 2) | 239 | if (length < 2) |
240 | ERREXIT("Erroneous JPEG marker length"); | 240 | ERREXIT("Erroneous JPEG marker length"); |
241 | length -= 2; | 241 | length -= 2; |
242 | 242 | ||
243 | while (length > 0) { | 243 | while (length > 0) { |
244 | ch = read_1_byte(); | 244 | ch = read_1_byte(); |
245 | if (raw) { | 245 | if (raw) { |
246 | putc(ch, stdout); | 246 | putc(ch, stdout); |
247 | /* Emit the character in a readable form. | 247 | /* Emit the character in a readable form. |
248 | * Nonprintables are converted to \nnn form, | 248 | * Nonprintables are converted to \nnn form, |
249 | * while \ is converted to \\. | 249 | * while \ is converted to \\. |
250 | * 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. |
251 | */ | 251 | */ |
252 | } else if (ch == '\r') { | 252 | } else if (ch == '\r') { |
253 | printf("\n"); | 253 | printf("\n"); |
254 | } else if (ch == '\n') { | 254 | } else if (ch == '\n') { |
255 | if (lastch != '\r') | 255 | if (lastch != '\r') |
256 | printf("\n"); | 256 | printf("\n"); |
257 | } else if (ch == '\\') { | 257 | } else if (ch == '\\') { |
258 | printf("\\\\"); | 258 | printf("\\\\"); |
259 | } else if (isprint(ch)) { | 259 | } else if (isprint(ch)) { |
260 | putc(ch, stdout); | 260 | putc(ch, stdout); |
261 | } else { | 261 | } else { |
262 | printf("\\%03o", ch); | 262 | printf("\\%03o", ch); |
263 | } | 263 | } |
264 | lastch = ch; | 264 | lastch = ch; |
265 | length--; | 265 | length--; |
266 | } | 266 | } |
267 | printf("\n"); | 267 | printf("\n"); |
268 | 268 | ||
269 | /* Bill Allombert: revert to C locale */ | 269 | /* Bill Allombert: revert to C locale */ |
270 | #ifdef HAVE_LOCALE_H | 270 | #ifdef HAVE_LOCALE_H |
271 | setlocale(LC_CTYPE, "C"); | 271 | setlocale(LC_CTYPE, "C"); |
272 | #endif | 272 | #endif |
273 | } | 273 | } |
274 | 274 | ||
275 | 275 | ||
276 | /* | 276 | /* |
277 | * Process a SOFn marker. | 277 | * Process a SOFn marker. |
278 | * 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... |
279 | */ | 279 | */ |
280 | 280 | ||
281 | static void | 281 | static void |
282 | process_SOFn (int marker) | 282 | process_SOFn (int marker) |
283 | { | 283 | { |
284 | unsigned int length; | 284 | unsigned int length; |
285 | unsigned int image_height, image_width; | 285 | unsigned int image_height, image_width; |
286 | int data_precision, num_components; | 286 | int data_precision, num_components; |
287 | const char * process; | 287 | const char * process; |
288 | int ci; | 288 | int ci; |
289 | 289 | ||
290 | length = read_2_bytes(); /* usual parameter length count */ | 290 | length = read_2_bytes(); /* usual parameter length count */ |
291 | 291 | ||
292 | data_precision = read_1_byte(); | 292 | data_precision = read_1_byte(); |
293 | image_height = read_2_bytes(); | 293 | image_height = read_2_bytes(); |
294 | image_width = read_2_bytes(); | 294 | image_width = read_2_bytes(); |
295 | num_components = read_1_byte(); | 295 | num_components = read_1_byte(); |
296 | 296 | ||
297 | switch (marker) { | 297 | switch (marker) { |
298 | case M_SOF0: process = "Baseline"; break; | 298 | case M_SOF0: process = "Baseline"; break; |
299 | case M_SOF1: process = "Extended sequential"; break; | 299 | case M_SOF1: process = "Extended sequential"; break; |
300 | case M_SOF2: process = "Progressive"; break; | 300 | case M_SOF2: process = "Progressive"; break; |
301 | case M_SOF3: process = "Lossless"; break; | 301 | case M_SOF3: process = "Lossless"; break; |
302 | case M_SOF5: process = "Differential sequential"; break; | 302 | case M_SOF5: process = "Differential sequential"; break; |
303 | case M_SOF6: process = "Differential progressive"; break; | 303 | case M_SOF6: process = "Differential progressive"; break; |
304 | case M_SOF7: process = "Differential lossless"; break; | 304 | case M_SOF7: process = "Differential lossless"; break; |
305 | case M_SOF9: process = "Extended sequential, arithmetic coding"; break; | 305 | case M_SOF9: process = "Extended sequential, arithmetic coding"; break; |
306 | case M_SOF10: process = "Progressive, arithmetic coding"; break; | 306 | case M_SOF10: process = "Progressive, arithmetic coding"; break; |
307 | case M_SOF11: process = "Lossless, arithmetic coding"; break; | 307 | case M_SOF11: process = "Lossless, arithmetic coding"; break; |
308 | case M_SOF13: process = "Differential sequential, arithmetic coding"; break; | 308 | case M_SOF13: process = "Differential sequential, arithmetic coding"; break; |
309 | case M_SOF14: process = "Differential progressive, arithmetic coding"; break; | 309 | case M_SOF14: process = "Differential progressive, arithmetic coding"; break; |
310 | case M_SOF15: process = "Differential lossless, arithmetic coding"; break; | 310 | case M_SOF15: process = "Differential lossless, arithmetic coding"; break; |
311 | default: process = "Unknown"; break; | 311 | default: process = "Unknown"; break; |
312 | } | 312 | } |
313 | 313 | ||
314 | printf("JPEG image is %uw * %uh, %d color components, %d bits per sample\n", | 314 | printf("JPEG image is %uw * %uh, %d color components, %d bits per sample\n", |
315 | image_width, image_height, num_components, data_precision); | 315 | image_width, image_height, num_components, data_precision); |
316 | printf("JPEG process: %s\n", process); | 316 | printf("JPEG process: %s\n", process); |
317 | 317 | ||
318 | if (length != (unsigned int) (8 + num_components * 3)) | 318 | if (length != (unsigned int) (8 + num_components * 3)) |
319 | ERREXIT("Bogus SOF marker length"); | 319 | ERREXIT("Bogus SOF marker length"); |
320 | 320 | ||
321 | for (ci = 0; ci < num_components; ci++) { | 321 | for (ci = 0; ci < num_components; ci++) { |
322 | (void) read_1_byte(); /* Component ID code */ | 322 | (void) read_1_byte(); /* Component ID code */ |
323 | (void) read_1_byte(); /* H, V sampling factors */ | 323 | (void) read_1_byte(); /* H, V sampling factors */ |
324 | (void) read_1_byte(); /* Quantization table number */ | 324 | (void) read_1_byte(); /* Quantization table number */ |
325 | } | 325 | } |
326 | } | 326 | } |
327 | 327 | ||
328 | 328 | ||
329 | /* | 329 | /* |
330 | * Parse the marker stream until SOS or EOI is seen; | 330 | * Parse the marker stream until SOS or EOI is seen; |
331 | * display any COM markers. | 331 | * display any COM markers. |
332 | * While the companion program wrjpgcom will always insert COM markers before | 332 | * While the companion program wrjpgcom will always insert COM markers before |
333 | * 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. |
334 | * 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. |
335 | * (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 |
336 | * 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.) |
337 | */ | 337 | */ |
338 | 338 | ||
339 | static int | 339 | static int |
340 | scan_JPEG_header (int verbose, int raw) | 340 | scan_JPEG_header (int verbose, int raw) |
341 | { | 341 | { |
342 | int marker; | 342 | int marker; |
343 | 343 | ||
344 | /* Expect SOI at start of file */ | 344 | /* Expect SOI at start of file */ |
345 | if (first_marker() != M_SOI) | 345 | if (first_marker() != M_SOI) |
346 | ERREXIT("Expected SOI marker first"); | 346 | ERREXIT("Expected SOI marker first"); |
347 | 347 | ||
348 | /* Scan miscellaneous markers until we reach SOS. */ | 348 | /* Scan miscellaneous markers until we reach SOS. */ |
349 | for (;;) { | 349 | for (;;) { |
350 | marker = next_marker(); | 350 | marker = next_marker(); |
351 | switch (marker) { | 351 | switch (marker) { |
352 | /* Note that marker codes 0xC4, 0xC8, 0xCC are not, and must not be, | 352 | /* Note that marker codes 0xC4, 0xC8, 0xCC are not, and must not be, |
353 | * treated as SOFn. C4 in particular is actually DHT. | 353 | * treated as SOFn. C4 in particular is actually DHT. |
354 | */ | 354 | */ |
355 | case M_SOF0: /* Baseline */ | 355 | case M_SOF0: /* Baseline */ |
356 | case M_SOF1: /* Extended sequential, Huffman */ | 356 | case M_SOF1: /* Extended sequential, Huffman */ |
357 | case M_SOF2: /* Progressive, Huffman */ | 357 | case M_SOF2: /* Progressive, Huffman */ |
358 | case M_SOF3: /* Lossless, Huffman */ | 358 | case M_SOF3: /* Lossless, Huffman */ |
359 | case M_SOF5: /* Differential sequential, Huffman */ | 359 | case M_SOF5: /* Differential sequential, Huffman */ |
360 | case M_SOF6: /* Differential progressive, Huffman */ | 360 | case M_SOF6: /* Differential progressive, Huffman */ |
361 | case M_SOF7: /* Differential lossless, Huffman */ | 361 | case M_SOF7: /* Differential lossless, Huffman */ |
362 | case M_SOF9: /* Extended sequential, arithmetic */ | 362 | case M_SOF9: /* Extended sequential, arithmetic */ |
363 | case M_SOF10: /* Progressive, arithmetic */ | 363 | case M_SOF10: /* Progressive, arithmetic */ |
364 | case M_SOF11: /* Lossless, arithmetic */ | 364 | case M_SOF11: /* Lossless, arithmetic */ |
365 | case M_SOF13: /* Differential sequential, arithmetic */ | 365 | case M_SOF13: /* Differential sequential, arithmetic */ |
366 | case M_SOF14: /* Differential progressive, arithmetic */ | 366 | case M_SOF14: /* Differential progressive, arithmetic */ |
367 | case M_SOF15: /* Differential lossless, arithmetic */ | 367 | case M_SOF15: /* Differential lossless, arithmetic */ |
368 | if (verbose) | 368 | if (verbose) |
369 | process_SOFn(marker); | 369 | process_SOFn(marker); |
370 | else | 370 | else |
371 | skip_variable(); | 371 | skip_variable(); |
372 | break; | 372 | break; |
373 | 373 | ||
374 | case M_SOS: /* stop before hitting compressed data */ | 374 | case M_SOS: /* stop before hitting compressed data */ |
375 | return marker; | 375 | return marker; |
376 | 376 | ||
377 | 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 */ |
378 | return marker; | 378 | return marker; |
379 | 379 | ||
380 | case M_COM: | 380 | case M_COM: |
381 | process_COM(raw); | 381 | process_COM(raw); |
382 | break; | 382 | break; |
383 | 383 | ||
384 | case M_APP12: | 384 | case M_APP12: |
385 | /* Some digital camera makers put useful textual information into | 385 | /* Some digital camera makers put useful textual information into |
386 | * 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. |
387 | */ | 387 | */ |
388 | if (verbose) { | 388 | if (verbose) { |
389 | printf("APP12 contains:\n"); | 389 | printf("APP12 contains:\n"); |
390 | process_COM(raw); | 390 | process_COM(raw); |
391 | } else | 391 | } else |
392 | skip_variable(); | 392 | skip_variable(); |
393 | break; | 393 | break; |
394 | 394 | ||
395 | default: /* Anything else just gets skipped */ | 395 | default: /* Anything else just gets skipped */ |
396 | skip_variable(); /* we assume it has a parameter count... */ | 396 | skip_variable(); /* we assume it has a parameter count... */ |
397 | break; | 397 | break; |
398 | } | 398 | } |
399 | } /* end loop */ | 399 | } /* end loop */ |
400 | } | 400 | } |
401 | 401 | ||
402 | 402 | ||
403 | /* Command line parsing code */ | 403 | /* Command line parsing code */ |
404 | 404 | ||
405 | static const char * progname; /* program name for error messages */ | 405 | static const char * progname; /* program name for error messages */ |
406 | 406 | ||
407 | 407 | ||
408 | static void | 408 | static void |
409 | usage (void) | 409 | usage (void) |
410 | /* complain about bad command line */ | 410 | /* complain about bad command line */ |
411 | { | 411 | { |
412 | 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"); |
413 | 413 | ||
414 | fprintf(stderr, "Usage: %s [switches] [inputfile]\n", progname); | 414 | fprintf(stderr, "Usage: %s [switches] [inputfile]\n", progname); |
415 | 415 | ||
416 | 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 (unsafe)\n"); | 417 | fprintf(stderr, " -raw Display non-printable characters in comments (unsafe)\n"); |
418 | fprintf(stderr, " -verbose Also display dimensions of JPEG image\n"); | 418 | fprintf(stderr, " -verbose Also display dimensions of JPEG image\n"); |
419 | 419 | ||
420 | exit(EXIT_FAILURE); | 420 | exit(EXIT_FAILURE); |
421 | } | 421 | } |
422 | 422 | ||
423 | 423 | ||
424 | static int | 424 | static int |
425 | keymatch (char * arg, const char * keyword, int minchars) | 425 | keymatch (char * arg, const char * keyword, int minchars) |
426 | /* Case-insensitive matching of (possibly abbreviated) keyword switches. */ | 426 | /* Case-insensitive matching of (possibly abbreviated) keyword switches. */ |
427 | /* keyword is the constant keyword (must be lower case already), */ | 427 | /* keyword is the constant keyword (must be lower case already), */ |
428 | /* minchars is length of minimum legal abbreviation. */ | 428 | /* minchars is length of minimum legal abbreviation. */ |
429 | { | 429 | { |
430 | register int ca, ck; | 430 | register int ca, ck; |
431 | register int nmatched = 0; | 431 | register int nmatched = 0; |
432 | 432 | ||
433 | while ((ca = *arg++) != '\0') { | 433 | while ((ca = *arg++) != '\0') { |
434 | if ((ck = *keyword++) == '\0') | 434 | if ((ck = *keyword++) == '\0') |
435 | return 0; /* arg longer than keyword, no good */ | 435 | return 0; /* arg longer than keyword, no good */ |
436 | if (isupper(ca)) /* force arg to lcase (assume ck is already) */ | 436 | if (isupper(ca)) /* force arg to lcase (assume ck is already) */ |
437 | ca = tolower(ca); | 437 | ca = tolower(ca); |
438 | if (ca != ck) | 438 | if (ca != ck) |
439 | return 0; /* no good */ | 439 | return 0; /* no good */ |
440 | nmatched++; /* count matched characters */ | 440 | nmatched++; /* count matched characters */ |
441 | } | 441 | } |
442 | /* reached end of argument; fail if it's too short for unique abbrev */ | 442 | /* reached end of argument; fail if it's too short for unique abbrev */ |
443 | if (nmatched < minchars) | 443 | if (nmatched < minchars) |
444 | return 0; | 444 | return 0; |
445 | return 1; /* A-OK */ | 445 | return 1; /* A-OK */ |
446 | } | 446 | } |
447 | 447 | ||
448 | 448 | ||
449 | /* | 449 | /* |
450 | * The main program. | 450 | * The main program. |
451 | */ | 451 | */ |
452 | 452 | ||
453 | int | 453 | int |
454 | main (int argc, char **argv) | 454 | main (int argc, char **argv) |
455 | { | 455 | { |
456 | int argn; | 456 | int argn; |
457 | char * arg; | 457 | char * arg; |
458 | int verbose = 0, raw = 0; | 458 | int verbose = 0, raw = 0; |
459 | 459 | ||
460 | /* On Mac, fetch a command line. */ | 460 | /* On Mac, fetch a command line. */ |
461 | #ifdef USE_CCOMMAND | 461 | #ifdef USE_CCOMMAND |
462 | argc = ccommand(&argv); | 462 | argc = ccommand(&argv); |
463 | #endif | 463 | #endif |
464 | 464 | ||
465 | progname = argv[0]; | 465 | progname = argv[0]; |
466 | if (progname == NULL || progname[0] == 0) | 466 | if (progname == NULL || progname[0] == 0) |
467 | progname = "rdjpgcom"; /* in case C library doesn't provide it */ | 467 | progname = "rdjpgcom"; /* in case C library doesn't provide it */ |
468 | 468 | ||
469 | /* Parse switches, if any */ | 469 | /* Parse switches, if any */ |
470 | for (argn = 1; argn < argc; argn++) { | 470 | for (argn = 1; argn < argc; argn++) { |
471 | arg = argv[argn]; | 471 | arg = argv[argn]; |
472 | if (arg[0] != '-') | 472 | if (arg[0] != '-') |
473 | break; /* not switch, must be file name */ | 473 | break; /* not switch, must be file name */ |
474 | arg++; /* advance over '-' */ | 474 | arg++; /* advance over '-' */ |
475 | if (keymatch(arg, "verbose", 1)) { | 475 | if (keymatch(arg, "verbose", 1)) { |
476 | verbose++; | 476 | verbose++; |
477 | } else if (keymatch(arg, "raw", 1)) { | 477 | } else if (keymatch(arg, "raw", 1)) { |
478 | raw = 1; | 478 | raw = 1; |
479 | } else | 479 | } else |
480 | usage(); | 480 | usage(); |
481 | } | 481 | } |
482 | 482 | ||
483 | /* Open the input file. */ | 483 | /* Open the input file. */ |
484 | /* Unix style: expect zero or one file name */ | 484 | /* Unix style: expect zero or one file name */ |
485 | if (argn < argc-1) { | 485 | if (argn < argc-1) { |
486 | fprintf(stderr, "%s: only one input file\n", progname); | 486 | fprintf(stderr, "%s: only one input file\n", progname); |
487 | usage(); | 487 | usage(); |
488 | } | 488 | } |
489 | if (argn < argc) { | 489 | if (argn < argc) { |
490 | if ((infile = fopen(argv[argn], READ_BINARY)) == NULL) { | 490 | if ((infile = fopen(argv[argn], READ_BINARY)) == NULL) { |
491 | fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]); | 491 | fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]); |
492 | exit(EXIT_FAILURE); | 492 | exit(EXIT_FAILURE); |
493 | } | 493 | } |
494 | } else { | 494 | } else { |
495 | /* default input file is stdin */ | 495 | /* default input file is stdin */ |
496 | #ifdef USE_SETMODE /* need to hack file mode? */ | 496 | #ifdef USE_SETMODE /* need to hack file mode? */ |
497 | setmode(fileno(stdin), O_BINARY); | 497 | setmode(fileno(stdin), O_BINARY); |
498 | #endif | 498 | #endif |
499 | #ifdef USE_FDOPEN /* need to re-open in binary mode? */ | 499 | #ifdef USE_FDOPEN /* need to re-open in binary mode? */ |
500 | if ((infile = fdopen(fileno(stdin), READ_BINARY)) == NULL) { | 500 | if ((infile = fdopen(fileno(stdin), READ_BINARY)) == NULL) { |
501 | fprintf(stderr, "%s: can't open stdin\n", progname); | 501 | fprintf(stderr, "%s: can't open stdin\n", progname); |
502 | exit(EXIT_FAILURE); | 502 | exit(EXIT_FAILURE); |
503 | } | 503 | } |
504 | #else | 504 | #else |
505 | infile = stdin; | 505 | infile = stdin; |
506 | #endif | 506 | #endif |
507 | } | 507 | } |
508 | 508 | ||
509 | /* Scan the JPEG headers. */ | 509 | /* Scan the JPEG headers. */ |
510 | (void) scan_JPEG_header(verbose, raw); | 510 | (void) scan_JPEG_header(verbose, raw); |
511 | 511 | ||
512 | /* All done. */ | 512 | /* All done. */ |
513 | exit(EXIT_SUCCESS); | 513 | exit(EXIT_SUCCESS); |
514 | return 0; /* suppress no-return-value warnings */ | 514 | return 0; /* suppress no-return-value warnings */ |
515 | } | 515 | } |