1#include "mupdf/fitz.h"
2#include "draw-imp.h"
3
4#include <string.h>
5
6/* Unpack image samples and optionally pad pixels with opaque alpha */
7
8#define get1(buf,x) ((buf[x >> 3] >> ( 7 - (x & 7) ) ) & 1 )
9#define get2(buf,x) ((buf[x >> 2] >> ( ( 3 - (x & 3) ) << 1 ) ) & 3 )
10#define get4(buf,x) ((buf[x >> 1] >> ( ( 1 - (x & 1) ) << 2 ) ) & 15 )
11#define get8(buf,x) (buf[x])
12#define get16(buf,x) (buf[x << 1])
13#define get24(buf,x) (buf[(x << 1) + x])
14#define get32(buf,x) (buf[x << 2])
15
16static unsigned char get1_tab_1[256][8];
17static unsigned char get1_tab_1p[256][16];
18static unsigned char get1_tab_255[256][8];
19static unsigned char get1_tab_255p[256][16];
20
21/*
22 Bug 697012 shows that the unpacking code can confuse valgrind due
23 to the use of undefined bits in the padding at the end of lines.
24 We unpack from bits to bytes by copying from a lookup table.
25 Valgrind is not capable of understanding that it doesn't matter
26 what the undefined bits are, as the bytes we copy that correspond
27 to the defined bits will always agree regardless of these
28 undefined bits by construction of the table.
29
30 We therefore have a VGMASK macro that explicitly masks off these
31 bits in PACIFY_VALGRIND builds.
32*/
33#ifdef PACIFY_VALGRIND
34static const unsigned char mask[9] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
35#define VGMASK(v,m) (v & mask[(m)])
36#else
37#define VGMASK(v,m) (v)
38#endif
39
40static void
41init_get1_tables(void)
42{
43 static int once = 0;
44 unsigned char bits[1];
45 int i, k, x;
46
47 /* TODO: mutex lock here */
48
49 if (once)
50 return;
51
52 for (i = 0; i < 256; i++)
53 {
54 bits[0] = i;
55 for (k = 0; k < 8; k++)
56 {
57 x = get1(bits, k);
58
59 get1_tab_1[i][k] = x;
60 get1_tab_1p[i][k * 2] = x;
61 get1_tab_1p[i][k * 2 + 1] = 255;
62
63 get1_tab_255[i][k] = x * 255;
64 get1_tab_255p[i][k * 2] = x * 255;
65 get1_tab_255p[i][k * 2 + 1] = 255;
66 }
67 }
68
69 once = 1;
70}
71
72static void
73fz_unpack_mono_line_unscaled(unsigned char *dp, unsigned char *sp, int w, int n)
74{
75 int w3 = w >> 3;
76 int x;
77
78 for (x = 0; x < w3; x++)
79 {
80 memcpy(dp, get1_tab_1[*sp++], 8);
81 dp += 8;
82 }
83 x = x << 3;
84 if (x < w)
85 memcpy(dp, get1_tab_1[VGMASK(*sp, w - x)], w - x);
86}
87
88static void
89fz_unpack_mono_line_scaled(unsigned char *dp, unsigned char *sp, int w, int n)
90{
91 int w3 = w >> 3;
92 int x;
93
94 for (x = 0; x < w3; x++)
95 {
96 memcpy(dp, get1_tab_255[*sp++], 8);
97 dp += 8;
98 }
99 x = x << 3;
100 if (x < w)
101 memcpy(dp, get1_tab_255[VGMASK(*sp, w - x)], w - x);
102}
103
104static void
105fz_unpack_mono_line_unscaled_with_padding(unsigned char *dp, unsigned char *sp, int w, int n)
106{
107 int w3 = w >> 3;
108 int x;
109
110 for (x = 0; x < w3; x++)
111 {
112 memcpy(dp, get1_tab_1p[*sp++], 16);
113 dp += 16;
114 }
115 x = x << 3;
116 if (x < w)
117 memcpy(dp, get1_tab_1p[VGMASK(*sp, w - x)], (w - x) << 1);
118}
119
120static void
121fz_unpack_mono_line_scaled_with_padding(unsigned char *dp, unsigned char *sp, int w, int n)
122{
123 int w3 = w >> 3;
124 int x;
125
126 for (x = 0; x < w3; x++)
127 {
128 memcpy(dp, get1_tab_255p[*sp++], 16);
129 dp += 16;
130 }
131 x = x << 3;
132 if (x < w)
133 memcpy(dp, get1_tab_255p[VGMASK(*sp, w - x)], (w - x) << 1);
134}
135
136static void
137fz_unpack_line(unsigned char *dp, unsigned char *sp, int w, int n)
138{
139 int len = w * n;
140 while (len--)
141 *dp++ = *sp++;
142}
143
144static void
145fz_unpack_line_with_padding(unsigned char *dp, unsigned char *sp, int w, int n)
146{
147 int x, k;
148
149 for (x = 0; x < w; x++)
150 {
151 for (k = 0; k < n; k++)
152 *dp++ = *sp++;
153 *dp++ = 255;
154 }
155}
156
157typedef void (*fz_unpack_line_fn)(unsigned char *dp, unsigned char *sp, int w, int n);
158
159void
160fz_unpack_tile(fz_context *ctx, fz_pixmap *dst, unsigned char *src, int n, int depth, size_t stride, int scale)
161{
162 unsigned char *sp = src;
163 unsigned char *dp = dst->samples;
164 fz_unpack_line_fn unpack_line = NULL;
165 int pad, y, skip;
166 int w = dst->w;
167 int h = dst->h;
168
169 pad = 0;
170 skip = 0;
171 if (dst->n > n)
172 pad = 255;
173 if (dst->n < n)
174 {
175 skip = n - dst->n;
176 n = dst->n;
177 }
178
179 if (depth == 1)
180 init_get1_tables();
181
182 if (scale == 0)
183 {
184 switch (depth)
185 {
186 case 1: scale = 255; break;
187 case 2: scale = 85; break;
188 case 4: scale = 17; break;
189 }
190 }
191
192 if (n == 1 && depth == 1 && scale == 1 && !pad && !skip)
193 unpack_line = fz_unpack_mono_line_unscaled;
194 else if (n == 1 && depth == 1 && scale == 255 && !pad && !skip)
195 unpack_line = fz_unpack_mono_line_scaled;
196 else if (n == 1 && depth == 1 && scale == 1 && pad && !skip)
197 unpack_line = fz_unpack_mono_line_unscaled_with_padding;
198 else if (n == 1 && depth == 1 && scale == 255 && pad && !skip)
199 unpack_line = fz_unpack_mono_line_scaled_with_padding;
200 else if (depth == 8 && !pad && !skip)
201 unpack_line = fz_unpack_line;
202 else if (depth == 8 && pad && !skip)
203 unpack_line = fz_unpack_line_with_padding;
204
205 if (unpack_line)
206 {
207 for (y = 0; y < h; y++, sp += stride, dp += dst->stride)
208 unpack_line(dp, sp, w, n);
209 }
210 else if (depth == 1 || depth == 2 || depth == 4 || depth == 8 || depth == 16 || depth == 24 || depth == 32)
211 {
212 for (y = 0; y < h; y++, sp += stride, dp += dst->stride)
213 {
214 unsigned char *p = dp;
215 int b = 0;
216 int x, k;
217
218 for (x = 0; x < w; x++)
219 {
220 for (k = 0; k < n; k++)
221 {
222 switch (depth)
223 {
224 case 1: *p++ = get1(sp, b) * scale; break;
225 case 2: *p++ = get2(sp, b) * scale; break;
226 case 4: *p++ = get4(sp, b) * scale; break;
227 case 8: *p++ = get8(sp, b); break;
228 case 16: *p++ = get16(sp, b); break;
229 case 24: *p++ = get24(sp, b); break;
230 case 32: *p++ = get32(sp, b); break;
231 }
232 b++;
233 }
234 b += skip;
235 if (pad)
236 *p++ = 255;
237 }
238 }
239 }
240 else if (depth > 0 && depth <= 8 * sizeof(int))
241 {
242 fz_stream *stm;
243 int x, k;
244 int skipbits = 8 * stride - w * n * depth;
245
246 stm = fz_open_memory(ctx, sp, h * stride);
247 fz_try(ctx)
248 {
249 for (y = 0; y < h; y++)
250 {
251 for (x = 0; x < w; x++)
252 {
253 for (k = 0; k < n; k++)
254 {
255 if (depth <= 8)
256 *dp++ = fz_read_bits(ctx, stm, depth) << (8 - depth);
257 else
258 *dp++ = fz_read_bits(ctx, stm, depth) >> (depth - 8);
259 }
260 if (pad)
261 *dp++ = 255;
262 }
263
264 dp += dst->stride - w * (n + (pad > 0));
265 (void) fz_read_bits(ctx, stm, skipbits);
266 }
267 }
268 fz_always(ctx)
269 fz_drop_stream(ctx, stm);
270 fz_catch(ctx)
271 fz_rethrow(ctx);
272 }
273 else
274 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot unpack tile with %d bits per component", depth);
275}
276
277/* Apply decode array */
278
279void
280fz_decode_indexed_tile(fz_context *ctx, fz_pixmap *pix, const float *decode, int maxval)
281{
282 int add[FZ_MAX_COLORS];
283 int mul[FZ_MAX_COLORS];
284 unsigned char *p = pix->samples;
285 int stride = pix->stride - pix->w * pix->n;
286 int len;
287 int pn = pix->n;
288 int n = pn - pix->alpha;
289 int needed;
290 int k;
291 int h;
292
293 needed = 0;
294 for (k = 0; k < n; k++)
295 {
296 int min = decode[k * 2] * 256;
297 int max = decode[k * 2 + 1] * 256;
298 add[k] = min;
299 mul[k] = (max - min) / maxval;
300 needed |= min != 0 || max != maxval * 256;
301 }
302
303 if (!needed)
304 return;
305
306 h = pix->h;
307 while (h--)
308 {
309 len = pix->w;
310 while (len--)
311 {
312 for (k = 0; k < n; k++)
313 {
314 int value = (add[k] + (((p[k] << 8) * mul[k]) >> 8)) >> 8;
315 p[k] = fz_clampi(value, 0, 255);
316 }
317 p += pn;
318 }
319 p += stride;
320 }
321}
322
323void
324fz_decode_tile(fz_context *ctx, fz_pixmap *pix, const float *decode)
325{
326 int add[FZ_MAX_COLORS];
327 int mul[FZ_MAX_COLORS];
328 unsigned char *p = pix->samples;
329 int stride = pix->stride - pix->w * pix->n;
330 int len;
331 int n = fz_maxi(1, pix->n - pix->alpha);
332 int k;
333 int h;
334
335 for (k = 0; k < n; k++)
336 {
337 int min = decode[k * 2] * 255;
338 int max = decode[k * 2 + 1] * 255;
339 add[k] = min;
340 mul[k] = max - min;
341 }
342
343 h = pix->h;
344 while (h--)
345 {
346 len = pix->w;
347 while (len--)
348 {
349 for (k = 0; k < n; k++)
350 {
351 int value = add[k] + fz_mul255(p[k], mul[k]);
352 p[k] = fz_clampi(value, 0, 255);
353 }
354 p += pix->n;
355 }
356 p += stride;
357 }
358}
359