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