Esempio n. 1
0
/*!
* \return	Convex hull object, NULL on error.
* \ingroup	WlzConvexHull
* \brief	Computes the convex hull of the given object.
* \param	obj			Given object.
* \param	dstErr			Destination error pointer, may be NULL.
*/
WlzObject *WlzObjToConvexHull(
  WlzObject	*obj,
  WlzErrorNum	*dstErr)
{
  WlzObject	*cvh=NULL;
  WlzValues	values;
  WlzErrorNum	errNum=WLZ_ERR_NONE;

  /* the convex hull is a polygon domain with values which are
     a set of chords with pre-calculated parameters which can be used
     by other procedures */
  if((cvh = WlzObjToConvexPolygon(obj, &errNum)) != NULL){
    if((values.c = WlzMakeConvexHullValues(cvh, obj, &errNum)) != NULL){
      /* assign values and reset object type which is now
	 WLZ_CONV_HULL rather than WLZ_2D_POLYGON */
      cvh->values = WlzAssignValues(values, NULL);
      if( cvh->type == WLZ_2D_POLYGON ){
	cvh->type = WLZ_CONV_HULL;
      }
      if( cvh->type == WLZ_3D_DOMAINOBJ ){
	cvh->domain.p->type = WLZ_PLANEDOMAIN_CONV_HULL;
      }
    }
  }

  if( dstErr ){
    *dstErr = errNum;
  }
  return cvh;
}
Esempio n. 2
0
/*!
* \return	New convex hull values.
* \ingroup	WlzConvexHull
* \brief	Fill in parameters of the convex hull into the values table.
* \param	cvh			Given convex hull.
* \param	obj			Given object.
* \param	dstErr			Destination error pointer, may be NULL.
*/
static WlzConvHullValues *WlzMakeConvexHullValues3d(
  WlzObject *cvh,
  WlzObject *obj,
  WlzErrorNum *dstErr)
{
  WlzValues		rtnvalues, *valuess, values;
  WlzObject		*obj1, *obj2;
  WlzDomain		*domains1, *domains2;
  WlzPixelV		bckgrnd;
  int			p;
  WlzErrorNum		errNum=WLZ_ERR_NONE;

  /* this is only called after a successful call to WlzObjToConvexPolygon
     therefore the given convex hull object and object have been checked
     and match */
  rtnvalues.c = NULL;
  bckgrnd.type = WLZ_GREY_UBYTE;
  bckgrnd.v.ubv = 0;

  /* make a voxeltable and calculate the convex hull values for each plane */
  if((rtnvalues.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_CONV_HULL,
					  cvh->domain.p->plane1,
					  cvh->domain.p->lastpl,
					  bckgrnd, NULL, &errNum)) != NULL){
    domains1 = cvh->domain.p->domains;
    domains2 = obj->domain.p->domains;
    valuess = rtnvalues.vox->values;
    for(p=cvh->domain.p->plane1; p <= cvh->domain.p->lastpl;
	p++, domains1++, domains2++, valuess++){
      if( (*domains1).core != NULL ){
	values.core = NULL;
	obj1 = WlzMakeMain(WLZ_2D_POLYGON, *domains1, values,
			   NULL, NULL, NULL);
	obj2 = WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains2, values,
			   NULL, NULL, NULL);
	if((values.c = WlzMakeConvexHullValues(obj1, obj2, &errNum)) != NULL){
	  *valuess = WlzAssignValues(values, NULL);
	}
	else {
	  WlzFreeObj(obj2);
	  WlzFreeObj(obj1);
	  WlzFreeVoxelValueTb(rtnvalues.vox);
	  rtnvalues.vox = NULL;
	  break;
	}
	WlzFreeObj(obj2);
	WlzFreeObj(obj1);
      }
    }
  }


  if( dstErr ){
    *dstErr = errNum;
  }
  return rtnvalues.c;
}
Esempio n. 3
0
/*!
* \return	New 3D object.
* \ingroup	WlzAllocation
* \brief	Constructs a 3D domain object from 2D domain objects read
*		from the given files. Each file is read in turn and added
*		to the 3D object. An empty plane can be specified by
*		setting the file string to NULL. Either all or none of
*		the 2D objects must have values. When the 2D objects
*		have values then the background value of the first 2D
*		object is set to be the background value of the 3D object.
* \param	nFileStr		Number of file strings.
* \param	fileStr			File strings.
* \param	plane1			The plane coordinate of the first
*					2D object.
* \param	xSz			Column voxel size.
* \param	ySz			Line voxel size.
* \param	zSz			Plane voxel size.
* \param	dstErr			Destination error pointer, may be NULL.
*/
WlzObject	*WlzConstruct3DObjFromFile(int nFileStr, char **fileStr,
					  int plane1,
					  float xSz, float ySz, float zSz,
					  WlzErrorNum *dstErr)
{
  int		idx,
  		lastpl;
  WlzDomain	dom3D;
  WlzValues	val3D;
  WlzObject	*obj2D = NULL,
  		*obj3D = NULL;
  WlzPixelV	bgd;
  FILE		*fP = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  dom3D.core = NULL;
  val3D.core = NULL;
  lastpl = plane1 + nFileStr - 1;
  if((nFileStr <= 0) || (fileStr == NULL) || (*fileStr == NULL))
  {
    errNum = WLZ_ERR_PARAM_NULL;
  }
  else
  {
    if((fP = fopen(*fileStr, "r")) == NULL)
    {
      errNum = WLZ_ERR_READ_EOF;
    }
    else
    {
      obj2D = WlzReadObj(fP, &errNum);
      (void )fclose(fP);
      fP = NULL;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    switch(obj2D->type)
    {
      case WLZ_EMPTY_OBJ:
	break;
      case WLZ_2D_DOMAINOBJ:
	if(obj2D->domain.core == NULL)
	{
	  errNum = WLZ_ERR_DOMAIN_NULL;
	}
	break;
      default:
	errNum = WLZ_ERR_OBJECT_TYPE;
	break;
    }
  }
  /* Make a plane domain, set column and line bounds later. */
  if(errNum == WLZ_ERR_NONE)
  {
    dom3D.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN,
    				 plane1, lastpl,
				 0, 1, 0, 1, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    dom3D.p->voxel_size[0] = xSz;
    dom3D.p->voxel_size[1] = ySz;
    dom3D.p->voxel_size[2] = zSz;
  }
  /* Make a voxel value table. */
  if(errNum == WLZ_ERR_NONE)
  {
    if(obj2D->values.core)
    {
      bgd = WlzGetBackground(obj2D, &errNum);
      if(errNum == WLZ_ERR_NONE)
      {
	val3D.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY,
					plane1, lastpl, bgd, NULL, &errNum);
      }
    }				    
  }
  idx = 0;
  while((errNum == WLZ_ERR_NONE) && (idx < nFileStr))
  {
    if(obj2D)
    {
      switch(obj2D->type)
      {
	case WLZ_EMPTY_OBJ:
	  break;
	case WLZ_2D_DOMAINOBJ:
	  if(obj2D->domain.core == NULL)
	  {
	    errNum = WLZ_ERR_DOMAIN_NULL;
	  }
	  break;
	default:
	  errNum = WLZ_ERR_OBJECT_TYPE;
	  break;
      }
      if(errNum == WLZ_ERR_NONE)
      {
	*(dom3D.p->domains + idx) = WlzAssignDomain(obj2D->domain, NULL);
	if(val3D.core)
	{
	  if((obj2D->domain.core != NULL) && (obj2D->values.core == NULL))
	  {
	    errNum = WLZ_ERR_VALUES_NULL;
	  }
	  else
	  {
	    *(val3D.vox->values + idx) = WlzAssignValues(obj2D->values, NULL);
	  }
	}
      }
      WlzFreeObj(obj2D);
      obj2D = NULL;
    }
    if(errNum == WLZ_ERR_NONE)
    {
      ++idx;
      if((idx < nFileStr) && *(fileStr + idx))
      {
	if((fP = fopen(*(fileStr + idx), "r")) == NULL)
	{
	  errNum = WLZ_ERR_READ_EOF;
	}
	else
	{
	  obj2D = WlzReadObj(fP, &errNum);
	  (void )fclose(fP);
	  fP = NULL;
	}
      }
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    errNum = WlzStandardPlaneDomain(dom3D.p, val3D.vox);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    obj3D = WlzMakeMain(WLZ_3D_DOMAINOBJ, dom3D, val3D, NULL, NULL, &errNum);
  }
  if(errNum != WLZ_ERR_NONE)
  {
    if(dom3D.core)
    {
      (void )WlzFreeDomain(dom3D);
    }
    if(val3D.core)
    {
      (void )WlzFreeValues(val3D);
    }
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(obj3D);
}
Esempio n. 4
0
/*!
* \return	Distance object which shares the given foreground object's
*		domain and has integer distance values, null on error.
* \ingroup	WlzMorphologyOps
* \brief	Computes the distance of every pixel/voxel in the foreground
* 		object from the reference object.
*
*		A distance transform maps all position within a  forground
*		domain to their distances from a reference domain.
*		The distance transforms implemented within this function
*		use efficient morphological primitives.
*		
*		Given two domains,
*		\f$\Omega_r\f$ the reference domain and \f$\Omega_f\f$
*		the domain specifying the region of interest,
*		a domain with a thin shell \f$\Omega_i\f$
*		is iteratively expanded from it's initial domain
*		corresponding to the reference domain \f$\Omega_r\f$.
*		At each iteration
*		\f$\Omega_i\f$ is dilated and clipped
*		by it's intersection with \f$\Omega_f\f$ until \f$\Omega_i\f$
*		becomes the null domain \f$\emptyset\f$.
*		At each iteration the current distance is recorded in a value
*		table which
*		covers the domain \f$\Omega_f\f$.
*
*		An octagonal distance scheme may be used in which
*		the distance metric is alternated between 4 and 8
*		connected for 2D and 6 and 26 connectivities in 3D.
*		See: G. Borgefors. "Distance Transformations in Arbitrary
*		Dimensions" CVGIP 27:321-345, 1984.
*
* 		An approximate Euclidean distance transform may be computed
* 		by: Scaling the given foreground and reference objects using
* 		the given approximation scale parameter, dilating the
* 		reference domain using a sphere with a radius having the same
* 		value as the scale parameter and then finaly sampling the
* 		scaled distances.
* \param	forObj			Foreground object.
* \param	refObj			Reference object.
* \param	dFn			Distance function which must be
*					appropriate to the dimension of
*					the foreground and reference objects.
* \param	dParam			Parameter required for distance
* 					function. Currently only
* 					WLZ_APX_EUCLIDEAN_DISTANCE requires a
* 					parameter. In this case the parameter
* 					is the approximation scale.
* \param	dstErr			Destination error pointer, may be NULL.
*/
WlzObject 	*WlzDistanceTransform(WlzObject *forObj, WlzObject *refObj,
				   WlzDistanceType dFn, double dParam,
				   WlzErrorNum *dstErr)
{
  int 		idP,
		lastP,
		dim,
  		notDone = 1;
  double	scale;
  WlzObject	*tmpObj,
		*sObj = NULL,
		*sForObj = NULL,
		*sRefObj = NULL,
		*dilObj = NULL,
  		*dstObj = NULL,
		*difObj = NULL,
  		*curItrObj = NULL;
  WlzObject 	*bothObj[2];
  WlzDomain	*difDoms;
  WlzPixelV 	dstV,
  		bgdV;
  WlzValues 	*difVals;
  WlzAffineTransform *tr = NULL;
  WlzConnectType con;
  WlzObjectType dstGType;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  WlzValues 	difVal,
  		dstVal,
		nullVal;
  /* By defining WLZ_DIST_TRANSFORM_ENV these normalization parameters
   * are read from the environment. This is useful for optimization. */
#ifndef WLZ_DIST_TRANSFORM_ENV
  const
#endif /* ! WLZ_DIST_TRANSFORM_ENV */
  /* These normalizarion factors have been choosen to minimize the sum of
   * squares of the deviation of the distance values from Euclidean values
   * over a radius 100 circle or sphere, where the distances are computed
   * from the circumference of the sphere towards it's centre. The values
   * were established by experiment. */
  double	nrmDist4 =  0.97,
		nrmDist6 =  0.91,
		nrmDist8 =  1.36,
		nrmDist18 = 1.34,
		nrmDist26 = 1.60;

#ifdef WLZ_DIST_TRANSFORM_ENV
  double	val;
  char		*envStr;

  if(((envStr = getenv("WLZ_DIST_TRANSFORM_NRMDIST4")) != NULL) &&
     (sscanf(envStr, "%lg", &val) == 1))
  {
    nrmDist4 = val;
  }
  if(((envStr = getenv("WLZ_DIST_TRANSFORM_NRMDIST6")) != NULL) &&
     (sscanf(envStr, "%lg", &val) == 1))
  {
    nrmDist6 = val;
  }
  if(((envStr = getenv("WLZ_DIST_TRANSFORM_NRMDIST8")) != NULL) &&
     (sscanf(envStr, "%lg", &val) == 1))
  {
    nrmDist8 = val;
  }
  if(((envStr = getenv("WLZ_DIST_TRANSFORM_NRMDIST18")) != NULL) &&
     (sscanf(envStr, "%lg", &val) == 1))
  {
    nrmDist18 = val;
  }
  if(((envStr = getenv("WLZ_DIST_TRANSFORM_NRMDIST26")) != NULL) &&
     (sscanf(envStr, "%lg", &val) == 1))
  {
    nrmDist26 = val;
  }
#endif /* WLZ_DIST_TRANSFORM_ENV */
  scale = dParam;
  nullVal.core = NULL;
  /* Check parameters. */
  if((forObj == NULL) || (refObj == NULL))
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if(((forObj->type != WLZ_2D_DOMAINOBJ) &&
           (forObj->type != WLZ_3D_DOMAINOBJ)) ||
          ((refObj->type != WLZ_POINTS) &&
	   (refObj->type != forObj->type)))
  {
    errNum = WLZ_ERR_OBJECT_TYPE;
  }
  else if((forObj->domain.core == NULL) || (refObj->domain.core == NULL))
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  if(errNum == WLZ_ERR_NONE)
  {
    bgdV.type = WLZ_GREY_INT;
    bgdV.v.inv = 0;
    dstV.type = WLZ_GREY_DOUBLE;
    dstV.v.dbv = 0.0;
    switch(forObj->type)
    {
      case WLZ_2D_DOMAINOBJ:
	switch(dFn)
	{
	  case WLZ_4_DISTANCE: /* FALLTHROUGH */
	  case WLZ_8_DISTANCE: /* FALLTHROUGH */
	  case WLZ_OCTAGONAL_DISTANCE: /* FALLTHROUGH */
	  case WLZ_APX_EUCLIDEAN_DISTANCE:
	    dim = 2;
	    break;
	  default:
	    errNum = WLZ_ERR_PARAM_DATA;
	    break;
	}
        break;
      case WLZ_3D_DOMAINOBJ:
	switch(dFn)
	{
	  case WLZ_6_DISTANCE:  /* FALLTHROUGH */
	  case WLZ_18_DISTANCE: /* FALLTHROUGH */
	  case WLZ_26_DISTANCE: /* FALLTHROUGH */
	  case WLZ_OCTAGONAL_DISTANCE: /* FALLTHROUGH */
	  case WLZ_APX_EUCLIDEAN_DISTANCE:
	    dim = 3;
	    break;
	  default:
	    errNum = WLZ_ERR_PARAM_DATA;
	    break;
	}
        break;
      default:
        errNum = WLZ_ERR_OBJECT_TYPE;
	break;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    switch(dFn)
    {
      case WLZ_4_DISTANCE:
        con = WLZ_4_CONNECTED;
	break;
      case WLZ_6_DISTANCE:
        con = WLZ_6_CONNECTED;
	break;
      case WLZ_8_DISTANCE:
        con = WLZ_8_CONNECTED;
	break;
      case WLZ_18_DISTANCE:
        con = WLZ_18_CONNECTED;
	break;
      case WLZ_26_DISTANCE:
        con = WLZ_26_CONNECTED;
	break;
      case WLZ_OCTAGONAL_DISTANCE:
        con = (dim == 2)? WLZ_8_CONNECTED: WLZ_26_CONNECTED;
	break;
      case WLZ_APX_EUCLIDEAN_DISTANCE:
        con = (dim == 2)? WLZ_8_CONNECTED: WLZ_26_CONNECTED;
	if(scale < 1.0)
	{
	  errNum = WLZ_ERR_PARAM_DATA;
	}
	break;
      case WLZ_EUCLIDEAN_DISTANCE:
	errNum = WLZ_ERR_UNIMPLEMENTED;
	break;
      default:
        errNum = WLZ_ERR_PARAM_DATA;
	break;
    }
  }
  /* Create scaled domains and a sphere domain for structual erosion if the
   * distance function is approximate Euclidean. */
  if(errNum == WLZ_ERR_NONE)
  {
    if(dFn == WLZ_APX_EUCLIDEAN_DISTANCE)
    {
      tr = (dim == 2)?
	   WlzAffineTransformFromScale(WLZ_TRANSFORM_2D_AFFINE,
	                               scale, scale, 0.0, &errNum):
	   WlzAffineTransformFromScale(WLZ_TRANSFORM_3D_AFFINE,
	                               scale, scale, scale, &errNum);
      if(errNum == WLZ_ERR_NONE)
      {
	tmpObj = WlzMakeMain(forObj->type, forObj->domain, nullVal,
			     NULL, NULL, &errNum);
	if(tmpObj)
	{
	  sForObj = WlzAssignObject(
	            WlzAffineTransformObj(tmpObj, tr,
		                          WLZ_INTERPOLATION_NEAREST,
		    			  &errNum), NULL);
	  (void )WlzFreeObj(tmpObj);
	}
      }
      if(errNum == WLZ_ERR_NONE)
      {
	if(refObj->type == WLZ_POINTS)
	{
	  sRefObj = WlzPointsToDomObj(refObj->domain.pts, scale, &errNum);
	}
	else /* type == WLZ_2D_DOMAINOBJ || type == WLZ_3D_DOMAINOBJ */
	{
	  tmpObj = WlzMakeMain(refObj->type, refObj->domain, nullVal,
			       NULL, NULL, &errNum);
	  if(errNum == WLZ_ERR_NONE)
	  {
	    sRefObj = WlzAssignObject(
		      WlzAffineTransformObj(tmpObj, tr,
					    WLZ_INTERPOLATION_NEAREST,
					    &errNum), NULL);
	  }
	}
	(void )WlzFreeObj(tmpObj);
      }
      if(errNum == WLZ_ERR_NONE)
      {
	sObj = WlzAssignObject(
	       WlzMakeSphereObject(forObj->type, scale,
	                           0.0, 0.0, 0.0, &errNum), NULL);
      }
      (void )WlzFreeAffineTransform(tr);
    }
    else
    {
      sForObj = WlzAssignObject(
	        WlzMakeMain(forObj->type, forObj->domain, nullVal,
	  		    NULL, NULL, &errNum), NULL);
      if(errNum == WLZ_ERR_NONE)
      {
	if(refObj->type == WLZ_POINTS)
	{
	  sRefObj = WlzPointsToDomObj(refObj->domain.pts, 1.0, &errNum);
	}
	else
	{
	  sRefObj = WlzAssignObject(
		    WlzMakeMain(refObj->type, refObj->domain, nullVal,
				NULL, NULL, &errNum), NULL);
	}
      }
    }
  }
  /* Create new values for the computed distances. */
  if(errNum == WLZ_ERR_NONE)
  {
    dstGType = WlzGreyTableType(WLZ_GREY_TAB_RAGR, WLZ_GREY_INT, NULL);
    if(dim == 2)
    {
      dstVal.v = WlzNewValueTb(sForObj, dstGType, bgdV, &errNum);
    }
    else
    {
      dstVal.vox = WlzNewValuesVox(sForObj, dstGType, bgdV, &errNum);
    }
  }
  /* Create a distance object using the foreground object's domain and
   * the new distance values. */
  if(errNum == WLZ_ERR_NONE)
  {
    dstObj = WlzMakeMain(sForObj->type, sForObj->domain, dstVal,
			 NULL, NULL, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    bothObj[0] = sForObj;
    errNum = WlzGreySetValue(dstObj, dstV);
  }
  /* Dilate the reference object while setting the distances in each
   * dilated shell. */
  while((errNum == WLZ_ERR_NONE) && notDone)
  {
    if(dFn == WLZ_APX_EUCLIDEAN_DISTANCE)
    {
      dstV.v.dbv += 1.0;
    }
    else
    {
      switch(con)
      {
	case WLZ_4_CONNECTED:
	  dstV.v.dbv += nrmDist4;
	  break;
	case WLZ_6_CONNECTED:
	  dstV.v.dbv += nrmDist6;
	  break;
	case WLZ_8_CONNECTED:
	  dstV.v.dbv += nrmDist8;
	  break;
	case WLZ_18_CONNECTED:
	  dstV.v.dbv += nrmDist18;
	  break;
	case WLZ_26_CONNECTED:
	  dstV.v.dbv += nrmDist26;
	  break;
        default:
	  errNum = WLZ_ERR_CONNECTIVITY_TYPE;
	  break;
      }
    }
    if(dFn == WLZ_APX_EUCLIDEAN_DISTANCE)
    {
      dilObj = WlzStructDilation(sRefObj, sObj, &errNum);
    }
    else
    {
      dilObj = WlzDilation(sRefObj, con, &errNum);
    }
    if(errNum == WLZ_ERR_NONE)
    {
      switch(sForObj->type)
      {
        case WLZ_2D_DOMAINOBJ:
	  curItrObj = WlzAssignObject(
	              WlzIntersect2(dilObj, sForObj, &errNum), NULL);
	  break;
        case WLZ_3D_DOMAINOBJ:
	  bothObj[1] = dilObj;
	  curItrObj = WlzAssignObject(
	              WlzIntersectN(2, bothObj, 1, &errNum), NULL);
	  break;
        default:
	  errNum = WLZ_ERR_OBJECT_TYPE;
	  break;
      }
    }
    (void)WlzFreeObj(dilObj);
    /* Create difference object for the expanding shell. */
    if(errNum == WLZ_ERR_NONE)
    {
      difObj = WlzDiffDomain(curItrObj, sRefObj, &errNum);
    }
    if((difObj == NULL) || WlzIsEmpty(difObj, &errNum))
    {
      notDone = 0;
    }
    else
    {
      /* Assign the distance object's values to the difference object
       * and set all it's values to the current distance. */
      if(errNum == WLZ_ERR_NONE)
      {
	switch(sForObj->type)
	{
	  case WLZ_2D_DOMAINOBJ:
	    difObj->values = WlzAssignValues(dstObj->values, NULL);
	    errNum = WlzGreySetValue(difObj, dstV);
	    break;
	  case WLZ_3D_DOMAINOBJ:
	    /* 3D is more complex than 2D: Need to create a temporary
	     * voxel valuetable and assign the individual 2D values. */
	    difVal.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY,
					     difObj->domain.p->plane1,
					     difObj->domain.p->lastpl,
					     bgdV, NULL, &errNum);
	    if(errNum == WLZ_ERR_NONE)
	    {
	      difObj->values = WlzAssignValues(difVal, NULL);
	      difDoms = difObj->domain.p->domains;
	      difVals = difObj->values.vox->values;
	      idP = difObj->domain.p->plane1;
	      lastP = difObj->domain.p->lastpl;
	      while(idP <= lastP)
	      {
		if((*difDoms).core)
		{
		  dstVal = dstObj->values.vox->values[idP - 
						      dstObj->domain.p->plane1];
		  *difVals = WlzAssignValues(dstVal, NULL);
		}
		++idP;
		++difDoms;
		++difVals;
	      }
	      if(difObj->domain.p->lastpl > difObj->domain.p->plane1)
	      {
		errNum = WlzGreySetValue(difObj, dstV);
	      }
	    }
	    break;
	  default:
	    errNum = WLZ_ERR_OBJECT_TYPE;
	    break;
	}
      }
      (void )WlzFreeObj(sRefObj);
      sRefObj = WlzAssignObject(curItrObj, NULL);
      (void )WlzFreeObj(curItrObj);
    }
    (void )WlzFreeObj(difObj); difObj = NULL;
    if(dFn == WLZ_OCTAGONAL_DISTANCE)
    {
      /* Alternate connectivities for octagonal distance. */
      if(dim == 2)
      {
	con = (con == WLZ_4_CONNECTED)? WLZ_8_CONNECTED: WLZ_4_CONNECTED;
      }
      else /* dim == 3 */
      {
	con = (con == WLZ_6_CONNECTED)? WLZ_26_CONNECTED: WLZ_6_CONNECTED;
      }
    }
  }
  (void )WlzFreeObj(sObj);
  (void )WlzFreeObj(sForObj);
  (void )WlzFreeObj(sRefObj);
  (void )WlzFreeObj(curItrObj);
  if((errNum == WLZ_ERR_NONE) && (dFn == WLZ_APX_EUCLIDEAN_DISTANCE))
  {
    tmpObj = WlzDistSample(dstObj, dim, scale, &errNum);
    (void )WlzFreeObj(dstObj);
    dstObj = tmpObj;
  }
  if(errNum != WLZ_ERR_NONE)
  {
    (void )WlzFreeObj(dstObj); dstObj = NULL;
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(dstObj);
}
Esempio n. 5
0
void read_reference_object_cb(
  Widget	w,
  XtPointer	client_data,
  XtPointer	call_data)
{
  XmFileSelectionBoxCallbackStruct *cbs =
    (XmFileSelectionBoxCallbackStruct *) call_data;
  WlzEffFormat		image_type;
  WlzObject		*obj;
  String		icsfile;
  WlzDomain	domain;
  WlzValues	values;
  WlzObject	*newObj;
  WlzErrorNum		errNum=WLZ_ERR_NONE;

  /* set hour glass cursor */
  HGU_XmSetHourGlassCursor(globals.topl);

  /* read the new reference object
     note the switch is to allow direct read
     given the image type to include the model
     input options */
  if( client_data ){
    image_type = (WlzEffFormat) client_data;
    if((icsfile = HGU_XmGetFileStr(globals.topl, cbs->value,
				   cbs->dir))){
      obj = WlzEffReadObj(NULL, icsfile, image_type, 0, 0, 0, &errNum);
      AlcFree(icsfile);
    }
    else {
      obj = NULL;
    }
  }
  else {
    obj = HGU_XmReadExtFFObject(read_obj_dialog, cbs,
			       &image_type, &errNum);
  }
  if( obj == NULL){
    HGU_XmUserError(globals.topl,
		    "Read Reference Object:\n"
		    "    No reference object read - either the\n"
		    "    selected file is empty or it is not the\n"
		    "    correct object type - please check the\n"
		    "    file or make a new selection",
   		    XmDIALOG_FULL_APPLICATION_MODAL);
    /* set hour glass cursor */
    HGU_XmUnsetHourGlassCursor(globals.topl);
    return;
  }

  if( obj->values.core == NULL ){
    HGU_XmUserError(globals.topl,
		    "Read Reference Object:\n"
		    "    The reference object must have a grey-\n"
		    "    value table. Please select an alternate\n"
		    "    object",
		    XmDIALOG_FULL_APPLICATION_MODAL);
    WlzFreeObj( obj );
    /* set hour glass cursor */
    HGU_XmUnsetHourGlassCursor(globals.topl);
    return;
  }

  /* install the new reference object */
  switch( obj->type ){

  case WLZ_2D_DOMAINOBJ:
    if((domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, 0, 0,
				      obj->domain.i->line1,
				      obj->domain.i->lastln,
				      obj->domain.i->kol1,
				      obj->domain.i->lastkl,
				      &errNum))){
      domain.p->domains[0] = WlzAssignDomain(obj->domain, NULL);
      if((values.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY,
					   0, 0, WlzGetBackground(obj, NULL),
					   NULL, &errNum))){
	values.vox->values[0] = WlzAssignValues(obj->values, NULL);
	newObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values,
			     obj->plist, NULL, &errNum);
	WlzFreeObj(obj);
	obj = newObj;
      }
    }
    globals.origObjType = WLZ_2D_DOMAINOBJ;
    break;

  case WLZ_3D_DOMAINOBJ:
    globals.origObjType = WLZ_3D_DOMAINOBJ;
    break;

  default:
    HGU_XmUserError(globals.topl,
		    "Read Reference Object:\n"
		    "    The reference object must be a 2- or 3-D\n"
		    "    grey-level image. Please select an alternate\n"
		    "    object",
		    XmDIALOG_FULL_APPLICATION_MODAL);
    WlzFreeObj( obj );
    /* set hour glass cursor */
    HGU_XmUnsetHourGlassCursor(globals.topl);
    return;
  }
  globals.origObjExtType = image_type;

  /* set title and reference file list */
  if((icsfile = HGU_XmGetFileStr(globals.topl, cbs->value, cbs->dir)))
  {
    Widget	cascade;
    HGU_XmFileListAddFile(globals.fileList, icsfile, image_type);
    HGU_XmFileListWriteResourceFile(globals.fileList,
				    globals.resourceFile);
    if((cascade = XtNameToWidget(globals.topl,
				 "*file_menu*_pulldown*Recent"))){
      HGU_XmFileListResetMenu(globals.fileList, cascade, referenceFileListCb);
    }
    if( XmStringGetLtoR(cbs->value, XmSTRING_DEFAULT_CHARSET, &icsfile) )
    {
      set_topl_title(icsfile);
      globals.file = icsfile;
    }
  }
  MAPaintLogData("ReferenceFile", globals.file, 0, NULL);

  /* clear feedback object and install new reference object */
  if( errNum == WLZ_ERR_NONE ){
    if( globals.fb_obj ){
      WlzFreeObj(globals.fb_obj);
      globals.fb_obj = NULL;
    }
    install_paint_reference_object( obj );
  }

  /* set hour glass cursor */
  HGU_XmUnsetHourGlassCursor(globals.topl);

  if( errNum != WLZ_ERR_NONE ){
    MAPaintReportWlzError(globals.topl, "read_reference_object_cb", errNum);
  }
  return;
}
Esempio n. 6
0
void file_menu_init(
  Widget	topl)
{
  Widget	rc, form, toggle;
  Visual	*visual;
  Arg		arg[1];
  char		fileStr[128];
  FILE 		*fp;
  WlzEffFormat	image_type=WLZEFF_FORMAT_WLZ;

  /* set the top-level title */
  set_topl_title(NULL);

  /* get the visual explicitly */
  visual = HGU_XmWidgetToVisual(topl);
  XtSetArg(arg[0], XmNvisual, visual);

  /* create the read-model file selection dialog */
  read_model_dialog = XmCreateFileSelectionDialog(topl,
						  "read_model_dialog", arg, 1);
  XtAddCallback(read_model_dialog, XmNokCallback,
		read_reference_object_cb, (XtPointer) WLZEFF_FORMAT_WLZ);
  XtAddCallback(read_model_dialog, XmNokCallback, PopdownCallback, NULL);
  XtAddCallback( read_model_dialog, XmNcancelCallback, 
		PopdownCallback, NULL);
  XtAddCallback(read_model_dialog, XmNmapCallback,
		FSBPopupCallback, NULL);
  XtManageChild( read_model_dialog );

  /* create the read-obj file selection dialog */
  read_obj_dialog = HGU_XmCreateExtFFObjectFSB(topl, "read_obj_dialog",
					      read_reference_object_cb, NULL);
  if((rc = XtNameToWidget(read_obj_dialog, "*.formatFormRC"))){

    /* add a form to include file type and fill-blanks toggle */
    form = XtVaCreateManagedWidget("read_file_form", xmFormWidgetClass,
				   rc,
				   XmNborderWidth,	0,
				   NULL);

    /* add a fill-blanks toggles */
    toggle = XtVaCreateManagedWidget("fill_blanks", xmToggleButtonGadgetClass,
				     form,
				     XmNindicatorOn, 	True,
				     XmNindicatorType,	XmN_OF_MANY,
				     XmNset,		False,
				     XmNtopAttachment,	XmATTACH_FORM,
				     XmNleftAttachment,	XmATTACH_FORM,
				     NULL);

    toggle = XtVaCreateManagedWidget("min_domain", xmToggleButtonGadgetClass,
				     form,
				     XmNindicatorOn, 	True,
				     XmNindicatorType,	XmN_OF_MANY,
				     XmNset,		True,
				     XmNtopAttachment,	XmATTACH_FORM,
				     XmNleftAttachment,	XmATTACH_WIDGET,
				     XmNleftWidget,	toggle,
				     NULL);
  }

  HGU_XmExtFFObjectFSBSetType(read_obj_dialog, WLZEFF_FORMAT_WLZ);
  XtManageChild( read_obj_dialog );

  /* add to the save restore list */
  HGU_XmSaveRestoreAddWidget( read_obj_dialog, HGU_XmFSD_SaveFunc,
			     (XtPointer) XtName(topl), NULL, NULL );

  /* create the write-obj file selection dialog */
  write_obj_dialog = HGU_XmCreateExtFFObjectFSB(topl, "write_obj_dialog",
					       write_reference_object_cb,
					       NULL);
  HGU_XmExtFFObjectFSBSetType(write_obj_dialog, WLZEFF_FORMAT_WLZ);


  /* initialise the reference file list pulldown */
  if( !globals.sectViewFlg ){
    Widget	cascade;

    if((cascade = XtNameToWidget(globals.topl,
				 "*file_menu*_pulldown*Recent"))){
      globals.resourceFile = (String) 
	AlcMalloc(sizeof(char) * (strlen(getenv("HOME")) + 16));
      sprintf(globals.resourceFile, "%s/%s", getenv("HOME"), ".maRecentFiles");
      globals.fileList = HGU_XmFileListCreateList(globals.resourceFile, NULL);
      HGU_XmFileListResetMenu(globals.fileList, cascade, referenceFileListCb);
    }
  }

  /* add to the save restore list */
  HGU_XmSaveRestoreAddWidget( write_obj_dialog, HGU_XmFSD_SaveFunc,
			     (XtPointer) XtName(topl), NULL, NULL );

  /* create the object properties dialog */
  obj_props_dialog_init( topl );

  globals.file      = NULL;
  globals.obj       = NULL;
  globals.orig_obj  = NULL;
  globals.fb_obj    = NULL;
  globals.origObjExtType = image_type;

  /* setup the theiler directory and menu item - check for stage */
  XtGetApplicationResources(topl, &globals, set_att_res,
			    XtNumber(set_att_res), NULL, 0);

  /* check the logfile */
  if( globals.logfile ){
    if( (globals.logfileFp = fopen(globals.logfile, "w")) == NULL ){
      fprintf(stderr,
	      "MAPaint: something wrong with the logfile %s\n"
	      "Please check name and permissions\n"
	      "Logging not enabled\n\007", globals.logfile);
    }
    else {
      char		timeBuf[16];
      struct hostent 	*hstnt;
      fprintf(stderr, "MAPaint: logging enabled to %s\n", globals.logfile);
      MAPaintLogData("Filename", globals.logfile, 0, NULL);
      MAPaintLogData("User", getenv("USER"), 0, NULL);
#if defined (LINUX2) || defined (DARWIN)
      strcpy(timeBuf, "00/00/00");
#else
      tmpTime = time(NULL);
      cftime(timeBuf, "%d/%m/%Y", &tmpTime);
#endif /* LINUX2 */
      MAPaintLogData("Date", timeBuf, 0, NULL);
#if defined (LINUX2) || defined (DARWIN)
      strcpy(timeBuf, "00.00");
#else
      cftime(timeBuf, "%H.%M", &tmpTime);
#endif /* LINUX2 */
      MAPaintLogData("Time", timeBuf, 0, NULL);
      hstnt = gethostbyname(getenv("HOST"));
      MAPaintLogData("Host", getenv("HOST"), 0, NULL);
      MAPaintLogData("Hostname", hstnt->h_name, 0, NULL);
    }
  }
  else {
    globals.logfileFp = NULL;
  }

  /* check base directory - if the string has come from the resources then
     we need to duplicate it to allow it to be freed
     possibly some memory leakage here */
  /* note: only non-NULL if set by the user, if NULL then attempt to find
     the cdrom or copied data */
  if( globals.base_theiler_dir ){
    globals.base_theiler_dir = AlcStrDup( globals.base_theiler_dir );
  }
/*  else {
    FILE	*pp;*/
    
    /* search for the Theiler mode directory as per the CDROM 
       should search local disc first */
/*#if defined (LINUX2)
    if((pp = popen("find /mnt -maxdepth 4 -name Models", "r"))){
      while( fscanf(pp, "%s", fileStr) != EOF ){
	if( strstr(fileStr, "Models") ){
	  globals.base_theiler_dir = AlcStrDup(fileStr);
	  break;
	}
      }
      pclose(pp);
    }
#elif defined (DARWIN)
    if( (pp = popen("find /Volumes -maxdepth 4 -name Models", "r")) ){
      while( fscanf(pp, "%s", fileStr) != EOF ){
	if( strstr(fileStr, "Models") ){
	  globals.base_theiler_dir = AlcStrDup(fileStr);
	  break;
	}
      }
      pclose(pp);
    }
#elif defined (SUNOS4) || defined (SUNOS5)
    if( pp = popen("find /cdrom -maxdepth 4 -name Models", "r") ){
      while( fscanf(pp, "%s", fileStr) != EOF ){
	if( strstr(fileStr, "Models") ){
	  globals.base_theiler_dir = AlcStrDup(fileStr);
	  break;
	}
      }
      pclose(pp);
    }
#else
    globals.base_theiler_dir = NULL;
#endif
  }*/
  if( globals.theiler_stage ){
    char *tStr;
    if((tStr = theilerString(globals.theiler_stage))){
      globals.theiler_stage = AlcStrDup(tStr);
    }
    else {
      globals.theiler_stage = NULL;
    }
  }
  theiler_menu_init( topl );

  /* check for an initial reference file else check Theiler stage */
  if( initial_reference_file != NULL ){
    WlzObject 	*obj;

    /* open the reference object file and install */
    if( (fp = fopen(initial_reference_file, "r")) ){
      HGU_XmSetHourGlassCursor(topl);
      if((obj = WlzReadObj( fp, NULL ))){
        WlzDomain	domain;
        WlzValues	values;
        WlzObject	*newObj;
	switch( obj->type ){

	case WLZ_2D_DOMAINOBJ:
	  domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, 0, 0,
					obj->domain.i->line1,
					obj->domain.i->lastln,
					obj->domain.i->kol1,
					obj->domain.i->lastkl,
					NULL);
	  domain.p->domains[0] = WlzAssignDomain(obj->domain, NULL);
	  values.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY,
					   0, 0, WlzGetBackground(obj, NULL),
					   NULL, NULL);
	  values.vox->values[0] = WlzAssignValues(obj->values, NULL);
	  newObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values,
			       NULL, NULL, NULL);
	  WlzFreeObj(obj);
	  obj = newObj;
	  globals.origObjType = WLZ_2D_DOMAINOBJ;
	  break;

	case WLZ_3D_DOMAINOBJ:
	  globals.origObjType = WLZ_3D_DOMAINOBJ;
	  break;

	default:
	  HGU_XmUserError(globals.topl,
			  "Read Reference Object:\n"
			  "    The reference object must be a 2- or 3-D woolz\n"
			  "    grey-level image. Please select an alternate\n"
			  "    object",
			  XmDIALOG_FULL_APPLICATION_MODAL);
	  WlzFreeObj( obj );
	  /* set hour glass cursor */
	  HGU_XmUnsetHourGlassCursor(globals.topl);
	  return;

	}
	HGU_XmFileListAddFile(globals.fileList, initial_reference_file,
			      image_type);
	HGU_XmFileListWriteResourceFile(globals.fileList,
					globals.resourceFile);
	MAPaintLogData("ReferenceFile", initial_reference_file, 0, NULL);
	install_paint_reference_object( obj );

	/* set the globals reference file */
	globals.file = initial_reference_file;

	/* set the title of the top-level window */
	set_topl_title(globals.file);
      }
      else {
	/* if it fails to read, check the file name
	   or the file content for special options */
	if( strstr(initial_reference_file, "MAPaint") ){
	  /* standard MAPaint startup */
	  globals.app_name = "MAPaint";
	  /* set the title of the top-level window */
	  set_topl_title(globals.file);
	}
	else if( strstr(initial_reference_file, "SectionView") ){
	  /* restricted section view startup */
	  globals.app_name = "SectionView";
	  globals.sectViewFlg = 1;
	  /* set the title of the top-level window */
	  set_topl_title(globals.file);
	}
	else if( theilerString(initial_reference_file) ){
	  /* load in theiler stage anatomy etc. */
	  globals.app_name = "SectionView";
	  globals.sectViewFlg = 1;
	  set_theiler_stage_cb(topl, theilerString(initial_reference_file),
			       NULL);
	}
	else {
	  char	strBuf[33];
	  /* check the content */
	  rewind(fp);
	  fscanf(fp, "%32s", strBuf);
	  if( strstr(strBuf, "MAPaint") ){
	    /* standard MAPaint startup */
	    globals.app_name = "MAPaint";
	    /* set the title of the top-level window */
	    set_topl_title(globals.file);
	  }
	  else if( strstr(strBuf, "SectionView") ){
	    /* restricted section view startup */
	    globals.app_name = "SectionView";
	    globals.sectViewFlg = 1;
	    /* set the title of the top-level window */
	    set_topl_title(globals.file);
	  }
	  else if( theilerString(strBuf) ){
	    /* load in theiler stage anatomy etc. */
	    globals.app_name = "SectionView";
	    globals.sectViewFlg = 1;
	    set_theiler_stage_cb(topl,
				 theilerString(strBuf),
				 NULL);
	  }
	}

	/* set the globals reference file */
	globals.file = NULL;
      }
      (void) fclose( fp );

      HGU_XmUnsetHourGlassCursor(topl);
    }
  }
  else if( globals.theiler_stage ){
    globals.app_name = "MAPaint";
    set_theiler_stage_cb(topl, theilerString(globals.theiler_stage), NULL);
  }

  /* reset the colormap */
  if( globals.sectViewFlg == 1 ){
    init_paint_cmapstruct(globals.topl);
  }

  /* check for an initial domain file */
  if( initial_domain_file != NULL ){
    WlzObject 	*obj;

    /* open the domain object file and put it in as a 3D feedback option */
    if( (fp = fopen(initial_domain_file, "rb")) ){
      HGU_XmSetHourGlassCursor(topl);
      if((obj = WlzReadObj( fp, NULL ))){
	if( globals.fb_obj ){
	  WlzFreeObj(globals.fb_obj);
	}
	globals.fb_obj = WlzAssignObject(obj, NULL);
	setup_ref_display_list_cb(read_obj_dialog, NULL, NULL);
      }
      (void) fclose( fp );
      HGU_XmUnsetHourGlassCursor(topl);
    }
  }

  return;
}
Esempio n. 7
0
/*!
* \return	Transformed object.
* \ingroup	WlzTransform
* \brief	Transform an object using the given view-transform.
*		Typically this is for mapping section data back into
*		the 3D space of the reference image/reconstruction.
* \param	srcObj			Given source object.
* \param	viewStr			Given view transform.
* \param	dstErr			Destination error pointer, may be NULL.
*/
WlzObject *Wlz3DViewTransformObj(
    WlzObject		*srcObj,
    WlzThreeDViewStruct	*viewStr,
    WlzErrorNum		*dstErr)
{
    WlzErrorNum		errNum=WLZ_ERR_NONE;
    AlcErrno		alcErr = ALC_ER_NONE;
    WlzObject		*dstObj=NULL;
    int			area;
    int			i, k, p, xp, yp, line;
    int			plane1, lastpl, line1, lastln, kol1, lastkl;
    WlzIVertex3		*vertices;
    int			numVtxs, vtxIdx;
    WlzIntervalWSpace	iwsp;
    WlzGreyWSpace		gwsp;
    WlzDomain		domain, tmpDomain;
    WlzValues		values;
    int			numInts, itvlFlg;
    WlzInterval		*itvl;


    /* check the object */
    if( srcObj == NULL ) {
        errNum = WLZ_ERR_OBJECT_NULL;
    }
    else {
        switch( srcObj->type ) {

        case WLZ_2D_DOMAINOBJ:
            if( srcObj->domain.core == NULL ) {
                errNum = WLZ_ERR_DOMAIN_NULL;
            }
            area = WlzArea(srcObj, &errNum);
            if( area == 0 ) {
                dstObj = WlzMakeEmpty(&errNum);
            }
            break;

        case WLZ_2D_POLYGON: /* to be done at some time to 3D polyline */
        case WLZ_BOUNDLIST: /* convert to 3D polylines */
        case WLZ_TRANS_OBJ:
            errNum = WLZ_ERR_OBJECT_TYPE;
            break;

        default:
            errNum = WLZ_ERR_OBJECT_TYPE;
            break;
        }
    }

    /* create the voxel list */
    if( (errNum == WLZ_ERR_NONE) && (dstObj == NULL) ) {
        numVtxs = sizeof(WlzIVertex3) * (area+4);

        vertices = AlcMalloc(sizeof(WlzIVertex3) * (area+4));
        numVtxs = 0;
        if( vertices ) {
            errNum = WlzInitRasterScan(srcObj, &iwsp, WLZ_RASTERDIR_ILIC);
        }
        else {
            errNum = WLZ_ERR_MEM_ALLOC;
        }

        if( errNum == WLZ_ERR_NONE ) {
            while( (errNum = WlzNextInterval(&iwsp)) == WLZ_ERR_NONE ) {
                float x, y, z;

                if((iwsp.linpos < (int) viewStr->minvals.vtY) ||
                        (iwsp.linpos > (int) viewStr->maxvals.vtY)) {
                    continue;
                }
                yp = iwsp.linpos - (int) viewStr->minvals.vtY;
                for(k=iwsp.lftpos; k <= iwsp.rgtpos; k++) {
                    if((k < (int) viewStr->minvals.vtX) ||
                            (k > (int) viewStr->maxvals.vtX)) {
                        continue;
                    }
                    xp = k - (int) viewStr->minvals.vtX;
                    x = (float )(viewStr->xp_to_x[xp] + viewStr->yp_to_x[yp]);
                    y = (float )(viewStr->xp_to_y[xp] + viewStr->yp_to_y[yp]);
                    z = (float )(viewStr->xp_to_z[xp] + viewStr->yp_to_z[yp]);
                    vertices[numVtxs].vtX = WLZ_NINT(x);
                    vertices[numVtxs].vtY = WLZ_NINT(y);
                    vertices[numVtxs].vtZ = WLZ_NINT(z);
                    numVtxs++;
                }
            }

            if(errNum == WLZ_ERR_EOO) /* Reset error from end of object */
            {
                errNum = WLZ_ERR_NONE;
            }
        }
    }

    /* sort wrt planes, lines, kols */
    if( (errNum == WLZ_ERR_NONE) && (dstObj == NULL) ) {
        qsort((void *) vertices, (size_t) numVtxs, sizeof(WlzIVertex3),
              compareVtxVal);

        /* create planedomain */
        plane1 = vertices[0].vtZ;
        lastpl = vertices[numVtxs - 1].vtZ;
        line1 = vertices[0].vtY;
        lastln = line1;
        kol1 = vertices[0].vtX;
        lastkl = kol1;
        for(i=1; i < numVtxs; i++) {
            if( kol1 > vertices[i].vtX ) {
                kol1 = vertices[i].vtX;
            }
            if( lastkl < vertices[i].vtX ) {
                lastkl = vertices[i].vtX;
            }
            if( line1 > vertices[i].vtY ) {
                line1 = vertices[i].vtY;
            }
            if( lastln < vertices[i].vtY ) {
                lastln = vertices[i].vtY;
            }
        }
        if( (domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN,
                                           plane1, lastpl,
                                           line1, lastln,
                                           kol1, lastkl,
                                           &errNum)) == NULL ) {
            AlcFree((void *) vertices);
        }
    }

    /* for each plane count intervals and make domain */
    if( (errNum == WLZ_ERR_NONE) && (dstObj == NULL) ) {

        vtxIdx = 0;
        for(p=plane1; p <= lastpl; p++) {

            /* increment vertex index to current plane */
            while( vertices[vtxIdx].vtZ < p ) {
                vtxIdx++;
            }

            /* check for empty domain */
            if( vertices[vtxIdx].vtZ > p ) {
                domain.p->domains[p - plane1].i = NULL;
                continue;
            }

            /* estimate intervals - foreach pixel add one,
            foreach adjacent pixel on the same line subtract one */
            numInts = 1;
            kol1 = vertices[vtxIdx].vtX;
            lastkl = kol1;
            for(i=vtxIdx+1; i < numVtxs; i++) {
                if( vertices[i].vtZ > p ) {
                    break;
                }
                numInts++;
                if((vertices[i].vtY == vertices[i-1].vtY) &&
                        ((vertices[i].vtX == (vertices[i-1].vtX)) ||
                         (vertices[i].vtX == (vertices[i-1].vtX + 1))
                        )) {
                    numInts--;
                }
                if(kol1 > vertices[i].vtX) {
                    kol1 = vertices[i].vtX;
                }
                if(lastkl < vertices[i].vtX) {
                    lastkl = vertices[i].vtX;
                }
            }
            line1 = vertices[vtxIdx].vtY;
            lastln = vertices[i-1].vtY;

            /* make the domain and add the intervals pointer */
            tmpDomain.i = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_INTVL,
                                                line1, lastln,
                                                kol1, lastkl,
                                                &errNum);
            itvl = (WlzInterval *) AlcMalloc(sizeof(WlzInterval)*numInts);
            tmpDomain.i->freeptr = AlcFreeStackPush(tmpDomain.i->freeptr,
                                                    (void *) itvl,
                                                    &alcErr);
            if(alcErr != ALC_ER_NONE) {
                errNum = WLZ_ERR_MEM_ALLOC;
            }
            /* one more loop to add the intervals */
            itvl->ileft = vertices[vtxIdx].vtX - kol1;
            line = vertices[vtxIdx].vtY;
            itvlFlg = 1; /* interval started */
            numInts = 1;
            for(i=vtxIdx+1; i < numVtxs; i++) {

                /* new plane -> interval finished if started */
                if( vertices[i].vtZ > p ) {
                    if( itvlFlg ) {
                        itvl[numInts-1].iright = vertices[i-1].vtX - kol1;
                        WlzMakeInterval(line, tmpDomain.i, numInts, itvl);
                        itvl += numInts;
                        itvlFlg = 0; /* interval finished */
                        numInts = 0;
                    }
                    break;
                }

                /* check if new interval */
                if( !itvlFlg ) {
                    itvl->ileft = vertices[i].vtX - kol1;
                    line = vertices[i].vtY;
                    itvlFlg = 1;
                    numInts = 1;
                    continue; /* no further tests */
                }

                /* check for gap  - increment interval count */
                if((vertices[i].vtY == line) &&
                        ((vertices[i].vtX - vertices[i-1].vtX) > 1)) {
                    itvl[numInts-1].iright = vertices[i-1].vtX - kol1;
                    numInts++;
                    itvl[numInts-1].ileft = vertices[i].vtX - kol1;
                    itvlFlg = 1;
                }

                /* check for new-line */
                if( line < vertices[i].vtY ) {
                    itvl[numInts-1].iright = vertices[i-1].vtX - kol1;
                    WlzMakeInterval(line, tmpDomain.i, numInts, itvl);
                    itvl += numInts;
                    itvl->ileft = vertices[i].vtX - kol1;
                    line = vertices[i].vtY;
                    itvlFlg = 1;
                    numInts = 1;
                }

            }

            /* complete the last interval */
            if( itvlFlg ) {
                itvl[numInts-1].iright = vertices[i-1].vtX - kol1;
                WlzMakeInterval(line, tmpDomain.i, numInts, itvl);
                itvl += numInts;
            }

            /* add the domain to the planedomain */
            domain.p->domains[p - plane1] =
                WlzAssignDomain(tmpDomain, &errNum);
            (void) WlzIntervalCount(tmpDomain.i, 0);

        }

    }

    /* create the new object */
    if( (errNum == WLZ_ERR_NONE) && (dstObj == NULL) ) {
        values.core = NULL;
        dstObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values,
                             NULL, NULL, &errNum);
    }

    /* check for grey-level data */
    if((errNum == WLZ_ERR_NONE) && dstObj &&
            (dstObj->type != WLZ_EMPTY_OBJ) && srcObj->values.core ) {
        WlzPixelV	bckgrnd;
        WlzObject	*tmpObj;
        WlzValues	tmpValues;
        WlzDVertex3	vtx;
        WlzGreyValueWSpace	*gVWSp = NULL;
        WlzObjectType	valueTbType;

        /* explicit intialisation to satisfy strict ANSI on SGI */
        bckgrnd = WlzGetBackground(srcObj, &errNum);
        valueTbType = WlzGreyTableType(WLZ_GREY_TAB_RAGR,
                                       bckgrnd.type, NULL);

        /* make a voxel table */
        values.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY,
                                         plane1, lastpl, bckgrnd,
                                         NULL, &errNum);
        dstObj->values = WlzAssignValues(values, &errNum);

        /* set up grey-value random access to original
           and loop through planes setting values */
        gVWSp = WlzGreyValueMakeWSp(srcObj, NULL);
        for(p=plane1; p <= lastpl; p++) {

            /* check for empty domain */
            if( domain.p->domains[p-plane1].core == NULL ) {
                continue;
            }

            /* make a value table */
            tmpObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, domain.p->domains[p-plane1],
                                 values.vox->values[p-plane1], NULL, NULL, &errNum);
            tmpValues.v = WlzNewValueTb(tmpObj, valueTbType, bckgrnd, &errNum);
            values.vox->values[p-plane1] = WlzAssignValues(tmpValues, &errNum);
            tmpObj->values = WlzAssignValues(tmpValues, &errNum);

            /* transfer values */
            errNum = WlzInitGreyScan(tmpObj, &iwsp, &gwsp);
            while((errNum == WLZ_ERR_NONE) &&
                    ((errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE)) {

                for(i=0;  i<iwsp.colrmn; i++) {
                    vtx.vtX = iwsp.colpos + i;
                    vtx.vtY = iwsp.linpos;
                    vtx.vtZ = p;
                    Wlz3DSectionTransformVtx(&vtx, viewStr);
                    WlzGreyValueGet(gVWSp, 0.0,
                                    WLZ_NINT(vtx.vtY), WLZ_NINT(vtx.vtX));
                    switch( gwsp.pixeltype ) {
                    case WLZ_GREY_LONG:
                        *(gwsp.u_grintptr.lnp+i) = gVWSp->gVal[0].lnv;
                        break;
                    case WLZ_GREY_INT:
                        *(gwsp.u_grintptr.inp+i) = gVWSp->gVal[0].inv;
                        break;
                    case WLZ_GREY_SHORT:
                        *(gwsp.u_grintptr.shp+i) = gVWSp->gVal[0].shv;
                        break;
                    case WLZ_GREY_UBYTE:
                        *(gwsp.u_grintptr.ubp+i) = gVWSp->gVal[0].ubv;
                        break;
                    case WLZ_GREY_FLOAT:
                        *(gwsp.u_grintptr.flp+i) = gVWSp->gVal[0].flv;
                        break;
                    case WLZ_GREY_DOUBLE:
                        *(gwsp.u_grintptr.dbp+i) = gVWSp->gVal[0].dbv;
                        break;
                    case WLZ_GREY_RGBA:
                        *(gwsp.u_grintptr.rgbp+i) = gVWSp->gVal[0].rgbv;
                        break;
                    case WLZ_GREY_BIT: /* not sure what to do with these */
                    default:
                        break;
                    }
                }
            }
            if(errNum == WLZ_ERR_EOO) /* Reset error from end of object */
            {
                errNum = WLZ_ERR_NONE;
            }
            WlzFreeObj(tmpObj);
        }

        WlzGreyValueFreeWSp(gVWSp);
    }

    /* clean temp allocation */
    if( vertices ) {
        AlcFree((void *) vertices);
    }

    if( dstErr ) {
        *dstErr = errNum;
    }
    return dstObj;
}
Esempio n. 8
0
/*!
* \return	Rescaled object.
* \ingroup	WlzTransform
* \brief	Rescales the given 2D domain object using an integer scale.
* \param	obj			Given object.
* \param	scale			Integer scale factor.
* \param	expand			If zero use \f$\frac{1}{scale}\f$.
* \param	dstErr			Destination error pointer, may be NULL.
*/
static WlzObject *WlzIntRescaleObj2D(
  WlzObject	*obj,
  int		scale,
  int		expand,
  WlzErrorNum	*dstErr)
{
  WlzObject		*rtnObj=NULL;
  WlzDomain		domain;
  WlzValues		values;
  WlzInterval		*intvls;
  int			k1, kl, l1, ll, l, num_intvls;
  WlzErrorNum		errNum=WLZ_ERR_NONE;

  /* check expand or contract */
  if( expand )
  {
    k1 = obj->domain.i->kol1   * scale;
    kl = obj->domain.i->lastkl * scale + scale - 1;
    l1 = obj->domain.i->line1  * scale;
    ll = obj->domain.i->lastln * scale + scale - 1;
  }
  else {
    k1 = obj->domain.i->kol1   / scale;
    kl = obj->domain.i->lastkl / scale;
    l1 = obj->domain.i->line1  / scale;
    ll = obj->domain.i->lastln / scale;
  }

  /* create a new object */
  if((domain.i = WlzMakeIntervalDomain(obj->domain.i->type,
				       l1, ll, k1, kl, &errNum)) != NULL){
    values.core = NULL;
    rtnObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, domain, values, 
			 NULL, NULL, NULL);
  }

  /* fill in the intervals */
  if( errNum == WLZ_ERR_NONE){
    if( domain.i->type == WLZ_INTERVALDOMAIN_INTVL )
    {
      int intvline_offset, max_offset;
      WlzIntervalLine *intvline;

      num_intvls = WlzIntervalCount(obj->domain.i, NULL);
      num_intvls = expand ? num_intvls * scale : num_intvls;
      intvls = (WlzInterval *)AlcMalloc(sizeof(WlzInterval) * num_intvls);
      domain.i->freeptr = AlcFreeStackPush(domain.i->freeptr, (void *)intvls,
      					   NULL);
      max_offset = obj->domain.i->lastln - obj->domain.i->line1;

      for(l=l1; l <= ll; l++)
      {
	int		i;

	intvline_offset = (expand?l/scale:l*scale) - obj->domain.i->line1;
	intvline_offset = WLZ_MAX(intvline_offset, 0);
	intvline_offset = WLZ_MIN(intvline_offset, max_offset);
	intvline = obj->domain.i->intvlines + intvline_offset;

	for(i=0; i < intvline->nintvs; i++)
	{
	  intvls[i].ileft  = (intvline->intvs + i)->ileft;
	  intvls[i].iright = (intvline->intvs + i)->iright;
	  if( expand )
	  {
	    intvls[i].ileft  *= scale;
	    intvls[i].iright *= scale;
	    intvls[i].iright += scale - 1;
	  }
	  else
	  {
	    intvls[i].ileft  /= scale;
	    intvls[i].iright /= scale;
	  }
	}

	i = check_intvs(intvls, i);
	WlzMakeInterval(l, domain.i, i, intvls);
	intvls += i;
      }
      (void) WlzStandardIntervalDomain( domain.i );
    }
  }

  /* create the valuetable */
  if( (errNum == WLZ_ERR_NONE) && obj->values.core )
  {
    WlzIntervalWSpace	iwsp;
    WlzGreyWSpace	gwsp;
    WlzPixelV 		backgrnd;
    WlzGreyValueWSpace	*gVWSp = NULL;
    WlzGreyType		gtype;

    backgrnd = WlzGetBackground(obj, NULL);
    if((values.v = WlzNewValueTb(rtnObj, obj->values.v->type,
				 backgrnd, &errNum)) != NULL){

      rtnObj->values = WlzAssignValues(values, NULL);
      
      /* fill in the grey-values */
      errNum = WlzInitGreyScan(rtnObj, &iwsp, &gwsp);
      if(errNum == WLZ_ERR_NONE) {
	gVWSp = WlzGreyValueMakeWSp(obj, &errNum);
	if(errNum == WLZ_ERR_NONE) {
	  gtype = WlzGreyTableTypeToGreyType(obj->values.v->type, NULL);
	}
	while((errNum == WLZ_ERR_NONE) &&
	      (errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE)
	{
	  int k;
	  int lp = expand ? iwsp.linpos/scale : iwsp.linpos*scale;

	  for( k=0; k <= (iwsp.rgtpos - iwsp.lftpos); k++ )
	  {
	    int	kp = expand ? (k+iwsp.lftpos)/scale : (k+iwsp.lftpos)*scale;

	    WlzGreyValueGet(gVWSp, 0, (double) lp, (double) kp);

	    switch(gtype)
	    {
	    case WLZ_GREY_INT: 
	      gwsp.u_grintptr.inp[k] = (*(gVWSp->gVal)).inv;
	      break;
	    case WLZ_GREY_SHORT:
	      gwsp.u_grintptr.shp[k] = (*(gVWSp->gVal)).shv;
	      break;
	    case WLZ_GREY_UBYTE:
	      gwsp.u_grintptr.ubp[k] = (*(gVWSp->gVal)).ubv;
	      break;
	    case WLZ_GREY_FLOAT:
	      gwsp.u_grintptr.flp[k] = (*(gVWSp->gVal)).flv;
	      break;
	    case WLZ_GREY_DOUBLE:
	      gwsp.u_grintptr.dbp[k] = (*(gVWSp->gVal)).dbv;
	      break;
	    case WLZ_GREY_RGBA:
	      gwsp.u_grintptr.rgbp[k] = (*(gVWSp->gVal)).rgbv;
	      break;
	    default:
	      errNum = WLZ_ERR_GREY_TYPE;
	      break;
	    }
	  }
	}
	if( errNum == WLZ_ERR_EOO ){
	  errNum = WLZ_ERR_NONE;
	}
	WlzGreyValueFreeWSp(gVWSp);
	(void )WlzEndGreyScan(&iwsp, &gwsp);
      }
    }
  }

  if( dstErr ){
    *dstErr = errNum;
  }
  return rtnObj;
}
Esempio n. 9
0
static WlzObject *WlzGreyTemplate3d(
  WlzObject	*obj,
  WlzObject	*tmpl,
  WlzPixelV	tmplVal,
  WlzErrorNum	*dstErr)
{
  WlzObject	*rtnObj=NULL;
  WlzObject	*tmpObj = NULL, *obj1 = NULL, *obj2 = NULL;
  WlzDomain	domain, *domains;
  WlzValues	values, *valuess;
  WlzPlaneDomain	*pdom;
  int		p;
  WlzErrorNum	errNum=WLZ_ERR_NONE;

  /* check the object - it is non-NULL and 3D but the
     domain needs checking */
  if( obj->domain.p == NULL ){
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else {
    switch( obj->domain.p->type ){
    case WLZ_2D_DOMAINOBJ:
      /* check there is a valuetable */
      if( obj->values.core == NULL ){
	errNum = WLZ_ERR_VALUES_NULL;
      } else if( WlzGreyTableIsTiled(obj->values.core->type) ){
	errNum = WLZ_ERR_VALUES_TYPE;
      }
      break;

    default:
      errNum = WLZ_ERR_DOMAIN_TYPE;
      break;
    }
  }

  /* check the template and create the return object */
  if( errNum == WLZ_ERR_NONE ){
    if( tmpl == NULL ){
      errNum = WLZ_ERR_OBJECT_NULL;
    }
    else {
      values.core = NULL;
      switch( tmpl->type ){
      case WLZ_2D_DOMAINOBJ:
	pdom = obj->domain.p;
	if((domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN,
					  pdom->plane1, pdom->lastpl,
					  pdom->line1, pdom->lastpl,
					  pdom->kol1, pdom->lastkl,
					  &errNum)) != NULL){
	  domain.p->voxel_size[0] = pdom->voxel_size[0];
	  domain.p->voxel_size[1] = pdom->voxel_size[1];
	  domain.p->voxel_size[2] = pdom->voxel_size[2];
	  for(p=pdom->plane1; p <= pdom->lastpl; p++){
	    domain.p->domains[p - pdom->plane1] = WlzAssignDomain(tmpl->domain,
								  NULL);
	  }
	  rtnObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values,
			       NULL, NULL, &errNum);
	}
	break;

      case WLZ_2D_POLYGON:
	pdom = obj->domain.p;
	if((domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN,
					  pdom->plane1, pdom->lastpl,
					  pdom->line1, pdom->lastpl,
					  pdom->kol1, pdom->lastkl,
					  &errNum)) != NULL){
	  domain.p->voxel_size[0] = pdom->voxel_size[0];
	  domain.p->voxel_size[1] = pdom->voxel_size[1];
	  domain.p->voxel_size[2] = pdom->voxel_size[2];
	  obj1 = WlzPolyToObj(tmpl->domain.poly, WLZ_SIMPLE_FILL, &errNum);
	  for(p=pdom->plane1; p <= pdom->lastpl; p++){
	    domain.p->domains[p - pdom->plane1] = WlzAssignDomain(obj1->domain,
								  NULL);
	  }
	  WlzFreeObj(obj1);
	  rtnObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values,
			       NULL, NULL, &errNum);
	}
	break;

      case WLZ_BOUNDLIST:
	pdom = obj->domain.p;
	if((domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN,
					  pdom->plane1, pdom->lastpl,
					  pdom->line1, pdom->lastpl,
					  pdom->kol1, pdom->lastkl,
					  &errNum)) != NULL){
	  domain.p->voxel_size[0] = pdom->voxel_size[0];
	  domain.p->voxel_size[1] = pdom->voxel_size[1];
	  domain.p->voxel_size[2] = pdom->voxel_size[2];
	  obj1 = WlzBoundToObj(tmpl->domain.b, WLZ_SIMPLE_FILL, &errNum);
	  for(p=pdom->plane1; p <= pdom->lastpl; p++){
	    domain.p->domains[p - pdom->plane1] = WlzAssignDomain(obj1->domain,
								  NULL);
	  }
	  WlzFreeObj(obj1);
	  rtnObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values,
			       NULL, NULL, &errNum);
	}
	break;

      case WLZ_3D_DOMAINOBJ:
	if( tmpl->domain.p ){
	  switch( tmpl->domain.p->type ){
	  case WLZ_2D_DOMAINOBJ:
	    domain.p = tmpl->domain.p;
	    break;

	  case WLZ_PLANEDOMAIN_POLYGON:
	  case WLZ_PLANEDOMAIN_CONV_HULL:
	    pdom = tmpl->domain.p;
	    if((domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN,
					      pdom->plane1, pdom->lastpl,
					      pdom->line1, pdom->lastpl,
					      pdom->kol1, pdom->lastkl,
					      &errNum)) != NULL){
	      domain.p->voxel_size[0] = pdom->voxel_size[0];
	      domain.p->voxel_size[1] = pdom->voxel_size[1];
	      domain.p->voxel_size[2] = pdom->voxel_size[2];
	      for(p=pdom->plane1; p <= pdom->lastpl; p++){
		if( pdom->domains[p-pdom->plane1].core ){
		  obj1 = WlzPolyToObj(pdom->domains[p-pdom->plane1].poly,
				      WLZ_SIMPLE_FILL, &errNum);
		  domain.p->domains[p - pdom->plane1] =
		    WlzAssignDomain(obj1->domain, NULL);
		}
		WlzFreeObj(obj1);
	      }
	      values.core = NULL;
	      rtnObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values,
				   NULL, NULL, &errNum);
	    }
	    break;

	  case WLZ_PLANEDOMAIN_BOUNDLIST:
	    pdom = tmpl->domain.p;
	    if((domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN,
					      pdom->plane1, pdom->lastpl,
					      pdom->line1, pdom->lastpl,
					      pdom->kol1, pdom->lastkl,
					      &errNum)) != NULL){
	      domain.p->voxel_size[0] = pdom->voxel_size[0];
	      domain.p->voxel_size[1] = pdom->voxel_size[1];
	      domain.p->voxel_size[2] = pdom->voxel_size[2];
	      for(p=pdom->plane1; p <= pdom->lastpl; p++){
		if( pdom->domains[p-pdom->plane1].core ){
		  obj1 = WlzBoundToObj(pdom->domains[p-pdom->plane1].b,
				      WLZ_SIMPLE_FILL, &errNum);
		  domain.p->domains[p - pdom->plane1] =
		    WlzAssignDomain(obj1->domain, NULL);
		}
		WlzFreeObj(obj1);
	      }
	      values.core = NULL;
	      rtnObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values,
				   NULL, NULL, &errNum);
	    }
	    break;

	  default:
	    errNum = WLZ_ERR_DOMAIN_TYPE;
	    break;
	  }
	  if( errNum == WLZ_ERR_NONE ){
	    rtnObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values,
				 NULL, NULL, &errNum);
	  }
	}
	else {
	  errNum = WLZ_ERR_DOMAIN_NULL;
	}
	break;

      case WLZ_EMPTY_OBJ:
	return WlzMakeEmpty(dstErr);

      default:
	errNum = WLZ_ERR_OBJECT_TYPE;
	break;
      }
    }
  }

  /* now we have a 3D obj and 3D template so run through the template
     and map values as required, note we must check that all the valuetables
     have the same type ie switch to obj type if necessary */
  if( errNum == WLZ_ERR_NONE ){
    WlzDomain	*objDoms;
    WlzValues	*objVals;
    WlzGreyType	gtype=WLZ_GREY_UBYTE;

    /* attach a voxel table with empty values list */
    values.vox = WlzMakeVoxelValueTb(obj->values.vox->type,
				     rtnObj->domain.p->plane1,
				     rtnObj->domain.p->lastpl,
				     obj->values.vox->bckgrnd,
				     NULL, NULL);
    rtnObj->values = WlzAssignValues(values, NULL);

    /* set some local variables */
    pdom = rtnObj->domain.p;
    domains = rtnObj->domain.p->domains;
    valuess = rtnObj->values.vox->values;
    objDoms = obj->domain.p->domains;
    objVals = obj->values.vox->values;

    /* calculate the new valuetables */
    for(p=pdom->plane1; p <= pdom->lastpl; p++, domains++, valuess++){
      if(((*domains).core)){
	if((p >= obj->domain.p->plane1) &&
	   (p <= obj->domain.p->lastpl) &&
	   (objDoms[p - obj->domain.p->plane1].core) ){
	  tmpObj = WlzMakeMain(WLZ_2D_DOMAINOBJ,
				objDoms[p - obj->domain.p->plane1],
				objVals[p - obj->domain.p->plane1],
				NULL, NULL, NULL);
	  gtype = WlzGreyTableTypeToGreyType(tmpObj->values.core->type, NULL);
	}
	else {
	  tmpObj = WlzMakeEmpty(NULL);
	}
	tmpObj = WlzAssignObject(tmpObj, NULL);
	values.core = NULL;
	obj1 = WlzAssignObject(
	  WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, values,
		      NULL, NULL, NULL), NULL);
	if((obj2 = WlzGreyTemplate(tmpObj, obj1, tmplVal, &errNum)) != NULL){
	  *valuess = WlzAssignValues(obj2->values, NULL);
	  WlzFreeObj(obj2);
	}
	WlzFreeObj(obj1);
	WlzFreeObj(tmpObj);
      }
    }

    /* now check all valuetables have the same grey type */
    domains = rtnObj->domain.p->domains;
    valuess = rtnObj->values.vox->values;
    for(p=pdom->plane1; p <= pdom->lastpl; p++, domains++, valuess++){
      if((*domains).core &&
	 (WlzGreyTableTypeToGreyType((*valuess).core->type, NULL) != gtype)){
	obj1 = WlzAssignObject(
	  WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, *valuess,
		      NULL, NULL, NULL), NULL);
	if((obj2 = WlzConvertPix(obj1, gtype, &errNum)) != NULL){
	  /* substitute the valuetable in the voxel table array */
	  WlzFreeValues(*valuess);
	  *valuess = WlzAssignValues(obj2->values, NULL);
	  WlzFreeObj(obj2);
	}
	WlzFreeObj(obj1);
      }
    }
  }

  if( dstErr ){
    *dstErr = errNum;
  }
  return rtnObj;
}
Esempio n. 10
0
/*! 
* \ingroup      WlzBinaryOps
* \brief        Calculate the set union of an array of domain objects.
 Domians only unless uvt non-zero in which case make an average grey
 table. Note background values are used in the averaging process. All
 objects must be domain objects of the same type (2D or 3D) unless
 WLZ_EMPTY_OBJ, NULL input objects are an error.

 This function may modify the order of the objects in the array it is
 passed if the array contains empty objects.
*
* \return       Union of the array of object.
* \param    n	number of input objects
* \param    objs	input object array
* \param    uvt	grey-table copy flag, copy if non-zero.
* \param    dstErr	error return.
* \par      Source:
*                WlzUnionN.c
*/
WlzObject *WlzUnionN(
  int		n,
  WlzObject 	**objs,
  int 		uvt,
  WlzErrorNum	*dstErr)
{
  WlzObject		*obj=NULL;
  WlzDomain		domain;
  WlzValues		values;
  WlzIntervalDomain	*idom;
  WlzInterval		*itvl, *jtvl;
  WlzIntervalWSpace	*iwsp;
  WlzIntervalWSpace	*biwsp, *tiwsp, niwsp;
  WlzGreyWSpace		*gwsp, ngwsp;
  WlzObjectType		type;
  int 			i, j, k, l;
  int			inttot, numactive, change, lwas, nints, noverlap;
  WlzPixelV		backg;
  int			line1, lastln;
  int			kol1,lastkl;
  WlzGreyV		gv;
  WlzGreyP		greyptr;
  int			**locbuff;
  int			*locbuffs;
  int			span;
  WlzErrorNum		errNum=WLZ_ERR_NONE;

  /* preliminary stuff - count of non-NULL objects, note WLZ_EMPTY_OBJs
     are ignored but NULL objects are an error */
  if( n < 1 ){
    errNum = WLZ_ERR_PARAM_DATA;
  }
  else {
    for (i=0; i<n ; i++ ){
      if ( objs[i] == NULL ){
	errNum = WLZ_ERR_OBJECT_NULL;
	break;
      }
      if( objs[i]->type == WLZ_EMPTY_OBJ ){
	obj = objs[i];
	for ( j=i; j<n-1 ; j++ ){
	  objs[j] = objs[j+1];
	}
	objs[n-1] = obj;
	n--;
	i--;
      }
    }
  }
	
  /* n has been checked therefore no objects implies all empty */
  if( (errNum == WLZ_ERR_NONE) && (n < 1) ){
    return WlzMakeEmpty(dstErr);
  }

  /* now check they are all of the same type */
  if( errNum == WLZ_ERR_NONE ){
    for(i=1; i < n; i++){
      if( objs[i]->type != objs[0]->type ){
	errNum = WLZ_ERR_OBJECT_TYPE;
	break;
      }
    }
  }

  /* now test the type note empty objects have been discarded */
  if( errNum == WLZ_ERR_NONE ){
    switch( objs[0]->type ){

    case WLZ_2D_DOMAINOBJ:
      break;

    case WLZ_3D_DOMAINOBJ:
      return WlzUnion3d(n, objs, uvt, dstErr);

    case WLZ_TRANS_OBJ:
    default:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;
    }
  }

  /* now discard empty objects */
  if( errNum == WLZ_ERR_NONE ){
    for (i=0; i<n ; i++ ){
      if( WlzIsEmpty(objs[i], NULL) ){
	obj = objs[i];
	for ( j=i; j<n-1 ; j++ ){
	  objs[j] = objs[j+1];
	}
	objs[n-1] = obj;
	n--;
	i--;
      }
    }
  }
  obj = NULL;

  /* recheck number of objects */
  if( (errNum == WLZ_ERR_NONE) && (n < 1) ){
    return WlzMakeEmpty(dstErr);
  }
  if( (errNum == WLZ_ERR_NONE) && (n == 1) ){
    return WlzMakeMain(objs[0]->type, objs[0]->domain,
		       objs[0]->values, NULL, NULL, dstErr);
  }

  /* check if grey-value merge is possible */
  if( errNum == WLZ_ERR_NONE ){
    for (i=0; i<n ; i++ ){
      if( objs[i]->values.core == NULL ){
	uvt = 0;
	break;
      }
    }
  }

  /*
   * find the line and column bounds of the union.
   */
  if( errNum == WLZ_ERR_NONE ){
    line1 = objs[0]->domain.i->line1;
    lastln = objs[0]->domain.i->lastln;
    kol1 = objs[0]->domain.i->kol1;
    lastkl = objs[0]->domain.i->lastkl;
    for (i=1; i<n; i++) {
      idom = objs[i]->domain.i;
      if (line1 > idom->line1)
	line1 = idom->line1;
      if (lastln < idom->lastln)
	lastln = idom->lastln;
      if (kol1 > idom->kol1)
	kol1 = idom->kol1;
      if (lastkl < idom->lastkl)
	lastkl = idom->lastkl;
    }
    span = lastkl - kol1 +1 ;
    if( (locbuff = (int **) AlcMalloc((n+1)*sizeof(int *))) == NULL ){
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }

  /* space must be allocated for the largest variety of grey-value */
  if( errNum == WLZ_ERR_NONE ){
    if( (locbuffs = (int *) AlcMalloc(sizeof(double)*span*(n+1))) == NULL ){
      AlcFree((void *) locbuff);
      errNum = WLZ_ERR_MEM_ALLOC;
    }
    else {
      for(i=0; i <= n; i++){
	locbuff[i] = locbuffs + i*span;
      }
    }
  }
  /*
   * count the individual intervals so that sufficient space
   * for the union may be allocated.
   */
  if( errNum == WLZ_ERR_NONE ){
    inttot=0;
    for(i=0; i < n; i++){
      inttot += WlzIntervalCount(objs[i]->domain.i, &errNum);
    }
  }

  /*
   * set up domain, value table structures, and object.
   */
  if( errNum == WLZ_ERR_NONE ){
    if( (idom = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_INTVL,
				      line1,lastln,kol1,lastkl,
				      &errNum)) == NULL ){
      AlcFree((void *) locbuffs);
      AlcFree((void *) locbuff);
    }
    else if( (itvl = (WlzInterval *)
	      AlcMalloc(inttot * sizeof(WlzInterval))) == NULL){
      AlcFree((void *) locbuffs);
      AlcFree((void *) locbuff);
      WlzFreeIntervalDomain(idom);
      errNum = WLZ_ERR_MEM_ALLOC;
    }
    else {
      idom->freeptr = AlcFreeStackPush(idom->freeptr, (void *)itvl, NULL);
      lwas = line1;
      jtvl = itvl;
      nints = 0;
      domain.i = idom;
      values.v = NULL;
      if( (obj = WlzMakeMain(WLZ_2D_DOMAINOBJ, domain, values,
			     NULL, NULL, &errNum)) == NULL ){
	WlzFreeIntervalDomain( idom );
	AlcFree((void *) locbuffs);
	AlcFree((void *) locbuff);
	return(NULL);
      }
    }
  }    

  /*
   * allocate space for workspaces
   */
  if( errNum == WLZ_ERR_NONE ){
    if( (iwsp = (WlzIntervalWSpace *)
        AlcMalloc (n * sizeof (WlzIntervalWSpace))) == NULL ){
      WlzFreeObj( obj );
      AlcFree((void *) locbuffs);
      AlcFree((void *) locbuff);
      errNum = WLZ_ERR_MEM_ALLOC;
      obj = NULL;
    }
    else {
      biwsp = iwsp;
      tiwsp = iwsp + n;
    }
  }

  /*
   * Construct the union object's table of intervals.
   * Initialise scanning on each object/workspace combination.
   * Scan synchronously, setting up the union of adjacent and
   * overlapping intervals.  Needs a clear head !!
   */
  if( errNum == WLZ_ERR_NONE ){
    for (i=0; i<n; i++) {
      WlzInitRasterScan(objs[i], iwsp, WLZ_RASTERDIR_ILIC);
      WlzNextInterval(iwsp++);
    }
    numactive = n;

    /*
     * find next line and left hand end of next interval of union
     */
    while (numactive > 0) {
      /*
       * find first remaining active object
       */
      iwsp = biwsp;
      while( iwsp->linrmn < 0 ){
	iwsp++;
      }
      /*
       * find minimum line number of remaining active intervals
       */
      l = iwsp->linpos;
      kol1 = iwsp->lftpos;
      lastkl = iwsp->rgtpos;
      for (iwsp++; iwsp<tiwsp; iwsp++)
	if (iwsp->linrmn >= 0 && iwsp->linpos < l) {
	  l = iwsp->linpos;
	  kol1 = iwsp->lftpos;
	  lastkl = iwsp->rgtpos;
	}
      /*
       * find left-most interval in this line
       */
      for (iwsp=biwsp; iwsp<tiwsp; iwsp++)
	if (iwsp->linrmn >= 0 && iwsp->linpos == l && iwsp->lftpos < kol1) {
	  kol1 = iwsp->lftpos;
	  lastkl = iwsp->rgtpos;
	}
      /*
       * construct maximal interval with current left end-point
       */
      do {
	change = 0;
	for (iwsp=biwsp; iwsp<tiwsp; iwsp++) {
	  while( iwsp->linrmn >= 0 && iwsp->linpos == l
		&& iwsp->lftpos <= lastkl+1 ){
	    if (iwsp->rgtpos > lastkl) {
	      lastkl = iwsp->rgtpos;
	      change = 1;
	    }
	    if (WlzNextInterval(iwsp) != WLZ_ERR_NONE) {
	      numactive--;
	    }
	  }
	}
      } while (change == 1);
      itvl->ileft = kol1 - idom->kol1;
      itvl->iright = lastkl - idom->kol1;
      if (l == lwas)
	nints++;
      else {
	(void) WlzMakeInterval(lwas,idom,nints,jtvl);
	for (j = lwas+1; j<l; j++) {
	  (void) WlzMakeInterval(j,idom,0,NULL);
	}
	lwas = l;
	nints = 1;
	jtvl = itvl;
      }
      itvl++;
    }
    (void) WlzMakeInterval(lwas,idom,nints,jtvl);
    for (j = lwas+1; j<=lastln; j++) {
      (void) WlzMakeInterval(j,idom,0,NULL);
    }
  }

  /* now deal with the grey-values if required */
  if( (errNum == WLZ_ERR_NONE) && (uvt != 0) ){
    WlzGreyType	grey_type;

    if( (gwsp = (WlzGreyWSpace *)
	 AlcMalloc (n * sizeof (WlzGreyWSpace))) == NULL){
      WlzFreeObj( obj );
      AlcFree((void *) locbuffs);
      AlcFree((void *) locbuff);
      AlcFree((void *) biwsp);
      errNum = WLZ_ERR_MEM_ALLOC;
      obj = NULL;
    }
    
    /* construct an empty "ragged-rectangle" greytable
       with appropriate grey-type */
    if( errNum == WLZ_ERR_NONE ){
      backg = WlzGetBackground(objs[0], NULL);
      grey_type = WlzGreyTableTypeToGreyType(objs[0]->values.core->type,
					     NULL);
      type = WlzGreyTableType(WLZ_GREY_TAB_RAGR, grey_type, NULL);
      if( (values.v = WlzNewValueTb(obj, type, backg, &errNum)) == NULL ){
	WlzFreeObj( obj );
	AlcFree((void *) locbuffs);
	AlcFree((void *) locbuff);
	AlcFree((void *) biwsp);
	obj = NULL;
      }
      else {
	obj->values = WlzAssignValues(values, NULL);
      }
    }

    /* fill the grey table.  Where more than one input objects
       overlap, take mean of grey values. */
    if( errNum == WLZ_ERR_NONE ){
      WlzInitGreyScan(obj, &niwsp, &ngwsp);
      iwsp = biwsp;
      for (i=0; i<n; i++) {
	WlzInitGreyScan(objs[i], iwsp, &gwsp[i]);
	WlzNextGreyInterval(iwsp++);
	if( gwsp[i].pixeltype != grey_type ){
	  AlcFree((void *) gwsp);
	  AlcFree((void *) locbuffs);
	  AlcFree((void *) locbuff);
	  AlcFree((void *) biwsp);
	  WlzFreeObj( obj );
	  obj = NULL;
	  errNum = WLZ_ERR_GREY_TYPE;
	}      
      }
    }

    if( errNum == WLZ_ERR_NONE ){
      while (WlzNextGreyInterval(&niwsp) == WLZ_ERR_NONE) {
	l = niwsp.linpos;
	greyptr = ngwsp.u_grintptr;
	switch( ngwsp.pixeltype ){

	case WLZ_GREY_INT:
	  for (k = niwsp.lftpos; k <= niwsp.rgtpos; k++) {
	    noverlap = 0;
	    gv.inv = 0;
	    for (iwsp=biwsp,i=0; iwsp<tiwsp; iwsp++,i++) {
	      while (iwsp->linrmn >= 0
		     && (iwsp->linpos < l
			 || (iwsp->linpos == l && iwsp->rgtpos < k))){
		WlzNextGreyInterval(iwsp);
	      }
	      if (iwsp->linrmn >= 0 && iwsp->linpos == l &&
		  iwsp->lftpos <= k) {
		noverlap++;
		gv.inv += *(gwsp[i].u_grintptr.inp + k - iwsp->lftpos);
	      }
	    }
	    *greyptr.inp = gv.inv / noverlap;
	    greyptr.inp++;
	  }
	  break;

	case WLZ_GREY_SHORT:
	  for (k = niwsp.lftpos; k <= niwsp.rgtpos; k++) {
	    noverlap = 0;
	    gv.shv = 0;
	    for (iwsp=biwsp,i=0; iwsp<tiwsp; iwsp++,i++) {
	      while (iwsp->linrmn >= 0
		     && (iwsp->linpos < l
			 || (iwsp->linpos == l && iwsp->rgtpos < k))){
		WlzNextGreyInterval(iwsp);
	      }
	      if (iwsp->linrmn >= 0 && iwsp->linpos == l &&
		  iwsp->lftpos <= k) {
		noverlap++;
		gv.shv += *(gwsp[i].u_grintptr.shp + k - iwsp->lftpos);
	      }
	    }
	    *greyptr.shp = (short )(gv.shv / noverlap);
	    greyptr.shp++;
	  }
	  break;

	case WLZ_GREY_UBYTE:
	  for (k = niwsp.lftpos; k <= niwsp.rgtpos; k++) {
	    noverlap = 0;
	    gv.inv = 0;
	    for (iwsp=biwsp,i=0; iwsp<tiwsp; iwsp++,i++) {
	      while (iwsp->linrmn >= 0
		     && (iwsp->linpos < l
			 || (iwsp->linpos == l && iwsp->rgtpos < k))){
		WlzNextGreyInterval(iwsp);
	      }
	      if (iwsp->linrmn >= 0 && iwsp->linpos == l &&
		  iwsp->lftpos <= k) {
		noverlap++;
		gv.inv += *(gwsp[i].u_grintptr.ubp + k - iwsp->lftpos);
	      }
	    }
	    *greyptr.ubp = (WlzUByte )(gv.inv / noverlap);
 	    greyptr.ubp++;
	  }
	  break;

	case WLZ_GREY_FLOAT:
	  for (k = niwsp.lftpos; k <= niwsp.rgtpos; k++) {
	    noverlap = 0;
	    gv.flv = 0;
	    for (iwsp=biwsp,i=0; iwsp<tiwsp; iwsp++,i++) {
	      while (iwsp->linrmn >= 0
		     && (iwsp->linpos < l
			 || (iwsp->linpos == l && iwsp->rgtpos < k))){
		WlzNextGreyInterval(iwsp);
	      }
	      if (iwsp->linrmn >= 0 && iwsp->linpos == l &&
		  iwsp->lftpos <= k) {
		noverlap++;
		gv.flv += *(gwsp[i].u_grintptr.flp + k - iwsp->lftpos);
	      }
	    }
	    *greyptr.flp = gv.flv / noverlap;
	    greyptr.flp++;
	  }
	  break;

	case WLZ_GREY_DOUBLE:
	  for (k = niwsp.lftpos; k <= niwsp.rgtpos; k++) {
	    noverlap = 0;
	    gv.dbv = 0;
	    for (iwsp=biwsp,i=0; iwsp<tiwsp; iwsp++,i++) {
	      while (iwsp->linrmn >= 0
		     && (iwsp->linpos < l
			 || (iwsp->linpos == l && iwsp->rgtpos < k))){
		WlzNextGreyInterval(iwsp);
	      }
	      if (iwsp->linrmn >= 0 && iwsp->linpos == l &&
		  iwsp->lftpos <= k) {
		noverlap++;
		gv.dbv += *(gwsp[i].u_grintptr.dbp + k - iwsp->lftpos);
	      }
	    }
	    *greyptr.dbp = gv.dbv / noverlap;
	    greyptr.dbp++;
	  }
	  break;
	case WLZ_GREY_RGBA: /* RGBA to be done - do properly RAB */
	  for (k = niwsp.lftpos; k <= niwsp.rgtpos; k++) {
	    noverlap = 0;
	    gv.rgbv = 0;
	    for (iwsp=biwsp,i=0; iwsp<tiwsp; iwsp++,i++) {
	      while (iwsp->linrmn >= 0
		     && (iwsp->linpos < l
			 || (iwsp->linpos == l && iwsp->rgtpos < k))){
		WlzNextGreyInterval(iwsp);
	      }
	      if (iwsp->linrmn >= 0 && iwsp->linpos == l &&
		  iwsp->lftpos <= k) {
		noverlap++;
		gv.rgbv += *(gwsp[i].u_grintptr.rgbp + k - iwsp->lftpos);
	      }
	    }
	    *greyptr.rgbp = gv.rgbv / noverlap;
	    greyptr.rgbp++;
	  }
	  break;

	default:
	  break;

	}
      }
    }
    AlcFree((void *) gwsp);
  }

  if( errNum == WLZ_ERR_NONE ){
    AlcFree( (void *) biwsp);
    AlcFree( (void *)locbuff );
    AlcFree( (void *)locbuffs );
  }

  if( dstErr ){
    *dstErr = errNum;
  }
  return( obj );
}
Esempio n. 11
0
/*!
* \return	New 3D domain object.
* \ingroup	WlzArithmetic
* \brief	Computes a new 3D object which shares the domain of the given
*		object, but which has grey values that are the result of
*		applying the given function to the grey values of the
*		given object.
* \param	sObj			Given source domain object with values.
* \param	fn			Scalar function to be applied.
* \param	dstErr			Destination error pointer, may be NULL.
*/
static WlzObject *WlzScalarFn3D(WlzObject *sObj, WlzFnType fn,
			        WlzErrorNum *dstErr)
{
  int		idx,
  		off;
  WlzPixelV	sBgd,
  		dBgd;
  WlzValues	dVal;
  WlzObject     *sObj2D,
		*dObj2D,
  		*dObj = NULL;
  WlzErrorNum   errNum = WLZ_ERR_NONE;

  if(errNum == WLZ_ERR_NONE)
  {
    sBgd = WlzGetBackground(sObj, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    dBgd = WlzScalarFnPixel(sBgd, fn, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    dVal.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY,
    				   sObj->domain.p->plane1,
				   sObj->domain.p->lastpl,
				   dBgd, NULL, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    for(idx = sObj->domain.p->plane1; idx <= sObj->domain.p->lastpl; ++idx)
    {
      off = idx - sObj->domain.p->plane1;
      dObj2D = NULL;
      sObj2D = WlzMakeMain(WLZ_2D_DOMAINOBJ,
      		           *(sObj->domain.p->domains + off),
			   *(sObj->values.vox->values + off),
			   NULL, NULL, &errNum);
      if(errNum == WLZ_ERR_NONE)
      {
        dObj2D = WlzScalarFn2D(sObj2D, fn, &errNum);
      }
      WlzFreeObj(sObj2D);
      if(errNum == WLZ_ERR_NONE)
      {
        *(dVal.vox->values + off) = WlzAssignValues(dObj2D->values, NULL);
      }
      WlzFreeObj(dObj2D);
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    dObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, sObj->domain, dVal,
    		       NULL, NULL, &errNum);
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(dObj);
}
Esempio n. 12
0
int             main(int argc, char *argv[])
{
  int		option,
		nReg = 0,
		tNReg = 0,
  		ok = 1,
		usage = 0,
		verbose = 0,
		threshSet = 0,
		centreSet = 0;
  double	minArea = 2;
  char		*inExt,
		*dbgExt,
		*inDir,
		*dbgDir,
		*inFile,
		*dbgFile,
  		*inPath = NULL,
		*dbgPath = NULL,
		*outFile = NULL;
  WlzRadDistVal distSort = WLZ_RADDISTVAL_AREA;
  WlzRadDistRec	*distData = NULL;
  WlzPixelV	thrVal;
  WlzDVertex2	centre;
  WlzCompThreshType thrMtd = WLZ_COMPTHRESH_OTSU;
  WlzThresholdType thrMod = WLZ_THRESH_HIGH;
  WlzEffFormat	inFmt = WLZEFF_FORMAT_NONE,
  		dbgFmt = WLZEFF_FORMAT_NONE;
  WlzObject	*inObj = NULL,
		*disObj = NULL,
  		*segObj = NULL;
  WlzGreyValueWSpace *disGVWSp = NULL;
  WlzObject	**regObjs = NULL;
  FILE		*fP = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  const int	maxObj = 1000000;
  char		pathBuf[FILENAME_MAX];
  const double	eps = 1.0e-06;
  const char	*errMsg;
  static char	optList[] = "hvAGDHELR:c:d:n:o:t:",
		defFile[] = "-";

  thrVal.type = WLZ_GREY_DOUBLE;
  thrVal.v.dbv = 0.0;
  outFile = defFile;
  while((usage == 0) && ok &&
        ((option = getopt(argc, argv, optList)) != -1))
  {
    switch(option)
    {
      case 'A':
        distSort = WLZ_RADDISTVAL_AREA;
	break;
      case 'D':
        distSort = WLZ_RADDISTVAL_DIST;
	break;
      case 'G':
        distSort = WLZ_RADDISTVAL_ANGLE;
	break;
      case 'H':
        thrMod = WLZ_THRESH_HIGH;
	break;
      case 'E':
        thrMod = WLZ_THRESH_EQUAL;
	break;
      case 'L':
        thrMod = WLZ_THRESH_LOW;
	break;
      case 'R':
        distSort = WLZ_RADDISTVAL_RADIUS;
	break;
      case 'h':
        usage = 1;
	break;
      case 'v':
        verbose = 1;
	break;
      case 'c':
	centreSet = 1;
        if(sscanf(optarg, "%lg,%lg", &(centre.vtX), &(centre.vtY)) != 2)
	{
	  usage = 1;
	}
        break;
      case 'd':
        dbgPath = optarg;
	break;
      case 'o':
        outFile = optarg;
	break;
      case 'n':
        if(sscanf(optarg, "%lg", &minArea) != 1)
	{
	  usage = 1;
	}
	break;
      case 't':
	threshSet = 1;
        if(sscanf(optarg, "%lg", &(thrVal.v.dbv)) != 1)
	{
	  usage = 1;
	}
	break;
      default:
        usage = 1;
	break;
    }
  }
  ok = !usage;
  if(ok)
  {
    if((optind + 1) != argc)
    {
      usage = 1;
      ok = 0;
    }
    else
    {
      inPath = *(argv + optind);
    }
  }
  if(ok && verbose)
  {
    (void )fprintf(stderr, "inPath = %s\n", inPath);
  }
  /* Parse input file path into path + name + ext. */
  if(ok)
  {
    ok = (usage = WlzRadDistParsePath(inPath, &inDir, &inFile, &inExt,
                                      &inFmt)) == 0;
  }
  if(ok && verbose)
  {
    (void )fprintf(stderr, "inDir = %s\n", inDir);
    (void )fprintf(stderr, "inFile = %s\n", inFile);
    (void )fprintf(stderr, "inExt = %s\n", (inExt)? inExt: "(null)");
    (void )fprintf(stderr, "inFmt = %s\n",
    		   WlzEffStringFromFormat(inFmt, NULL));
  }
  /* Read image. */
  if(ok)
  {
    errNum = WLZ_ERR_READ_EOF;
    if(inExt)
    {
      (void )sprintf(pathBuf, "%s/%s.%s", inDir, inFile, inExt);
    }
    else
    {
      (void )sprintf(pathBuf, "%s/%s", inDir, inFile);
    }
    if(((inObj = WlzAssignObject(WlzEffReadObj(NULL, pathBuf, inFmt,
    					       0, 0, 0,
					       &errNum), NULL)) == NULL) ||
       (inObj->type != WLZ_2D_DOMAINOBJ))
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
      		     "%s: Failed to read 2D image object from file %s (%s)\n",
		     *argv, pathBuf, errMsg);
    }
  }
  if(ok && verbose)
  {
    (void )fprintf(stderr, "read input image ok.\n");
  }
  /* Convert to grey if needed, normalise 0 - 255 if needed and compute
   * threshold value unless already known. */
  if(ok)
  {
    if(WlzGreyTypeFromObj(inObj, NULL) == WLZ_GREY_RGBA)
    {
      WlzObject *ppObj;

      ppObj = WlzAssignObject(
	      WlzRGBAToModulus(inObj, &errNum), NULL);
      if(errNum == WLZ_ERR_NONE)
      {
	(void )WlzFreeObj(inObj);
	inObj = ppObj;
      }
    }
    if(threshSet == 0)
    {
      WlzObject *hObj = NULL;

      errNum = WlzGreyNormalise(inObj, 1);
      if(errNum == WLZ_ERR_NONE)
      {
        hObj = WlzHistogramObj(inObj, 256, 0.0, 1.0, &errNum);
      }
      if(errNum == WLZ_ERR_NONE)
      {
	threshSet = 1;
        errNum = WlzCompThreshold(&thrVal.v.dbv, hObj, thrMtd, 0);
      }
      (void )WlzFreeObj(hObj);
    }
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr, "%s: failed to normalise object (%s)\n",
		     *argv, errMsg);
    }
  }
  /* Segment the object. */
  if(ok)
  {
    if(inObj->values.core == NULL)
    {
      segObj = WlzAssignObject(inObj, NULL);
    }
    else
    {
      segObj = WlzAssignObject(
               WlzThreshold(inObj, thrVal, thrMod, &errNum), NULL);
      if(errNum != WLZ_ERR_NONE)
      {
	ok = 0;
	(void )WlzStringFromErrorNum(errNum, &errMsg);
	(void )fprintf(stderr, "%s: failed to segment image (%s)\n",
		       *argv, errMsg);
      }
    }
  }
  /* Compute object with the same domain as the input object but in which
   * the values are the minimum distance from an edge. */
  if(ok)
  {
    WlzObject	*bObj = NULL;

    bObj = WlzBoundaryDomain(inObj, &errNum);
    if(errNum == WLZ_ERR_NONE)
    {
      disObj = WlzAssignObject(       
               WlzDistanceTransform(inObj, bObj, WLZ_OCTAGONAL_DISTANCE,
	       			    0.0, 0.0, &errNum), NULL);
    }
    if(errNum == WLZ_ERR_NONE)
    {
      disGVWSp = WlzGreyValueMakeWSp(disObj, &errNum);
    }
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr, "%s: failed to compute distance object (%s)\n",
		     *argv, errMsg);
    }
    (void )WlzFreeObj(bObj);
  }
  /* Output the debug image if required. */
  if(ok && dbgPath)
  {
    WlzObject	*dbgObj;

    dbgObj = WlzAssignObject(WlzCopyObject(inObj, &errNum), NULL);
    if(errNum == WLZ_ERR_NONE)
    {
      WlzPixelV	iMin,
		iMax,
		oMin,
		oMax;

      if(dbgObj->values.core == NULL)
      {
        WlzValues tmpVal;

	oMax.type = WLZ_GREY_UBYTE;
	oMax.v.ubv = 255;
	tmpVal.v = WlzNewValueTb(dbgObj,
				 WlzGreyTableType(WLZ_GREY_TAB_RAGR,
				                  WLZ_GREY_UBYTE, NULL),
	                         oMax, &errNum);
        if(errNum == WLZ_ERR_NONE)
	{
	  dbgObj->values = WlzAssignValues(tmpVal, NULL);
	}
      }
      else
      {
        WlzObject *tmpObj = NULL;

	oMin.type = WLZ_GREY_UBYTE;
	oMin.v.ubv = 0;
	oMax.type = WLZ_GREY_UBYTE;
	oMax.v.ubv = 200;
	errNum = WlzGreyRange(dbgObj, &iMin, &iMax);
	if(errNum == WLZ_ERR_NONE)
	{
	  errNum = WlzGreySetRange(dbgObj, iMin, iMax, oMin, oMax, 0);
	}
	if(errNum == WLZ_ERR_NONE)
	{
	  tmpObj = WlzMakeMain(inObj->type, segObj->domain, dbgObj->values,
	                       NULL, NULL, &errNum);
	}
	if(errNum == WLZ_ERR_NONE)
	{
	  oMax.v.ubv = 255;
	  errNum = WlzGreySetValue(tmpObj, oMax);
	}
	(void )WlzFreeObj(tmpObj);
	if(errNum == WLZ_ERR_NONE)
	{
	  tmpObj = WlzConvertPix(dbgObj, WLZ_GREY_UBYTE, &errNum);
	  (void )WlzFreeObj(dbgObj);
	  dbgObj = WlzAssignObject(tmpObj, NULL);
	}
      }
    }
    if(errNum == WLZ_ERR_NONE)
    {
      (void )WlzRadDistParsePath(dbgPath, &dbgDir, &dbgFile, &dbgExt,
      			         &dbgFmt);
      if(dbgExt)
      {
	(void )sprintf(pathBuf, "%s/%s.%s", dbgDir, dbgFile, dbgExt);
      }
      else
      {
	(void )sprintf(pathBuf, "%s/%s", dbgDir, dbgFile);
      }
      errNum = WlzEffWriteObj(NULL, pathBuf, dbgObj, dbgFmt);
    }
    (void )WlzFreeObj(dbgObj);
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr, "%s: failed to output the debug image (%s)\n",
		     *argv, errMsg);
    }
  }
  /* Label the segmented object. */
  if(ok)
  {
    errNum = WlzLabel(segObj, &nReg, &regObjs, maxObj, 0, WLZ_8_CONNECTED);
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      errNum = WLZ_ERR_MEM_ALLOC;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr, "%s: failed to split into components (%s)\n",
		     *argv, errMsg);
    }
    if(ok && verbose)
    {
      (void )fprintf(stderr, "nReg = %d\n", nReg);
    }
  }
  /* Compute centre of mass if not known. */
  if(ok)
  {
    if(centreSet == 0)                          
    {
      centre = WlzCentreOfMass2D(inObj, 1, NULL, &errNum);
      if(errNum != WLZ_ERR_NONE)
      {
	ok = 0;
	(void )WlzStringFromErrorNum(errNum, &errMsg);
	(void )fprintf(stderr, "%s: failed to compute centre of mass (%s)\n",
		       *argv, errMsg);
      }
    }
    if(ok && verbose)
    {
      (void )fprintf(stderr, "centre = %lg,%lg\n", centre.vtX, centre.vtY);
    }
  }
  /* Allocate a radial distribution table. */
  if(ok)
  {
    if((distData = (WlzRadDistRec *)
                   AlcCalloc(nReg, sizeof(WlzRadDistRec))) == NULL)
    {
      ok = 0;
      errNum = WLZ_ERR_MEM_ALLOC;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr, "%s: failed to allocate result lable (%s)\n",
		     *argv, errMsg);
    }
    
  }
  /* Compute the redial distribution data. */
  if(ok)
  {
    int		idR = 0,
    		idS = 0;

    while((errNum == WLZ_ERR_NONE) && (idR < nReg))
    {
      double	mass;
      WlzDVertex2 com;

      com = WlzCentreOfMass2D(regObjs[idR], 1, &mass, NULL);
      if(mass > minArea - eps)
      {
	WlzGreyValueGet(disGVWSp, 0.0, com.vtY, com.vtX);
	distData[idS].pos = com;
	distData[idS].area = mass;
	WLZ_VTX_2_SUB(com, centre, com);
	distData[idS].radius = WLZ_VTX_2_LENGTH(com);
	distData[idS].angle = ALG_M_PI + atan2(com.vtY, com.vtX);
	switch(disGVWSp->gType)
	{
	  case WLZ_GREY_LONG:
	    distData[idS].dist = *(disGVWSp->gPtr[0].lnp);
	    break;
	  case WLZ_GREY_INT:
	    distData[idS].dist = *(disGVWSp->gPtr[0].inp);
	    break;
	  case WLZ_GREY_SHORT:
	    distData[idS].dist = *(disGVWSp->gPtr[0].shp);
	    break;
	  case WLZ_GREY_UBYTE:
	    distData[idS].dist = *(disGVWSp->gPtr[0].ubp);
	    break;
	  case WLZ_GREY_FLOAT:
	    distData[idS].dist = *(disGVWSp->gPtr[0].flp);
	    break;
	  case WLZ_GREY_DOUBLE:
	    distData[idS].dist = *(disGVWSp->gPtr[0].dbp);
	    break;
	  default:
	    distData[idS].dist = 0.0;
	    break;
	}
	++idS;
      }
      ++idR;
    }
    tNReg = idS;
    switch(distSort)
    {
      case WLZ_RADDISTVAL_AREA:
        (void )qsort(distData, tNReg, sizeof(WlzRadDistRec),
		     WlzRadDistRecSortArea);
	break;
      case WLZ_RADDISTVAL_ANGLE:
        (void )qsort(distData, tNReg, sizeof(WlzRadDistRec), 
		     WlzRadDistRecSortAngle);
	break;
      case WLZ_RADDISTVAL_RADIUS:
        (void )qsort(distData, tNReg, sizeof(WlzRadDistRec),
		     WlzRadDistRecSortRadius);
	break;
      case WLZ_RADDISTVAL_DIST:
        (void )qsort(distData, tNReg, sizeof(WlzRadDistRec),
		     WlzRadDistRecSortDist);
	break;
    }
  }
  /* Output the sorted radial distribution table. */
  if(ok)
  {
    if(((fP = strcmp(outFile, "-")?
              fopen(outFile, "w"): stdout)) == NULL)
    {
      ok = 0;
      (void )fprintf(stderr, "%s: failed to open output file %s\n",
                     *argv, outFile);
    }
  }
  if(ok)
  {
    int		idR;

    for(idR = 0; idR < tNReg; ++idR)
    {
      double a;

      a = (distData[idR].angle > 0.0)?
	  0   + (180 * distData[idR].angle / ALG_M_PI):
          360 + (180 * distData[idR].angle / ALG_M_PI);
      (void )fprintf(fP, "%g %g %g %g,%g %g\n",
		     a,
                     distData[idR].radius,
		     distData[idR].area,
		     distData[idR].pos.vtX,
		     distData[idR].pos.vtY,
		     distData[idR].dist);
    }
  }
  if(strcmp(outFile, "-"))
  {
    (void )fclose(fP);
  }
  /* Tidy up. */
  AlcFree(distData);
  WlzGreyValueFreeWSp(disGVWSp);
  (void )WlzFreeObj(inObj);
  (void )WlzFreeObj(disObj);
  (void )WlzFreeObj(segObj);
  if(regObjs)
  {
    int		idR;

    for(idR = 0; idR < nReg; ++idR)
    {
      (void )WlzFreeObj(regObjs[idR]);
    }
    AlcFree(regObjs);
  }
  if(usage)
  {
    (void )fprintf(stderr,
    "Usage: %s [-h] [-v] [-A] [-D] [-G] [-H] [-E] [-L] [-R]\n"
    "\t\t[-c #,#] [-d <debug image>] [-n #]  [-o <out file>]\n"
    "\t\t[-t #] [<input image>]\n"
    "Segments the given object using a threshold value and outputs the \n"
    "radial distribution of the thresholded components.\n"
    "Version: %s\n"
    "Options:\n"
    "  -h  Help - prints this usage masseage.\n"
    "  -v  Verbose output.\n"
    "  -A  Sort output by area (default).\n"
    "  -D  Sort output by distance from boundary.\n"
    "  -G  Sort output by angle.\n"
    "  -H  Threshold high, use pixels at or above threshold (default).\n"
    "  -E  Threshold equal, use pixels at threshold.\n"
    "  -L  Threshold low, use pixels below threshold.\n"
    "  -R  Sort output by radial distance from centre.\n"
    "  -c  Centre (default is image centre).\n"
    "  -d  Debug image.\n"
    "  -n  Minimum area (default %g).\n"
    "  -t  Threshold value (default is to compute using Otsu's method).\n"
    "By default the input image object is read from the standard input and\n"
    "the radial distribution is written to the standard output.\n"
    "The image formats understood include wlz, jpg and tif.\n"
    "The output format is:\n"
    "  <angle> <dist from centre> <area> <x pos>,<y pos> <dist form boundary>\n"
    "Example:\n"
    "  %s -o out.txt -d debug.jpg in.tif\n"
    "The input image is read from in.tif, a debug image showing the\n"
    "segmented regions is written to debug.jpg and the radial distribution\n"
    "statistics are written to the file out.txt. With the output in\n"
    "out.txt, the following R code would plot the data as a set of circles\n"
    "with radius proportional to the square root of the component area:\n"
    "  data <- read.table(\"out.txt\")\n"
    "  attach(data)\n"
    "  symbols(x=data$V1, y=data$V2, circles=sqrt(data$V3))\n",
    argv[0],
    WlzVersion(),
    minArea,
    argv[0]);
  }
  return(!ok);
}
Esempio n. 13
0
static WlzObject *WlzIndexToRGBA3D(
  WlzObject	*obj,
  unsigned char	colormap[3][256],
  WlzErrorNum	*dstErr)
{
  WlzObject		*obj1, *temp;
  WlzPlaneDomain	*pdom, *npdom;
  WlzVoxelValues	*voxtab, *nvoxtab;
  WlzDomain		*domains, *ndomains, domain;
  WlzValues		*values, *nvalues, vals;
  int			i, nplanes;
  WlzErrorNum		errNum=WLZ_ERR_NONE;

  /* no need to check the object pointer or type because this procedure
     can only be accessed via WlzIndexToRGBA. The domain and valuetable
     must be checked however */
  obj1 = NULL;
  if( obj->domain.p == NULL ){
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if( obj->values.vox == NULL ){
    errNum = WLZ_ERR_VALUES_NULL;
  }

  /* check types */
  if( errNum == WLZ_ERR_NONE ){
    switch( obj->domain.p->type ){

    case WLZ_PLANEDOMAIN_DOMAIN:
      break;

    default:
      errNum = WLZ_ERR_PLANEDOMAIN_TYPE;
      break;
    }
  }
  if( errNum == WLZ_ERR_NONE ){
    switch( obj->values.vox->type ){

    case WLZ_VOXELVALUETABLE_GREY:
      break;

    default:
      errNum = WLZ_ERR_VOXELVALUES_TYPE;
      break;
    }
  }

  /* make new planedomain and voxelvaluetable */
  if( errNum == WLZ_ERR_NONE ){
    pdom = obj->domain.p;
    voxtab = obj->values.vox;
    npdom = WlzMakePlaneDomain(pdom->type,
			       pdom->plane1, pdom->lastpl,
			       pdom->line1, pdom->lastln,
			       pdom->kol1, pdom->lastkl, &errNum);
  }
    
  if((errNum == WLZ_ERR_NONE) &&
     ((nvoxtab = WlzMakeVoxelValueTb(voxtab->type, voxtab->plane1,
				     voxtab->lastpl, voxtab->bckgrnd,
				     NULL, &errNum)) == NULL) ){
    WlzFreePlaneDomain(npdom);
  }

  if( errNum == WLZ_ERR_NONE ){
    /* set up variables */
    domains = pdom->domains;
    ndomains = npdom->domains;
    values = voxtab->values;
    nvalues = nvoxtab->values;
    nplanes = pdom->lastpl - pdom->plane1 + 1;

    /* copy voxel_sizes */
    for(i=0; i < 3; i++){
      npdom->voxel_size[i] = pdom->voxel_size[i];
    }
  }

  /* convert each plane */
  while( (errNum == WLZ_ERR_NONE) && nplanes-- ){
    if(((*domains).core == NULL) || ((*values).core == NULL)){
      (*ndomains).core = NULL;
      (*nvalues).core = NULL;
    }
    else if((temp = WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, *values,
				NULL, NULL, &errNum)) != NULL){

      if( temp->domain.i != NULL ){
	if((obj1 = WlzIndexToRGBA(temp, colormap, &errNum)) != NULL){
	  if( obj1->type == WLZ_2D_DOMAINOBJ ){
	    *ndomains = WlzAssignDomain(obj1->domain, NULL);
	    *nvalues = WlzAssignValues(obj1->values, NULL);
	  }
	  else {
	    (*ndomains).core = NULL;
	    (*nvalues).core = NULL;
	  }
	  WlzFreeObj(obj1);
	}
      } else {
	(*ndomains).core = NULL;
	(*nvalues).core = NULL;
      }
    }
    else {
      WlzFreePlaneDomain(npdom);
      WlzFreeVoxelValueTb( nvoxtab );
      break;
    }

    domains++;
    ndomains++;
    values++;
    nvalues++;
  }
  /* return a new object */
  if( errNum == WLZ_ERR_NONE ){
    domain.p = npdom;
    vals.vox = nvoxtab;
    if((obj1 = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, vals,
			   NULL, obj, &errNum)) != NULL){
      /*	nvoxtab->original = obj1; */
      nvoxtab->original_table = WlzAssignValues(obj->values, NULL);
    }
    else {
      WlzFreePlaneDomain( npdom );
      WlzFreeVoxelValueTb( nvoxtab );
    }
  }

  if( dstErr ){
    *dstErr = errNum;
  }
  return obj1;
}
Esempio n. 14
0
/*!
* \return	New 3D domain object with corresponding WLZ_GREY_RGBA values.
* \ingroup      WlzValuesUtils
* \brief	Creates a WLZ_GREY_RGBA valued object from the given compound
* 		array. This is a static function which will always be called
* 		with valid parameters so they aren't checked.
* \param	cObj			Compound array object.
* \param	cSpc 			The colour space.
* \param	dstErr			Destination error pointer may be NULL.
*/
static WlzObject *WlzCompoundToRGBA3D(WlzCompoundArray *cObj,
  				WlzRGBAColorSpace cSpc, WlzErrorNum *dstErr)
{
  WlzIBox3 	bBox;
  WlzDomain	dom;
  WlzValues	val;
  WlzPixelV	bgd;
  WlzObject	*rObj = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  
  dom.core = NULL;
  val.core = NULL;
  bgd.v.rgbv = 0;
  bgd.type = WLZ_GREY_RGBA;
  bBox = WlzBoundingBox3I((WlzObject *)cObj, &errNum);
  if(errNum == WLZ_ERR_NONE)
  {
    dom.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, bBox.zMin, bBox.zMax,
		               bBox.yMin, bBox.yMax, bBox.xMin, bBox.xMax,
			       &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    val.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY,
                                  bBox.zMin, bBox.zMax, bgd, NULL,
			          &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    rObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, dom, val, NULL, NULL, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    int		idP,
    		nPl;

    nPl = bBox.zMax - bBox.zMin + 1;
    for(idP = 0; idP < nPl; ++idP)
    {
      if(errNum == WLZ_ERR_NONE)
      {
	int	idC;
	WlzObject *rObj2 = NULL;
	WlzCompoundArray *cObj2 = NULL;
	WlzErrorNum errNum2 = WLZ_ERR_NONE;

	cObj2 = WlzMakeCompoundArray(WLZ_COMPOUND_ARR_2, 1, cObj->n,
	                             NULL, WLZ_2D_DOMAINOBJ, &errNum2);

	idC = 0;
	while((errNum2 == WLZ_ERR_NONE) && (idC < cObj->n))
	{
	  int		idP2,
	  		nPl2;
	  WlzDomain	dom2;
	  WlzValues	val2;

	  dom2.core = NULL;
	  val2.core = NULL;
	  if((cObj->o[idC] != NULL) &&
	     (cObj->o[idC]->type == WLZ_3D_DOMAINOBJ))
	  {
	    idP2 = bBox.zMin + idP - cObj->o[idC]->domain.p->plane1;
	    nPl2 = cObj->o[idC]->domain.p->lastpl - 
	           cObj->o[idC]->domain.p->plane1 + 1;
	    if((idP2 >= 0) && (idP2 <= nPl2))
	    {
	      dom2 = *(cObj->o[idC]->domain.p->domains + idP2);
	      val2 = *(cObj->o[idC]->values.vox->values + idP2);
	    }
	  }
	  cObj2->o[idC] = (dom2.core == NULL)?
	                  WlzMakeEmpty(&errNum2):
	                  WlzMakeMain(WLZ_2D_DOMAINOBJ, dom2, val2,
	                              NULL, NULL, &errNum2);
	  ++idC;
	}
	if(errNum2 == WLZ_ERR_NONE)
	{
	  rObj2 = WlzCompoundToRGBA2D(cObj2, cSpc, &errNum2);
	}
	if(errNum2 == WLZ_ERR_NONE)
	{
	  dom.p->domains[idP] = WlzAssignDomain(rObj2->domain, NULL);
	  val.vox->values[idP] = WlzAssignValues(rObj2->values, NULL);
	}
	(void )WlzFreeObj(rObj2);
	(void )WlzFreeObj((WlzObject *)cObj2);
	if(errNum2 != WLZ_ERR_NONE)
	{
	  errNum = errNum2;
	}
      }
    }
  }
  if(errNum != WLZ_ERR_NONE)
  {
    if(rObj != NULL)
    {
      (void )WlzFreeObj(rObj);
      rObj = NULL;
    }
    else
    {
      (void )WlzFreePlaneDomain(dom.p);
      (void )WlzFreeVoxelValueTb(val.vox);
    }
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(rObj);
}
Esempio n. 15
0
/*!
* \return	New 3D domain object with corresponding WLZ_GREY_RGBA values.
* \ingroup      WlzValuesUtils
* \brief	Creates a WLZ_GREY_RGBA valued object from the given compound
* 		array. This is a static function which will always be called
* 		with valid parameters so they aren't checked.
* \param	cObj			Compound array object.
* \param	cSpc 			The colour space.
* \param	dstErr			Destination error pointer may be NULL.
*/
static WlzObject *WlzCompoundToRGBA2D(WlzCompoundArray *cObj,
  				WlzRGBAColorSpace cSpc, WlzErrorNum *dstErr)
{
  int		i,
  		j;
  WlzObject	*rtnObj=NULL;
  WlzPixelV	bckgrnd;
  WlzObject	*objs[4];
  WlzObjectType vType;
  WlzUInt	b[4];
  WlzErrorNum	errNum=WLZ_ERR_NONE;

  /* Make a copy of the object pointers because WlzUnionN() modifies the
   * array if it contains empty objects. */
  for(i = 0; i < 3; ++i)
  {
    objs[i] = cObj->o[i];
  }
  rtnObj = WlzUnionN(3, objs, 0, &errNum);
  if(errNum == WLZ_ERR_NONE)
  {
    /* Add an RGBA valuetable, extract background for each channel */
    vType = WlzGreyTableType(WLZ_GREY_TAB_RAGR, WLZ_GREY_RGBA, &errNum);
    for(i=0; (errNum == WLZ_ERR_NONE) && (i < 3); i++)
    {
      bckgrnd = WlzGetBackground(cObj->o[i], &errNum);
      if(errNum == WLZ_ERR_NONE)
      {
        errNum = WlzValueConvertPixel(&bckgrnd, bckgrnd, WLZ_GREY_UBYTE);
        b[i] = bckgrnd.v.ubv;
      }
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    WlzValues	values;

    bckgrnd.type = WLZ_GREY_RGBA;
    WLZ_RGBA_RGBA_SET(bckgrnd.v.rgbv, b[0], b[1], b[2], 255);
    values.v = WlzNewValueTb(rtnObj, vType, bckgrnd, &errNum);
    if(values.v != NULL)
    {
      rtnObj->values = WlzAssignValues(values, &errNum);
    }
    else
    {
      (void )WlzFreeObj(rtnObj);
      rtnObj = NULL;
    }
  }
  /* Transfer values */
  if( errNum == WLZ_ERR_NONE)
  {
    WlzGreyValueWSpace	*gValWSpc[4];
    WlzIntervalWSpace	iwsp;
    WlzGreyWSpace	gwsp;
    WlzGreyV		gval;

    /* do it dumb fashion for now, rgb only */
    gValWSpc[0] = gValWSpc[1] = gValWSpc[2] = gValWSpc[3] = NULL;
    for(i=0; i < 3; i++)
    {
      if((cObj->o[i] != NULL) && (cObj->o[i]->type != WLZ_EMPTY_OBJ))
      {
        gValWSpc[i] = WlzGreyValueMakeWSp(cObj->o[i], &errNum);
	if(errNum != WLZ_ERR_NONE)
	{
	  break;
	}
      }
    }
    if(errNum == WLZ_ERR_NONE)
    {
      errNum = WlzInitGreyScan(rtnObj, &iwsp, &gwsp);
    }
    while((errNum == WLZ_ERR_NONE) &&
          ((errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE))
    {
      WlzPixelV	pix;

      for(j = iwsp.lftpos; j <= iwsp.rgtpos; j++)
      {
	for(i = 0; i < 3; i++)
	{
	  if(gValWSpc[i] == NULL)
	  {
	    pix.v.ubv = (i < 2)? 0: 255;
	  }
	  else
	  {
	    WlzGreyValueGet(gValWSpc[i], 0, iwsp.linpos, j);
	    pix.type = gValWSpc[i]->gType;
	    pix.v = gValWSpc[i]->gVal[0];
	    WlzValueConvertPixel(&pix, pix, WLZ_GREY_UBYTE);
	  }
	  b[i] = pix.v.ubv;
	}
	WLZ_RGBA_RGBA_SET(gval.rgbv, b[0], b[1], b[2], b[3]);
	*gwsp.u_grintptr.rgbp = gval.rgbv;
	gwsp.u_grintptr.rgbp++;
      }
    }
    if(errNum == WLZ_ERR_EOO)
    {
      errNum = WLZ_ERR_NONE;
    }
    for(i=0; i < 3; i++)
    {
      WlzGreyValueFreeWSp(gValWSpc[i]);
    }
  }
  if(dstErr != NULL)
  {
    *dstErr = errNum;
  }
  return(rtnObj);
}
Esempio n. 16
0
static WlzObject *WlzGreyMask3d(
  WlzObject	*obj,
  WlzObject	*mask,
  WlzPixelV	maskVal,
  WlzErrorNum	*dstErr)
{
  WlzObject	*rtnObj=NULL;
  WlzObject	*tmpMask, *obj1, *obj2;
  WlzDomain	*domains;
  WlzValues	values, *valuess, *newvaluess;
  WlzPlaneDomain	*pdom;
  int		p;
  WlzErrorNum	errNum=WLZ_ERR_NONE;

  /* check the object - it is non-NULL and 3D but the
     domain needs checking */
  if( obj->domain.p == NULL ){
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else {
    switch( obj->domain.p->type ){
    case WLZ_2D_DOMAINOBJ:
      /* check there is a valuetable */
      if( obj->values.core == NULL ){
	errNum = WLZ_ERR_VALUES_NULL;
      }
      break;

    case WLZ_EMPTY_DOMAIN:
      return WlzMakeEmpty(dstErr);

    default:
      errNum = WLZ_ERR_DOMAIN_TYPE;
      break;
    }
  }

  /* check the mask */
  if( errNum == WLZ_ERR_NONE ){
    if( mask == NULL ){
      errNum = WLZ_ERR_OBJECT_NULL;
    }
    else {
      /* set some local variables */
      pdom = obj->domain.p;
      domains = obj->domain.p->domains;
      valuess = obj->values.vox->values;

      /* create a new voxel object, initially no values */
      values.vox = WlzMakeVoxelValueTb(obj->values.vox->type,
				       obj->values.vox->plane1,
				       obj->values.vox->lastpl,
				       obj->values.vox->bckgrnd,
				       obj, NULL);
      rtnObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, obj->domain, values,
			   NULL, NULL, NULL);
      newvaluess = rtnObj->values.vox->values;

      /* switch on mask type - a 2D mask is applied to each plane */
      switch( mask->type ){
      case WLZ_2D_DOMAINOBJ:
      case WLZ_2D_POLYGON:
      case WLZ_BOUNDLIST:
      case WLZ_EMPTY_OBJ:
	for(p=pdom->plane1; p <= pdom->lastpl; p++, domains++, valuess++){
	  if( (*domains).core ){
	    obj1 = WlzAssignObject(
	      WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, *valuess,
			  NULL, NULL, NULL), NULL);
	    if((obj2 = WlzGreyMask(obj1, mask, maskVal, &errNum)) != NULL){
	      newvaluess[p - pdom->plane1] =
		WlzAssignValues(obj->values, NULL);
	      WlzFreeObj(obj2);
	    }
	    WlzFreeObj(obj1);
	  }
	}
	break;

      case WLZ_3D_DOMAINOBJ:
	/* switch on plane domain type - polygon and boundlist
	   are legal but need transforming first. */
	switch( obj->domain.p->type ){
	  WlzDomain	*maskDoms;

	case WLZ_PLANEDOMAIN_DOMAIN:
	  maskDoms = mask->domain.p->domains;
	  for(p=pdom->plane1; p <= pdom->lastpl; p++, domains++, valuess++){
	    if(((*domains).core)){
	      if((p >= mask->domain.p->plane1) &&
		 (p <= mask->domain.p->lastpl) &&
		 (maskDoms[p - mask->domain.p->plane1].core) ){
		values.core = NULL;
		tmpMask = WlzMakeMain(WLZ_2D_DOMAINOBJ,
				      maskDoms[p - mask->domain.p->plane1],
				      values, NULL, NULL, NULL);
	      }
	      else {
		tmpMask = WlzMakeEmpty(NULL);
	      }

	      obj1 = WlzAssignObject(
		WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, *valuess,
			    NULL, NULL, NULL), NULL);
	      if((obj2 = WlzGreyMask(obj1, tmpMask, maskVal,
	      			     &errNum)) != NULL){
		newvaluess[p - pdom->plane1] =
		  WlzAssignValues(obj2->values, NULL);
		WlzFreeObj(obj2);
	      }
	      WlzFreeObj(obj1);
	      WlzFreeObj(tmpMask);
	    }
	  }
	  break;

	case WLZ_PLANEDOMAIN_POLYGON:
	  maskDoms = mask->domain.p->domains;
	  for(p=pdom->plane1; p <= pdom->lastpl; p++, domains++, valuess++){
	    if(((*domains).core)){
	      if((p >= mask->domain.p->plane1) &&
		 (p <= mask->domain.p->lastpl) &&
		 (maskDoms[p - mask->domain.p->plane1].core) ){
		values.core = NULL;
		tmpMask = WlzMakeMain(WLZ_2D_POLYGON,
				      maskDoms[p - mask->domain.p->plane1],
				      values, NULL, NULL, NULL);
	      }
	      else {
		tmpMask = WlzMakeEmpty(NULL);
	      }

	      obj1 = WlzAssignObject(
		WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, *valuess,
			    NULL, NULL, NULL), NULL);
	      if((obj2 = WlzGreyMask(obj1, tmpMask, maskVal,
	                             &errNum)) != NULL){
		newvaluess[p - pdom->plane1] =
		  WlzAssignValues(obj2->values, NULL);
		WlzFreeObj(obj2);
	      }
	      WlzFreeObj(obj1);
	      WlzFreeObj(tmpMask);
	    }
	  }
	  break;

	case WLZ_PLANEDOMAIN_BOUNDLIST:
	  maskDoms = mask->domain.p->domains;
	  for(p=pdom->plane1; p <= pdom->lastpl; p++, domains++, valuess++){
	    if(((*domains).core)){
	      if((p >= mask->domain.p->plane1) &&
		 (p <= mask->domain.p->lastpl) &&
		 (maskDoms[p - mask->domain.p->plane1].core) ){
		values.core = NULL;
		tmpMask = WlzMakeMain(WLZ_BOUNDLIST,
				      maskDoms[p - mask->domain.p->plane1],
				      values, NULL, NULL, NULL);
	      }
	      else {
		tmpMask = WlzMakeEmpty(NULL);
	      }

	      obj1 = WlzAssignObject(
		WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, *valuess,
			    NULL, NULL, NULL), NULL);
	      if((obj2 = WlzGreyMask(obj1, tmpMask, maskVal,
	                             &errNum)) != NULL){
		newvaluess[p - pdom->plane1] =
		  WlzAssignValues(obj2->values, NULL);
		WlzFreeObj(obj2);
	      }
	      WlzFreeObj(obj1);
	      WlzFreeObj(tmpMask);
	    }
	  }
	  break;

	default:
	  errNum = WLZ_ERR_DOMAIN_TYPE;
	  WlzFreeObj(rtnObj);
	  rtnObj = NULL;
	  break;
	}
	break;

      default:
	errNum = WLZ_ERR_OBJECT_NULL;
	WlzFreeObj(rtnObj);
	rtnObj = NULL;
	break;
      }
    }
  }


  if( dstErr ){
    *dstErr = errNum;
  }
  return rtnObj;
}
Esempio n. 17
0
/*! 
* \ingroup      WlzValuesUtils
* \brief        Set the value maskVal within the domain given by the	
*		mask object. The mask object can be a 2D, 3D, polygon	
*		or boundary object. A 3D mask with a 2D object is an	
*		error. A 2D mask with a 3D object will be applied to	
*		each plane in turn.			
*
* \return       New object with the same domain as the input object but
 with values in the intersection with the mask domain set to the mask
 value. NULL on error.
 * \param    obj	Input object
 * \param    mask	Mask object.
 * \param    maskVal	mask value.
 * \param    dstErr	Error return.
* \par      Source:
*                WlzGreyMask.c
*/
WlzObject *WlzGreyMask(
  WlzObject	*obj,
  WlzObject	*mask,
  WlzPixelV	maskVal,
  WlzErrorNum	*dstErr)
{
  WlzObject	*rtnObj=NULL;
  WlzObject	*tmpMask, *obj1;
  WlzValues	values;
  WlzPixelV	tmpMaskval;
  WlzIntervalWSpace	iwsp;
  WlzGreyWSpace		gwsp;
  WlzGreyP		gptr;
  int			i;
  WlzErrorNum	errNum=WLZ_ERR_NONE;

  /* check obj */
  if( obj == NULL ){
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else {
    switch( obj->type ){
    case WLZ_2D_DOMAINOBJ:
      if( obj->values.core == NULL ){
	errNum = WLZ_ERR_VALUES_NULL;
      }
      break;

    case WLZ_3D_DOMAINOBJ:
      return WlzGreyMask3d(obj, mask, maskVal, dstErr);

    case WLZ_TRANS_OBJ:
      if((values.obj = WlzGreyMask(obj->values.obj, mask, maskVal,
      				   &errNum)) != NULL){
	return WlzMakeMain(WLZ_TRANS_OBJ, obj->domain, values,
			   NULL, NULL, dstErr);
      }
      break;

    case WLZ_EMPTY_OBJ:
      return WlzMakeEmpty(dstErr);

    default:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;
    }
  }

  /* check the mask */
  if( errNum == WLZ_ERR_NONE ){
    if( mask == NULL ){
      errNum = WLZ_ERR_OBJECT_NULL;
    }
    else {
      values.core = NULL;
      switch( mask->type ){
      case WLZ_2D_DOMAINOBJ:
	tmpMask = WlzMakeMain(WLZ_2D_DOMAINOBJ, mask->domain, values,
			      NULL, NULL, &errNum);
	break;

      case WLZ_TRANS_OBJ:
	tmpMask = WlzMakeMain(WLZ_2D_DOMAINOBJ, mask->values.obj->domain,
			      values, NULL, NULL, &errNum);
	break;

      case WLZ_EMPTY_OBJ:
	return WlzMakeMain(WLZ_2D_DOMAINOBJ, obj->domain, obj->values,
			   NULL, NULL, dstErr);

      case WLZ_2D_POLYGON:
	tmpMask = WlzPolyToObj(mask->domain.poly, WLZ_SIMPLE_FILL, &errNum);
	break;

      case WLZ_BOUNDLIST:
	tmpMask = WlzBoundToObj(mask->domain.b, WLZ_SIMPLE_FILL, &errNum);
	break;

      default:
	errNum = WLZ_ERR_OBJECT_TYPE;
	break;
      }
      if( errNum == WLZ_ERR_NONE ){
	tmpMask = WlzAssignObject(tmpMask, NULL);
      }
    }
  }

  /* copy input obj and setvalues in the intersection */
  if(errNum == WLZ_ERR_NONE){
    if((rtnObj = WlzNewGrey(obj, &errNum)) != NULL){
      if((obj1 = WlzIntersect2(obj, tmpMask, &errNum)) != NULL){
	obj1->values = WlzAssignValues(rtnObj->values, NULL);
	errNum = WlzInitGreyScan(obj1, &iwsp, &gwsp);
	WlzValueConvertPixel(&tmpMaskval, maskVal, gwsp.pixeltype);
	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++){
	      *gptr.inp = tmpMaskval.v.inv;
	    }
	    break;
	  case WLZ_GREY_SHORT:
	    for(i=0; i<iwsp.colrmn; i++, gptr.shp++){
	      *gptr.shp = tmpMaskval.v.shv;
	    }
	    break;
	  case WLZ_GREY_UBYTE:
	    for(i=0; i<iwsp.colrmn; i++, gptr.ubp++){
	      *gptr.ubp = tmpMaskval.v.ubv;
	    }
	    break;
	  case WLZ_GREY_FLOAT:
	    for(i=0; i<iwsp.colrmn; i++, gptr.flp++){
	      *gptr.flp = tmpMaskval.v.flv;
	    }
	    break;
	  case WLZ_GREY_DOUBLE:
	    for(i=0; i<iwsp.colrmn; i++, gptr.dbp++){
	      *gptr.dbp = tmpMaskval.v.dbv;
	    }
	    break;
	  case WLZ_GREY_RGBA:
	    for(i=0; i<iwsp.colrmn; i++, gptr.rgbp++){
	      *gptr.rgbp = tmpMaskval.v.rgbv;
	    }
	    break;
	  default:
	    errNum = WLZ_ERR_GREY_TYPE;
	    break;
	  }
	}
	if( errNum == WLZ_ERR_EOO ){
	  errNum = WLZ_ERR_NONE;
	}
	WlzFreeObj(obj1);
      }
      else {
	WlzFreeObj(rtnObj);
	rtnObj = NULL;
      }
    }
    WlzFreeObj(tmpMask);
  }

  if( dstErr ){
    *dstErr = errNum;
  }
  return rtnObj;
}
Esempio n. 18
0
/*! 
* \ingroup      WlzValuesUtils
* \brief        
*
* \return       New object with the same domain <tt>tmpl</tt> but
 values in the intersection with <tt>obj</tt> set to those of the object.
 Returns NULL on error.
* \param    obj	Input object to which the template is applied
* \param    tmpl	Template object
* \param    tmplVal	Template value for regions in the template
 not in the original object
* \param    dstErr	Error return.
* \par      Source:
*                WlzGreyTemplate.c
*/
WlzObject *WlzGreyTemplate(
  WlzObject	*obj,
  WlzObject	*tmpl,
  WlzPixelV	tmplVal,
  WlzErrorNum	*dstErr)
{
  WlzObject	*rtnObj=NULL;
  WlzObject	*obj1, *obj2;
  WlzValues	values;
  WlzPixelV	bckgrnd;
  WlzObjectType	type;
  WlzGreyType	gtype=WLZ_GREY_UBYTE;
  WlzIntervalWSpace	iwsp1, iwsp2;
  WlzGreyWSpace		gwsp1, gwsp2;
  int			size;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  /* check obj */
  if( obj == NULL ){
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else {
    switch( obj->type ){
    case WLZ_2D_DOMAINOBJ:
      if( obj->values.core == NULL ){
	errNum = WLZ_ERR_VALUES_NULL;
      }
      else if( WlzGreyTableIsTiled(obj->values.core->type) ){
	errNum = WLZ_ERR_VALUES_TYPE;
      } else {
        bckgrnd = WlzGetBackground(obj, &errNum);
      }
      if(errNum == WLZ_ERR_NONE) {
        gtype = WlzGreyTableTypeToGreyType(obj->values.core->type, NULL);
      }
      break;

    case WLZ_3D_DOMAINOBJ:
      return WlzGreyTemplate3d(obj, tmpl, tmplVal, dstErr);

    case WLZ_TRANS_OBJ:
      if((values.obj = WlzGreyTemplate(obj->values.obj, tmpl,
				       tmplVal, &errNum)) != NULL){
	return WlzMakeMain(WLZ_TRANS_OBJ, obj->domain, values,
			   NULL, NULL, dstErr);
      }
      break;

    case WLZ_EMPTY_OBJ:
      bckgrnd.type = WLZ_GREY_UBYTE;
      bckgrnd.v.ubv = 0;
      break;

    default:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;
    }
  }

  /* check the template */
  if( errNum == WLZ_ERR_NONE ){
    if( tmpl == NULL ){
      errNum = WLZ_ERR_OBJECT_NULL;
    }
    else {
      values.core = NULL;
      switch( tmpl->type ){
      case WLZ_2D_DOMAINOBJ:
	rtnObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, tmpl->domain, values,
			      NULL, NULL, &errNum);
	break;

      case WLZ_TRANS_OBJ:
	rtnObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, tmpl->values.obj->domain,
			      values, NULL, NULL, &errNum);
	break;

      case WLZ_EMPTY_OBJ:
	return WlzMakeEmpty(dstErr);

      case WLZ_2D_POLYGON:
	rtnObj = WlzPolyToObj(tmpl->domain.poly, WLZ_SIMPLE_FILL, &errNum);
	break;

      case WLZ_BOUNDLIST:
	rtnObj = WlzBoundToObj(tmpl->domain.b, WLZ_SIMPLE_FILL, &errNum);
	break;

      default:
	errNum = WLZ_ERR_OBJECT_TYPE;
	break;
      }
    }
  }

  /* attach a value table to the template and set to the template value,
     note the background is set to the input object or zero if empty */
  if( errNum == WLZ_ERR_NONE ){
    type = WlzGreyTableType(WLZ_GREY_TAB_RAGR, gtype, NULL);
    if((values.v = WlzNewValueTb(rtnObj, type, bckgrnd, &errNum)) != NULL){
      rtnObj->values = WlzAssignValues(values, NULL);
      errNum = WlzGreySetValue(rtnObj, tmplVal);
    }
  }

  /* copy input obj values within the intersection */
  if( errNum == WLZ_ERR_NONE ){
    if((obj->type != WLZ_EMPTY_OBJ) ){
      if( (obj1 = WlzIntersect2(obj, rtnObj, &errNum)) ){
	obj1->values = WlzAssignValues(rtnObj->values, NULL);
	obj2 = WlzMakeMain(obj1->type, obj1->domain, obj->values,
			   NULL, NULL, NULL);

	errNum = WlzInitGreyScan(obj1, &iwsp1, &gwsp1);
	errNum = WlzInitGreyScan(obj2, &iwsp2, &gwsp2);
	switch( gwsp1.pixeltype ){
	case WLZ_GREY_INT:
	  size = sizeof(int);
	  break;
	case WLZ_GREY_SHORT:
	  size = sizeof(short);
	  break;
	case WLZ_GREY_UBYTE:
	  size = sizeof(WlzUByte);
	  break;
	case WLZ_GREY_FLOAT:
	  size = sizeof(float);
	  break;
	case WLZ_GREY_DOUBLE:
	  size = sizeof(double);
	  break;
	case WLZ_GREY_RGBA:
	  size = sizeof(WlzUInt);
	  break;
	default:
	  errNum = WLZ_ERR_GREY_TYPE;
	  break;
	}

	while((errNum == WLZ_ERR_NONE) &&
	      ((errNum = WlzNextGreyInterval(&iwsp1)) == WLZ_ERR_NONE)){
	  (void) WlzNextGreyInterval(&iwsp2);
	  memcpy((void *) gwsp1.u_grintptr.inp,
		 (const void *) gwsp2.u_grintptr.inp,
		 size * iwsp1.colrmn);
	}
	if( errNum == WLZ_ERR_EOO ){
	  errNum = WLZ_ERR_NONE;
	}
	WlzFreeObj(obj2);
	WlzFreeObj(obj1);
      }
      else {
	WlzFreeObj(rtnObj);
	rtnObj = NULL;
      }
    }
  }

  if( dstErr ){
    *dstErr = errNum;
  }
  return rtnObj;
}
Esempio n. 19
0
/*!
* \return	Rescaled object.
* \ingroup	WlzTransform
* \brief	Rescales the given 3D domain object using an integer scale.
* \param	gObj			Given object.
* \param	scale			Integer scale factor.
* \param	expand			If zero use \f$\frac{1}{scale}\f$.
* \param	dstErr			Destination error pointer, may be NULL.
*/
WlzObject	*WlzIntRescaleObj3D(WlzObject *gObj, int scale, int expand,
				    WlzErrorNum *dstErr)
{
  int		gPIdx,
  		nPIdx;
  WlzDomain	gDom,
  		nDom;
  WlzValues	gVal,
  		nVal,
		dumVal;
  WlzObject	*gTObj = NULL,
  		*nTObj = NULL,
		*rObj = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  WlzIBox3	nBox;

  nDom.core = NULL;
  nVal.core = NULL;
  dumVal.core = NULL;
  gDom = gObj->domain;
  gVal = gObj->values;
  if(expand)
  {
    nBox.xMin = gDom.p->kol1 * scale;
    nBox.xMax = ((gDom.p->lastkl + 1) * scale) - 1;
    nBox.yMin = gDom.p->line1 * scale;
    nBox.yMax = ((gDom.p->lastln + 1) * scale) - 1;
    nBox.zMin = gDom.p->plane1 * scale;
    nBox.zMax = ((gDom.p->lastpl + 1) * scale) - 1;
  }
  else
  {
    nBox.xMin = gDom.p->kol1 / scale;
    nBox.xMax = gDom.p->lastkl / scale;
    nBox.yMin = gDom.p->line1 / scale;
    nBox.yMax = gDom.p->lastln / scale;
    nBox.zMin = gDom.p->plane1 / scale;
    nBox.zMax = gDom.p->lastpl / scale;
  }
  nDom.p = WlzMakePlaneDomain(gDom.p->type, nBox.zMin, nBox.zMax,
			      nBox.yMin, nBox.yMax, nBox.xMin, nBox.xMax,
			      &errNum);
  if(errNum == WLZ_ERR_NONE)
  {
    if(gVal.core && (gVal.core->type != WLZ_EMPTY_OBJ))
    {
      if(WlzGreyTableIsTiled(gVal.core->type))
      {
        errNum = WLZ_ERR_VALUES_TYPE;
      }
      else
      {
	nVal.vox = WlzMakeVoxelValueTb(gVal.vox->type, nBox.zMin, nBox.zMax,
				WlzGetBackground(gObj, NULL),
				NULL, &errNum);
      }
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    nPIdx = nBox.zMin;
    while((errNum == WLZ_ERR_NONE) && (nPIdx <= nBox.zMax))
    {
      gPIdx = (expand)? nPIdx / scale: nPIdx * scale;
      if(nVal.vox)
      {
        gTObj = WlzMakeMain(WLZ_2D_DOMAINOBJ,
                            *(gDom.p->domains + gPIdx),
                            *(gVal.vox->values + gPIdx),
                            NULL, NULL, &errNum);
      }
      else
      {
        gTObj = WlzMakeMain(WLZ_2D_DOMAINOBJ,
                            *(gDom.p->domains + gPIdx),
                            dumVal,
                            NULL, NULL, &errNum);
      }
      if(errNum == WLZ_ERR_NONE)
      {
	nTObj = WlzIntRescaleObj2D(gTObj, scale, expand, &errNum);
      }
      (void )WlzFreeObj(gTObj);
      gTObj = NULL;
      if(errNum == WLZ_ERR_NONE)
      {
        *(nDom.p->domains + nPIdx) = WlzAssignDomain(nTObj->domain, NULL);
        if(nVal.vox)
        {
          *(nVal.vox->values + nPIdx) = WlzAssignValues(nTObj->values, NULL);
        }
      }
      (void )WlzFreeObj(nTObj);
      nTObj = NULL;
      ++nPIdx;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    rObj = WlzMakeMain(gObj->type, nDom, nVal, NULL, NULL, &errNum);
  }
  else
  {
    (void )WlzFreePlaneDomain(nDom.p);
    (void )WlzFreeVoxelValueTb(nVal.vox);
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(rObj);
}
/*! 
* \return       Object with transformed grey-values.
* \ingroup      WlzArithmetic
* \brief        Apply a binary operation (add subtract etc) to
*               each pixel value in the given object. The operand value
*               is in <tt>pval</tt>.
* \param    o1	Input object
* \param    pval	Pixel value for binary operation.
* \param    op		Opertor
* \param    dstErr	Error return.
* \par      Source:
*                WlzScalarArithmeticOp.c
*/
WlzObject *WlzScalarBinaryOp2(
  WlzObject	*o1,
  WlzPixelV	pval,
  WlzBinaryOperatorType	op,
  WlzErrorNum	*dstErr)
{
  WlzObject	*obj=NULL, *tmp3;
  WlzErrorNum	errNum=WLZ_ERR_NONE;
  WlzValues	values;
  WlzPixelV	old_bckgrnd, new_bckgrnd;
  WlzGreyType	new_grey_type;
  int		p;

  /* check object pointers */
  if( (o1 == NULL) ){
    errNum = WLZ_ERR_OBJECT_NULL;
  }

  /* check object types - WLZ_EMPTY_OBJ is legal */
  if( errNum == WLZ_ERR_NONE ){
    switch( o1->type ){

    case WLZ_2D_DOMAINOBJ: /* FALLTHROUGH */
    case WLZ_3D_DOMAINOBJ: /* FALLTHROUGH */
    case WLZ_TRANS_OBJ:
      break;

    case WLZ_EMPTY_OBJ:
      obj = WlzMakeEmpty(&errNum);
      break;

    default:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;

    }
  }

  /* check domains and valuetables */
  if( (errNum == WLZ_ERR_NONE) && (obj == NULL) ){
    switch( o1->type ){

    case WLZ_2D_DOMAINOBJ:
      if( (o1->domain.core == NULL) ){
	errNum = WLZ_ERR_DOMAIN_NULL;
	break;
      }
      if( (o1->values.core == NULL) ){
	errNum = WLZ_ERR_VALUES_NULL;
	break;
      }
      break;

    case WLZ_3D_DOMAINOBJ:
      if( (o1->domain.core == NULL) ){
	errNum = WLZ_ERR_DOMAIN_NULL;
	break;
      }
      if( (o1->domain.p->type != WLZ_PLANEDOMAIN_DOMAIN) ){
	errNum = WLZ_ERR_PLANEDOMAIN_TYPE;
	break;
      }
      if( (o1->values.core == NULL) ){
	errNum = WLZ_ERR_VALUES_NULL;
	break;
      }
      if( (o1->values.vox->type != WLZ_VOXELVALUETABLE_GREY) ){
	errNum = WLZ_ERR_VOXELVALUES_TYPE;
	break;
      }
      break;

    case WLZ_TRANS_OBJ:
      if( (o1->domain.core == NULL) ){
	errNum = WLZ_ERR_DOMAIN_NULL;
	break;
      }
      if( (o1->values.core == NULL) ){
	errNum = WLZ_ERR_VALUES_NULL;
	break;
      }
      if((values.obj = WlzScalarBinaryOp2(o1->values.obj, pval,
					 op, &errNum)) != NULL){
	obj = WlzMakeMain(WLZ_TRANS_OBJ, o1->domain, values,
			  NULL, NULL, &errNum);
	break;
      }
      break;
    default:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;
    }
  }

  /* set up temporary object */
  if((errNum == WLZ_ERR_NONE) && (obj == NULL)){
    switch( o1->type ){

    case WLZ_2D_DOMAINOBJ:
      values.core = NULL;
      if( (tmp3 = WlzMakeMain(WLZ_2D_DOMAINOBJ, o1->domain,
			      values, NULL, NULL, &errNum)) == NULL ){
	break;
      }
      old_bckgrnd = WlzGetBackground(o1, NULL);
      switch( WlzGreyTableTypeToGreyType(o1->values.core->type, NULL) ){
      case WLZ_GREY_INT:   /* FALLTHROUGH */
      case WLZ_GREY_SHORT: /* FALLTHROUGH */
      case WLZ_GREY_FLOAT: /* FALLTHROUGH */
      case WLZ_GREY_DOUBLE:
	new_grey_type = WlzGreyTableTypeToGreyType(o1->values.core->type,
						   NULL);
	new_bckgrnd = old_bckgrnd;
	break;	
      case WLZ_GREY_UBYTE:
	new_grey_type = WLZ_GREY_SHORT;
	new_bckgrnd.type = WLZ_GREY_SHORT;
	new_bckgrnd.v.shv = old_bckgrnd.v.ubv;
	break;
      default:
        errNum = WLZ_ERR_OBJECT_TYPE;
	break;
      }
      if(errNum == WLZ_ERR_NONE){
	values.v = WlzNewValueTb(tmp3,
				 WlzGreyTableType(WLZ_GREY_TAB_RAGR,
						  new_grey_type, NULL),
				 new_bckgrnd, &errNum);
	tmp3->values = WlzAssignValues( values, NULL );
      }
      break;

    case WLZ_3D_DOMAINOBJ:
      values.core = NULL;
      if((tmp3 = WlzMakeMain(WLZ_3D_DOMAINOBJ, o1->domain, values,
			     NULL, NULL, &errNum)) == NULL){
	break;
      }

      /* now a new destination voxeltable */
      old_bckgrnd = WlzGetBackground(o1, NULL);
      switch( old_bckgrnd.type ){
      case WLZ_GREY_INT:   /* FALLTHROUGH */
      case WLZ_GREY_SHORT: /* FALLTHROUGH */
      case WLZ_GREY_FLOAT: /* FALLTHROUGH */
      case WLZ_GREY_DOUBLE:
	new_grey_type = old_bckgrnd.type;
	new_bckgrnd = old_bckgrnd;
	break;	
      case WLZ_GREY_UBYTE:
	new_grey_type = WLZ_GREY_SHORT;
	new_bckgrnd.type = WLZ_GREY_SHORT;
	new_bckgrnd.v.shv = old_bckgrnd.v.ubv;
	break;
      default:
        errNum = WLZ_ERR_GREY_TYPE;
	break;
      }
      if(errNum == WLZ_ERR_NONE){
	values.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY,
					 tmp3->domain.p->plane1,
					 tmp3->domain.p->lastpl,
					 new_bckgrnd, NULL, &errNum);
	if( values.vox == NULL ){break;}

	for(p=tmp3->domain.p->plane1; p <= tmp3->domain.p->lastpl; p++){
	  WlzValues	values2d;

	  /* currently test for NULL domain to imply WLZ_EMPTY_DOMAIN */
	  if( tmp3->domain.p->domains[p-tmp3->domain.p->plane1].core
	     == NULL ){
	    values2d.core = NULL;
	  }
	  else {
	    WlzObject	*tmp2d;
	    values2d.core = NULL;
	    if((tmp2d = WlzMakeMain(WLZ_2D_DOMAINOBJ,
		             tmp3->domain.p->domains[p-tmp3->domain.p->plane1],
		             values2d, NULL, NULL, &errNum)) != NULL){
	      values2d.v = WlzNewValueTb(
		tmp2d, WlzGreyTableType(WLZ_GREY_TAB_RAGR, new_grey_type,
					NULL), new_bckgrnd, &errNum);
	      WlzFreeObj( tmp2d );
	    }
	  }
	  values.vox->values[p-tmp3->domain.p->plane1] = 
	    WlzAssignValues(values2d, NULL);
	}
	tmp3->values = WlzAssignValues(values, NULL);
      }

      break;

    default:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;
    }
  }

  /* apply operation and free space */
  if((errNum == WLZ_ERR_NONE) && (obj == NULL)){
    if((errNum = WlzScalarBinaryOp(o1, pval, tmp3, op)) != WLZ_ERR_NONE){
      WlzFreeObj( tmp3 );
    }
    else {
      obj = tmp3;
    }
  }

  if( dstErr ){
    *dstErr = errNum;
  }
  return obj;
}
Esempio n. 21
0
void warpSetSignalDomain(
  WlzIVertex2	*selVtx)
{
  WlzErrorNum	errNum=WLZ_ERR_NONE;
  WlzPixelV	threshV, threshV1;
  WlzObject	*obj, *obj1;
  WlzUInt	combineMode;

  /* image processing sequence */
  if( warpGlobals.sgnlThreshObj == NULL ){
    warpSetSignalThreshObj();
  }
  if( warpGlobals.sgnlThreshObj ){
    obj1 = WlzAssignObject(warpGlobals.sgnlThreshObj, &errNum);
  }
  else {
    return;
  }

  /* threshold the resultant image */
  if( errNum == WLZ_ERR_NONE ){
    switch( warpGlobals.thresholdType ){
    case WLZ_RGBA_THRESH_NONE:
      break;

    case WLZ_RGBA_THRESH_SINGLE:
      threshV.type = WLZ_GREY_INT;
      threshV.v.inv = warpGlobals.threshRangeLow;
      if( obj1 ){
	/* clear signal object */
	if( warpGlobals.sgnlObj ){
	  WlzFreeObj(warpGlobals.sgnlObj);
	}
	  
	if((obj = WlzThreshold(obj1, threshV, WLZ_THRESH_HIGH, &errNum)) && (WlzVolume(obj, &errNum) > 0)){
	  obj = WlzAssignObject(obj, &errNum);
	  WlzFreeObj(obj1);
	  threshV.v.inv = warpGlobals.threshRangeHigh + 1;
	  if((obj1 = WlzThreshold(obj, threshV, WLZ_THRESH_LOW, &errNum)) && (WlzVolume(obj1, &errNum) > 0)){
	    warpGlobals.sgnlObj = WlzAssignObject(obj1, &errNum);
	  }
	  else {
	    if( obj1 ){
	      WlzFreeObj(obj1);
	    }
	    warpGlobals.sgnlObj = NULL;
	  }
	  WlzFreeObj(obj);
	}
	else {
	  if( obj ) {
	    WlzFreeObj(obj);
	  }
	  WlzFreeObj(obj1);
	  warpGlobals.sgnlObj = NULL;
	}
      }
      break;

    case WLZ_RGBA_THRESH_MULTI:
      /* clear signal object */
      if( warpGlobals.sgnlObj ){
	WlzFreeObj(warpGlobals.sgnlObj);
      }

      /* set the thresholds and combine mode */
      threshV.type = WLZ_GREY_RGBA;
      WLZ_RGBA_RGBA_SET(threshV.v.rgbv,
			warpGlobals.threshRangeRGBLow[0],
			warpGlobals.threshRangeRGBLow[1],
			warpGlobals.threshRangeRGBLow[2],
			255);
      threshV1.type = WLZ_GREY_RGBA;
      WLZ_RGBA_RGBA_SET(threshV1.v.rgbv,
			warpGlobals.threshRangeRGBHigh[0],
			warpGlobals.threshRangeRGBHigh[1],
			warpGlobals.threshRangeRGBHigh[2],
			255);
      WLZ_RGBA_RGBA_SET(combineMode,
			WLZ_BO_AND, WLZ_BO_AND, WLZ_BO_AND, 255);

      /* use multi-threshold */
      if((obj = WlzRGBAMultiThreshold(obj1, threshV, threshV1,
				      combineMode, &errNum))){
	if( WlzIsEmpty(obj, &errNum) ){
	    WlzFreeObj(obj);
	    warpGlobals.sgnlObj = NULL;
	} else {
	    warpGlobals.sgnlObj = WlzAssignObject(obj, &errNum);
	}
      }
      else {
	warpGlobals.sgnlObj = NULL;
      }
      WlzFreeObj(obj1);
      break;

    case WLZ_RGBA_THRESH_BOX:
      /* clear signal object */
      if( warpGlobals.sgnlObj ){
	WlzFreeObj(warpGlobals.sgnlObj);
      }

      /* use box-threshold */
      if((obj = WlzRGBABoxThreshold(obj1,
				    warpGlobals.lowRGBPoint,
				    warpGlobals.highRGBPoint,
				    &errNum))){
	if( WlzIsEmpty(obj, &errNum) ){
	    WlzFreeObj(obj);
	    warpGlobals.sgnlObj = NULL;
	} else {
	    warpGlobals.sgnlObj = WlzAssignObject(obj, &errNum);
	}
      }
      else {
	warpGlobals.sgnlObj = NULL;
      }
      WlzFreeObj(obj1);	  
      break;

    case WLZ_RGBA_THRESH_SLICE:
      /* clear signal object */
      if( warpGlobals.sgnlObj ){
	WlzFreeObj(warpGlobals.sgnlObj);
      }

      /* use slice-threshold */
      if((obj = WlzRGBASliceThreshold(obj1,
				      warpGlobals.lowRGBPoint,
				      warpGlobals.highRGBPoint,
				      &errNum))){
	if( WlzIsEmpty(obj, &errNum) ){
	    WlzFreeObj(obj);
	    warpGlobals.sgnlObj = NULL;
	} else {
	    warpGlobals.sgnlObj = WlzAssignObject(obj, &errNum);
	}
      }
      else {
	warpGlobals.sgnlObj = NULL;
      }
      WlzFreeObj(obj1);	  
      break;

    case WLZ_RGBA_THRESH_SPHERE:
      /* clear signal object */
      if( warpGlobals.sgnlObj ){
	WlzFreeObj(warpGlobals.sgnlObj);
      }

      /* use Ellipsoid-threshold */
      if((obj = WlzRGBAEllipsoidThreshold(obj1,
					  warpGlobals.lowRGBPoint,
					  warpGlobals.highRGBPoint,
					  warpGlobals.colorEllipseEcc,
					  &errNum))){
	if( WlzIsEmpty(obj, &errNum) ){
	    WlzFreeObj(obj);
	    warpGlobals.sgnlObj = NULL;
	} else {
	    warpGlobals.sgnlObj = WlzAssignObject(obj, &errNum);
	}
      }
      else {
	warpGlobals.sgnlObj = NULL;
      }
      WlzFreeObj(obj1);	  
      break;

    default:
      errNum = WLZ_ERR_PARAM_DATA;
      if( obj1 ){
	WlzFreeObj(obj1);
      }
      if( warpGlobals.sgnlObj ){
	WlzFreeObj(warpGlobals.sgnlObj);
	warpGlobals.sgnlObj = NULL;
      }
      break;
    }
  }

  /* check for local mode */
  if( warpGlobals.sgnlObj && !warpGlobals.globalThreshFlg ){
    if( selVtx != NULL ){
      warpGlobals.globalThreshVtx = *selVtx;
    }
    /* extract a local domain if the vertex is sensible */
    if( warpGlobals.globalThreshVtx.vtX != -10000 ){
      WlzObject	**objs=NULL;
      int	i, numObjs;
      double	x, y;
      obj1 = NULL;
      x = warpGlobals.globalThreshVtx.vtX;
      y = warpGlobals.globalThreshVtx.vtY;
      errNum = WlzLabel(warpGlobals.sgnlObj, &numObjs, &objs, 8192, 0,
			WLZ_4_CONNECTED);
      if( (errNum == WLZ_ERR_INT_DATA) && (numObjs == 8192) ){
	WlzObject	*tmpObj1, *tmpObj2;
	WlzDomain	domain;
	WlzValues	values;

	/* try again, smaller domain */
	for(i=0; i < numObjs; i++){
	  WlzFreeObj( objs[i] );
	}
	AlcFree((void *) objs);
	objs = NULL;
	numObjs = 0;
	domain.i = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_RECT,
					 y - 80, y + 80,
					 x - 80, x + 80, &errNum);
	values.core = NULL;
	if((tmpObj1 = WlzMakeMain(warpGlobals.sgnlObj->type, domain, values,
				  NULL, NULL, &errNum))){
	  if((tmpObj2 = WlzIntersect2(warpGlobals.sgnlObj, tmpObj1, &errNum))){
	    tmpObj2->values = WlzAssignValues(warpGlobals.sgnlObj->values, NULL);
	    errNum = WlzLabel(warpGlobals.sgnlObj, &numObjs, &objs, 8192, 0,
			      WLZ_4_CONNECTED);
	    WlzFreeObj(tmpObj2);
	    if((errNum == WLZ_ERR_INT_DATA) && (numObjs == 8192) ){
	      errNum = WLZ_ERR_NONE;
	    }
	  }
	  WlzFreeObj(tmpObj1);
	}
	
      }
      if( errNum == WLZ_ERR_NONE ){

	for(i=0; i < numObjs; i++){
	  if( WlzInsideDomain( objs[i], 0.0, y, x, NULL ) ){
	    obj1 = WlzMakeMain(objs[i]->type,
			       objs[i]->domain,
			       objs[i]->values,
			       NULL, NULL, NULL);
	    obj1 = WlzAssignObject(obj1, NULL);
	  }
	  WlzFreeObj( objs[i] );
	}
	AlcFree((void *) objs);
      }
      if( obj1 ){
	WlzFreeObj(warpGlobals.sgnlObj);
	warpGlobals.sgnlObj = obj1;
      }
    }
    else {
      WlzFreeObj(warpGlobals.sgnlObj);
      warpGlobals.sgnlObj = NULL;
    }
  }

  /* check for increment mode */
  if( warpGlobals.incrThreshFlg && sgnlIncrObj() ){
    if( warpGlobals.sgnlObj ){
      if((obj1 = WlzUnion2(warpGlobals.sgnlObj, sgnlIncrObj(),
			   &errNum))){
	WlzFreeObj(warpGlobals.sgnlObj);
	warpGlobals.sgnlObj = WlzAssignObject(obj1, &errNum);
      }
    }
    else {
      warpGlobals.sgnlObj = WlzAssignObject(sgnlIncrObj(),
					    &errNum);
    }
  }

  if( errNum != WLZ_ERR_NONE ){
    MAPaintReportWlzError(globals.topl, "warpSetSignalDomain", errNum);
  }
  return;
}
/*!
* \return	New woolz object or NULL on error.
* \ingroup	WlzArithmetic
* \brief	Scales the values of the given 3D Woolz object so that
* 		\f$v_{new} = m v_{given} + a.\f$ The input object is known
* 		to be a valid 3D domain object with grey values.
* \param	iObj			Given object.
* \param	m			Value to multiply object values by.
* \param	a			Value to add to product.
* \param	rGType			Required grey type for returned object.
* \param	dstErr			Destination error pointer, may be NULL.
*/
static WlzObject *WlzScalarMulAdd3D(WlzObject *iObj, WlzPixelV m, WlzPixelV a,
				WlzGreyType rGType, WlzErrorNum *dstErr)
{
  WlzValues	rValues;
  WlzObjectType rVType;
  WlzPixelV	bgdV;
  WlzObject	*rObj = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  rValues.core = NULL;
  bgdV = WlzGetBackground(iObj, &errNum);
  if(errNum == WLZ_ERR_NONE)
  {
    rVType = WlzGreyTableType(WLZ_GREY_TAB_RAGR, rGType, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    rValues.vox = WlzNewValuesVox(iObj, rVType, bgdV, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    int		idP,
    		plMin,
    		plMax;
    WlzPlaneDomain *iPDom;
    WlzVoxelValues *iVox,
    		*rVox;

    iPDom = iObj->domain.p;
    iVox = iObj->values.vox;
    rVox = rValues.vox;
    plMin = iPDom->plane1;
    plMax = iPDom->lastpl;
#ifdef _OPENMP
#pragma omp parallel for
#endif
    for(idP = plMin; idP <= plMax; ++idP)
    {
      WlzErrorNum errNum2D = WLZ_ERR_NONE;

      if(errNum == WLZ_ERR_NONE)
      {
	int	      idO;
	WlzDomain *iDom2D;
	WlzValues *iVal2D,
		  *rVal2D;

	idO = idP - iPDom->plane1;
	iDom2D = iPDom->domains + idO;
	iVal2D = iVox->values + idO;
	rVal2D = rVox->values + idO;
	if(((*iDom2D).core != NULL) && ((*iVal2D).core != NULL) &&
	   ((*rVal2D).core != NULL))
	{
	  WlzObject *iObj2D = NULL,
		    *rObj2D = NULL;
	  
	  if((iObj2D = WlzMakeMain(WLZ_2D_DOMAINOBJ, *iDom2D, *iVal2D,
				   NULL, NULL, &errNum2D)) != NULL)
	  {
	    rObj2D = WlzScalarMulAdd2D(iObj2D, m, a, rGType, &errNum2D);
	  }
	  if(errNum2D == WLZ_ERR_NONE)
	  {
	    *rVal2D = WlzAssignValues(rObj2D->values, NULL);
	  }
	  (void )WlzFreeObj(iObj2D);
	  (void )WlzFreeObj(rObj2D);
	}
      }
      if(errNum2D != WLZ_ERR_NONE)
      {
#ifdef _OPENMP
#pragma omp critical
	{
#endif
	  if(errNum == WLZ_ERR_NONE)
	  {
	    errNum = errNum2D;
	  }
#ifdef _OPENMP
	}
#endif
      }
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    rObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, iObj->domain, rValues,
    		       iObj->plist, iObj->assoc, &errNum);
  }
  if(errNum != WLZ_ERR_NONE)
  {
    if(rObj == NULL)
    {
      (void )WlzFreeVoxelValueTb(rValues.vox);
    }
    else
    {
      (void )WlzFreeObj(rObj);
      rObj = NULL;
    }
  }
  if(dstErr != NULL)
  {
    *dstErr = errNum;
  }
  return(rObj);
}
Esempio n. 23
0
void referenceFileListCb(
  Widget	w,
  XtPointer	client_data,
  XtPointer	call_data)
{
  HGU_XmFileListCallbackStruct	*cbs=
    (HGU_XmFileListCallbackStruct *) client_data;
  WlzObject	*obj;
  Widget	cascade;
  WlzErrorNum	errNum=WLZ_ERR_NONE;

  HGU_XmSetHourGlassCursor(globals.topl);
  if( cbs == NULL ){
    /* clear list selection */
    HGU_XmFileListClearList(globals.fileList);
    HGU_XmFileListWriteResourceFile(globals.fileList,
				    globals.resourceFile);
    if((cascade = XtNameToWidget(globals.topl,
				 "*file_menu*_pulldown*Recent"))){
      HGU_XmFileListResetMenu(globals.fileList, cascade, referenceFileListCb);
    }
  }
  else if((obj = HGU_XmFileListReadObject(w, cbs, &errNum))){
    WlzDomain	domain;
    WlzValues	values;
    WlzObject	*newObj;

    switch( obj->type ){

    case WLZ_2D_DOMAINOBJ:
      if((domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, 0, 0,
					obj->domain.i->line1,
					obj->domain.i->lastln,
					obj->domain.i->kol1,
					obj->domain.i->lastkl,
					&errNum))){
	domain.p->domains[0] = WlzAssignDomain(obj->domain, NULL);
	if((values.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY,
					     0, 0, WlzGetBackground(obj, NULL),
					     NULL, &errNum))){
	  values.vox->values[0] = WlzAssignValues(obj->values, NULL);
	  newObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values,
			       NULL, NULL, NULL);
	  WlzFreeObj(obj);
	  obj = newObj;
	}
      }
      globals.origObjType = WLZ_2D_DOMAINOBJ;
      break;

    case WLZ_3D_DOMAINOBJ:
      globals.origObjType = WLZ_3D_DOMAINOBJ;
      break;

    default:
      HGU_XmUserError(globals.topl,
		      "Read Reference Object:\n"
		      "    The reference object must be a 2- or 3-D\n"
		      "    grey-level image. Please select an alternate\n"
		      "    object",
		      XmDIALOG_FULL_APPLICATION_MODAL);
      WlzFreeObj( obj );
      /* set hour glass cursor */
      HGU_XmUnsetHourGlassCursor(globals.topl);
      return;
    }
    MAPaintLogData("ReferenceFile", refFileList[0], 0, NULL);
    install_paint_reference_object( obj );

    /* set the title of the top-level window */
    set_topl_title(cbs->file);
    globals.file = AlcStrDup(cbs->file);
    globals.origObjExtType = cbs->format;

    /* add to the file list and write file */
    HGU_XmFileListAddFile(globals.fileList, cbs->file, cbs->format);
    HGU_XmFileListWriteResourceFile(globals.fileList,
				    globals.resourceFile);
    if((cascade = XtNameToWidget(globals.topl,
				 "*file_menu*_pulldown*Recent"))){
      HGU_XmFileListResetMenu(globals.fileList, cascade, referenceFileListCb);
    }
  }

  HGU_XmUnsetHourGlassCursor(globals.topl);

  if( errNum != WLZ_ERR_NONE ){
    MAPaintReportWlzError(globals.topl, "ReferenceFileListCb", errNum);
  }
  return;
}
Esempio n. 24
0
static WlzObject *WlzSelect1InN(
  WlzObject	*obj,
  int 		first_pl,
  int 		last_pl,
  int 		step,
  WlzErrorNum	*dstErr)
{
  WlzObject	*nobj=NULL;
  int		p, new_p, new_plane1, new_lastpl;
  WlzDomain	domain;
  WlzValues	values;
  WlzErrorNum	errNum=WLZ_ERR_NONE;

  /* check the object */
  if( obj == NULL ){
    errNum = WLZ_ERR_OBJECT_NULL;
  }

  if( errNum == WLZ_ERR_NONE ){
    domain.core = NULL;
    values.core = NULL;
    switch( obj->type ){

    case WLZ_3D_DOMAINOBJ:
      if( obj->domain.core == NULL ){
	errNum = WLZ_ERR_DOMAIN_NULL;
	break;
      }
      if( obj->domain.core->type == WLZ_EMPTY_DOMAIN ){
	return WlzMakeEmpty(dstErr);
      }
      break;

    case WLZ_EMPTY_OBJ:
      return WlzMakeEmpty(dstErr);

    default:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;
    }
  }

  /* check the parameters */
  if( errNum == WLZ_ERR_NONE ){
    if( first_pl > last_pl ){
      errNum = WLZ_ERR_PARAM_DATA;
    }
    else if( step <= 0 ){
      errNum = WLZ_ERR_PARAM_DATA;
    }
    /* check for empty object */
    else if((first_pl > obj->domain.p->lastpl) ||
	    (last_pl < obj->domain.p->plane1) ){
      return WlzMakeEmpty(dstErr);
    }
  }

  /* make a new planedomain and voxel table as required */
  if( errNum == WLZ_ERR_NONE ){
    for(p=first_pl; p <= last_pl; p += step){
      if( p >= obj->domain.p->plane1 ){
	new_plane1 = p / step;
	break;
      }
    }
    for(;p <= last_pl; p += step){
      if( p > obj->domain.p->lastpl ){
	break;
      }
      new_lastpl = p / step;
    }

    if((domain.p = WlzMakePlaneDomain(obj->domain.p->type,
				      new_plane1, new_lastpl,
				      obj->domain.p->line1,
				      obj->domain.p->lastln,
				      obj->domain.p->kol1,
				      obj->domain.p->lastkl,
				      &errNum)) != NULL){
      domain.p->voxel_size[0] = obj->domain.p->voxel_size[0];
      domain.p->voxel_size[1] = obj->domain.p->voxel_size[1];
      domain.p->voxel_size[2] = step * (obj->domain.p->voxel_size[2]);

      if( obj->values.core != NULL ){
	if( (values.vox =
	     WlzMakeVoxelValueTb(obj->values.vox->type,
				 new_plane1, new_lastpl,
				 obj->values.vox->bckgrnd,
				 obj, &errNum)) == NULL ){
	  (void) WlzFreePlaneDomain(domain.p);
	}
      }
    }
  }

  /* set domain and voxel values */
  if( errNum == WLZ_ERR_NONE ){
    for(p=first_pl; p <= last_pl; p += step){
      if( p < obj->domain.p->plane1 ){
	continue;
      }
      if( p > obj->domain.p->lastpl ){
	break;
      }
      new_p = (p / step) - domain.p->plane1;
      domain.p->domains[new_p] =
	WlzAssignDomain(obj->domain.p->domains[p - obj->domain.p->plane1],
			NULL);
      if( obj->values.core != NULL ){
	values.vox->values[new_p] =
	  WlzAssignValues(	
	    obj->values.vox->values[p - obj->domain.p->plane1], NULL);
      }
    }
  }

  if( errNum == WLZ_ERR_NONE ){
    nobj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values,
		       NULL, NULL, &errNum);
  }

  if( dstErr ){
    *dstErr = errNum;
  }
  return nobj;
}
Esempio n. 25
0
/*!
* \return	New object or NULL on error.
* \ingroup	WlzValuesUtils
* \brief 	Transfers grey values from the source object to the
*               destination object within the intersection of the source
*               and destination. Grey values within the destination
*               object outside of the source object are unchanged.
*               It is an error if either object has a different dimension
*               or grey value type, except for when either is an empty
*               object.
* \param	dObj			Destination object which may be
* 					empty, but otherwise should be of the
* 					same dimension as the source object
* 					with valid values..
* \param	sObj			Source object which if not empty must
* 					have both a valid domain and valid
* 					values.
* \param	inplace			Overwrite the destination object's
* 					values if non zero.
* \param	dstErr			Destination error pointer, may be NULL.
*/
WlzObject			*WlzGreyTransfer(
				  WlzObject *dObj,
				  WlzObject *sObj,
				  int inplace,
				  WlzErrorNum *dstErr)
{
  WlzObject	*rObj = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  if((dObj == NULL) || (sObj == NULL))
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if(WlzIsEmpty(dObj, NULL))
  {
    rObj = WlzMakeEmpty(&errNum);
  }
  else if(WlzIsEmpty(sObj, NULL))
  {
    rObj = WlzMakeMain(dObj->type, dObj->domain, dObj->values,
                       dObj->plist, NULL, &errNum);
  }
  else if(dObj->type != sObj->type)
  {
    errNum = WLZ_ERR_OBJECT_TYPE;
  }
  else if((dObj->domain.core == NULL) || (sObj->domain.core == NULL))
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if(sObj->values.core == NULL)
  {
    errNum = WLZ_ERR_VALUES_NULL;
  }
  else
  {
    switch(sObj->type)
    {
      case WLZ_2D_DOMAINOBJ:
      case WLZ_3D_DOMAINOBJ: /* FALLTHROUGH */
        {
	  WlzObject	*rIObj = NULL;

	  rIObj = WlzIntersect2(dObj, sObj, &errNum);
	  if((errNum == WLZ_ERR_NONE) && (WlzIsEmpty(rIObj, NULL) == 0))
	  {
	    rObj = (inplace)?
		   WlzMakeMain(dObj->type, dObj->domain, dObj->values,
			       dObj->plist, NULL, &errNum):
		   WlzCopyObject(dObj, &errNum);
	    if(errNum == WLZ_ERR_NONE)
	    {
	      /* If the destination object does not have values then
	       * create them to match the domain of the destination
	       * object. */
	      if((sObj->values.core != NULL) && (rObj->values.core == NULL))
	      {
		WlzPixelV bgdV;
		WlzGreyType gType;
		WlzObjectType gTT;
		WlzValues	newVal;

		newVal.core = NULL;
		bgdV = WlzGetBackground(sObj, &errNum);
		if(errNum == WLZ_ERR_NONE)
		{
		  gType = WlzGreyTypeFromObj(sObj, &errNum);
		}
		if(errNum == WLZ_ERR_NONE)
		{
		  gTT = WlzGreyTableType(WLZ_GREY_TAB_RAGR, gType, NULL);
		  if(rObj->type == WLZ_2D_DOMAINOBJ)
		  {
		    newVal.v = WlzNewValueTb(rObj, gTT, bgdV, &errNum);
		  }
		  else /* rObj->type == WLZ_3D_DOMAINOBJ */
		  {
		    newVal.vox = WlzNewValuesVox(rObj, gTT, bgdV, &errNum);
		  }
		}
		if(errNum == WLZ_ERR_NONE)
		{
		  rObj->values = WlzAssignValues(newVal, NULL);
		}
		if(errNum == WLZ_ERR_NONE)
		{
		  errNum = WlzGreySetValue(rObj, bgdV);
		}
	      }
	    }
	    if(errNum == WLZ_ERR_NONE)
	    {
	      if(sObj->type == WLZ_2D_DOMAINOBJ)
	      {
		WlzObject *sIObj;

		rIObj->values = WlzAssignValues(rObj->values, NULL);
		sIObj = WlzMakeMain(WLZ_2D_DOMAINOBJ,
				    rIObj->domain, sObj->values,
				    NULL, NULL, &errNum);
		if(errNum == WLZ_ERR_NONE)
		{
		  errNum = WlzGreyTransfer2D(rIObj, sIObj);
		}
		(void )WlzFreeObj(sIObj);
	      }
	      else /* sObj->type == WLZ_3D_DOMAINOBJ */
	      {
		int	p,
			  rTiled,
			  sTiled,
			  nPlanes;

		rTiled = WlzGreyTableIsTiled(rObj->values.core->type);
		sTiled = WlzGreyTableIsTiled(sObj->values.core->type);
		nPlanes = rIObj->domain.p->lastpl - rIObj->domain.p->plane1 + 1;
#ifdef _OPENMP
#pragma omp parallel for
#endif
		for(p = 0; p < nPlanes; ++p)
		{
		  if(errNum == WLZ_ERR_NONE)
		  {
		    int	     pln;
		    WlzDomain  dom;
		    WlzValues  val;
		    WlzObject  *rIObj2D = NULL,
			       *sIObj2D = NULL;
		    WlzErrorNum errNum2D = WLZ_ERR_NONE;

		    pln = p + rIObj->domain.p->plane1;
		    dom = rIObj->domain.p->domains[p];
		    val = (rTiled)?
			  rObj->values:
			  rObj->values.vox->values[pln -
						   rObj->values.vox->plane1];
		    rIObj2D = WlzMakeMain(WLZ_2D_DOMAINOBJ,
					  dom, val, NULL, NULL, &errNum2D);
		    if(errNum2D == WLZ_ERR_NONE)
		    {
		      val = (sTiled)?
			    sObj->values:
			    sObj->values.vox->values[pln -
						     sObj->values.vox->plane1];
		      sIObj2D = WlzMakeMain(WLZ_2D_DOMAINOBJ,
					    dom, val, NULL, NULL, &errNum2D);
		    }
		    if(errNum2D == WLZ_ERR_NONE)
		    {
		      errNum2D = WlzGreyTransfer2D(rIObj2D, sIObj2D);
		    }
		    (void )WlzFreeObj(rIObj2D);
		    (void )WlzFreeObj(sIObj2D);
#ifdef _OPENMP
#pragma omp critical
		    {
#endif
		      if((errNum == WLZ_ERR_NONE) && (errNum2D != WLZ_ERR_NONE))
		      {
			errNum = errNum2D;
		      }
#ifdef _OPENMP
		    }
#endif
		  }
		}
	      }
	    }
	  }
	  (void )WlzFreeObj(rIObj);
	}
	break;
      default:
	errNum = WLZ_ERR_OBJECT_TYPE;
        break;
    }
  }
  if(errNum != WLZ_ERR_NONE)
  {
    WlzFreeObj(rObj);
    rObj = NULL;
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(rObj);
}
Esempio n. 26
0
double WlzMixtureValue(
  WlzObject	*obj1,
  WlzObject	*obj2,
  int		numCatRows,
  int		numCatCols,
  double	**mixing,
  double	**contrib,
  WlzErrorNum	*dstErr)
{
  double	val, con;
  WlzObject	*tmpObj, *tmpObj1, *tmpObj2;
  WlzIntervalWSpace	iwsp;
  WlzGreyWSpace		gwsp;
  WlzGreyP		gptr;
  WlzGreyValueWSpace	*gVWSp;
  WlzPixelV		minP, maxP;
  int		i;
  WlzErrorNum	errNum=WLZ_ERR_NONE;

  /* objects must be same type with grey-values */
  if( (obj1 == NULL) || (obj2 == NULL) ){
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else {
    switch( obj1->type ){
    case WLZ_2D_DOMAINOBJ:
      if( obj2->type != obj1->type ){
	errNum = WLZ_ERR_OBJECT_TYPE;
      }
      else {
	if((obj1->values.core == NULL) || (obj2->values.core == NULL)){
	  errNum = WLZ_ERR_VALUES_NULL;
	}
	else {
	  /* convert to int and check range */
	  if((tmpObj1 = WlzConvertPix(obj1, WLZ_GREY_INT, &errNum)) != NULL){
	    errNum = WlzGreyRange(tmpObj1, &minP, &maxP);
	    if( errNum == WLZ_ERR_NONE ){
	      if((minP.v.inv < 1) || (minP.v.inv > numCatRows) ||
		 (maxP.v.inv < 1) || (maxP.v.inv > numCatRows)){
		errNum = WLZ_ERR_OBJECT_DATA;
		WlzFreeObj(tmpObj1);
	      }
	    }
	    else {
	      WlzFreeObj(tmpObj1);
	    }
	  }
	  if((errNum == WLZ_ERR_NONE) &&
	     (tmpObj2 = WlzConvertPix(obj2, WLZ_GREY_INT, &errNum)) ){
	    errNum = WlzGreyRange(tmpObj2, &minP, &maxP);
	    if( errNum == WLZ_ERR_NONE ){
	      if((minP.v.inv < 1) || (minP.v.inv > numCatCols) ||
		 (maxP.v.inv < 1) || (maxP.v.inv > numCatCols)){
		errNum = WLZ_ERR_OBJECT_DATA;
		WlzFreeObj(tmpObj1);
		WlzFreeObj(tmpObj2);
	      }
	    }
	    else {
	      WlzFreeObj(tmpObj1);
	      WlzFreeObj(tmpObj2);
	    }
	  }
	}
      }
      break;

    case WLZ_3D_DOMAINOBJ:
    default:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;
    }
  }

  /* get the intersection region */
  if( errNum == WLZ_ERR_NONE ){
    if((tmpObj = WlzIntersect2(tmpObj1, tmpObj2, &errNum)) != NULL){
      tmpObj->values = WlzAssignValues(tmpObj1->values, &errNum);
    }
    else {
      WlzFreeObj(tmpObj1);
      WlzFreeObj(tmpObj2);
    }
  }

  /* now calculate the mixture value */
  if( errNum == WLZ_ERR_NONE ){
    errNum = WlzInitGreyScan(tmpObj, &iwsp, &gwsp);
    gVWSp = WlzGreyValueMakeWSp(tmpObj2, &errNum);
    val = 0.0;
    con = 0.0;
    while((errNum == WLZ_ERR_NONE) &&
	  (errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE ){

      gptr = gwsp.u_grintptr;
      for (i=0; i<iwsp.colrmn; i++, gptr.inp++){
	WlzGreyValueGet(gVWSp, 0, iwsp.linpos, iwsp.colpos+i);
	val += mixing[(*gptr.inp)-1][gVWSp->gVal[0].inv-1];
	con += contrib[(*gptr.inp)-1][gVWSp->gVal[0].inv-1];
      }
    }
    if( errNum == WLZ_ERR_EOO ){
      errNum = WLZ_ERR_NONE;
    }
    WlzGreyValueFreeWSp(gVWSp);
    WlzFreeObj(tmpObj);
    WlzFreeObj(tmpObj1);
    WlzFreeObj(tmpObj2);
  }

  if( dstErr ){
    *dstErr = errNum;
  }
  if( con > 0.0 ){
    return val/con;
  }
  else {
    return 0.0;
  }
}
Esempio n. 27
0
/*!
* \return	New 3D object.
* \ingroup	WlzAllocation
* \brief	Constructs a 3D domain object from 2D domain objects. Each
*		2D object is assigned in turn to the 3D object no domains
*		or values are copied. An empty can be specified by
*		setting the 2D object to NULL. Either all or none of
*		the 2D objects must have values. When the 2D objects
*		have values then the background value of the first 2D
*		object is set to be the background value of the 3D object.
* \param	nObjs			Number of objects.
* \param	objs			The 2D objects, the first of which
*					MUST not be NULL.
* \param	plane1			The plane coordinate of the first
*					2D object.
* \param	xSz			Column voxel size.
* \param	ySz			Line voxel size.
* \param	zSz			Plane voxel size.
* \param	dstErr			Destination error pointer, may be NULL.
*/
WlzObject	*WlzConstruct3DObjFromObj(int nObjs, WlzObject **objs,
					 int plane1,
					 float xSz, float ySz, float zSz,
					 WlzErrorNum *dstErr)
{
  int		idx,
  		lastpl;
  WlzDomain	dom3D;
  WlzValues	val3D;
  WlzObject	*obj2D,
  		*obj3D = NULL;
  WlzPixelV	bgd;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  dom3D.core = NULL;
  val3D.core = NULL;
  lastpl = plane1 + nObjs - 1;
  if((nObjs <= 0) || (objs == NULL))
  {
    errNum = WLZ_ERR_PARAM_NULL;
  }
  else if((obj2D = *objs) == NULL)
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else
  {
    switch(obj2D->type)
    {
      case WLZ_EMPTY_OBJ:
	break;
      case WLZ_2D_DOMAINOBJ:
	if(obj2D->domain.core == NULL)
	{
	  errNum = WLZ_ERR_DOMAIN_NULL;
	}
	break;
      default:
	errNum = WLZ_ERR_OBJECT_TYPE;
	break;
    }
  }
  /* Make a plane domain, set column and line bounds later. */
  if(errNum == WLZ_ERR_NONE)
  {
    dom3D.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN,
    				 plane1, lastpl,
				 0, 1, 0, 1, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    dom3D.p->voxel_size[0] = xSz;
    dom3D.p->voxel_size[1] = ySz;
    dom3D.p->voxel_size[2] = zSz;
  }
  /* Make a voxel value table. */
  if(errNum == WLZ_ERR_NONE)
  {
    if(obj2D->values.core)
    {
      bgd = WlzGetBackground(obj2D, &errNum);
      if(errNum == WLZ_ERR_NONE)
      {
	val3D.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY,
					plane1, lastpl, bgd, NULL, &errNum);
      }
    }				    
  }
  for(idx = 0; (errNum == WLZ_ERR_NONE) && (idx < nObjs); ++idx)
  {
    obj2D = *(objs + idx);
    if(obj2D)
    {
      switch(obj2D->type)
      {
	case WLZ_EMPTY_OBJ:
	  break;
	case WLZ_2D_DOMAINOBJ:
	  if(obj2D->domain.core == NULL)
	  {
	    errNum = WLZ_ERR_DOMAIN_NULL;
	  }
	  break;
	default:
	  errNum = WLZ_ERR_OBJECT_TYPE;
	  break;
      }
      if(errNum == WLZ_ERR_NONE)
      {
	*(dom3D.p->domains + idx) = WlzAssignDomain(obj2D->domain, NULL);
	if(val3D.core)
	{
	  if((obj2D->domain.core != NULL) && (obj2D->values.core == NULL))
	  {
	    errNum = WLZ_ERR_VALUES_NULL;
	  }
	  else
	  {
	    *(val3D.vox->values + idx) = WlzAssignValues(obj2D->values, NULL);
	  }
	}
      }
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    errNum = WlzStandardPlaneDomain(dom3D.p, val3D.vox);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    obj3D = WlzMakeMain(WLZ_3D_DOMAINOBJ, dom3D, val3D, NULL, NULL, &errNum);
  }
  if(errNum != WLZ_ERR_NONE)
  {
    if(dom3D.core)
    {
      (void )WlzFreeDomain(dom3D);
    }
    if(val3D.core)
    {
      (void )WlzFreeValues(val3D);
    }
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(obj3D);
}
Esempio n. 28
0
/*!
* \return	New Woolz object.
* \ingroup	WlzAllocation
* \brief	Creates a new or adds to an existing 3D spatial domain
*  		object using a rectangular buffer of values to a single
*  		plane of the given current object (which may be NULL or
*  		empty if the object is to be created).
* 		The returned object will share domains and values of
* 		planes other than the given plane with the current object.
* \param	cObj			Given current object.
* \param	og			Origin of rectangular buffer.
* \param	sz			Buffer size (note 2D).
* \param	gType			Grey type which must be consistent
* 					with the current object (if it is
* 					valid) and the buffer of values.
* \param	bufSz			Number of values in the buffer
* 					(ie sz.vtX * sz.vtY).
* \param	bufP			Given buffer of values.
* \param	dstErr			Destination error pointer, may be NULL.
*/
WlzObject	*WlzBuildObj3(WlzObject *cObj,
                          WlzIVertex3 og, WlzIVertex2 sz,
                          WlzGreyType gType,
                          int bufSz, WlzGreyP bufP,
                          WlzErrorNum *dstErr)
{
    int		nPlnReq = 1;
    WlzDomain	cDom,
                nDom;
    WlzValues	cVal,
                nVal;
    WlzObject	*nObj = NULL;
    WlzErrorNum	errNum = WLZ_ERR_NONE;

    cDom.core = NULL;
    nDom.core = NULL;
    cVal.core = NULL;
    nVal.core = NULL;
    if(cObj)
    {
        WlzGreyType cGType = WLZ_GREY_ERROR;;

        switch(cObj->type)
        {
        case WLZ_EMPTY_OBJ:
            cObj = NULL;
            break;
        case WLZ_3D_DOMAINOBJ:
            if(cObj->domain.core == NULL)
            {
                errNum = WLZ_ERR_DOMAIN_NULL;
            }
            else if(cObj->values.core == NULL)
            {
                errNum = WLZ_ERR_VALUES_NULL;
            }
            else
            {
                cDom = cObj->domain;
                cVal = cObj->values;
                cGType = WlzGreyTypeFromObj(cObj, &errNum);
            }
            if((errNum == WLZ_ERR_NONE) && (cGType != gType))
            {
                errNum = WLZ_ERR_GREY_TYPE;
            }
            break;
        default:
            errNum = WLZ_ERR_OBJECT_TYPE;
            break;
        }
    }
    /* Create a new object with new plane domain and voxel values. */
    if(errNum == WLZ_ERR_NONE)
    {
        WlzIBox3	nBox;
        WlzPixelV	bgdV;
        float	vxSz[3];

        nBox.xMin = og.vtX;
        nBox.yMin = og.vtY;
        nBox.zMin = og.vtZ;
        nBox.xMax = og.vtX + sz.vtX - 1;
        nBox.yMax = og.vtY + sz.vtY - 1;
        nBox.zMax = og.vtZ;
        if(cObj)
        {
            nPlnReq = (og.vtZ < cDom.p->plane1) ||
                      (og.vtZ > cDom.p->lastpl) ||
                      ((*(cDom.p->domains + og.vtZ - cDom.p->plane1)).core == NULL);
            nBox.xMin = ALG_MIN(nBox.xMin, cDom.p->kol1);
            nBox.yMin = ALG_MIN(nBox.yMin, cDom.p->line1);
            nBox.zMin = ALG_MIN(nBox.zMin, cDom.p->plane1);
            nBox.xMax = ALG_MAX(nBox.xMax, cDom.p->lastkl);
            nBox.yMax = ALG_MAX(nBox.yMax, cDom.p->lastln);
            nBox.zMax = ALG_MAX(nBox.zMax, cDom.p->lastpl);
            vxSz[0] = cDom.p->voxel_size[0];
            vxSz[1] = cDom.p->voxel_size[1];
            vxSz[2] = cDom.p->voxel_size[2];
            bgdV = WlzGetBackground(cObj, &errNum);
        }
        else
        {
            vxSz[0] = vxSz[1] = vxSz[2] = 1.0f;
            bgdV.type = WLZ_GREY_INT;
            bgdV.v.inv = 0;
        }
        if(errNum == WLZ_ERR_NONE)
        {
            nDom.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN,
                                        nBox.zMin, nBox.zMax,
                                        nBox.yMin, nBox.yMax,
                                        nBox.xMin, nBox.xMax,
                                        &errNum);
        }
        if(errNum == WLZ_ERR_NONE)
        {
            nVal.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY,
                                           nBox.zMin, nBox.zMax,
                                           bgdV, NULL, &errNum);
        }
        if(errNum == WLZ_ERR_NONE)
        {
            nDom.p->voxel_size[0] = vxSz[0];
            nDom.p->voxel_size[1] = vxSz[1];
            nDom.p->voxel_size[2] = vxSz[2];
            nObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, nDom, nVal, NULL, NULL, &errNum);
        }
    }
    /* Set the domain and values on each plane for the new object. */
    if(errNum == WLZ_ERR_NONE)
    {
        int		idZ;

        for(idZ = nDom.p->plane1; idZ <= nDom.p->lastpl; ++idZ)
        {
            int	idP;
            WlzDomain	nDom2;
            WlzValues nVal2;

            nDom2.core = NULL;
            nVal2.core = NULL;
            idP = idZ - nDom.p->plane1;
            if(idZ == og.vtZ)
            {
                /* Plane with buffer. */
                WlzIVertex2 og2,
                            sz2;
                WlzObject   *cObj2 = NULL,
                             *nObj2 = NULL;

                og2.vtX = og.vtX;
                og2.vtY = og.vtY;
                sz2.vtX = sz.vtX;
                sz2.vtY = sz.vtY;
                if(nPlnReq == 0)
                {
                    int	idP;

                    idP = idZ - cDom.p->plane1;
                    cObj2 = WlzMakeMain(WLZ_2D_DOMAINOBJ,
                                        *(cDom.p->domains  + idP),
                                        *(cVal.vox->values + idP),
                                        NULL, NULL, &errNum);
                }
                nObj2 = WlzBuildObj2(cObj2, og2, sz2, gType, bufSz, bufP, &errNum);
                if(errNum == WLZ_ERR_NONE)
                {
                    nDom2 = WlzAssignDomain(nObj2->domain, NULL);
                    nVal2 = WlzAssignValues(nObj2->values, NULL);
                }
                (void )WlzFreeObj(cObj2);
                (void )WlzFreeObj(nObj2);
            }
            else if((idZ >= cDom.p->plane1) && (idZ <= cDom.p->lastpl))
            {
                /* Not buffer plane, but previously existing plane. */
                int	idQ;

                idQ = idZ - cDom.p->plane1;
                nDom2 = WlzAssignDomain(*(cDom.p->domains  + idQ), NULL);
                nVal2 = WlzAssignValues(*(cVal.vox->values + idQ), NULL);
            }
            if(errNum == WLZ_ERR_NONE)
            {
                *(nDom.p->domains  + idP) = nDom2;
                *(nVal.vox->values + idP) = nVal2;
            }
            else
            {
                break;
            }
        }
    }
    if(dstErr)
    {
        *dstErr = errNum;
    }
    return(nObj);
}
Esempio n. 29
0
/*!
* \return	New Woolz object without holes or NULL on error.
* \ingroup	WlzDomainOps
* \brief	Fills the holes in the given object's domain (which are by
* 		definition not connected to the outside). When the given
* 		object's domain has more than one component part, the
* 		object should first be labeled, this function should then be
* 		called for each of the labeled parts and then the union of
* 		the filled domains should be formed.
* \param	srcObj			Given 3D domain object.
* \param	dstErr			Destination error pointer, may be NULL.
*/
WlzObject 			*WlzDomainFill3D(
  				  WlzObject *srcObj,
    				  WlzErrorNum *dstErr)
{
  int		nPln = 0;
  WlzObject	*bndObj = NULL,
  		*filObj = NULL,
  		*gvnObj = NULL,
		*sedObj = NULL,
		*shlObj = NULL;
  WlzPixelV	zeroV;
  WlzValues 	nullVal;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  nullVal.core = NULL;
  zeroV.type = WLZ_GREY_UBYTE;
  zeroV.v.ubv = 0;
  if(srcObj == NULL)
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if(srcObj->type != WLZ_3D_DOMAINOBJ)
  {
    errNum = WLZ_ERR_OBJECT_TYPE;
  }
  else if(srcObj->domain.core == NULL)
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else
  {
    gvnObj = WlzMakeMain(srcObj->type, srcObj->domain, nullVal,
    		         NULL, NULL, &errNum);
  }
  /* Create a then shell 1 voxel thick just inside the given objects's
   * domain. */
  if(errNum == WLZ_ERR_NONE)
  {
    WlzObject	*difObj = NULL;

    difObj = WlzAssignObject(
	     WlzBoundaryDomain(gvnObj, &errNum), NULL);
    if(errNum == WLZ_ERR_NONE)
    {
      WlzIBox3	clipBox;

      /* Clip the dilated shell domain to make sure it stays within the
       * bounding box of the given object then all planes will align. */
      clipBox.xMin = gvnObj->domain.p->kol1;
      clipBox.yMin = gvnObj->domain.p->line1;
      clipBox.zMin = gvnObj->domain.p->plane1;
      clipBox.xMax = gvnObj->domain.p->lastkl;
      clipBox.yMax = gvnObj->domain.p->lastln;
      clipBox.zMax = gvnObj->domain.p->lastpl;
      shlObj = WlzAssignObject(
	       WlzClipObjToBox3D(difObj, clipBox, &errNum), NULL);
    }
    (void )WlzFreeObj(difObj);
  }
  /* Make sure that the bounding box of the thin shell domain fits it and
   * that it's first and last planes have interrvals. */
  if(errNum == WLZ_ERR_NONE)
  {
    errNum = WlzStandardPlaneDomain(shlObj->domain.p, NULL);
  }
  /* Create a value table for the shell object with values set to zero. */
  if(errNum == WLZ_ERR_NONE)
  {
    WlzValues	val;
    WlzObjectType tType;

    tType = WlzGreyTableType(WLZ_GREY_TAB_INTL, WLZ_GREY_UBYTE, NULL);
    val.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY,
				  shlObj->domain.p->plane1,
				  shlObj->domain.p->lastpl,
				  zeroV, NULL, &errNum);
    if(errNum == WLZ_ERR_NONE)
    {
      int	p;

      nPln = shlObj->domain.p->lastpl - shlObj->domain.p->plane1 + 1;
      shlObj->values = WlzAssignValues(val, NULL);
#ifdef _OPENMP
#pragma omp parallel for shared(shlObj)
#endif
      for(p = 0; p < nPln; ++p)
      {
	if(errNum == WLZ_ERR_NONE)
	{
	  WlzDomain dom2;
	  WlzErrorNum errNum2;

	  dom2 = shlObj->domain.p->domains[p];
	  if(dom2.core)
	  {
	    WlzValues val2;
	    WlzObject *shlObj2;
	    shlObj2 = WlzMakeMain(WLZ_2D_DOMAINOBJ, dom2, nullVal, NULL, NULL,
				&errNum2);
	    if(errNum2 == WLZ_ERR_NONE)
	    {
	      val2.i = WlzMakeIntervalValues(tType, shlObj2, zeroV, &errNum2);
	      /* WlzMakeIntervalValues() sets all values to zero. */
	    }
	    if(errNum2 == WLZ_ERR_NONE)                          
	    {
	      shlObj->values.vox->values[p] = WlzAssignValues(val2, NULL);
	    }
	    (void )WlzFreeObj(shlObj2);
	    if(errNum2 == WLZ_ERR_NONE)
	    {
#ifdef _OPENMP
#pragma omp critical
	      {
#endif
		if((errNum == WLZ_ERR_NONE) && (errNum2 != WLZ_ERR_NONE))
		{
		  errNum = errNum2;
		}
#ifdef _OPENMP
	      }
#endif
	    }
	  }
	}
      }
    }
  }
  /* Compute the (plane-wise) boundary list for the given object. */
  if(errNum == WLZ_ERR_NONE)
  {
    bndObj = WlzObjToBoundary(gvnObj, 0, &errNum);
  }
  /* Sweep down through the boundary object setting the values of
   * those voxels in the shell object to a non zero value when they
   * correspond to top level boundaries. */
  if(errNum == WLZ_ERR_NONE)
  {
    int		p;

#ifdef _OPENMP
#pragma omp parallel for shared(bndObj,shlObj)
#endif
    for(p = 0; p < nPln; ++p)
    {
      if(errNum == WLZ_ERR_NONE)
      {
	WlzDomain bDom2;

	bDom2 = bndObj->domain.p->domains[p];
	if(bDom2.core)
	{
	  WlzDomain iDom2;
	  WlzValues iVal2;
	  WlzObject *iObj2 = NULL;
	  WlzGreyValueWSpace *gVWSp = NULL;
	  WlzErrorNum errNum2 = WLZ_ERR_NONE;

	  iDom2 = shlObj->domain.p->domains[p];
	  iVal2 = shlObj->values.vox->values[p];
	  iObj2 = WlzMakeMain(WLZ_2D_DOMAINOBJ, iDom2, iVal2, NULL, NULL,
			      &errNum2);
	  if(errNum == WLZ_ERR_NONE)
	  {
	    gVWSp = WlzGreyValueMakeWSp(iObj2, &errNum2);
	  }
	  if(errNum2 == WLZ_ERR_NONE)
	  {
	    WlzBoundList *bnd,
			 *bnd2;

	    bnd2 = bDom2.b;
	    for(bnd = bnd2; bnd != NULL; bnd = bnd->next)
	    {
	      if(bnd->poly != NULL)
	      {
		WlzPolygonDomain *ply;

		ply = bnd->poly;
		if(ply)
		{
		  int	i;
		  WlzIVertex2 *vtx;

		  vtx = ply->vtx;
		  for(i = 0; i < ply->nvertices; ++i)
		  {
		    WlzGreyValueGet(gVWSp, 0, vtx[i].vtY, vtx[i].vtX);
		    *(gVWSp->gPtr[0].ubp) = 255;
		  }
		}
	      }
	    }
	  }
	  else
	  {
#ifdef _OPENMP
#pragma omp critical
	    {
#endif
	      if(errNum == WLZ_ERR_NONE)
	      {
		errNum = errNum2;
	      }
#ifdef _OPENMP
	    }
#endif
	  }
	  (void )WlzFreeObj(iObj2);
	  WlzGreyValueFreeWSp(gVWSp);
	}
      }
    }
  }
  /* Threshold the shell object, throwing away all but where the voxels
   * are set to create a seed domain. Then remove the value table from
   * the shell object and free it as it's no longer needed. */
  if(errNum == WLZ_ERR_NONE)
  {
    WlzObject	*tObj = NULL;
    WlzPixelV	tV;

    tV.type = WLZ_GREY_UBYTE;
    tV.v.ubv = 1;
    tObj = WlzAssignObject(
    	   WlzThreshold(shlObj, tV, WLZ_THRESH_HIGH, &errNum), NULL);
    if(errNum == WLZ_ERR_NONE)
    {
      sedObj = WlzAssignObject(
      	       WlzMakeMain(tObj->type, tObj->domain, nullVal,
			   NULL, NULL, &errNum), NULL);
    }
    (void )WlzFreeObj(tObj); tObj = NULL;
    if(errNum == WLZ_ERR_NONE)
    {
      tObj = WlzAssignObject(
             WlzMakeMain(shlObj->type, shlObj->domain, nullVal,
			 NULL, NULL, &errNum), NULL);
    }
    (void )WlzFreeObj(shlObj); shlObj = NULL;
    if(errNum == WLZ_ERR_NONE)
    {
      shlObj = tObj;
      tObj = NULL;
    }
    (void )WlzFreeObj(tObj);
#ifdef WLZ_DOMOMAINFILL3D_DEBUG
    {
      FILE	*fP;
      fP = fopen("debug-shlObj-00.wlz", "w");
      (void )WlzWriteObj(fP, shlObj);
      (void )fclose(fP);
    }
#endif
  }
  /* Label the shell domain using 26-connectivity in 3D and then
   * keep only those component objects which intersect the seed domain.
   * Then free the shell and seed domains replacing the shell domain
   * with the union of the intersecting labeled component objects.
   * Finaly free the intersecting component objects, keeping only the
   * new shell domain. */
  if(errNum == WLZ_ERR_NONE)
  {
    int		i,
		j,
    		nCSObj = 0;
    WlzIBox3	bBox;
    WlzObject	**csObj = NULL;

    bBox = WlzBoundingBox3I(shlObj, &errNum);
    if(errNum == WLZ_ERR_NONE)      
    {
      int	maxCSObj;

      maxCSObj = ((bBox.xMax - bBox.xMin + 1) *
      		  (bBox.yMax - bBox.yMin + 1) *
      		  (bBox.zMax - bBox.zMin + 1)) / 8;
      if(maxCSObj < 8)
      {
        maxCSObj = 8;
      }
      errNum = WlzLabel(shlObj, &nCSObj, &csObj, maxCSObj, 0,
			WLZ_26_CONNECTED);
    }
    if(errNum == WLZ_ERR_NONE)
    {
      for(i = 0; i < nCSObj; ++i)
      {
        if(!WlzHasIntersection(csObj[i], sedObj, &errNum))
	{
	  (void )WlzFreeObj(csObj[i]);
	  csObj[i] = NULL;
	}
      }
    }
    if(errNum == WLZ_ERR_NONE)
    {
      /* Squeeze out any NULL objects reseting their number.*/
      for(i = 0, j = 0; i < nCSObj; ++i)
      {
        if(csObj[i])
	{
	  csObj[j++] = csObj[i];
	}
      }
      nCSObj = j;
    }
    if(errNum == WLZ_ERR_NONE)
    {
      WlzObject	*iObj = NULL,
      		*uObj = NULL;

      uObj = WlzAssignObject(
      	     WlzUnionN(nCSObj, csObj, 0, &errNum), NULL);
      iObj = WlzAssignObject(
               WlzIntersect2(uObj, shlObj, &errNum),  NULL);
      (void )WlzFreeObj(uObj);
      (void )WlzFreeObj(shlObj);
      shlObj = iObj;
#ifdef WLZ_DOMOMAINFILL3D_DEBUG
      {
	FILE	*fP;
	fP = fopen("debug-shlObj-01.wlz", "w");
	(void )WlzWriteObj(fP, shlObj);
	(void )fclose(fP);
      }
#endif
    }
    if(csObj)
    {
      for(i = 0; i < nCSObj; ++i)
      {
        (void )WlzFreeObj(csObj[i]);
      }
      (void )AlcFree(csObj);
    }
  }
  /* Sweep down through the boundary lists again creating new boundary lists
   * which do not have boundaries that do not intersect the new shell domain.
   * Then create a new filled object from these boundary lists. */
  if(errNum == WLZ_ERR_NONE)
  {
    int		p,
    		nPlnFil;
    WlzDomain	filDom;

    nPlnFil = shlObj->domain.p->lastpl - shlObj->domain.p->plane1 + 1;
    filDom.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, 
		shlObj->domain.p->plane1, shlObj->domain.p->lastpl,
                shlObj->domain.p->line1, shlObj->domain.p->lastln,
                shlObj->domain.p->kol1, shlObj->domain.p->lastkl,
		&errNum);
#ifdef _OPENMP
#pragma omp parallel for shared(bndObj,shlObj)
#endif
    for(p = 0; p < nPlnFil; ++p)
    {
      if(errNum == WLZ_ERR_NONE)
      {
	WlzDomain bDom2;
	
	bDom2 = bndObj->domain.p->domains[p];
	if(bDom2.core)
	{
	  WlzDomain 	sDom2;
	  WlzObject	*fObj2 = NULL;
	  WlzBoundList  *newBnd = NULL;
	  WlzErrorNum	errNum2 = WLZ_ERR_NONE;

	  sDom2 = shlObj->domain.p->domains[p];
	  if(sDom2.core)
	  {
	    newBnd = WlzDomFill3DDoBound2D(bDom2.b, sDom2, &errNum2);
	    if(newBnd != NULL)
	    {
	      fObj2 = WlzBoundToObj(newBnd, WLZ_SIMPLE_FILL, &errNum2);
	      (void )WlzFreeBoundList(newBnd);
	    }
	    if(errNum2 == WLZ_ERR_NONE)
	    {
	      if(fObj2)
	      {
		filDom.p->domains[p] = WlzAssignDomain(fObj2->domain, NULL);
	      }
	    }
	    else
	    {
#ifdef _OPENMP
#pragma omp critical
	      {
#endif
		if(errNum == WLZ_ERR_NONE)
		{
		  errNum = errNum2;
		}
#ifdef _OPENMP
	      }
#endif
	    }
	    (void )WlzFreeObj(fObj2);
	  }
	}
      }
    }
    if(errNum == WLZ_ERR_NONE)
    {
      errNum = WlzStandardPlaneDomain(filDom.p, NULL);
    }
    if(errNum == WLZ_ERR_NONE)
    {
      WlzObject	*tObj0 = NULL,
      		*tObj1 = NULL;

      /* Put back any isolated voxels this function has removed. */
      tObj0 = WlzAssignObject(
              WlzMakeMain(srcObj->type, filDom, nullVal,
      			  NULL, NULL, &errNum), NULL);
      if(errNum == WLZ_ERR_NONE)
      {
        tObj1 = WlzUnion2(gvnObj, tObj0, &errNum);
      }
      if(errNum == WLZ_ERR_NONE)
      {
	filObj = WlzMakeMain(tObj1->type, tObj1->domain, nullVal,
			     NULL, NULL, &errNum);
      }
      (void )WlzFreeObj(tObj0);
      (void )WlzFreeObj(tObj1);
    }
  }
  (void )WlzFreeObj(bndObj);
  (void )WlzFreeObj(gvnObj);
  (void )WlzFreeObj(shlObj);
  (void )WlzFreeObj(sedObj);
  if((errNum != WLZ_ERR_NONE) && (filObj != NULL))
  {
    (void )WlzFreeObj(filObj);
    filObj = NULL;
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(filObj);
}
Esempio n. 30
0
/*!
* \return	New Woolz object.
* \ingroup	WlzAllocation
* \brief	Creates a new 2D spatial domain object by adding a
* 		rectangular buffer of values to the given current
* 		object (which may be NULL or empty).
* \param	cObj			Given current object.
* \param	og			Origin of rectangular buffer.
* \param	sz			Buffer size.
* \param	gType			Grey type which must be consistent
* 					with the current object and the
* 					buffer of values.
* \param	bufSz			Number of values in the buffer.
* \param	bufP			Given buffer of values.
* \param	dstErr			Destination error pointer, may be NULL.
*/
static WlzObject *WlzBuildObj2(WlzObject *cObj,
                               WlzIVertex2 og, WlzIVertex2 sz,
                               WlzGreyType gType, int bufSz, WlzGreyP bufP,
                               WlzErrorNum *dstErr)
{
    WlzDomain	bDom;
    WlzValues	bVal,
                nVal;
    WlzObject	*bObj = NULL,
                 *nObj = NULL;
    WlzPixelV	bgdV;
    WlzErrorNum	errNum = WLZ_ERR_NONE;

    bDom.core = NULL;
    bVal.core = NULL;
    nVal.core = NULL;
    bgdV.type = WLZ_GREY_INT;
    bgdV.v.inv = 0;
    if(cObj)
    {
        WlzGreyType cGType = WLZ_GREY_ERROR;;

        switch(cObj->type)
        {
        case WLZ_EMPTY_OBJ:
            cObj = NULL;
            break;
        case WLZ_2D_DOMAINOBJ:
            if(cObj->domain.core == NULL)
            {
                errNum = WLZ_ERR_DOMAIN_NULL;
            }
            else if(cObj->values.core == NULL)
            {
                errNum = WLZ_ERR_VALUES_NULL;
            }
            else
            {
                cGType = WlzGreyTypeFromObj(cObj, &errNum);
                bgdV = WlzGetBackground(cObj, &errNum);
            }
            if((errNum == WLZ_ERR_NONE) && (cGType != gType))
            {
                errNum = WLZ_ERR_GREY_TYPE;
            }
            break;
        default:
            errNum = WLZ_ERR_OBJECT_TYPE;
            break;
        }
    }
    /* Create new object with domain and values of given rectangular buffer. */
    if(errNum == WLZ_ERR_NONE)
    {
        bDom.i = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_RECT,
                                       og.vtY, og.vtY + sz.vtY - 1,
                                       og.vtX, og.vtX + sz.vtX - 1,
                                       &errNum);
    }
    if(errNum == WLZ_ERR_NONE)
    {
        WlzObjectType gTT;

        gTT = WlzGreyTableType(WLZ_GREY_TAB_RECT, gType, NULL);
        bVal.r = WlzMakeRectValueTb(gTT, bDom.i->line1, bDom.i->lastln,
                                    bDom.i->kol1, sz.vtX, bgdV, bufP.inp, &errNum);
    }
    if(errNum == WLZ_ERR_NONE)
    {
        bObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, bDom, bVal, NULL, NULL, &errNum);
    }
    if(errNum == WLZ_ERR_NONE)
    {
        if(cObj == NULL)
        {
            /* Just copy the buffer object. */
            nObj = WlzCopyObject(bObj, &errNum);
        }
        else
        {
            /* Compute union of current and buffer objects. */
            nObj = (cObj)? WlzUnion2(cObj, bObj, &errNum):
                   WlzMakeMain(WLZ_2D_DOMAINOBJ, bDom, nVal,
                               NULL, NULL, &errNum);
            /* Create new value table. */
            if(errNum == WLZ_ERR_NONE)
            {
                WlzObjectType gTT;

                gTT = WlzGreyTableType(WLZ_GREY_TAB_RAGR, gType, NULL);
                nVal.v = WlzNewValueTb(nObj, gTT, bgdV, &errNum);
            }
            if(errNum == WLZ_ERR_NONE)
            {
                nObj->values = WlzAssignValues(nVal, NULL);
            }
            if(errNum == WLZ_ERR_NONE)
            {
                WlzObject 	*tObj;

                /* Copy existing values to new object. */
                tObj = WlzGreyTransfer(nObj, cObj, &errNum);
                (void )WlzFreeObj(nObj);
                nObj = tObj;
                /* Then copy buffer values to new object. */
                if(errNum == WLZ_ERR_NONE)
                {
                    tObj = WlzGreyTransfer(nObj, bObj, &errNum);
                    (void )WlzFreeObj(nObj);
                    nObj = tObj;
                }
            }
        }
    }
    (void )WlzFreeObj(bObj);
    if(dstErr)
    {
        *dstErr = errNum;
    }
    return(nObj);
}