Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4680 right-hear 1
#include "fitz.h"
2
 
3
/* TODO: check if this works with 16bpp images */
4
 
5
enum { MAXC = 32 };
6
 
7
typedef struct fz_predict_s fz_predict;
8
 
9
struct fz_predict_s
10
{
11
	fz_stream *chain;
12
 
13
	int predictor;
14
	int columns;
15
	int colors;
16
	int bpc;
17
 
18
	int stride;
19
	int bpp;
20
	unsigned char *in;
21
	unsigned char *out;
22
	unsigned char *ref;
23
	unsigned char *rp, *wp;
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
	}
35
	return 0;
36
}
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
	}
48
}
49
 
50
static inline int paeth(int a, int b, int c)
51
{
52
	/* The definitions of ac and bc are correct, not a typo. */
53
	int ac = b - c, bc = a - c, abcc = ac + bc;
54
	int pa = ABS(ac);
55
	int pb = ABS(bc);
56
	int pc = ABS(abcc);
57
	return pa <= pb && pa <= pc ? a : pb <= pc ? b : c;
58
}
59
 
60
static void
61
fz_predict_tiff(fz_predict *state, unsigned char *out, unsigned char *in, int len)
62
{
63
	int left[MAXC];
64
	int i, k;
65
 
66
	for (k = 0; k < state->colors; k++)
67
		left[k] = 0;
68
 
69
	for (i = 0; i < state->columns; i++)
70
	{
71
		for (k = 0; k < state->colors; k++)
72
		{
73
			int a = getcomponent(in, i * state->colors + k, state->bpc);
74
			int b = a + left[k];
75
			int c = b % (1 << state->bpc);
76
			putcomponent(out, i * state->colors + k, state->bpc, c);
77
			left[k] = c;
78
		}
79
	}
80
}
81
 
82
static void
83
fz_predict_png(fz_predict *state, unsigned char *out, unsigned char *in, int len, int predictor)
84
{
85
	int bpp = state->bpp;
86
	int i;
87
	unsigned char *ref = state->ref;
88
 
89
	switch (predictor)
90
	{
91
	case 0:
92
		memcpy(out, in, len);
93
		break;
94
	case 1:
95
		for (i = bpp; i > 0; i--)
96
		{
97
			*out++ = *in++;
98
		}
99
		for (i = len - bpp; i > 0; i--)
100
		{
101
			*out = *in++ + out[-bpp];
102
			out++;
103
		}
104
		break;
105
	case 2:
106
		for (i = bpp; i > 0; i--)
107
		{
108
			*out++ = *in++ + *ref++;
109
		}
110
		for (i = len - bpp; i > 0; i--)
111
		{
112
			*out++ = *in++ + *ref++;
113
		}
114
		break;
115
	case 3:
116
		for (i = bpp; i > 0; i--)
117
		{
118
			*out++ = *in++ + (*ref++) / 2;
119
		}
120
		for (i = len - bpp; i > 0; i--)
121
		{
122
			*out = *in++ + (out[-bpp] + *ref++) / 2;
123
			out++;
124
		}
125
		break;
126
	case 4:
127
		for (i = bpp; i > 0; i--)
128
		{
129
			*out++ = *in++ + paeth(0, *ref++, 0);
130
		}
131
		for (i = len - bpp; i > 0; i --)
132
		{
133
			*out = *in++ + paeth(out[-bpp], *ref, ref[-bpp]);
134
			ref++;
135
			out++;
136
		}
137
		break;
138
	}
139
}
140
 
141
static int
142
read_predict(fz_stream *stm, unsigned char *buf, int len)
143
{
144
	fz_predict *state = stm->state;
145
	unsigned char *p = buf;
146
	unsigned char *ep = buf + len;
147
	int ispng = state->predictor >= 10;
148
	int n;
149
 
150
	while (state->rp < state->wp && p < ep)
151
		*p++ = *state->rp++;
152
 
153
	while (p < ep)
154
	{
155
		n = fz_read(state->chain, state->in, state->stride + ispng);
156
		if (n < 0)
157
			return fz_rethrow(n, "read error in prediction filter");
158
		if (n == 0)
159
			return p - buf;
160
 
161
		if (state->predictor == 1)
162
			memcpy(state->out, state->in, n);
163
		else if (state->predictor == 2)
164
			fz_predict_tiff(state, state->out, state->in, n);
165
		else
166
		{
167
			fz_predict_png(state, state->out, state->in + 1, n - 1, state->in[0]);
168
			memcpy(state->ref, state->out, state->stride);
169
		}
170
 
171
		state->rp = state->out;
172
		state->wp = state->out + n - ispng;
173
 
174
		while (state->rp < state->wp && p < ep)
175
			*p++ = *state->rp++;
176
	}
177
 
178
	return p - buf;
179
}
180
 
181
static void
182
close_predict(fz_stream *stm)
183
{
184
	fz_predict *state = stm->state;
185
	fz_close(state->chain);
186
	fz_free(state->in);
187
	fz_free(state->out);
188
	fz_free(state->ref);
189
	fz_free(state);
190
}
191
 
192
fz_stream *
193
fz_open_predict(fz_stream *chain, fz_obj *params)
194
{
195
	fz_predict *state;
196
	fz_obj *obj;
197
 
198
	state = fz_malloc(sizeof(fz_predict));
199
	state->chain = chain;
200
 
201
	state->predictor = 1;
202
	state->columns = 1;
203
	state->colors = 1;
204
	state->bpc = 8;
205
 
206
	obj = fz_dict_gets(params, "Predictor");
207
	if (obj)
208
		state->predictor = fz_to_int(obj);
209
 
210
	if (state->predictor != 1 && state->predictor != 2 &&
211
		state->predictor != 10 && state->predictor != 11 &&
212
		state->predictor != 12 && state->predictor != 13 &&
213
		state->predictor != 14 && state->predictor != 15)
214
	{
215
		fz_warn("invalid predictor: %d", state->predictor);
216
		state->predictor = 1;
217
	}
218
 
219
	obj = fz_dict_gets(params, "Columns");
220
	if (obj)
221
		state->columns = fz_to_int(obj);
222
 
223
	obj = fz_dict_gets(params, "Colors");
224
	if (obj)
225
		state->colors = fz_to_int(obj);
226
 
227
	obj = fz_dict_gets(params, "BitsPerComponent");
228
	if (obj)
229
		state->bpc = fz_to_int(obj);
230
 
231
	state->stride = (state->bpc * state->colors * state->columns + 7) / 8;
232
	state->bpp = (state->bpc * state->colors + 7) / 8;
233
 
234
	state->in = fz_malloc(state->stride + 1);
235
	state->out = fz_malloc(state->stride);
236
	state->ref = fz_malloc(state->stride);
237
	state->rp = state->out;
238
	state->wp = state->out;
239
 
240
	memset(state->ref, 0, state->stride);
241
 
242
	return fz_new_stream(state, read_predict, close_predict);
243
}