/*! * 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; }
/*! * 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; }
/*! * 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; }
/*! * 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; }
/*! * 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; }
/*! * 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; }
/*! * 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; }
/*! * 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; }