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  *------------------------------------------------------------------*/
73 PIX *
75  l_uint8 *intab)
76 {
77 l_uint8 byte0, byte1;
78 l_uint8 *tab;
79 l_uint16 shortd;
80 l_int32 i, id, j, ws, hs, wpls, wpld, wplsi;
81 l_uint32 word;
82 l_uint32 *datas, *datad, *lines, *lined;
83 PIX *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  *------------------------------------------------------------------*/
151 PIX *
153  l_int32 level1,
154  l_int32 level2,
155  l_int32 level3,
156  l_int32 level4)
157 {
158 PIX *pix1, *pix2, *pix3, *pix4;
159 l_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 
226 PIX *
228  l_int32 level,
229  l_uint8 *intab)
230 {
231 l_uint8 byte0, byte1;
232 l_uint8 *tab;
233 l_uint16 shortd;
234 l_int32 i, id, j, ws, hs, wpls, wpld, wplsi;
235 l_uint32 word1, word2, word3, word4;
236 l_uint32 *datas, *datad, *lines, *lined;
237 PIX *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 
390 l_uint8 *
392 {
393 l_uint8 *tab;
394 l_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
l_uint8 * makeSubsampleTab2x(void)
makeSubsampleTab2x()
Definition: binreduce.c:391
PIX * pixReduceBinary2(PIX *pixs, l_uint8 *intab)
pixReduceBinary2()
Definition: binreduce.c:74
PIX * pixReduceRankBinary2(PIX *pixs, l_int32 level, l_uint8 *intab)
pixReduceRankBinary2()
Definition: binreduce.c:227
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
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 * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
l_ok pixSetPadBits(PIX *pix, l_int32 val)
pixSetPadBits()
Definition: pix2.c:1382
Definition: pix.h:139