comparison mupdf-source/thirdparty/leptonica/src/rotateorth.c @ 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 /*====================================================================*
2 - Copyright (C) 2001 Leptonica. All rights reserved.
3 -
4 - Redistribution and use in source and binary forms, with or without
5 - modification, are permitted provided that the following conditions
6 - are met:
7 - 1. Redistributions of source code must retain the above copyright
8 - notice, this list of conditions and the following disclaimer.
9 - 2. Redistributions in binary form must reproduce the above
10 - copyright notice, this list of conditions and the following
11 - disclaimer in the documentation and/or other materials
12 - provided with the distribution.
13 -
14 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18 - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *====================================================================*/
26
27 /*!
28 * \file rotateorth.c
29 * <pre>
30 *
31 * Top-level rotation by multiples of 90 degrees
32 * PIX *pixRotateOrth()
33 *
34 * 180-degree rotation
35 * PIX *pixRotate180()
36 *
37 * 90-degree rotation (both directions)
38 * PIX *pixRotate90()
39 *
40 * Left-right flip
41 * PIX *pixFlipLR()
42 *
43 * Top-bottom flip
44 * PIX *pixFlipTB()
45 *
46 * Byte reverse tables
47 * static l_uint8 *makeReverseByteTab1()
48 * static l_uint8 *makeReverseByteTab2()
49 * static l_uint8 *makeReverseByteTab4()
50 * </pre>
51 */
52
53 #ifdef HAVE_CONFIG_H
54 #include <config_auto.h>
55 #endif /* HAVE_CONFIG_H */
56
57 #include <string.h>
58 #include "allheaders.h"
59
60 static l_uint8 *makeReverseByteTab1(void);
61 static l_uint8 *makeReverseByteTab2(void);
62 static l_uint8 *makeReverseByteTab4(void);
63
64 /*------------------------------------------------------------------*
65 * Top-level rotation by multiples of 90 degrees *
66 *------------------------------------------------------------------*/
67 /*!
68 * \brief pixRotateOrth()
69 *
70 * \param[in] pixs all depths
71 * \param[in] quads 0-3; number of 90 degree cw rotations
72 * \return pixd, or NULL on error
73 */
74 PIX *
75 pixRotateOrth(PIX *pixs,
76 l_int32 quads)
77 {
78 if (!pixs)
79 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
80 if (quads < 0 || quads > 3)
81 return (PIX *)ERROR_PTR("quads not in {0,1,2,3}", __func__, NULL);
82
83 if (quads == 0)
84 return pixCopy(NULL, pixs);
85 else if (quads == 1)
86 return pixRotate90(pixs, 1);
87 else if (quads == 2)
88 return pixRotate180(NULL, pixs);
89 else /* quads == 3 */
90 return pixRotate90(pixs, -1);
91 }
92
93
94 /*------------------------------------------------------------------*
95 * 180 degree rotation *
96 *------------------------------------------------------------------*/
97 /*!
98 * \brief pixRotate180()
99 *
100 * \param[in] pixd [optional]; can be null, equal to pixs,
101 * or different from pixs
102 * \param[in] pixs all depths
103 * \return pixd, or NULL on error
104 *
105 * <pre>
106 * Notes:
107 * (1) This does a 180 rotation of the image about the center,
108 * which is equivalent to a left-right flip about a vertical
109 * line through the image center, followed by a top-bottom
110 * flip about a horizontal line through the image center.
111 * (2) There are 3 cases for input:
112 * (a) pixd == null (creates a new pixd)
113 * (b) pixd == pixs (in-place operation)
114 * (c) pixd != pixs (existing pixd)
115 * (3) For clarity, use these three patterns, respectively:
116 * (a) pixd = pixRotate180(NULL, pixs);
117 * (b) pixRotate180(pixs, pixs);
118 * (c) pixRotate180(pixd, pixs);
119 * </pre>
120 */
121 PIX *
122 pixRotate180(PIX *pixd,
123 PIX *pixs)
124 {
125 l_int32 d;
126
127 if (!pixs)
128 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
129 d = pixGetDepth(pixs);
130 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
131 return (PIX *)ERROR_PTR("pixs not in {1,2,4,8,16,32} bpp",
132 __func__, NULL);
133
134 /* Prepare pixd for in-place operation */
135 if ((pixd = pixCopy(pixd, pixs)) == NULL)
136 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
137
138 pixFlipLR(pixd, pixd);
139 pixFlipTB(pixd, pixd);
140 return pixd;
141 }
142
143
144 /*------------------------------------------------------------------*
145 * 90 degree rotation *
146 *------------------------------------------------------------------*/
147 /*!
148 * \brief pixRotate90()
149 *
150 * \param[in] pixs all depths
151 * \param[in] direction clockwise = 1, counterclockwise = -1
152 * \return pixd, or NULL on error
153 *
154 * <pre>
155 * Notes:
156 * (1) This does a 90 degree rotation of the image about the center,
157 * either cw or ccw, returning a new pix.
158 * (2) The direction must be either 1 (cw) or -1 (ccw).
159 * </pre>
160 */
161 PIX *
162 pixRotate90(PIX *pixs,
163 l_int32 direction)
164 {
165 l_int32 wd, hd, d, wpls, wpld;
166 l_int32 i, j, k, m, iend, nswords;
167 l_uint32 val, word;
168 l_uint32 *lines, *datas, *lined, *datad;
169 PIX *pixd;
170
171 if (!pixs)
172 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
173 pixGetDimensions(pixs, &hd, &wd, &d); /* note: reversed */
174 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
175 return (PIX *)ERROR_PTR("pixs not in {1,2,4,8,16,32} bpp",
176 __func__, NULL);
177 if (direction != 1 && direction != -1)
178 return (PIX *)ERROR_PTR("invalid direction", __func__, NULL);
179
180 if ((pixd = pixCreate(wd, hd, d)) == NULL)
181 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
182 pixCopyColormap(pixd, pixs);
183 pixCopyResolution(pixd, pixs);
184 pixCopyInputFormat(pixd, pixs);
185 pixCopySpp(pixd, pixs);
186
187 datas = pixGetData(pixs);
188 wpls = pixGetWpl(pixs);
189 datad = pixGetData(pixd);
190 wpld = pixGetWpl(pixd);
191
192 if (direction == 1) { /* clockwise */
193 switch (d)
194 {
195 case 32:
196 for (i = 0; i < hd; i++) {
197 lined = datad + i * wpld;
198 lines = datas + (wd - 1) * wpls;
199 for (j = 0; j < wd; j++) {
200 lined[j] = lines[i];
201 lines -= wpls;
202 }
203 }
204 break;
205 case 16:
206 for (i = 0; i < hd; i++) {
207 lined = datad + i * wpld;
208 lines = datas + (wd - 1) * wpls;
209 for (j = 0; j < wd; j++) {
210 if ((val = GET_DATA_TWO_BYTES(lines, i)))
211 SET_DATA_TWO_BYTES(lined, j, val);
212 lines -= wpls;
213 }
214 }
215 break;
216 case 8:
217 for (i = 0; i < hd; i++) {
218 lined = datad + i * wpld;
219 lines = datas + (wd - 1) * wpls;
220 for (j = 0; j < wd; j++) {
221 if ((val = GET_DATA_BYTE(lines, i)))
222 SET_DATA_BYTE(lined, j, val);
223 lines -= wpls;
224 }
225 }
226 break;
227 case 4:
228 for (i = 0; i < hd; i++) {
229 lined = datad + i * wpld;
230 lines = datas + (wd - 1) * wpls;
231 for (j = 0; j < wd; j++) {
232 if ((val = GET_DATA_QBIT(lines, i)))
233 SET_DATA_QBIT(lined, j, val);
234 lines -= wpls;
235 }
236 }
237 break;
238 case 2:
239 for (i = 0; i < hd; i++) {
240 lined = datad + i * wpld;
241 lines = datas + (wd - 1) * wpls;
242 for (j = 0; j < wd; j++) {
243 if ((val = GET_DATA_DIBIT(lines, i)))
244 SET_DATA_DIBIT(lined, j, val);
245 lines -= wpls;
246 }
247 }
248 break;
249 case 1:
250 nswords = hd / 32;
251 for (j = 0; j < wd; j++) {
252 lined = datad;
253 lines = datas + (wd - 1 - j) * wpls;
254 for (k = 0; k < nswords; k++) {
255 word = lines[k];
256 if (!word) {
257 lined += 32 * wpld;
258 continue;
259 } else {
260 iend = 32 * (k + 1);
261 for (m = 0, i = 32 * k; i < iend; i++, m++) {
262 if ((word << m) & 0x80000000)
263 SET_DATA_BIT(lined, j);
264 lined += wpld;
265 }
266 }
267 }
268 for (i = 32 * nswords; i < hd; i++) {
269 if (GET_DATA_BIT(lines, i))
270 SET_DATA_BIT(lined, j);
271 lined += wpld;
272 }
273 }
274 break;
275 default:
276 pixDestroy(&pixd);
277 L_ERROR("illegal depth: %d\n", __func__, d);
278 break;
279 }
280 } else { /* direction counter-clockwise */
281 switch (d)
282 {
283 case 32:
284 for (i = 0; i < hd; i++) {
285 lined = datad + i * wpld;
286 lines = datas;
287 for (j = 0; j < wd; j++) {
288 lined[j] = lines[hd - 1 - i];
289 lines += wpls;
290 }
291 }
292 break;
293 case 16:
294 for (i = 0; i < hd; i++) {
295 lined = datad + i * wpld;
296 lines = datas;
297 for (j = 0; j < wd; j++) {
298 if ((val = GET_DATA_TWO_BYTES(lines, hd - 1 - i)))
299 SET_DATA_TWO_BYTES(lined, j, val);
300 lines += wpls;
301 }
302 }
303 break;
304 case 8:
305 for (i = 0; i < hd; i++) {
306 lined = datad + i * wpld;
307 lines = datas;
308 for (j = 0; j < wd; j++) {
309 if ((val = GET_DATA_BYTE(lines, hd - 1 - i)))
310 SET_DATA_BYTE(lined, j, val);
311 lines += wpls;
312 }
313 }
314 break;
315 case 4:
316 for (i = 0; i < hd; i++) {
317 lined = datad + i * wpld;
318 lines = datas;
319 for (j = 0; j < wd; j++) {
320 if ((val = GET_DATA_QBIT(lines, hd - 1 - i)))
321 SET_DATA_QBIT(lined, j, val);
322 lines += wpls;
323 }
324 }
325 break;
326 case 2:
327 for (i = 0; i < hd; i++) {
328 lined = datad + i * wpld;
329 lines = datas;
330 for (j = 0; j < wd; j++) {
331 if ((val = GET_DATA_DIBIT(lines, hd - 1 - i)))
332 SET_DATA_DIBIT(lined, j, val);
333 lines += wpls;
334 }
335 }
336 break;
337 case 1:
338 nswords = hd / 32;
339 for (j = 0; j < wd; j++) {
340 lined = datad + (hd - 1) * wpld;
341 lines = datas + (wd - 1 - j) * wpls;
342 for (k = 0; k < nswords; k++) {
343 word = lines[k];
344 if (!word) {
345 lined -= 32 * wpld;
346 continue;
347 } else {
348 iend = 32 * (k + 1);
349 for (m = 0, i = 32 * k; i < iend; i++, m++) {
350 if ((word << m) & 0x80000000)
351 SET_DATA_BIT(lined, wd - 1 - j);
352 lined -= wpld;
353 }
354 }
355 }
356 for (i = 32 * nswords; i < hd; i++) {
357 if (GET_DATA_BIT(lines, i))
358 SET_DATA_BIT(lined, wd - 1 - j);
359 lined -= wpld;
360 }
361 }
362 break;
363 default:
364 pixDestroy(&pixd);
365 L_ERROR("illegal depth: %d\n", __func__, d);
366 break;
367 }
368 }
369
370 return pixd;
371 }
372
373
374 /*------------------------------------------------------------------*
375 * Left-right flip *
376 *------------------------------------------------------------------*/
377 /*!
378 * \brief pixFlipLR()
379 *
380 * \param[in] pixd [optional]; can be null, equal to pixs,
381 * or different from pixs
382 * \param[in] pixs all depths
383 * \return pixd, or NULL on error
384 *
385 * <pre>
386 * Notes:
387 * (1) This does a left-right flip of the image, which is
388 * equivalent to a rotation out of the plane about a
389 * vertical line through the image center.
390 * (2) There are 3 cases for input:
391 * (a) pixd == null (creates a new pixd)
392 * (b) pixd == pixs (in-place operation)
393 * (c) pixd != pixs (existing pixd)
394 * (3) For clarity, use these three patterns, respectively:
395 * (a) pixd = pixFlipLR(NULL, pixs);
396 * (b) pixFlipLR(pixs, pixs);
397 * (c) pixFlipLR(pixd, pixs);
398 * (4) If an existing pixd is not the same size as pixs, the
399 * image data will be reallocated.
400 * (5) The pixel access routines allow a trivial implementation.
401 * However, for d < 8, it is more efficient to right-justify
402 * each line to a 32-bit boundary and then extract bytes and
403 * do pixel reversing. In those cases, as in the 180 degree
404 * rotation, we right-shift the data (if necessary) to
405 * right-justify on the 32 bit boundary, and then read the
406 * bytes off each raster line in reverse order, reversing
407 * the pixels in each byte using a table. These functions
408 * for 1, 2 and 4 bpp were tested against the "trivial"
409 * version (shown here for 4 bpp):
410 * for (i = 0; i < h; i++) {
411 * line = data + i * wpl;
412 * memcpy(buffer, line, bpl);
413 * for (j = 0; j < w; j++) {
414 * val = GET_DATA_QBIT(buffer, w - 1 - j);
415 * SET_DATA_QBIT(line, j, val);
416 * }
417 * }
418 * </pre>
419 */
420 PIX *
421 pixFlipLR(PIX *pixd,
422 PIX *pixs)
423 {
424 l_uint8 *tab;
425 l_int32 w, h, d, wpl;
426 l_int32 extra, shift, databpl, bpl, i, j;
427 l_uint32 val;
428 l_uint32 *line, *data, *buffer;
429
430 if (!pixs)
431 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
432 pixGetDimensions(pixs, &w, &h, &d);
433 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
434 return (PIX *)ERROR_PTR("pixs not in {1,2,4,8,16,32} bpp",
435 __func__, NULL);
436
437 /* Prepare pixd for in-place operation */
438 if ((pixd = pixCopy(pixd, pixs)) == NULL)
439 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
440
441 data = pixGetData(pixd);
442 wpl = pixGetWpl(pixd);
443 switch (d)
444 {
445 case 1:
446 tab = makeReverseByteTab1();
447 break;
448 case 2:
449 tab = makeReverseByteTab2();
450 break;
451 case 4:
452 tab = makeReverseByteTab4();
453 break;
454 default:
455 tab = NULL;
456 break;
457 }
458
459 /* Possibly inplace assigning return val, so on failure return pixd */
460 if ((buffer = (l_uint32 *)LEPT_CALLOC(wpl, sizeof(l_uint32))) == NULL) {
461 if (tab) LEPT_FREE(tab);
462 return (PIX *)ERROR_PTR("buffer not made", __func__, pixd);
463 }
464
465 bpl = 4 * wpl;
466 switch (d)
467 {
468 case 32:
469 for (i = 0; i < h; i++) {
470 line = data + i * wpl;
471 memcpy(buffer, line, bpl);
472 for (j = 0; j < w; j++)
473 line[j] = buffer[w - 1 - j];
474 }
475 break;
476 case 16:
477 for (i = 0; i < h; i++) {
478 line = data + i * wpl;
479 memcpy(buffer, line, bpl);
480 for (j = 0; j < w; j++) {
481 val = GET_DATA_TWO_BYTES(buffer, w - 1 - j);
482 SET_DATA_TWO_BYTES(line, j, val);
483 }
484 }
485 break;
486 case 8:
487 for (i = 0; i < h; i++) {
488 line = data + i * wpl;
489 memcpy(buffer, line, bpl);
490 for (j = 0; j < w; j++) {
491 val = GET_DATA_BYTE(buffer, w - 1 - j);
492 SET_DATA_BYTE(line, j, val);
493 }
494 }
495 break;
496 case 4:
497 extra = (w * d) & 31;
498 if (extra)
499 shift = 8 - extra / 4;
500 else
501 shift = 0;
502 if (shift)
503 rasteropHipLow(data, h, d, wpl, 0, h, shift);
504
505 databpl = (w + 1) / 2;
506 for (i = 0; i < h; i++) {
507 line = data + i * wpl;
508 memcpy(buffer, line, bpl);
509 for (j = 0; j < databpl; j++) {
510 val = GET_DATA_BYTE(buffer, bpl - 1 - j);
511 SET_DATA_BYTE(line, j, tab[val]);
512 }
513 }
514 break;
515 case 2:
516 extra = (w * d) & 31;
517 if (extra)
518 shift = 16 - extra / 2;
519 else
520 shift = 0;
521 if (shift)
522 rasteropHipLow(data, h, d, wpl, 0, h, shift);
523
524 databpl = (w + 3) / 4;
525 for (i = 0; i < h; i++) {
526 line = data + i * wpl;
527 memcpy(buffer, line, bpl);
528 for (j = 0; j < databpl; j++) {
529 val = GET_DATA_BYTE(buffer, bpl - 1 - j);
530 SET_DATA_BYTE(line, j, tab[val]);
531 }
532 }
533 break;
534 case 1:
535 extra = (w * d) & 31;
536 if (extra)
537 shift = 32 - extra;
538 else
539 shift = 0;
540 if (shift)
541 rasteropHipLow(data, h, d, wpl, 0, h, shift);
542
543 databpl = (w + 7) / 8;
544 for (i = 0; i < h; i++) {
545 line = data + i * wpl;
546 memcpy(buffer, line, bpl);
547 for (j = 0; j < databpl; j++) {
548 val = GET_DATA_BYTE(buffer, bpl - 1 - j);
549 SET_DATA_BYTE(line, j, tab[val]);
550 }
551 }
552 break;
553 default:
554 pixDestroy(&pixd);
555 L_ERROR("illegal depth: %d\n", __func__, d);
556 break;
557 }
558
559 LEPT_FREE(buffer);
560 if (tab) LEPT_FREE(tab);
561 return pixd;
562 }
563
564
565 /*------------------------------------------------------------------*
566 * Top-bottom flip *
567 *------------------------------------------------------------------*/
568 /*!
569 * \brief pixFlipTB()
570 *
571 * \param[in] pixd [optional]; can be null, equal to pixs,
572 * or different from pixs
573 * \param[in] pixs all depths
574 * \return pixd, or NULL on error
575 *
576 * <pre>
577 * Notes:
578 * (1) This does a top-bottom flip of the image, which is
579 * equivalent to a rotation out of the plane about a
580 * horizontal line through the image center.
581 * (2) There are 3 cases for input:
582 * (a) pixd == null (creates a new pixd)
583 * (b) pixd == pixs (in-place operation)
584 * (c) pixd != pixs (existing pixd)
585 * (3) For clarity, use these three patterns, respectively:
586 * (a) pixd = pixFlipTB(NULL, pixs);
587 * (b) pixFlipTB(pixs, pixs);
588 * (c) pixFlipTB(pixd, pixs);
589 * (4) If an existing pixd is not the same size as pixs, the
590 * image data will be reallocated.
591 * (5) This is simple and fast. We use the memcpy function
592 * to do all the work on aligned data, regardless of pixel
593 * depth.
594 * </pre>
595 */
596 PIX *
597 pixFlipTB(PIX *pixd,
598 PIX *pixs)
599 {
600 l_int32 h, d, wpl, i, k, h2, bpl;
601 l_uint32 *linet, *lineb;
602 l_uint32 *data, *buffer;
603
604 if (!pixs)
605 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
606 pixGetDimensions(pixs, NULL, &h, &d);
607 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
608 return (PIX *)ERROR_PTR("pixs not in {1,2,4,8,16,32} bpp",
609 __func__, NULL);
610
611 /* Prepare pixd for in-place operation */
612 if ((pixd = pixCopy(pixd, pixs)) == NULL)
613 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
614
615 data = pixGetData(pixd);
616 wpl = pixGetWpl(pixd);
617 if ((buffer = (l_uint32 *)LEPT_CALLOC(wpl, sizeof(l_uint32))) == NULL)
618 return (PIX *)ERROR_PTR("buffer not made", __func__, pixd);
619
620 h2 = h / 2;
621 bpl = 4 * wpl;
622 for (i = 0, k = h - 1; i < h2; i++, k--) {
623 linet = data + i * wpl;
624 lineb = data + k * wpl;
625 memcpy(buffer, linet, bpl);
626 memcpy(linet, lineb, bpl);
627 memcpy(lineb, buffer, bpl);
628 }
629
630 LEPT_FREE(buffer);
631 return pixd;
632 }
633
634
635 /*------------------------------------------------------------------*
636 * Static byte reverse tables *
637 *------------------------------------------------------------------*/
638 /*!
639 * \brief makeReverseByteTab1()
640 *
641 * Notes:
642 * (1) This generates an 8 bit lookup table for reversing
643 * the order of eight 1-bit pixels.
644 */
645 static l_uint8 *
646 makeReverseByteTab1(void)
647 {
648 l_int32 i;
649 l_uint8 *tab;
650
651 tab = (l_uint8 *)LEPT_CALLOC(256, sizeof(l_uint8));
652 for (i = 0; i < 256; i++)
653 tab[i] = ((0x80 & i) >> 7) |
654 ((0x40 & i) >> 5) |
655 ((0x20 & i) >> 3) |
656 ((0x10 & i) >> 1) |
657 ((0x08 & i) << 1) |
658 ((0x04 & i) << 3) |
659 ((0x02 & i) << 5) |
660 ((0x01 & i) << 7);
661 return tab;
662 }
663
664
665 /*!
666 * \brief makeReverseByteTab2()
667 *
668 * Notes:
669 * (1) This generates an 8 bit lookup table for reversing
670 * the order of four 2-bit pixels.
671 */
672 static l_uint8 *
673 makeReverseByteTab2(void)
674 {
675 l_int32 i;
676 l_uint8 *tab;
677
678 tab = (l_uint8 *)LEPT_CALLOC(256, sizeof(l_uint8));
679 for (i = 0; i < 256; i++)
680 tab[i] = ((0xc0 & i) >> 6) |
681 ((0x30 & i) >> 2) |
682 ((0x0c & i) << 2) |
683 ((0x03 & i) << 6);
684 return tab;
685 }
686
687
688 /*!
689 * \brief makeReverseByteTab4()
690 *
691 * Notes:
692 * (1) This generates an 8 bit lookup table for reversing
693 * the order of two 4-bit pixels.
694 */
695 static l_uint8 *
696 makeReverseByteTab4(void)
697 {
698 l_int32 i;
699 l_uint8 *tab;
700
701 tab = (l_uint8 *)LEPT_CALLOC(256, sizeof(l_uint8));
702 for (i = 0; i < 256; i++)
703 tab[i] = ((0xf0 & i) >> 4) | ((0x0f & i) << 4);
704 return tab;
705 }