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