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