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