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