Beispiel #1
0
/*! 
* \ingroup      WlzAllocation
* \brief        Free a histogram domain.
*
* \return       Error number, values: from WlzFreeDomain().
* \param    hist	Histogram domain to be freed.
* \par      Source:
*                WlzFreeSpace.c
*/
WlzErrorNum WlzFreeHistogramDomain(WlzHistogramDomain *hist)
{
  WlzDomain	domain;

  domain.hist  = hist;

  return( WlzFreeDomain(domain) );
}
Beispiel #2
0
/*! 
* \ingroup      WlzAllocation
* \brief        Free an interval domain - convenience link to
 WlzFreeDomain()
*
* \return       Error number, values: from WlzFreeDomain().
* \param    idom	interval domain pointer to be freed.
* \par      Source:
*                WlzFreeSpace.c
*/
WlzErrorNum WlzFreeIntervalDomain(WlzIntervalDomain *idom)
{
  WlzDomain	domain;

  domain.i = idom;

  return( WlzFreeDomain(domain) );
}
Beispiel #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);
}
Beispiel #4
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);
}
Beispiel #5
0
/*!
* \return	New 2D Woolz object or NULL on error.
* \ingroup	WlzTransform
* \brief	Creates a new 2D Woolz object with a single line which
* 		is the profile from the given start position to the
* 		given end position. This function assumes that it is
* 		given either a 2 or 3D spatial domain object and that
* 		this object has a non-NULL domain. See WlzProfileLine().
* \param	gObj		Given Woolz object.
* \param	sPos		Start position.
* \param	ePos		End position.
* \param	dstErr		Destination error pointer, may be NULL.
*/
static WlzObject *WlzProfileLnSD(
  WlzObject *gObj,
  WlzIVertex3 sPos,
  WlzIVertex3 ePos,
  WlzErrorNum *dstErr)
{
  WlzDomain	rDom = {0};
  WlzValues	rVal = {0};
  WlzObject	*rObj = NULL;
  WlzGreyP	rPix = {0};
  WlzGreyValueWSpace *gVWSp = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  rDom.i = WlzProfileLineIDom(gObj, sPos, ePos, &errNum);
  if(errNum == WLZ_ERR_NONE)
  {
    if(gObj->values.core)
    {
      gVWSp = WlzGreyValueMakeWSp(gObj, &errNum);
      if(errNum == WLZ_ERR_NONE)
      {
	int	len;
	size_t	gSz;

	len = rDom.i->lastkl - rDom.i->kol1 +1;
	if((gSz = WlzGreySize(gVWSp->gType)) == 0)
	{
	  errNum = WLZ_ERR_GREY_TYPE;
	}
	else if((rPix.v = AlcMalloc(len * gSz)) == NULL)
	{
	  errNum = WLZ_ERR_MEM_ALLOC;
	}
      }
      if(errNum == WLZ_ERR_NONE)
      {
	WlzPixelV bgd;
	WlzObjectType tType;

	bgd.type = gVWSp->gType;
	bgd.v = gVWSp->gBkd;
	tType = WlzGreyValueTableType(0, WLZ_GREY_TAB_RECT, gVWSp->gType,
	                              NULL);
	rVal.r = WlzMakeRectValueTb(tType,
	                            rDom.i->line1, rDom.i->lastln, rDom.i->kol1,
				    (rDom.i->lastkl - rDom.i->kol1) + 1,
				    bgd, rPix.inp, &errNum);
      }
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    rObj = WlzMakeMain(gObj->type, rDom, rVal, NULL, NULL, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    errNum = WlzProfileWalkValues(gObj, rObj, gVWSp, sPos, ePos, &errNum);
  }
  if(errNum != WLZ_ERR_NONE)
  {
    if(rObj)
    {
      (void )WlzFreeObj(rObj);
      rObj = NULL;
    }
    else
    {
      if(rVal.core)
      {
	(void )WlzFreeDomain(rDom);
	(void )WlzFreeValues(rVal);
      }
      else
      {
        AlcFree(rPix.v);
      }
    }
  }
  if(dstErr)    
  {
    *dstErr = errNum;
  }
  return(rObj);
}
Beispiel #6
0
/*! 
* \ingroup      WlzAllocation
* \brief        Free space allocated to a woolz object.
*
* \return       Error number, values: WLZ_ERR_NONE, WLZ_ERR_MEM_FREE
* \param    obj	Object to be freed.
* \par      Source:
*                WlzFreeSpace.c
*/
WlzErrorNum WlzFreeObj(WlzObject *obj)
{
  int 			i;
  WlzCompoundArray	*ca = (WlzCompoundArray *) obj;
  WlzErrorNum		errNum = WLZ_ERR_NONE;

  WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_FN|WLZ_DBG_LVL_1),
  	  ("WlzFreeObj FE %p\n",
	   obj));

  /* check the object pointer and linkcount */
  if (obj == NULL){
    return( WLZ_ERR_NONE );
  }

  if( WlzUnlink(&(obj->linkcount), &errNum) ){    /* Check linkcount */

    switch( obj->type ){

    case WLZ_2D_DOMAINOBJ:
      WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1),
	      ("WlzFreeObj %p WLZ_2D_DOMAINOBJ "
	       "%p %d %p %d %p\n",
	       obj, (obj->domain.i),
	       (obj->domain.i?obj->domain.i->linkcount: 0),
	       (obj->values.core),
	       ((obj->values.core)? obj->values.core->linkcount: 0),
	       (obj->plist)));
      errNum = WlzFreeDomain(obj->domain);
      if((errNum == WLZ_ERR_NONE) && (obj->values.core != NULL)) {
	if(WlzGreyTableIsTiled(obj->values.core->type) == WLZ_GREY_TAB_TILED) {
	  errNum = WlzFreeTiledValues(obj->values.t);
	}
	else {
	  errNum = WlzFreeValueTb(obj->values.v);
	}
      }
      if(errNum == WLZ_ERR_NONE) {
        errNum = WlzFreePropertyList(obj->plist);
      }
      if(errNum == WLZ_ERR_NONE) {
        errNum = WlzFreeObj(obj->assoc);
      }
      break;

    case WLZ_3D_DOMAINOBJ:
      WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1),
      	      ("WlzFreeObj %p WLZ_3D_DOMAINOBJ %p, "
	       "%d %p %d %p\n",
	       obj, obj->domain.i,
	       (obj->domain.p? obj->domain.p->linkcount: 0),
	       obj->values.core,
	       (obj->values.core? obj->values.core->linkcount: 0),
	       obj->plist));
      errNum = WlzFreePlaneDomain(obj->domain.p);
      if((errNum == WLZ_ERR_NONE) && (obj->values.core != NULL)){
	if(WlzGreyTableIsTiled(obj->values.core->type) == WLZ_GREY_TAB_TILED) {
	  errNum = WlzFreeTiledValues(obj->values.t);
	}
	else {
	  errNum = WlzFreeVoxelValueTb(obj->values.vox);
	}
      }
      if(errNum == WLZ_ERR_NONE) {
        errNum = WlzFreePropertyList(obj->plist);
      }
      if(errNum == WLZ_ERR_NONE) {
        errNum = WlzFreeObj(obj->assoc);
      }
      break;

    case WLZ_TRANS_OBJ:
      WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1),
      	      ("WlzFreeObj %p WLZ_TRANS_OBJ %p, "
	       "%d %p %d %p\n",
	       obj, obj->domain.t,
	       ((obj->domain.t)?(obj->domain.t)->linkcount: 0),
	       obj->values.obj,
	       ((obj->values.obj)?(obj->values.obj)->linkcount: 0),
	       obj->plist));
      if( WlzFreeAffineTransform(obj->domain.t) ||
	  WlzFreeObj(obj->values.obj) ||
	  WlzFreePropertyList(obj->plist) ||
	  WlzFreeObj(obj->assoc) ){
	errNum = WLZ_ERR_MEM_FREE;
      }
      break;

    case WLZ_2D_POLYGON:
      WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1),
      	      ("WlzFreeObj %p WLZ_2D_POLYGON %p\n",
	       obj, obj->domain.poly));
      errNum = WlzFreePolyDmn(obj->domain.poly);
      break;

    case WLZ_BOUNDLIST:
      WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1),
      	      ("WlzFreeObj %p WLZ_BOUNDLIST %p\n",
	       obj, obj->domain.b));
      errNum = WlzFreeBoundList(obj->domain.b);
      break;

    case WLZ_CONTOUR:
      WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1),
      	      ("WlzFreeObj %p WLZ_CONTOUR %p\n",
	       obj, obj->domain.ctr));
      errNum = WlzFreeContour(obj->domain.ctr);
      break;

    case WLZ_CONV_HULL:
      WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1),
      	      ("WlzFreeObj %p WLZ_CONV_HULL %p %p\n",
	       obj, obj->domain.core, obj->values.core));
      if(obj->domain.core) {
        switch(obj->domain.core->type) {
	  case WLZ_CONVHULL_DOMAIN_2D:
	    errNum = WlzFreeConvexHullDomain2(obj->domain.cvh2);
	    break;
	  case WLZ_CONVHULL_DOMAIN_3D:
	    errNum = WlzFreeConvexHullDomain3(obj->domain.cvh3);
	    break;
	  default:
	    errNum = WLZ_ERR_DOMAIN_TYPE;
	    break;
	}
      }
      break;

    case WLZ_CMESH_2D:
      WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1),
      	      ("WlzFreeObj %p WLZ_CMESH_2D %p, "
	       "%d %p %d %p\n",
	       obj, obj->domain.cm2,
	       ((obj->domain.cm2)? (obj->domain.cm2)->linkcount: 0),
	       obj->values.x,
	       ((obj->values.x)? (obj->values.x)->linkcount: 0),
	       obj->plist));
      errNum = WlzCMeshFree2D(obj->domain.cm2);
      if((errNum == WLZ_ERR_NONE) && (obj->values.core != NULL))
      {
	errNum = WlzFreeIndexedValues(obj->values.x);
      }
      if((errNum == WLZ_ERR_NONE) && (obj->plist != NULL))
      {
	errNum = WlzFreePropertyList(obj->plist);
      }
      if((errNum == WLZ_ERR_NONE) && (obj->assoc != NULL))
      {
	errNum = WlzFreeObj(obj->assoc);
      }
      break;
    case WLZ_CMESH_2D5:
      WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1),
      	      ("WlzFreeObj %p WLZ_CMESH_2D5 %p, "
	       "%d %p %d %p\n",
	       obj, obj->domain.cm2d5,
	       ((obj->domain.cm2d5)? (obj->domain.cm2d5)->linkcount: 0),
	       obj->values.x,
	       ((obj->values.x)? (obj->values.x)->linkcount: 0),
	       obj->plist));
      errNum = WlzCMeshFree2D5(obj->domain.cm2d5);
      if((errNum == WLZ_ERR_NONE) && (obj->values.core != NULL))
      {
	errNum = WlzFreeIndexedValues(obj->values.x);
      }
      if((errNum == WLZ_ERR_NONE) && (obj->plist != NULL))
      {
	errNum = WlzFreePropertyList(obj->plist);
      }
      if((errNum == WLZ_ERR_NONE) && (obj->assoc != NULL))
      {
	errNum = WlzFreeObj(obj->assoc);
      }
      break;

    case WLZ_CMESH_3D:
      WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1),
      	      ("WlzFreeObj %p WLZ_CMESH_3D %p, "
	       "%d %p %d %p\n",
	       obj, obj->domain.cm3,
	       ((obj->domain.cm3)?(obj->domain.cm3)->linkcount: 0),
	       obj->values.x,
	       ((obj->values.x)?(obj->values.x)->linkcount: 0),
	       obj->plist));
      errNum = WlzCMeshFree3D(obj->domain.cm3);
      if((errNum == WLZ_ERR_NONE) && (obj->values.core != NULL))
      {
	errNum = WlzFreeIndexedValues(obj->values.x);
      }
      if((errNum == WLZ_ERR_NONE) && (obj->plist != NULL))
      {
	errNum = WlzFreePropertyList(obj->plist);
      }
      if((errNum == WLZ_ERR_NONE) && (obj->assoc != NULL))
      {
	errNum = WlzFreeObj(obj->assoc);
      }
      break;

    case WLZ_POINTS:
      WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1),
      	      ("WlzFreeObj %p WLZ_POINTS %p\n",
	       obj, obj->domain.pts));
      errNum = WlzFreeDomain(obj->domain);
      if((errNum == WLZ_ERR_NONE) && (obj->values.core != NULL))
      {
        errNum = WlzFreePointValues(obj->values.pts);
      }
      if((errNum == WLZ_ERR_NONE) && (obj->plist != NULL))
      {
        errNum = WlzFreePropertyList(obj->plist);
      }
      if((errNum == WLZ_ERR_NONE) && (obj->assoc != NULL))
      {
	errNum = WlzFreeObj(obj->assoc);
      }
      break;

    case WLZ_HISTOGRAM:
      WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1),
      	      ("WlzFreeObj %p WLZ_CONV_HULL %p\n",
	       obj, obj->domain.hist));
      errNum = WlzFreeDomain(obj->domain);
      break;

    case WLZ_RECTANGLE:
      WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1),
      	      ("WlzFreeObj %p WLZ_RECTANGLE %p\n",
	       obj, obj->domain.r));
      errNum = WlzFreeDomain(obj->domain);
      break;

    case WLZ_AFFINE_TRANS:
      WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1),
      	      ("WlzFreeObj %p WLZ_AFFINE_TRANS\n",
	       obj));
      errNum = WlzFreeAffineTransform(obj->domain.t);
      break;

    case WLZ_LUT:
      WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1),
              ("WlzFreeObj %p WLZ_LUT\n",
	      obj));
      errNum = WlzFreeDomain(obj->domain);
      if(errNum == WLZ_ERR_NONE)
      {
        errNum = WlzFreeLUTValues(obj->values);
      }
      break;

    case WLZ_COMPOUND_ARR_1:
      WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1),
      	      ("WlzFreeObj %p WLZ_COMPOUND_ARR_1\n",
	       ca));
      for (i=0; i<ca->n; i++){
	if( WlzFreeObj(ca->o[i]) != WLZ_ERR_NONE ){
	  errNum = WLZ_ERR_MEM_FREE;
	}
      }
      break;

    case WLZ_COMPOUND_ARR_2:
      WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1),
      	      ("WlzFreeObj %p WLZ_COMPOUND_ARR_2\n",
	       ca));
      for (i=0; i<ca->n; i++){
	if( WlzFreeObj(ca->o[i]) != WLZ_ERR_NONE ){
	  errNum = WLZ_ERR_MEM_FREE;
	}
      }
      break;

    case WLZ_PROPERTY_OBJ:
      WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1),
      	      ("WlzFreeObj %p WLZ_PROPERTY_OBJ\n",
	       obj));
      errNum = WlzFreePropertyList(obj->plist);
      break;

    case WLZ_EMPTY_OBJ:
      WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1),
      	      ("WlzFreeObj %p WLZ_EMPTY_OBJ\n",
	       obj));
      break;

    default:
      WLZ_DBG((WLZ_DBG_ALLOC|WLZ_DBG_LVL_1),
      	      ("WlzFreeObj %p %d\n",
	       obj, (int )(obj->type)));
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;

    }    /* End of switch */

    AlcFree((void *) obj);
  }

  return( errNum );
}
Beispiel #7
0
/*! 
* \ingroup      WlzAllocation
* \brief        Free a planedomain
*
* \return       Error number, values: WLZ_ERR_NONE and errors from
 WlzFreeAffineTransform(), WlzFreeDomain(), WlzFreeBoundList(),
 WlzFreePolyDmn().
* \param    planedm	Pointer to planedomain structure to be freed.
* \par      Source:
*                WlzFreeSpace.c
*/
WlzErrorNum WlzFreePlaneDomain(WlzPlaneDomain *planedm)
{
  WlzDomain	*domains;
  int 		nplanes;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  /* check the object pointer and linkcount */
  if (planedm == NULL){
    return( WLZ_ERR_NONE );
  }

  if( WlzUnlink(&(planedm->linkcount), &errNum) ){

    nplanes = planedm->lastpl - planedm->plane1 + 1;
    domains = planedm->domains;

    switch( planedm->type ){

    case WLZ_PLANEDOMAIN_DOMAIN:
      while( nplanes-- ){
	errNum |= WlzFreeDomain( *domains );
	domains++;
      }
      break;

    case WLZ_PLANEDOMAIN_POLYGON:
      while( nplanes-- ){
	errNum |= WlzFreePolyDmn((*domains).poly);
	domains++;
      }
      break;

    case WLZ_PLANEDOMAIN_BOUNDLIST:
      while( nplanes-- ){
	errNum |= WlzFreeBoundList((*domains).b);
	domains++;
      }
      break;

    case WLZ_PLANEDOMAIN_HISTOGRAM:
      while( nplanes-- ){
	errNum |= WlzFreeDomain(*domains);
	domains++;
      }
      break;

    case WLZ_PLANEDOMAIN_AFFINE:
      while( nplanes-- ){
	errNum |= WlzFreeAffineTransform((*domains).t);
	domains++;
      }
      break;

    default:
      return( WLZ_ERR_PLANEDOMAIN_TYPE );

    }
    AlcFree((void *) planedm->domains);
    AlcFree((void *) planedm);
  }

  return( errNum );
}
Beispiel #8
0
/*!
* \return	New Woolz domain object with maximal domain and grey
*		values which encode the gradient's direction or NULL
*		on error.
* \ingroup	WlzFeatures
* \brief	Computes the maximal domain and gradient direction of
*               given Woolz 2D domain object.
* \note         All the objects domains are known to be the same.
* \param	grdM			Gradient magnitude.
* \param	grdY			Gradient (partial derivative)
*                                       through lines.
* \param	grdX			Gradient (partial derivative)
*                                       through columns.
* \param	minThrV			Minimum gradient value to
*                                       consider.
* \param	dstErr			Destination error pointer, may
*                                       be null.
*/
static WlzObject *WlzNMSuppress2D(WlzObject *grdM,
				  WlzObject *grdY, WlzObject *grdX,
				  WlzPixelV minThrV, WlzErrorNum *dstErr)
{
  int		idN,
		inLen,
		outLen,
  		inLnIdx = 0;
  WlzGreyType	gType,
  		bufType;
  WlzIVertex2	bufSz,
  		inPos,
		outPos,
		orgPos;
  WlzValues	tmpVal;
  WlzDomain	dstDom,
  		grdDom;
  WlzIntervalWSpace tmpIWSp = {0},
  		grdMIWSp = {0},
  		grdYIWSp = {0},
		grdXIWSp = {0};
  WlzGreyWSpace tmpGWSp,
  		grdMGWSp,
  		grdYGWSp,
		grdXGWSp;
  WlzPixelV	zeroV;
  WlzGreyP	grdMBufGP,
  		grdYBufGP,
		grdXBufGP;
  WlzDynItvPool pool;
  WlzObject	*dstObj = NULL,
  		*tmpObj = NULL;
  void 		*grdYBuf = NULL,
		*grdXBuf = NULL;
  void		**grdMBuf = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  tmpVal.core = NULL;
  pool.itvBlock = NULL;
  dstDom.core = NULL;
  if((grdM->type != WLZ_2D_DOMAINOBJ) ||
     (grdY->type != WLZ_2D_DOMAINOBJ) ||
     (grdX->type != WLZ_2D_DOMAINOBJ))
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if((grdM->domain.core == NULL) ||
          (grdY->domain.core == NULL) ||
          (grdX->domain.core == NULL))
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if((grdM->values.core == NULL) ||
  	  (grdY->values.core == NULL) ||
	  (grdX->values.core == NULL))
  {
    errNum = WLZ_ERR_VALUES_NULL;
  }
  else
  {
    /* Find required buffer type (WLZ_GREY_DOUBLE or WLZ_GREY_INT). */
    bufType = WLZ_GREY_INT;
    gType = WlzGreyTableTypeToGreyType(grdM->values.core->type, &errNum);
    if(errNum == WLZ_ERR_NONE)
    {
      if((gType == WLZ_GREY_FLOAT) || (gType == WLZ_GREY_DOUBLE))
      {
	bufType = WLZ_GREY_DOUBLE;
      }
      else
      {
	gType = WlzGreyTableTypeToGreyType(grdY->values.core->type, &errNum);
	if(errNum == WLZ_ERR_NONE)
	{
	  if((gType == WLZ_GREY_FLOAT) || (gType == WLZ_GREY_DOUBLE))
	  {
	    bufType = WLZ_GREY_DOUBLE;
	  }
	  else
	  {
	    gType = WlzGreyTableTypeToGreyType(grdX->values.core->type,
	    				       &errNum);
	    if(errNum == WLZ_ERR_NONE)
	    {
	      if((gType == WLZ_GREY_FLOAT) || (gType == WLZ_GREY_DOUBLE))
	      {
		bufType = WLZ_GREY_DOUBLE;
	      }
	    }
	  }
	}
      }
    }
  }
  /* Convert minimum gradient threshold value. */
  if(errNum == WLZ_ERR_NONE)
  {
    if(bufType == WLZ_GREY_INT)
    {
      errNum = WlzValueConvertPixel(&minThrV, minThrV, WLZ_GREY_INT);
    }
    else /* bufType == WLZ_GREY_DOUBLE */
    {
      errNum = WlzValueConvertPixel(&minThrV, minThrV, WLZ_GREY_DOUBLE);
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    grdDom = grdM->domain;
    /* Make destination object with WLZ_GREY_UBYTE greys. */
    zeroV.type = WLZ_GREY_UBYTE;
    zeroV.v.inv = 0;
    tmpVal.v = WlzNewValueTb(grdM, WlzGreyTableType(WLZ_GREY_TAB_RAGR,
						    WLZ_GREY_UBYTE, NULL),
			     zeroV, &errNum);
    if(errNum == WLZ_ERR_NONE)
    {
      /* Use the input domain while calculating the new maximal domain. */
      tmpObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, grdM->domain, tmpVal,
			   NULL, NULL, &errNum);
    }
  }
  /* Initialize the memory pool with some size of block. Any +ve number
   * greater than the maximum number of intervals in any destination line
   * would work but the fewer allocations then the more efficient the code,
   * hence this attempt to guess the required number of intervals in the
   * destination domain. */
  if(errNum == WLZ_ERR_NONE)
  {
    pool.itvsInBlock = (((grdDom.i->lastkl - grdDom.i->kol1 + 1) *
			(grdDom.i->lastln - grdDom.i->line1 + 1)) / 64) +
		       grdDom.i->lastkl - grdDom.i->kol1 + 1024;
  }
  /* Make gradient buffers. */
  if(errNum == WLZ_ERR_NONE)
  {
    bufSz.vtY = 3;
    bufSz.vtX = grdDom.i->lastkl - grdDom.i->kol1 + 1;
    if(bufType == WLZ_GREY_INT)
    {
      if((AlcInt2Malloc((int ***)&grdMBuf,
			bufSz.vtY, bufSz.vtX) != ALC_ER_NONE) ||
	 ((grdYBuf = AlcMalloc(sizeof(int) * bufSz.vtX)) == NULL) ||
	 ((grdXBuf = AlcMalloc(sizeof(int) * bufSz.vtX)) == NULL))
      {
	errNum = WLZ_ERR_MEM_ALLOC;
      }
      else
      {
	grdYBufGP.inp = (int *)grdYBuf;
	grdXBufGP.inp = (int *)grdXBuf;
      }
    }
    else /* bufType == WLZ_GREY_DOUBLE */
    {
      if((AlcDouble2Malloc((double ***)&grdMBuf,
			   bufSz.vtY, bufSz.vtX) != ALC_ER_NONE) ||
	 ((grdYBuf = AlcMalloc(sizeof(double) * bufSz.vtX)) == NULL) ||
	 ((grdXBuf = AlcMalloc(sizeof(double) * bufSz.vtX)) == NULL))
      {
	errNum = WLZ_ERR_MEM_ALLOC;
      }
      else
      {
	grdYBufGP.dbp = (double *)grdYBuf;
	grdXBufGP.dbp = (double *)grdXBuf;
      }
    }
  }
  /* Make destination interval domain with interval lines but not intervals. */
  if(errNum == WLZ_ERR_NONE)
  {
    dstDom.i = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_INTVL,
    				     grdDom.i->line1, grdDom.i->lastln,
				     grdDom.i->kol1, grdDom.i->lastkl,
				     &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    /* Scan down through the gradient objects. */
    if(((errNum = WlzInitGreyScan(tmpObj,
    				  &tmpIWSp, &tmpGWSp)) == WLZ_ERR_NONE) &&
       ((errNum = WlzInitGreyScan(grdM,
    				  &grdMIWSp, &grdMGWSp)) == WLZ_ERR_NONE) &&
       ((errNum = WlzInitGreyScan(grdY,
    				  &grdYIWSp, &grdYGWSp)) == WLZ_ERR_NONE) &&
       ((errNum = WlzInitGreyScan(grdX,
    				  &grdXIWSp, &grdXGWSp)) == WLZ_ERR_NONE))
    {
      orgPos.vtX = grdDom.i->kol1;
      orgPos.vtY = grdDom.i->line1;
      while((errNum == WLZ_ERR_NONE) &&
            ((errNum = WlzNextGreyInterval(&grdMIWSp)) == WLZ_ERR_NONE))
      {
        inLen = grdMIWSp.rgtpos - grdMIWSp.lftpos + 1;
	inPos.vtX = grdMIWSp.lftpos - orgPos.vtX;
	/* Process any lines between this and the last by clearing the
	 * gradient magnitude buffer . */
	if(grdMIWSp.nwlpos > 0)
	{
	  idN = (grdMIWSp.nwlpos >= 3)? 3: grdMIWSp.nwlpos;
	  while(--idN >= 0)
	  {
	    inPos.vtY = grdMIWSp.linpos - orgPos.vtY - idN;
	    inLnIdx = (3 + inPos.vtY) % 3;
	    if(bufType == WLZ_GREY_INT)
	    {
	      WlzValueSetInt(*((int **)grdMBuf + inLnIdx), 0,
	      		     bufSz.vtX);
	    }
	    else /* bufType == WLZ_GREY_DOUBLE */
	    {
	      WlzValueSetDouble(*((double **)grdMBuf + inLnIdx), 0,
	      			bufSz.vtX);
	    }
	  }
	}
	/* Copy intervals to values buffers. */
	if(bufType == WLZ_GREY_INT)
	{
	  grdMBufGP.inp = *((int **)grdMBuf + inLnIdx);
	}
	else /* bufType == WLZ_GREY_DOUBLE */
	{
	  grdMBufGP.dbp = *((double **)grdMBuf + inLnIdx);
	}
	WlzValueCopyGreyToGrey(grdMBufGP, inPos.vtX, bufType,
			       grdMGWSp.u_grintptr, 0, grdMGWSp.pixeltype,
			       inLen);
	if(grdMIWSp.intrmn == 0)
	{
	  while((errNum == WLZ_ERR_NONE) &&
	        (tmpIWSp.linpos < grdMIWSp.linpos))
	  {
	    outPos.vtY = tmpIWSp.linpos - orgPos.vtY;
	    if(outPos.vtY >= 0)
	    {
	      outLen = tmpIWSp.rgtpos - tmpIWSp.lftpos + 1;
	      outPos.vtX = tmpIWSp.lftpos - orgPos.vtX;
	      WlzValueCopyGreyToGrey(grdYBufGP, 0, bufType,
				     grdYGWSp.u_grintptr, 0,
				     grdYGWSp.pixeltype, outLen);
	      WlzValueCopyGreyToGrey(grdXBufGP, 0, bufType,
				     grdXGWSp.u_grintptr, 0,
				     grdXGWSp.pixeltype, outLen);
	      if(bufType == WLZ_GREY_INT)
	      {
		errNum = WlzNMSuppress2DBufI(dstDom.i,
					     (int **)grdMBuf,
					     (int *)grdYBuf,
					     (int *)grdXBuf,
					     &pool,
					     tmpGWSp.u_grintptr.ubp,
					     outLen, outPos, orgPos,
					     minThrV.v.inv);
	      }
	      else /* bufType == WLZ_GREY_DOUBLE */
	      {
		errNum = WlzNMSuppress2DBufD(dstDom.i,
				    	     (double **)grdMBuf,
				    	     (double *)grdYBuf,
					     (double *)grdXBuf,
					     &pool,
					     tmpGWSp.u_grintptr.ubp,
					     outLen, outPos, orgPos,
					     minThrV.v.dbv);
	      }
	    }
	    if(errNum == WLZ_ERR_NONE)
	    {
	      errNum = WlzNextGreyInterval(&tmpIWSp);
	    }
	    if(errNum == WLZ_ERR_NONE)
	    {
	      errNum = WlzNextGreyInterval(&grdYIWSp);
	    }
	    if(errNum == WLZ_ERR_NONE)
	    {
	      errNum = WlzNextGreyInterval(&grdXIWSp);
	    }
	  }
        }
      }
      if(errNum == WLZ_ERR_EOO)
      {
        errNum = WLZ_ERR_NONE;
      }
    }
    if(tmpIWSp.gryptr == &tmpGWSp)
    {
      (void )WlzEndGreyScan(&tmpIWSp, &tmpGWSp);
    }
    if(grdMIWSp.gryptr == &grdMGWSp)
    {
      (void )WlzEndGreyScan(&grdMIWSp, &grdMGWSp);
    }
    if(grdYIWSp.gryptr == &grdYGWSp)
    {
      (void )WlzEndGreyScan(&grdYIWSp, &grdYGWSp);
    }
    if(grdXIWSp.gryptr == &grdXGWSp)
    {
      (void )WlzEndGreyScan(&grdXIWSp, &grdXGWSp);
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if((errNum = WlzStandardIntervalDomain(dstDom.i)) == WLZ_ERR_NONE)
    {
      dstObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, dstDom, tmpVal,
			   NULL, NULL, &errNum);
    }
  }
  if(tmpObj)
  {
    WlzFreeObj(tmpObj);
  }
  if(errNum != WLZ_ERR_NONE)
  {
    if(tmpObj == NULL)
    {
      if(dstDom.core)
      {
        (void )WlzFreeDomain(dstDom);
      }
      if(tmpVal.core)
      {
        (void )WlzFreeValues(tmpVal);
      }
    }
  }
  if(grdMBuf)
  {
    Alc2Free(grdMBuf);
  }
  if(grdYBuf)
  {
    AlcFree(grdYBuf);
  }
  if(grdXBuf)
  {
    AlcFree(grdXBuf);
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(dstObj);
}
/*! 
* \return       projection object
* \ingroup      WlzTransform
* \brief        Use the view transform to define a projection from
*		3D to 2D. Currently only the domain is projected as
*		an opaque shadow.
*		This is old code temporarily kept for compatibility.
* \param    obj	source 3D object
* \param    viewStr	view structure defining the projection
* \param    intFunc	grey-value summation function
* \param    intFuncData data to be passed to the integration function
* \param    dstErr	error return
*/
WlzObject *WlzGetProjectionFromObject(
  WlzObject		*obj,
  WlzThreeDViewStruct 	*viewStr,
  Wlz3DProjectionIntFn 	intFunc,
  void			*intFuncData,
  WlzErrorNum		*dstErr)
{
  WlzObject		*rtnObj=NULL,
  			*obj1;
  WlzThreeDViewStruct	*viewStr1=NULL;
  WlzDomain		domain;
  WlzValues		values;
  WlzGreyType		srcGType = WLZ_GREY_UBYTE,
  			dstGType = WLZ_GREY_UBYTE;
  WlzPixelV		pixval;
  WlzPixelP		pixptr;
  WlzIntervalWSpace	iwsp;
  WlzGreyWSpace		gwsp;
  WlzGreyValueWSpace	*gVWSp = NULL;
  WlzDVertex3		vtx, vtx1;
  double		x, y, z;
  double		*s_to_x=NULL;
  double		*s_to_y=NULL;
  double		*s_to_z=NULL;
  int			k, xp, yp, s, sp;
  int			length = 0, size = 0, occupiedFlg;
  WlzErrorNum 	errNum=WLZ_ERR_NONE;

  /* check inputs */
  if( obj == NULL ){
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if( obj->type != WLZ_3D_DOMAINOBJ ){
    errNum = WLZ_ERR_OBJECT_TYPE;
  }
  else if( obj->domain.core == NULL ){
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if( obj->domain.core->type != WLZ_PLANEDOMAIN_DOMAIN ){
    errNum = WLZ_ERR_DOMAIN_TYPE;
  }

  if( (errNum == WLZ_ERR_NONE) && (viewStr == NULL) ){
    errNum = WLZ_ERR_OBJECT_NULL;
  }

  /* create new view transform */
  if( errNum == WLZ_ERR_NONE ){
    if((viewStr1 = WlzMake3DViewStruct(WLZ_3D_VIEW_STRUCT, &errNum)) != NULL){
      /* need to worry about fixed line mode here sometime */
      viewStr1->fixed = viewStr->fixed;
      viewStr1->theta = viewStr->theta;
      viewStr1->phi = viewStr->phi;
      viewStr1->zeta = viewStr->zeta;
      viewStr1->dist = viewStr->dist;
      viewStr1->scale = viewStr->scale;
      viewStr1->voxelSize[0] = viewStr->voxelSize[0];
      viewStr1->voxelSize[1] = viewStr->voxelSize[1];
      viewStr1->voxelSize[2] = viewStr->voxelSize[2];
      viewStr1->voxelRescaleFlg = viewStr->voxelRescaleFlg;
      viewStr1->interp = viewStr->interp;
      viewStr1->view_mode = viewStr->view_mode;
      viewStr1->up = viewStr->up;

      /* now intialize it */
      /* could optimise by setting fixed point to object centre */
      if( (errNum = WlzInit3DViewStruct(viewStr1, obj)) != WLZ_ERR_NONE ){
	WlzFree3DViewStruct(viewStr1);
	viewStr1 = NULL;
      }
    }
  }

  /* set up orthogonal line parameters & luts */
  if( errNum == WLZ_ERR_NONE ){
    length = WLZ_NINT(viewStr1->maxvals.vtZ) -
      WLZ_NINT(viewStr1->minvals.vtZ) + 1;
    s_to_x = (double *) AlcMalloc(sizeof(double) * length );
    s_to_y = (double *) AlcMalloc(sizeof(double) * length );
    s_to_z = (double *) AlcMalloc(sizeof(double) * length );

    /* transform a perpendicular vector */
    vtx.vtX = 0.0;
    vtx.vtY = 0.0;
    vtx.vtZ = 1.0;
    Wlz3DSectionTransformInvVtx(&vtx, viewStr1);
    vtx1.vtX = 0.0;
    vtx1.vtY = 0.0;
    vtx1.vtZ = 0.0;
    Wlz3DSectionTransformInvVtx(&vtx1, viewStr1);
    vtx.vtX -= vtx1.vtX;
    vtx.vtY -= vtx1.vtY;
    vtx.vtZ -= vtx1.vtZ;

    /* assign lut values */
    s = (int )(WLZ_NINT(viewStr1->minvals.vtZ) - viewStr1->dist);
    for(sp=0; sp < length; sp++, s++){
      s_to_x[sp] = s * vtx.vtX;
      s_to_y[sp] = s * vtx.vtY;
      s_to_z[sp] = s * vtx.vtZ;
    }
  }

  /* if there is an integration function then allocate space for
     the grey-level array */
  if( (errNum == WLZ_ERR_NONE) && (intFunc) ){
    srcGType = WlzGreyTypeFromObj(obj, &errNum);
    switch( srcGType ){
    case WLZ_GREY_LONG:
      size = sizeof(WlzLong)*length;
      break;
    case WLZ_GREY_INT:
      size = sizeof(int)*length;
      break;
    case WLZ_GREY_SHORT:
      size = sizeof(short)*length;
      break;
    case WLZ_GREY_UBYTE:
      size = sizeof(WlzUByte)*length;
      break;
    case WLZ_GREY_FLOAT:
      size = sizeof(float)*length;
      break;
    case WLZ_GREY_DOUBLE:
      size = sizeof(double)*length;
      break;
    case WLZ_GREY_RGBA:
      size = sizeof(int)*length;
      break;
    default:
      errNum = WLZ_ERR_GREY_TYPE;
      break;
    }
    if( (pixptr.p.inp = (int *) AlcMalloc(size)) == NULL ){
      errNum = WLZ_ERR_MEM_ALLOC;
    }
    pixptr.type = srcGType;

    /* set up the grey-value workspace for random access */
    gVWSp = WlzGreyValueMakeWSp(obj, &errNum);
  }

  /* create rectangular projection image */
  if( errNum == WLZ_ERR_NONE ){
    if((domain.i = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_RECT,
				     WLZ_NINT(viewStr1->minvals.vtY),
				     WLZ_NINT(viewStr1->maxvals.vtY),
				     WLZ_NINT(viewStr1->minvals.vtX),
				     WLZ_NINT(viewStr1->maxvals.vtX),
					 &errNum)) != NULL){
      values.core = NULL;
      if((rtnObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, domain, values, NULL, NULL,
			       &errNum)) != NULL){
	/* note the grey-values required are determined by the integration
	   function. Here we use WlzUByte and reset later if needed */
	dstGType = WLZ_GREY_UBYTE;
	pixval.type = WLZ_GREY_UBYTE;
	pixval.v.ubv = (WlzUByte )0;
	if((values.v = WlzNewValueTb(rtnObj,
				     WlzGreyTableType(WLZ_GREY_TAB_RECT,
						      dstGType, NULL),
				     pixval, &errNum)) != NULL){
	  rtnObj->values = WlzAssignValues(values, &errNum);
	}
	else {
	  WlzFreeObj(rtnObj);
	  rtnObj = NULL;
	}
      }
      else {
	WlzFreeDomain(domain);
	domain.core = NULL;
      }
    }
  }

  /* scan image setting values */
  if( errNum == WLZ_ERR_NONE ){
    errNum = WlzInitGreyScan(rtnObj, &iwsp, &gwsp);
  }
  if( errNum == WLZ_ERR_NONE ){
    while( (errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE ){
      yp = iwsp.linpos - WLZ_NINT(viewStr1->minvals.vtY);
      for(k=iwsp.lftpos; k <= iwsp.rgtpos; k++){
	xp = k - WLZ_NINT(viewStr1->minvals.vtX);
	vtx.vtX = viewStr1->xp_to_x[xp] + viewStr1->yp_to_x[yp];
	vtx.vtY = viewStr1->xp_to_y[xp] + viewStr1->yp_to_y[yp];
	vtx.vtZ = viewStr1->xp_to_z[xp] + viewStr1->yp_to_z[yp];

	/* get the projection values */
	/* if no function then just check for occupancy */
	if( intFunc == NULL ){
	  occupiedFlg = 0;
	  sp = (int )(viewStr1->dist - WLZ_NINT(viewStr1->minvals.vtZ));
	  for(; !occupiedFlg && (sp < length); sp++){
	    x = vtx.vtX + s_to_x[sp];
	    y = vtx.vtY + s_to_y[sp];
	    z = vtx.vtZ + s_to_z[sp];
	    if( WlzInsideDomain(obj, z, y, x, &errNum) ){
	      occupiedFlg = 1;
	    }
	  }
	  sp = (int )(viewStr1->dist - WLZ_NINT(viewStr1->minvals.vtZ) - 1);
	  for(; !occupiedFlg && (sp >= 0); sp--){
	    x = vtx.vtX + s_to_x[sp];
	    y = vtx.vtY + s_to_y[sp];
	    z = vtx.vtZ + s_to_z[sp];
	    if( WlzInsideDomain(obj, z, y, x, &errNum) ){
	      occupiedFlg = 1;
	    }
	  }

	  /* set the integrated value - only WlzUByte at the moment */
	  *(gwsp.u_grintptr.ubp) = (WlzUByte )occupiedFlg;
	  gwsp.u_grintptr.ubp++;
	}
	/* use integration function */
	else {
	  /* set array of pixel values */
	  for(sp=0; sp < length; sp++){
	    x = vtx.vtX + s_to_x[sp];
	    y = vtx.vtY + s_to_y[sp];
	    z = vtx.vtZ + s_to_z[sp];
	    WlzGreyValueGet(gVWSp, WLZ_NINT(z), WLZ_NINT(y),
			    WLZ_NINT(x));
	    switch( srcGType ){
	    case WLZ_GREY_LONG:
	      pixptr.p.lnp[sp] = gVWSp->gVal[0].lnv;
	      break;
	    case WLZ_GREY_INT:
	      pixptr.p.inp[sp] = gVWSp->gVal[0].inv;
	      break;
	    case WLZ_GREY_SHORT:
	      pixptr.p.shp[sp] = gVWSp->gVal[0].shv;
	      break;
	    case WLZ_GREY_UBYTE:
	      pixptr.p.ubp[sp] = gVWSp->gVal[0].ubv;
	      break;
	    case WLZ_GREY_FLOAT:
	      pixptr.p.flp[sp] = gVWSp->gVal[0].flv;
	      break;
	    case WLZ_GREY_DOUBLE:
	      pixptr.p.dbp[sp] = gVWSp->gVal[0].dbv;
	      break;
	    case WLZ_GREY_RGBA:
	      pixptr.p.rgbp[sp] = gVWSp->gVal[0].rgbv;
	      break;
	    default:
	      errNum = WLZ_ERR_GREY_TYPE;
	      break;
	    }
	  }
	  /* call integration function and seet value */
	  intFunc(pixptr, length, (int )(viewStr1->dist -
		                         WLZ_NINT(viewStr1->minvals.vtZ)),
		  intFuncData, &errNum);
	}
      }
    }
    (void )WlzEndGreyScan(&iwsp, &gwsp);
    if(errNum == WLZ_ERR_EOO)	   /* Reset error from end of intervals */ 
    {
      errNum = WLZ_ERR_NONE;
    }

    /* if no integration function then threshold - binary only */
    if( intFunc == NULL ){
      pixval.v.ubv = 1;
      rtnObj = WlzAssignObject(rtnObj, NULL);
      if((obj1 = WlzThreshold(rtnObj, pixval, WLZ_THRESH_HIGH,
                              &errNum)) != NULL){
	WlzFreeObj(rtnObj);
	values.core = NULL;
	rtnObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, obj1->domain, values, NULL, NULL,
			     &errNum);
	WlzFreeObj(obj1);
      }
      else {
	WlzFreeObj(rtnObj);
	rtnObj = NULL;
      }
    }
  }

  /* clear space */
  if( viewStr1 ){
    errNum = WlzFree3DViewStruct(viewStr1);
  }
  if( s_to_x ){
    AlcFree( s_to_x );
  }
  if( s_to_y ){
    AlcFree( s_to_y );
  }
  if( s_to_z ){
    AlcFree( s_to_z );
  }

  /* check error and return */
  if( dstErr ){
    *dstErr = errNum;
  }
  return rtnObj;
}
Beispiel #10
0
int             main(int argc, char **argv)
{
  int		dim = 3,
  		nSPts,
  		nIPts,
		nOPts,
		option,
		planeFlg = 0,
		planeIdx = 0,
		ok = 1,
		usage = 0;
  double	delta,
  		tau,
		sAlpha,
		iAlpha,
		oAlpha,
		iDist,
		oDist,
		samFac = 1.0;
  WlzObject 	*dObj = NULL;
  WlzBox	bBox0,
  		bBox1;
  WlzVertexP	sPts,
  		iPts,
		oPts;
  WlzPixelV	bgdV;
  WlzDomain	outDom;
  WlzValues	dumVal;
  WlzObject	*outObj = NULL;
  FILE		*fP = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  char 		*sFileStr,
  		*iFileStr,
  		*oFileStr,
		*outObjFileStr;
  const char    *errMsg;
  static char	optList[] = "h23o:S:I:O:a:b:c:d:e:D:M:T:X:",
		defFileStr[] = "-";

  bgdV.type = WLZ_GREY_DOUBLE;
  outDom.core = NULL;
  dumVal.core = NULL;
  sPts.v = iPts.v = oPts.v = NULL;
  /* Parse the command line. */
  opterr = 0;
  sFileStr = iFileStr = oFileStr = outObjFileStr = defFileStr;
  while(ok && ((option = getopt(argc, argv, optList)) != -1))
  {
    switch(option)
    {
      case '2':
        dim = 2;
	break;
      case '3':
        dim = 3;
	break;
      case 'o':
        outObjFileStr = optarg;
	break;
      case 'S':
        sFileStr = optarg;
	break;
      case 'I':
        iFileStr = optarg;
	break;
      case 'O':
        oFileStr = optarg;
	break;
      case 'a':
        if(sscanf(optarg, "%lg", &sAlpha) != 1)
	{
	  usage = 1;
	}
	break;
      case 'b':
        if(sscanf(optarg, "%lg", &iAlpha) != 1)
	{
	  usage = 1;
	}
	break;
      case 'c':
        if(sscanf(optarg, "%lg", &oAlpha) != 1)
	{
	  usage = 1;
	}
	break;
      case 'd':
        if(sscanf(optarg, "%lg", &iDist) != 1)
	{
	  usage = 1;
	}
	break;
      case 'e':
        if(sscanf(optarg, "%lg", &oDist) != 1)
	{
	  usage = 1;
	}
	break;
      case 'D':
        if(sscanf(optarg, "%lg", &delta) != 1)
	{
	  usage = 1;
	}
	break;
      case 'M':
        if(sscanf(optarg, "%lg", &samFac) != 1)
	{
	  usage = 1;
	}
	break;
      case 'T':
        if(sscanf(optarg, "%lg", &tau) != 1)
	{
	  usage = 1;
	}
	break;
      case 'X':
        if(sscanf(optarg, "%d", &planeIdx) != 1)
	{
	  usage = 1;
	}
	else
	{
	  planeFlg = 1;
	}
	break;
      case 'h':
      default:
        usage = 1;
	break;
    }
  }
  if(ok && (optind < argc))
  {
    usage = 1;
  }
  if((outObjFileStr == NULL) || (*outObjFileStr == '\0') ||
     (sFileStr == NULL) || (*sFileStr == '\0') ||
     (iFileStr == NULL) || (*iFileStr == '\0') ||
     (oFileStr == NULL) || (*oFileStr == '\0'))
  {
    usage = 1;
  }
  ok = ok && !usage;
  /* Read the surface, inside and outside points. */
  if(ok)
  {
    if(strcmp(sFileStr, "-"))
    {
      if((fP = fopen(sFileStr, "r")) == NULL)
      {
	ok = 0;
	errNum = WLZ_ERR_READ_EOF;
	(void )WlzStringFromErrorNum(errNum, &errMsg);
	(void )fprintf(stderr,
		       "%s: failed to open surface points file %s (%s).\n",
		       *argv, sFileStr, errMsg);
      }
    }
    else
    {
      fP = stdin;
    }
  }
  if(ok)
  {
    sPts = WlzCFPReadVtxArray(fP, dim, &nSPts, &errNum);
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
	             "%s: failed to read points from file %s (%s).\n",
		     *argv, sFileStr, errMsg);
    }
  }
  if(fP)
  {
    if(strcmp(sFileStr, "-"))
    {
      (void )fclose(fP);
    }
    fP = NULL;
  }
  if(ok)
  {
    if(strcmp(sFileStr, "-"))
    {
      if((fP = fopen(iFileStr, "r")) == NULL)
      {
	ok = 0;
	errNum = WLZ_ERR_READ_EOF;
	(void )WlzStringFromErrorNum(errNum, &errMsg);
	(void )fprintf(stderr,
		       "%s: failed to open inside points file %s (%s).\n",
		       *argv, iFileStr, errMsg);
      }
    }
    else
    {
      fP = stdin;
    }
  }
  if(ok)
  {
    iPts = WlzCFPReadVtxArray(fP, dim, &nIPts, &errNum);
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
	             "%s: failed to read points from file %s (%s).\n",
		     *argv, sFileStr, errMsg);
    }
  }
  if(fP)
  {
    if(strcmp(iFileStr, "-"))
    {
      (void )fclose(fP);
    }
    fP = NULL;
  }
  if(ok)
  {
    if(strcmp(sFileStr, "-"))
    {
      if((fP = fopen(oFileStr, "r")) == NULL)
      {
	ok = 0;
	errNum = WLZ_ERR_READ_EOF;
	(void )WlzStringFromErrorNum(errNum, &errMsg);
	(void )fprintf(stderr,
		       "%s: failed to open outside points file %s (%s).\n",
		       *argv, oFileStr, errMsg);
      }
    }
    else
    {
      fP = stdin;
    }
  }
  if(ok)
  {
    oPts = WlzCFPReadVtxArray(fP, dim, &nOPts, &errNum);
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
	             "%s: failed to read points from file %s (%s).\n",
		     *argv, oFileStr, errMsg);
    }
  }
  if(fP)
  {
    if(strcmp(oFileStr, "-"))
    {
      (void )fclose(fP);
    }
    fP = NULL;
  }
  if(ok)
  {
    bgdV.v.dbv = oDist;
    bgdV.type = WLZ_GREY_DOUBLE;
    switch(dim)
    {
      case 2:
        errNum = WLZ_ERR_UNIMPLEMENTED;
	break;
      case 3:
	/* Compute ounding box of points. */
	bBox0.d3 = WlzBoundingBoxVtx3D(nSPts, sPts.d3, NULL);
	bBox1.d3 = WlzBoundingBoxVtx3D(nIPts, iPts.d3, NULL);
	bBox0.d3 = WlzBoundingBoxUnion3D(bBox0.d3, bBox1.d3);
	bBox1.d3 = WlzBoundingBoxVtx3D(nOPts, oPts.d3, NULL);
	bBox0.d3 = WlzBoundingBoxUnion3D(bBox0.d3, bBox1.d3);
	/* Create distance object that will be used to accumulate distance
	   values. If only a 2D contour is required then create a distance
	   object with a single plane. */
	dObj = WlzMakeCuboid((planeFlg)?
	                     planeIdx: (int )floor(bBox0.d3.zMin) - 2,
			     (planeFlg)?
			     planeIdx: (int )ceil(bBox0.d3.zMax) + 2,
			     (int )floor(bBox0.d3.yMin) - 2,
			     (int )ceil(bBox0.d3.yMax) + 2,
			     (int )floor(bBox0.d3.xMin) - 2,
			     (int )ceil(bBox0.d3.xMax) + 2,
			     WLZ_GREY_DOUBLE, bgdV,
			     NULL, NULL, &errNum);
	if((dObj == NULL) || (errNum != WLZ_ERR_NONE))
	{
	  ok = 0;
	  if(errNum == WLZ_ERR_NONE)
	  {
	    errNum = WLZ_ERR_MEM_ALLOC;
	  }
	  (void )WlzStringFromErrorNum(errNum, &errMsg);
	  (void )fprintf(stderr,
	  		 "%s: failed to allocate distance object (%s).\n",
			 *argv, errMsg);

	}
	/* Compute contour using given distance object. */
	outDom.ctr = WlzContourFromPoints(dObj, WLZ_VERTEX_D3,
					  nSPts, sPts, sAlpha,
					  nIPts, iPts, iDist, iAlpha,
					  nOPts, oPts, oDist, oAlpha,
					  delta, tau, samFac,
					  &errNum);
	WlzFreeObj(dObj);
	break;
    }
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
	             "%s: failed to compute contour from points (%s).\n",
		     *argv, errMsg);
    }
  }
  /* Compute the contour from the point sets. */
  if(ok)
  {
    outObj = WlzMakeMain(WLZ_CONTOUR, outDom, dumVal, NULL, NULL, &errNum);
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
                     "%s: Failed to create output woolz object (%s).\n",
                     argv[0], errMsg);
    }
    if(outObj)
    {
      outDom.core = NULL;
    }
  }
  /* Write out the contour object. */
  if(ok)
  {
    if(strcmp(outObjFileStr, "-"))
    {
      if((fP = fopen(outObjFileStr, "w")) == NULL)
      {
	ok = 0;
	errNum = WLZ_ERR_WRITE_EOF;
	(void )WlzStringFromErrorNum(errNum, &errMsg);
	(void )fprintf(stderr,
		       "%s: failed to open output object file %s (%s).\n",
		       *argv, outObjFileStr, errMsg);
      }
    }
    else
    {
      fP = stdout;
    }
    if(ok)
    {
      if((errNum = WlzWriteObj(fP, outObj)) != WLZ_ERR_NONE)
      {
	ok = 0;
	(void )WlzStringFromErrorNum(errNum, &errMsg);
	(void )fprintf(stderr,
		       "%s: failed to write output object to file %s (%s).\n",
		       *argv, outObjFileStr, errMsg);
      }
    }
    if(strcmp(outObjFileStr, "-"))
    {
      (void )fclose(fP);
    }
    fP = NULL;
  }
  AlcFree(sPts.v);
  AlcFree(iPts.v);
  AlcFree(oPts.v);
  (void )WlzFreeDomain(outDom);
  (void )WlzFreeObj(outObj);
  /* Tidy up and exit. */
  if(usage)
  {
    (void )fprintf(stderr,
    "Usage: %s%s",
    *argv,
    "WlzContourFromPoints [-h] [-2] [-3] [-o<out object>]\n"
    "                     [-S<surface points file>]\n"
    "                     [-I<inside points file>] [-O<outside points file>]\n"
    "                     [-a#] [-b#] [-c#] [-d#] [-e#] [-D#] [-M#] [-T#]\n"
    "                     [-X#]\n"
    "Options:\n"
    "  -h  Print this usage message.\n"
    "  -2  Points are 2D and contour is a curve in 2D.\n"
    "  -3  Points are 3D and contour is a surface in 3D.\n"
    "  -o  Output object file name.\n"
    "  -S  On surface points file.\n"
    "  -I  Inside points file.\n"
    "  -O  Outside points file.\n"
    "  -a  Surface points alpha value.\n"
    "  -b  Inside points alpha value.\n"
    "  -c  Outside points alpha value.\n"
    "  -d  Inside points distance value.\n"
    "  -e  Outside points distance value.\n"
    "  -D  Delta multiorder spline soothing value.\n"
    "  -M  Distance object sampling factor (can be used to reduce the\n"
    "      number of surface facets.)\n"
    "  -T  Tau multiorder spline soothing value.\n"
    "  -X  Plane for 2D contour from 3D point sets.\n"
    "Computes a contour from three point sets: inside; outside and on a\n"
    "surface.\n"
    "All points are given using the following ascii format:\n"
    "  <vertex x> <vertex y> [<vertex z>]\n");
  }
  return(!ok);
}
Beispiel #11
0
/*!
* \return	New Woolz domain object with gradient grey values or NULL
*		on error.
* \ingroup      WlzValuesFilters
* \brief	Computes the magnitude of the gray values in the
*               3 given Woolz 3D domain objects.
* \param	srcObj0			First object.
* \param	srcObj1			Second object.
* \param	srcObj2			Third object.
* \param	dstErr			Destination error pointer, may
*                                       be null.
*/
static 	WlzObject *WlzGreyMagnitude3D(WlzObject *srcObj0, WlzObject *srcObj1,
				      WlzObject *srcObj2, WlzErrorNum *dstErr)
{
  int		idN,
		idP,
  		nPlanes;
  WlzDomain	dstDom;
  WlzValues	dstVal;
  WlzObject	*dstObj2D,
  		*istObj = NULL,
		*dstObj = NULL;
  WlzObject	*srcObjA[3],
  		*iObj3DA[3],
  		*iObj2DA[3];
  WlzPixelV	bgdV;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  dstDom.core = NULL;
  dstVal.core = NULL;
  iObj3DA[0] = iObj3DA[1] = iObj3DA[2] = NULL;
  if((srcObj0->domain.core->type != WLZ_PLANEDOMAIN_DOMAIN) ||
     (srcObj1->domain.core->type != WLZ_PLANEDOMAIN_DOMAIN) ||
     (srcObj2->domain.core->type != WLZ_PLANEDOMAIN_DOMAIN))
  {
    errNum = WLZ_ERR_DOMAIN_TYPE;
  }
  else if ((srcObj0->values.core->type != WLZ_VOXELVALUETABLE_GREY) ||
           (srcObj1->values.core->type != WLZ_VOXELVALUETABLE_GREY) ||
	   (srcObj2->values.core->type != WLZ_VOXELVALUETABLE_GREY))
  {
    errNum = WLZ_ERR_VALUES_TYPE;
  }
  else
  {
    srcObjA[0] = srcObj0;
    srcObjA[1] = srcObj1;
    srcObjA[2] = srcObj2;
    istObj = WlzIntersectN(3, srcObjA, 0, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if(istObj->type == WLZ_EMPTY_OBJ)
    {
      dstObj = istObj;
    }
    else
    {
      dstDom = WlzAssignDomain(istObj->domain, NULL);
      WlzFreeObj(istObj);
      idN = 0;
      while((errNum == WLZ_ERR_NONE) && (idN < 3))
      {
        iObj3DA[idN] = WlzMakeMain(WLZ_3D_DOMAINOBJ,
				   dstDom, srcObjA[idN]->values,
				   NULL, NULL, &errNum);
        ++idN;
      }
      if(errNum == WLZ_ERR_NONE)
      {
	idP = 0;
        nPlanes = dstDom.p->lastpl - dstDom.p->plane1 + 1;
	while((errNum == WLZ_ERR_NONE) &&
	      (idP < nPlanes))
        {
	  if((dstDom.p->domains + idN)->core == NULL)
	  {
	    (dstVal.vox->values + idP)->core = NULL;
	  }
	  else
	  {
	    dstObj2D = NULL;
	    iObj2DA[0] = iObj2DA[1] = iObj2DA[2] = NULL;
	    idN = 0;
	    /* Make 2D objects. */
	    while((errNum == WLZ_ERR_NONE) && (idN < 3))
	    {
	      iObj2DA[idN] = WlzMakeMain(WLZ_2D_DOMAINOBJ,
				    *(iObj3DA[idN]->domain.p->domains + idP),
				    *(iObj3DA[idN]->values.vox->values + idP),
				    NULL, NULL, &errNum);
	      ++idN;
	    }
	    /* Compute magnitude. */
	    if(errNum == WLZ_ERR_NONE)
	    {
	      dstObj2D = WlzGreyMagnitude2D3(iObj2DA[0], iObj2DA[1],
					     iObj2DA[2], &errNum);
	    }
	    /* If first plane get grey type and background, then create new
	     * 3D object with new voxel values. */
	    if((idP == 0) && (errNum == WLZ_ERR_NONE))
	    {
      	      bgdV = WlzGetBackground(iObj2DA[0], &errNum);
	      if(errNum == WLZ_ERR_NONE)
	      {
		dstVal.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY,
						 dstDom.p->plane1,
						 dstDom.p->lastpl,
						 bgdV, NULL, &errNum);
	      }
	      if(errNum == WLZ_ERR_NONE)
	      {
	        dstObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, dstDom, dstVal,
				     NULL, NULL, &errNum);
	      }
	    }
	    /* Add 2D values to the 3D objects values. */
	    if(errNum == WLZ_ERR_NONE)
	    {
	      *(dstVal.vox->values + idP) = WlzAssignValues(dstObj2D->values,
	      						    NULL);
	    }
	    /* Free temporary 2D object. */
	    if(dstObj2D)
	    {
	      WlzFreeObj(dstObj2D);
	    }
	    idN = 0;
	    while(idN < 3)
	    {
	      if(iObj2DA[idN])
	      {
		WlzFreeObj(iObj2DA[idN]);
	      }
	      ++idN;
	    }
	  }
	  ++idP;
	}
      }
      /* Free 3D intersection gradient objects. */
      idN = 0;
      while(idN < 3)
      {
	if(iObj3DA[idN])
	{
	  WlzFreeObj(iObj3DA[idN]);
	}
	++idN;
      }
      /* Decrement link count to the destination 3D domain. */
      (void )WlzFreeDomain(dstDom);
    }
  }
  if((errNum != WLZ_ERR_NONE) && (dstObj != NULL))
  {
    WlzFreeObj(dstObj);
    dstObj = NULL;
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(dstObj);
}