Exemple #1
0
/*!
 *  pixApplyHorizontalDisparity()
 *
 *      Input:  pixs (1, 8 or 32 bpp)
 *              fpix (horizontal disparity array)
 *              extraw (extra width added to pixd)
 *      Return: pixd (modified by fpix), or null on error
 *
 *  Notes:
 *      (1) This applies the horizontal disparity array to the specified
 *          image.
 */
PIX *
pixApplyHorizontalDisparity(PIX     *pixs,
                            FPIX    *fpix,
                            l_int32  extraw)
{
l_int32     i, j, w, h, d, wd, fw, fh, wpls, wpld, wplf, jsrc, val8;
l_uint32   *datas, *lines, *datad, *lined;
l_float32  *dataf, *linef;
PIX        *pixd;

    PROCNAME("pixApplyHorizontalDisparity");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (!fpix)
        return (PIX *)ERROR_PTR("fpix not defined", procName, NULL);
    pixGetDimensions(pixs, &w, &h, &d);
    if (d != 1 && d != 8 && d != 32)
        return (PIX *)ERROR_PTR("pix not 1, 8 or 32 bpp", procName, NULL);
    fpixGetDimensions(fpix, &fw, &fh);
    if (fw < w + extraw || fh < h) {
        fprintf(stderr, "fw = %d, w = %d, fh = %d, h = %d\n", fw, w, fh, h);
        return (PIX *)ERROR_PTR("invalid fpix size", procName, NULL);
    }

    wd = w + extraw;
    pixd = pixCreate(wd, h, d);
    datas = pixGetData(pixs);
    datad = pixGetData(pixd);
    dataf = fpixGetData(fpix);
    wpls = pixGetWpl(pixs);
    wpld = pixGetWpl(pixd);
    wplf = fpixGetWpl(fpix);
    if (d == 1) {
        for (i = 0; i < h; i++) {
            lines = datas + i * wpls;
            lined = datad + i * wpld;
            linef = dataf + i * wplf;
            for (j = 0; j < wd; j++) {
                jsrc = (l_int32)(j - linef[j] + 0.5);
                if (jsrc < 0) jsrc = 0;
                if (jsrc > w - 1) jsrc = w - 1;
                if (GET_DATA_BIT(lines, jsrc))
                    SET_DATA_BIT(lined, j);
            }
        }
    }
    else if (d == 8) {
        for (i = 0; i < h; i++) {
            lines = datas + i * wpls;
            lined = datad + i * wpld;
            linef = dataf + i * wplf;
            for (j = 0; j < wd; j++) {
                jsrc = (l_int32)(j - linef[j] + 0.5);
                if (jsrc < 0) jsrc = 0;
                if (jsrc > w - 1) jsrc = w - 1;
                val8 = GET_DATA_BYTE(lines, jsrc);
                SET_DATA_BYTE(lined, j, val8);
            }
        }
    }
    else {  /* d == 32 */
        for (i = 0; i < h; i++) {
            lines = datas + i * wpls;
            lined = datad + i * wpld;
            linef = dataf + i * wplf;
            for (j = 0; j < wd; j++) {
                jsrc = (l_int32)(j - linef[j] + 0.5);
                if (jsrc < 0) jsrc = 0;
                if (jsrc > w - 1) jsrc = w - 1;
                lined[j] = lines[jsrc];
            }
        }
    }

    return pixd;
}
Exemple #2
0
/*!
 *  fpixLinearCombo()
 *
 *      Input:  fpixd (<optional>; this can be null, equal to fpixs1, or
 *                     different from fpixs1)
 *              fpixs1 (can be == to fpixd)
 *              fpixs2
 *      Return: pixd always
 *  
 *  Notes:
 *      (1) Computes pixelwise linear combination: a * src1 + b * src2
 *      (2) Alignment is to UL corner.
 *      (3) There are 3 cases.  The result can go to a new dest,
 *          in-place to fpixs1, or to an existing input dest:
 *          * fpixd == null:   (src1 + src2) --> new fpixd
 *          * fpixd == fpixs1:  (src1 + src2) --> src1  (in-place)
 *          * fpixd != fpixs1: (src1 + src2) --> input fpixd
 *      (4) fpixs2 must be different from both fpixd and fpixs1.
 */
FPIX *
fpixLinearCombination(FPIX      *fpixd,
                      FPIX      *fpixs1,
                      FPIX      *fpixs2,
                      l_float32  a,
                      l_float32  b)
{
l_int32     i, j, ws, hs, w, h, wpls, wpld;
l_float32   val;
l_float32  *datas, *datad, *lines, *lined;

    PROCNAME("fpixLinearCombination");

    if (!fpixs1)
        return (FPIX *)ERROR_PTR("fpixs1 not defined", procName, fpixd);
    if (!fpixs2)
        return (FPIX *)ERROR_PTR("fpixs2 not defined", procName, fpixd);
    if (fpixs1 == fpixs2)
        return (FPIX *)ERROR_PTR("fpixs1 == fpixs2", procName, fpixd);
    if (fpixs2 == fpixd)
        return (FPIX *)ERROR_PTR("fpixs2 == fpixd", procName, fpixd);

    if (fpixs1 != fpixd)
        fpixd = fpixCopy(fpixd, fpixs1);

    datas = fpixGetData(fpixs2);
    datad = fpixGetData(fpixd);
    wpls = fpixGetWpl(fpixs2);
    wpld = fpixGetWpl(fpixd);
    fpixGetDimensions(fpixs2, &ws, &hs);
    fpixGetDimensions(fpixd, &w, &h);
    w = L_MIN(ws, w);
    h = L_MIN(hs, h);
    for (i = 0; i < h; i++) {
        lines = datas + i * wpls;
        lined = datad + i * wpld;
        if (a == 1.0 && b == 1.0) {  /* sum */
            for (j = 0; j < w; j++)
                *(lined + j) += *(lines + j);
        }
        else if (a == 1.0 && b == -1.0) {  /* diff */
            for (j = 0; j < w; j++)
                *(lined + j) -= *(lines + j);
        }
        else if (a == -1.0 && b == 1.0) {  /* diff */
            for (j = 0; j < w; j++) {
                val = *(lined + j);
                *(lined + j) = -val + *(lines + j);
            }
        }
        else if (a == -1.0 && b == -1.0) {
            for (j = 0; j < w; j++) {
                val = *(lined + j);
                *(lined + j) = -val - *(lines + j);
            }
        }
        else {
            for (j = 0; j < w; j++)
                *(lined + j) = a * lined[j] + b * lines[j];
        }
    }

    return fpixd;
}
Exemple #3
0
/*!
 *  pixApplyVerticalDisparity()
 *
 *      Input:  pixs (1, 8 or 32 bpp)
 *              fpix (vertical disparity array)
 *      Return: pixd (modified by fpix), or null on error
 *
 *  Notes:
 *      (1) This applies the vertical disparity array to the specified
 *          image.  For src pixels above the image, we use the pixels
 *          in the first raster line.
 */
PIX *
pixApplyVerticalDisparity(PIX   *pixs,
                          FPIX  *fpix)
{
l_int32     i, j, w, h, d, fw, fh, wpld, wplf, isrc, val8;
l_uint32   *datad, *lined;
l_float32  *dataf, *linef;
void      **lineptrs;
PIX        *pixd;

    PROCNAME("pixApplyVerticalDisparity");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (!fpix)
        return (PIX *)ERROR_PTR("fpix not defined", procName, NULL);
    pixGetDimensions(pixs, &w, &h, &d);
    if (d != 1 && d != 8 && d != 32)
        return (PIX *)ERROR_PTR("pix not 1, 8 or 32 bpp", procName, NULL);
    fpixGetDimensions(fpix, &fw, &fh);
    if (fw < w || fh < h) {
        fprintf(stderr, "fw = %d, w = %d, fh = %d, h = %d\n", fw, w, fh, h);
        return (PIX *)ERROR_PTR("invalid fpix size", procName, NULL);
    }

    pixd = pixCreateTemplate(pixs);
    datad = pixGetData(pixd);
    dataf = fpixGetData(fpix);
    wpld = pixGetWpl(pixd);
    wplf = fpixGetWpl(fpix);
    if (d == 1) {
        lineptrs = pixGetLinePtrs(pixs, NULL);
        for (i = 0; i < h; i++) {
            lined = datad + i * wpld;
            linef = dataf + i * wplf;
            for (j = 0; j < w; j++) {
                isrc = (l_int32)(i - linef[j] + 0.5);
                if (isrc < 0) isrc = 0;
                if (isrc > h - 1) isrc = h - 1;
                if (GET_DATA_BIT(lineptrs[isrc], j))
                    SET_DATA_BIT(lined, j);
            }
        }
    }
    else if (d == 8) {
        lineptrs = pixGetLinePtrs(pixs, NULL);
        for (i = 0; i < h; i++) {
            lined = datad + i * wpld;
            linef = dataf + i * wplf;
            for (j = 0; j < w; j++) {
                isrc = (l_int32)(i - linef[j] + 0.5);
                if (isrc < 0) isrc = 0;
                if (isrc > h - 1) isrc = h - 1;
                val8 = GET_DATA_BYTE(lineptrs[isrc], j);
                SET_DATA_BYTE(lined, j, val8);
            }
        }
    }
    else {  /* d == 32 */
        lineptrs = pixGetLinePtrs(pixs, NULL);
        for (i = 0; i < h; i++) {
            lined = datad + i * wpld;
            linef = dataf + i * wplf;
            for (j = 0; j < w; j++) {
                isrc = (l_int32)(i - linef[j] + 0.5);
                if (isrc < 0) isrc = 0;
                if (isrc > h - 1) isrc = h - 1;
                lined[j] = GET_DATA_FOUR_BYTES(lineptrs[isrc], j);
            }
        }
    }

    FREE(lineptrs);
    return pixd;
}
Exemple #4
0
/*!
 *  fpixRasterop()
 *
 *      Input:  fpixd  (dest fpix)
 *              dx     (x val of UL corner of dest rectangle)
 *              dy     (y val of UL corner of dest rectangle)
 *              dw     (width of dest rectangle)
 *              dh     (height of dest rectangle)
 *              fpixs  (src fpix)
 *              sx     (x val of UL corner of src rectangle)
 *              sy     (y val of UL corner of src rectangle)
 *      Return: 0 if OK; 1 on error.
 *
 *  Notes:
 *      (1) This is similiar in structure to pixRasterop(), except
 *          it only allows copying from the source into the destination.
 *          For that reason, no op code is necessary.  Additionally,
 *          all pixels are 32 bit words (float values), which makes
 *          the copy very simple.
 *      (2) Clipping of both src and dest fpix are done automatically.
 *      (3) This allows in-place copying, without checking to see if
 *          the result is valid:  use for in-place with caution!
 */
l_int32
fpixRasterop(FPIX    *fpixd,
             l_int32  dx,
             l_int32  dy,
             l_int32  dw,
             l_int32  dh,
             FPIX    *fpixs,
             l_int32  sx,
             l_int32  sy)
{
l_int32     fsw, fsh, fdw, fdh, dhangw, shangw, dhangh, shangh;
l_int32     i, j, wpls, wpld;
l_float32  *datas, *datad, *lines, *lined;

    PROCNAME("fpixRasterop");

    if (!fpixs)
        return ERROR_INT("fpixs not defined", procName, 1);
    if (!fpixd)
        return ERROR_INT("fpixd not defined", procName, 1);

    /* -------------------------------------------------------- *
     *      Clip to maximum rectangle with both src and dest    *
     * -------------------------------------------------------- */
    fpixGetDimensions(fpixs, &fsw, &fsh);
    fpixGetDimensions(fpixd, &fdw, &fdh);

        /* First clip horizontally (sx, dx, dw) */
    if (dx < 0) {
        sx -= dx;  /* increase sx */
        dw += dx;  /* reduce dw */
        dx = 0;
    }
    if (sx < 0) {
        dx -= sx;  /* increase dx */
        dw += sx;  /* reduce dw */
        sx = 0;
    }
    dhangw = dx + dw - fdw;  /* rect overhang of dest to right */
    if (dhangw > 0)
        dw -= dhangw;  /* reduce dw */
    shangw = sx + dw - fsw;   /* rect overhang of src to right */
    if (shangw > 0)
        dw -= shangw;  /* reduce dw */

        /* Then clip vertically (sy, dy, dh) */
    if (dy < 0) {
        sy -= dy;  /* increase sy */
        dh += dy;  /* reduce dh */
        dy = 0;
    }
    if (sy < 0) {
        dy -= sy;  /* increase dy */
        dh += sy;  /* reduce dh */
        sy = 0;
    }
    dhangh = dy + dh - fdh;  /* rect overhang of dest below */
    if (dhangh > 0)
        dh -= dhangh;  /* reduce dh */
    shangh = sy + dh - fsh;  /* rect overhang of src below */
    if (shangh > 0)
        dh -= shangh;  /* reduce dh */

        /* if clipped entirely, quit */
    if ((dw <= 0) || (dh <= 0))
        return 0;

    /* -------------------------------------------------------- *
     *                    Copy block of data                    *
     * -------------------------------------------------------- */
    datas = fpixGetData(fpixs);
    datad = fpixGetData(fpixd);
    wpls = fpixGetWpl(fpixs);
    wpld = fpixGetWpl(fpixd);
    datas += sy * wpls + sx;  /* at UL corner of block */
    datad += dy * wpld + dx;  /* at UL corner of block */
    for (i = 0; i < dh; i++) {
        lines = datas + i * wpls;
        lined = datad + i * wpld;
        for (j = 0; j < dw; j++) {
            *lined = *lines;
            lines++;
            lined++;
        }
    }

    return 0;
}
Exemple #5
0
/*!
 *  fpixConvertToPix()
 *
 *      Input:  fpixs 
 *              outdepth (0, 8, 16 or 32 bpp)
 *              negvals (L_CLIP_TO_ZERO, L_TAKE_ABSVAL)
 *              errorflag (1 to output error stats; 0 otherwise)
 *      Return: pixd, or null on error
 *
 *  Notes:
 *      (1) Use @outdepth = 0 to programmatically determine the
 *          output depth.  If no values are greater than 255,
 *          it will set outdepth = 8; otherwise to 16 or 32.
 *      (2) Because we are converting a float to an unsigned int
 *          with a specified dynamic range (8, 16 or 32 bits), errors
 *          can occur.  If errorflag == TRUE, output the number
 *          of values out of range, both negative and positive.
 *      (3) If a pixel value is positive and out of range, clip to
 *          the maximum value represented at the outdepth of 8, 16
 *          or 32 bits.
 */
PIX *
fpixConvertToPix(FPIX    *fpixs,
                 l_int32  outdepth,
                 l_int32  negvals,
                 l_int32  errorflag)
{
l_int32     w, h, i, j, wpls, wpld, maxval;
l_uint32    vald;
l_float32   val;
l_float32  *datas, *lines;
l_uint32   *datad, *lined;
PIX        *pixd;

    PROCNAME("fpixConvertToPix");

    if (!fpixs)
        return (PIX *)ERROR_PTR("fpixs not defined", procName, NULL);
    if (negvals != L_CLIP_TO_ZERO && negvals != L_TAKE_ABSVAL)
        return (PIX *)ERROR_PTR("invalid negvals", procName, NULL);
    if (outdepth != 0 && outdepth != 8 && outdepth != 16 && outdepth != 32)
        return (PIX *)ERROR_PTR("outdepth not in {0,8,16,32}", procName, NULL);

    fpixGetDimensions(fpixs, &w, &h);
    datas = fpixGetData(fpixs);
    wpls = fpixGetWpl(fpixs);

        /* Adaptive determination of output depth */
    if (outdepth == 0) {
        outdepth = 8;
        for (i = 0; i < h; i++) {
            lines = datas + i * wpls;
            for (j = 0; j < w; j++) {
                if (lines[j] > 65535.5) {
                    outdepth = 32;
                    break;
                }
                if (lines[j] > 255.5)
                    outdepth = 16;
            }
            if (outdepth == 32) break;
        }
    }
    maxval = (1 << outdepth) - 1;

        /* Gather statistics if @errorflag = TRUE */
    if (errorflag) {
        l_int32  negs = 0;
        l_int32  overvals = 0;
        for (i = 0; i < h; i++) {
            lines = datas + i * wpls;
            for (j = 0; j < w; j++) {
                val = lines[j];
                if (val < 0.0)
                    negs++;
                else if (val > maxval)
                    overvals++;
            }
        }
        if (negs > 0)
            L_ERROR_INT("Number of negative values: %d", procName, negs);
        if (overvals > 0)
            L_ERROR_INT("Number of too-large values: %d", procName, overvals);
    }

        /* Make the pix and convert the data */
    if ((pixd = pixCreate(w, h, outdepth)) == NULL)
        return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    datad = pixGetData(pixd);
    wpld = pixGetWpl(pixd);
    for (i = 0; i < h; i++) {
	lines = datas + i * wpls;
	lined = datad + i * wpld;
	for (j = 0; j < w; j++) {
	    val = lines[j];
            if (val >= 0.0)
                vald = (l_uint32)(val + 0.5);
            else {  /* val < 0.0 */
                if (negvals == L_CLIP_TO_ZERO)
                    vald = 0;
                else
                    vald = (l_uint32)(-val + 0.5);
            }
            if (vald > maxval)
                vald = maxval;
            if (outdepth == 8)
                SET_DATA_BYTE(lined, j, vald);
            else if (outdepth == 16)
                SET_DATA_TWO_BYTES(lined, j, vald);
            else  /* outdepth == 32 */
                SET_DATA_FOUR_BYTES(lined, j, vald);
        }  
    }

    return pixd;
}
Exemple #6
0
/*!
 *  dewarpPopulateFullRes()
 *
 *      Input:  dew
 *              pix (<optional>, to give size of actual image)
 *              x, y (origin for generation of disparity arrays)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) If the full resolution vertical and horizontal disparity
 *          arrays do not exist, they are built from the subsampled ones.
 *      (2) If pixs is not given, the size of the arrays is determined
 *          by the original image from which the sampled version was
 *          generated.  Any values of (x,y) are ignored.
 *      (3) If pixs is given, the full resolution disparity arrays must
 *          be large enough to accommodate it.
 *          (a) If the arrays do not exist, the value of (x,y) determines
 *              the origin of the full resolution arrays without extension,
 *              relative to pixs.  Thus, (x,y) gives the amount of
 *              slope extension in (left, top).  The (right, bottom)
 *              extension is then determined by the size of pixs and
 *              (x,y); the values should never be < 0.
 *          (b) If the arrays exist and pixs is too large, the existing
 *              full res arrays are destroyed and new ones are made,
 *              again using (x,y) to determine the extension in the
 *              four directions.
 */
l_int32
dewarpPopulateFullRes(L_DEWARP  *dew,
                      PIX       *pix,
                      l_int32    x,
                      l_int32    y)
{
l_int32     width, height, fw, fh, deltaw, deltah, redfactor;
FPIX       *fpixt1, *fpixt2;

    PROCNAME("dewarpPopulateFullRes");

    if (!dew)
        return ERROR_INT("dew not defined", procName, 1);
    if (!dew->sampvdispar)
        return ERROR_INT("no sampled vert disparity", procName, 1);
    if (x < 0) x = 0;
    if (y < 0) y = 0;

        /* Establish the target size for the full res arrays */
    if (pix)
        pixGetDimensions(pix, &width, &height, NULL);
    else {
        width = dew->w;
        height = dew->h;
    }

        /* Destroy the existing arrays if they are too small */
    if (dew->fullvdispar) {
        fpixGetDimensions(dew->fullvdispar, &fw, &fh);
        if (width > fw || height > fw)
            fpixDestroy(&dew->fullvdispar);
    }
    if (dew->fullhdispar) {
        fpixGetDimensions(dew->fullhdispar, &fw, &fh);
        if (width > fw || height > fw)
            fpixDestroy(&dew->fullhdispar);
    }

        /* Find the required width and height expansion deltas */
    deltaw = width - dew->sampling * (dew->nx - 1) + 2;
    deltah = height - dew->sampling * (dew->ny - 1) + 2;
    redfactor = dew->redfactor;
    deltaw = redfactor * L_MAX(0, deltaw);
    deltah = redfactor * L_MAX(0, deltah);

        /* Generate the full res vertical array if it doesn't exist,
         * extending it as required to make it big enough.  Use x,y
         * to determine the amounts on each side. */
    if (!dew->fullvdispar) {
        fpixt1 = fpixCopy(NULL, dew->sampvdispar);
        if (redfactor == 2)
            fpixAddMultConstant(fpixt1, 0.0, (l_float32)redfactor);
        fpixt2 = fpixScaleByInteger(fpixt1, dew->sampling * redfactor);
        fpixDestroy(&fpixt1);
        if (deltah == 0 && deltaw == 0) {
            dew->fullvdispar = fpixt2;
        }
        else {
            dew->fullvdispar = fpixAddSlopeBorder(fpixt2, x, deltaw - x,
                                                  y, deltah - y);
            fpixDestroy(&fpixt2);
        }
    }

        /* Similarly, generate the full res horizontal array if it
         * doesn't exist.  Do this even if useboth == 0. */
    if (!dew->fullhdispar && dew->samphdispar) {
        fpixt1 = fpixCopy(NULL, dew->samphdispar);
        if (redfactor == 2)
            fpixAddMultConstant(fpixt1, 0.0, (l_float32)redfactor);
        fpixt2 = fpixScaleByInteger(fpixt1, dew->sampling * redfactor);
        fpixDestroy(&fpixt1);
        if (deltah == 0 && deltaw == 0) {
            dew->fullhdispar = fpixt2;
        }
        else {
            dew->fullhdispar = fpixAddSlopeBorder(fpixt2, x, deltaw - x,
                                                  y, deltah - y);
            fpixDestroy(&fpixt2);
        }
    }

    return 0;
}
Exemple #7
0
/*!
 *  boxaApplyDisparity()
 *
 *      Input:  dew
 *              boxa
 *              direction (L_HORIZ or L_VERT)
 *              mapdir (1 if mapping forward from original to dewarped;
 *                      0 if backward)
 *      Return: boxad (modified by the disparity), or null on error
 */
static BOXA *
boxaApplyDisparity(L_DEWARP  *dew,
                   BOXA      *boxa,
                   l_int32    direction,
                   l_int32    mapdir)
{
l_int32     x, y, w, h, ib, ip, nbox, wpl;
l_float32   xn, yn;
l_float32  *data, *line;
BOX        *boxs, *boxd;
BOXA       *boxad;
FPIX       *fpix;
PTA        *ptas, *ptad;

    PROCNAME("boxaApplyDisparity");

    if (!dew)
        return (BOXA *)ERROR_PTR("dew not defined", procName, NULL);
    if (!boxa)
        return (BOXA *)ERROR_PTR("boxa not defined", procName, NULL);
    if (direction == L_VERT)
        fpix = dew->fullvdispar;
    else if (direction == L_HORIZ)
        fpix = dew->fullhdispar;
    else
        return (BOXA *)ERROR_PTR("invalid direction", procName, NULL);
    if (!fpix)
        return (BOXA *)ERROR_PTR("full disparity not defined", procName, NULL);
    fpixGetDimensions(fpix, &w, &h);

        /* Clip the output to the positive quadrant because all box
         * coordinates must be non-negative. */
    data = fpixGetData(fpix);
    wpl = fpixGetWpl(fpix);
    nbox = boxaGetCount(boxa);
    boxad = boxaCreate(nbox);
    for (ib = 0; ib < nbox; ib++) {
        boxs = boxaGetBox(boxa, ib, L_COPY);
        ptas = boxConvertToPta(boxs, 4);
        ptad = ptaCreate(4);
        for (ip = 0; ip < 4; ip++) {
            ptaGetIPt(ptas, ip, &x, &y);
            line = data + y * wpl;
            if (direction == L_VERT) {
                if (mapdir == 0)
                    yn = y - line[x];
                else
                    yn = y + line[x];
                yn = L_MAX(0, yn);
                ptaAddPt(ptad, x, yn);
            } else {  /* direction == L_HORIZ */
                if (mapdir == 0)
                    xn = x - line[x];
                else
                    xn = x + line[x];
                xn = L_MAX(0, xn);
                ptaAddPt(ptad, xn, y);
            }
        }
        boxd = ptaConvertToBox(ptad);
        boxaAddBox(boxad, boxd, L_INSERT);
        boxDestroy(&boxs);
        ptaDestroy(&ptas);
        ptaDestroy(&ptad);
    }

    return boxad;
}
Exemple #8
0
/*!
 *  pixApplyHorizDisparity()
 *
 *      Input:  dew
 *              pixs (1, 8 or 32 bpp)
 *              grayin (gray value, from 0 to 255, for pixels brought in;
 *                      use -1 to use pixels on the boundary of pixs)
 *      Return: pixd (modified to remove horizontal disparity if possible),
 *              or null on error.
 *
 *  Notes:
 *      (1) This applies the horizontal disparity array to the specified
 *          image.
 *      (2) Specify gray color for pixels brought in from the outside:
 *          0 is black, 255 is white.  Use -1 to select pixels from the
 *          boundary of the source image.
 *      (3) The input pixs has already been corrected for vertical disparity.
 *          If the horizontal disparity array doesn't exist, this returns
 *          a clone of @pixs.
 */
static PIX *
pixApplyHorizDisparity(L_DEWARP  *dew,
                       PIX       *pixs,
                       l_int32    grayin)
{
l_int32     i, j, w, h, d, fw, fh, wpls, wpld, wplf, jsrc, val8;
l_uint32   *datas, *lines, *datad, *lined;
l_float32  *dataf, *linef;
FPIX       *fpix;
PIX        *pixd;

    PROCNAME("pixApplyHorizDisparity");

    if (!dew)
        return (PIX *)ERROR_PTR("dew not defined", procName, pixs);
    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    pixGetDimensions(pixs, &w, &h, &d);
    if (d != 1 && d != 8 && d != 32)
        return (PIX *)ERROR_PTR("pix not 1, 8 or 32 bpp", procName, NULL);
    if ((fpix = dew->fullhdispar) == NULL)
        return (PIX *)ERROR_PTR("fullhdispar not defined", procName, NULL);
    fpixGetDimensions(fpix, &fw, &fh);
    if (fw < w || fh < h) {
        fprintf(stderr, "fw = %d, w = %d, fh = %d, h = %d\n", fw, w, fh, h);
        return (PIX *)ERROR_PTR("invalid fpix size", procName, NULL);
    }

        /* Two choices for requested pixels outside pixs: (1) use pixels'
         * from the boundary of pixs; use white or light gray pixels. */
    pixd = pixCreateTemplate(pixs);
    if (grayin >= 0)
        pixSetAllGray(pixd, grayin);
    datas = pixGetData(pixs);
    datad = pixGetData(pixd);
    dataf = fpixGetData(fpix);
    wpls = pixGetWpl(pixs);
    wpld = pixGetWpl(pixd);
    wplf = fpixGetWpl(fpix);
    if (d == 1) {
        for (i = 0; i < h; i++) {
            lines = datas + i * wpls;
            lined = datad + i * wpld;
            linef = dataf + i * wplf;
            for (j = 0; j < w; j++) {
                jsrc = (l_int32)(j - linef[j] + 0.5);
                if (grayin < 0)  /* use value at boundary if outside */
                    jsrc = L_MIN(L_MAX(jsrc, 0), w - 1);
                if (jsrc >= 0 && jsrc < w) {  /* remains gray if outside */
                    if (GET_DATA_BIT(lines, jsrc))
                        SET_DATA_BIT(lined, j);
                }
            }
        }
    } else if (d == 8) {
        for (i = 0; i < h; i++) {
            lines = datas + i * wpls;
            lined = datad + i * wpld;
            linef = dataf + i * wplf;
            for (j = 0; j < w; j++) {
                jsrc = (l_int32)(j - linef[j] + 0.5);
                if (grayin < 0)
                    jsrc = L_MIN(L_MAX(jsrc, 0), w - 1);
                if (jsrc >= 0 && jsrc < w) {
                    val8 = GET_DATA_BYTE(lines, jsrc);
                    SET_DATA_BYTE(lined, j, val8);
                }
            }
        }
    } else {  /* d == 32 */
        for (i = 0; i < h; i++) {
            lines = datas + i * wpls;
            lined = datad + i * wpld;
            linef = dataf + i * wplf;
            for (j = 0; j < w; j++) {
                jsrc = (l_int32)(j - linef[j] + 0.5);
                if (grayin < 0)
                    jsrc = L_MIN(L_MAX(jsrc, 0), w - 1);
                if (jsrc >= 0 && jsrc < w)
                    lined[j] = lines[jsrc];
            }
        }
    }

    return pixd;
}