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 | |
16 | static unsigned char get1_tab_1[256][8]; |
17 | static unsigned char get1_tab_1p[256][16]; |
18 | static unsigned char get1_tab_255[256][8]; |
19 | static 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 |
34 | static 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 | |
40 | static void |
41 | init_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 | |
72 | static void |
73 | fz_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 | |
88 | static void |
89 | fz_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 | |
104 | static void |
105 | fz_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 | |
120 | static void |
121 | fz_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 | |
136 | static void |
137 | fz_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 | |
144 | static void |
145 | fz_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 | |
157 | typedef void (*fz_unpack_line_fn)(unsigned char *dp, unsigned char *sp, int w, int n); |
158 | |
159 | void |
160 | fz_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 | |
279 | void |
280 | fz_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 | |
323 | void |
324 | fz_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 | |