1 // jpeg_jo.cpp - (JPEG transformation - decoding/encoding Huffman)
2 
3 #include <stdio.h>
4 #include <stdlib.h>
5 
6 //  JPEG header info
7 static int huf[384], hufsel[2][10], hbuf[2048];
8 static int mcusize,  rsti;
9 
10 // actual position and state
11 static int state, hcode, len, mcupos, rs,  rst_code;
12 
parse_ht(int p,unsigned char * b,int pos)13 void parse_ht(int p, unsigned char *b, int pos)
14 {
15   int j, end = p + b[p - 2] * 256 + b[p - 1] - 2, cnt = 0;
16   while (p < end && end < pos && end < p + 2048 && ++cnt < 10) {
17     int tc = b[p] >> 4, th = b[p] & 15;
18     if (tc >= 2 || th >= 4) break;
19     const int a1 = p + 17, a2 = tc * 64 + th * 16, a3 = a2 * 16;
20     for (j = 0; j < 256; j++) hbuf[a3 + j] = b[a1 + j] / 16 + (b[a1 + j] % 16) * 16;
21     int t = 0, c = 0;
22     for (j = 0; j < 16; j++) {
23       huf[a2 + j] = (c *= 2);
24       huf[a2 + j + 128] = (c += b[p + j + 1]);
25       huf[a2 + j + 256] = a3 + t;
26       t += b[p + j + 1];
27     }
28     p = a1 + t;
29   }
30 }
31 
parse_st(int sos,int sof,unsigned char * b)32 void parse_st(int sos, int sof, unsigned char *b)
33 {
34   int s1 = b[sos + 4], s2 = b[sof + 9], t = 0, d = 0;
35   if (s1 > 4 || s2 > 4) s1 = s2 = 0;
36   for (int i = 0; i < s1; i++)
37     for (int j = 0; j < s2; j++)
38       if (b[sos + 2 * i + 5] == b[sof + 3 * j + 10]) {
39         int x = b[sof + 3 * j + 11], y = b[sos + 2 * i + 6];
40         int z = b[sof + 3 * j + 12];
41         if ((x >> 4) > d) d = x >> 4;
42         x = (x & 15) * (x >> 4);
43         x *= (t + x <= 10);
44         z *= (z < 4);
45         while (x--) {
46           hufsel[0][t] = (y >> 4) & 3;
47           hufsel[1][t] = y & 3;
48           t++;
49         }
50       }
51   mcusize = t * 64;
52 }
53 
read_header(FILE * f_input,FILE * f_output)54 void read_header(FILE *f_input, FILE *f_output)
55 {
56   int p = 0, st = 6, ht[8], hts = 0;
57   int sos=0, sof=0, dri=0, dqt=0, data=0;
58   unsigned char b[65536], *r;
59   mcusize = 0;
60   while (!mcusize && p < 65536) {
61     b[p++] = fgetc(f_input);
62     r = &b[p - 5];
63     fputc(r[4], f_output);
64     if (st>=0) { st--; if (st>0) continue; }
65     if (r[0] == 255 && r[1] == 218 && r[4] >= 0 && r[4] <= 4 &&
66         r[2] * 256 + r[3] == 6 + 2 * r[4]) data = (sos = p - 5) + r[2] * 256 + r[3] + 2;
67     if (r[1] == 255) {
68       if (st==0 && (r[2] > 192 && r[2] < 255)) st = r[3] * 256 + r[4] + 2;
69       if (r[2] == 196 && hts < 8) ht[hts++] = p;
70       if (r[2] == 192) sof = p - 4;
71       if (r[2] == 219) dqt = p - 2;
72       if (r[2] == 221) dri = p + 2;
73     }
74     if (p == dri) rsti = r[3] * 256 + r[4];
75     if (p == data && sof && sos) {
76       for (int i = 0; i < hts; i++) parse_ht(ht[i], b, p);
77       parse_st(sos, sof, b);
78     }
79   }
80 }
81 
transform(FILE * in,FILE * out)82 void transform(FILE *in, FILE *out) {
83   read_header(in, out);
84   int c = fgetc(in);
85   state = hcode = len = mcupos = 0;
86   while (c >= 0) {
87     for (int i = 7; i >= 0; i--) {
88       int bit=((c >> i) & 1);
89 
90       hcode += hcode + bit;
91       len++;
92       if (!state) {
93         if (len > 16) len = 16;
94         int ac = (mcupos & 63) > 0;
95         int hi = (abs(ac * 64 + hufsel[ac][mcupos >> 6] * 16 + len - 1)) & 127;
96         if (hcode < huf[hi + 128]) {
97           int k = huf[hi + 256] + hcode - huf[hi];
98           if (k < 0 || k >= 2048) k = 0;
99           rs = hbuf[k];
100           hcode = 0;
101           state = len + (rs / 16);
102         }
103       }
104       if (state == len) {
105         int r=rs % 16, s= rs / 16;
106         if ((mcupos & 63) == 0) {
107           mcupos++;
108         } else {
109           if (rs == 0) {
110             while ((mcupos & 63) != 0) mcupos++;
111           } else {
112             mcupos += r + 1;
113           }
114         }
115         if (mcupos >= mcusize) mcupos = 0;
116         fputc(r+s*16, out);
117         if (s>8) {
118           fputc(hcode/256, out);
119           fputc(hcode%256, out);
120         } else if (s>0) {
121           fputc(hcode, out);
122         }
123         hcode = len = state = 0;
124       }
125     }
126     if ((c = fgetc(in)) == 255) {
127       if (c = fgetc(in)) {
128         c = ((c & 248) == 208)?fgetc(in):-1;
129         state = hcode = len = mcupos = 0;
130       } else c = 255;
131     }
132   }
133 }
134 
write_bits(int c,int num,FILE * f_output)135 void write_bits(int c, int num, FILE *f_output)
136 {
137   hcode = hcode * (1 << num) + c;
138   len += num;
139   while (len >= 8) {
140     len -= 8;
141     int b = hcode >> len;
142     fputc(b, f_output);
143     if (b == 255) fputc(0, f_output);
144     hcode -= (b << len);
145   }
146 }
147 
write_rst(int c,FILE * f_output)148 void write_rst(int c, FILE *f_output)
149 {
150   if (len > 0) write_bits((1 << (8 - len)) - 1, 8 - len, f_output);
151   fputc(255, f_output);
152   fputc(208 + c, f_output);
153 }
154 
itransform(FILE * in,FILE * out)155 void itransform(FILE *in, FILE *out) {
156   read_header(in, out);
157   state = hcode = len = mcupos = 0;
158   rst_code = 0;
159   while (1) {
160     int i=0, x, t, s, rs;
161     while (i<64) {
162       rs=fgetc(in);
163       if (rs==EOF) { write_rst(9, out); return; }
164     if (i==0 && rsti && state == rsti) {
165       write_rst(rst_code, out);
166       rst_code = (rst_code + 1) % 8;
167       state = hcode = len = mcupos = 0;
168     }
169       s=rs/16;
170       x=0;
171       if (s>0) x=fgetc(in);
172       if (s>8) x=x*256+fgetc(in);
173       int k = (i!=0) * 4 + hufsel[i!=0][mcupos >> 6];
174       const int *h = &huf[k * 16];
175       int c = 0, u = 0, t = 0;
176       for (int j = 255; j >= 0; j--) if (hbuf[k * 256 + j] == rs) c = j;
177       while ((t += h[u + 128] - h[u]) <= c && u < 16) u++;
178       c += h[u + 128] - t;
179       write_bits(c, u + 1, out);
180       write_bits(x, s, out);
181       if (rs==0 && i>0) i=64; else i+=(rs%16)+1;
182     }
183     if ((mcupos += 64) >= mcusize) { mcupos = 0; state++; }
184   }
185 }
186 
main(int argc,char ** argv)187 int main(int argc, char **argv) {
188   if (argc<4 || (argv[1][0]!='e' && argv[1][0]!='d')) printf("To transform: jpeg_jo e input output\n To inverse transform jpeg_jo d input output\n"), exit(1);
189 
190   FILE *in=fopen(argv[2],"rb");
191   if (!in) perror(argv[2]), exit(1);
192   FILE *out=fopen(argv[3],"wb");
193   if (!out) perror(argv[3]), exit(1);
194   if (argv[1][0]=='e') {
195     // encoding
196     transform(in, out);
197   } else {
198     // decoding
199     itransform(in, out);
200   }
201   fclose(out);
202   fclose(in);
203   return 0;
204 }