]> rtime.felk.cvut.cz Git - hornmich/skoda-qr-demo.git/blob - QRScanner/mobile/jni/fitz/filter-predict.c
Add MuPDF native source codes
[hornmich/skoda-qr-demo.git] / QRScanner / mobile / jni / fitz / filter-predict.c
1 #include "mupdf/fitz.h"
2
3 /* TODO: check if this works with 16bpp images */
4
5 typedef struct fz_predict_s fz_predict;
6
7 struct fz_predict_s
8 {
9         fz_stream *chain;
10
11         int predictor;
12         int columns;
13         int colors;
14         int bpc;
15
16         int stride;
17         int bpp;
18         unsigned char *in;
19         unsigned char *out;
20         unsigned char *ref;
21         unsigned char *rp, *wp;
22
23         unsigned char buffer[4096];
24 };
25
26 static inline int getcomponent(unsigned char *line, int x, int bpc)
27 {
28         switch (bpc)
29         {
30         case 1: return (line[x >> 3] >> ( 7 - (x & 7) ) ) & 1;
31         case 2: return (line[x >> 2] >> ( ( 3 - (x & 3) ) << 1 ) ) & 3;
32         case 4: return (line[x >> 1] >> ( ( 1 - (x & 1) ) << 2 ) ) & 15;
33         case 8: return line[x];
34         case 16: return (line[x<<1]<<8)+line[(x<<1)+1];
35         }
36         return 0;
37 }
38
39 static inline void putcomponent(unsigned char *buf, int x, int bpc, int value)
40 {
41         switch (bpc)
42         {
43         case 1: buf[x >> 3] |= value << (7 - (x & 7)); break;
44         case 2: buf[x >> 2] |= value << ((3 - (x & 3)) << 1); break;
45         case 4: buf[x >> 1] |= value << ((1 - (x & 1)) << 2); break;
46         case 8: buf[x] = value; break;
47         case 16: buf[x<<1] = value>>8; buf[(x<<1)+1] = value; break;
48         }
49 }
50
51 static inline int paeth(int a, int b, int c)
52 {
53         /* The definitions of ac and bc are correct, not a typo. */
54         int ac = b - c, bc = a - c, abcc = ac + bc;
55         int pa = fz_absi(ac);
56         int pb = fz_absi(bc);
57         int pc = fz_absi(abcc);
58         return pa <= pb && pa <= pc ? a : pb <= pc ? b : c;
59 }
60
61 static void
62 fz_predict_tiff(fz_predict *state, unsigned char *out, unsigned char *in, int len)
63 {
64         int left[FZ_MAX_COLORS];
65         int i, k;
66         const int mask = (1 << state->bpc)-1;
67
68         for (k = 0; k < state->colors; k++)
69                 left[k] = 0;
70
71         /* special fast case */
72         if (state->bpc == 8)
73         {
74                 for (i = 0; i < state->columns; i++)
75                         for (k = 0; k < state->colors; k++)
76                                 *out++ = left[k] = (*in++ + left[k]) & 0xFF;
77                 return;
78         }
79
80         /* putcomponent assumes zeroed memory for bpc < 8 */
81         if (state->bpc < 8)
82                 memset(out, 0, state->stride);
83
84         for (i = 0; i < state->columns; i++)
85         {
86                 for (k = 0; k < state->colors; k++)
87                 {
88                         int a = getcomponent(in, i * state->colors + k, state->bpc);
89                         int b = a + left[k];
90                         int c = b & mask;
91                         putcomponent(out, i * state->colors + k, state->bpc, c);
92                         left[k] = c;
93                 }
94         }
95 }
96
97 static void
98 fz_predict_png(fz_predict *state, unsigned char *out, unsigned char *in, int len, int predictor)
99 {
100         int bpp = state->bpp;
101         int i;
102         unsigned char *ref = state->ref;
103
104         if (bpp > len)
105                 bpp = len;
106
107         switch (predictor)
108         {
109         case 0:
110                 memcpy(out, in, len);
111                 break;
112         case 1:
113                 for (i = bpp; i > 0; i--)
114                 {
115                         *out++ = *in++;
116                 }
117                 for (i = len - bpp; i > 0; i--)
118                 {
119                         *out = *in++ + out[-bpp];
120                         out++;
121                 }
122                 break;
123         case 2:
124                 for (i = bpp; i > 0; i--)
125                 {
126                         *out++ = *in++ + *ref++;
127                 }
128                 for (i = len - bpp; i > 0; i--)
129                 {
130                         *out++ = *in++ + *ref++;
131                 }
132                 break;
133         case 3:
134                 for (i = bpp; i > 0; i--)
135                 {
136                         *out++ = *in++ + (*ref++) / 2;
137                 }
138                 for (i = len - bpp; i > 0; i--)
139                 {
140                         *out = *in++ + (out[-bpp] + *ref++) / 2;
141                         out++;
142                 }
143                 break;
144         case 4:
145                 for (i = bpp; i > 0; i--)
146                 {
147                         *out++ = *in++ + paeth(0, *ref++, 0);
148                 }
149                 for (i = len - bpp; i > 0; i --)
150                 {
151                         *out = *in++ + paeth(out[-bpp], *ref, ref[-bpp]);
152                         ref++;
153                         out++;
154                 }
155                 break;
156         }
157 }
158
159 static int
160 next_predict(fz_stream *stm, int len)
161 {
162         fz_predict *state = stm->state;
163         unsigned char *buf = state->buffer;
164         unsigned char *p = buf;
165         unsigned char *ep;
166         int ispng = state->predictor >= 10;
167         int n;
168
169         if (len >= sizeof(state->buffer))
170                 len = sizeof(state->buffer);
171         ep = buf + len;
172
173         while (state->rp < state->wp && p < ep)
174                 *p++ = *state->rp++;
175
176         while (p < ep)
177         {
178                 n = fz_read(state->chain, state->in, state->stride + ispng);
179                 if (n == 0)
180                         break;
181
182                 if (state->predictor == 1)
183                         memcpy(state->out, state->in, n);
184                 else if (state->predictor == 2)
185                         fz_predict_tiff(state, state->out, state->in, n);
186                 else
187                 {
188                         fz_predict_png(state, state->out, state->in + 1, n - 1, state->in[0]);
189                         memcpy(state->ref, state->out, state->stride);
190                 }
191
192                 state->rp = state->out;
193                 state->wp = state->out + n - ispng;
194
195                 while (state->rp < state->wp && p < ep)
196                         *p++ = *state->rp++;
197         }
198
199         stm->rp = buf;
200         stm->wp = p;
201         if (stm->rp == stm->wp)
202                 return EOF;
203         stm->pos += p - buf;
204
205         return *stm->rp++;
206 }
207
208 static void
209 close_predict(fz_context *ctx, void *state_)
210 {
211         fz_predict *state = (fz_predict *)state_;
212         fz_close(state->chain);
213         fz_free(ctx, state->in);
214         fz_free(ctx, state->out);
215         fz_free(ctx, state->ref);
216         fz_free(ctx, state);
217 }
218
219 static fz_stream *
220 rebind_predict(fz_stream *s)
221 {
222         fz_predict *state = s->state;
223         return state->chain;
224 }
225
226 /* Default values: predictor = 1, columns = 1, colors = 1, bpc = 8 */
227 fz_stream *
228 fz_open_predict(fz_stream *chain, int predictor, int columns, int colors, int bpc)
229 {
230         fz_context *ctx = chain->ctx;
231         fz_predict *state = NULL;
232
233         fz_var(state);
234
235         if (predictor < 1)
236                 predictor = 1;
237         if (columns < 1)
238                 columns = 1;
239         if (colors < 1)
240                 colors = 1;
241         if (bpc < 1)
242                 bpc = 8;
243
244         fz_try(ctx)
245         {
246                 if (bpc != 1 && bpc != 2 && bpc != 4 && bpc != 8 && bpc != 16)
247                         fz_throw(ctx, FZ_ERROR_GENERIC, "invalid number of bits per component: %d", bpc);
248                 if (colors > FZ_MAX_COLORS)
249                         fz_throw(ctx, FZ_ERROR_GENERIC, "too many color components (%d > %d)", colors, FZ_MAX_COLORS);
250                 if (columns >= INT_MAX / (bpc * colors))
251                         fz_throw(ctx, FZ_ERROR_GENERIC, "too many columns lead to an integer overflow (%d)", columns);
252
253                 state = fz_malloc_struct(ctx, fz_predict);
254                 state->in = NULL;
255                 state->out = NULL;
256                 state->chain = chain;
257
258                 state->predictor = predictor;
259                 state->columns = columns;
260                 state->colors = colors;
261                 state->bpc = bpc;
262
263                 if (state->predictor != 1 && state->predictor != 2 &&
264                         state->predictor != 10 && state->predictor != 11 &&
265                         state->predictor != 12 && state->predictor != 13 &&
266                         state->predictor != 14 && state->predictor != 15)
267                 {
268                         fz_warn(ctx, "invalid predictor: %d", state->predictor);
269                         state->predictor = 1;
270                 }
271
272                 state->stride = (state->bpc * state->colors * state->columns + 7) / 8;
273                 state->bpp = (state->bpc * state->colors + 7) / 8;
274
275                 state->in = fz_malloc(ctx, state->stride + 1);
276                 state->out = fz_malloc(ctx, state->stride);
277                 state->ref = fz_malloc(ctx, state->stride);
278                 state->rp = state->out;
279                 state->wp = state->out;
280
281                 memset(state->ref, 0, state->stride);
282         }
283         fz_catch(ctx)
284         {
285                 if (state)
286                 {
287                         fz_free(ctx, state->in);
288                         fz_free(ctx, state->out);
289                 }
290                 fz_free(ctx, state);
291                 fz_close(chain);
292                 fz_rethrow(ctx);
293         }
294
295         return fz_new_stream(ctx, state, next_predict, close_predict, rebind_predict);
296 }