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 }