Esempio n. 1
0
/*!
* \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);
}
Esempio n. 2
0
/*!
* \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);
}
Esempio n. 3
0
/*! 
* \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;
}
Esempio n. 4
0
/*! 
* \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;
}
Esempio n. 5
0
/*!
* \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);
}
Esempio n. 6
0
/*! 
* \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);
}
Esempio n. 8
0
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);
}
Esempio n. 9
0
/*! 
* \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;
}
Esempio n. 10
0
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;
}
Esempio n. 11
0
/*!
* \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);
}