jpegdump.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. /* jpeg parser by tom szymanski */
  2. #include <stddef.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <math.h>
  7. #include <ctype.h>
  8. /* subroutines done by macros */
  9. #define min(A,B) ((A)<(B) ? (A) : (B))
  10. #define max(A,B) ((A)>(B) ? (A) : (B))
  11. #define maxeql(A,B) if (A < (B)) A = (B);
  12. #define mineql(A,B) if (A > (B)) A = (B);
  13. #define eatarg0 (argc--, argv++)
  14. #define arrayLength(A) ((sizeof A)/ (sizeof A[0]))
  15. FILE *infile;
  16. char *fname;
  17. /* Routines to print error messages of varying severity */
  18. /* externally visible variables */
  19. int warncnt;
  20. char *myname;
  21. void getname (char *arg) {
  22. /* Save name of invoking program for use by error routines */
  23. register char *p;
  24. p = strrchr (arg, '/');
  25. if (p == NULL)
  26. myname = arg;
  27. else
  28. myname = ++p;
  29. }
  30. static void introduction (void) {
  31. warncnt++;
  32. fflush (stdout);
  33. if (myname != NULL)
  34. fprintf (stderr, "%s: ", myname);
  35. }
  36. void warn (char *fmt, ...) {
  37. va_list args;
  38. introduction ();
  39. va_start (args, fmt);
  40. vfprintf (stderr, fmt, args);
  41. va_end (args);
  42. fputc ('\n', stderr);
  43. fflush (stderr);
  44. }
  45. void quit (char *fmt, ...) {
  46. va_list args;
  47. introduction ();
  48. va_start (args, fmt);
  49. vfprintf (stderr, fmt, args);
  50. va_end (args);
  51. fputc ('\n', stderr);
  52. fflush (stderr);
  53. exit (1);
  54. }
  55. void fatal (char *fmt, ...) {
  56. va_list args;
  57. introduction ();
  58. va_start (args, fmt);
  59. vfprintf (stderr, fmt, args);
  60. va_end (args);
  61. fprintf (stderr, "\nbetter get help!\n");
  62. fflush (stderr);
  63. abort ();
  64. }
  65. int toption = 0;
  66. int dqt[16][64];
  67. int get1 (void) {
  68. unsigned char x;
  69. if (fread(&x, 1, 1, infile) == 0)
  70. quit ("unexpected EOF");
  71. return x;
  72. }
  73. int get2 (void) {
  74. int x;
  75. x = get1() << 8;
  76. return x | get1();
  77. }
  78. void eatmarker (int kind) {
  79. int l, c;
  80. l = get2();
  81. printf ("%02x len=%d\n", kind, l);
  82. for (l -= 2; l > 0; l--)
  83. get1();
  84. }
  85. char *sofName[16] = {
  86. "Baseline sequential DCT - Huffman coding",
  87. "Extended sequential DCT - Huffman coding",
  88. "Progressive DCT - Huffman coding",
  89. "Lossless - Huffman coding",
  90. "4 is otherwise used",
  91. "Sequential DCT - differential Huffman coding",
  92. "Progressive DCT - differential Huffman coding",
  93. "Lossless - differential Huffman coding",
  94. "8 is reserved",
  95. "Extended Sequential DCT - arithmetic coding",
  96. "Progressive DCT - arithmetic coding",
  97. "Lossless - arithmetic coding",
  98. "c is otherwise used",
  99. "Sequential DCT - differential arithmetic coding",
  100. "Progressive DCT - differential arithmetic coding",
  101. "Lossless - differential arithmetic coding",
  102. };
  103. void get_sof (int kind) {
  104. int i, length, height, width, precision, ncomponents;
  105. int id, sf, tab;
  106. length = get2();
  107. precision = get1();
  108. height = get2();
  109. width = get2();
  110. ncomponents = get1();
  111. printf ("SOF%d:\t%s\n", kind - 0xc0, sofName[kind - 0xc0]);
  112. printf ("\t%d wide, %d high, %d deep, %d components\n",
  113. width, height, precision, ncomponents);
  114. for (i = 0; i < ncomponents; i++) {
  115. id = get1();
  116. sf = get1();
  117. tab = get1();
  118. printf ("\tcomponent %d: %d hsample, %d vsample, quantization table %d\n",
  119. id, sf >> 4, sf & 0xf, tab);
  120. }
  121. }
  122. void get_com (int kind) {
  123. int l, c;
  124. l = get2();
  125. printf ("COM len=%d '", l);
  126. for (l -= 2; l > 0; l--)
  127. putchar (c = get1());
  128. printf ("'\n");
  129. }
  130. void get_app (int kind) {
  131. int l, c, first;
  132. char buf[6];
  133. int nbuf, nok;
  134. l = get2();
  135. printf ("APP%d len=%d\n", kind - 0xe0, l);
  136. nbuf = 0;
  137. nok = 0;
  138. first = 1;
  139. /* dump printable strings in comment */
  140. for (l -= 2; l > 0; l--){
  141. c = get1();
  142. if(isprint(c)){
  143. if(nbuf >= sizeof buf){
  144. if(!first && nbuf == nok)
  145. printf(" ");
  146. printf("%.*s", nbuf, buf);
  147. nbuf = 0;
  148. first = 0;
  149. }
  150. buf[nbuf++] = c;
  151. nok++;
  152. }else{
  153. if(nok >= sizeof buf)
  154. if(nbuf > 0)
  155. printf("%.*s", nbuf, buf);
  156. nbuf = 0;
  157. nok = 0;
  158. }
  159. }
  160. if(nok >= sizeof buf)
  161. if(nbuf > 0){
  162. if(!first && nbuf == nok)
  163. printf(" ");
  164. printf("%.*s", nbuf, buf);
  165. }
  166. }
  167. void get_dac (int kind) {
  168. eatmarker (kind);
  169. }
  170. int get1dqt (void) {
  171. int t, p, i, *tab;
  172. t = get1();
  173. p = t >> 4;
  174. t = t & 0xf;
  175. printf ("DQT:\tp = %d, table = %d\n", p, t);
  176. tab = &dqt[t][0];
  177. for (i = 0; i < 64; i++)
  178. tab[i] = p ? get2() : get1();
  179. if (toption) {
  180. for (i = 0; i < 64; i++)
  181. printf ("\t%q[%02d] = %d\n", i, tab[i]);
  182. }
  183. return p ? 65 : 129;
  184. }
  185. void get_dqt (int kind) {
  186. int length;
  187. length = get2() - 2;
  188. while (length > 0)
  189. length -= get1dqt();
  190. }
  191. int get1dht (void) {
  192. int l, tcth, p, i, j, v[16], vv[16][256];
  193. tcth = get1();
  194. printf ("DHT:\tclass = %d, table = %d\n", tcth >> 4, tcth & 0xf);
  195. for (i = 0; i < 16; i++)
  196. v[i] = get1();
  197. l = 17;
  198. for (i = 0; i < 16; i++)
  199. for (j = 0; j < v[i]; j++) {
  200. vv[i][j] = get1();
  201. l += 1;
  202. }
  203. if (toption) {
  204. for (i = 0; i < 16; i++)
  205. printf ("\t%l[%02d] = %d\n", i+1, v[i]);
  206. for (i = 0; i < 16; i++)
  207. for (j = 0; j < v[i]; j++)
  208. printf ("\t%v[%02d,%02d] = %d\n", i+1, j+1, vv[i][j]);
  209. }
  210. return l;
  211. }
  212. void get_dht (int kind) {
  213. int length;
  214. length = get2() - 2;
  215. while (length > 0)
  216. length -= get1dht();
  217. }
  218. void get_sos (int kind) {
  219. int i, length, ncomponents, id, dcac, ahal;
  220. length = get2();
  221. ncomponents = get1();
  222. printf ("SOS:\t%d components\n", ncomponents);
  223. for (i = 0; i < ncomponents; i++) {
  224. id = get1();
  225. dcac = get1();
  226. printf ("\tcomponent %d: %d DC, %d AC\n", id, dcac >> 4, dcac & 0xf);
  227. }
  228. printf ("\tstart spectral %d\n", get1());
  229. printf ("\tend spectral %d\n", get1());
  230. ahal = get1();
  231. printf ("\tah = %d, al = %d\n", ahal >> 4, ahal &0xf);
  232. }
  233. main (int argc, char *argv[]) {
  234. int l, stuff, i, j, c;
  235. while (argc > 1 && argv[1][0] == '-') {
  236. switch (argv[1][1]) {
  237. case 't':
  238. toption = 1;
  239. break;
  240. default:
  241. warn ("bad option '%c'", argv[1][1]);
  242. }
  243. eatarg0;
  244. }
  245. fname = argv[1];
  246. infile = fopen (fname, "r");
  247. if (infile == NULL)
  248. quit ("can't open %s\n", fname);
  249. Start:
  250. // if (get1() != 0xff || get1() != 0xd8)
  251. // quit ("not JFIF");
  252. // printf ("SOI\n");
  253. // get_app (0xe0);
  254. for (;;) {
  255. c = get1();
  256. if (c != 0xff)
  257. quit ("expected marker, got %2x", c);
  258. do {
  259. c = get1();
  260. } while (c == 0xff);
  261. marker:
  262. switch (c) {
  263. case 0xc0: case 0xc1: case 0xc2: case 0xc3:
  264. case 0xc5: case 0xc6: case 0xc7:
  265. case 0xc8: case 0xc9: case 0xca: case 0xcb:
  266. case 0xcd: case 0xce: case 0xcf:
  267. get_sof (c);
  268. break;
  269. case 0xc4:
  270. get_dht (c);
  271. break;
  272. case 0xcc:
  273. get_dac (c);
  274. break;
  275. case 0xd8:
  276. printf ("SOI\n");
  277. break;
  278. case 0xe0: case 0xe1: case 0xe2: case 0xe3:
  279. case 0xe4: case 0xe5: case 0xe6: case 0xe7:
  280. case 0xe8: case 0xe9: case 0xea: case 0xeb:
  281. case 0xec: case 0xed: case 0xee: case 0xef:
  282. get_app(c);
  283. break;
  284. case 0xda:
  285. get_sos (c);
  286. goto newentropy;
  287. case 0xdb:
  288. get_dqt (c);
  289. break;
  290. case 0xfe:
  291. get_com (c);
  292. break;
  293. case 0xd9:
  294. printf ("EOI\n");
  295. if((c=getc(infile)) == EOF)
  296. exit(0);
  297. ungetc(c, infile);
  298. goto Start;
  299. default:
  300. eatmarker (c);
  301. }
  302. continue;
  303. newentropy:
  304. l = stuff = 0;
  305. entropy:
  306. while ((c = get1()) != 0xff)
  307. l += 1;
  308. while (c == 0xff)
  309. c = get1();
  310. if (c == 0) {
  311. stuff += 1;
  312. goto entropy;
  313. }
  314. printf ("sequence length %d with %d stuffs\n", l, stuff);
  315. if (0xd0 <= c && c <= 0xd7) {
  316. printf ("restart %d\n", c - 0xd0);
  317. goto newentropy;
  318. }
  319. goto marker;
  320. }
  321. }