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