Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
7640 views
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_context *ctx, 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(ctx, 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_drop_stream(ctx, 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
/* Default values: predictor = 1, columns = 1, colors = 1, bpc = 8 */
220
fz_stream *
221
fz_open_predict(fz_context *ctx, fz_stream *chain, int predictor, int columns, int colors, int bpc)
222
{
223
fz_predict *state = NULL;
224
225
fz_var(state);
226
227
if (predictor < 1)
228
predictor = 1;
229
if (columns < 1)
230
columns = 1;
231
if (colors < 1)
232
colors = 1;
233
if (bpc < 1)
234
bpc = 8;
235
236
fz_try(ctx)
237
{
238
if (bpc != 1 && bpc != 2 && bpc != 4 && bpc != 8 && bpc != 16)
239
fz_throw(ctx, FZ_ERROR_GENERIC, "invalid number of bits per component: %d", bpc);
240
if (colors > FZ_MAX_COLORS)
241
fz_throw(ctx, FZ_ERROR_GENERIC, "too many color components (%d > %d)", colors, FZ_MAX_COLORS);
242
if (columns >= INT_MAX / (bpc * colors))
243
fz_throw(ctx, FZ_ERROR_GENERIC, "too many columns lead to an integer overflow (%d)", columns);
244
245
state = fz_malloc_struct(ctx, fz_predict);
246
state->in = NULL;
247
state->out = NULL;
248
state->chain = chain;
249
250
state->predictor = predictor;
251
state->columns = columns;
252
state->colors = colors;
253
state->bpc = bpc;
254
255
if (state->predictor != 1 && state->predictor != 2 &&
256
state->predictor != 10 && state->predictor != 11 &&
257
state->predictor != 12 && state->predictor != 13 &&
258
state->predictor != 14 && state->predictor != 15)
259
{
260
fz_warn(ctx, "invalid predictor: %d", state->predictor);
261
state->predictor = 1;
262
}
263
264
state->stride = (state->bpc * state->colors * state->columns + 7) / 8;
265
state->bpp = (state->bpc * state->colors + 7) / 8;
266
267
state->in = fz_malloc(ctx, state->stride + 1);
268
state->out = fz_malloc(ctx, state->stride);
269
state->ref = fz_malloc(ctx, state->stride);
270
state->rp = state->out;
271
state->wp = state->out;
272
273
memset(state->ref, 0, state->stride);
274
}
275
fz_catch(ctx)
276
{
277
if (state)
278
{
279
fz_free(ctx, state->in);
280
fz_free(ctx, state->out);
281
}
282
fz_free(ctx, state);
283
fz_drop_stream(ctx, chain);
284
fz_rethrow(ctx);
285
}
286
287
return fz_new_stream(ctx, state, next_predict, close_predict);
288
}
289
290