Why not?
This commit is contained in:
parent
a01e58366c
commit
28994509cc
82 changed files with 13293 additions and 0 deletions
346
src/cmd/jpg/jpegdump.c
Normal file
346
src/cmd/jpg/jpegdump.c
Normal file
|
|
@ -0,0 +1,346 @@
|
|||
/* jpeg parser by tom szymanski */
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* subroutines done by macros */
|
||||
#define min(A,B) ((A)<(B) ? (A) : (B))
|
||||
#define max(A,B) ((A)>(B) ? (A) : (B))
|
||||
#define maxeql(A,B) if (A < (B)) A = (B);
|
||||
#define mineql(A,B) if (A > (B)) A = (B);
|
||||
#define eatarg0 (argc--, argv++)
|
||||
#define arrayLength(A) ((sizeof A)/ (sizeof A[0]))
|
||||
|
||||
FILE *infile;
|
||||
char *fname;
|
||||
|
||||
/* Routines to print error messages of varying severity */
|
||||
|
||||
/* externally visible variables */
|
||||
int warncnt;
|
||||
char *myname;
|
||||
|
||||
void getname (char *arg) {
|
||||
/* Save name of invoking program for use by error routines */
|
||||
register char *p;
|
||||
p = strrchr (arg, '/');
|
||||
if (p == NULL)
|
||||
myname = arg;
|
||||
else
|
||||
myname = ++p;
|
||||
}
|
||||
|
||||
static void introduction (void) {
|
||||
warncnt++;
|
||||
fflush (stdout);
|
||||
if (myname != NULL)
|
||||
fprintf (stderr, "%s: ", myname);
|
||||
}
|
||||
|
||||
void warn (char *fmt, ...) {
|
||||
va_list args;
|
||||
introduction ();
|
||||
va_start (args, fmt);
|
||||
vfprintf (stderr, fmt, args);
|
||||
va_end (args);
|
||||
fputc ('\n', stderr);
|
||||
fflush (stderr);
|
||||
}
|
||||
|
||||
void quit (char *fmt, ...) {
|
||||
va_list args;
|
||||
introduction ();
|
||||
va_start (args, fmt);
|
||||
vfprintf (stderr, fmt, args);
|
||||
va_end (args);
|
||||
fputc ('\n', stderr);
|
||||
fflush (stderr);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
void fatal (char *fmt, ...) {
|
||||
va_list args;
|
||||
introduction ();
|
||||
va_start (args, fmt);
|
||||
vfprintf (stderr, fmt, args);
|
||||
va_end (args);
|
||||
fprintf (stderr, "\nbetter get help!\n");
|
||||
fflush (stderr);
|
||||
abort ();
|
||||
}
|
||||
|
||||
int toption = 0;
|
||||
int dqt[16][64];
|
||||
|
||||
int get1 (void) {
|
||||
unsigned char x;
|
||||
if (fread(&x, 1, 1, infile) == 0)
|
||||
quit ("unexpected EOF");
|
||||
return x;
|
||||
}
|
||||
|
||||
int get2 (void) {
|
||||
int x;
|
||||
|
||||
x = get1() << 8;
|
||||
return x | get1();
|
||||
}
|
||||
|
||||
void eatmarker (int kind) {
|
||||
int l, c;
|
||||
l = get2();
|
||||
printf ("%02x len=%d\n", kind, l);
|
||||
for (l -= 2; l > 0; l--)
|
||||
get1();
|
||||
}
|
||||
|
||||
char *sofName[16] = {
|
||||
"Baseline sequential DCT - Huffman coding",
|
||||
"Extended sequential DCT - Huffman coding",
|
||||
"Progressive DCT - Huffman coding",
|
||||
"Lossless - Huffman coding",
|
||||
"4 is otherwise used",
|
||||
"Sequential DCT - differential Huffman coding",
|
||||
"Progressive DCT - differential Huffman coding",
|
||||
"Lossless - differential Huffman coding",
|
||||
"8 is reserved",
|
||||
"Extended Sequential DCT - arithmetic coding",
|
||||
"Progressive DCT - arithmetic coding",
|
||||
"Lossless - arithmetic coding",
|
||||
"c is otherwise used",
|
||||
"Sequential DCT - differential arithmetic coding",
|
||||
"Progressive DCT - differential arithmetic coding",
|
||||
"Lossless - differential arithmetic coding",
|
||||
};
|
||||
|
||||
void get_sof (int kind) {
|
||||
int i, length, height, width, precision, ncomponents;
|
||||
int id, sf, tab;
|
||||
length = get2();
|
||||
precision = get1();
|
||||
height = get2();
|
||||
width = get2();
|
||||
ncomponents = get1();
|
||||
printf ("SOF%d:\t%s\n", kind - 0xc0, sofName[kind - 0xc0]);
|
||||
printf ("\t%d wide, %d high, %d deep, %d components\n",
|
||||
width, height, precision, ncomponents);
|
||||
for (i = 0; i < ncomponents; i++) {
|
||||
id = get1();
|
||||
sf = get1();
|
||||
tab = get1();
|
||||
printf ("\tcomponent %d: %d hsample, %d vsample, quantization table %d\n",
|
||||
id, sf >> 4, sf & 0xf, tab);
|
||||
}
|
||||
}
|
||||
|
||||
void get_com (int kind) {
|
||||
int l, c;
|
||||
l = get2();
|
||||
printf ("COM len=%d '", l);
|
||||
for (l -= 2; l > 0; l--)
|
||||
putchar (c = get1());
|
||||
printf ("'\n");
|
||||
}
|
||||
|
||||
void get_app (int kind) {
|
||||
int l, c, first;
|
||||
char buf[6];
|
||||
int nbuf, nok;
|
||||
l = get2();
|
||||
printf ("APP%d len=%d\n", kind - 0xe0, l);
|
||||
nbuf = 0;
|
||||
nok = 0;
|
||||
first = 1;
|
||||
/* dump printable strings in comment */
|
||||
for (l -= 2; l > 0; l--){
|
||||
c = get1();
|
||||
if(isprint(c)){
|
||||
if(nbuf >= sizeof buf){
|
||||
if(!first && nbuf == nok)
|
||||
printf(" ");
|
||||
printf("%.*s", nbuf, buf);
|
||||
nbuf = 0;
|
||||
first = 0;
|
||||
}
|
||||
buf[nbuf++] = c;
|
||||
nok++;
|
||||
}else{
|
||||
if(nok >= sizeof buf)
|
||||
if(nbuf > 0)
|
||||
printf("%.*s", nbuf, buf);
|
||||
nbuf = 0;
|
||||
nok = 0;
|
||||
}
|
||||
}
|
||||
if(nok >= sizeof buf)
|
||||
if(nbuf > 0){
|
||||
if(!first && nbuf == nok)
|
||||
printf(" ");
|
||||
printf("%.*s", nbuf, buf);
|
||||
}
|
||||
}
|
||||
|
||||
void get_dac (int kind) {
|
||||
eatmarker (kind);
|
||||
}
|
||||
|
||||
int get1dqt (void) {
|
||||
int t, p, i, *tab;
|
||||
t = get1();
|
||||
p = t >> 4;
|
||||
t = t & 0xf;
|
||||
printf ("DQT:\tp = %d, table = %d\n", p, t);
|
||||
tab = &dqt[t][0];
|
||||
for (i = 0; i < 64; i++)
|
||||
tab[i] = p ? get2() : get1();
|
||||
if (toption) {
|
||||
for (i = 0; i < 64; i++)
|
||||
printf ("\t%q[%02d] = %d\n", i, tab[i]);
|
||||
}
|
||||
return p ? 65 : 129;
|
||||
}
|
||||
|
||||
void get_dqt (int kind) {
|
||||
int length;
|
||||
length = get2() - 2;
|
||||
while (length > 0)
|
||||
length -= get1dqt();
|
||||
}
|
||||
|
||||
int get1dht (void) {
|
||||
int l, tcth, p, i, j, v[16], vv[16][256];
|
||||
tcth = get1();
|
||||
printf ("DHT:\tclass = %d, table = %d\n", tcth >> 4, tcth & 0xf);
|
||||
for (i = 0; i < 16; i++)
|
||||
v[i] = get1();
|
||||
l = 17;
|
||||
for (i = 0; i < 16; i++)
|
||||
for (j = 0; j < v[i]; j++) {
|
||||
vv[i][j] = get1();
|
||||
l += 1;
|
||||
}
|
||||
if (toption) {
|
||||
for (i = 0; i < 16; i++)
|
||||
printf ("\t%l[%02d] = %d\n", i+1, v[i]);
|
||||
for (i = 0; i < 16; i++)
|
||||
for (j = 0; j < v[i]; j++)
|
||||
printf ("\t%v[%02d,%02d] = %d\n", i+1, j+1, vv[i][j]);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
void get_dht (int kind) {
|
||||
int length;
|
||||
length = get2() - 2;
|
||||
while (length > 0)
|
||||
length -= get1dht();
|
||||
}
|
||||
|
||||
void get_sos (int kind) {
|
||||
int i, length, ncomponents, id, dcac, ahal;
|
||||
length = get2();
|
||||
ncomponents = get1();
|
||||
printf ("SOS:\t%d components\n", ncomponents);
|
||||
for (i = 0; i < ncomponents; i++) {
|
||||
id = get1();
|
||||
dcac = get1();
|
||||
printf ("\tcomponent %d: %d DC, %d AC\n", id, dcac >> 4, dcac & 0xf);
|
||||
}
|
||||
printf ("\tstart spectral %d\n", get1());
|
||||
printf ("\tend spectral %d\n", get1());
|
||||
ahal = get1();
|
||||
printf ("\tah = %d, al = %d\n", ahal >> 4, ahal &0xf);
|
||||
}
|
||||
|
||||
main (int argc, char *argv[]) {
|
||||
int l, stuff, i, j, c;
|
||||
while (argc > 1 && argv[1][0] == '-') {
|
||||
switch (argv[1][1]) {
|
||||
case 't':
|
||||
toption = 1;
|
||||
break;
|
||||
default:
|
||||
warn ("bad option '%c'", argv[1][1]);
|
||||
}
|
||||
eatarg0;
|
||||
}
|
||||
fname = argv[1];
|
||||
infile = fopen (fname, "r");
|
||||
if (infile == NULL)
|
||||
quit ("can't open %s\n", fname);
|
||||
Start:
|
||||
// if (get1() != 0xff || get1() != 0xd8)
|
||||
// quit ("not JFIF");
|
||||
// printf ("SOI\n");
|
||||
// get_app (0xe0);
|
||||
for (;;) {
|
||||
c = get1();
|
||||
if (c != 0xff)
|
||||
quit ("expected marker, got %2x", c);
|
||||
do {
|
||||
c = get1();
|
||||
} while (c == 0xff);
|
||||
marker:
|
||||
switch (c) {
|
||||
case 0xc0: case 0xc1: case 0xc2: case 0xc3:
|
||||
case 0xc5: case 0xc6: case 0xc7:
|
||||
case 0xc8: case 0xc9: case 0xca: case 0xcb:
|
||||
case 0xcd: case 0xce: case 0xcf:
|
||||
get_sof (c);
|
||||
break;
|
||||
case 0xc4:
|
||||
get_dht (c);
|
||||
break;
|
||||
case 0xcc:
|
||||
get_dac (c);
|
||||
break;
|
||||
case 0xd8:
|
||||
printf ("SOI\n");
|
||||
break;
|
||||
case 0xe0: case 0xe1: case 0xe2: case 0xe3:
|
||||
case 0xe4: case 0xe5: case 0xe6: case 0xe7:
|
||||
case 0xe8: case 0xe9: case 0xea: case 0xeb:
|
||||
case 0xec: case 0xed: case 0xee: case 0xef:
|
||||
get_app(c);
|
||||
break;
|
||||
case 0xda:
|
||||
get_sos (c);
|
||||
goto newentropy;
|
||||
case 0xdb:
|
||||
get_dqt (c);
|
||||
break;
|
||||
case 0xfe:
|
||||
get_com (c);
|
||||
break;
|
||||
case 0xd9:
|
||||
printf ("EOI\n");
|
||||
if((c=getc(infile)) == EOF)
|
||||
exit(0);
|
||||
ungetc(c, infile);
|
||||
goto Start;
|
||||
default:
|
||||
eatmarker (c);
|
||||
}
|
||||
continue;
|
||||
newentropy:
|
||||
l = stuff = 0;
|
||||
entropy:
|
||||
while ((c = get1()) != 0xff)
|
||||
l += 1;
|
||||
while (c == 0xff)
|
||||
c = get1();
|
||||
if (c == 0) {
|
||||
stuff += 1;
|
||||
goto entropy;
|
||||
}
|
||||
printf ("sequence length %d with %d stuffs\n", l, stuff);
|
||||
if (0xd0 <= c && c <= 0xd7) {
|
||||
printf ("restart %d\n", c - 0xd0);
|
||||
goto newentropy;
|
||||
}
|
||||
goto marker;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue