/*! * \return Woolz error code. * \ingroup WlzTransform * \brief Walks along a line segment calling the given function. * \param obj Object passed to function. * \param fn Function to call. * \param pWSp Workspace in which the start and end positions, * a valid interval domain and sufficent * intervals have been set. */ static WlzErrorNum WlzProfileWalk( WlzObject *obj, WlzProfileWalkFn fn, WlzProfileWalkWSp *pWSp) { int i, m; WlzIVertex3 d, e, p, s; WlzErrorNum errNum = WLZ_ERR_NONE; WLZ_VTX_3_SUB(d, pWSp->end, pWSp->start); WLZ_VTX_3_SIGN(s, d); WLZ_VTX_3_ABS(d, d); m = ALG_MAX3(d.vtX, d.vtY, d.vtZ); WLZ_VTX_3_SET(e, m / 2, m / 2, m / 2); i = m; pWSp->index = 0; pWSp->inside = 0; p = pWSp->start; while(1) { WlzIVertex3 t0, t1; errNum = (*fn)(obj, p, pWSp); if((errNum != WLZ_ERR_NONE) || (--i < 0)) { break; } ++(pWSp->index); WLZ_VTX_3_SUB(e, e, d); WLZ_VTX_3_SET(t0, (e.vtX < 0), (e.vtY < 0), (e.vtZ < 0)); WLZ_VTX_3_SCALE_ADD(e, t0, m, e); WLZ_VTX_3_HAD(t1, t0, s); WLZ_VTX_3_ADD(p, p, t1); } return(errNum); }
/*! * \return New filtered object with new values or NULL on error. * \ingroup WlzValuesFilters * \brief Applies a seperable filter to the given object using the given * convolution kernels. * \param inObj Input 2 or 3D spatial domain object * to be filtered which must have scalar * values. * \param cBufSz Convolution kernel sizes (sz), each * kernel buffer is sized (2 * sz) + 1 * with the centre indexed sz into the * buffer. * \param cBuf Convolution kernel buffers. * \param direc Set to non-zero in directions for which * the filter is to be applied. * \param gType Required return object grey type. * Passing in WLZ_GREY_ERROR will * request the given input object's grey * type. * \param pad Type of padding. * \param padVal Padding value, only used when * pad == ALG_PAD_VALUE. * \param dstErr Destination error pointer may be NULL. */ WlzObject *WlzSepFilter(WlzObject *inObj, WlzIVertex3 cBufSz, double *cBuf[], WlzIVertex3 direc, WlzGreyType gType, AlgPadType pad, double padVal, WlzErrorNum *dstErr) { int dim = 0, vSz = 0, nThr = 1; double **iBuf = NULL, **rBuf = NULL; double *vBuf = NULL; WlzObject *rnObj = NULL; WlzIVertex3 vBufSz = {0}; WlzIBox3 bBox = {0}; WlzErrorNum errNum = WLZ_ERR_NONE; #ifdef _OPENMP #pragma omp parallel { #pragma omp master { nThr = omp_get_num_threads(); } } #endif if(inObj == NULL) { errNum = WLZ_ERR_OBJECT_NULL; } else if(inObj->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } else if(inObj->values.core == NULL) { errNum = WLZ_ERR_VALUES_NULL; } else { switch(inObj->type) { case WLZ_2D_DOMAINOBJ: dim = 2; break; case WLZ_3D_DOMAINOBJ: dim = 3; break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } if((errNum == WLZ_ERR_NONE) && (gType == WLZ_GREY_ERROR)) { gType = WlzGreyTypeFromObj(inObj, &errNum); } if(errNum == WLZ_ERR_NONE) { if(errNum == WLZ_ERR_NONE) { switch(gType) { case WLZ_GREY_INT: /* FALLTHROUGH */ case WLZ_GREY_SHORT: /* FALLTHROUGH */ case WLZ_GREY_UBYTE: /* FALLTHROUGH */ case WLZ_GREY_FLOAT: /* FALLTHROUGH */ case WLZ_GREY_DOUBLE: break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } } if(errNum == WLZ_ERR_NONE) { bBox = WlzBoundingBox3I(inObj, &errNum); if(errNum == WLZ_ERR_NONE) { vBufSz.vtX = bBox.xMax - bBox.xMin + 1; vBufSz.vtY = bBox.yMax - bBox.yMin + 1; if(dim == 3) { vBufSz.vtZ = bBox.zMax - bBox.zMin + 1; } } } if(errNum == WLZ_ERR_NONE) { vSz = ALG_MAX3(vBufSz.vtX, vBufSz.vtY, vBufSz.vtZ); if(((iBuf = (double **)AlcMalloc(sizeof(double *) * 2 * nThr)) == NULL) || ((vBuf = (double *)AlcMalloc(sizeof(double) * 2 * nThr * vSz)) == NULL)) { errNum = WLZ_ERR_MEM_ALLOC; } else { int idt; rBuf = iBuf + nThr; for(idt = 0; idt < nThr; ++idt) { iBuf[idt] = vBuf + (idt * vSz); rBuf[idt] = vBuf + ((nThr + idt) * vSz); } } } if(errNum == WLZ_ERR_NONE) { /* Convolve the object values. */ if(direc.vtX) { rnObj = WlzSepFilterX(inObj, dim, nThr, iBuf, rBuf, cBufSz.vtX, cBuf[0], pad, padVal, &errNum); } if((errNum == WLZ_ERR_NONE) && direc.vtY) { WlzObject *tObj; tObj = WlzSepFilterY((rnObj)? rnObj: inObj, dim, nThr, iBuf, rBuf, cBufSz.vtY, cBuf[1], pad, padVal, &errNum); (void )WlzFreeObj(rnObj); rnObj = tObj; } if((errNum == WLZ_ERR_NONE) && (dim == 3) && direc.vtZ) { WlzObject *tObj; tObj = WlzSepFilterZ((rnObj)? rnObj: inObj, bBox, nThr, iBuf, rBuf, cBufSz.vtZ, cBuf[2], pad, padVal, &errNum); (void )WlzFreeObj(rnObj); rnObj = tObj; } } if((errNum == WLZ_ERR_NONE) && (rnObj != NULL) && (gType != WLZ_GREY_DOUBLE)) { WlzObject *tObj; /* Convert object values to the required grey type. */ tObj = WlzConvertPix((rnObj)? rnObj: inObj, gType, &errNum); (void )WlzFreeObj(rnObj); rnObj = tObj; } if(errNum != WLZ_ERR_NONE) { (void )WlzFreeObj(rnObj); rnObj = NULL; } AlcFree(iBuf); AlcFree(vBuf); return(rnObj); }