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 *
pixFlipFHMTGen(PIX * pixd,PIX * pixs,char * selname)77 pixFlipFHMTGen(PIX   *pixd,
78                PIX   *pixs,
79                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
flipfhmtgen_low(l_uint32 * datad,l_int32 w,l_int32 h,l_int32 wpld,l_uint32 * datas,l_int32 wpls,l_int32 index)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
fhmt_1_0(l_uint32 * datad,l_int32 w,l_int32 h,l_int32 wpld,l_uint32 * datas,l_int32 wpls)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
fhmt_1_1(l_uint32 * datad,l_int32 w,l_int32 h,l_int32 wpld,l_uint32 * datas,l_int32 wpls)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
fhmt_1_2(l_uint32 * datad,l_int32 w,l_int32 h,l_int32 wpld,l_uint32 * datas,l_int32 wpls)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
fhmt_1_3(l_uint32 * datad,l_int32 w,l_int32 h,l_int32 wpld,l_uint32 * datas,l_int32 wpls)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 }
353