1 /*====================================================================*
2  -  Copyright (C) 2001 Leptonica.  All rights reserved.
3  -  This software is distributed in the hope that it will be
4  -  useful, but with NO WARRANTY OF ANY KIND.
5  -  No author or distributor accepts responsibility to anyone for the
6  -  consequences of using this software, or for whether it serves any
7  -  particular purpose or works at all, unless he or she says so in
8  -  writing.  Everyone is granted permission to copy, modify and
9  -  redistribute this source code, for commercial or non-commercial
10  -  purposes, with the following restrictions: (1) the origin of this
11  -  source code must not be misrepresented; (2) modified versions must
12  -  be plainly marked as such; and (3) this notice may not be removed
13  -  or altered from any source or modified source distribution.
14  *====================================================================*/
15 
16 
17 /*
18  *  binreducelow.c
19  *
20  *          Low-level subsampled reduction
21  *                  void       reduceBinary2Low()
22  *
23  *          Low-level threshold reduction
24  *                  void       reduceRankBinary2Low()
25  *                  l_uint8   *makeSubsampleTab2x()
26  *
27  *
28  */
29 
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33 
34 #include "allheaders.h"
35 
36 
37 
38 /*-------------------------------------------------------------------*
39  *                   Low-level subsampled reduction                  *
40  *-------------------------------------------------------------------*/
41 /*!
42  *  reduceBinary2Low()
43  *
44  *  After folding, the data is in bytes 0 and 2 of the word,
45  *  and the bits in each byte are in the following order
46  *  (with 0 being the leftmost originating pair and 7 being
47  *  the rightmost originating pair):
48  *
49  *      0 4 1 5 2 6 3 7
50  *
51  *  These need to be permuted to
52  *
53  *      0 1 2 3 4 5 6 7
54  *
55  *  which is done with an 8-bit table generated by
56  *  makeSubsampleTab2x().
57  *
58  */
59 void
reduceBinary2Low(l_uint32 * datad,l_int32 wpld,l_uint32 * datas,l_int32 hs,l_int32 wpls,l_uint8 * tab)60 reduceBinary2Low(l_uint32  *datad,
61                  l_int32    wpld,
62                  l_uint32  *datas,
63                  l_int32    hs,
64                  l_int32    wpls,
65                  l_uint8   *tab)
66 {
67 l_int32    i, id, j, wplsi;
68 l_uint8    byte0, byte1;
69 l_uint16   shortd;
70 l_uint32   word;
71 l_uint32  *lines, *lined;
72 
73         /* e.g., if ws = 65: wd = 32, wpls = 3, wpld = 1 --> trouble */
74     wplsi = L_MIN(wpls, 2 * wpld);  /* iterate over this number of words */
75 
76     for (i = 0, id = 0; i < hs - 1; i += 2, id++) {
77         lines = datas + i * wpls;
78         lined = datad + id * wpld;
79         for (j = 0; j < wplsi; j++) {
80             word = *(lines + j);
81             word = word & 0xaaaaaaaa;  /* mask */
82             word = word | (word << 7);  /* fold; data in bytes 0 & 2 */
83             byte0 = word >> 24;
84             byte1 = (word >> 8) & 0xff;
85             shortd = (tab[byte0] << 8) | tab[byte1];
86             SET_DATA_TWO_BYTES(lined, j, shortd);
87         }
88     }
89 
90     return;
91 }
92 
93 
94 /*-------------------------------------------------------------------*
95  *                 Low-level rank filtered reduction                 *
96  *-------------------------------------------------------------------*/
97 /*!
98  *  reduceRankBinary2Low()
99  *
100  *  Rank filtering is done to the UL corner of each 2x2 pixel block,
101  *  using only logical operations.
102  *
103  *  Then these pixels are chosen in the 2x subsampling process,
104  *  subsampled, as described above in reduceBinary2Low().
105  */
106 void
reduceRankBinary2Low(l_uint32 * datad,l_int32 wpld,l_uint32 * datas,l_int32 hs,l_int32 wpls,l_uint8 * tab,l_int32 level)107 reduceRankBinary2Low(l_uint32  *datad,
108                      l_int32    wpld,
109                      l_uint32  *datas,
110                      l_int32    hs,
111                      l_int32    wpls,
112                      l_uint8   *tab,
113                      l_int32    level)
114 {
115 l_int32    i, id, j, wplsi;
116 l_uint8    byte0, byte1;
117 l_uint16   shortd;
118 l_uint32   word1, word2, word3, word4;
119 l_uint32  *lines, *lined;
120 
121         /* e.g., if ws = 65: wd = 32, wpls = 3, wpld = 1 --> trouble */
122     wplsi = L_MIN(wpls, 2 * wpld);  /* iterate over this number of words */
123 
124     switch (level)
125     {
126 
127     case 1:
128         for (i = 0, id = 0; i < hs - 1; i += 2, id++) {
129             lines = datas + i * wpls;
130             lined = datad + id * wpld;
131             for (j = 0; j < wplsi; j++) {
132                 word1 = *(lines + j);
133                 word2 = *(lines + wpls + j);
134 
135                     /* OR/OR */
136                 word2 = word1 | word2;
137                 word2 = word2 | (word2 << 1);
138 
139                 word2 = word2 & 0xaaaaaaaa;  /* mask */
140                 word1 = word2 | (word2 << 7);  /* fold; data in bytes 0 & 2 */
141                 byte0 = word1 >> 24;
142                 byte1 = (word1 >> 8) & 0xff;
143                 shortd = (tab[byte0] << 8) | tab[byte1];
144                 SET_DATA_TWO_BYTES(lined, j, shortd);
145             }
146         }
147         break;
148 
149     case 2:
150         for (i = 0, id = 0; i < hs - 1; i += 2, id++) {
151             lines = datas + i * wpls;
152             lined = datad + id * wpld;
153             for (j = 0; j < wplsi; j++) {
154                 word1 = *(lines + j);
155                 word2 = *(lines + wpls + j);
156 
157                     /* (AND/OR) OR (OR/AND) */
158                 word3 = word1 & word2;
159                 word3 = word3 | (word3 << 1);
160                 word4 = word1 | word2;
161                 word4 = word4 & (word4 << 1);
162                 word2 = word3 | word4;
163 
164                 word2 = word2 & 0xaaaaaaaa;  /* mask */
165                 word1 = word2 | (word2 << 7);  /* fold; data in bytes 0 & 2 */
166                 byte0 = word1 >> 24;
167                 byte1 = (word1 >> 8) & 0xff;
168                 shortd = (tab[byte0] << 8) | tab[byte1];
169                 SET_DATA_TWO_BYTES(lined, j, shortd);
170             }
171         }
172         break;
173 
174     case 3:
175         for (i = 0, id = 0; i < hs - 1; i += 2, id++) {
176             lines = datas + i * wpls;
177             lined = datad + id * wpld;
178             for (j = 0; j < wplsi; j++) {
179                 word1 = *(lines + j);
180                 word2 = *(lines + wpls + j);
181 
182                     /* (AND/OR) AND (OR/AND) */
183                 word3 = word1 & word2;
184                 word3 = word3 | (word3 << 1);
185                 word4 = word1 | word2;
186                 word4 = word4 & (word4 << 1);
187                 word2 = word3 & word4;
188 
189                 word2 = word2 & 0xaaaaaaaa;  /* mask */
190                 word1 = word2 | (word2 << 7);  /* fold; data in bytes 0 & 2 */
191                 byte0 = word1 >> 24;
192                 byte1 = (word1 >> 8) & 0xff;
193                 shortd = (tab[byte0] << 8) | tab[byte1];
194                 SET_DATA_TWO_BYTES(lined, j, shortd);
195             }
196         }
197         break;
198 
199     case 4:
200         for (i = 0, id = 0; i < hs - 1; i += 2, id++) {
201             lines = datas + i * wpls;
202             lined = datad + id * wpld;
203             for (j = 0; j < wplsi; j++) {
204                 word1 = *(lines + j);
205                 word2 = *(lines + wpls + j);
206 
207                     /* AND/AND */
208                 word2 = word1 & word2;
209                 word2 = word2 & (word2 << 1);
210 
211                 word2 = word2 & 0xaaaaaaaa;  /* mask */
212                 word1 = word2 | (word2 << 7);  /* fold; data in bytes 0 & 2 */
213                 byte0 = word1 >> 24;
214                 byte1 = (word1 >> 8) & 0xff;
215                 shortd = (tab[byte0] << 8) | tab[byte1];
216                 SET_DATA_TWO_BYTES(lined, j, shortd);
217             }
218         }
219         break;
220     }
221 
222     return;
223 }
224 
225 
226 
227 
228 /*!
229  *  makeSubsampleTab2x()
230  *
231  *  This table permutes the bits in a byte, from
232  *      0 4 1 5 2 6 3 7
233  *  to
234  *      0 1 2 3 4 5 6 7
235  */
236 l_uint8 *
makeSubsampleTab2x(void)237 makeSubsampleTab2x(void)
238 {
239 l_uint8  *tab;
240 l_int32   i;
241 
242     PROCNAME("makeSubsampleTab2x");
243 
244     if ((tab = (l_uint8 *) CALLOC(256, sizeof(l_uint8))) == NULL)
245         return (l_uint8 *)ERROR_PTR("tab not made", procName, NULL);
246 
247     for (i = 0; i < 256; i++)
248         tab[i] = ((i & 0x01)     ) |    /* 7 */
249                  ((i & 0x04) >> 1) |    /* 6 */
250                  ((i & 0x10) >> 2) |    /* 5 */
251                  ((i & 0x40) >> 3) |    /* 4 */
252                  ((i & 0x02) << 3) |    /* 3 */
253                  ((i & 0x08) << 2) |    /* 2 */
254                  ((i & 0x20) << 1) |    /* 1 */
255                  ((i & 0x80)     );     /* 0 */
256 
257     return tab;
258 }
259 
260