comparison mupdf-source/source/fitz/deskew_c.h @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 // Copyright (C) 2004-2024 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 /* This file is included from deskew.c if C cores are allowed. */
24
25 static void
26 zoom_x(uint8_t * FZ_RESTRICT tmp,
27 const uint8_t * FZ_RESTRICT src,
28 const index_t * FZ_RESTRICT index,
29 const weight_t * FZ_RESTRICT weights,
30 uint32_t dst_w,
31 uint32_t src_w,
32 uint32_t channels,
33 const uint8_t * FZ_RESTRICT bg)
34 {
35 if (0)
36 slow:
37 {
38 uint32_t i;
39 /* Do any where we might index off the edge of the source */
40 int pn = index->first_pixel;
41 const uint8_t *s0 = &src[pn * (int)channels];
42
43 for (i = 0; i < channels; i++)
44 {
45 const weight_t *w = &weights[index->index];
46 uint32_t j = index->n;
47 int32_t pixel = WEIGHT_ROUND;
48 int pix_num = pn;
49 const uint8_t *s = s0++;
50 if (pix_num < 0)
51 {
52 assert(pix_num == -1);
53 pixel += bg[i] * *w++;
54 s += channels;
55 j--;
56 pix_num = 0;
57 }
58 pix_num = (int)src_w - pix_num;
59 if (pix_num > (int)j)
60 pix_num = j;
61 j -= pix_num;
62 while (pix_num > 0)
63 {
64 pixel += *s * *w++;
65 s += channels;
66 pix_num--;
67 }
68 if (j > 0)
69 {
70 assert(j == 1);
71 pixel += bg[i] * *w++;
72 }
73 pixel >>= WEIGHT_SHIFT;
74 *tmp++ = CLAMP(pixel, 0, 255);
75 }
76 index++;
77 dst_w--;
78 }
79
80 while (dst_w > 0)
81 {
82 int i;
83 const uint8_t *sr;
84
85 /* Jump out of band to do the (rare) slow (edge) pixels */
86 if (index->slow)
87 goto slow;
88
89 sr = &src[index->first_pixel * channels];
90
91 for (i = channels; i > 0; i--)
92 {
93 const weight_t *w = &weights[index->index];
94 uint32_t j = index->n;
95 int32_t pixel = WEIGHT_ROUND;
96 const uint8_t *s = sr++;
97 for (j = index->n; j > 0; j--, s += channels)
98 {
99 pixel += *s * *w++;
100 }
101 pixel >>= WEIGHT_SHIFT;
102 *tmp++ = CLAMP(pixel, 0, 255);
103 }
104 index++;
105 dst_w--;
106 }
107 }
108
109 static void
110 zoom_x1(uint8_t * FZ_RESTRICT tmp,
111 const uint8_t * FZ_RESTRICT src,
112 const index_t * FZ_RESTRICT index,
113 const weight_t * FZ_RESTRICT weights,
114 uint32_t dst_w,
115 uint32_t src_w,
116 uint32_t channels,
117 const uint8_t * FZ_RESTRICT bg)
118 {
119 if (0)
120 slow:
121 {
122 /* Do any where we might index off the edge of the source */
123 int pix_num = index->first_pixel;
124 const uint8_t *s = &src[pix_num];
125 const weight_t *w = &weights[index->index];
126 uint32_t j = index->n;
127 int32_t pixel0 = WEIGHT_ROUND;
128 if (pix_num < 0)
129 {
130 int32_t wt = *w++;
131 assert(pix_num == -1);
132 pixel0 += bg[0] * wt;
133 s++;
134 j--;
135 pix_num = 0;
136 }
137 pix_num = (int)src_w - pix_num;
138 if (pix_num > (int)j)
139 pix_num = j;
140 j -= pix_num;
141 while (pix_num > 0)
142 {
143 pixel0 += *s++ * *w++;
144 pix_num--;
145 }
146 if (j > 0)
147 {
148 assert(j == 1);
149 pixel0 += bg[0] * *w;
150 }
151 pixel0 >>= WEIGHT_SHIFT;
152 *tmp++ = CLAMP(pixel0, 0, 255);
153 index++;
154 dst_w--;
155 }
156
157 while (dst_w > 0)
158 {
159 const uint8_t *s;
160
161 /* Jump out of band to do the (rare) slow (edge) pixels */
162 if (index->slow)
163 goto slow;
164
165 s = &src[index->first_pixel];
166
167 {
168 const weight_t *w = &weights[index->index];
169 uint32_t j = index->n;
170 int32_t pixel0 = WEIGHT_ROUND;
171 for (j = index->n; j > 0; j--)
172 {
173 pixel0 += *s++ * *w++;
174 }
175 pixel0 >>= WEIGHT_SHIFT;
176 *tmp++ = CLAMP(pixel0, 0, 255);
177 }
178 index++;
179 dst_w--;
180 }
181 }
182
183 static void
184 zoom_x3(uint8_t * FZ_RESTRICT tmp,
185 const uint8_t * FZ_RESTRICT src,
186 const index_t * FZ_RESTRICT index,
187 const weight_t * FZ_RESTRICT weights,
188 uint32_t dst_w,
189 uint32_t src_w,
190 uint32_t channels,
191 const uint8_t * FZ_RESTRICT bg)
192 {
193 if (0)
194 slow:
195 {
196 /* Do any where we might index off the edge of the source */
197 int pix_num = index->first_pixel;
198 const uint8_t *s = &src[pix_num * 3];
199 const weight_t *w = &weights[index->index];
200 uint32_t j = index->n;
201 int32_t pixel0 = WEIGHT_ROUND;
202 int32_t pixel1 = WEIGHT_ROUND;
203 int32_t pixel2 = WEIGHT_ROUND;
204 if (pix_num < 0)
205 {
206 int32_t wt = *w++;
207 assert(pix_num == -1);
208 pixel0 += bg[0] * wt;
209 pixel1 += bg[1] * wt;
210 pixel2 += bg[2] * wt;
211 s += 3;
212 j--;
213 pix_num = 0;
214 }
215 pix_num = (int)src_w - pix_num;
216 if (pix_num > (int)j)
217 pix_num = j;
218 j -= pix_num;
219 while (pix_num > 0)
220 {
221 int32_t wt = *w++;
222 pixel0 += *s++ * wt;
223 pixel1 += *s++ * wt;
224 pixel2 += *s++ * wt;
225 pix_num--;
226 }
227 if (j > 0)
228 {
229 int32_t wt = *w++;
230 assert(j == 1);
231 pixel0 += bg[0] * wt;
232 pixel1 += bg[1] * wt;
233 pixel2 += bg[2] * wt;
234 }
235 pixel0 >>= WEIGHT_SHIFT;
236 pixel1 >>= WEIGHT_SHIFT;
237 pixel2 >>= WEIGHT_SHIFT;
238 *tmp++ = CLAMP(pixel0, 0, 255);
239 *tmp++ = CLAMP(pixel1, 0, 255);
240 *tmp++ = CLAMP(pixel2, 0, 255);
241 index++;
242 dst_w--;
243 }
244
245 while (dst_w > 0)
246 {
247 const uint8_t *s;
248
249 /* Jump out of band to do the (rare) slow (edge) pixels */
250 if (index->slow)
251 goto slow;
252
253 s = &src[index->first_pixel * 3];
254
255 {
256 const weight_t *w = &weights[index->index];
257 uint32_t j = index->n;
258 int32_t pixel0 = WEIGHT_ROUND;
259 int32_t pixel1 = WEIGHT_ROUND;
260 int32_t pixel2 = WEIGHT_ROUND;
261 for (j = index->n; j > 0; j--)
262 {
263 int32_t wt = *w++;
264 pixel0 += *s++ * wt;
265 pixel1 += *s++ * wt;
266 pixel2 += *s++ * wt;
267 }
268 pixel0 >>= WEIGHT_SHIFT;
269 pixel1 >>= WEIGHT_SHIFT;
270 pixel2 >>= WEIGHT_SHIFT;
271 *tmp++ = CLAMP(pixel0, 0, 255);
272 *tmp++ = CLAMP(pixel1, 0, 255);
273 *tmp++ = CLAMP(pixel2, 0, 255);
274 }
275 index++;
276 dst_w--;
277 }
278 }
279
280 static void
281 zoom_x4(uint8_t * FZ_RESTRICT tmp,
282 const uint8_t * FZ_RESTRICT src,
283 const index_t * FZ_RESTRICT index,
284 const weight_t * FZ_RESTRICT weights,
285 uint32_t dst_w,
286 uint32_t src_w,
287 uint32_t channels,
288 const uint8_t * FZ_RESTRICT bg)
289 {
290 if (0)
291 slow:
292 {
293 /* Do any where we might index off the edge of the source */
294 int pn = index->first_pixel;
295 const uint8_t *s = &src[pn * 4];
296 const weight_t *w = &weights[index->index];
297 uint32_t j = index->n;
298 int32_t pixel0 = WEIGHT_ROUND;
299 int32_t pixel1 = WEIGHT_ROUND;
300 int32_t pixel2 = WEIGHT_ROUND;
301 int32_t pixel3 = WEIGHT_ROUND;
302 int pix_num = pn;
303 if (pix_num < 0)
304 {
305 int32_t wt = *w++;
306 assert(pix_num == -1);
307 pixel0 += bg[0] * wt;
308 pixel1 += bg[1] * wt;
309 pixel2 += bg[2] * wt;
310 pixel3 += bg[3] * wt;
311 s += 4;
312 j--;
313 pix_num = 0;
314 }
315 pix_num = (int)src_w - pix_num;
316 if (pix_num > (int)j)
317 pix_num = j;
318 j -= pix_num;
319 while (pix_num > 0)
320 {
321 int32_t wt = *w++;
322 pixel0 += *s++ * wt;
323 pixel1 += *s++ * wt;
324 pixel2 += *s++ * wt;
325 pixel3 += *s++ * wt;
326 pix_num--;
327 }
328 if (j > 0)
329 {
330 int32_t wt = *w;
331 assert(j == 1);
332 pixel0 += bg[0] * wt;
333 pixel1 += bg[1] * wt;
334 pixel2 += bg[2] * wt;
335 pixel3 += bg[3] * wt;
336 }
337 pixel0 >>= WEIGHT_SHIFT;
338 pixel1 >>= WEIGHT_SHIFT;
339 pixel2 >>= WEIGHT_SHIFT;
340 pixel3 >>= WEIGHT_SHIFT;
341 *tmp++ = CLAMP(pixel0, 0, 255);
342 *tmp++ = CLAMP(pixel1, 0, 255);
343 *tmp++ = CLAMP(pixel2, 0, 255);
344 *tmp++ = CLAMP(pixel3, 0, 255);
345 index++;
346 dst_w--;
347 }
348
349 while (dst_w > 0)
350 {
351 const uint8_t *s;
352
353 /* Jump out of band to do the (rare) slow (edge) pixels */
354 if (index->slow)
355 goto slow;
356
357 s = &src[index->first_pixel * 4];
358
359 {
360 const weight_t *w = &weights[index->index];
361 uint32_t j = index->n;
362 int32_t pixel0 = WEIGHT_ROUND;
363 int32_t pixel1 = WEIGHT_ROUND;
364 int32_t pixel2 = WEIGHT_ROUND;
365 int32_t pixel3 = WEIGHT_ROUND;
366 for (j = index->n; j > 0; j--)
367 {
368 int32_t wt = *w++;
369 pixel0 += *s++ * wt;
370 pixel1 += *s++ * wt;
371 pixel2 += *s++ * wt;
372 pixel3 += *s++ * wt;
373 }
374 pixel0 >>= WEIGHT_SHIFT;
375 pixel1 >>= WEIGHT_SHIFT;
376 pixel2 >>= WEIGHT_SHIFT;
377 pixel3 >>= WEIGHT_SHIFT;
378 *tmp++ = CLAMP(pixel0, 0, 255);
379 *tmp++ = CLAMP(pixel1, 0, 255);
380 *tmp++ = CLAMP(pixel2, 0, 255);
381 *tmp++ = CLAMP(pixel3, 0, 255);
382 }
383 index++;
384 dst_w--;
385 }
386 }
387
388 static void
389 zoom_y(uint8_t * dst,
390 const uint8_t * FZ_RESTRICT tmp,
391 const index_t * FZ_RESTRICT index,
392 const weight_t * FZ_RESTRICT weights,
393 uint32_t width,
394 uint32_t channels,
395 uint32_t mod,
396 int32_t y)
397 {
398 uint32_t stride = width * channels;
399 uint32_t offset = 0;
400
401 while (width--)
402 {
403 uint32_t i;
404 uint32_t off = (index->first_pixel + y) * stride + offset;
405
406 offset += channels;
407 if (off >= mod)
408 off -= mod;
409
410 for (i = 0; i < channels; i++)
411 {
412 const weight_t *w = &weights[index->index];
413 uint32_t j = index->n;
414 int32_t pixel = WEIGHT_ROUND;
415 uint32_t o = off++;
416
417 for (j = index->n; j > 0; j--)
418 {
419 pixel += tmp[o] * *w++;
420 o += stride;
421 if (o >= mod)
422 o -= mod;
423 }
424 pixel >>= WEIGHT_SHIFT;
425 *dst++ = CLAMP(pixel, 0, 255);
426 }
427 index++;
428 }
429 }
430
431 static void
432 zoom_y1(uint8_t * dst,
433 const uint8_t * FZ_RESTRICT tmp,
434 const index_t * FZ_RESTRICT index,
435 const weight_t * FZ_RESTRICT weights,
436 uint32_t width,
437 uint32_t channels,
438 uint32_t mod,
439 int32_t y)
440 {
441 uint32_t stride = width;
442 uint32_t offset = 0;
443
444 while (width--)
445 {
446 uint32_t off = (index->first_pixel + y) * stride + offset;
447
448 offset++;
449 if (off >= mod)
450 off -= mod;
451
452 {
453 const weight_t *w = &weights[index->index];
454 uint32_t j = index->n;
455 int32_t pixel0 = WEIGHT_ROUND;
456
457 for (j = index->n; j > 0; j--)
458 {
459 pixel0 += tmp[off ] * *w++;
460 off += stride;
461 if (off >= mod)
462 off -= mod;
463 }
464 pixel0 >>= WEIGHT_SHIFT;
465 *dst++ = CLAMP(pixel0, 0, 255);
466 }
467 index++;
468 }
469 }
470
471 static void
472 zoom_y3(uint8_t * dst,
473 const uint8_t * FZ_RESTRICT tmp,
474 const index_t * FZ_RESTRICT index,
475 const weight_t * FZ_RESTRICT weights,
476 uint32_t width,
477 uint32_t channels,
478 uint32_t mod,
479 int32_t y)
480 {
481 uint32_t stride = width * 3;
482 uint32_t offset = 0;
483
484 while (width--)
485 {
486 uint32_t off = (index->first_pixel + y) * stride + offset;
487
488 offset += 3;
489 if (off >= mod)
490 off -= mod;
491
492 {
493 const weight_t *w = &weights[index->index];
494 uint32_t j = index->n;
495 int32_t pixel0 = WEIGHT_ROUND;
496 int32_t pixel1 = WEIGHT_ROUND;
497 int32_t pixel2 = WEIGHT_ROUND;
498
499 for (j = index->n; j > 0; j--)
500 {
501 int32_t wt = *w++;
502 pixel0 += tmp[off ] * wt;
503 pixel1 += tmp[off+1] * wt;
504 pixel2 += tmp[off+2] * wt;
505 off += stride;
506 if (off >= mod)
507 off -= mod;
508 }
509 pixel0 >>= WEIGHT_SHIFT;
510 pixel1 >>= WEIGHT_SHIFT;
511 pixel2 >>= WEIGHT_SHIFT;
512 *dst++ = CLAMP(pixel0, 0, 255);
513 *dst++ = CLAMP(pixel1, 0, 255);
514 *dst++ = CLAMP(pixel2, 0, 255);
515 }
516 index++;
517 }
518 }
519
520 static void
521 zoom_y4(uint8_t * dst,
522 const uint8_t * FZ_RESTRICT tmp,
523 const index_t * FZ_RESTRICT index,
524 const weight_t * FZ_RESTRICT weights,
525 uint32_t width,
526 uint32_t channels,
527 uint32_t mod,
528 int32_t y)
529 {
530 uint32_t stride = width * 4;
531 uint32_t offset = 0;
532
533 while (width--)
534 {
535 uint32_t off = (index->first_pixel + y) * stride + offset;
536
537 offset += 4;
538 if (off >= mod)
539 off -= mod;
540
541 {
542 const weight_t *w = &weights[index->index];
543 uint32_t j = index->n;
544 int32_t pixel0 = WEIGHT_ROUND;
545 int32_t pixel1 = WEIGHT_ROUND;
546 int32_t pixel2 = WEIGHT_ROUND;
547 int32_t pixel3 = WEIGHT_ROUND;
548
549 for (j = index->n; j > 0; j--)
550 {
551 int32_t wt = *w++;
552 pixel0 += tmp[off] * wt;
553 pixel1 += tmp[off+1] * wt;
554 pixel2 += tmp[off+2] * wt;
555 pixel3 += tmp[off+3] * wt;
556 off += stride;
557 if (off >= mod)
558 off -= mod;
559 }
560 pixel0 >>= WEIGHT_SHIFT;
561 pixel1 >>= WEIGHT_SHIFT;
562 pixel2 >>= WEIGHT_SHIFT;
563 pixel3 >>= WEIGHT_SHIFT;
564 *dst++ = CLAMP(pixel0, 0, 255);
565 *dst++ = CLAMP(pixel1, 0, 255);
566 *dst++ = CLAMP(pixel2, 0, 255);
567 *dst++ = CLAMP(pixel3, 0, 255);
568 }
569 index++;
570 }
571 }