comparison mupdf-source/thirdparty/leptonica/src/flipdetectdwa.c.notused @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
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 * \file flipdetectdwa.c.notused
29 * <pre>
30 *
31 * NOTE
32 * ==============================================================
33 * This code has been retired from the library. It is faster than
34 * the rasterop implementation, but not by a large amount. On a
35 * standard 8 Mpixel page image, the timings are:
36 * Rasterop: 0.37 sec
37 * DWA: 0.21 sec.
38 * It is preserved here to show how the dwa code can be generated
39 * and then used in an application.
40 * ==============================================================
41 *
42 * DWA page orientation detection (pure rotation by 90 degree increments):
43 * l_int32 pixOrientDetectDwa()
44 * l_int32 pixUpDownDetectDwa()
45 *
46 * DWA mirror detection (flip 180 degrees about line in plane of image):
47 * l_int32 pixMirrorDetectDwa()
48 *
49 * Low-level auto-generated DWA implementation of hit-miss transforms.
50 * This code (rearranged) was generated by prog/flipselgen.c.
51 * static PIX *pixFlipFHMTGen()
52 * --> static l_int32 flipfhmtgen_low() -- dispatcher
53 * --> static void fhmt_1_0()
54 * --> static void fhmt_1_1()
55 * --> static void fhmt_1_2()
56 * --> static void fhmt_1_3()
57 *
58 * The four Sels used are defined in prog/flipselgen.c.
59 * They are the same as those in flipdetect.c.
60 * </pre>
61 */
62
63 #ifdef HAVE_CONFIG_H
64 #include <config_auto.h>
65 #endif /* HAVE_CONFIG_H */
66
67 #include <math.h>
68 #include <string.h>
69 #include "allheaders.h"
70
71 /* Parameters for determining orientation */
72 static const l_int32 DefaultMinUpDownCount = 70;
73 static const l_float32 DefaultMinUpDownConf = 8.0;
74
75 /* Parameters for determining mirror flip */
76 static const l_int32 DefaultMinMirrorFlipCount = 100;
77 static const l_float32 DefaultMinMirrorFlipConf = 5.0;
78
79 static l_int32 NUM_SELS_GENERATED = 4;
80 static char SEL_NAMES[][10] = {"flipsel1",
81 "flipsel2",
82 "flipsel3",
83 "flipsel4"};
84
85 static l_int32 flipfhmtgen_low(l_uint32 *, l_int32, l_int32, l_int32,
86 l_uint32 *, l_int32, l_int32);
87
88 static void fhmt_1_0(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *,
89 l_int32);
90 static void fhmt_1_1(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *,
91 l_int32);
92 static void fhmt_1_2(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *,
93 l_int32);
94 static void fhmt_1_3(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *,
95 l_int32);
96
97 /*----------------------------------------------------------------*
98 * High-level interface for orientation detection *
99 * (four 90 degree angles) *
100 *----------------------------------------------------------------*/
101 /*!
102 * \brief pixOrientDetectDwa()
103 *
104 * \param[in] pixs 1 bpp, deskewed, English text
105 * \param[out] pupconf [optional] ; may be NULL
106 * \param[out] pleftconf [optional] ; may be NULL
107 * \param[in] mincount min number of up + down; use 0 for default
108 * \param[in] debug 1 for debug output; 0 otherwise
109 * \return 0 if OK, 1 on error
110 *
111 * <pre>
112 * Notes:
113 * (1) Same interface as for pixOrientDetect(). See notes
114 * there for usage.
115 * (2) Uses auto-gen'd code for the Sels defined at the
116 * top of this file, with some renaming of functions.
117 * The auto-gen'd code is in fliphmtgen.c, and can
118 * be generated by a simple executable; see prog/flipselgen.c.
119 * (3) This runs about 1.5 times faster than the pixOrientDetect().
120 * </pre>
121 */
122 l_ok
123 pixOrientDetectDwa(PIX *pixs,
124 l_float32 *pupconf,
125 l_float32 *pleftconf,
126 l_int32 mincount,
127 l_int32 debug)
128 {
129 PIX *pix1;
130
131 if (!pixs || pixGetDepth(pixs) != 1)
132 return ERROR_INT("pixs not defined or not 1 bpp", __func__, 1);
133 if (!pupconf && !pleftconf)
134 return ERROR_INT("nothing to do", __func__, 1);
135 if (mincount == 0)
136 mincount = DefaultMinUpDownCount;
137
138 if (pupconf)
139 pixUpDownDetectDwa(pixs, pupconf, mincount, 0, debug);
140 if (pleftconf) {
141 pix1 = pixRotate90(pixs, 1);
142 pixUpDownDetectDwa(pix1, pleftconf, mincount, 0, debug);
143 pixDestroy(&pix1);
144 }
145
146 return 0;
147 }
148
149
150 /*!
151 * \brief pixUpDownDetectDwa()
152 *
153 * \param[in] pixs 1 bpp, deskewed, English text, 150 - 300 ppi
154 * \param[out] pconf confidence that text is rightside-up
155 * \param[in] mincount min number of up + down; use 0 for default
156 * \param[in] npixels number of pixels removed from each side of word box
157 * \param[in] debug 1 for debug output; 0 otherwise
158 * \return 0 if OK, 1 on error
159 *
160 * <pre>
161 * Notes:
162 * (1) Faster (DWA) version of pixUpDownDetect().
163 * (2) If npixels == 0, the pixels identified through the HMT
164 * (hit-miss transform) are not clipped by a truncated word
165 * mask pixm. See pixUpDownDetect() for usage and other details.
166 * (3) The returned confidence is the normalized difference
167 * between the number of detected up and down ascenders,
168 * assuming that the text is either rightside-up or upside-down
169 * and not rotated at a 90 degree angle.
170 * </pre>
171 */
172 l_ok
173 pixUpDownDetectDwa(PIX *pixs,
174 l_float32 *pconf,
175 l_int32 mincount,
176 l_int32 npixels,
177 l_int32 debug)
178 {
179 char flipsel1[] = "flipsel1";
180 char flipsel2[] = "flipsel2";
181 char flipsel3[] = "flipsel3";
182 char flipsel4[] = "flipsel4";
183 l_int32 countup, countdown, nmax;
184 l_float32 nup, ndown;
185 PIX *pixt, *pix0, *pix1, *pix2, *pix3, *pixm;
186
187 if (!pconf)
188 return ERROR_INT("&conf not defined", __func__, 1);
189 *pconf = 0.0;
190 if (!pixs || pixGetDepth(pixs) != 1)
191 return ERROR_INT("pixs not defined or not 1 bpp", __func__, 1);
192 if (mincount == 0)
193 mincount = DefaultMinUpDownCount;
194 if (npixels < 0)
195 npixels = 0;
196
197 /* One of many reasonable pre-filtering sequences: (1, 8) and (30, 1).
198 * This closes holes in x-height characters and joins them at
199 * the x-height. There is more noise in the descender detection
200 * from this, but it works fairly well. */
201 pixt = pixMorphSequenceDwa(pixs, "c1.8 + c30.1", 0);
202
203 /* Be sure to add the border before the flip DWA operations! */
204 pix0 = pixAddBorderGeneral(pixt, ADDED_BORDER, ADDED_BORDER,
205 ADDED_BORDER, ADDED_BORDER, 0);
206 pixDestroy(&pixt);
207
208 /* Optionally, make a mask of the word bounding boxes, shortening
209 * each of them by a fixed amount at each end. */
210 pixm = NULL;
211 if (npixels > 0) {
212 l_int32 i, nbox, x, y, w, h;
213 BOX *box;
214 BOXA *boxa;
215 pix1 = pixMorphSequenceDwa(pix0, "o10.1", 0);
216 boxa = pixConnComp(pix1, NULL, 8);
217 pixm = pixCreateTemplate(pix1);
218 pixDestroy(&pix1);
219 nbox = boxaGetCount(boxa);
220 for (i = 0; i < nbox; i++) {
221 box = boxaGetBox(boxa, i, L_CLONE);
222 boxGetGeometry(box, &x, &y, &w, &h);
223 if (w > 2 * npixels)
224 pixRasterop(pixm, x + npixels, y - 6, w - 2 * npixels, h + 13,
225 PIX_SET, NULL, 0, 0);
226 boxDestroy(&box);
227 }
228 boxaDestroy(&boxa);
229 }
230
231 /* Find the ascenders and optionally filter with pixm.
232 * For an explanation of the procedure used for counting the result
233 * of the HMT, see comments in pixUpDownDetect(). */
234 pix1 = pixFlipFHMTGen(NULL, pix0, flipsel1);
235 pix2 = pixFlipFHMTGen(NULL, pix0, flipsel2);
236 pixOr(pix1, pix1, pix2);
237 if (pixm)
238 pixAnd(pix1, pix1, pixm);
239 pix3 = pixReduceRankBinaryCascade(pix1, 1, 1, 0, 0);
240 pixCountPixels(pix3, &countup, NULL);
241 pixDestroy(&pix1);
242 pixDestroy(&pix2);
243 pixDestroy(&pix3);
244
245 /* Find the ascenders and optionally filter with pixm. */
246 pix1 = pixFlipFHMTGen(NULL, pix0, flipsel3);
247 pix2 = pixFlipFHMTGen(NULL, pix0, flipsel4);
248 pixOr(pix1, pix1, pix2);
249 if (pixm)
250 pixAnd(pix1, pix1, pixm);
251 pix3 = pixReduceRankBinaryCascade(pix1, 1, 1, 0, 0);
252 pixCountPixels(pix3, &countdown, NULL);
253 pixDestroy(&pix1);
254 pixDestroy(&pix2);
255 pixDestroy(&pix3);
256
257 /* Evaluate statistically, generating a confidence that is
258 * related to the probability with a gaussian distribution. */
259 nup = (l_float32)(countup);
260 ndown = (l_float32)(countdown);
261 nmax = L_MAX(countup, countdown);
262 if (nmax > mincount)
263 *pconf = 2. * ((nup - ndown) / sqrt(nup + ndown));
264
265 if (debug) {
266 if (pixm) {
267 lept_mkdir("lept/orient");
268 pixWriteDebug("/tmp/lept/orient/pixm2.png", pixm, IFF_PNG);
269 }
270 lept_stderr("nup = %7.3f, ndown = %7.3f, conf = %7.3f\n",
271 nup, ndown, *pconf);
272 if (*pconf > DefaultMinUpDownConf)
273 lept_stderr("Text is rightside-up\n");
274 if (*pconf < -DefaultMinUpDownConf)
275 lept_stderr("Text is upside-down\n");
276 }
277
278 pixDestroy(&pix0);
279 pixDestroy(&pixm);
280 return 0;
281 }
282
283
284 /*----------------------------------------------------------------*
285 * Left-right mirror detection *
286 * DWA implementation *
287 *----------------------------------------------------------------*/
288 /*!
289 * \brief pixMirrorDetectDwa()
290 *
291 * \param[in] pixs 1 bpp, deskewed, English text
292 * \param[out] pconf confidence that text is not LR mirror reversed
293 * \param[in] mincount min number of left + right; use 0 for default
294 * \param[in] debug 1 for debug output; 0 otherwise
295 * \return 0 if OK, 1 on error
296 *
297 * <pre>
298 * Notes:
299 * (1) We assume the text is horizontally oriented, with
300 * ascenders going up.
301 * (2) See notes in pixMirrorDetect().
302 * </pre>
303 */
304 l_ok
305 pixMirrorDetectDwa(PIX *pixs,
306 l_float32 *pconf,
307 l_int32 mincount,
308 l_int32 debug)
309 {
310 char flipsel1[] = "flipsel1";
311 char flipsel2[] = "flipsel2";
312 l_int32 count1, count2, nmax;
313 l_float32 nleft, nright;
314 PIX *pix0, *pix1, *pix2, *pix3;
315
316 if (!pconf)
317 return ERROR_INT("&conf not defined", __func__, 1);
318 *pconf = 0.0;
319 if (!pixs || pixGetDepth(pixs) != 1)
320 return ERROR_INT("pixs not defined or not 1 bpp", __func__, 1);
321 if (mincount == 0)
322 mincount = DefaultMinMirrorFlipCount;
323
324 /* Fill x-height characters but not space between them, sort of. */
325 pix3 = pixMorphSequenceDwa(pixs, "d1.30", 0);
326 pixXor(pix3, pix3, pixs);
327 pix0 = pixMorphSequenceDwa(pixs, "c15.1", 0);
328 pixXor(pix0, pix0, pixs);
329 pixAnd(pix0, pix0, pix3);
330 pixOr(pix3, pix0, pixs);
331 pixDestroy(&pix0);
332 pix0 = pixAddBorderGeneral(pix3, ADDED_BORDER, ADDED_BORDER,
333 ADDED_BORDER, ADDED_BORDER, 0);
334 pixDestroy(&pix3);
335
336 /* Filter the right-facing characters. */
337 pix1 = pixFlipFHMTGen(NULL, pix0, flipsel1);
338 pix3 = pixReduceRankBinaryCascade(pix1, 1, 1, 0, 0);
339 pixCountPixels(pix3, &count1, NULL);
340 pixDestroy(&pix1);
341 pixDestroy(&pix3);
342
343 /* Filter the left-facing characters. */
344 pix2 = pixFlipFHMTGen(NULL, pix0, flipsel2);
345 pix3 = pixReduceRankBinaryCascade(pix2, 1, 1, 0, 0);
346 pixCountPixels(pix3, &count2, NULL);
347 pixDestroy(&pix2);
348 pixDestroy(&pix3);
349
350 pixDestroy(&pix0);
351 nright = (l_float32)count1;
352 nleft = (l_float32)count2;
353 nmax = L_MAX(count1, count2);
354
355 if (nmax > mincount)
356 *pconf = 2. * ((nright - nleft) / sqrt(nright + nleft));
357
358 if (debug) {
359 lept_stderr("nright = %f, nleft = %f\n", nright, nleft);
360 if (*pconf > DefaultMinMirrorFlipConf)
361 lept_stderr("Text is not mirror reversed\n");
362 if (*pconf < -DefaultMinMirrorFlipConf)
363 lept_stderr("Text is mirror reversed\n");
364 }
365
366 return 0;
367 }
368
369
370 /*---------------------------------------------------------------------*
371 * Auto-generated hmt code *
372 *---------------------------------------------------------------------*/
373 /*
374 * pixFlipFHMTGen()
375 *
376 * Input: pixd (usual 3 choices: null, == pixs, != pixs)
377 * pixs
378 * sel name (one of four defined in SEL_NAMES[])
379 * Return: pixd
380 *
381 * Notes:
382 * Action: hit-miss transform on pixs by the sel
383 * N.B.: the sel must have at least one hit, and it
384 * can have any number of misses.
385 */
386 PIX *
387 pixFlipFHMTGen(PIX *pixd,
388 PIX *pixs,
389 const char *selname)
390 {
391 l_int32 i, index, found, w, h, wpls, wpld;
392 l_uint32 *datad, *datas, *datat;
393 PIX *pixt;
394
395 if (!pixs)
396 return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
397 if (pixGetDepth(pixs) != 1)
398 return (PIX *)ERROR_PTR("pixs must be 1 bpp", __func__, pixd);
399
400 found = FALSE;
401 for (i = 0; i < NUM_SELS_GENERATED; i++) {
402 if (strcmp(selname, SEL_NAMES[i]) == 0) {
403 found = TRUE;
404 index = i;
405 break;
406 }
407 }
408 if (found == FALSE)
409 return (PIX *)ERROR_PTR("sel index not found", __func__, pixd);
410
411 if (pixd) {
412 if (!pixSizesEqual(pixs, pixd))
413 return (PIX *)ERROR_PTR("sizes not equal", __func__, pixd);
414 } else {
415 if ((pixd = pixCreateTemplate(pixs)) == NULL)
416 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
417 }
418
419 wpls = pixGetWpl(pixs);
420 wpld = pixGetWpl(pixd);
421
422 /* The images must be surrounded with ADDED_BORDER white pixels,
423 * that we'll read from. We fabricate a "proper"
424 * image as the subimage within the border, having the
425 * following parameters: */
426 w = pixGetWidth(pixs) - 2 * ADDED_BORDER;
427 h = pixGetHeight(pixs) - 2 * ADDED_BORDER;
428 datas = pixGetData(pixs) + ADDED_BORDER * wpls + ADDED_BORDER / 32;
429 datad = pixGetData(pixd) + ADDED_BORDER * wpld + ADDED_BORDER / 32;
430
431 if (pixd == pixs) { /* need temp image if in-place */
432 if ((pixt = pixCopy(NULL, pixs)) == NULL)
433 return (PIX *)ERROR_PTR("pixt not made", __func__, pixd);
434 datat = pixGetData(pixt) + ADDED_BORDER * wpls + ADDED_BORDER / 32;
435 flipfhmtgen_low(datad, w, h, wpld, datat, wpls, index);
436 pixDestroy(&pixt);
437 } else { /* simple and not in-place */
438 flipfhmtgen_low(datad, w, h, wpld, datas, wpls, index);
439 }
440
441 return pixd;
442 }
443
444
445 /*---------------------------------------------------------------------*
446 * Fast hmt dispatcher *
447 *---------------------------------------------------------------------*/
448 /*
449 * flipfhmtgen_low()
450 *
451 * A dispatcher to appropriate low-level code for flip hmt ops
452 */
453 static l_int32
454 flipfhmtgen_low(l_uint32 *datad,
455 l_int32 w,
456 l_int32 h,
457 l_int32 wpld,
458 l_uint32 *datas,
459 l_int32 wpls,
460 l_int32 index)
461 {
462
463 switch (index)
464 {
465 case 0:
466 fhmt_1_0(datad, w, h, wpld, datas, wpls);
467 break;
468 case 1:
469 fhmt_1_1(datad, w, h, wpld, datas, wpls);
470 break;
471 case 2:
472 fhmt_1_2(datad, w, h, wpld, datas, wpls);
473 break;
474 case 3:
475 fhmt_1_3(datad, w, h, wpld, datas, wpls);
476 break;
477 }
478
479 return 0;
480 }
481
482
483 /*--------------------------------------------------------------------------*
484 * Low-level auto-generated hmt routines *
485 *--------------------------------------------------------------------------*/
486 /*
487 * N.B. in all the low-level routines, the part of the image
488 * that is accessed has been clipped by ADDED_BORDER pixels
489 * on all four sides. This is done in the higher level
490 * code by redefining w and h smaller and by moving the
491 * start-of-image pointers up to the beginning of this
492 * interior rectangle.
493 */
494
495 static void
496 fhmt_1_0(l_uint32 *datad,
497 l_int32 w,
498 l_int32 h,
499 l_int32 wpld,
500 l_uint32 *datas,
501 l_int32 wpls)
502 {
503 l_int32 i;
504 l_int32 j, pwpls;
505 l_uint32 *sptr, *dptr;
506 l_int32 wpls2, wpls3;
507
508 wpls2 = 2 * wpls;
509 wpls3 = 3 * wpls;
510 pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */
511
512 for (i = 0; i < h; i++) {
513 sptr = datas + i * wpls;
514 dptr = datad + i * wpld;
515 for (j = 0; j < pwpls; j++, sptr++, dptr++) {
516 *dptr = ((*(sptr - wpls) >> 3) | (*(sptr - wpls - 1) << 29)) &
517 (~*(sptr - wpls)) &
518 ((~*(sptr - wpls) << 1) | (~*(sptr - wpls + 1) >> 31)) &
519 ((*(sptr) >> 3) | (*(sptr - 1) << 29)) &
520 ((~*(sptr) >> 1) | (~*(sptr - 1) << 31)) &
521 (~*sptr) &
522 ((~*(sptr) << 1) | (~*(sptr + 1) >> 31)) &
523 ((*(sptr + wpls) >> 3) | (*(sptr + wpls - 1) << 29)) &
524 (~*(sptr + wpls)) &
525 ((*(sptr + wpls2) >> 3) | (*(sptr + wpls2 - 1) << 29)) &
526 ((*(sptr + wpls3) >> 3) | (*(sptr + wpls3 - 1) << 29)) &
527 ((*(sptr + wpls3) >> 2) | (*(sptr + wpls3 - 1) << 30)) &
528 ((*(sptr + wpls3) >> 1) | (*(sptr + wpls3 - 1) << 31)) &
529 (*(sptr + wpls3)) &
530 ((*(sptr + wpls3) << 1) | (*(sptr + wpls3 + 1) >> 31)) &
531 ((*(sptr + wpls3) << 2) | (*(sptr + wpls3 + 1) >> 30));
532 }
533 }
534 }
535
536
537 static void
538 fhmt_1_1(l_uint32 *datad,
539 l_int32 w,
540 l_int32 h,
541 l_int32 wpld,
542 l_uint32 *datas,
543 l_int32 wpls)
544 {
545 l_int32 i;
546 l_int32 j, pwpls;
547 l_uint32 *sptr, *dptr;
548 l_int32 wpls2, wpls3;
549
550 wpls2 = 2 * wpls;
551 wpls3 = 3 * wpls;
552 pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */
553
554 for (i = 0; i < h; i++) {
555 sptr = datas + i * wpls;
556 dptr = datad + i * wpld;
557 for (j = 0; j < pwpls; j++, sptr++, dptr++) {
558 *dptr = ((~*(sptr - wpls) >> 1) | (~*(sptr - wpls - 1) << 31)) &
559 (~*(sptr - wpls)) &
560 ((*(sptr - wpls) << 3) | (*(sptr - wpls + 1) >> 29)) &
561 ((~*(sptr) >> 1) | (~*(sptr - 1) << 31)) &
562 (~*sptr) &
563 ((~*(sptr) << 1) | (~*(sptr + 1) >> 31)) &
564 ((*(sptr) << 3) | (*(sptr + 1) >> 29)) &
565 (~*(sptr + wpls)) &
566 ((*(sptr + wpls) << 3) | (*(sptr + wpls + 1) >> 29)) &
567 ((*(sptr + wpls2) << 3) | (*(sptr + wpls2 + 1) >> 29)) &
568 ((*(sptr + wpls3) >> 2) | (*(sptr + wpls3 - 1) << 30)) &
569 ((*(sptr + wpls3) >> 1) | (*(sptr + wpls3 - 1) << 31)) &
570 (*(sptr + wpls3)) &
571 ((*(sptr + wpls3) << 1) | (*(sptr + wpls3 + 1) >> 31)) &
572 ((*(sptr + wpls3) << 2) | (*(sptr + wpls3 + 1) >> 30)) &
573 ((*(sptr + wpls3) << 3) | (*(sptr + wpls3 + 1) >> 29));
574 }
575 }
576 }
577
578
579 static void
580 fhmt_1_2(l_uint32 *datad,
581 l_int32 w,
582 l_int32 h,
583 l_int32 wpld,
584 l_uint32 *datas,
585 l_int32 wpls)
586 {
587 l_int32 i;
588 l_int32 j, pwpls;
589 l_uint32 *sptr, *dptr;
590 l_int32 wpls2, wpls3;
591
592 wpls2 = 2 * wpls;
593 wpls3 = 3 * wpls;
594 pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */
595
596 for (i = 0; i < h; i++) {
597 sptr = datas + i * wpls;
598 dptr = datad + i * wpld;
599 for (j = 0; j < pwpls; j++, sptr++, dptr++) {
600 *dptr = ((*(sptr - wpls3) >> 3) | (*(sptr - wpls3 - 1) << 29)) &
601 ((*(sptr - wpls3) >> 2) | (*(sptr - wpls3 - 1) << 30)) &
602 ((*(sptr - wpls3) >> 1) | (*(sptr - wpls3 - 1) << 31)) &
603 (*(sptr - wpls3)) &
604 ((*(sptr - wpls3) << 1) | (*(sptr - wpls3 + 1) >> 31)) &
605 ((*(sptr - wpls3) << 2) | (*(sptr - wpls3 + 1) >> 30)) &
606 ((*(sptr - wpls2) >> 3) | (*(sptr - wpls2 - 1) << 29)) &
607 ((*(sptr - wpls) >> 3) | (*(sptr - wpls - 1) << 29)) &
608 (~*(sptr - wpls)) &
609 ((*(sptr) >> 3) | (*(sptr - 1) << 29)) &
610 ((~*(sptr) >> 1) | (~*(sptr - 1) << 31)) &
611 (~*sptr) &
612 ((~*(sptr) << 1) | (~*(sptr + 1) >> 31)) &
613 ((*(sptr + wpls) >> 3) | (*(sptr + wpls - 1) << 29)) &
614 (~*(sptr + wpls)) &
615 ((~*(sptr + wpls) << 1) | (~*(sptr + wpls + 1) >> 31));
616 }
617 }
618 }
619
620
621 static void
622 fhmt_1_3(l_uint32 *datad,
623 l_int32 w,
624 l_int32 h,
625 l_int32 wpld,
626 l_uint32 *datas,
627 l_int32 wpls)
628 {
629 l_int32 i;
630 l_int32 j, pwpls;
631 l_uint32 *sptr, *dptr;
632 l_int32 wpls2, wpls3;
633
634 wpls2 = 2 * wpls;
635 wpls3 = 3 * wpls;
636 pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */
637
638 for (i = 0; i < h; i++) {
639 sptr = datas + i * wpls;
640 dptr = datad + i * wpld;
641 for (j = 0; j < pwpls; j++, sptr++, dptr++) {
642 *dptr = ((*(sptr - wpls3) >> 2) | (*(sptr - wpls3 - 1) << 30)) &
643 ((*(sptr - wpls3) >> 1) | (*(sptr - wpls3 - 1) << 31)) &
644 (*(sptr - wpls3)) &
645 ((*(sptr - wpls3) << 1) | (*(sptr - wpls3 + 1) >> 31)) &
646 ((*(sptr - wpls3) << 2) | (*(sptr - wpls3 + 1) >> 30)) &
647 ((*(sptr - wpls3) << 3) | (*(sptr - wpls3 + 1) >> 29)) &
648 ((*(sptr - wpls2) << 3) | (*(sptr - wpls2 + 1) >> 29)) &
649 (~*(sptr - wpls)) &
650 ((*(sptr - wpls) << 3) | (*(sptr - wpls + 1) >> 29)) &
651 ((~*(sptr) >> 1) | (~*(sptr - 1) << 31)) &
652 (~*sptr) &
653 ((~*(sptr) << 1) | (~*(sptr + 1) >> 31)) &
654 ((*(sptr) << 3) | (*(sptr + 1) >> 29)) &
655 ((~*(sptr + wpls) >> 1) | (~*(sptr + wpls - 1) << 31)) &
656 (~*(sptr + wpls)) &
657 ((*(sptr + wpls) << 3) | (*(sptr + wpls + 1) >> 29));
658 }
659 }
660 }