Leptonica 1.82.0
Image processing and image analysis suite
binreduce.c
Go to the documentation of this file.
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
43#ifdef HAVE_CONFIG_H
44#include <config_auto.h>
45#endif /* HAVE_CONFIG_H */
46
47#include <string.h>
48#include "allheaders.h"
49
50/*------------------------------------------------------------------*
51 * Subsampled reduction *
52 *------------------------------------------------------------------*/
73PIX *
75 l_uint8 *intab)
76{
77l_uint8 byte0, byte1;
78l_uint8 *tab;
79l_uint16 shortd;
80l_int32 i, id, j, ws, hs, wpls, wpld, wplsi;
81l_uint32 word;
82l_uint32 *datas, *datad, *lines, *lined;
83PIX *pixd;
84
85 PROCNAME("pixReduceBinary2");
86
87 if (!pixs || pixGetDepth(pixs) != 1)
88 return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
89
90 pixGetDimensions(pixs, &ws, &hs, NULL);
91 if (hs <= 1)
92 return (PIX *)ERROR_PTR("hs must be at least 2", procName, NULL);
93 wpls = pixGetWpl(pixs);
94 datas = pixGetData(pixs);
95 pixSetPadBits(pixs, 0);
96
97 if ((pixd = pixCreate(ws / 2, hs / 2, 1)) == NULL)
98 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
99 pixCopyResolution(pixd, pixs);
100 pixScaleResolution(pixd, 0.5, 0.5);
101 wpld = pixGetWpl(pixd);
102 datad = pixGetData(pixd);
103
104 tab = (intab) ? intab : makeSubsampleTab2x();
105 if (!tab) {
106 pixDestroy(&pixd);
107 return (PIX *)ERROR_PTR("tab not made", procName, NULL);
108 }
109
110 /* e.g., if ws = 65: wd = 32, wpls = 3, wpld = 1 --> trouble */
111 wplsi = L_MIN(wpls, 2 * wpld); /* iterate over this number of words */
112
113 for (i = 0, id = 0; i < hs - 1; i += 2, id++) {
114 lines = datas + i * wpls;
115 lined = datad + id * wpld;
116 for (j = 0; j < wplsi; j++) {
117 word = *(lines + j);
118 word = word & 0xaaaaaaaa; /* mask */
119 word = word | (word << 7); /* fold; data in bytes 0 & 2 */
120 byte0 = word >> 24;
121 byte1 = (word >> 8) & 0xff;
122 shortd = (tab[byte0] << 8) | tab[byte1];
123 SET_DATA_TWO_BYTES(lined, j, shortd);
124 }
125 }
126
127 if (!intab) LEPT_FREE(tab);
128 return pixd;
129}
130
131
132/*------------------------------------------------------------------*
133 * Rank filtered binary reductions *
134 *------------------------------------------------------------------*/
151PIX *
153 l_int32 level1,
154 l_int32 level2,
155 l_int32 level3,
156 l_int32 level4)
157{
158PIX *pix1, *pix2, *pix3, *pix4;
159l_uint8 *tab;
160
161 PROCNAME("pixReduceRankBinaryCascade");
162
163 if (!pixs)
164 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
165 if (pixGetDepth(pixs) != 1)
166 return (PIX *)ERROR_PTR("pixs must be binary", procName, NULL);
167 if (level1 > 4 || level2 > 4 || level3 > 4 || level4 > 4)
168 return (PIX *)ERROR_PTR("levels must not exceed 4", procName, NULL);
169
170 if (level1 <= 0) {
171 L_WARNING("no reduction because level1 not > 0\n", procName);
172 return pixCopy(NULL, pixs);
173 }
174
175 if ((tab = makeSubsampleTab2x()) == NULL)
176 return (PIX *)ERROR_PTR("tab not made", procName, NULL);
177
178 pix1 = pixReduceRankBinary2(pixs, level1, tab);
179 if (level2 <= 0) {
180 LEPT_FREE(tab);
181 return pix1;
182 }
183
184 pix2 = pixReduceRankBinary2(pix1, level2, tab);
185 pixDestroy(&pix1);
186 if (level3 <= 0) {
187 LEPT_FREE(tab);
188 return pix2;
189 }
190
191 pix3 = pixReduceRankBinary2(pix2, level3, tab);
192 pixDestroy(&pix2);
193 if (level4 <= 0) {
194 LEPT_FREE(tab);
195 return pix3;
196 }
197
198 pix4 = pixReduceRankBinary2(pix3, level4, tab);
199 pixDestroy(&pix3);
200 LEPT_FREE(tab);
201 return pix4;
202}
203
204
226PIX *
228 l_int32 level,
229 l_uint8 *intab)
230{
231l_uint8 byte0, byte1;
232l_uint8 *tab;
233l_uint16 shortd;
234l_int32 i, id, j, ws, hs, wpls, wpld, wplsi;
235l_uint32 word1, word2, word3, word4;
236l_uint32 *datas, *datad, *lines, *lined;
237PIX *pixd;
238
239 PROCNAME("pixReduceRankBinary2");
240
241 if (!pixs)
242 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
243
244 if (pixGetDepth(pixs) != 1)
245 return (PIX *)ERROR_PTR("pixs not binary", procName, NULL);
246 if (level < 1 || level > 4)
247 return (PIX *)ERROR_PTR("level must be in set {1,2,3,4}",
248 procName, NULL);
249
250 pixGetDimensions(pixs, &ws, &hs, NULL);
251 if (hs <= 1)
252 return (PIX *)ERROR_PTR("hs must be at least 2", procName, NULL);
253 wpls = pixGetWpl(pixs);
254 datas = pixGetData(pixs);
255 pixSetPadBits(pixs, 0);
256
257 if ((pixd = pixCreate(ws / 2, hs / 2, 1)) == NULL)
258 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
259 pixCopyResolution(pixd, pixs);
260 pixScaleResolution(pixd, 0.5, 0.5);
261 wpld = pixGetWpl(pixd);
262 datad = pixGetData(pixd);
263
264 tab = (intab) ? intab : makeSubsampleTab2x();
265 if (!tab) {
266 pixDestroy(&pixd);
267 return (PIX *)ERROR_PTR("tab not made", procName, NULL);
268 }
269
270 /* e.g., if ws = 65: wd = 32, wpls = 3, wpld = 1 --> trouble */
271 wplsi = L_MIN(wpls, 2 * wpld); /* iterate over this number of words */
272
273 switch (level)
274 {
275
276 case 1:
277 for (i = 0, id = 0; i < hs - 1; i += 2, id++) {
278 lines = datas + i * wpls;
279 lined = datad + id * wpld;
280 for (j = 0; j < wplsi; j++) {
281 word1 = *(lines + j);
282 word2 = *(lines + wpls + j);
283
284 /* OR/OR */
285 word2 = word1 | word2;
286 word2 = word2 | (word2 << 1);
287
288 word2 = word2 & 0xaaaaaaaa; /* mask */
289 word1 = word2 | (word2 << 7); /* fold; data in bytes 0 & 2 */
290 byte0 = word1 >> 24;
291 byte1 = (word1 >> 8) & 0xff;
292 shortd = (tab[byte0] << 8) | tab[byte1];
293 SET_DATA_TWO_BYTES(lined, j, shortd);
294 }
295 }
296 break;
297
298 case 2:
299 for (i = 0, id = 0; i < hs - 1; i += 2, id++) {
300 lines = datas + i * wpls;
301 lined = datad + id * wpld;
302 for (j = 0; j < wplsi; j++) {
303 word1 = *(lines + j);
304 word2 = *(lines + wpls + j);
305
306 /* (AND/OR) OR (OR/AND) */
307 word3 = word1 & word2;
308 word3 = word3 | (word3 << 1);
309 word4 = word1 | word2;
310 word4 = word4 & (word4 << 1);
311 word2 = word3 | word4;
312
313 word2 = word2 & 0xaaaaaaaa; /* mask */
314 word1 = word2 | (word2 << 7); /* fold; data in bytes 0 & 2 */
315 byte0 = word1 >> 24;
316 byte1 = (word1 >> 8) & 0xff;
317 shortd = (tab[byte0] << 8) | tab[byte1];
318 SET_DATA_TWO_BYTES(lined, j, shortd);
319 }
320 }
321 break;
322
323 case 3:
324 for (i = 0, id = 0; i < hs - 1; i += 2, id++) {
325 lines = datas + i * wpls;
326 lined = datad + id * wpld;
327 for (j = 0; j < wplsi; j++) {
328 word1 = *(lines + j);
329 word2 = *(lines + wpls + j);
330
331 /* (AND/OR) AND (OR/AND) */
332 word3 = word1 & word2;
333 word3 = word3 | (word3 << 1);
334 word4 = word1 | word2;
335 word4 = word4 & (word4 << 1);
336 word2 = word3 & word4;
337
338 word2 = word2 & 0xaaaaaaaa; /* mask */
339 word1 = word2 | (word2 << 7); /* fold; data in bytes 0 & 2 */
340 byte0 = word1 >> 24;
341 byte1 = (word1 >> 8) & 0xff;
342 shortd = (tab[byte0] << 8) | tab[byte1];
343 SET_DATA_TWO_BYTES(lined, j, shortd);
344 }
345 }
346 break;
347
348 case 4:
349 for (i = 0, id = 0; i < hs - 1; i += 2, id++) {
350 lines = datas + i * wpls;
351 lined = datad + id * wpld;
352 for (j = 0; j < wplsi; j++) {
353 word1 = *(lines + j);
354 word2 = *(lines + wpls + j);
355
356 /* AND/AND */
357 word2 = word1 & word2;
358 word2 = word2 & (word2 << 1);
359
360 word2 = word2 & 0xaaaaaaaa; /* mask */
361 word1 = word2 | (word2 << 7); /* fold; data in bytes 0 & 2 */
362 byte0 = word1 >> 24;
363 byte1 = (word1 >> 8) & 0xff;
364 shortd = (tab[byte0] << 8) | tab[byte1];
365 SET_DATA_TWO_BYTES(lined, j, shortd);
366 }
367 }
368 break;
369 }
370
371 if (!intab) LEPT_FREE(tab);
372 return pixd;
373}
374
375
390l_uint8 *
392{
393l_uint8 *tab;
394l_int32 i;
395
396 PROCNAME("makeSubsampleTab2x");
397
398 tab = (l_uint8 *) LEPT_CALLOC(256, sizeof(l_uint8));
399 for (i = 0; i < 256; i++) {
400 tab[i] = ((i & 0x01) ) | /* 7 */
401 ((i & 0x04) >> 1) | /* 6 */
402 ((i & 0x10) >> 2) | /* 5 */
403 ((i & 0x40) >> 3) | /* 4 */
404 ((i & 0x02) << 3) | /* 3 */
405 ((i & 0x08) << 2) | /* 2 */
406 ((i & 0x20) << 1) | /* 1 */
407 ((i & 0x80) ); /* 0 */
408 }
409 return tab;
410}
#define SET_DATA_TWO_BYTES(pdata, n, val)
Definition: arrayaccess.h:222
PIX * pixReduceRankBinaryCascade(PIX *pixs, l_int32 level1, l_int32 level2, l_int32 level3, l_int32 level4)
pixReduceRankBinaryCascade()
Definition: binreduce.c:152
PIX * pixReduceRankBinary2(PIX *pixs, l_int32 level, l_uint8 *intab)
pixReduceRankBinary2()
Definition: binreduce.c:227
l_uint8 * makeSubsampleTab2x(void)
makeSubsampleTab2x()
Definition: binreduce.c:391
PIX * pixReduceBinary2(PIX *pixs, l_uint8 *intab)
pixReduceBinary2()
Definition: binreduce.c:74
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1113
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
l_ok pixSetPadBits(PIX *pix, l_int32 val)
pixSetPadBits()
Definition: pix2.c:1382
Definition: pix.h:139