Change the translation of the "Help" menu item to "?", so that the menu can be displa...
[reactos.git] / rosapps / smartpdf / fitz / stream / filt_predict.c
1 #include "fitz-base.h"
2 #include "fitz-stream.h"
3
4 /* TODO: check if this works with 16bpp images */
5
6 enum { MAXC = 32 };
7
8 typedef struct fz_predict_s fz_predict;
9
10 struct fz_predict_s
11 {
12 fz_filter super;
13
14 int predictor;
15 int columns;
16 int colors;
17 int bpc;
18
19 int stride;
20 int bpp;
21 unsigned char *ref;
22
23 int encode;
24 };
25
26 fz_error *
27 fz_newpredict(fz_filter **fp, fz_obj *params, int encode)
28 {
29 fz_obj *obj;
30
31 FZ_NEWFILTER(fz_predict, p, predict);
32
33 p->encode = encode;
34
35 p->predictor = 1;
36 p->columns = 1;
37 p->colors = 1;
38 p->bpc = 8;
39
40 obj = fz_dictgets(params, "Predictor");
41 if (obj) p->predictor = fz_toint(obj);
42
43 obj = fz_dictgets(params, "Columns");
44 if (obj) p->columns = fz_toint(obj);
45
46 obj = fz_dictgets(params, "Colors");
47 if (obj) p->colors = fz_toint(obj);
48
49 obj = fz_dictgets(params, "BitsPerComponent");
50 if (obj) p->bpc = fz_toint(obj);
51
52 p->stride = (p->bpc * p->colors * p->columns + 7) / 8;
53 p->bpp = (p->bpc * p->colors + 7) / 8;
54
55 if (p->predictor >= 10) {
56 p->ref = fz_malloc(p->stride);
57 if (!p->ref) { fz_free(p); return fz_outofmem; }
58 memset(p->ref, 0, p->stride);
59 }
60 else {
61 p->ref = nil;
62 }
63
64 return nil;
65 }
66
67 void
68 fz_droppredict(fz_filter *filter)
69 {
70 fz_predict *p = (fz_predict*)filter;
71 fz_free(p->ref);
72 }
73
74 static inline int
75 getcomponent(unsigned char *buf, int x, int bpc)
76 {
77 switch (bpc)
78 {
79 case 1: return buf[x / 8] >> (7 - (x % 8)) & 0x01;
80 case 2: return buf[x / 4] >> ((3 - (x % 4)) * 2) & 0x03;
81 case 4: return buf[x / 2] >> ((1 - (x % 2)) * 4) & 0x0f;
82 case 8: return buf[x];
83 }
84 return 0;
85 }
86
87 static inline void
88 putcomponent(unsigned char *buf, int x, int bpc, int value)
89 {
90 switch (bpc)
91 {
92 case 1: buf[x / 8] |= value << (7 - (x % 8)); break;
93 case 2: buf[x / 4] |= value << ((3 - (x % 4)) * 2); break;
94 case 4: buf[x / 2] |= value << ((1 - (x % 2)) * 4); break;
95 case 8: buf[x] = value; break;
96 }
97 }
98
99 static inline int
100 paeth(int a, int b, int c)
101 {
102 /* The definitions of ac and bc are correct, not a typo. */
103 int ac = b - c, bc = a - c, abcc = ac + bc;
104 int pa = (ac < 0 ? -ac : ac);
105 int pb = (bc < 0 ? -bc : bc);
106 int pc = (abcc < 0 ? -abcc : abcc);
107 return pa <= pb && pa <= pc ? a : pb <= pc ? b : c;
108 }
109
110 static inline void
111 none(fz_predict *p, unsigned char *in, unsigned char *out)
112 {
113 memcpy(out, in, p->stride);
114 }
115
116 static void
117 tiff(fz_predict *p, unsigned char *in, unsigned char *out)
118 {
119 int left[MAXC];
120 int i, k;
121
122 for (k = 0; k < p->colors; k++)
123 left[k] = 0;
124
125 for (i = 0; i < p->columns; i++) {
126 for (k = 0; k < p->colors; k++) {
127 int a = getcomponent(in, i * p->colors + k, p->bpc);
128 int b = p->encode ? a - left[k] : a + left[k];
129 int c = b % (1 << p->bpc);
130 putcomponent(out, i * p->colors + k, p->bpc, c);
131 left[k] = p->encode ? a : c;
132 }
133 }
134 }
135
136 static void
137 png(fz_predict *p, unsigned char *in, unsigned char *out, int predictor)
138 {
139 int upleft[MAXC], left[MAXC], i, k;
140
141 for (k = 0; k < p->bpp; k++) {
142 left[k] = 0;
143 upleft[k] = 0;
144 }
145
146 if (p->encode)
147 {
148 for (k = 0, i = 0; i < p->stride; k = (k + 1) % p->bpp, i ++)
149 {
150 switch (predictor)
151 {
152 case 0: out[i] = in[i]; break;
153 case 1: out[i] = in[i] - left[k]; break;
154 case 2: out[i] = in[i] - p->ref[i]; break;
155 case 3: out[i] = in[i] - (left[k] + p->ref[i]) / 2; break;
156 case 4: out[i] = in[i] - paeth(left[k], p->ref[i], upleft[k]); break;
157 }
158 left[k] = in[i];
159 upleft[k] = p->ref[i];
160 }
161 }
162
163 else
164 {
165 for (k = 0, i = 0; i < p->stride; k = (k + 1) % p->bpp, i ++)
166 {
167 switch (predictor)
168 {
169 case 0: out[i] = in[i]; break;
170 case 1: out[i] = in[i] + left[k]; break;
171 case 2: out[i] = in[i] + p->ref[i]; break;
172 case 3: out[i] = in[i] + (left[k] + p->ref[i]) / 2; break;
173 case 4: out[i] = in[i] + paeth(left[k], p->ref[i], upleft[k]); break;
174 }
175 left[k] = out[i];
176 upleft[k] = p->ref[i];
177 }
178 }
179 }
180
181 fz_error *
182 fz_processpredict(fz_filter *filter, fz_buffer *in, fz_buffer *out)
183 {
184 fz_predict *dec = (fz_predict*)filter;
185 int ispng = dec->predictor >= 10;
186 int predictor;
187
188 while (1)
189 {
190 if (in->rp + dec->stride + (!dec->encode && ispng) > in->wp) {
191 if (in->eof)
192 return fz_iodone;
193 return fz_ioneedin;
194 }
195
196 if (out->wp + dec->stride + (dec->encode && ispng) > out->ep)
197 return fz_ioneedout;
198
199 if (dec->predictor == 1) {
200 none(dec, in->rp, out->wp);
201 }
202 else if (dec->predictor == 2) {
203 if (dec->bpc != 8)
204 memset(out->wp, 0, dec->stride);
205 tiff(dec, in->rp, out->wp);
206 }
207 else {
208 if (dec->encode) {
209 predictor = dec->predictor - 10;
210 if (predictor < 0 || predictor > 4)
211 predictor = 1;
212 *out->wp ++ = predictor;
213 }
214 else {
215 predictor = *in->rp++;
216 }
217 png(dec, in->rp, out->wp, predictor);
218 }
219
220 if (dec->ref)
221 memcpy(dec->ref, out->wp, dec->stride);
222
223 in->rp += dec->stride;
224 out->wp += dec->stride;
225 }
226 }
227
228 fz_error *
229 fz_newpredictd(fz_filter **fp, fz_obj *params)
230 {
231 return fz_newpredict(fp, params, 0);
232 }
233
234 fz_error *
235 fz_newpredicte(fz_filter **fp, fz_obj *params)
236 {
237 return fz_newpredict(fp, params, 1);
238 }
239