Mercurial > hgrepos > Python2 > PyMuPDF
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mupdf-source/thirdparty/leptonica/src/flipdetectdwa.c.notused Mon Sep 15 11:43:07 2025 +0200 @@ -0,0 +1,660 @@ +/*====================================================================* + - Copyright (C) 2001 Leptonica. All rights reserved. + - + - Redistribution and use in source and binary forms, with or without + - modification, are permitted provided that the following conditions + - are met: + - 1. Redistributions of source code must retain the above copyright + - notice, this list of conditions and the following disclaimer. + - 2. Redistributions in binary form must reproduce the above + - copyright notice, this list of conditions and the following + - disclaimer in the documentation and/or other materials + - provided with the distribution. + - + - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY + - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *====================================================================*/ + +/*! + * \file flipdetectdwa.c.notused + * <pre> + * + * NOTE + * ============================================================== + * This code has been retired from the library. It is faster than + * the rasterop implementation, but not by a large amount. On a + * standard 8 Mpixel page image, the timings are: + * Rasterop: 0.37 sec + * DWA: 0.21 sec. + * It is preserved here to show how the dwa code can be generated + * and then used in an application. + * ============================================================== + * + * DWA page orientation detection (pure rotation by 90 degree increments): + * l_int32 pixOrientDetectDwa() + * l_int32 pixUpDownDetectDwa() + * + * DWA mirror detection (flip 180 degrees about line in plane of image): + * l_int32 pixMirrorDetectDwa() + * + * Low-level auto-generated DWA implementation of hit-miss transforms. + * This code (rearranged) was generated by prog/flipselgen.c. + * static PIX *pixFlipFHMTGen() + * --> static l_int32 flipfhmtgen_low() -- dispatcher + * --> static void fhmt_1_0() + * --> static void fhmt_1_1() + * --> static void fhmt_1_2() + * --> static void fhmt_1_3() + * + * The four Sels used are defined in prog/flipselgen.c. + * They are the same as those in flipdetect.c. + * </pre> + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <math.h> +#include <string.h> +#include "allheaders.h" + + /* Parameters for determining orientation */ +static const l_int32 DefaultMinUpDownCount = 70; +static const l_float32 DefaultMinUpDownConf = 8.0; + + /* Parameters for determining mirror flip */ +static const l_int32 DefaultMinMirrorFlipCount = 100; +static const l_float32 DefaultMinMirrorFlipConf = 5.0; + +static l_int32 NUM_SELS_GENERATED = 4; +static char SEL_NAMES[][10] = {"flipsel1", + "flipsel2", + "flipsel3", + "flipsel4"}; + +static l_int32 flipfhmtgen_low(l_uint32 *, l_int32, l_int32, l_int32, + l_uint32 *, l_int32, l_int32); + +static void fhmt_1_0(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, + l_int32); +static void fhmt_1_1(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, + l_int32); +static void fhmt_1_2(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, + l_int32); +static void fhmt_1_3(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, + l_int32); + +/*----------------------------------------------------------------* + * High-level interface for orientation detection * + * (four 90 degree angles) * + *----------------------------------------------------------------*/ +/*! + * \brief pixOrientDetectDwa() + * + * \param[in] pixs 1 bpp, deskewed, English text + * \param[out] pupconf [optional] ; may be NULL + * \param[out] pleftconf [optional] ; may be NULL + * \param[in] mincount min number of up + down; use 0 for default + * \param[in] debug 1 for debug output; 0 otherwise + * \return 0 if OK, 1 on error + * + * <pre> + * Notes: + * (1) Same interface as for pixOrientDetect(). See notes + * there for usage. + * (2) Uses auto-gen'd code for the Sels defined at the + * top of this file, with some renaming of functions. + * The auto-gen'd code is in fliphmtgen.c, and can + * be generated by a simple executable; see prog/flipselgen.c. + * (3) This runs about 1.5 times faster than the pixOrientDetect(). + * </pre> + */ +l_ok +pixOrientDetectDwa(PIX *pixs, + l_float32 *pupconf, + l_float32 *pleftconf, + l_int32 mincount, + l_int32 debug) +{ +PIX *pix1; + + if (!pixs || pixGetDepth(pixs) != 1) + return ERROR_INT("pixs not defined or not 1 bpp", __func__, 1); + if (!pupconf && !pleftconf) + return ERROR_INT("nothing to do", __func__, 1); + if (mincount == 0) + mincount = DefaultMinUpDownCount; + + if (pupconf) + pixUpDownDetectDwa(pixs, pupconf, mincount, 0, debug); + if (pleftconf) { + pix1 = pixRotate90(pixs, 1); + pixUpDownDetectDwa(pix1, pleftconf, mincount, 0, debug); + pixDestroy(&pix1); + } + + return 0; +} + + +/*! + * \brief pixUpDownDetectDwa() + * + * \param[in] pixs 1 bpp, deskewed, English text, 150 - 300 ppi + * \param[out] pconf confidence that text is rightside-up + * \param[in] mincount min number of up + down; use 0 for default + * \param[in] npixels number of pixels removed from each side of word box + * \param[in] debug 1 for debug output; 0 otherwise + * \return 0 if OK, 1 on error + * + * <pre> + * Notes: + * (1) Faster (DWA) version of pixUpDownDetect(). + * (2) If npixels == 0, the pixels identified through the HMT + * (hit-miss transform) are not clipped by a truncated word + * mask pixm. See pixUpDownDetect() for usage and other details. + * (3) The returned confidence is the normalized difference + * between the number of detected up and down ascenders, + * assuming that the text is either rightside-up or upside-down + * and not rotated at a 90 degree angle. + * </pre> + */ +l_ok +pixUpDownDetectDwa(PIX *pixs, + l_float32 *pconf, + l_int32 mincount, + l_int32 npixels, + l_int32 debug) +{ +char flipsel1[] = "flipsel1"; +char flipsel2[] = "flipsel2"; +char flipsel3[] = "flipsel3"; +char flipsel4[] = "flipsel4"; +l_int32 countup, countdown, nmax; +l_float32 nup, ndown; +PIX *pixt, *pix0, *pix1, *pix2, *pix3, *pixm; + + if (!pconf) + return ERROR_INT("&conf not defined", __func__, 1); + *pconf = 0.0; + if (!pixs || pixGetDepth(pixs) != 1) + return ERROR_INT("pixs not defined or not 1 bpp", __func__, 1); + if (mincount == 0) + mincount = DefaultMinUpDownCount; + if (npixels < 0) + npixels = 0; + + /* One of many reasonable pre-filtering sequences: (1, 8) and (30, 1). + * This closes holes in x-height characters and joins them at + * the x-height. There is more noise in the descender detection + * from this, but it works fairly well. */ + pixt = pixMorphSequenceDwa(pixs, "c1.8 + c30.1", 0); + + /* Be sure to add the border before the flip DWA operations! */ + pix0 = pixAddBorderGeneral(pixt, ADDED_BORDER, ADDED_BORDER, + ADDED_BORDER, ADDED_BORDER, 0); + pixDestroy(&pixt); + + /* Optionally, make a mask of the word bounding boxes, shortening + * each of them by a fixed amount at each end. */ + pixm = NULL; + if (npixels > 0) { + l_int32 i, nbox, x, y, w, h; + BOX *box; + BOXA *boxa; + pix1 = pixMorphSequenceDwa(pix0, "o10.1", 0); + boxa = pixConnComp(pix1, NULL, 8); + pixm = pixCreateTemplate(pix1); + pixDestroy(&pix1); + nbox = boxaGetCount(boxa); + for (i = 0; i < nbox; i++) { + box = boxaGetBox(boxa, i, L_CLONE); + boxGetGeometry(box, &x, &y, &w, &h); + if (w > 2 * npixels) + pixRasterop(pixm, x + npixels, y - 6, w - 2 * npixels, h + 13, + PIX_SET, NULL, 0, 0); + boxDestroy(&box); + } + boxaDestroy(&boxa); + } + + /* Find the ascenders and optionally filter with pixm. + * For an explanation of the procedure used for counting the result + * of the HMT, see comments in pixUpDownDetect(). */ + pix1 = pixFlipFHMTGen(NULL, pix0, flipsel1); + pix2 = pixFlipFHMTGen(NULL, pix0, flipsel2); + pixOr(pix1, pix1, pix2); + if (pixm) + pixAnd(pix1, pix1, pixm); + pix3 = pixReduceRankBinaryCascade(pix1, 1, 1, 0, 0); + pixCountPixels(pix3, &countup, NULL); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + + /* Find the ascenders and optionally filter with pixm. */ + pix1 = pixFlipFHMTGen(NULL, pix0, flipsel3); + pix2 = pixFlipFHMTGen(NULL, pix0, flipsel4); + pixOr(pix1, pix1, pix2); + if (pixm) + pixAnd(pix1, pix1, pixm); + pix3 = pixReduceRankBinaryCascade(pix1, 1, 1, 0, 0); + pixCountPixels(pix3, &countdown, NULL); + pixDestroy(&pix1); + pixDestroy(&pix2); + pixDestroy(&pix3); + + /* Evaluate statistically, generating a confidence that is + * related to the probability with a gaussian distribution. */ + nup = (l_float32)(countup); + ndown = (l_float32)(countdown); + nmax = L_MAX(countup, countdown); + if (nmax > mincount) + *pconf = 2. * ((nup - ndown) / sqrt(nup + ndown)); + + if (debug) { + if (pixm) { + lept_mkdir("lept/orient"); + pixWriteDebug("/tmp/lept/orient/pixm2.png", pixm, IFF_PNG); + } + lept_stderr("nup = %7.3f, ndown = %7.3f, conf = %7.3f\n", + nup, ndown, *pconf); + if (*pconf > DefaultMinUpDownConf) + lept_stderr("Text is rightside-up\n"); + if (*pconf < -DefaultMinUpDownConf) + lept_stderr("Text is upside-down\n"); + } + + pixDestroy(&pix0); + pixDestroy(&pixm); + return 0; +} + + +/*----------------------------------------------------------------* + * Left-right mirror detection * + * DWA implementation * + *----------------------------------------------------------------*/ +/*! + * \brief pixMirrorDetectDwa() + * + * \param[in] pixs 1 bpp, deskewed, English text + * \param[out] pconf confidence that text is not LR mirror reversed + * \param[in] mincount min number of left + right; use 0 for default + * \param[in] debug 1 for debug output; 0 otherwise + * \return 0 if OK, 1 on error + * + * <pre> + * Notes: + * (1) We assume the text is horizontally oriented, with + * ascenders going up. + * (2) See notes in pixMirrorDetect(). + * </pre> + */ +l_ok +pixMirrorDetectDwa(PIX *pixs, + l_float32 *pconf, + l_int32 mincount, + l_int32 debug) +{ +char flipsel1[] = "flipsel1"; +char flipsel2[] = "flipsel2"; +l_int32 count1, count2, nmax; +l_float32 nleft, nright; +PIX *pix0, *pix1, *pix2, *pix3; + + if (!pconf) + return ERROR_INT("&conf not defined", __func__, 1); + *pconf = 0.0; + if (!pixs || pixGetDepth(pixs) != 1) + return ERROR_INT("pixs not defined or not 1 bpp", __func__, 1); + if (mincount == 0) + mincount = DefaultMinMirrorFlipCount; + + /* Fill x-height characters but not space between them, sort of. */ + pix3 = pixMorphSequenceDwa(pixs, "d1.30", 0); + pixXor(pix3, pix3, pixs); + pix0 = pixMorphSequenceDwa(pixs, "c15.1", 0); + pixXor(pix0, pix0, pixs); + pixAnd(pix0, pix0, pix3); + pixOr(pix3, pix0, pixs); + pixDestroy(&pix0); + pix0 = pixAddBorderGeneral(pix3, ADDED_BORDER, ADDED_BORDER, + ADDED_BORDER, ADDED_BORDER, 0); + pixDestroy(&pix3); + + /* Filter the right-facing characters. */ + pix1 = pixFlipFHMTGen(NULL, pix0, flipsel1); + pix3 = pixReduceRankBinaryCascade(pix1, 1, 1, 0, 0); + pixCountPixels(pix3, &count1, NULL); + pixDestroy(&pix1); + pixDestroy(&pix3); + + /* Filter the left-facing characters. */ + pix2 = pixFlipFHMTGen(NULL, pix0, flipsel2); + pix3 = pixReduceRankBinaryCascade(pix2, 1, 1, 0, 0); + pixCountPixels(pix3, &count2, NULL); + pixDestroy(&pix2); + pixDestroy(&pix3); + + pixDestroy(&pix0); + nright = (l_float32)count1; + nleft = (l_float32)count2; + nmax = L_MAX(count1, count2); + + if (nmax > mincount) + *pconf = 2. * ((nright - nleft) / sqrt(nright + nleft)); + + if (debug) { + lept_stderr("nright = %f, nleft = %f\n", nright, nleft); + if (*pconf > DefaultMinMirrorFlipConf) + lept_stderr("Text is not mirror reversed\n"); + if (*pconf < -DefaultMinMirrorFlipConf) + lept_stderr("Text is mirror reversed\n"); + } + + return 0; +} + + +/*---------------------------------------------------------------------* + * Auto-generated hmt code * + *---------------------------------------------------------------------*/ +/* + * pixFlipFHMTGen() + * + * Input: pixd (usual 3 choices: null, == pixs, != pixs) + * pixs + * sel name (one of four defined in SEL_NAMES[]) + * Return: pixd + * + * Notes: + * Action: hit-miss transform on pixs by the sel + * N.B.: the sel must have at least one hit, and it + * can have any number of misses. + */ +PIX * +pixFlipFHMTGen(PIX *pixd, + PIX *pixs, + const char *selname) +{ +l_int32 i, index, found, w, h, wpls, wpld; +l_uint32 *datad, *datas, *datat; +PIX *pixt; + + if (!pixs) + return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd); + if (pixGetDepth(pixs) != 1) + return (PIX *)ERROR_PTR("pixs must be 1 bpp", __func__, pixd); + + found = FALSE; + for (i = 0; i < NUM_SELS_GENERATED; i++) { + if (strcmp(selname, SEL_NAMES[i]) == 0) { + found = TRUE; + index = i; + break; + } + } + if (found == FALSE) + return (PIX *)ERROR_PTR("sel index not found", __func__, pixd); + + if (pixd) { + if (!pixSizesEqual(pixs, pixd)) + return (PIX *)ERROR_PTR("sizes not equal", __func__, pixd); + } else { + if ((pixd = pixCreateTemplate(pixs)) == NULL) + return (PIX *)ERROR_PTR("pixd not made", __func__, NULL); + } + + wpls = pixGetWpl(pixs); + wpld = pixGetWpl(pixd); + + /* The images must be surrounded with ADDED_BORDER white pixels, + * that we'll read from. We fabricate a "proper" + * image as the subimage within the border, having the + * following parameters: */ + w = pixGetWidth(pixs) - 2 * ADDED_BORDER; + h = pixGetHeight(pixs) - 2 * ADDED_BORDER; + datas = pixGetData(pixs) + ADDED_BORDER * wpls + ADDED_BORDER / 32; + datad = pixGetData(pixd) + ADDED_BORDER * wpld + ADDED_BORDER / 32; + + if (pixd == pixs) { /* need temp image if in-place */ + if ((pixt = pixCopy(NULL, pixs)) == NULL) + return (PIX *)ERROR_PTR("pixt not made", __func__, pixd); + datat = pixGetData(pixt) + ADDED_BORDER * wpls + ADDED_BORDER / 32; + flipfhmtgen_low(datad, w, h, wpld, datat, wpls, index); + pixDestroy(&pixt); + } else { /* simple and not in-place */ + flipfhmtgen_low(datad, w, h, wpld, datas, wpls, index); + } + + return pixd; +} + + +/*---------------------------------------------------------------------* + * Fast hmt dispatcher * + *---------------------------------------------------------------------*/ +/* + * flipfhmtgen_low() + * + * A dispatcher to appropriate low-level code for flip hmt ops + */ +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) +{ + + switch (index) + { + case 0: + fhmt_1_0(datad, w, h, wpld, datas, wpls); + break; + case 1: + fhmt_1_1(datad, w, h, wpld, datas, wpls); + break; + case 2: + fhmt_1_2(datad, w, h, wpld, datas, wpls); + break; + case 3: + fhmt_1_3(datad, w, h, wpld, datas, wpls); + break; + } + + return 0; +} + + +/*--------------------------------------------------------------------------* + * Low-level auto-generated hmt routines * + *--------------------------------------------------------------------------*/ +/* + * N.B. in all the low-level routines, the part of the image + * that is accessed has been clipped by ADDED_BORDER pixels + * on all four sides. This is done in the higher level + * code by redefining w and h smaller and by moving the + * start-of-image pointers up to the beginning of this + * interior rectangle. + */ + +static void +fhmt_1_0(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr - wpls) >> 3) | (*(sptr - wpls - 1) << 29)) & + (~*(sptr - wpls)) & + ((~*(sptr - wpls) << 1) | (~*(sptr - wpls + 1) >> 31)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((~*(sptr) >> 1) | (~*(sptr - 1) << 31)) & + (~*sptr) & + ((~*(sptr) << 1) | (~*(sptr + 1) >> 31)) & + ((*(sptr + wpls) >> 3) | (*(sptr + wpls - 1) << 29)) & + (~*(sptr + wpls)) & + ((*(sptr + wpls2) >> 3) | (*(sptr + wpls2 - 1) << 29)) & + ((*(sptr + wpls3) >> 3) | (*(sptr + wpls3 - 1) << 29)) & + ((*(sptr + wpls3) >> 2) | (*(sptr + wpls3 - 1) << 30)) & + ((*(sptr + wpls3) >> 1) | (*(sptr + wpls3 - 1) << 31)) & + (*(sptr + wpls3)) & + ((*(sptr + wpls3) << 1) | (*(sptr + wpls3 + 1) >> 31)) & + ((*(sptr + wpls3) << 2) | (*(sptr + wpls3 + 1) >> 30)); + } + } +} + + +static void +fhmt_1_1(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((~*(sptr - wpls) >> 1) | (~*(sptr - wpls - 1) << 31)) & + (~*(sptr - wpls)) & + ((*(sptr - wpls) << 3) | (*(sptr - wpls + 1) >> 29)) & + ((~*(sptr) >> 1) | (~*(sptr - 1) << 31)) & + (~*sptr) & + ((~*(sptr) << 1) | (~*(sptr + 1) >> 31)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + (~*(sptr + wpls)) & + ((*(sptr + wpls) << 3) | (*(sptr + wpls + 1) >> 29)) & + ((*(sptr + wpls2) << 3) | (*(sptr + wpls2 + 1) >> 29)) & + ((*(sptr + wpls3) >> 2) | (*(sptr + wpls3 - 1) << 30)) & + ((*(sptr + wpls3) >> 1) | (*(sptr + wpls3 - 1) << 31)) & + (*(sptr + wpls3)) & + ((*(sptr + wpls3) << 1) | (*(sptr + wpls3 + 1) >> 31)) & + ((*(sptr + wpls3) << 2) | (*(sptr + wpls3 + 1) >> 30)) & + ((*(sptr + wpls3) << 3) | (*(sptr + wpls3 + 1) >> 29)); + } + } +} + + +static void +fhmt_1_2(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr - wpls3) >> 3) | (*(sptr - wpls3 - 1) << 29)) & + ((*(sptr - wpls3) >> 2) | (*(sptr - wpls3 - 1) << 30)) & + ((*(sptr - wpls3) >> 1) | (*(sptr - wpls3 - 1) << 31)) & + (*(sptr - wpls3)) & + ((*(sptr - wpls3) << 1) | (*(sptr - wpls3 + 1) >> 31)) & + ((*(sptr - wpls3) << 2) | (*(sptr - wpls3 + 1) >> 30)) & + ((*(sptr - wpls2) >> 3) | (*(sptr - wpls2 - 1) << 29)) & + ((*(sptr - wpls) >> 3) | (*(sptr - wpls - 1) << 29)) & + (~*(sptr - wpls)) & + ((*(sptr) >> 3) | (*(sptr - 1) << 29)) & + ((~*(sptr) >> 1) | (~*(sptr - 1) << 31)) & + (~*sptr) & + ((~*(sptr) << 1) | (~*(sptr + 1) >> 31)) & + ((*(sptr + wpls) >> 3) | (*(sptr + wpls - 1) << 29)) & + (~*(sptr + wpls)) & + ((~*(sptr + wpls) << 1) | (~*(sptr + wpls + 1) >> 31)); + } + } +} + + +static void +fhmt_1_3(l_uint32 *datad, + l_int32 w, + l_int32 h, + l_int32 wpld, + l_uint32 *datas, + l_int32 wpls) +{ +l_int32 i; +l_int32 j, pwpls; +l_uint32 *sptr, *dptr; +l_int32 wpls2, wpls3; + + wpls2 = 2 * wpls; + wpls3 = 3 * wpls; + pwpls = (l_uint32)(w + 31) / 32; /* proper wpl of src */ + + for (i = 0; i < h; i++) { + sptr = datas + i * wpls; + dptr = datad + i * wpld; + for (j = 0; j < pwpls; j++, sptr++, dptr++) { + *dptr = ((*(sptr - wpls3) >> 2) | (*(sptr - wpls3 - 1) << 30)) & + ((*(sptr - wpls3) >> 1) | (*(sptr - wpls3 - 1) << 31)) & + (*(sptr - wpls3)) & + ((*(sptr - wpls3) << 1) | (*(sptr - wpls3 + 1) >> 31)) & + ((*(sptr - wpls3) << 2) | (*(sptr - wpls3 + 1) >> 30)) & + ((*(sptr - wpls3) << 3) | (*(sptr - wpls3 + 1) >> 29)) & + ((*(sptr - wpls2) << 3) | (*(sptr - wpls2 + 1) >> 29)) & + (~*(sptr - wpls)) & + ((*(sptr - wpls) << 3) | (*(sptr - wpls + 1) >> 29)) & + ((~*(sptr) >> 1) | (~*(sptr - 1) << 31)) & + (~*sptr) & + ((~*(sptr) << 1) | (~*(sptr + 1) >> 31)) & + ((*(sptr) << 3) | (*(sptr + 1) >> 29)) & + ((~*(sptr + wpls) >> 1) | (~*(sptr + wpls - 1) << 31)) & + (~*(sptr + wpls)) & + ((*(sptr + wpls) << 3) | (*(sptr + wpls + 1) >> 29)); + } + } +}
