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