Leptonica  1.77.0
Image processing and image analysis suite
fliphmtgen.c
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 
27 /*
28  * fliphmtgen.c
29  *
30  * DWA implementation of hit-miss transforms with auto-generated sels
31  * for pixOrientDetectDwa() and pixUpDownDetectDwa() in flipdetect.c
32  *
33  * PIX *pixFlipFHMTGen()
34  * static l_int32 flipfhmtgen_low() -- dispatcher
35  * static void fhmt_1_0()
36  * static void fhmt_1_1()
37  * static void fhmt_1_2()
38  * static void fhmt_1_3()
39  *
40  * The code (rearranged) was generated by prog/flipselgen.c
41  */
42 
43 #include <string.h>
44 #include "allheaders.h"
45 
46 static l_int32 NUM_SELS_GENERATED = 4;
47 static char SEL_NAMES[][10] = {"flipsel1",
48  "flipsel2",
49  "flipsel3",
50  "flipsel4"};
51 
52 static l_int32 flipfhmtgen_low(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32, l_int32);
53 
54 static void fhmt_1_0(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32);
55 static void fhmt_1_1(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32);
56 static void fhmt_1_2(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32);
57 static void fhmt_1_3(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32);
58 
59 
60 /*---------------------------------------------------------------------*
61  * Top-level hmt functions *
62  *---------------------------------------------------------------------*/
63 /*
64  * pixFlipFHMTGen()
65  *
66  * Input: pixd (usual 3 choices: null, == pixs, != pixs)
67  * pixs
68  * sel name (one of four defined in SEL_NAMES[])
69  * Return: pixd
70  *
71  * Notes:
72  * Action: hit-miss transform on pixs by the sel
73  * N.B.: the sel must have at least one hit, and it
74  * can have any number of misses.
75  */
76 PIX *
77 pixFlipFHMTGen(PIX *pixd,
78  PIX *pixs,
79  const char *selname)
80 {
81 l_int32 i, index, found, w, h, wpls, wpld;
82 l_uint32 *datad, *datas, *datat;
83 PIX *pixt;
84 
85  PROCNAME("pixFlipFHMTGen");
86 
87  if (!pixs)
88  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
89  if (pixGetDepth(pixs) != 1)
90  return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, pixd);
91 
92  found = FALSE;
93  for (i = 0; i < NUM_SELS_GENERATED; i++) {
94  if (strcmp(selname, SEL_NAMES[i]) == 0) {
95  found = TRUE;
96  index = i;
97  break;
98  }
99  }
100  if (found == FALSE)
101  return (PIX *)ERROR_PTR("sel index not found", procName, pixd);
102 
103  if (pixd) {
104  if (!pixSizesEqual(pixs, pixd))
105  return (PIX *)ERROR_PTR("sizes not equal", procName, pixd);
106  } else {
107  if ((pixd = pixCreateTemplate(pixs)) == NULL)
108  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
109  }
110 
111  wpls = pixGetWpl(pixs);
112  wpld = pixGetWpl(pixd);
113 
114  /* The images must be surrounded with ADDED_BORDER white pixels,
115  * that we'll read from. We fabricate a "proper"
116  * image as the subimage within the border, having the
117  * following parameters: */
118  w = pixGetWidth(pixs) - 2 * ADDED_BORDER;
119  h = pixGetHeight(pixs) - 2 * ADDED_BORDER;
120  datas = pixGetData(pixs) + ADDED_BORDER * wpls + ADDED_BORDER / 32;
121  datad = pixGetData(pixd) + ADDED_BORDER * wpld + ADDED_BORDER / 32;
122 
123  if (pixd == pixs) { /* need temp image if in-place */
124  if ((pixt = pixCopy(NULL, pixs)) == NULL)
125  return (PIX *)ERROR_PTR("pixt not made", procName, pixd);
126  datat = pixGetData(pixt) + ADDED_BORDER * wpls + ADDED_BORDER / 32;
127  flipfhmtgen_low(datad, w, h, wpld, datat, wpls, index);
128  pixDestroy(&pixt);
129  } else { /* simple and not in-place */
130  flipfhmtgen_low(datad, w, h, wpld, datas, wpls, index);
131  }
132 
133  return pixd;
134 }
135 
136 
137 /*---------------------------------------------------------------------*
138  * Fast hmt dispatcher *
139  *---------------------------------------------------------------------*/
140 /*
141  * flipfhmtgen_low()
142  *
143  * A dispatcher to appropriate low-level code for flip hmt ops
144  */
145 static l_int32
146 flipfhmtgen_low(l_uint32 *datad,
147  l_int32 w,
148  l_int32 h,
149  l_int32 wpld,
150  l_uint32 *datas,
151  l_int32 wpls,
152  l_int32 index)
153 {
154 
155  switch (index)
156  {
157  case 0:
158  fhmt_1_0(datad, w, h, wpld, datas, wpls);
159  break;
160  case 1:
161  fhmt_1_1(datad, w, h, wpld, datas, wpls);
162  break;
163  case 2:
164  fhmt_1_2(datad, w, h, wpld, datas, wpls);
165  break;
166  case 3:
167  fhmt_1_3(datad, w, h, wpld, datas, wpls);
168  break;
169  }
170 
171  return 0;
172 }
173 
174 
175 /*--------------------------------------------------------------------------*
176  * Low-level auto-generated hmt routines *
177  *--------------------------------------------------------------------------*/
178 /*
179  * N.B. in all the low-level routines, the part of the image
180  * that is accessed has been clipped by ADDED_BORDER pixels
181  * on all four sides. This is done in the higher level
182  * code by redefining w and h smaller and by moving the
183  * start-of-image pointers up to the beginning of this
184  * interior rectangle.
185  */
186 
187 static void
188 fhmt_1_0(l_uint32 *datad,
189  l_int32 w,
190  l_int32 h,
191  l_int32 wpld,
192  l_uint32 *datas,
193  l_int32 wpls)
194 {
195 l_int32 i;
196 register l_int32 j, pwpls;
197 register l_uint32 *sptr, *dptr;
198 l_int32 wpls2, wpls3;
199 
200  wpls2 = 2 * wpls;
201  wpls3 = 3 * wpls;
202  pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */
203 
204  for (i = 0; i < h; i++) {
205  sptr = datas + i * wpls;
206  dptr = datad + i * wpld;
207  for (j = 0; j < pwpls; j++, sptr++, dptr++) {
208  *dptr = ((*(sptr - wpls) >> 3) | (*(sptr - wpls - 1) << 29)) &
209  (~*(sptr - wpls)) &
210  ((~*(sptr - wpls) << 1) | (~*(sptr - wpls + 1) >> 31)) &
211  ((*(sptr) >> 3) | (*(sptr - 1) << 29)) &
212  ((~*(sptr) >> 1) | (~*(sptr - 1) << 31)) &
213  (~*sptr) &
214  ((~*(sptr) << 1) | (~*(sptr + 1) >> 31)) &
215  ((*(sptr + wpls) >> 3) | (*(sptr + wpls - 1) << 29)) &
216  (~*(sptr + wpls)) &
217  ((*(sptr + wpls2) >> 3) | (*(sptr + wpls2 - 1) << 29)) &
218  ((*(sptr + wpls3) >> 3) | (*(sptr + wpls3 - 1) << 29)) &
219  ((*(sptr + wpls3) >> 2) | (*(sptr + wpls3 - 1) << 30)) &
220  ((*(sptr + wpls3) >> 1) | (*(sptr + wpls3 - 1) << 31)) &
221  (*(sptr + wpls3)) &
222  ((*(sptr + wpls3) << 1) | (*(sptr + wpls3 + 1) >> 31)) &
223  ((*(sptr + wpls3) << 2) | (*(sptr + wpls3 + 1) >> 30));
224  }
225  }
226 }
227 
228 
229 static void
230 fhmt_1_1(l_uint32 *datad,
231  l_int32 w,
232  l_int32 h,
233  l_int32 wpld,
234  l_uint32 *datas,
235  l_int32 wpls)
236 {
237 l_int32 i;
238 register l_int32 j, pwpls;
239 register l_uint32 *sptr, *dptr;
240 l_int32 wpls2, wpls3;
241 
242  wpls2 = 2 * wpls;
243  wpls3 = 3 * wpls;
244  pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */
245 
246  for (i = 0; i < h; i++) {
247  sptr = datas + i * wpls;
248  dptr = datad + i * wpld;
249  for (j = 0; j < pwpls; j++, sptr++, dptr++) {
250  *dptr = ((~*(sptr - wpls) >> 1) | (~*(sptr - wpls - 1) << 31)) &
251  (~*(sptr - wpls)) &
252  ((*(sptr - wpls) << 3) | (*(sptr - wpls + 1) >> 29)) &
253  ((~*(sptr) >> 1) | (~*(sptr - 1) << 31)) &
254  (~*sptr) &
255  ((~*(sptr) << 1) | (~*(sptr + 1) >> 31)) &
256  ((*(sptr) << 3) | (*(sptr + 1) >> 29)) &
257  (~*(sptr + wpls)) &
258  ((*(sptr + wpls) << 3) | (*(sptr + wpls + 1) >> 29)) &
259  ((*(sptr + wpls2) << 3) | (*(sptr + wpls2 + 1) >> 29)) &
260  ((*(sptr + wpls3) >> 2) | (*(sptr + wpls3 - 1) << 30)) &
261  ((*(sptr + wpls3) >> 1) | (*(sptr + wpls3 - 1) << 31)) &
262  (*(sptr + wpls3)) &
263  ((*(sptr + wpls3) << 1) | (*(sptr + wpls3 + 1) >> 31)) &
264  ((*(sptr + wpls3) << 2) | (*(sptr + wpls3 + 1) >> 30)) &
265  ((*(sptr + wpls3) << 3) | (*(sptr + wpls3 + 1) >> 29));
266  }
267  }
268 }
269 
270 
271 static void
272 fhmt_1_2(l_uint32 *datad,
273  l_int32 w,
274  l_int32 h,
275  l_int32 wpld,
276  l_uint32 *datas,
277  l_int32 wpls)
278 {
279 l_int32 i;
280 register l_int32 j, pwpls;
281 register l_uint32 *sptr, *dptr;
282 l_int32 wpls2, wpls3;
283 
284  wpls2 = 2 * wpls;
285  wpls3 = 3 * wpls;
286  pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */
287 
288  for (i = 0; i < h; i++) {
289  sptr = datas + i * wpls;
290  dptr = datad + i * wpld;
291  for (j = 0; j < pwpls; j++, sptr++, dptr++) {
292  *dptr = ((*(sptr - wpls3) >> 3) | (*(sptr - wpls3 - 1) << 29)) &
293  ((*(sptr - wpls3) >> 2) | (*(sptr - wpls3 - 1) << 30)) &
294  ((*(sptr - wpls3) >> 1) | (*(sptr - wpls3 - 1) << 31)) &
295  (*(sptr - wpls3)) &
296  ((*(sptr - wpls3) << 1) | (*(sptr - wpls3 + 1) >> 31)) &
297  ((*(sptr - wpls3) << 2) | (*(sptr - wpls3 + 1) >> 30)) &
298  ((*(sptr - wpls2) >> 3) | (*(sptr - wpls2 - 1) << 29)) &
299  ((*(sptr - wpls) >> 3) | (*(sptr - wpls - 1) << 29)) &
300  (~*(sptr - wpls)) &
301  ((*(sptr) >> 3) | (*(sptr - 1) << 29)) &
302  ((~*(sptr) >> 1) | (~*(sptr - 1) << 31)) &
303  (~*sptr) &
304  ((~*(sptr) << 1) | (~*(sptr + 1) >> 31)) &
305  ((*(sptr + wpls) >> 3) | (*(sptr + wpls - 1) << 29)) &
306  (~*(sptr + wpls)) &
307  ((~*(sptr + wpls) << 1) | (~*(sptr + wpls + 1) >> 31));
308  }
309  }
310 }
311 
312 
313 static void
314 fhmt_1_3(l_uint32 *datad,
315  l_int32 w,
316  l_int32 h,
317  l_int32 wpld,
318  l_uint32 *datas,
319  l_int32 wpls)
320 {
321 l_int32 i;
322 register l_int32 j, pwpls;
323 register l_uint32 *sptr, *dptr;
324 l_int32 wpls2, wpls3;
325 
326  wpls2 = 2 * wpls;
327  wpls3 = 3 * wpls;
328  pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */
329 
330  for (i = 0; i < h; i++) {
331  sptr = datas + i * wpls;
332  dptr = datad + i * wpld;
333  for (j = 0; j < pwpls; j++, sptr++, dptr++) {
334  *dptr = ((*(sptr - wpls3) >> 2) | (*(sptr - wpls3 - 1) << 30)) &
335  ((*(sptr - wpls3) >> 1) | (*(sptr - wpls3 - 1) << 31)) &
336  (*(sptr - wpls3)) &
337  ((*(sptr - wpls3) << 1) | (*(sptr - wpls3 + 1) >> 31)) &
338  ((*(sptr - wpls3) << 2) | (*(sptr - wpls3 + 1) >> 30)) &
339  ((*(sptr - wpls3) << 3) | (*(sptr - wpls3 + 1) >> 29)) &
340  ((*(sptr - wpls2) << 3) | (*(sptr - wpls2 + 1) >> 29)) &
341  (~*(sptr - wpls)) &
342  ((*(sptr - wpls) << 3) | (*(sptr - wpls + 1) >> 29)) &
343  ((~*(sptr) >> 1) | (~*(sptr - 1) << 31)) &
344  (~*sptr) &
345  ((~*(sptr) << 1) | (~*(sptr + 1) >> 31)) &
346  ((*(sptr) << 3) | (*(sptr + 1) >> 29)) &
347  ((~*(sptr + wpls) >> 1) | (~*(sptr + wpls - 1) << 31)) &
348  (~*(sptr + wpls)) &
349  ((*(sptr + wpls) << 3) | (*(sptr + wpls + 1) >> 29));
350  }
351  }
352 }
static const l_int32 ADDED_BORDER
Definition: morph.h:245
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1624
PIX * pixCreateTemplate(PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:367
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
Definition: pix.h:134
PIX * pixCopy(PIX *pixd, PIX *pixs)
pixCopy()
Definition: pix1.c:628
l_int32 pixSizesEqual(const PIX *pix1, const PIX *pix2)
pixSizesEqual()
Definition: pix1.c:781