/*! * \return Woolz error code. * \ingroup WlzBinaryOps * \brief For each value in the given 2D distance object the count in * the given distance histogram (array) is incremented. The * distance if clipped to the range [0-maxDist]. * \param maxDist Maximum distance value. * \param dHist Distance histogram (array). * \param dObj Given 2D distance object. */ static WlzErrorNum WlzRCCCompDistHist2D( int maxDist, int *dHist, WlzObject *dObj) { WlzGreyWSpace gWSp; WlzIntervalWSpace iWSp; WlzErrorNum errNum = WLZ_ERR_NONE; errNum = WlzInitGreyScan(dObj, &iWSp, &gWSp); if(errNum == WLZ_ERR_NONE) { while((errNum = WlzNextGreyInterval(&iWSp)) == WLZ_ERR_NONE) { int i; int *p; p = gWSp.u_grintptr.inp; for(i = iWSp.lftpos; i <= iWSp.rgtpos; ++i) { int d; d = *p++; d = WLZ_CLAMP(d, 0, maxDist); ++(dHist[d]); } } if(errNum == WLZ_ERR_EOO) { errNum = WLZ_ERR_NONE; } } return(errNum); }
/*! * \return The grey value as an int. * \ingroup WlzAccess * \brief Gets a single grey value for the given point from the * object with which the given work space was initialised. * \param gVWSp Grey value work space. * \param plane Plane (z) coordinate of point. * \param line Line (y) coordinate of point. * \param kol Column (x) coordinate of point. */ int WlzGreyValueGetI(WlzGreyValueWSpace *gVWSp, double plane, double line, double kol) { int val = 0; if(gVWSp) { WlzGreyValueGet(gVWSp, plane, line, kol); switch(gVWSp->gType) { case WLZ_GREY_LONG: val = WLZ_CLAMP(gVWSp->gVal[0].lnv, LLONG_MIN, LLONG_MAX); break; case WLZ_GREY_INT: val = gVWSp->gVal[0].inv; break; case WLZ_GREY_SHORT: val = gVWSp->gVal[0].shv; break; case WLZ_GREY_UBYTE: val = gVWSp->gVal[0].ubv; break; case WLZ_GREY_FLOAT: val = WLZ_NINT(gVWSp->gVal[0].flv); break; case WLZ_GREY_DOUBLE: val = WLZ_NINT(gVWSp->gVal[0].dbv); break; case WLZ_GREY_RGBA: val = gVWSp->gVal[0].rgbv; break; default: break; } } return(val); }
/*! * \ingroup WlzValuesFilters * \brief Set new grey-range by simple linear interpolation. It assumes that the min and max values enclose the true range of grey-values in the object. Failure to check this could result in a segmentation fault. The transform function is: \f[g' = \frac{(gMax - gMin)}{(gmax - gmin)} (g - gmin) + gMin + \delta \f] Here \f$\delta\f$ is the dither value. * * \return Woolz error number * \param obj Input grey-level object whose values are to be reset. * \param min Initial minimum value * \param max Initial maximum value * \param Min Final minimum value * \param Max Final maximum value * \param Dither values if destination range is greater than source range * and this flag is non-zero. * \par Source: * WlzGreySetRange.c */ WlzErrorNum WlzGreySetRange( WlzObject *obj, WlzPixelV min, WlzPixelV max, WlzPixelV Min, WlzPixelV Max, int dither) { double gMin = 0.0, gMax = 0.0, sigma = 0.0, factor, val; WlzIntervalWSpace iwsp; WlzGreyWSpace gwsp; WlzGreyP gptr; WlzObject *tempobj; WlzValues *values; WlzDomain *domains; int i, j, nplanes; WlzErrorNum errNum = WLZ_ERR_NONE; /* check object */ if( obj == NULL ){ errNum = WLZ_ERR_OBJECT_NULL; } if( errNum == WLZ_ERR_NONE ){ switch( obj->type ){ case WLZ_2D_DOMAINOBJ: if( obj->domain.i == NULL ){ return WLZ_ERR_DOMAIN_NULL; } if( obj->values.core == NULL ){ return WLZ_ERR_VALUES_NULL; } if( WlzGreyTableIsTiled(obj->values.core->type) ){ return WLZ_ERR_VALUES_TYPE; } break; case WLZ_3D_DOMAINOBJ: /* check planedomain and voxeltable */ if( obj->domain.p == NULL ){ return WLZ_ERR_DOMAIN_NULL; } if( obj->domain.p->type != WLZ_PLANEDOMAIN_DOMAIN ){ return WLZ_ERR_PLANEDOMAIN_TYPE; } if( obj->values.vox == NULL ){ return WLZ_ERR_VALUES_NULL; } if( obj->values.vox->type != WLZ_VOXELVALUETABLE_GREY ){ return WLZ_ERR_VOXELVALUES_TYPE; } /* set range of each plane if non-empty - indicated by NULL */ domains = obj->domain.p->domains; values = obj->values.vox->values; nplanes = obj->domain.p->lastpl - obj->domain.p->plane1 + 1; for(i=0; i < nplanes; i++, domains++, values++){ if( (*domains).core == NULL || (*values).core == NULL ){ continue; } tempobj = WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, *values, NULL, NULL, &errNum); if((tempobj == NULL) && (errNum == WLZ_ERR_NONE) ){ errNum = WLZ_ERR_UNSPECIFIED; break; } errNum = WlzGreySetRange(tempobj, min, max, Min, Max, dither); WlzFreeObj( tempobj ); if( errNum != WLZ_ERR_NONE ){ break; } } return errNum; case WLZ_TRANS_OBJ: return WlzGreySetRange(obj->values.obj, min, max, Min, Max, dither); case WLZ_EMPTY_OBJ: return errNum; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } if( errNum == WLZ_ERR_NONE ){ /* get conversion function - should use LUT use 4 LUTS for rgb type since bounded */ if( WlzGreyTypeFromObj(obj, &errNum) == WLZ_GREY_RGBA ){ WlzUByte rgbaLut[4][256]; WlzUInt rgbamin[4], rgbaMin[4]; double rgbaFactor[4], val1; WlzUInt red, green, blue, alpha; rgbamin[0] = WLZ_RGBA_RED_GET(min.v.rgbv); rgbaMin[0] = WLZ_RGBA_RED_GET(Min.v.rgbv); if(WLZ_RGBA_RED_GET(max.v.rgbv) > WLZ_RGBA_RED_GET(min.v.rgbv)){ rgbaFactor[0] = (((double) WLZ_RGBA_RED_GET(Max.v.rgbv) - WLZ_RGBA_RED_GET(Min.v.rgbv))/ (WLZ_RGBA_RED_GET(max.v.rgbv) - WLZ_RGBA_RED_GET(min.v.rgbv))); } else { rgbaFactor[0] = 0.0; } rgbamin[1] = WLZ_RGBA_GREEN_GET(min.v.rgbv); rgbaMin[1] = WLZ_RGBA_GREEN_GET(Min.v.rgbv); if(WLZ_RGBA_GREEN_GET(max.v.rgbv) > WLZ_RGBA_GREEN_GET(min.v.rgbv)){ rgbaFactor[1] = (((double) WLZ_RGBA_GREEN_GET(Max.v.rgbv) - WLZ_RGBA_GREEN_GET(Min.v.rgbv))/ (WLZ_RGBA_GREEN_GET(max.v.rgbv) - WLZ_RGBA_GREEN_GET(min.v.rgbv))); } else { rgbaFactor[1] = 0.0; } rgbamin[2] = WLZ_RGBA_BLUE_GET(min.v.rgbv); rgbaMin[2] = WLZ_RGBA_BLUE_GET(Min.v.rgbv); if(WLZ_RGBA_BLUE_GET(max.v.rgbv) > WLZ_RGBA_BLUE_GET(min.v.rgbv)){ rgbaFactor[2] = (((double) WLZ_RGBA_BLUE_GET(Max.v.rgbv) - WLZ_RGBA_BLUE_GET(Min.v.rgbv))/ (WLZ_RGBA_BLUE_GET(max.v.rgbv) - WLZ_RGBA_BLUE_GET(min.v.rgbv))); } else { rgbaFactor[2] = 0.0; } rgbamin[3] = WLZ_RGBA_ALPHA_GET(min.v.rgbv); rgbaMin[3] = WLZ_RGBA_ALPHA_GET(Min.v.rgbv); if(WLZ_RGBA_ALPHA_GET(max.v.rgbv) > WLZ_RGBA_ALPHA_GET(min.v.rgbv)){ rgbaFactor[3] = (((double) WLZ_RGBA_ALPHA_GET(Max.v.rgbv) - WLZ_RGBA_ALPHA_GET(Min.v.rgbv))/ (WLZ_RGBA_ALPHA_GET(max.v.rgbv) - WLZ_RGBA_ALPHA_GET(min.v.rgbv))); } else { rgbaFactor[3] = 0.0; } /* now set up the LUTS */ for(i=0; i < 4; i++){ for(j=0; j < 256; j++){ val1 = rgbaFactor[i] * (j - rgbamin[i]) + rgbaMin[i]; rgbaLut[i][j] = (WlzUByte )WLZ_CLAMP(val1, 0, 255); } } /* set values - can assume rgba grey-type */ errNum = WlzInitGreyScan(obj, &iwsp, &gwsp); if(errNum == WLZ_ERR_NONE) { while( WlzNextGreyInterval(&iwsp) == WLZ_ERR_NONE ){ gptr = gwsp.u_grintptr; for (i=0; i<iwsp.colrmn; i++, gptr.rgbp++){ red = rgbaLut[0][WLZ_RGBA_RED_GET(*gptr.rgbp)]; green = rgbaLut[0][WLZ_RGBA_GREEN_GET(*gptr.rgbp)]; blue = rgbaLut[0][WLZ_RGBA_BLUE_GET(*gptr.rgbp)]; alpha = rgbaLut[0][WLZ_RGBA_ALPHA_GET(*gptr.rgbp)]; WLZ_RGBA_RGBA_SET(*gptr.rgbp, red, green, blue, alpha); } } (void )WlzEndGreyScan(&iwsp, &gwsp); if(errNum == WLZ_ERR_EOO){ errNum = WLZ_ERR_NONE; } } } else { WlzValueConvertPixel(&min, min, WLZ_GREY_DOUBLE); WlzValueConvertPixel(&max, max, WLZ_GREY_DOUBLE); WlzValueConvertPixel(&Min, Min, WLZ_GREY_DOUBLE); WlzValueConvertPixel(&Max, Max, WLZ_GREY_DOUBLE); if( fabs(max.v.dbv - min.v.dbv) < DBL_EPSILON ){ return WLZ_ERR_FLOAT_DATA; } errNum = WlzInitGreyScan(obj, &iwsp, &gwsp); if(errNum == WLZ_ERR_NONE) { factor = (Max.v.dbv - Min.v.dbv) / (max.v.dbv - min.v.dbv); if(dither) { if(fabs(factor) < 1.0 + DBL_EPSILON) { dither = 0; } else { sigma = fabs(2.0 / factor); AlgRandSeed(101); switch(gwsp.pixeltype) { case WLZ_GREY_INT: gMin = ALG_MAX(Min.v.dbv, INT_MIN); gMax = ALG_MIN(Max.v.dbv, INT_MAX); break; case WLZ_GREY_SHORT: gMin = ALG_MAX(Min.v.dbv, SHRT_MIN); gMax = ALG_MIN(Max.v.dbv, SHRT_MAX); break; case WLZ_GREY_UBYTE: gMin = ALG_MAX(Min.v.dbv, 0); gMax = ALG_MIN(Max.v.dbv, 255); break; case WLZ_GREY_FLOAT: gMin = ALG_MAX(Min.v.dbv, FLT_MIN); gMax = ALG_MIN(Max.v.dbv, FLT_MAX); break; case WLZ_GREY_DOUBLE: gMin = Min.v.dbv; gMax = Max.v.dbv; break; default: break; } } } while((errNum == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE)){ gptr = gwsp.u_grintptr; switch (gwsp.pixeltype) { case WLZ_GREY_INT: for (i=0; i<iwsp.colrmn; i++, gptr.inp++){ if(dither){ val = factor * (*gptr.inp + AlgRandZigNormal(0.0, sigma) - min.v.dbv) + Min.v.dbv; val = WLZ_CLAMP(val, gMin, gMax); } else { val = factor * (*gptr.inp - min.v.dbv) + Min.v.dbv; } *gptr.inp = WLZ_NINT(val); } break; case WLZ_GREY_SHORT: for (i=0; i<iwsp.colrmn; i++, gptr.shp++){ if(dither){ val = factor * (*gptr.shp + AlgRandZigNormal(0.0, sigma) - min.v.dbv) + Min.v.dbv; val = WLZ_CLAMP(val, gMin, gMax); } else { val = factor * (*gptr.shp - min.v.dbv) + Min.v.dbv; } *gptr.shp = (short )WLZ_NINT(val); } break; case WLZ_GREY_UBYTE: for (i=0; i<iwsp.colrmn; i++, gptr.ubp++){ if(dither){ val = factor * (*gptr.ubp + AlgRandZigNormal(0.0, sigma) - min.v.dbv) + Min.v.dbv; val = WLZ_CLAMP(val, gMin, gMax); } else { val = factor * (*gptr.ubp - min.v.dbv) + Min.v.dbv; } *gptr.ubp = (WlzUByte )WLZ_NINT(val); } break; case WLZ_GREY_FLOAT: for (i=0; i<iwsp.colrmn; i++, gptr.flp++){ if(dither){ val = factor * (*gptr.flp + AlgRandZigNormal(0.0, sigma) - min.v.dbv) + Min.v.dbv; val = WLZ_CLAMP(val, gMin, gMax); } else { val = factor * (*gptr.flp - min.v.dbv) + Min.v.dbv; } *gptr.flp = (float )val; } break; case WLZ_GREY_DOUBLE: for (i=0; i<iwsp.colrmn; i++, gptr.dbp++){ if(dither){ val = factor * (*gptr.dbp + AlgRandZigNormal(0.0, sigma) - min.v.dbv) + Min.v.dbv; val = WLZ_CLAMP(val, gMin, gMax); } else { val = factor * (*gptr.dbp - min.v.dbv) + Min.v.dbv; } *gptr.dbp = val; } break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } (void )WlzEndGreyScan(&iwsp, &gwsp); if(errNum == WLZ_ERR_EOO){ errNum = WLZ_ERR_NONE; } } } } return errNum; }
/*! * \ingroup WlzValuesFilters * \brief Perform a 1D convolution on a 1D array of data. Typically used to pass to WlzSepTrans(). The params variable is a 1D convolution mask. * * \return Woolz error * \param stwspc Separable transfom work space * \param params parameters passed from top-level calling function, unchanged by WlzSepTrans() * \par Source: * WlzGauss.c */ WlzErrorNum Wlz1DConv( WlzSepTransWSpace *stwspc, void *params) { Wlz1DConvMask *convParams = (Wlz1DConvMask *) params; int i, j, n, *mask, factor, length; int intSum; double dblSum; WlzGreyP inbuf, outbuf; WlzUInt red, green, blue; /* set some local parameters */ n = convParams->mask_size / 2; mask = convParams->mask_values + n; factor = convParams->norm_factor; inbuf = stwspc->inbuf.p; outbuf = stwspc->outbuf.p; length = stwspc->len; /* calculate the new value - use int for WlzUByte, short and int double otherwise, separate rgb values each use WlzUInt */ switch( stwspc->inbuf.type ){ case WLZ_GREY_INT: /* first convolve up to the half-width of the mask */ for(i=0; (i < n) && (i < length); i++){ intSum = *inbuf.inp * mask[0]; for(j=1; j <= n; j++){ intSum += inbuf.inp[(j+i)>(length-1)?-i+length-1:j] * mask[j]; intSum += inbuf.inp[-((i>j)?j:i)] * mask[-j]; } inbuf.inp++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = intSum/factor; break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(intSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(intSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(intSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = intSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(intSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the central portion */ while( i < (length-n-1) ){ intSum = *inbuf.inp * mask[0]; for(j=1; j <= n; j++){ intSum += inbuf.inp[j] * mask[j]; intSum += inbuf.inp[-j] * mask[-j]; } inbuf.inp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = intSum/factor; break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(intSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(intSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(intSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = intSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(intSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the last bit within a half-width of the end */ while( i < length ){ intSum = *inbuf.inp * mask[0]; for(j=1; j <= n; j++){ intSum += inbuf.inp[(j+i)>(length-1)?-i+length-1:j] * mask[j]; intSum += inbuf.inp[-j] * mask[-j]; } inbuf.inp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = intSum/factor; break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(intSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(intSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(intSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = intSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(intSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } break; case WLZ_GREY_SHORT: /* first convolve up to the half-width of the mask */ for(i=0; (i < n) && (i < length); i++){ intSum = *inbuf.shp * mask[0]; for(j=1; j <= n; j++){ intSum += inbuf.shp[(j+i)>(length-1)?-i+length-1:j] * mask[j]; intSum += inbuf.shp[-((i>j)?j:i)] * mask[-j]; } inbuf.shp++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = intSum/factor; break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(intSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(intSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(intSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = intSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(intSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the central portion */ while( i < (length-n-1) ){ intSum = *inbuf.shp * mask[0]; for(j=1; j <= n; j++){ intSum += inbuf.shp[j] * mask[j]; intSum += inbuf.shp[-j] * mask[-j]; } inbuf.shp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = intSum/factor; break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(intSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(intSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ =(float )( intSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = intSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(intSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the last bit within a half-width of the end */ while( i < length ){ intSum = *inbuf.shp * mask[0]; for(j=1; j <= n; j++){ intSum += inbuf.shp[(j+i)>(length-1)?-i+length-1:j] * mask[j]; intSum += inbuf.shp[-j] * mask[-j]; } inbuf.shp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = intSum/factor; break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(intSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(intSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(intSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = intSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(intSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } break; case WLZ_GREY_UBYTE: /* first convolve up to the half-width of the mask */ for(i=0; (i < n) && (i < length); i++){ intSum = *inbuf.ubp * mask[0]; for(j=1; j <= n; j++){ intSum += inbuf.ubp[(j+i)>(length-1)?-i+length-1:j] * mask[j]; intSum += inbuf.ubp[-((i>j)?j:i)] * mask[-j]; } inbuf.ubp++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = intSum/factor; break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(intSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(intSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(intSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = intSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(intSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the central portion */ while( i < (length-n-1) ){ intSum = *inbuf.ubp * mask[0]; for(j=1; j <= n; j++){ intSum += inbuf.ubp[j] * mask[j]; intSum += inbuf.ubp[-j] * mask[-j]; } inbuf.ubp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = intSum/factor; break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(intSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(intSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(intSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = intSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(intSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the last bit within a half-width of the end */ while( i < length ){ intSum = *inbuf.ubp * mask[0]; for(j=1; j <= n; j++){ intSum += inbuf.ubp[(j+i)>(length-1)?-i+length-1:j] * mask[j]; intSum += inbuf.ubp[-j] * mask[-j]; } inbuf.ubp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = intSum/factor; break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(intSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(intSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(intSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = intSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(intSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } break; case WLZ_GREY_FLOAT: /* first convolve up to the half-width of the mask */ for(i=0; (i < n) && (i < length); i++){ dblSum = *inbuf.flp * mask[0]; for(j=1; j <= n; j++){ dblSum += inbuf.flp[(j+i)>(length-1)?-i+length-1:j] * mask[j]; dblSum += inbuf.flp[-((i>j)?j:i)] * mask[-j]; } inbuf.flp++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = (int )(dblSum/factor); break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(dblSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(dblSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(dblSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = dblSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(dblSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the central portion */ while( i < (length-n-1) ){ dblSum = *inbuf.flp * mask[0]; for(j=1; j <= n; j++){ dblSum += inbuf.flp[j] * mask[j]; dblSum += inbuf.flp[-j] * mask[-j]; } inbuf.flp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = (int )(dblSum/factor); break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(dblSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(dblSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(dblSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = dblSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(dblSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the last bit within a half-width of the end */ while( i < length ){ dblSum = *inbuf.flp * mask[0]; for(j=1; j <= n; j++){ dblSum += inbuf.flp[(j+i)>(length-1)?-i+length-1:j] * mask[j]; dblSum += inbuf.flp[-j] * mask[-j]; } inbuf.flp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = (int )(dblSum/factor); break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(dblSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(dblSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(dblSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = dblSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(dblSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } break; case WLZ_GREY_DOUBLE: /* first convolve up to the half-width of the mask */ for(i=0; (i < n) && (i < length); i++){ dblSum = *inbuf.dbp * mask[0]; for(j=1; j <= n; j++){ dblSum += inbuf.dbp[(j+i)>(length-1)?-i+length-1:j] * mask[j]; dblSum += inbuf.dbp[-((i>j)?j:i)] * mask[-j]; } inbuf.dbp++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = (int )(dblSum/factor); break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(dblSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(dblSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(dblSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = dblSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(dblSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the central portion */ while( i < (length-n-1) ){ dblSum = *inbuf.dbp * mask[0]; for(j=1; j <= n; j++){ dblSum += inbuf.dbp[j] * mask[j]; dblSum += inbuf.dbp[-j] * mask[-j]; } inbuf.dbp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = (int )(dblSum/factor); break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(dblSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(dblSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(dblSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = dblSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(dblSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the last bit within a half-width of the end */ while( i < length ){ dblSum = *inbuf.dbp * mask[0]; for(j=1; j <= n; j++){ dblSum += inbuf.dbp[(j+i)>(length-1)?-i+length-1:j] * mask[j]; dblSum += inbuf.dbp[-j] * mask[-j]; } inbuf.dbp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = (int )(dblSum/factor); break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )(dblSum/factor); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )(dblSum/factor); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )(dblSum/factor); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = dblSum/factor; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(dblSum/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, red, red, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } break; case WLZ_GREY_RGBA: /* first convolve up to the half-width of the mask */ for(i=0; (i < n) && (i < length); i++){ red = WLZ_RGBA_RED_GET(*inbuf.rgbp) * mask[0]; green = WLZ_RGBA_GREEN_GET(*inbuf.rgbp) * mask[0]; blue = WLZ_RGBA_BLUE_GET(*inbuf.rgbp) * mask[0]; for(j=1; j <= n; j++){ red += WLZ_RGBA_RED_GET(inbuf.rgbp[(j+i)>(length-1)?-i+length-1:j]) * mask[j]; red += WLZ_RGBA_RED_GET(inbuf.rgbp[-((i>j)?j:i)]) * mask[-j]; green += WLZ_RGBA_GREEN_GET(inbuf.rgbp[(j+i)>(length-1)?-i+length-1:j]) * mask[j]; green += WLZ_RGBA_GREEN_GET(inbuf.rgbp[-((i>j)?j:i)]) * mask[-j]; blue += WLZ_RGBA_BLUE_GET(inbuf.rgbp[(j+i)>(length-1)?-i+length-1:j]) * mask[j]; blue += WLZ_RGBA_BLUE_GET(inbuf.rgbp[-((i>j)?j:i)]) * mask[-j]; } inbuf.rgbp++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = (int )((red+green+blue)/factor/3.0); break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )((red+green+blue)/factor/3.0); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )((red+green+blue)/factor/3.0); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )((red+green+blue)/factor/3.0); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = (red+green+blue)/factor/3.0; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(red/factor, 0, 255); green = (WlzUInt )WLZ_CLAMP(green/factor, 0, 255); blue = (WlzUInt )WLZ_CLAMP(blue/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, green, blue, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the central portion */ while( i < (length-n-1) ){ red = WLZ_RGBA_RED_GET(*inbuf.rgbp) * mask[0]; green = WLZ_RGBA_GREEN_GET(*inbuf.rgbp) * mask[0]; blue = WLZ_RGBA_BLUE_GET(*inbuf.rgbp) * mask[0]; for(j=1; j <= n; j++){ red += WLZ_RGBA_RED_GET(inbuf.rgbp[j]) * mask[j]; red += WLZ_RGBA_RED_GET(inbuf.rgbp[-j]) * mask[-j]; green += WLZ_RGBA_GREEN_GET(inbuf.rgbp[j]) * mask[j]; green += WLZ_RGBA_GREEN_GET(inbuf.rgbp[-j]) * mask[-j]; blue += WLZ_RGBA_BLUE_GET(inbuf.rgbp[j]) * mask[j]; blue += WLZ_RGBA_BLUE_GET(inbuf.rgbp[-j]) * mask[-j]; } inbuf.rgbp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = (int )((red+green+blue)/factor/3.0); break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )((red+green+blue)/factor/3.0); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte )((red+green+blue)/factor/3.0); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )((red+green+blue)/factor/3.0); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = (red+green+blue)/factor/3.0; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(red/factor, 0, 255); green = (WlzUInt )WLZ_CLAMP(green/factor, 0, 255); blue = (WlzUInt )WLZ_CLAMP(blue/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, green, blue, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } /* now the last bit within a half-width of the end */ while( i < length ){ red = WLZ_RGBA_RED_GET(*inbuf.rgbp) * mask[0]; green = WLZ_RGBA_GREEN_GET(*inbuf.rgbp) * mask[0]; blue = WLZ_RGBA_BLUE_GET(*inbuf.rgbp) * mask[0]; for(j=1; j <= n; j++){ red += WLZ_RGBA_RED_GET(inbuf.rgbp[(j+i)>(length-1)?-i+length-1:j]) * mask[j]; red += WLZ_RGBA_RED_GET(inbuf.rgbp[-j]) * mask[-j]; green += WLZ_RGBA_GREEN_GET(inbuf.rgbp[(j+i)>(length-1)?-i+length-1:j]) * mask[j]; green += WLZ_RGBA_GREEN_GET(inbuf.rgbp[-j]) * mask[-j]; blue += WLZ_RGBA_BLUE_GET(inbuf.rgbp[(j+i)>(length-1)?-i+length-1:j]) * mask[j]; blue += WLZ_RGBA_BLUE_GET(inbuf.rgbp[-j]) * mask[-j]; } inbuf.rgbp++; i++; switch( stwspc->outbuf.type ){ case WLZ_GREY_INT: *outbuf.inp++ = (int )((red+green+blue)/factor/3.0); break; case WLZ_GREY_SHORT: *outbuf.shp++ = (short )((red+green+blue)/factor/3.0); break; case WLZ_GREY_UBYTE: *outbuf.ubp++ = (WlzUByte)((red+green+blue)/factor/3.0); break; case WLZ_GREY_FLOAT: *outbuf.flp++ = (float )((red+green+blue)/factor/3.0); break; case WLZ_GREY_DOUBLE: *outbuf.dbp++ = (red+green+blue)/factor/3.0; break; case WLZ_GREY_RGBA: red = (WlzUInt )WLZ_CLAMP(red/factor, 0, 255); green = (WlzUInt )WLZ_CLAMP(green/factor, 0, 255); blue = (WlzUInt )WLZ_CLAMP(blue/factor, 0, 255); WLZ_RGBA_RGBA_SET(*outbuf.rgbp, red, green, blue, 255); outbuf.rgbp++; break; default: return WLZ_ERR_GREY_TYPE; break; } } break; default: return WLZ_ERR_GREY_TYPE; break; } return WLZ_ERR_NONE; }
/*! * \return Woolz error code. * \ingroup WlzBinaryOps * \brief Splits the given montage object into component objects * clipped from the montage object. The montage object * must be composed of component images embedded in a * background, with little variation in the background * values. * \param mObj Montage object, which must be either * a WLZ_2D_DOMAINOBJ or a * WLZ_3D_DOMAINOBJ with values. * \param gapV Value for the uniform background. * Must be either WLZ_GREY_INT or * WLZ_GREY_RGBA. * \param tol Tolerance (fraction) for the * variation in background values. * \param bWidth Additional boundary width added * to detected images before they are * clipped. * \param minArea Minimum area for a valid component * image, must be greater than zero. * \param maxComp Maximum number of components. * \param dstNComp Destination pointer for the number of * components extracted, must not be NULL. * \param dstComp Destination pointer for the extracted * components, must not be NULL. */ WlzErrorNum WlzSplitMontageObj(WlzObject *mObj, WlzPixelV gapV, double tol, int bWidth, int minArea, int maxComp, int *dstNComp, WlzObject ***dstComp) { int id0, id1, area, nLComp = 0; WlzObject *gObj = NULL, *tObj = NULL; WlzObject **lComp; WlzGreyType objG; WlzBox box; WlzPixelV gapLV, gapHV; WlzConnectType lCon; int tI[8]; WlzErrorNum errNum = WLZ_ERR_NONE; tol = WLZ_CLAMP(tol, 0.0, 1.0); if(mObj == NULL) { errNum = WLZ_ERR_OBJECT_NULL; } else if(minArea < 1) { errNum = WLZ_ERR_PARAM_DATA; } else { switch(mObj->type) { case WLZ_2D_DOMAINOBJ: lCon = WLZ_4_CONNECTED; break; case WLZ_3D_DOMAINOBJ: lCon = WLZ_6_CONNECTED; break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } if(errNum == WLZ_ERR_NONE) { objG = WlzGreyTypeFromObj(mObj, &errNum); } if(errNum == WLZ_ERR_NONE) { switch(gapV.type) { case WLZ_GREY_INT: /* FALLTHROUGH */ case WLZ_GREY_RGBA: break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } if(errNum == WLZ_ERR_NONE) { if(objG == WLZ_GREY_RGBA) { if(gapV.type != WLZ_GREY_RGBA) { (void )WlzValueConvertPixel(&gapV, gapV, WLZ_GREY_RGBA); } } else { if(gapV.type != WLZ_GREY_INT) { (void )WlzValueConvertPixel(&gapV, gapV, WLZ_GREY_INT); } } gapLV.type = gapHV.type = gapV.type; if(gapV.type == WLZ_GREY_INT) { tI[0] = gapV.v.inv * tol; gapLV.v.inv = gapV.v.inv - tI[0]; gapHV.v.inv = gapV.v.inv + tI[0]; tObj = WlzThreshold(mObj, gapLV, WLZ_THRESH_HIGH, &errNum); if((errNum == WLZ_ERR_NONE) && (tObj != NULL)) { gObj = WlzThreshold(tObj, gapHV, WLZ_THRESH_LOW, &errNum); } (void )WlzFreeObj(tObj); tObj = NULL; } else /* gapV.type == WLZ_GREY_RGBA */ { tI[0] = WLZ_RGBA_RED_GET(gapV.v.rgbv); tI[1] = (int )floor((double )(tI[0]) * tol); tI[2] = tI[0] - tI[1]; tI[5] = tI[0] + tI[1]; tI[0] = WLZ_RGBA_GREEN_GET(gapV.v.rgbv); tI[1] = (int )floor((double )(tI[0]) * tol); tI[3] = tI[0] - tI[1]; tI[6] = tI[0] + tI[1]; tI[0] = WLZ_RGBA_BLUE_GET(gapV.v.rgbv); tI[1] = (int )floor((double )(tI[0]) * tol); tI[4] = tI[0] - tI[1]; tI[7] = tI[0] + tI[1]; tI[2] = WLZ_CLAMP(tI[2], 0, 255); tI[3] = WLZ_CLAMP(tI[3], 0, 255); tI[4] = WLZ_CLAMP(tI[4], 0, 255); WLZ_RGBA_RGBA_SET(gapLV.v.rgbv, tI[2], tI[3], tI[4], 255); tI[5] = WLZ_CLAMP(tI[5], 0, 255); tI[6] = WLZ_CLAMP(tI[6], 0, 255); tI[7] = WLZ_CLAMP(tI[7], 0, 255); WLZ_RGBA_RGBA_SET(gapHV.v.rgbv, tI[5], tI[6], tI[7], 255); gObj = WlzRGBABoxThreshold(mObj, gapLV, gapHV, &errNum); } } if(errNum == WLZ_ERR_NONE) { tObj = WlzDiffDomain(mObj, gObj, &errNum); } (void )WlzFreeObj(gObj); if(errNum == WLZ_ERR_NONE) { errNum = WlzLabel(tObj, &nLComp, &lComp, maxComp, 0, lCon); } (void )WlzFreeObj(tObj); if(errNum == WLZ_ERR_NONE) { /* Get rid of small objects using minArea as the threshold. */ id0 = 0; id1 = 0; while(id0 < nLComp) { switch((*(lComp + id0))->type) { case WLZ_2D_DOMAINOBJ: area = WlzArea(*(lComp + id0), NULL); break; case WLZ_3D_DOMAINOBJ: area = WlzVolume(*(lComp + id0), NULL); break; default: area = 0; break; } if(area >= minArea) { *(lComp + id1) = *(lComp + id0); ++id1; } else { (void )WlzFreeObj(*(lComp + id0)); *(lComp + id0) = NULL; } ++id0; } nLComp = id1; } if(errNum == WLZ_ERR_NONE) { /* Clip rectangular objects from the montage object. */ id0 = 0; while((errNum == WLZ_ERR_NONE) && (id0 < nLComp)) { if(tObj->type == WLZ_2D_DOMAINOBJ) { box.i2 = WlzBoundingBox2I(*(lComp + id0), &errNum); box.i2.xMin -= bWidth; box.i2.yMin -= bWidth; box.i2.xMax += bWidth; box.i2.yMax += bWidth; (void )WlzFreeObj(*(lComp + id0)); *(lComp + id0) = WlzClipObjToBox2D(mObj, box.i2, &errNum); } else /* tObj->type == WLZ_3D_DOMAINOBJ */ { box.i3 = WlzBoundingBox3I(*(lComp + id0), &errNum); box.i3.xMin -= bWidth; box.i3.yMin -= bWidth; box.i3.zMin -= bWidth; box.i3.xMax += bWidth; box.i3.yMax += bWidth; box.i3.zMax += bWidth; (void )WlzFreeObj(*(lComp + id0)); *(lComp + id0) = WlzClipObjToBox3D(mObj, box.i3, &errNum); } ++id0; } } *dstNComp = nLComp; *dstComp = lComp; return(errNum); }
/*! * \ingroup WlzValuesUtils * \brief Handle grey table for an interval. This must follow a call to "nextinterval". * * \return Woolz error. * \param iwsp Interval scaning workspace. * \par Source: * WlzGreyScan.c */ WlzErrorNum WlzGreyInterval(WlzIntervalWSpace *iwsp) { WlzGreyP g; WlzValues vdmn; WlzGreyWSpace *gwsp = iwsp->gryptr; int i; WlzValueIntervalLine *vil; WlzValueLine *val; vdmn = gwsp->gtable; switch( gwsp->gdomaintype ){ case WLZ_GREY_TAB_RAGR: if (iwsp->nwlpos){ /* new line signal, move to next line of greytable */ gwsp->gline += iwsp->nwlpos*iwsp->lineraster; } /* pointer to grey values */ switch( gwsp->pixeltype ){ case WLZ_GREY_INT: g.inp = (gwsp->gline->values.inp + iwsp->lftpos - vdmn.v->kol1 - gwsp->gline->vkol1); break; case WLZ_GREY_SHORT: g.shp = (gwsp->gline->values.shp + iwsp->lftpos - vdmn.v->kol1 - gwsp->gline->vkol1); break; case WLZ_GREY_UBYTE: g.ubp = (gwsp->gline->values.ubp + iwsp->lftpos - vdmn.v->kol1 - gwsp->gline->vkol1); break; case WLZ_GREY_FLOAT: g.flp = (gwsp->gline->values.flp + iwsp->lftpos - vdmn.v->kol1 - gwsp->gline->vkol1); break; case WLZ_GREY_DOUBLE: g.dbp = (gwsp->gline->values.dbp + iwsp->lftpos - vdmn.v->kol1 - gwsp->gline->vkol1); break; case WLZ_GREY_RGBA: g.rgbp = (gwsp->gline->values.rgbp + iwsp->lftpos - vdmn.v->kol1 - gwsp->gline->vkol1); break; default: return( WLZ_ERR_GREY_TYPE ); /* break */ } break; case WLZ_GREY_TAB_RECT: /* pointer to grey values */ switch (gwsp->pixeltype) { case WLZ_GREY_INT: g.inp = (vdmn.r->values.inp + (iwsp->linpos - vdmn.r->line1) * vdmn.r->width + iwsp->lftpos - vdmn.r->kol1); break; case WLZ_GREY_SHORT: g.shp = (vdmn.r->values.shp + (iwsp->linpos - vdmn.r->line1) * vdmn.r->width + iwsp->lftpos - vdmn.r->kol1); break; case WLZ_GREY_UBYTE: g.ubp = (vdmn.r->values.ubp + (iwsp->linpos - vdmn.r->line1) * vdmn.r->width + iwsp->lftpos - vdmn.r->kol1); break; case WLZ_GREY_FLOAT: g.flp = (vdmn.r->values.flp + (iwsp->linpos - vdmn.r->line1) * vdmn.r->width + iwsp->lftpos - vdmn.r->kol1); break; case WLZ_GREY_DOUBLE: g.dbp = (vdmn.r->values.dbp + (iwsp->linpos - vdmn.r->line1) * vdmn.r->width + iwsp->lftpos - vdmn.r->kol1); break; case WLZ_GREY_RGBA: g.rgbp = (vdmn.r->values.rgbp + (iwsp->linpos - vdmn.r->line1) * vdmn.r->width + iwsp->lftpos - vdmn.r->kol1); break; default: return( WLZ_ERR_GREY_TYPE ); /* break */ } break; case WLZ_GREY_TAB_INTL: if (iwsp->nwlpos){ /* new line signal, move to next line of greytable */ gwsp->gline = (WlzValueLine *) (((WlzValueIntervalLine *) gwsp->gline) + iwsp->nwlpos*iwsp->lineraster); } vil = (WlzValueIntervalLine *) gwsp->gline; val = vil->vtbint; for (i=0; i<vil->nintvs; i++) { if( (vdmn.i->kol1 + val->vkol1 <= iwsp->lftpos) && (vdmn.i->kol1 + val->vlastkl >= iwsp->rgtpos) ) { switch (gwsp->pixeltype) { case WLZ_GREY_INT: g.inp = val->values.inp + iwsp->lftpos - vdmn.i->kol1 - val->vkol1; break; case WLZ_GREY_SHORT: g.shp = val->values.shp + iwsp->lftpos - vdmn.i->kol1 - val->vkol1; break; case WLZ_GREY_UBYTE: g.ubp = val->values.ubp + iwsp->lftpos - vdmn.i->kol1 - val->vkol1; break; case WLZ_GREY_FLOAT: g.flp = val->values.flp + iwsp->lftpos - vdmn.i->kol1 - val->vkol1; break; case WLZ_GREY_DOUBLE: g.dbp = val->values.dbp + iwsp->lftpos - vdmn.i->kol1 - val->vkol1; break; case WLZ_GREY_RGBA: g.rgbp = val->values.rgbp + iwsp->lftpos - vdmn.i->kol1 - val->vkol1; break; default: return( WLZ_ERR_GREY_TYPE ); /* break */ } goto G_OK; } val++; } return( WLZ_ERR_VALUES_DATA ); G_OK: break; default: return( WLZ_ERR_VALUES_TYPE ); } if (gwsp->tranpl != 0) { /* transplant mode */ /* * MOD 12/1/92 - in transplant mode, we will always copy to or from * an integer array. This change is made so that routines like * seqpar can more easily deal with differing pixel types. */ switch (gwsp->gvio) { case 0 : /* input to object */ switch(gwsp->pixeltype ) { case WLZ_GREY_INT: for (i=0; i<iwsp->colrmn; i++) *g.inp++ = gwsp->u_grintptr.inp[i]; break; case WLZ_GREY_SHORT: for (i=0; i<iwsp->colrmn; i++) *g.shp++ = (short )WLZ_CLAMP(gwsp->u_grintptr.inp[i], SHRT_MIN, SHRT_MAX); break; case WLZ_GREY_UBYTE: for (i=0; i<iwsp->colrmn; i++) *g.ubp++ = (WlzUByte )WLZ_CLAMP(gwsp->u_grintptr.inp[i], 0, 255); break; case WLZ_GREY_FLOAT: for (i=0; i<iwsp->colrmn; i++) *g.flp++ = (float )(gwsp->u_grintptr.inp[i]); break; case WLZ_GREY_DOUBLE: for (i=0; i<iwsp->colrmn; i++) *g.dbp++ = gwsp->u_grintptr.inp[i]; break; case WLZ_GREY_RGBA: for (i=0; i<iwsp->colrmn; i++) *g.rgbp++ = gwsp->u_grintptr.inp[i]; break; default: /* can't get here because grey-type already checked */ break; } break; case 1 : /* output from object */ switch(gwsp->pixeltype ) { case WLZ_GREY_INT: for (i=0; i<iwsp->colrmn; i++) gwsp->u_grintptr.inp[i] = *g.inp++; break; case WLZ_GREY_SHORT: for (i=0; i<iwsp->colrmn; i++) gwsp->u_grintptr.inp[i] = *g.shp++; break; case WLZ_GREY_UBYTE: for (i=0; i<iwsp->colrmn; i++) gwsp->u_grintptr.inp[i] = *g.ubp++; break; case WLZ_GREY_FLOAT: for (i=0; i<iwsp->colrmn; i++) gwsp->u_grintptr.inp[i] = (int )(*g.flp++); break; case WLZ_GREY_DOUBLE: for (i=0; i<iwsp->colrmn; i++) gwsp->u_grintptr.inp[i] = (int )(*g.dbp++); break; case WLZ_GREY_RGBA: for (i=0; i<iwsp->colrmn; i++) gwsp->u_grintptr.inp[i] = *g.rgbp++; break; default: /* can't get here because grey-type already checked */ break; } break; default: return( WLZ_ERR_INT_DATA ); } } else { gwsp->u_grintptr = g; /* direct mode */ } return( WLZ_ERR_NONE ); }
/*! * \return Woolz error code. * \ingroup WlzArithmetic * \brief Sets the values of the return object from the input object * using simple linear scaling, see WlzScalarMulAdd(). The * objects are known to be 2D, have the same domain. * \param rObj * \param iObj * \param m * \param a */ static WlzErrorNum WlzScalarMulAddSet2D(WlzObject *rObj, WlzObject *iObj, double m, double a) { int bufLen; WlzGreyWSpace iGWSp, rGWSp; WlzIntervalWSpace iIWSp = {0}, rIWSp = {0}; WlzErrorNum errNum = WLZ_ERR_NONE; bufLen = iObj->domain.i->lastkl - iObj->domain.i->kol1 + 1; if((bufLen != iObj->domain.i->lastkl - iObj->domain.i->kol1 + 1) || (bufLen < 0)) { errNum = WLZ_ERR_DOMAIN_DATA; } else if(bufLen > 0) { if(errNum == WLZ_ERR_NONE) { errNum = WlzInitGreyScan(iObj, &iIWSp, &iGWSp); } if(errNum == WLZ_ERR_NONE) { errNum = WlzInitGreyScan(rObj, &rIWSp, &rGWSp); } if(errNum == WLZ_ERR_NONE) { double *buf = NULL; if((buf = AlcMalloc(sizeof(double) * bufLen)) == NULL) { errNum = WLZ_ERR_MEM_ALLOC; } else { while((errNum = WlzNextGreyInterval(&iIWSp)) == WLZ_ERR_NONE) { int t, idN, itvLen; double f; itvLen = iIWSp.colrmn; (void )WlzNextGreyInterval(&rIWSp); switch(iGWSp.pixeltype) { case WLZ_GREY_INT: WlzValueCopyIntToDouble(buf, iGWSp.u_grintptr.inp, itvLen); break; case WLZ_GREY_SHORT: WlzValueCopyShortToDouble(buf, iGWSp.u_grintptr.shp, itvLen); break; case WLZ_GREY_UBYTE: WlzValueCopyUByteToDouble(buf, iGWSp.u_grintptr.ubp, itvLen); break; case WLZ_GREY_FLOAT: WlzValueCopyFloatToDouble(buf, iGWSp.u_grintptr.flp, itvLen); break; case WLZ_GREY_DOUBLE: WlzValueCopyDoubleToDouble(buf, iGWSp.u_grintptr.dbp, itvLen); break; case WLZ_GREY_RGBA: WlzValueCopyRGBAToDouble(buf, iGWSp.u_grintptr.rgbp, itvLen); break; default: break; } switch(rGWSp.pixeltype) { case WLZ_GREY_UBYTE: for(idN = 0; idN < itvLen; ++idN) { f = (buf[idN] * m) + a; f = WLZ_CLAMP(f, 0, 255); rGWSp.u_grintptr.ubp[idN] = WLZ_NINT(f); } break; case WLZ_GREY_SHORT: for(idN = 0; idN < itvLen; ++idN) { f = (buf[idN] * m) + a; f = WLZ_CLAMP(f, SHRT_MIN, SHRT_MAX); rGWSp.u_grintptr.shp[idN] = WLZ_NINT(f); } break; case WLZ_GREY_INT: for(idN = 0; idN < itvLen; ++idN) { f = (buf[idN] * m) + a; f = WLZ_CLAMP(f, INT_MIN, INT_MAX); rGWSp.u_grintptr.inp[idN] = WLZ_NINT(f); } break; case WLZ_GREY_RGBA: for(idN = 0; idN < itvLen; ++idN) { WlzUInt u; f = (buf[idN] * m) + a; f = WLZ_CLAMP(f, 0, 255); t = WLZ_NINT(f); WLZ_RGBA_RGBA_SET(u, t, t, t, 255); rGWSp.u_grintptr.inp[idN] = u; } case WLZ_GREY_FLOAT: for(idN = 0; idN < itvLen; ++idN) { double t; t = (buf[idN] * m) + a; rGWSp.u_grintptr.flp[idN] = WLZ_CLAMP(t, -(FLT_MAX), FLT_MAX); } break; case WLZ_GREY_DOUBLE: for(idN = 0; idN < itvLen; ++idN) { rGWSp.u_grintptr.dbp[idN] = (buf[idN] * m) + a; } break; default: break; } } if(errNum == WLZ_ERR_EOO) { errNum = WLZ_ERR_NONE; } } AlcFree(buf); } (void )WlzEndGreyScan(&iIWSp, &iGWSp); (void )WlzEndGreyScan(&rIWSp, &rGWSp); } return(errNum); }
int main(int argc, char **argv) { int tI, errIdx, option, keep2D = 0, ok = 1, usage = 0; WlzDDOVxSzSrc voxSzSrc = WLZDDO_VSS_UNIT; WlzDVertex2 org; WlzThreeDViewStruct *view = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; WlzObject *dwnObj = NULL, *refObj = NULL; FILE *fP = NULL; char *errMsg0, *cmdStr = NULL, *refFileStr = NULL, *outFileStr, *inFileStr; double voxSz[3]; const char *errMsg; static char optList[] = "a:b:d:E:f:g:m:o:r:s:u:2eh", outFileStrDef[] = "-", inFileStrDef[] = "-"; opterr = 0; errMsg = errMsg0 = ""; org.vtX = org.vtY = 0.0; inFileStr = inFileStrDef; outFileStr = outFileStrDef; voxSz[0] = voxSz[1] = voxSz[2] = 1.0; if((view = WlzMake3DViewStruct(WLZ_3D_VIEW_STRUCT, &errNum)) == NULL) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to create view structure (%s)\n", *argv, errMsg); } if(ok) { view->dist = 0.0; view->scale = 1.0; view->ref_obj = NULL; view->view_mode = WLZ_UP_IS_UP_MODE; view->phi = view->theta = view->zeta = 0.0; view->up.vtX = view->up.vtY = 0.0; view->up.vtZ = 1.0; view->fixed.vtX = view->fixed.vtY = view->fixed.vtZ = 0.0; while((usage == 0) && ((option = getopt(argc, argv, optList)) != -1)) { switch(option) { case '2': keep2D = 1; break; case 'a': usage = WlzDrawDomObjScanTriple(optarg, &(view->phi), &(view->theta), &(view->zeta)) < 1; break; case 'e': voxSzSrc = WLZDDO_VSS_OBJ; break; case 'E': voxSzSrc = WLZDDO_VSS_GVN; usage = WlzDrawDomObjScanTriple(optarg, &(voxSz[0]), &(voxSz[1]), &(voxSz[2])) < 1; break; case 'f': usage = WlzDrawDomObjScanTriple(optarg, &(view->fixed.vtX), &(view->fixed.vtY), &(view->fixed.vtZ)) < 1; break; case 'd': usage = sscanf(optarg, "%lg", &(view->dist)) != 1; break; case 'b': usage = WlzDrawDomObjReadView(optarg, view, &errMsg0) != WLZ_ERR_NONE; if(usage) { (void )fprintf(stderr, "%s: failed to read view parameters from file " "%s (%s)\n", *argv, optarg, errMsg0); } break; case 'm': if(WlzStringMatchValue(&tI, optarg, "up-is-up", WLZ_UP_IS_UP_MODE, "statue", WLZ_STATUE_MODE, "absolute", WLZ_ZETA_MODE, NULL)) { view->view_mode = (WlzThreeDViewMode )tI; } else { usage = 1; } break; case 'u': usage = WlzDrawDomObjScanTriple(optarg, &(view->up.vtX), &(view->up.vtY), &(view->up.vtZ)) < 1; break; case 'g': usage = WlzDrawDomObjScanPair(optarg, &(org.vtX), &(org.vtY)) < 1; break; case 'o': outFileStr = optarg; break; case 'r': refFileStr = optarg; errNum = WLZ_ERR_READ_EOF; if((refFileStr == NULL) || (*refFileStr == '\0') || ((fP = (strcmp(refFileStr, "-")? fopen(refFileStr, "r"): stdin)) == NULL) || ((refObj = WlzAssignObject( WlzReadObj(fP, &errNum), NULL)) == NULL) || (errNum != WLZ_ERR_NONE)) { usage = 1; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to read 3D reference object from %s (%s)\n", *argv, refFileStr, errMsg); } if(fP) { if(strcmp(refFileStr, "-")) { (void )fclose(fP); } fP = NULL; } break; case 's': if((cmdStr = AlcStrDup(optarg)) == NULL) { usage = 1; errNum = WLZ_ERR_MEM_ALLOC; } break; case 'h': default: usage = 1; ok = 0; break; } } if((usage == 0) && (cmdStr == NULL)) { if((optind == argc)) { inFileStr = inFileStrDef; } else if(optind + 1 == argc ) { inFileStr = *(argv + optind); } else { usage = 1; } if(usage == 0) { cmdStr = WlzDrawDomObjReadStr(inFileStr, &errNum); } } ok = usage == 0; } if(ok) { switch(voxSzSrc) { case WLZDDO_VSS_UNIT: view->voxelRescaleFlg = 0; view->voxelSize[0] = 1.0f; view->voxelSize[1] = 1.0f; view->voxelSize[2] = 1.0f; break; case WLZDDO_VSS_GVN: view->voxelRescaleFlg = 1; view->voxelSize[0] = (float )WLZ_CLAMP(voxSz[0], FLT_MIN, FLT_MAX); view->voxelSize[1] = (float )WLZ_CLAMP(voxSz[1], FLT_MIN, FLT_MAX); view->voxelSize[2] = (float )WLZ_CLAMP(voxSz[2], FLT_MIN, FLT_MAX); break; case WLZDDO_VSS_OBJ: /* Handled below. */ break; } } if(ok && refObj) { WlzObject *sObj = NULL; WlzThreeDViewStruct *v = NULL; v = WlzMake3DViewStruct(WLZ_3D_VIEW_STRUCT, &errNum); if(errNum == WLZ_ERR_NONE) { v->type = view->type; v->fixed = view->fixed; v->theta = view->theta; v->phi = view->phi; v->zeta = view->zeta; v->dist = view->dist; v->scale = view->scale; if(voxSzSrc == WLZDDO_VSS_OBJ) { view->voxelRescaleFlg = 1; if((refObj->type == WLZ_3D_DOMAINOBJ) && (refObj->domain.core != NULL) && (refObj->domain.core->type == WLZ_PLANEDOMAIN_DOMAIN)) { view->voxelSize[0] = refObj->domain.p->voxel_size[0]; view->voxelSize[1] = refObj->domain.p->voxel_size[1]; view->voxelSize[2] = refObj->domain.p->voxel_size[2]; } } v->voxelRescaleFlg = view->voxelRescaleFlg; v->voxelSize[0] = view->voxelSize[0]; v->voxelSize[1] = view->voxelSize[1]; v->voxelSize[2] = view->voxelSize[2]; v->interp = view->interp; v->view_mode = view->view_mode; v->up = view->up; v->fixed_2 = view->fixed_2; v->fixed_line_angle = view->fixed_line_angle; errNum = WlzInit3DViewStruct(v, refObj); } if(errNum == WLZ_ERR_NONE) { sObj = WlzGetSectionFromObject(refObj, v, WLZ_INTERPOLATION_NEAREST, &errNum); } if(errNum == WLZ_ERR_NONE) { if((sObj->type != WLZ_2D_DOMAINOBJ) || (sObj->domain.core == NULL)) { errNum = WLZ_ERR_DOMAIN_DATA; } else { org.vtX += sObj->domain.i->kol1; org.vtY += sObj->domain.i->line1; } } (void )WlzFree3DViewStruct(v); (void )WlzFreeObj(sObj); if(errNum != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed find offset from reference object (%s).\n", *argv, errMsg); } } if(ok) { dwnObj = WlzDrawDomainObj(org, view, keep2D, cmdStr, &errIdx, &errNum); if(errNum != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to draw object in command prior to string\n" "position %d (%s)\n", *argv, errIdx, errMsg); } } if(ok) { errNum = WLZ_ERR_WRITE_EOF; if((fP = (strcmp(outFileStr, "-")? fopen(outFileStr, "w"): stdout)) == NULL) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to open output file (%s).\n", *argv, errMsg); } else { if((errNum = WlzWriteObj(fP, dwnObj)) != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: Failed to write output object (%s).\n", argv[0], errMsg); } } if(fP && strcmp(outFileStr, "-")) { fclose(fP); } } AlcFree(cmdStr); (void )WlzFreeObj(refObj); (void )WlzFree3DViewStruct(view); (void )WlzFreeObj(dwnObj); if(usage) { (void )fprintf(stderr, "Usage: %s%s%s%sExample: %s%s", *argv, " [-2] [-a<pitch,yaw,roll>]\n" " [-f <fx,fy,fz>]\n" " [-d <dist> [-b <view bib file>]\n" " [-m <mode>] [-u<ux,uy,uz>]\n" " [-e] [-E<vx,vy,vz>]\n" " [-g <ox,oy,oz>] [-h] [-o<output>]\n" " [-r <ref object>]\n" " [-s <cmd str>] [<cmd str file>>]\n" "Version: ", WlzVersion(), "\n" "Options:\n" " -2 Ignore the view struct and keep as a 2D object.\n" " -a Viewing angles: pitch (phi), yaw (theta) and roll (zeta),\n" " default 0.0,0.0,0.0.\n" " -f Fixed point position, default 0.0,0.0,0.0.\n" " -d Distance parameter, default 0.0.\n" " -b Bib file with view parameters, e.g. saved from MAPaint.\n" " -m Viewing mode, one of: up-is-up, statue or absolute, default\n" " is up-is-up.\n" " -u Up vector, default 0.0,0.0,1.0.\n" " -e Use object voxel size, default is voxel size 1.0,1.0,1.0.\n" " -E Use supplied voxel size rather than the object voxel size,\n" " default 1.0,1.0,1.0.\n" " -g Origin of the drawing with respect to the 2D Woolz object\n" " cut using the view transform, default 0.0,0.0.\n" " -r Reference object. If given this is must be a 3D spatial domain\n" " object. The object is used to determine an additional offset\n" " for the origin of the 2D plane with respect to the section in 3D\n" " (i.e. it is added to any offset given using the -g option).\n" " -s Drawing command string.\n" " -h Help, prints this usage message.\n" " -o Output file name.\n" "Reads drawing commands from either a string given on the command line,\n" "a file given on the command line or the standard input (in this order\n" "of precidence). The drawing commands are used to create a drawn\n" "section which is placed into 3D using the view transform.\n" "\n" "The command string must have the following syntax:\n" " <command string> = <init command>[<command>]+<end command>\n" " <init command> = <ident>:<version>;\n" " <end command> = END:;\n" " <ident> = WLZ_DRAW_DOMAIN\n" " <version> = 1\n" " <command> = <command name>:[<parameter>[,<parameter>]*];\n" " <command name> = PEN | LINE | CIRCLE\n" "In addition to the init and end commands, the following\n" "drawing commands are recognised:\n" " CIRCLE:<action>:<radius>,<x>,<y>;\n" " LINE:<action>:<width>,<x>,<y>,<x>,<y>;\n" " PEN:<action>,<width>,<x>,<y>[,<x>,<y>]*;\n" "Where:\n" " <action> = DRAW | ERASE\n" "The circle command draws or erases a filled circle which is specified\n" "by it's radius and centre parameters.\n" "The line command draws a rectangle using the given width and end\n" "coordinates of the mid-line.\n" "The pen command draws a polyline which is composed of a series of\n" "rectangular segments, with each segment ending in a semi-circular cap.\n" "The parameters of the pen command are the width and line segment end\n" "point coordinates.\n" "All widths, radii and coordinates may be in any floating point format\n" "recognised by scanf(3).\n" "Other commands may be present provided they have the same syntax\n" "described above, but they will be ignored.\n" "All white space characters are ignored.\n", *argv, " -o out.wlz -s 'WLZ_DRAW_DOMAIN:1; CIRCLE:DRAW,100,200,300; END:;'\n" "This creates a 3D domain object with a single plane at z = 0\n" "which has a domain that is a single circle (radius = 100,\n" "centre = 200,300).\n"); } return(!ok); }
/*! * \ingroup WlzValuesUtils * \brief Convert a grey-level woolz object to RGBA via a colourmap look-up table. Values are clamped to [0,255] and the LUT is assumed to be unsigned byte 3x256 * * \return Woolz object * \param obj Input object to be converted * \param colormap Colourmap array * \param dstErr Error return * \par Source: * WlzRGBAConvert.c */ WlzObject *WlzIndexToRGBA( WlzObject *obj, unsigned char colormap[3][256], WlzErrorNum *dstErr) { WlzObject *rtnObj=NULL; WlzGreyType oldpixtype; WlzGreyP go, gn; WlzIntervalWSpace oldiwsp, newiwsp; WlzGreyWSpace oldgwsp, newgwsp; WlzObjectType newvtbltype; WlzPixelV bg; WlzValues values; int k, greyVal, redVal, greenVal, blueVal; unsigned int rgbaVal; WlzErrorNum errNum=WLZ_ERR_NONE; /* check object - must be domain object with a values table */ if( obj ){ switch( obj->type ){ case WLZ_2D_DOMAINOBJ: if( obj->domain.core ){ if( obj->values.core == NULL ){ errNum = WLZ_ERR_VALUES_NULL; } else { oldpixtype = WlzGreyTableTypeToGreyType(obj->values.core->type, NULL); if( oldpixtype == WLZ_GREY_RGBA ){ return WlzMakeMain(obj->type, obj->domain, obj->values, NULL, NULL, dstErr); } } } else { errNum = WLZ_ERR_DOMAIN_NULL; } break; case WLZ_3D_DOMAINOBJ: return WlzIndexToRGBA3D(obj, colormap, dstErr); default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } else { errNum = WLZ_ERR_OBJECT_NULL; } /* * Set type of new value table so as to preserve * rectangular/single interval/multiple interval * type. */ if( errNum == WLZ_ERR_NONE ){ newvtbltype = WlzGreyTableTypeToTableType(obj->values.core->type, &errNum); } if( errNum == WLZ_ERR_NONE ){ newvtbltype = WlzGreyTableType(newvtbltype, WLZ_GREY_RGBA, &errNum); } /* get the background - note background now carries its own type */ if( errNum == WLZ_ERR_NONE ){ bg = WlzGetBackground(obj, &errNum); switch( bg.type ){ case WLZ_GREY_INT: greyVal = WLZ_CLAMP(bg.v.inv, 0, 255); break; case WLZ_GREY_SHORT: greyVal = WLZ_CLAMP(bg.v.shv, 0, 255); break; case WLZ_GREY_UBYTE: greyVal = bg.v.ubv; break; case WLZ_GREY_FLOAT: greyVal = WLZ_CLAMP(bg.v.flv, 0, 255); break; case WLZ_GREY_DOUBLE: greyVal = (int )WLZ_CLAMP(bg.v.dbv, 0, 255); break; default: errNum = WLZ_ERR_GREY_TYPE; break; } bg.type = WLZ_GREY_RGBA; WLZ_RGBA_RGBA_SET(bg.v.rgbv, colormap[0][greyVal], colormap[1][greyVal], colormap[2][greyVal], 255); } /* * Make the new object with new value table type and value table * allocated (but blank). Share original idom. */ if( errNum == WLZ_ERR_NONE ){ values.v = WlzNewValueTb(obj, newvtbltype, bg, &errNum); } if( errNum == WLZ_ERR_NONE ){ rtnObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, obj->domain, values, obj->plist, obj->assoc, &errNum); } if( errNum == WLZ_ERR_NONE ){ errNum = WlzInitGreyScan(obj, &oldiwsp, &oldgwsp); } if( errNum == WLZ_ERR_NONE ){ errNum = WlzInitGreyScan(rtnObj, &newiwsp, &newgwsp); } while( ((errNum = WlzNextGreyInterval(&oldiwsp)) == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(&newiwsp)) == WLZ_ERR_NONE) ){ go = oldgwsp.u_grintptr; gn = newgwsp.u_grintptr; for(k=0; k <= oldiwsp.colrmn; k++){ switch( oldgwsp.pixeltype ){ case WLZ_GREY_INT: greyVal = WLZ_CLAMP(*(go.inp), 0, 255); go.inp++; break; case WLZ_GREY_SHORT: greyVal = WLZ_CLAMP(*(go.shp), 0, 255); go.shp++; break; case WLZ_GREY_UBYTE: greyVal = *(go.ubp); go.ubp++; break; case WLZ_GREY_FLOAT: greyVal = WLZ_CLAMP(*(go.flp), 0, 255); go.flp++; break; case WLZ_GREY_DOUBLE: greyVal = (int )WLZ_CLAMP(*(go.dbp), 0, 255); go.dbp++; break; default: errNum = WLZ_ERR_GREY_TYPE; break; } redVal = colormap[0][greyVal]; greenVal = colormap[1][greyVal]; blueVal = colormap[2][greyVal]; WLZ_RGBA_RGBA_SET(rgbaVal, redVal, greenVal, blueVal, 0xff); *(gn.rgbp) = rgbaVal; gn.rgbp++; } } /* while */ if(errNum == WLZ_ERR_EOO) /* Reset error from end of intervals */ { errNum = WLZ_ERR_NONE; } if( dstErr ){ *dstErr = errNum; } return rtnObj; }
WlzErrorNum WlzGreyScalarDivValue( WlzObject *obj, WlzPixelV val) { WlzObject *tmpObj; WlzIntervalWSpace iwsp; WlzGreyWSpace gwsp; WlzGreyP gptr; WlzPixelV tmpVal; WlzDomain *domains; WlzValues *values; int i, nplanes; int red = 0, green = 0, blue = 0, alpha = 0; WlzErrorNum errNum=WLZ_ERR_NONE; /* check object */ if( obj == NULL ){ errNum = WLZ_ERR_OBJECT_NULL; } else { switch( obj->type ){ case WLZ_2D_DOMAINOBJ: if( obj->domain.i == NULL ){ errNum = WLZ_ERR_DOMAIN_NULL; } else if( obj->values.v == NULL ){ errNum = WLZ_ERR_VALUES_NULL; } break; case WLZ_3D_DOMAINOBJ: /* check planedomain and voxeltable */ if( obj->domain.p == NULL ){ errNum = WLZ_ERR_DOMAIN_NULL; } else if( obj->domain.p->type != WLZ_PLANEDOMAIN_DOMAIN ){ errNum = WLZ_ERR_DOMAIN_TYPE; } else if( obj->values.vox == NULL ){ errNum = WLZ_ERR_VALUES_NULL; } else if( obj->values.vox->type != WLZ_VOXELVALUETABLE_GREY ){ errNum = WLZ_ERR_VALUES_TYPE; } else { /* set range of each plane if non-empty - indicated by NULL */ domains = obj->domain.p->domains; values = obj->values.vox->values; nplanes = obj->domain.p->lastpl - obj->domain.p->plane1 + 1; for(i=0; (errNum == WLZ_ERR_NONE) && (i < nplanes); i++, domains++, values++){ if( (*domains).core == NULL || (*values).core == NULL ){ continue; } if((tmpObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, *values, NULL, NULL, NULL)) != NULL){ errNum = WlzGreyScalarDivValue(tmpObj, val); WlzFreeObj( tmpObj ); } } } return errNum; case WLZ_TRANS_OBJ: return WlzGreyScalarDivValue(obj->values.obj, val); case WLZ_EMPTY_OBJ: return errNum; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } if( errNum == WLZ_ERR_NONE ){ errNum = WlzInitGreyScan(obj, &iwsp, &gwsp); WlzValueConvertPixel(&tmpVal, val, WLZ_GREY_DOUBLE); while( (errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE ){ gptr = gwsp.u_grintptr; switch (gwsp.pixeltype) { case WLZ_GREY_INT: for (i=0; i<iwsp.colrmn; i++, gptr.inp++) *gptr.inp /= tmpVal.v.dbv; break; case WLZ_GREY_SHORT: for (i=0; i<iwsp.colrmn; i++, gptr.shp++) *gptr.shp /= tmpVal.v.dbv; break; case WLZ_GREY_UBYTE: for (i=0; i<iwsp.colrmn; i++, gptr.ubp++) *gptr.ubp /= tmpVal.v.dbv; break; case WLZ_GREY_FLOAT: for (i=0; i<iwsp.colrmn; i++, gptr.flp++) *gptr.flp /= tmpVal.v.dbv; break; case WLZ_GREY_DOUBLE: for (i=0; i<iwsp.colrmn; i++, gptr.dbp++) *gptr.dbp /= tmpVal.v.dbv; break; case WLZ_GREY_RGBA: for (i=0; i<iwsp.colrmn; i++, gptr.rgbp++) red = WLZ_RGBA_RED_GET(*gptr.rgbp) / tmpVal.v.dbv; green = WLZ_RGBA_GREEN_GET(*gptr.rgbp) / tmpVal.v.dbv; blue = WLZ_RGBA_BLUE_GET(*gptr.rgbp) / tmpVal.v.dbv; alpha = WLZ_RGBA_ALPHA_GET(*gptr.rgbp); red = WLZ_CLAMP(red, 0, 255); green = WLZ_CLAMP(red, 0, 255); blue = WLZ_CLAMP(red, 0, 255); WLZ_RGBA_RGBA_SET(*gptr.rgbp, red, green, blue, alpha); break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } if( errNum == WLZ_ERR_EOO ){ errNum = WLZ_ERR_NONE; } } return errNum; }
/*! * \return Shade corrected object or NULL on error. * \ingroup WlzValueFilters * \brief Shade corrects the given 2D domain object with grey * values. Grey value types known to be the same. * \param srcObj Given object to be shade * corrected. * \param shdObj Given bright field object. * \param nrmVal Normalization value. * \param inPlace Modify the grey values of the * given object if non-zero. * \param dstErr Destination error pointer, may * be null. */ static WlzObject *WlzShadeCorrect2DG(WlzObject *srcObj, WlzObject *shdObj, double nrmVal, int inPlace, WlzErrorNum *dstErr) { int tI0, iCnt, red, green, blue; double tD0; WlzUInt tUI0, tUI1; WlzObject *uObj = NULL, *uSrcObj = NULL, *uShdObj = NULL, *rtnObj = NULL; WlzGreyP srcPix, shdPix, rtnPix; WlzValues newVal; WlzIntervalWSpace srcIWSp, shdIWSp, rtnIWSp; WlzGreyWSpace srcGWSp, shdGWSp, rtnGWSp; WlzErrorNum errNum = WLZ_ERR_NONE; /* Find intersection of the given and shade objects. */ uObj = WlzIntersect2(srcObj, shdObj, &errNum); /* Make new objects with the values of the given and shade objects * but the domain of their intersection. */ if(errNum == WLZ_ERR_NONE) { uSrcObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, uObj->domain, srcObj->values, NULL, NULL, &errNum); } if(errNum == WLZ_ERR_NONE) { uShdObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, uObj->domain, shdObj->values, NULL, NULL, &errNum); } /* Make a new object, again using the union for the domain, but this time * either sharing the given objects values or creating a new value table. */ if(errNum == WLZ_ERR_NONE) { if(inPlace) { rtnObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, uObj->domain, srcObj->values, NULL, NULL, &errNum); } else { newVal.v = WlzNewValueTb(uObj, srcObj->values.core->type, WlzGetBackground(srcObj, NULL), &errNum); if(errNum == WLZ_ERR_NONE) { if((rtnObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, uObj->domain, newVal, NULL, NULL, &errNum)) == NULL) { (void )WlzFreeValueTb(newVal.v); } } } } /* Work through the intervals setting the grey values. */ if(errNum == WLZ_ERR_NONE) { if(((errNum = WlzInitGreyScan(uSrcObj, &srcIWSp, &srcGWSp)) == WLZ_ERR_NONE) && ((errNum = WlzInitGreyScan(uShdObj, &shdIWSp, &shdGWSp)) == WLZ_ERR_NONE) && ((errNum = WlzInitGreyScan(rtnObj, &rtnIWSp, &rtnGWSp)) == WLZ_ERR_NONE)) { while(((errNum = WlzNextGreyInterval(&srcIWSp)) == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(&shdIWSp)) == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(&rtnIWSp)) == WLZ_ERR_NONE)) { srcPix = srcGWSp.u_grintptr; shdPix = shdGWSp.u_grintptr; rtnPix = rtnGWSp.u_grintptr; iCnt = rtnIWSp.rgtpos - rtnIWSp.lftpos + 1; switch(rtnGWSp.pixeltype) { case WLZ_GREY_INT: while(iCnt-- > 0) { tD0 = (*(srcPix.inp)++ * nrmVal) / (*(shdPix.inp)++ + 1.0); *(rtnPix.inp)++ = WLZ_NINT(tD0); } break; case WLZ_GREY_SHORT: while(iCnt-- > 0) { tD0 = (*(srcPix.shp)++ * nrmVal) / (*(shdPix.shp)++ + 1.0); tI0 = WLZ_NINT(tD0); *(rtnPix.shp)++ = (short )WLZ_CLAMP(tI0, SHRT_MIN, SHRT_MAX); } break; case WLZ_GREY_UBYTE: while(iCnt-- > 0) { tD0 = (*(srcPix.ubp)++ * nrmVal) / (*(shdPix.ubp)++ + 1.0); tI0 = WLZ_NINT(tD0); *(rtnPix.ubp)++ = (WlzUByte )WLZ_CLAMP(tI0, 0, 255); } break; case WLZ_GREY_FLOAT: while(iCnt-- > 0) { tD0 = (*(srcPix.flp)++ * nrmVal) / (*(shdPix.flp)++ + 1.0); *(rtnPix.flp)++ = (float )tD0; } break; case WLZ_GREY_DOUBLE: while(iCnt-- > 0) { tD0 = (*(srcPix.dbp)++ * nrmVal) / (*(shdPix.dbp)++ + 1.0); *(rtnPix.dbp)++ = tD0; } break; case WLZ_GREY_RGBA: while(iCnt-- > 0) { /* slightly different logic here. Avoid divide by zero by explicit check */ tUI0 = *(srcPix.rgbp)++; tUI1 = *(shdPix.rgbp)++; red = WLZ_RGBA_RED_GET(tUI1); red = (red)? (int )(((WLZ_RGBA_RED_GET(tUI0) * nrmVal))/red): (int )nrmVal; red = WLZ_CLAMP(red, 0, 255); green = WLZ_RGBA_GREEN_GET(tUI1); green = (green)? (int )(((WLZ_RGBA_GREEN_GET(tUI0) * nrmVal))/green): (int )nrmVal; green = WLZ_CLAMP(green, 0, 255); blue = WLZ_RGBA_BLUE_GET(tUI1); blue = (blue)? (int )(((WLZ_RGBA_BLUE_GET(tUI0) * nrmVal))/blue): (int )nrmVal; blue = WLZ_CLAMP(blue, 0, 255); WLZ_RGBA_RGBA_SET(tUI0, red, green, blue, 255); *(rtnPix.rgbp)++ = tUI0; } break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } if(errNum == WLZ_ERR_EOO) /* Reset error from end of intervals */ { errNum = WLZ_ERR_NONE; } } } (void )WlzFreeObj(uObj); (void )WlzFreeObj(uSrcObj); (void )WlzFreeObj(uShdObj); if(errNum != WLZ_ERR_NONE) { (void )WlzFreeObj(rtnObj); rtnObj = NULL; } if(dstErr) { *dstErr = errNum; } return(rtnObj); }