comparison mupdf-source/source/fitz/draw-unpack.c @ 3:2c135c81b16c

MERGE: upstream PyMuPDF 1.26.4 with MuPDF 1.26.7
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:44:09 +0200
parents b50eed0cc0ef
children
comparison
equal deleted inserted replaced
0:6015a75abc2d 3:2c135c81b16c
1 // Copyright (C) 2004-2021 Artifex Software, Inc.
2 //
3 // This file is part of MuPDF.
4 //
5 // MuPDF is free software: you can redistribute it and/or modify it under the
6 // terms of the GNU Affero General Public License as published by the Free
7 // Software Foundation, either version 3 of the License, or (at your option)
8 // any later version.
9 //
10 // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13 // details.
14 //
15 // You should have received a copy of the GNU Affero General Public License
16 // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17 //
18 // Alternative licensing terms are available from the licensor.
19 // For commercial licensing, see <https://www.artifex.com/> or contact
20 // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21 // CA 94129, USA, for further information.
22
23 #include "mupdf/fitz.h"
24 #include "draw-imp.h"
25
26 #include <string.h>
27
28 /* Unpack image samples and optionally pad pixels with opaque alpha */
29
30 #define get1(buf,x) ((buf[x >> 3] >> ( 7 - (x & 7) ) ) & 1 )
31 #define get2(buf,x) ((buf[x >> 2] >> ( ( 3 - (x & 3) ) << 1 ) ) & 3 )
32 #define get4(buf,x) ((buf[x >> 1] >> ( ( 1 - (x & 1) ) << 2 ) ) & 15 )
33 #define get8(buf,x) (buf[x])
34 #define get16(buf,x) (buf[x << 1])
35 #define get24(buf,x) (buf[(x << 1) + x])
36 #define get32(buf,x) (buf[x << 2])
37
38 static unsigned char get1_tab_1[256][8];
39 static unsigned char get1_tab_1p[256][16];
40 static unsigned char get1_tab_255[256][8];
41 static unsigned char get1_tab_255p[256][16];
42
43 /*
44 Bug 697012 shows that the unpacking code can confuse valgrind due
45 to the use of undefined bits in the padding at the end of lines.
46 We unpack from bits to bytes by copying from a lookup table.
47 Valgrind is not capable of understanding that it doesn't matter
48 what the undefined bits are, as the bytes we copy that correspond
49 to the defined bits will always agree regardless of these
50 undefined bits by construction of the table.
51
52 We therefore have a VGMASK macro that explicitly masks off these
53 bits in PACIFY_VALGRIND builds.
54 */
55 #ifdef PACIFY_VALGRIND
56 static const unsigned char mask[9] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
57 #define VGMASK(v,m) (v & mask[(m)])
58 #else
59 #define VGMASK(v,m) (v)
60 #endif
61
62 static void
63 init_get1_tables(void)
64 {
65 static int once = 0;
66 unsigned char bits[1];
67 int i, k, x;
68
69 /* TODO: mutex lock here */
70
71 if (once)
72 return;
73
74 for (i = 0; i < 256; i++)
75 {
76 bits[0] = i;
77 for (k = 0; k < 8; k++)
78 {
79 x = get1(bits, k);
80
81 get1_tab_1[i][k] = x;
82 get1_tab_1p[i][k * 2] = x;
83 get1_tab_1p[i][k * 2 + 1] = 255;
84
85 get1_tab_255[i][k] = x * 255;
86 get1_tab_255p[i][k * 2] = x * 255;
87 get1_tab_255p[i][k * 2 + 1] = 255;
88 }
89 }
90
91 once = 1;
92 }
93
94 static void
95 fz_unpack_mono_line_unscaled(unsigned char *dp, unsigned char *sp, int w, int n, int depth, int scale, int pad, int skip)
96 {
97 int w3 = w >> 3;
98 int x;
99
100 for (x = 0; x < w3; x++)
101 {
102 memcpy(dp, get1_tab_1[*sp++], 8);
103 dp += 8;
104 }
105 x = x << 3;
106 if (x < w)
107 memcpy(dp, get1_tab_1[VGMASK(*sp, w - x)], w - x);
108 }
109
110 static void
111 fz_unpack_mono_line_scaled(unsigned char *dp, unsigned char *sp, int w, int n, int depth, int scale, int pad, int skip)
112 {
113 int w3 = w >> 3;
114 int x;
115
116 for (x = 0; x < w3; x++)
117 {
118 memcpy(dp, get1_tab_255[*sp++], 8);
119 dp += 8;
120 }
121 x = x << 3;
122 if (x < w)
123 memcpy(dp, get1_tab_255[VGMASK(*sp, w - x)], w - x);
124 }
125
126 static void
127 fz_unpack_mono_line_unscaled_with_padding(unsigned char *dp, unsigned char *sp, int w, int n, int depth, int scale, int pad, int skip)
128 {
129 int w3 = w >> 3;
130 int x;
131
132 for (x = 0; x < w3; x++)
133 {
134 memcpy(dp, get1_tab_1p[*sp++], 16);
135 dp += 16;
136 }
137 x = x << 3;
138 if (x < w)
139 memcpy(dp, get1_tab_1p[VGMASK(*sp, w - x)], (w - x) << 1);
140 }
141
142 static void
143 fz_unpack_mono_line_scaled_with_padding(unsigned char *dp, unsigned char *sp, int w, int n, int depth, int scale, int pad, int skip)
144 {
145 int w3 = w >> 3;
146 int x;
147
148 for (x = 0; x < w3; x++)
149 {
150 memcpy(dp, get1_tab_255p[*sp++], 16);
151 dp += 16;
152 }
153 x = x << 3;
154 if (x < w)
155 memcpy(dp, get1_tab_255p[VGMASK(*sp, w - x)], (w - x) << 1);
156 }
157
158 static void
159 fz_unpack_line(unsigned char *dp, unsigned char *sp, int w, int n, int depth, int scale, int pad, int skip)
160 {
161 int len = w * n;
162 while (len--)
163 *dp++ = *sp++;
164 }
165
166 static void
167 fz_unpack_line_with_padding(unsigned char *dp, unsigned char *sp, int w, int n, int depth, int scale, int pad, int skip)
168 {
169 int x, k;
170
171 for (x = 0; x < w; x++)
172 {
173 for (k = 0; k < n; k++)
174 *dp++ = *sp++;
175 *dp++ = 255;
176 }
177 }
178
179 static void
180 fz_unpack_any_l2depth(unsigned char *dp, unsigned char *sp, int w, int n, int depth, int scale, int pad, int skip)
181 {
182 unsigned char *p = dp;
183 int b = 0;
184 int x, k;
185
186 for (x = 0; x < w; x++)
187 {
188 for (k = 0; k < n; k++)
189 {
190 switch (depth)
191 {
192 case 1: *p++ = get1(sp, b) * scale; break;
193 case 2: *p++ = get2(sp, b) * scale; break;
194 case 4: *p++ = get4(sp, b) * scale; break;
195 case 8: *p++ = get8(sp, b); break;
196 case 16: *p++ = get16(sp, b); break;
197 case 24: *p++ = get24(sp, b); break;
198 case 32: *p++ = get32(sp, b); break;
199 }
200 b++;
201 }
202 b += skip;
203 if (pad)
204 *p++ = 255;
205 }
206 }
207
208 typedef void (*fz_unpack_line_fn)(unsigned char *dp, unsigned char *sp, int w, int n, int depth, int scale, int pad, int skip);
209
210 void
211 fz_unpack_tile(fz_context *ctx, fz_pixmap *dst, unsigned char *src, int n, int depth, size_t stride, int scale)
212 {
213 unsigned char *sp = src;
214 unsigned char *dp = dst->samples;
215 fz_unpack_line_fn unpack_line = NULL;
216 int pad, y, skip;
217 int w = dst->w;
218 int h = dst->h;
219
220 pad = 0;
221 skip = 0;
222 if (dst->n > n)
223 pad = 255;
224 if (dst->n < n)
225 {
226 skip = n - dst->n;
227 n = dst->n;
228 }
229
230 if (depth == 1)
231 init_get1_tables();
232
233 if (scale == 0)
234 {
235 switch (depth)
236 {
237 case 1: scale = 255; break;
238 case 2: scale = 85; break;
239 case 4: scale = 17; break;
240 }
241 }
242
243 if (n == 1 && depth == 1 && scale == 1 && !pad && !skip)
244 unpack_line = fz_unpack_mono_line_unscaled;
245 else if (n == 1 && depth == 1 && scale == 255 && !pad && !skip)
246 unpack_line = fz_unpack_mono_line_scaled;
247 else if (n == 1 && depth == 1 && scale == 1 && pad && !skip)
248 unpack_line = fz_unpack_mono_line_unscaled_with_padding;
249 else if (n == 1 && depth == 1 && scale == 255 && pad && !skip)
250 unpack_line = fz_unpack_mono_line_scaled_with_padding;
251 else if (depth == 8 && !pad && !skip)
252 unpack_line = fz_unpack_line;
253 else if (depth == 8 && pad && !skip)
254 unpack_line = fz_unpack_line_with_padding;
255 else if (depth == 1 || depth == 2 || depth == 4 || depth == 8 || depth == 16 || depth == 24 || depth == 32)
256 unpack_line = fz_unpack_any_l2depth;
257
258 if (unpack_line)
259 {
260 for (y = 0; y < h; y++, sp += stride, dp += dst->stride)
261 unpack_line(dp, sp, w, n, depth, scale, pad, skip);
262 }
263 else if (depth > 0 && depth <= 8 * (int)sizeof(int))
264 {
265 fz_stream *stm;
266 int x, k;
267 size_t skipbits = 8 * stride - (size_t)w * n * depth;
268
269 if (skipbits > 32)
270 fz_throw(ctx, FZ_ERROR_ARGUMENT, "Inappropriate stride!");
271
272 stm = fz_open_memory(ctx, sp, h * stride);
273 fz_try(ctx)
274 {
275 for (y = 0; y < h; y++)
276 {
277 for (x = 0; x < w; x++)
278 {
279 for (k = 0; k < n; k++)
280 {
281 if (depth <= 8)
282 *dp++ = fz_read_bits(ctx, stm, depth) << (8 - depth);
283 else
284 *dp++ = fz_read_bits(ctx, stm, depth) >> (depth - 8);
285 }
286 if (pad)
287 *dp++ = 255;
288 }
289
290 dp += dst->stride - (size_t)w * (n + (pad > 0));
291 (void) fz_read_bits(ctx, stm, (int)skipbits);
292 }
293 }
294 fz_always(ctx)
295 fz_drop_stream(ctx, stm);
296 fz_catch(ctx)
297 fz_rethrow(ctx);
298 }
299 else
300 fz_throw(ctx, FZ_ERROR_ARGUMENT, "cannot unpack tile with %d bits per component", depth);
301 }
302
303 /* Apply decode array */
304
305 void
306 fz_decode_indexed_tile(fz_context *ctx, fz_pixmap *pix, const float *decode, int maxval)
307 {
308 int add[FZ_MAX_COLORS];
309 int mul[FZ_MAX_COLORS];
310 unsigned char *p = pix->samples;
311 size_t stride = pix->stride - pix->w * (size_t)pix->n;
312 int len;
313 int pn = pix->n;
314 int n = pn - pix->alpha;
315 int needed;
316 int k;
317 int h;
318
319 needed = 0;
320 for (k = 0; k < n; k++)
321 {
322 int min = decode[k * 2] * 256;
323 int max = decode[k * 2 + 1] * 256;
324 add[k] = min;
325 mul[k] = (max - min) / maxval;
326 needed |= min != 0 || max != maxval * 256;
327 }
328
329 if (!needed)
330 return;
331
332 h = pix->h;
333 while (h--)
334 {
335 len = pix->w;
336 while (len--)
337 {
338 for (k = 0; k < n; k++)
339 {
340 int value = (add[k] + (((p[k] << 8) * mul[k]) >> 8)) >> 8;
341 p[k] = fz_clampi(value, 0, 255);
342 }
343 p += pn;
344 }
345 p += stride;
346 }
347 }
348
349 void
350 fz_decode_tile(fz_context *ctx, fz_pixmap *pix, const float *decode)
351 {
352 int add[FZ_MAX_COLORS];
353 int mul[FZ_MAX_COLORS];
354 unsigned char *p = pix->samples;
355 size_t stride = pix->stride - pix->w * (size_t)pix->n;
356 int len;
357 int n = fz_maxi(1, pix->n - pix->alpha);
358 int k;
359 int h;
360
361 for (k = 0; k < n; k++)
362 {
363 int min = decode[k * 2] * 255;
364 int max = decode[k * 2 + 1] * 255;
365 add[k] = min;
366 mul[k] = max - min;
367 }
368
369 h = pix->h;
370 while (h--)
371 {
372 len = pix->w;
373 while (len--)
374 {
375 for (k = 0; k < n; k++)
376 {
377 int value = add[k] + fz_mul255(p[k], mul[k]);
378 p[k] = fz_clampi(value, 0, 255);
379 }
380 p += pix->n;
381 }
382 p += stride;
383 }
384 }
385
386 typedef struct
387 {
388 fz_stream *src;
389 int depth;
390 int w;
391 int h;
392 int n;
393 int skip;
394 int pad;
395 int scale;
396 int src_stride;
397 int dst_stride;
398 fz_unpack_line_fn unpack;
399 unsigned char buf[1];
400 } unpack_state;
401
402 static int
403 unpack_next(fz_context *ctx, fz_stream *stm, size_t max)
404 {
405 unpack_state *state = (unpack_state *)stm->state;
406 size_t n = state->src_stride;
407
408 stm->rp = state->buf;
409 do
410 {
411 size_t a = fz_available(ctx, state->src, n);
412 if (a == 0)
413 return EOF;
414 if (a > n)
415 a = n;
416 memcpy(stm->rp, state->src->rp, a);
417 stm->rp += a;
418 state->src->rp += a;
419 n -= a;
420 }
421 while (n);
422
423 state->h--;
424 stm->pos += state->dst_stride;
425 stm->wp = stm->rp + state->dst_stride;
426 state->unpack(stm->rp, state->buf, state->w, state->n, state->depth, state->scale, state->pad, state->skip);
427
428 return *stm->rp++;
429 }
430
431 static void
432 unpack_drop(fz_context *ctx, void *state)
433 {
434 fz_free(ctx, state);
435 }
436
437 fz_stream *
438 fz_unpack_stream(fz_context *ctx, fz_stream *src, int depth, int w, int h, int n, int indexed, int pad, int skip)
439 {
440 int src_stride = (w*depth*n+7)>>3;
441 int dst_stride;
442 unpack_state *state;
443 fz_unpack_line_fn unpack_line = NULL;
444 int scale = 1;
445
446 if (depth == 1)
447 init_get1_tables();
448
449 if (!indexed)
450 switch (depth)
451 {
452 case 1: scale = 255; break;
453 case 2: scale = 85; break;
454 case 4: scale = 17; break;
455 }
456
457 dst_stride = w * (n + !!pad);
458
459 if (n == 1 && depth == 1 && scale == 1 && !pad && !skip)
460 unpack_line = fz_unpack_mono_line_unscaled;
461 else if (n == 1 && depth == 1 && scale == 255 && !pad && !skip)
462 unpack_line = fz_unpack_mono_line_scaled;
463 else if (n == 1 && depth == 1 && scale == 1 && pad && !skip)
464 unpack_line = fz_unpack_mono_line_unscaled_with_padding;
465 else if (n == 1 && depth == 1 && scale == 255 && pad && !skip)
466 unpack_line = fz_unpack_mono_line_scaled_with_padding;
467 else if (depth == 8 && !pad && !skip)
468 unpack_line = fz_unpack_line;
469 else if (depth == 8 && pad && !skip)
470 unpack_line = fz_unpack_line_with_padding;
471 else if (depth == 1 || depth == 2 || depth == 4 || depth == 8 || depth == 16 || depth == 24 || depth == 32)
472 unpack_line = fz_unpack_any_l2depth;
473 else
474 fz_throw(ctx, FZ_ERROR_ARGUMENT, "Unsupported combination in fz_unpack_stream");
475
476 state = fz_malloc(ctx, sizeof(unpack_state) + dst_stride + src_stride);
477 state->src = src;
478 state->depth = depth;
479 state->w = w;
480 state->h = h;
481 state->n = n;
482 state->skip = skip;
483 state->pad = pad;
484 state->scale = scale;
485 state->unpack = unpack_line;
486 state->src_stride = src_stride;
487 state->dst_stride = dst_stride;
488
489 return fz_new_stream(ctx, state, unpack_next, unpack_drop);
490 }