Example #1
0
/*!
* \return	New Woolz domain object with gradient grey values or
*		NULL on error.
* \ingroup      WlzValuesFilters
* \brief	Computes the gradient of the gray values in the
*               given Woolz 2D domain object.
* \param	dstGrdY			Destination pointer for the
*                                       gradient (partial derivative)
*                                       through lines, may be NULL.
* \param	dstGrdX			Destination pointer for the
*                                       gradient (partial derivative)
*                                       through columns, may be NULL.
* \param	srcObj			Given source object.
* \param	flt			Recursive filter to use.
* \param	dstErr			Destination error pointer, may
*                                       be null.
*/
static WlzObject *WlzGreyGradient2D(WlzObject **dstGrdY, WlzObject **dstGrdX,
				    WlzObject *srcObj,
				    WlzRsvFilter *flt, WlzErrorNum *dstErr)
{
  WlzObject	*grdX = NULL,
  		*grdY = NULL,
		*dstObj = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  if(srcObj == NULL)
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if(srcObj->domain.core == NULL)
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if(srcObj->values.core == NULL)
  {
    errNum = WLZ_ERR_VALUES_NULL;
  }
  else if(WlzGreyTableIsTiled(srcObj->values.core->type))
  {
    errNum = WLZ_ERR_VALUES_TYPE;
  }
  if(errNum == WLZ_ERR_NONE)
  {
    grdX = WlzRsvFilterObj(srcObj, flt, WLZ_RSVFILTER_ACTION_X, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    grdY = WlzRsvFilterObj(srcObj, flt, WLZ_RSVFILTER_ACTION_Y, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    dstObj = WlzImageArithmetic(grdY, grdX, WLZ_BO_MAGNITUDE, 0, &errNum);
  }
  if(dstGrdX && (errNum == WLZ_ERR_NONE))
  {
    *dstGrdX = grdX;
  }
  else if(grdX)
  {
    WlzFreeObj(grdX);
  }
  if(dstGrdY && (errNum == WLZ_ERR_NONE))
  {
    *dstGrdY = grdY;
  }
  else if(grdY)
  {
    WlzFreeObj(grdY);
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(dstObj);
}
/*!
* \return	Woolz error code.
* \ingroup	WlzArithmetic
* \brief	Increments all valus of the firstobjct which are within
* 		the domain of the second object. The domain of the first
* 		object must cover that of the second.
* \param	gObj		First object.
* \param	dObj		Second object.
*/
WlzErrorNum	WlzGreyIncValuesInDomain(WlzObject *gObj, WlzObject *dObj)
{
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  if((gObj == NULL) || (dObj == NULL))
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if((gObj->domain.core == NULL) || (dObj->domain.core == NULL))
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if(gObj->type != dObj->type)
  {
    errNum = WLZ_ERR_OBJECT_TYPE;
  }
  else if(gObj->values.core == NULL)
  {
    errNum = WLZ_ERR_VALUES_NULL;
  }
  else if(WlzGreyTableIsTiled(gObj->values.core->type))
  {
    errNum = WLZ_ERR_VALUES_TYPE;
  }
  else
  {
    switch(gObj->type)
    {
      case WLZ_2D_DOMAINOBJ:
	errNum = WlzGreyIncValuesInDomain2D(gObj, dObj);
        break;
      case WLZ_3D_DOMAINOBJ:
	errNum = WlzGreyIncValuesInDomain3D(gObj, dObj);
        break;
      default:
	errNum = WLZ_ERR_OBJECT_TYPE;
        break;
    }
  }
  return(errNum);
}
Example #3
0
/*!
* \return	Grey value work space or NULL on error.
* \ingroup	WlzAccess
* \brief	Creates a grey value work space from the given object.
*		The resulting grey value work space should be freed
*		using WlzGreyValueFreeWSp().
* \param	obj			Given object.
* \param	dstErrNum		Destination error pointer, may be NULL.
*/
WlzGreyValueWSpace *WlzGreyValueMakeWSp(WlzObject *obj,
					WlzErrorNum *dstErrNum)
{
  int		planeIdx, numPlanes;
  WlzDomain	*planeDomains;
  WlzValues	*planeValues;
  WlzObjectType	gTabType0,
	        gTabType1 = WLZ_DUMMY_ENTRY;
  WlzGreyType	gType0 = WLZ_GREY_ERROR,
		gType1 = WLZ_GREY_ERROR;
  WlzPixelV	bkdPix;
  WlzAffineTransform *trans0,
  		*trans1;
  WlzGreyValueWSpace *gVWSp = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  bkdPix.v.ubv = 0;
  bkdPix.type = WLZ_GREY_INT;
  WLZ_DBG((WLZ_DBG_LVL_1),
  	   ("WlzGreyValueMakeWSp FE %p %p\n",
	    obj, dstErrNum));
  if(obj == NULL)
  {
    errNum = WLZ_ERR_PARAM_DATA;
  }
  else
  {
    switch(obj->type)
    {
      case WLZ_2D_DOMAINOBJ:
	if(obj->domain.core == NULL)
	{
	  errNum = WLZ_ERR_DOMAIN_NULL;
	}
	else if(obj->values.core == NULL)
	{
	  errNum = WLZ_ERR_VALUES_NULL;
	}
	else if((gVWSp = (WlzGreyValueWSpace *)AlcCalloc(1,
					  sizeof(WlzGreyValueWSpace))) == NULL)
	{
	  errNum = WLZ_ERR_MEM_ALLOC;
	}
	else
	{
	  gVWSp->objType = obj->type;
	  gVWSp->values = obj->values;
	  gVWSp->gType = WlzGreyTableTypeToGreyType(obj->values.core->type,
	  					    &errNum);
	  if(errNum == WLZ_ERR_NONE)
	  {
	    gVWSp->gTabType = WlzGreyTableTypeToTableType(
	    				obj->values.core->type,
					&errNum);
	    gVWSp->gTabType2D = gVWSp->gTabType;
	  }
	  if(errNum == WLZ_ERR_NONE)
	  {
	    switch(gVWSp->gTabType2D)
	    {
	      case WLZ_GREY_TAB_RAGR:
	        gVWSp->values2D = obj->values;
		bkdPix = gVWSp->values2D.v->bckgrnd;
		break;
	      case WLZ_GREY_TAB_RECT:
	        gVWSp->values2D = obj->values;
		bkdPix = gVWSp->values2D.r->bckgrnd;
		break;
	      case WLZ_GREY_TAB_INTL:
	        gVWSp->values2D = obj->values;
		bkdPix = gVWSp->values2D.i->bckgrnd;
		break;
	      case WLZ_GREY_TAB_TILED:
	        gVWSp->values2D = obj->values;
		bkdPix = gVWSp->values2D.t->bckgrnd;
		break;
	      default:
		errNum = WLZ_ERR_VALUES_TYPE;
		break;
	    }
	  }
	  if(errNum == WLZ_ERR_NONE)
	  {
	    switch(gVWSp->gType)
	    {
	      case WLZ_GREY_LONG:
	      case WLZ_GREY_INT:
	      case WLZ_GREY_SHORT:
	      case WLZ_GREY_UBYTE:
	      case WLZ_GREY_FLOAT:
	      case WLZ_GREY_DOUBLE:
	      case WLZ_GREY_RGBA:
		break;
	      default:
		errNum = WLZ_ERR_GREY_TYPE;
		break;
	    }
	  }
	  if((gVWSp->gType != bkdPix.type) && (errNum == WLZ_ERR_NONE))
	  {
	    errNum = WLZ_ERR_VALUES_DATA;
	  }
	}
	if(errNum == WLZ_ERR_NONE)
	{
	  gVWSp->gBkd = bkdPix.v;
	  gVWSp->domain = obj->domain;
	  gVWSp->iDom2D = obj->domain.i;
	  if((gVWSp->iDom2D->type != WLZ_INTERVALDOMAIN_INTVL) &&
	     (gVWSp->iDom2D->type != WLZ_INTERVALDOMAIN_RECT))
	  {
	    errNum = WLZ_ERR_DOMAIN_TYPE;
	  }
	}
	break;
      case WLZ_3D_DOMAINOBJ:
	if(obj->domain.core == NULL)
	{
	  errNum = WLZ_ERR_DOMAIN_NULL;
	}
	else if(obj->values.core == NULL)
	{
	  errNum = WLZ_ERR_VALUES_NULL;
	}
	else if(obj->domain.core->type != WLZ_PLANEDOMAIN_DOMAIN)
	{
	  errNum = WLZ_ERR_DOMAIN_TYPE;
	}
	else if((gVWSp = (WlzGreyValueWSpace *)AlcCalloc(1,
					  sizeof(WlzGreyValueWSpace))) == NULL)
	{
	  errNum = WLZ_ERR_MEM_ALLOC;
	}
	else
	{
	  gVWSp->objType = obj->type;
	  gVWSp->domain = obj->domain;
	  gVWSp->values = obj->values;
	  if(WlzGreyTableIsTiled(obj->values.core->type) == WLZ_GREY_TAB_TILED)
	  {
	    gVWSp->gTabType = WLZ_GREY_TAB_TILED;
	    gVWSp->gTabType2D = WLZ_GREY_TAB_TILED;
	    gVWSp->gType = WlzGreyTableTypeToGreyType(
	        obj->values.core->type, &errNum);
	    gVWSp->plane = obj->domain.p->plane1;
	    gVWSp->iDom2D = (*(obj->domain.p->domains)).i;
	    gVWSp->gBkd = obj->values.t->bckgrnd.v;
	    if(obj->values.t->bckgrnd.type != gVWSp->gType)
	    {
	      errNum = WLZ_ERR_VALUES_DATA;
	    }
	  }
	  else
	  {
	    gVWSp->gTabType = WLZ_VOXELVALUETABLE_GREY;
	    /* Put in a list of grey-table types - purely for efficiency
	       to avoid re-computing the type for each voxel request.
	       When table types are no longer computed this in principle
	       could go */
	    numPlanes = obj->domain.p->lastpl - obj->domain.p->plane1 + 1;
	    if((gVWSp->gTabTypes3D = (WlzObjectType *)
			  AlcCalloc(numPlanes, sizeof(WlzObjectType))) == NULL)
	    {
	      errNum = WLZ_ERR_MEM_ALLOC;
	    }
	    if(errNum == WLZ_ERR_NONE)
	    {
	      WlzObjectType	*gTabTypes3D;

	      gVWSp->values2D.core = NULL;
	      planeIdx = obj->domain.p->plane1;
	      planeDomains = obj->domain.p->domains;
	      planeValues = obj->values.vox->values;
	      gTabTypes3D = gVWSp->gTabTypes3D;
	      while((planeIdx <= obj->domain.p->lastpl) &&
		    (errNum == WLZ_ERR_NONE))
	      {
		if(((*planeValues).core) &&
		   ((*planeValues).core->type != WLZ_EMPTY_OBJ))
		{
		  gType0 = WlzGreyTableTypeToGreyType(
		      (*planeValues).core->type, &errNum);
		  if(errNum == WLZ_ERR_NONE)
		  {
		    gTabType0 = WlzGreyTableTypeToTableType((*planeValues).
			                                    core->type,
							    &errNum);
		    *gTabTypes3D = gTabType0;
		  }
		  if(errNum == WLZ_ERR_NONE)
		  {
		    if((gType0 != gType1) && (gType1 != WLZ_GREY_ERROR))
		    {
		      errNum = WLZ_ERR_VALUES_DATA;
		    }
		    else
		    {
		      gType1 = gType0;
		      gTabType1 = gTabType0;
		      if(gVWSp->values2D.core == NULL)
		      {
			gVWSp->plane = planeIdx;
			gVWSp->iDom2D = (*planeDomains).i;
			gVWSp->values2D = *planeValues;
		      }
		    }
		  }
		}
		++planeIdx;
		++planeDomains;
		++planeValues;
		++gTabTypes3D;
	      }
	      if((gType1 == WLZ_GREY_ERROR) || (gTabType1 == WLZ_DUMMY_ENTRY))
	      {
		errNum = WLZ_ERR_VALUES_DATA;
	      }
	    }
	    if(errNum == WLZ_ERR_NONE)
	    {
	      gVWSp->gType = gType0;
	      gVWSp->gTabType2D = gVWSp->gTabTypes3D[0];
	      switch(gVWSp->gTabType2D)
	      {
		case WLZ_GREY_TAB_RAGR:
		  bkdPix = gVWSp->values2D.v->bckgrnd;
		  break;
		case WLZ_GREY_TAB_RECT:
		  bkdPix = gVWSp->values2D.r->bckgrnd;
		  break;
		case WLZ_GREY_TAB_INTL:
		  bkdPix = gVWSp->values2D.i->bckgrnd;
		  break;
		case WLZ_GREY_TAB_TILED:
		  bkdPix = gVWSp->values2D.t->bckgrnd;
		  break;
		default:
		  errNum = WLZ_ERR_VALUES_TYPE;
		  break;
	      }
	      if((gVWSp->gType != bkdPix.type) && (errNum == WLZ_ERR_NONE))
	      {
		errNum = WLZ_ERR_VALUES_DATA;
	      }
	      else if((gVWSp->iDom2D->type != WLZ_INTERVALDOMAIN_INTVL) &&
		      (gVWSp->iDom2D->type != WLZ_INTERVALDOMAIN_RECT))
	      {
		errNum = WLZ_ERR_DOMAIN_TYPE;
	      }
	      else
	      {
		gVWSp->gBkd = bkdPix.v;
	      }
	    }
	  }
	}
	break;
      case WLZ_TRANS_OBJ:
	trans0 = NULL;
	while((errNum == WLZ_ERR_NONE) && (obj->type == WLZ_TRANS_OBJ))
	{
	  if(trans0 == NULL)
	  {
	    trans0 = WlzAffineTransformCopy(obj->domain.t, &errNum);
	  }
	  else
	  {
	    if((trans1 = WlzAffineTransformProduct(trans0, obj->domain.t,
	    				           &errNum)) != NULL)
	    {
	      WlzFreeAffineTransform(trans0);
	      trans0 = trans1;
	      trans1 = NULL;
	    }
	  }
	  if((obj = obj->values.obj) == NULL)
	  {
	    errNum = WLZ_ERR_OBJECT_NULL;
	  }
	}
	if(errNum == WLZ_ERR_NONE)
	{
	  gVWSp = WlzGreyValueMakeWSp(obj, &errNum);
	}
	if(errNum == WLZ_ERR_NONE)
	{
	  gVWSp->invTrans = WlzAffineTransformInverse(trans0, &errNum);
	}
	if(trans0)
	{
	  WlzFreeAffineTransform(trans0);
	}
	break;
      default:
	errNum = WLZ_ERR_OBJECT_TYPE;
	break;
    }
  }
  if((errNum != WLZ_ERR_NONE) && (gVWSp != NULL))
  {
    WlzGreyValueFreeWSp(gVWSp);
    gVWSp = NULL;
  }
  if(dstErrNum)
  {
    *dstErrNum = errNum;
  }
  WLZ_DBG((WLZ_DBG_LVL_FN|WLZ_DBG_LVL_1),
  	  ("WlzGreyValueMakeWSp FX %p\n",
	   gVWSp));
  return(gVWSp);
}
Example #4
0
/*! 
* \ingroup      WlzValuesFilters
* \brief        Perform 2D seperable transform on a 2D grey-level image.
* 		It is the users responsibility to ensure that the grey-value
* 		types are appropriate.
* 		Now extended to include compound objects.
*
* \return       Pointer to transformed object
* \param    obj	Input object pointer
* \param    x_fun	Convolution function to be applied in the x-direction (along the rows).
* \param    x_params	Parameter pointer to be passed to the x-function.
* \param    y_fun	Convolution function to be applied in the y-direction (down the columns).
* \param    y_params	Parameter pointer to be passed to the y-function.
* \param    dstErr	error return.
* \par      Source:
*                WlzSepTrans.c
*/
WlzObject *WlzSepTrans(
  WlzObject		*obj,
  WlzIntervalConvFunc	x_fun,
  void			*x_params,
  WlzIntervalConvFunc	y_fun,
  void			*y_params,
  WlzErrorNum		*dstErr)
{
  WlzIntervalWSpace	iwspace;
  WlzGreyWSpace		gwspace;
  WlzSepTransWSpace	stwspc;
  WlzValues		values;
  WlzObject		*obj1, *obj2;
  int			i, width, height;
  WlzCompoundArray	*cobj1, *cobj2;
  WlzErrorNum		errNum=WLZ_ERR_NONE;

  /* check object pointers and type */
  obj2 = NULL;
  stwspc.outbuf.p.dbp = NULL;
  if( obj == NULL ){
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else {
    switch( obj->type ){

    case WLZ_2D_DOMAINOBJ:
      /* check domain and valuetable */
      if( obj->domain.core == NULL ){
	errNum = WLZ_ERR_DOMAIN_NULL;
	break;
      }
      if( obj->values.core == NULL ){
	errNum = WLZ_ERR_VALUES_NULL;
	break;
      }
      if(WlzGreyTableIsTiled(obj->values.core->type)){
	errNum = WLZ_ERR_VALUES_TYPE;
	break;
      }
      break;

    default:
    case WLZ_3D_DOMAINOBJ:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;

    case WLZ_TRANS_OBJ:
      if((obj1 = WlzSepTrans(obj->values.obj,
			     x_fun, x_params, y_fun, y_params,
			     &errNum)) != NULL){
	values.obj = obj1;
	return WlzMakeMain(obj->type, obj->domain, values,
			   NULL, obj, dstErr);
      }
      break;

    case WLZ_COMPOUND_ARR_1:
    case WLZ_COMPOUND_ARR_2:
      cobj1 = (WlzCompoundArray *) obj;
      if((cobj2 = WlzMakeCompoundArray(cobj1->type, 1, cobj1->n, NULL,
				       cobj1->otype, &errNum)) != NULL){
	/* transform each object, ignore type errors */
	for(i=0; i < cobj1->n; i++){
	  cobj2->o[i] =
	    WlzAssignObject(WlzSepTrans(cobj1->o[i],
					x_fun, x_params, y_fun, y_params,
					&errNum), NULL);
	}
	return (WlzObject *) cobj2;
      }
      break;

    case WLZ_EMPTY_OBJ:
      return WlzMakeEmpty(dstErr);
    }
  }

  /* make space for a calculation buffer - assume worst case of doubles */
  if( errNum == WLZ_ERR_NONE ){
    width  = obj->domain.i->lastkl - obj->domain.i->kol1 + 1;
    height = obj->domain.i->lastln - obj->domain.i->line1 + 1;
    stwspc.inbuf.type = WlzGreyTableTypeToGreyType(obj->values.core->type,
						   NULL);
    stwspc.bckgrnd = WlzGetBackground(obj, NULL);

    switch( stwspc.inbuf.type ){
    case WLZ_GREY_INT:
    case WLZ_GREY_SHORT:
    case WLZ_GREY_UBYTE:
      stwspc.outbuf.type = WLZ_GREY_INT;
      break;
    default:
      stwspc.outbuf.type = stwspc.inbuf.type;
      break;
    }

    if( (stwspc.outbuf.p.dbp = (double *) 
	 AlcMalloc(sizeof(double)*(width>height?width:height))) == NULL){
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }

  /* tranpose the object - interchange x & y coordinates */
  if( errNum == WLZ_ERR_NONE ){
    obj1 = WlzTransposeObj(obj, &errNum);
  }

  /* perform the y convolution */
  if((errNum == WLZ_ERR_NONE) &&
     ((errNum = WlzInitGreyScan(obj1, &iwspace, &gwspace)) == WLZ_ERR_NONE))
  {
    while( (errNum = WlzNextGreyInterval(&iwspace)) == WLZ_ERR_NONE ){
      stwspc.inbuf.p.inp = gwspace.u_grintptr.inp;
      stwspc.len = iwspace.rgtpos - iwspace.lftpos + 1;
      if((errNum = (*y_fun)(&stwspc, y_params)) == WLZ_ERR_NONE){
	switch(  stwspc.inbuf.type ){
	case WLZ_GREY_INT:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.inp++)
	    *stwspc.inbuf.p.inp = stwspc.outbuf.p.inp[i];
	  break;
	case WLZ_GREY_SHORT:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.shp++)
	    *stwspc.inbuf.p.shp = (short )(stwspc.outbuf.p.inp[i]);
	  break;
	case WLZ_GREY_UBYTE:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.ubp++)
	    *stwspc.inbuf.p.ubp = (WlzUByte )(stwspc.outbuf.p.inp[i]);
	  break;
	case WLZ_GREY_FLOAT:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.flp++)
	    *stwspc.inbuf.p.flp = stwspc.outbuf.p.flp[i];
	  break;
	case WLZ_GREY_DOUBLE:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.dbp++)
	    *stwspc.inbuf.p.dbp = stwspc.outbuf.p.dbp[i];
	  break;
	case WLZ_GREY_RGBA:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.rgbp++)
	    *stwspc.inbuf.p.rgbp = stwspc.outbuf.p.rgbp[i];
	  break;
	default:
	  errNum = WLZ_ERR_GREY_TYPE;
	  break;
	}
      }
      else {
	break; /* break from the while loop */
      }
    }
    if( errNum == WLZ_ERR_EOO ){
      errNum = WLZ_ERR_NONE;
    }
  }

  /* rotate back and free temporary object */
  if( errNum == WLZ_ERR_NONE ){
    obj2 = WlzTransposeObj(obj1, &errNum);
    WlzFreeObj(obj1);
  }

  /* perform x convolution */
  if((errNum == WLZ_ERR_NONE) &&
     ((errNum = WlzInitGreyScan(obj2, &iwspace, &gwspace)) == WLZ_ERR_NONE))
  {
    while((errNum = WlzNextGreyInterval(&iwspace)) == WLZ_ERR_NONE){
      stwspc.inbuf.p.inp = gwspace.u_grintptr.inp;
      stwspc.len = iwspace.rgtpos - iwspace.lftpos + 1;
      if( (errNum = (*x_fun)(&stwspc, x_params)) == WLZ_ERR_NONE ){
	switch(  gwspace.pixeltype ){
	case WLZ_GREY_INT:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.inp++)
	    *stwspc.inbuf.p.inp = stwspc.outbuf.p.inp[i];
	  break;
	case WLZ_GREY_SHORT:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.shp++)
	    *stwspc.inbuf.p.shp = (short )(stwspc.outbuf.p.inp[i]);
	  break;
	case WLZ_GREY_UBYTE:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.ubp++)
	    *stwspc.inbuf.p.ubp = (WlzUByte )(stwspc.outbuf.p.inp[i]);
	  break;
	case WLZ_GREY_FLOAT:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.flp++)
	    *stwspc.inbuf.p.flp = stwspc.outbuf.p.flp[i];
	  break;
	case WLZ_GREY_DOUBLE:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.dbp++)
	    *stwspc.inbuf.p.dbp = stwspc.outbuf.p.dbp[i];
	  break;
	case WLZ_GREY_RGBA:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.rgbp++)
	    *stwspc.inbuf.p.rgbp = stwspc.outbuf.p.rgbp[i];
	  break;
	default:
	  errNum = WLZ_ERR_GREY_TYPE;
	  break;
	}
      }
      else {
	break; /* break from the while loop */
      }
    }
  }
  if( errNum == WLZ_ERR_EOO ){
    errNum = WLZ_ERR_NONE;
  }

  /* free the buffer and return transformed object */
  if( stwspc.outbuf.p.dbp ){
    AlcFree((void *) stwspc.outbuf.p.dbp);
  }

  if( dstErr ){
    *dstErr = errNum;
  }
  return obj2;
}
Example #5
0
/*!
* \return	Shade corrected object or NULL on error.
* \ingroup	WlzValueFilters
* \brief	Shade corrects the given domain object with grey
*               values.
*		\f[
		  p_i = n \frac{(o_i - d_i)}{(s_i - d_i}
		\f]
*               The shade corrected image P with values \f$p_i\f$ is
*		created by applying a correction factor to each image
*		value of the given image O with values \f$o_i\f$.
*		\f$s_i\f$ and \f$d_i\f$ are the bright and dark-field
*		shade image values respectively.
* \param	srcObj			Given object to be shade corrected.
* \param	shdObj			Given bright field object.
* \param	shdDFObj		Given dark field object (may be NULL).
* \param	nrmVal			Normalization value.
* \param	inPlace			Modify the grey values of the given
*					object in place if non-zero.
* \param	dstErr			Destination error pointer, may
*                                       be null.
*/
WlzObject	*WlzShadeCorrectBFDF(
  WlzObject 	*srcObj,
  WlzObject 	*shdObj,
  WlzObject 	*shdDFObj,
  double 	nrmVal,
  int 		inPlace,
  WlzErrorNum 	*dstErr)
{
  WlzObject	*rtnObj = NULL;
  WlzObject	*obj1, *obj2;
  WlzCompoundArray	*inCobj, *outCobj;
  WlzObject	**outArray;
  WlzValues	values;
  int		i;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  if((srcObj == NULL) || (shdObj == NULL))
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if((srcObj->domain.core == NULL) || (shdObj->domain.core == NULL))
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if((srcObj->values.core == NULL) || (shdObj->values.core == NULL))
  {
    errNum = WLZ_ERR_VALUES_NULL;
  }
  else if(WlzGreyTableIsTiled(srcObj->values.core->type) ||
          WlzGreyTableIsTiled(shdObj->values.core->type))
  {
    errNum = WLZ_ERR_VALUES_TYPE;
  }
  else
  {
    switch(srcObj->type)
    {
    case WLZ_2D_DOMAINOBJ:
      if(shdObj->type != srcObj->type)
      {
	errNum = WLZ_ERR_OBJECT_TYPE;
      }
      else if( shdDFObj ){
	if( WlzGreyTypeFromObj(srcObj, &errNum) == WLZ_GREY_RGBA ){
	  obj1 = WlzRGBAImageArithmetic(srcObj, shdDFObj, WLZ_BO_SUBTRACT,
					0, &errNum);
	  obj2 = WlzRGBAImageArithmetic(shdObj, shdDFObj, WLZ_BO_SUBTRACT,
					0, &errNum);
	}
	else {
	  obj1 = WlzImageArithmetic(srcObj, shdDFObj, WLZ_BO_SUBTRACT,
				    0, &errNum);
	  obj2 = WlzImageArithmetic(shdObj, shdDFObj, WLZ_BO_SUBTRACT,
				    0, &errNum);
	}
	rtnObj = WlzShadeCorrect2D(obj1, obj2, nrmVal, inPlace, &errNum);
	WlzFreeObj(obj1);
	WlzFreeObj(obj2);;
      }
      else {
	rtnObj = WlzShadeCorrect2D(srcObj, shdObj, nrmVal, inPlace, &errNum);
      }
      break;

    case WLZ_COMPOUND_ARR_1:
    case WLZ_COMPOUND_ARR_2:
      inCobj = (WlzCompoundArray *) srcObj;
      if( inCobj->n > 0 ){
	if( (outArray = (WlzObject **)
	     AlcCalloc(inCobj->n, sizeof(WlzObject *))) == NULL){
	  errNum = WLZ_ERR_MEM_ALLOC;
	}
	else {
	  for(i=0; (i < inCobj->n) && (errNum == WLZ_ERR_NONE); i++){
	    /* allow special behaviour of a non-compound shade image
	       to be used for each object in a compound but must align */
	    switch( shdObj->type ){
	    case WLZ_2D_DOMAINOBJ:
	    case WLZ_3D_DOMAINOBJ:
	      outArray[i] = WlzShadeCorrectBFDF(inCobj->o[i],
						shdObj, shdDFObj,
						nrmVal, inPlace, &errNum);
	      break;

	    case WLZ_COMPOUND_ARR_1:
	    case WLZ_COMPOUND_ARR_2:
	      outArray[i] =
		WlzShadeCorrectBFDF(inCobj->o[i],
				    ((WlzCompoundArray *) shdObj)->o[i],
				    shdDFObj?
				    ((WlzCompoundArray *) shdDFObj)->o[i]:NULL,
				    nrmVal, inPlace, &errNum);
	      break;
	    default:
	      errNum = WLZ_ERR_OBJECT_TYPE;
	      break;
	    }
	      
	  }
	  if( errNum == WLZ_ERR_NONE ){
	    outCobj = WlzMakeCompoundArray(srcObj->type, 3, inCobj->n,
					   outArray, outArray[0]->type,
					   &errNum);
	    rtnObj = (WlzObject *) outCobj;
	  }
	  else {
	    while( i >= 0 ){
	      WlzFreeObj(outArray[i--]);
	    }
	  }
	  AlcFree(outArray);
	}
      }
      else {
	errNum = WLZ_ERR_OBJECT_DATA;
      }
      break;

    case WLZ_3D_DOMAINOBJ:
      errNum = WLZ_ERR_UNIMPLEMENTED;
      break;

    case WLZ_TRANS_OBJ:
      if((rtnObj = WlzShadeCorrectBFDF(srcObj->values.obj,
                                       shdObj, shdDFObj, nrmVal,
				       inPlace, &errNum)) != NULL){
	values.obj = rtnObj;
	return WlzMakeMain(WLZ_TRANS_OBJ, srcObj->domain, values,
			   NULL, NULL, dstErr);
      }
      break;

    case WLZ_EMPTY_OBJ:
      return WlzMakeEmpty(dstErr);

    default:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;
    }
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(rtnObj);
}
Example #6
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);
}
Example #7
0
/*!
* \return	Rescaled object.
* \ingroup	WlzTransform
* \brief	Rescales the given 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	*WlzIntRescaleObj(WlzObject *gObj, int scale, int expand,
				WlzErrorNum *dstErr)
{
  WlzObject	*rObj = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  if(gObj == NULL)
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if(scale < 1)
  {
    errNum = WLZ_ERR_PARAM_DATA;
  }
  else
  {
    switch(gObj->type)
    {
      case WLZ_2D_DOMAINOBJ: /* FALLTHROUGH */
      case WLZ_3D_DOMAINOBJ:
	if(gObj->domain.i == NULL)
	{
	  errNum = WLZ_ERR_DOMAIN_NULL;
	}
	else if(gObj->domain.i->type == WLZ_EMPTY_DOMAIN)
	{
	  rObj = WlzMakeEmpty(&errNum);
	}
	else if(scale == 1)
	{
          rObj = WlzMakeMain(gObj->type, gObj->domain, gObj->values,
			     NULL, NULL, &errNum);
	}
	else
	{
	  if(gObj->values.core &&
	     WlzGreyTableIsTiled(gObj->values.core->type))
	  {
	    errNum = WLZ_ERR_VALUES_TYPE;
	  }
	  else
	  {
	    rObj = (gObj->type == WLZ_2D_DOMAINOBJ)?
		   WlzIntRescaleObj2D(gObj, scale, expand, &errNum):
		   WlzIntRescaleObj3D(gObj, scale, expand, &errNum);
	  }
	}
	break;
      case WLZ_TRANS_OBJ: /* FALLTHROUGH */
      case WLZ_2D_POLYGON: /* FALLTHROUGH */
      case WLZ_BOUNDLIST: /* FALLTHROUGH */
      case WLZ_3D_POLYGON:
	errNum = WLZ_ERR_OBJECT_TYPE;
	break;
      case WLZ_EMPTY_OBJ:
	rObj = WlzMakeEmpty(&errNum);
      default:
	errNum = WLZ_ERR_OBJECT_TYPE;
	break;
    }
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(rObj);
}
Example #8
0
/*!
* \return	The filtered object, or NULL on error.
* \ingroup	WlzValueFilters
* \brief	Applies a recursive filter to the given object.
* \param	srcObj			Given object.
* \param	ftr			Recursive filter.
* \param	actionMsk		Action mask.
* \param	dstErr			Destination error pointer, may
*                                       be null.
*/
WlzObject	*WlzRsvFilterObj(WlzObject *srcObj, WlzRsvFilter *ftr,
			         int actionMsk, WlzErrorNum *dstErr)
{
  WlzValues	tVal;
  WlzObject	*xObj = NULL,
		*yObj = NULL,
		*xyObj = NULL,
		*zObj = NULL,
  		*dstObj = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  if((srcObj == NULL) || (ftr == NULL))
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if(srcObj->domain.core == NULL)
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if(srcObj->values.core == NULL)
  {
    errNum = WLZ_ERR_VALUES_NULL;
  }
  else if(WlzGreyTableIsTiled(srcObj->values.core->type))
  {
    errNum = WLZ_ERR_VALUES_TYPE;
  }
  else
  {
    switch(srcObj->type)
    {
      case WLZ_EMPTY_OBJ:
        dstObj = WlzMakeEmpty(&errNum);
	break;
      case WLZ_2D_DOMAINOBJ:
	if((actionMsk & (WLZ_RSVFILTER_ACTION_X |
			 WLZ_RSVFILTER_ACTION_Y)) != 0)
	{
	  /* Filter in each required direction. */
	  if((actionMsk & WLZ_RSVFILTER_ACTION_X) != 0)
	  {
	    xObj = WlzRsvFilterObj2DX(srcObj, ftr, &errNum);
	  }
	  if((errNum == WLZ_ERR_NONE) &&
	     ((actionMsk & WLZ_RSVFILTER_ACTION_Y) != 0))
	  {
	    yObj = WlzRsvFilterObj2DY((xObj)? xObj: srcObj,
	    		              ftr, &errNum);
	  }
	  if(errNum == WLZ_ERR_NONE)
	  {
	    if(yObj)
	    {
	      dstObj = yObj;
	      yObj = NULL;
	    }
	    else if(xObj)
	    {
	      dstObj = xObj;
	      xObj = NULL;
	    }
	  }
	  if(xObj)
	  {
	    WlzFreeObj(xObj);
	  }
	  if(yObj)
	  {
	    WlzFreeObj(yObj);
	  }
	}
	else
	{
	  /* No filtering required. */
	  dstObj = WlzNewGrey(srcObj, &errNum);
	}
        break;
      case WLZ_3D_DOMAINOBJ:
	if((actionMsk & (WLZ_RSVFILTER_ACTION_X | WLZ_RSVFILTER_ACTION_Y |
			  WLZ_RSVFILTER_ACTION_Z)) != 0)
	{
	  if((actionMsk & (WLZ_RSVFILTER_ACTION_X | 
	  		   WLZ_RSVFILTER_ACTION_Y)) != 0)
	  {
	    xyObj = WlzRsvFilterObj3DXY(srcObj, ftr, actionMsk,
	    				&errNum);
	  }
	  if((errNum == WLZ_ERR_NONE) && 
	     ((actionMsk & WLZ_RSVFILTER_ACTION_Z) != 0))
	  {
	    zObj = WlzRsvFilterObj3DZ((xyObj)? xyObj: srcObj, ftr, &errNum);
	  }
	  if(errNum == WLZ_ERR_NONE)
	  {
	    if(zObj)
	    {
	      dstObj = zObj;
	      zObj = NULL;
	    }
	    else if(xyObj)
	    {
	      dstObj = xyObj;
	      xyObj = NULL;
	    }
	  }
	  if(xyObj)
	  {
	    WlzFreeObj(xyObj);
	  }
	  if(zObj)
	  {
	    WlzFreeObj(zObj);
	  }
	}
	else
	{
	  /* No filtering required. */
	  tVal = WlzCopyValues(srcObj->type, srcObj->values, srcObj->domain,
	  		       &errNum);
	  if(errNum == WLZ_ERR_NONE)
	  {
	    dstObj= WlzMakeMain(srcObj->type, srcObj->domain, tVal,
	    			NULL, NULL, &errNum);
	  }
	}
        break;
      default:
        errNum = WLZ_ERR_OBJECT_TYPE;
	break;
    }
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(dstObj);
}
Example #9
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 );
}
Example #10
0
static WlzObject *WlzCbThreshold3d(
  WlzObject	*obj,
  WlzThreshCbFn	threshCb,
  void		*clientData,
  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 WlzThreshold. The domain and valuetable
     must be checked however */
  obj1 = NULL;
  if( obj->domain.core == NULL ){
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if( obj->values.core == NULL ){
    errNum = WLZ_ERR_VALUES_NULL;
  }
  else if( WlzGreyTableIsTiled(obj->values.core->type) ){
    errNum = WLZ_ERR_VALUES_TYPE;
  }

  /* 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];
    }
  }

  /* threshold 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) && 
	 (obj1 = WlzCbThreshold(temp, threshCb, clientData, &errNum)) ){
	*ndomains = WlzAssignDomain(obj1->domain, NULL);
	*nvalues = WlzAssignValues(obj1->values, NULL);
	WlzFreeObj(obj1);
      } else {
	(*ndomains).core = NULL;
	(*nvalues).core = NULL;
      }
    }
    else {
      WlzFreePlaneDomain(npdom);
      WlzFreeVoxelValueTb( nvoxtab );
      break;
    }

    domains++;
    ndomains++;
    values++;
    nvalues++;
  }

  /* standardise the plane domain */
  if((errNum == WLZ_ERR_NONE) &&
     ((errNum = WlzStandardPlaneDomain(npdom, nvoxtab)) != WLZ_ERR_NONE) ){
    WlzFreePlaneDomain( npdom );
    WlzFreeVoxelValueTb( nvoxtab );
  }

  /* 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;
}
Example #11
0
/*! 
* \return       New object with the rojection.
* \ingroup      WlzTransform
* \brief        Use the view transform to define a projection from
*		3D to 2D and then project the object onto this plane.
*		The object supplied to this function must be a 3D
*		spatial domain object (WLZ_3D_DOMAINOBJ) with either
*		no values or for integration WLZ_GREY_UBYTE values.
*		Integration will assign each output pixel the sum of
*		all input voxels mapped via either the domain density
*		or the voxel density.
*		The integration is controled by the integrate parameter
*		with valid values:
*		WLZ_PROJECT_INT_MODE_NONE - a "shadow domain" without values
*               is computed,
*		WLZ_PROJECT_INT_MODE_DOMAIN - the voxels of the domain are
*		integrated using
*		\f[
		p = \frac{1}{255} n d
                \f]
*		WLZ_PROJECT_INT_MODE_VALUES - the voxel values are integrated
*		using
*		\f[
		p = \frac{1}{255} \sum{l\left[v\right]}.
		\f]
*		Where
*		  \f$p\f$ is the projected image value,
*		  \f$n\f$ is the number of voxels projected for \f$p\f$,
*		  \f$d\f$ is the density of domain voxels,
*		  \f$l\f$ is the voxel value density look up table and
*		  \f$v\f$ is a voxel value.
* \param	obj			The given object.
* \param	vStr			Given view structure defining the
* 					projection plane.
* \param	intMod			This may take three values:
* 					WLZ_PROJECT_INT_MODE_NONE,
* 					WLZ_PROJECT_INT_MODE_DOMAIN or
* 					WLZ_PROJECT_INT_MODE_VALUES.
* \param	denDom			Density of domain voxels this value
* 					is not used unless the integration
* 					mode is WLZ_PROJECT_INT_MODE_DOMAIN.
* \param	denVal			Density look up table for object
* 					voxel density values which must be
* 					an array of 256 values. This may be
* 					NULL if the integration mode is not
* 					WLZ_PROJECT_INT_MODE_VALUES.
* \param	depth			If greater than zero, the projection
* 					depth perpendicular to the viewing
* 					plane.
* \param	dstErr			Destination error pointer, may be NULL.
*/
WlzObject 	*WlzProjectObjToPlane(WlzObject *obj,
  				WlzThreeDViewStruct *vStr,
  				WlzProjectIntMode intMod,
				WlzUByte denDom, WlzUByte *denVal,
				double depth, WlzErrorNum *dstErr)
{
  int		nThr = 1,
		itvVal = 0;
  WlzIVertex2	prjSz;
  WlzIBox2	prjBox = {0};
  double	pln[4];
  WlzObject	*bufObj = NULL,
  		*prjObj = NULL;
  WlzThreeDViewStruct *vStr1 = NULL;
  double	**vMat = NULL;
  WlzValues	nullVal;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  WlzAffineTransform *rescaleTr = NULL;
  WlzGreyValueWSpace **gVWSp = NULL;
  void		***prjAry = NULL;
  const double	eps = 0.000001;
#ifdef WLZ_DEBUG_PROJECT3D_TIME
struct timeval	times[3];
#endif /* WLZ_DEBUG_PROJECT3D_TIME */

  nullVal.core = NULL;
  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;
  }
  else if(vStr == NULL)
  {
    errNum = WLZ_ERR_TRANSFORM_NULL;
  }
  else if((intMod == WLZ_PROJECT_INT_MODE_VALUES) &&
          (obj->values.core == NULL))
  {
    errNum = WLZ_ERR_VALUES_NULL;
  }
#ifdef WLZ_DEBUG_PROJECT3D_TIME
  gettimeofday(times + 0, NULL);
#endif /* WLZ_DEBUG_PROJECT3D_TIME */
  /* Create new view transform without voxel scaling. The voxel scaling
   * is done after the projection. */
  if(errNum == WLZ_ERR_NONE)
  {
    if((vStr1 = WlzMake3DViewStruct(WLZ_3D_VIEW_STRUCT, &errNum)) != NULL)
    {
      vStr1->fixed = vStr->fixed;
      vStr1->theta = vStr->theta;
      vStr1->phi = vStr->phi;
      vStr1->zeta = vStr->zeta;
      vStr1->dist = vStr->dist;
      vStr1->scale = vStr->scale;
      vStr1->voxelSize[0] = 1.0;
      vStr1->voxelSize[1] = 1.0;
      vStr1->voxelSize[2] = 1.0;
      vStr1->voxelRescaleFlg = 0;
      vStr1->interp = vStr->interp;
      vStr1->view_mode = vStr->view_mode;
      vStr1->up = vStr->up;
      vStr1->initialised = WLZ_3DVIEWSTRUCT_INIT_NONE;
      vMat = vStr1->trans->mat;
      errNum = WlzInit3DViewStructAffineTransform(vStr1);
      if(errNum == WLZ_ERR_NONE)
      {
        errNum = Wlz3DViewStructTransformBB(obj, vStr1);
      }
      if(errNum != WLZ_ERR_NONE)
      {
	WlzFree3DViewStruct(vStr1);
	vStr1 = NULL;
      }
    }
  }
  /* Compute bounding box of the projection. */
  if(errNum == WLZ_ERR_NONE)
  {
    prjBox.xMin = WLZ_NINT(vStr1->minvals.vtX);
    prjBox.yMin = WLZ_NINT(vStr1->minvals.vtY);
    prjBox.xMax = WLZ_NINT(vStr1->maxvals.vtX);
    prjBox.yMax = WLZ_NINT(vStr1->maxvals.vtY);
    prjSz.vtX = prjBox.xMax - prjBox.xMin + 1;
    prjSz.vtY = prjBox.yMax - prjBox.yMin + 1;
  }
  /* Compute post projection scaling. */
  if((errNum == WLZ_ERR_NONE) && (vStr->voxelRescaleFlg != 0))
  {
    WlzIBox2	sBox;
    WlzIVertex2 sSz;
    WlzThreeDViewStruct *vStr2;

    vStr2 = WlzMake3DViewStruct(WLZ_3D_VIEW_STRUCT, &errNum);
    if(errNum == WLZ_ERR_NONE)
    {
      vStr2->fixed = vStr->fixed;
      vStr2->theta = vStr->theta;
      vStr2->phi = vStr->phi;
      vStr2->zeta = vStr->zeta;
      vStr2->dist = vStr->dist;
      vStr2->scale = vStr->scale;
      vStr2->voxelSize[0] = vStr->voxelSize[0];
      vStr2->voxelSize[1] = vStr->voxelSize[1];
      vStr2->voxelSize[2] = vStr->voxelSize[2];
      vStr2->voxelRescaleFlg = vStr->voxelRescaleFlg;
      vStr2->interp = vStr->interp;
      vStr2->view_mode = vStr->view_mode;
      vStr2->up = vStr->up;
      vStr2->initialised = WLZ_3DVIEWSTRUCT_INIT_NONE;
      errNum = WlzInit3DViewStructAffineTransform(vStr2);
      if(errNum == WLZ_ERR_NONE)
      {
        errNum = Wlz3DViewStructTransformBB(obj, vStr2);
      }
      if(errNum == WLZ_ERR_NONE)
      {
	sBox.xMin = WLZ_NINT(vStr2->minvals.vtX);
	sBox.yMin = WLZ_NINT(vStr2->minvals.vtY);
	sBox.xMax = WLZ_NINT(vStr2->maxvals.vtX);
	sBox.yMax = WLZ_NINT(vStr2->maxvals.vtY);
	sSz.vtX = sBox.xMax - sBox.xMin + 1;
	sSz.vtY = sBox.yMax - sBox.yMin + 1;
        rescaleTr = WlzMakeAffineTransform(WLZ_TRANSFORM_2D_AFFINE, &errNum);
      }
      if(errNum == WLZ_ERR_NONE)
      {
        double	**m;

	m = rescaleTr->mat;
	m[0][0] = (sSz.vtX * eps) / (prjSz.vtX * eps);
	m[1][1] = (sSz.vtY * eps) / (prjSz.vtY * eps);
	m[0][2] = sBox.xMin - WLZ_NINT(m[0][0] * prjBox.xMin);
	m[1][2] = sBox.yMin - WLZ_NINT(m[1][1] * prjBox.yMin);
      }
      (void )WlzFree3DViewStruct(vStr2);
    }
  }
  /* Compute plane equation, used to clip intervals if depth was given. */
  if((errNum == WLZ_ERR_NONE) && (depth > eps))
  {
    Wlz3DViewGetPlaneEqn(vStr1, pln + 0, pln + 1, pln + 2, pln + 3);
  }
  /* Create rectangular projection array buffers, one for each thread,
   * also if integrating values create a grey value workspace per thread. */
  if(errNum == WLZ_ERR_NONE)
  {
    int		idB;

#ifdef _OPENMP
#pragma omp parallel
    {
#pragma omp master
      {
        nThr = omp_get_num_threads();
      }
    }
#endif
    if((prjAry = (void ***)AlcCalloc(nThr, sizeof(void **))) == NULL)
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
    else
    {
      if(intMod == WLZ_PROJECT_INT_MODE_NONE)
      {
	for(idB = 0; idB < nThr; ++idB)
	{
	  if(AlcUnchar2Calloc((WlzUByte ***)&(prjAry[idB]),
			      prjSz.vtY, prjSz.vtX) != ALC_ER_NONE)
	  {
	    errNum = WLZ_ERR_MEM_ALLOC;
	    break;
	  }
	}
      }
      else
      {
	for(idB = 0; idB < nThr; ++idB)
	{
	  if(AlcInt2Calloc((int ***)&(prjAry[idB]),
			   prjSz.vtY, prjSz.vtX) != ALC_ER_NONE)
	  {
	    errNum = WLZ_ERR_MEM_ALLOC;
	    break;
	  }
	}
      }
    }
    if((errNum == WLZ_ERR_NONE) &&
       (intMod == WLZ_PROJECT_INT_MODE_VALUES))
    {
      itvVal = (WlzGreyTableIsTiled(obj->values.core->type) == 0);
      if(itvVal == 0)
      {
	if((gVWSp = AlcCalloc(nThr, sizeof(WlzGreyValueWSpace *))) == NULL)
	{
	  errNum = WLZ_ERR_MEM_ALLOC;
	}
	else
	{
	  for(idB = 0; idB < nThr; ++idB) 
	  {
	    gVWSp[idB] = WlzGreyValueMakeWSp(obj, &errNum);
	    if(gVWSp[idB]->gType != WLZ_GREY_UBYTE)
	    {
	      errNum = WLZ_ERR_GREY_TYPE;
	      break;
	    }
	  }
	}
      }
    }
  }
  /* Scan through the 3D domain setting value in the projection array. */
  if(errNum == WLZ_ERR_NONE)
  {
    int		pIdx,
    		pCnt;
    WlzDomain	*doms;
    WlzValues	*vals = NULL;

    doms = obj->domain.p->domains;
    if(itvVal)
    {
      vals = obj->values.vox->values;
    }
    pCnt = obj->domain.p->lastpl - obj->domain.p->plane1 + 1;
#ifdef _OPENMP
#pragma omp parallel for
#endif
    for(pIdx =  0; pIdx < pCnt; ++pIdx)
    {
      int	thrId = 0;

      if((errNum == WLZ_ERR_NONE) && (doms[pIdx].core != NULL))
      {
	WlzObject   *obj2;
	WlzGreyWSpace gWSp;
	WlzIntervalWSpace iWSp;
	WlzErrorNum errNum2 = WLZ_ERR_NONE;

#ifdef _OPENMP
	thrId = omp_get_thread_num();
#endif
        obj2 = WlzMakeMain(WLZ_2D_DOMAINOBJ, doms[pIdx],
	                   (vals)? vals[pIdx]: nullVal,
	                   NULL, NULL, &errNum2);
        if(errNum2 == WLZ_ERR_NONE)
	{
	  if(itvVal)
	  {
	    errNum2 = WlzInitGreyScan(obj2, &iWSp, &gWSp);
	  }
	  else
	  {
	    errNum2 = WlzInitRasterScan(obj2, &iWSp, WLZ_RASTERDIR_ILIC);
	  }
	}
        if(errNum2 == WLZ_ERR_NONE)
	{
	  double      plnZ,
	  	      vMZX,
	  	      vMZY;
	  WlzIVertex3 p0,
	    	      p1;

	  p0.vtZ = p1.vtZ = obj->domain.p->plane1 + pIdx;
	  vMZX = (vMat[0][2] * p0.vtZ) + vMat[0][3] - prjBox.xMin;
	  vMZY = (vMat[1][2] * p0.vtZ) + vMat[1][3] - prjBox.yMin;
	  plnZ = (pln[2] * p0.vtZ) + pln[3];
	  while(((itvVal == 0) &&
	        ((errNum2 = WlzNextInterval(&iWSp)) == WLZ_ERR_NONE)) ||
	        ((itvVal != 0) &&
	        ((errNum2 = WlzNextGreyInterval(&iWSp)) == WLZ_ERR_NONE)))
	  {
	    int		skip = 0;
	    WlzDVertex2 q0,
	    		q1;

            p0.vtX = iWSp.lftpos;
	    p1.vtX = iWSp.rgtpos;
	    p0.vtY = p1.vtY = iWSp.linpos;
	    if(depth > eps)
	    {
	      int	c;
	      double	d0,
	      		d1,
			plnYZ;

	      /* Clip the 3D line segment p0,p1 using the plane equation. */
	      plnYZ = (pln[1] * p0.vtY) + plnZ;
	      d0 = (pln[0] * p0.vtX) + plnYZ;
	      d1 = (pln[0] * p1.vtX) + plnYZ;
	      c = ((d1 >  depth) << 3) | ((d0 >  depth) << 2) |
		  ((d1 < -depth) << 1) |  (d0 < -depth);
	      if(c)
	      {
		if((c == 3) || (c == 12)) /* 00-- or ++00 */
		{
		  /* Both out of range, so don't render. */
		  skip = 1;
		}
		else
		{
		  if(fabs(pln[0]) > eps)
		  {
		    double	plnX;

		    plnX = -1.0 / pln[0];
		    if((c &  1) != 0)      /* x0x- */
		    {
		      p0.vtX = plnX * (plnYZ + depth);
		    }
		    else if((c &  4) != 0) /* x+x0 */
		    {
		      p0.vtX = plnX * (plnYZ - depth);
		    }
		    if((c &  2) != 0)      /* 0x-x */
		    {
		      p1.vtX = plnX * (plnYZ + depth);
		    }
		    else if((c &  8) != 0) /* +x0x */
		    {
		      p1.vtX = plnX * (plnYZ - depth);
		    }
		  }
		}
	      }
	    }
	    if(skip == 0)
	    {
	      q0.vtX = (vMat[0][0] * p0.vtX) + (vMat[0][1] * p0.vtY) + vMZX;
	      q0.vtY = (vMat[1][0] * p0.vtX) + (vMat[1][1] * p0.vtY) + vMZY;
	      q1.vtX = (vMat[0][0] * p1.vtX) + (vMat[0][1] * p1.vtY) + vMZX;
	      q1.vtY = (vMat[1][0] * p1.vtX) + (vMat[1][1] * p1.vtY) + vMZY;
	      switch(intMod)
	      {
		case WLZ_PROJECT_INT_MODE_NONE:
		  {
		    WlzIVertex2 u0,
				u1;

		    WLZ_VTX_2_NINT(u0, q0);
		    WLZ_VTX_2_NINT(u1, q1);
		    WlzProjectObjLine((WlzUByte **)(prjAry[thrId]), u0, u1);
		  }
		  break;
		case WLZ_PROJECT_INT_MODE_DOMAIN:
		  {
		    int	        np,
				nq;
		    WlzDVertex3 dq;
		    WlzIVertex2 u0,
				u1;

		    WLZ_VTX_2_NINT(u0, q0);
		    WLZ_VTX_2_NINT(u1, q1);
		    WLZ_VTX_2_SUB(dq, q0, q1);
		    np = denDom * (iWSp.rgtpos - iWSp.lftpos + 1);
		    nq = (int )ceil(WLZ_VTX_2_LENGTH(dq) + eps);
		    WlzProjectObjLineDom((int **)(prjAry[thrId]), np / nq,
					 u0, u1);
		  }
		  break;
		case WLZ_PROJECT_INT_MODE_VALUES:
		  if(itvVal)
		  {
		    WlzProjectObjLineVal((int **)(prjAry[thrId]), denVal,
					 gWSp.u_grintptr.ubp, NULL,
					 vMat, vMZX, vMZY, p0, p1);
		  }
		  else
		  {
		    WlzProjectObjLineVal((int **)(prjAry[thrId]), denVal,
					 NULL, gVWSp[thrId],
					 vMat, vMZX, vMZY, p0, p1);
		  }
		  break;
	      }
	    }
	  }
	  (void )WlzEndGreyScan(&iWSp, &gWSp);
	  if(errNum2 == WLZ_ERR_EOO)
	  {
	    errNum2 = WLZ_ERR_NONE;
	  }
	}
	(void )WlzFreeObj(obj2);
	if(errNum2 != WLZ_ERR_NONE)
	{
#ifdef _OPENMP
#pragma omp critical
	  {
#endif
	    if(errNum == WLZ_ERR_NONE)
	    {
	      errNum = errNum2;
	    }
#ifdef _OPENMP
	  }
#endif
	}
      }
    }
  }
  /* Free grey value workspaces if they were created. */
  if(gVWSp)
  {
    int		idB;

    for(idB = 0; idB < nThr; ++idB) 
    {
      WlzGreyValueFreeWSp(gVWSp[idB]);
    }
    AlcFree(gVWSp);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    int		idB;
    size_t	idC,
    		bufSz;
    WlzGreyP	buf0,
      		buf1;
    WlzIVertex2	prjOrg;

    prjOrg.vtX = prjBox.xMin;
    prjOrg.vtY = prjBox.yMin;
    bufSz = prjSz.vtX * prjSz.vtY;
    for(idB = 1; idB < nThr; ++idB)
    {
      if(intMod == WLZ_PROJECT_INT_MODE_NONE)
      {
        buf0.ubp = ((WlzUByte ***)(prjAry))[0][0],
	buf1.ubp = ((WlzUByte ***)(prjAry))[idB][0];
	for(idC = 0; idC < bufSz; ++idC)
	{
	  buf0.ubp[idC] += buf1.ubp[idC];
	}
      }
      else
      {
        buf0.inp = ((int ***)(prjAry))[0][0],
	buf1.inp = ((int ***)(prjAry))[idB][0];
	for(idC = 0; idC < bufSz; ++idC)
	{
	  buf0.inp[idC] += buf1.inp[idC];
	}
      }
    }
    switch(intMod != WLZ_PROJECT_INT_MODE_NONE)
    {
      buf0.inp = ((int ***)(prjAry))[0][0];
      for(idC = 0; idC < bufSz; ++idC)
      {
	buf0.inp[idC] /= 256;
      }
    }
    if(intMod == WLZ_PROJECT_INT_MODE_NONE)
    {
      bufObj = WlzAssignObject(
	       WlzFromArray2D((void **)(prjAry[0]), prjSz, prjOrg,
			      WLZ_GREY_UBYTE, WLZ_GREY_UBYTE,
			      0.0, 1.0, 1, 0, &errNum), NULL);
    }
    else
    {
      bufObj = WlzAssignObject(
	       WlzFromArray2D((void **)(prjAry[0]), prjSz, prjOrg,
			      WLZ_GREY_INT, WLZ_GREY_INT,
			      0.0, 1.0, 1, 0, &errNum), NULL);
    }
  }
  /* Free the projection array(s). */
  if(prjAry)
  {
    int		idB;

    for(idB = 0; idB < nThr; ++idB)
    {
      (void )Alc2Free((prjAry[idB]));
    }
    AlcFree(prjAry);
  }
  /* Make return object using threshold. */
  if(errNum == WLZ_ERR_NONE)
  {
    WlzPixelV	tV;
    WlzObject	*tObj = NULL;

    tV.type = WLZ_GREY_UBYTE;
    tV.v.ubv = 1;
    tObj = WlzAssignObject(
	   WlzThreshold(bufObj, tV, WLZ_THRESH_HIGH, &errNum), NULL);
    if(tObj)
    {
      if(intMod == WLZ_PROJECT_INT_MODE_NONE)
      {
	prjObj = WlzMakeMain(tObj->type, tObj->domain, nullVal,
			     NULL, NULL, &errNum);
      }
      else
      {
	prjObj = WlzMakeMain(tObj->type, tObj->domain, tObj->values,
			     NULL, NULL, &errNum);
      }
    }
    (void )WlzFreeObj(tObj);
  }
  (void )WlzFreeObj(bufObj);
  (void )WlzFree3DViewStruct(vStr1);
  /* Scale image. */
  if(rescaleTr != NULL)
  {
    if(errNum == WLZ_ERR_NONE)
    {
      WlzObject	*tObj = NULL;

      tObj = WlzAffineTransformObj(prjObj, rescaleTr, 
				   WLZ_INTERPOLATION_NEAREST, &errNum);
      
      (void )WlzFreeObj(prjObj);
      prjObj = tObj;
    }
    (void )WlzFreeAffineTransform(rescaleTr);
  }
#ifdef WLZ_DEBUG_PROJECT3D_TIME
  gettimeofday(times + 1, NULL);
  ALC_TIMERSUB(times + 1, times + 0, times + 2);
  (void )fprintf(stderr, "WlzGetProjectionFromObject: Elapsed time = %g\n",
                 times[2].tv_sec + (0.000001 * times[2].tv_usec));
#endif /* WLZ_DEBUG_PROJECT3D_TIME */
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(prjObj);
}
Example #12
0
/*! 
* \ingroup      WlzBinaryOps
* \brief        Calculate the intersection of a set of objects. If
 uvt=0 calculate domain only, uvt=1 calculate the mmean grey-value at
 each point. Input objects must be all non-NULL and domain objects of
 the same type i.e. either 2D or 3D otherwise an error is returned.
*
* \return       Intersection object with grey-table as required, if the intersection is empty returns WLZ_EMPTY_OBJ, NULL on error.
* \param    n	number of input objects
* \param    objs	input object array
* \param    uvt	grey-table copy flag (1 - copy, 0 - no copy)
* \param    dstErr	error return.
* \par      Source:
*                WlzIntersectN.c
*/
WlzObject *WlzIntersectN(
  int 	n,
  WlzObject **objs,
  int 	uvt,
  WlzErrorNum *dstErr)
{
  WlzObject 		*obj = NULL;
  WlzIntervalDomain 	*idom;
  WlzInterval 		*itvl, *jtvl;
  WlzIntervalWSpace 	*iwsp;
  WlzIntervalWSpace 	*biwsp,*tiwsp,niwsp;
  WlzGreyWSpace 	*gwsp,ngwsp;
  WlzDomain		domain;
  WlzValues		values;
  WlzObjectType		type;
  WlzPixelV		backg;
  WlzGreyP		greyptr;
  WlzGreyV		gv;
  int 			i, j, k, l, inttot, change, lwas, nints;
  int 			line1, lastln;
  int 			kol1, lastkl;
  WlzErrorNum		errNum = WLZ_ERR_NONE;

  /*
   * check pointers
   */
  /* intersecction of no objects is an empty domain */
  domain.i = NULL;
  values.v = NULL;
  if( n < 1 )
  {
    return WlzMakeEmpty(dstErr);
  }

  /* array pointer == NULL or any object pointer == NULL is an error */
  if(objs == NULL){
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else
  {
    for(i=0; i<n; i++){
      if(objs[i] == NULL){
	errNum = WLZ_ERR_OBJECT_NULL;
      }
    }
  }
  if(errNum != WLZ_ERR_NONE)
  {
    obj = NULL;
    if(dstErr) {
      *dstErr = errNum;
    }
    return(obj);
  }

  /* check type of first object */
  switch( objs[0]->type ){

  case WLZ_2D_DOMAINOBJ:
    break;

  case WLZ_3D_DOMAINOBJ:
    return WlzIntersect3d(objs, n, uvt, &errNum);

  case WLZ_EMPTY_OBJ:
    return WlzMakeEmpty(dstErr);

  default:
    errNum = WLZ_ERR_OBJECT_TYPE;
    if(dstErr) {
      *dstErr = errNum;
    }
    return NULL;

  }

  /* check number */
  if (n == 1){
    obj = WlzMakeMain(objs[0]->type, objs[0]->domain, objs[0]->values,
		      NULL, NULL, &errNum);
    if(dstErr) {
      *dstErr = errNum;
    }
    return(obj);
  }

  /* check all objects are non-empty and have the same type
     Note an empty object is not an error */
  for (i=0; i<n; i++){
    if( objs[i]->type != objs[0]->type ){
      if( objs[i]->type == WLZ_EMPTY_OBJ ){
	return WlzMakeEmpty(dstErr);
      }
      else {
	errNum = WLZ_ERR_OBJECT_TYPE;
	if(dstErr) {
	  *dstErr = errNum;
	}
	return NULL;
      }
    }

    /* check for size */
    if( WlzIsEmpty(objs[i], &errNum) ){
      return WlzMakeEmpty(dstErr);
    }
    else {
      if( errNum != WLZ_ERR_NONE ){
	if(dstErr) {
	  *dstErr = errNum;
	}
	return NULL;
      }
    }
  }

  /* This function doesn't support objects with tiled values if the
   * uvt flag is set. */
  if((errNum == WLZ_ERR_NONE) && uvt)
  {
    for(i = 0; i < n; ++i)
    {
      if(objs[i] && objs[i]->values.core &&
         WlzGreyTableIsTiled(objs[i]->values.core->type))
      {
        errNum = WLZ_ERR_VALUES_TYPE;
	break;
      }
    }
    if(errNum != WLZ_ERR_NONE)
    {
      *dstErr = errNum;
      return NULL;
    }
  }

  /*
   * Find the line and column bounds of the intersection.
   */
  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;
    }
  }
  if( lastkl < kol1 || lastln < line1 ){
    return WlzMakeEmpty(dstErr);
  }

  /*
   * Count the individual intervals so that sufficient space
   * for the intersection may be allocated.
   */
  inttot=0;
  for (i=0; (i < n) && (errNum == WLZ_ERR_NONE); i++) {
    inttot += WlzIntervalCount(objs[i]->domain.i, &errNum);
  }
  if(errNum != WLZ_ERR_NONE) {
    if(dstErr) {
      *dstErr = errNum;
    }
    return NULL;
  }

  /*
   * Set up domain, value table structures, and object.
   */

  if( (idom = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_INTVL,
				    line1, lastln, 0, lastkl-kol1,
				    &errNum)) == NULL ){
    if(dstErr) {
      *dstErr = errNum;
    }
    return NULL;
  }
  if( (itvl = (WlzInterval *)
       AlcMalloc (inttot * sizeof(WlzInterval))) == NULL ){
    WlzFreeIntervalDomain(idom);
    errNum = WLZ_ERR_MEM_ALLOC;
    if(dstErr) {
      *dstErr = errNum;
    }
    return NULL;
  }

  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);
    if(dstErr) {
      *dstErr = errNum;
    }
    return NULL;
  }

  /*
   * allocate space for workspaces
   */
  if( (iwsp = (WlzIntervalWSpace *)
       AlcMalloc(n * sizeof(WlzIntervalWSpace))) == NULL ){
    WlzFreeObj( obj );
    errNum = WLZ_ERR_MEM_ALLOC;
    if(dstErr) {
      *dstErr = errNum;
    }
    return NULL;
  }
  biwsp = iwsp;
  tiwsp = biwsp + n;

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

  l = lwas;
  for (;;) {
    /*
     * find next line of intersection
     */
    do {
      change = 0;
      for (iwsp=biwsp; iwsp<tiwsp; iwsp++) {
	if (iwsp->linpos > l) {
	  l = iwsp->linpos;
        }
      }
      for (iwsp=biwsp; iwsp<tiwsp; iwsp++) {
	while (iwsp->linpos < l) {
	  if ((errNum = WlzNextInterval(iwsp)) != WLZ_ERR_NONE) {
	    if(errNum == WLZ_ERR_EOO)
	    {
	      errNum = WLZ_ERR_NONE;
	    }
	    goto firstfinished;
	  }
	  if (iwsp->linpos > l) {
	    change = 1;
	  }
	}
      }
    } while (change != 0);
    /*
     * find next interval of intersection
     */
    kol1 = biwsp->lftpos;
    lastkl = biwsp->rgtpos;
    while(errNum == WLZ_ERR_NONE) {
      do {
	change = 0;
	for (iwsp=biwsp; iwsp<tiwsp; iwsp++)
	  if (iwsp->lftpos > lastkl) {
	    kol1 = iwsp->lftpos;
	    lastkl = iwsp->rgtpos;
	  } else if (iwsp->lftpos > kol1)
	    kol1 = iwsp->lftpos;
	for (iwsp=biwsp; iwsp<tiwsp; iwsp++) {
	  while (iwsp->rgtpos < kol1) {
	    if ((errNum = WlzNextInterval(iwsp)) != WLZ_ERR_NONE) {
	      if(errNum == WLZ_ERR_EOO)
	      {
	        errNum = WLZ_ERR_NONE;
	      }
	      goto firstfinished;
	    }
	    if (iwsp->linpos != l) {
	      l = iwsp->linpos;
	      goto jumpline;
	    }
	    if (iwsp->lftpos > kol1)
	      change = 1;
	  }
	}
      } while ((change != 0) && (errNum == WLZ_ERR_NONE));
      if(errNum == WLZ_ERR_NONE)
      {
	for (iwsp=biwsp; iwsp < tiwsp; iwsp++) {
	  if (iwsp->rgtpos <= lastkl) {
	    lastkl = iwsp->rgtpos;
	  }
	}
	if (lastkl >= kol1) {
	  itvl->ileft = kol1 - idom->kol1;
	  itvl->iright = lastkl - idom->kol1;
	  if (l == lwas) {
	    nints++;
	  } else {
	    errNum = WlzMakeInterval(lwas,idom,nints,jtvl);
	    for (j = lwas+1; (j < l) && (errNum == WLZ_ERR_NONE); j++) {
	      errNum = WlzMakeInterval(j,idom,0,NULL);
	    }
	    if(errNum == WLZ_ERR_NONE) {
	      lwas = l;
	      nints = 1;
	      jtvl = itvl;
	    }
	  }
	  itvl++;
	}
	kol1 = lastkl+1;
      }
    }

  jumpline:
    ;
  }

firstfinished:
  if(errNum != WLZ_ERR_NONE) {
    WlzFreeObj(obj);
    if(dstErr) {
      *dstErr = errNum;
    }
    return NULL;
  }

  errNum = WlzMakeInterval(lwas,idom,nints,jtvl);
  for (j = lwas+1; (j <= lastln) && (errNum == WLZ_ERR_NONE); j++) {
    errNum = WlzMakeInterval(j,idom,0,NULL);
  }
  if(errNum != WLZ_ERR_NONE)
  {
    WlzFreeObj(obj);
    AlcFree((void *) biwsp);
    if(dstErr)
    {
      *dstErr = errNum;
    }
    return NULL;
  }

  /*
   * standardise the interval list (remove leading and trailing
   * empty lines, set kol1 so that at least one interval commences
   * at zero, set lastkl correctly)
   */
  (void )WlzStandardIntervalDomain(idom);

  /* check for error or empty */
  nints = WlzIntervalCount(idom, &errNum);
  if( nints < 0 ){
    /* error */
    WlzFreeObj(obj);
    AlcFree((void *) biwsp);
    if(dstErr)
    {
      *dstErr = errNum;
    }
    return NULL;
  }
  else if( nints == 0 ){
    /* empty object */
    WlzFreeObj(obj);
    AlcFree((void *) biwsp);
    return WlzMakeEmpty(dstErr);
  }

  if (uvt != 0) {
    WlzGreyType	grey_type;
    if( (gwsp = (WlzGreyWSpace *)
	 AlcMalloc (n * sizeof (WlzGreyWSpace))) == NULL ){
      WlzFreeObj(obj);
      AlcFree((void *) biwsp);
      errNum = WLZ_ERR_MEM_ALLOC;
      if(dstErr)
      {
        *dstErr = errNum;
      }
      return NULL;
    }

    /* construct an empty "ragged-rectangle" (type 1  or 2) greytable
       choosing the grey-value type from the first object in the list */
    backg = WlzGetBackground(objs[0], &errNum);
    if(errNum == WLZ_ERR_NONE) {
      grey_type = WlzGreyTableTypeToGreyType(objs[0]->values.core->type,
      					     &errNum);
    }
    if(errNum == WLZ_ERR_NONE) {
      type = WlzGreyTableType(WLZ_GREY_TAB_RAGR, grey_type, &errNum);
    }
    if((errNum != WLZ_ERR_NONE) ||
       (values.v = WlzNewValueTb(obj, type, backg, &errNum)) == NULL ){
      WlzFreeObj( obj );
      AlcFree((void *) gwsp);
      AlcFree((void *) biwsp);
      if(dstErr)
      {
        *dstErr = errNum;
      }
      return NULL;
    }
    obj->values = WlzAssignValues(values, &errNum);
    if(errNum != WLZ_ERR_NONE) {
      WlzFreeObj( obj );
      AlcFree((void *) gwsp);
      AlcFree((void *) biwsp);
      if(dstErr)
      { 
	*dstErr = errNum;
      }
      return NULL;
    }
	
    /*
     * fill the grey table with mean of grey values.
     */
    /* initialise the work-spaces and check pixel type */
    errNum = WlzInitGreyScan(obj, &niwsp, &ngwsp);
    iwsp = biwsp;
    for (i=0; (i < n) && (errNum == WLZ_ERR_NONE); i++) {
      errNum = WlzInitGreyScan(objs[i], iwsp, &gwsp[i]);
      if(errNum == WLZ_ERR_NONE) {
	errNum = WlzNextGreyInterval(iwsp++);
      }
      if( gwsp[i].pixeltype != grey_type ){
        errNum = WLZ_ERR_GREY_TYPE;
      }
    }
    if(errNum != WLZ_ERR_NONE) {
      WlzFreeObj( obj );
      AlcFree((void *) gwsp);
      AlcFree((void *) biwsp);
      if(dstErr) {
        *dstErr = errNum;
      }
      return NULL;
    }

    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++) {
	  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))){
	      (void )WlzNextGreyInterval(iwsp);
	    }
	    gv.inv += *(gwsp[i].u_grintptr.inp + k - iwsp->lftpos);
	  }
	  *greyptr.inp = gv.inv / n;
	  greyptr.inp++;
	}
	break;

      case WLZ_GREY_SHORT:
	for (k = niwsp.lftpos; k <= niwsp.rgtpos; k++) {
	  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))){
	      (void )WlzNextGreyInterval(iwsp);
	    }
	    gv.shv += *(gwsp[i].u_grintptr.shp + k - iwsp->lftpos);
	  }
	  *greyptr.shp = (short )(gv.shv / n);
	  greyptr.shp++;
	}
	break;

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

      case WLZ_GREY_FLOAT:
	for (k = niwsp.lftpos; k <= niwsp.rgtpos; k++) {
	  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))){
	      (void )WlzNextGreyInterval(iwsp);
	    }
	    gv.flv += *(gwsp[i].u_grintptr.flp + k - iwsp->lftpos);
	  }
	  *greyptr.flp = gv.flv / n;
	  greyptr.flp++;
	}
	break;

      case WLZ_GREY_DOUBLE:
	for (k = niwsp.lftpos; k <= niwsp.rgtpos; k++) {
	  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))){
	      (void )WlzNextGreyInterval(iwsp);
	    }
	    gv.dbv += *(gwsp[i].u_grintptr.dbp + k - iwsp->lftpos);
	  }
	  *greyptr.dbp = gv.dbv / n;
	  greyptr.dbp++;
	}
	break;

      case WLZ_GREY_RGBA: /* RGBA to be done again RAB */
	for (k = niwsp.lftpos; k <= niwsp.rgtpos; k++) {
	  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))){
	      (void )WlzNextGreyInterval(iwsp);
	    }
	    gv.rgbv += *(gwsp[i].u_grintptr.rgbp + k - iwsp->lftpos);
	  }
	  *greyptr.rgbp = gv.rgbv / n;
	  greyptr.rgbp++;
	}
	break;

      default:
	errNum = WLZ_ERR_GREY_TYPE;
	break;

      }
    }
    if(errNum == WLZ_ERR_EOO)
    {
      errNum = WLZ_ERR_NONE;
    }
    AlcFree((void *) gwsp);
  }
  AlcFree((void *) biwsp);

  if(dstErr) {
    *dstErr = errNum;
  }
  return obj;
}
Example #13
0
/*! 
* \ingroup      WlzValuesUtils
* \brief        Transfer grey values from the source object to the
 destination object. Currently it is assumed that the objects are
 of the same type (2D/3D) and have the same grey-value type.
*
* \return       Woolz object with transferred grey values
* \param    obj	destination object
* \param    srcObj	source object
* \param    dstErr	error return
* \par      Source:
*                WlzGreyTransfer.c
*/
WlzObject *WlzGreyTransfer(
  WlzObject	*obj,
  WlzObject	*srcObj,
  WlzErrorNum	*dstErr)
{
  WlzObject	*rtnObj=NULL;
  WlzObject	*obj1, *obj2;
  WlzValues	values;
  WlzIntervalWSpace	iwsp1, iwsp2;
  WlzGreyWSpace		gwsp1, gwsp2;
  int			size;
  WlzErrorNum	errNum=WLZ_ERR_NONE;

  /* check destination 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 {
        rtnObj = WlzCopyObject(obj, &errNum);
      }
      break;

    case WLZ_3D_DOMAINOBJ:
      return WlzGreyTransfer3d(obj, srcObj, dstErr);

    case WLZ_TRANS_OBJ:
      if((values.obj = WlzGreyTransfer(obj->values.obj, srcObj,
				       &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 source object */
  if( errNum == WLZ_ERR_NONE ){
    if( srcObj == NULL ){
      errNum = WLZ_ERR_OBJECT_NULL;
    }
    else {
      switch( srcObj->type ){
      case WLZ_2D_DOMAINOBJ:
	break;

      case WLZ_TRANS_OBJ:
	srcObj = srcObj->values.obj;
	break;

      case WLZ_EMPTY_OBJ:
	if( dstErr ){
	  *dstErr = errNum;
	}
	return rtnObj;

      default:
	errNum = WLZ_ERR_OBJECT_TYPE;
	break;
      }
    }
  }

  /* copy source obj values within the intersection */
  if( errNum == WLZ_ERR_NONE ){
    if((srcObj->type != WLZ_EMPTY_OBJ) ){
      if( (obj1 = WlzIntersect2(srcObj, rtnObj, &errNum)) ){
	obj1->values = WlzAssignValues(rtnObj->values, NULL);
	obj2 = WlzMakeMain(obj1->type, obj1->domain, srcObj->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;
}
Example #14
0
/*! 
* \ingroup      WlzValuesUtils
* \brief        static function to implement WlzGreyTransfer for 3D objects.
*
* \return       woolz object
* \param    obj	destination object
* \param    srcObj	source object
* \param    dstErr	error return
* \par      Source:
*                WlzGreyTransfer.c
*/
static WlzObject *WlzGreyTransfer3d(
  WlzObject	*obj,
  WlzObject	*srcObj,
  WlzErrorNum	*dstErr)
{
  WlzObject	*rtnObj=NULL;
  WlzObject	*obj1, *obj2, *tmpObj;
  WlzDomain	*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 source object */
  if( errNum == WLZ_ERR_NONE ){
    if( srcObj == NULL ){
      errNum = WLZ_ERR_OBJECT_NULL;
    }
    else {
      switch( srcObj->type ){

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

	  default:
	    errNum = WLZ_ERR_DOMAIN_TYPE;
	    break;
	  }
	}
	else {
	  errNum = WLZ_ERR_DOMAIN_NULL;
	}
	break;

      case WLZ_EMPTY_OBJ:
	return WlzCopyObject(obj, dstErr);

      default:
	errNum = WLZ_ERR_OBJECT_TYPE;
	break;
      }
    }
  }

  /* now we have a 3D obj and 3D srcObject so run through the source
     and map values as required */
  if( errNum == WLZ_ERR_NONE ){
    WlzDomain	*objDoms;
    WlzValues	*objVals;

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

    /* 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++, objDoms++, objVals++){
      if(((*domains).core)){
	obj1 = WlzMakeMain(WLZ_2D_DOMAINOBJ, *objDoms, *objVals,
			   NULL, NULL, &errNum);
	obj1 = WlzAssignObject(obj1, &errNum);
			   
	if((p >= srcObj->domain.p->plane1) &&
	   (p <= srcObj->domain.p->lastpl) &&
	   (srcObj->domain.p->domains[p-srcObj->domain.p->plane1].core)){
	  obj2 = 
	    WlzMakeMain(WLZ_2D_DOMAINOBJ,
			srcObj->domain.p->domains[p-srcObj->domain.p->plane1],
			srcObj->values.vox->values[p-srcObj->domain.p->plane1],
			NULL, NULL, &errNum);
	}
	else {
	  obj2 = WlzMakeEmpty(NULL);
	}
	obj2 = WlzAssignObject(obj2, &errNum);

	tmpObj = WlzGreyTransfer(obj1, obj2, &errNum);
	*valuess = WlzAssignValues(tmpObj->values, &errNum);
	WlzFreeObj(obj1);
	WlzFreeObj(obj2);
	WlzFreeObj(tmpObj);
      }
    }
  }

  if( dstErr ){
    *dstErr = errNum;
  }
  return rtnObj;
}
Example #15
0
int		main(int argc, char *argv[])
{
  int		option,
  		ok = 1,
  		nFiles = 0,
		usage = 0;
  WlzIVertex3	offset;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  WlzObject	*tlObj = NULL;
  char		*tlFileStr;
  const char	*errMsg;
  static char	optList[] = "ht:x:y:z:",
		tlFileStrDef[] = "-";

  opterr = 0;
  tlFileStr = tlFileStrDef;
  WLZ_VTX_3_SET(offset, 0, 0, 0);
  while((usage == 0) && ((option = getopt(argc, argv, optList)) != -1))
  {
    switch(option)
    {
      case 't':
        tlFileStr = optarg;
	break;
      case 'x':
        if(sscanf(optarg, "%d", &(offset.vtX)) != 1)
	{
	  usage = 1;
	}
	break;
      case 'y':
        if(sscanf(optarg, "%d", &(offset.vtY)) != 1)
	{
	  usage = 1;
	}
	break;
      case 'z':
        if(sscanf(optarg, "%d", &(offset.vtZ)) != 1)
	{
	  usage = 1;
	}
	break;
      case 'h': /* FALLTHROUGH */
      default:
	usage = 1;
	break;
    }
  }
  if(usage == 0)
  {
    if((nFiles = argc - optind) <= 0)
    {
      usage = 1;
    }
  }
  ok = !usage;
  if(ok)
  {
    FILE	*fP = NULL;

    errNum = WLZ_ERR_READ_EOF;
    if(((fP = fopen(tlFileStr, "r+")) == NULL) ||
       ((tlObj= WlzAssignObject(WlzReadObj(fP, &errNum), NULL)) == NULL))
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
                     "%s: Failed to open tiled object in file %s (%s).\n",
		     *argv, tlFileStr, errMsg);
    }
    if(fP)
    {
      (void )fclose(fP);
    }
  }
  if(ok)
  {
    if(tlObj == NULL)
    {
      errNum = WLZ_ERR_OBJECT_NULL;
    }
    else if(tlObj->domain.core == NULL)
    {
      errNum = WLZ_ERR_DOMAIN_NULL;
    }
    else if(tlObj->values.core == NULL)
    {
      errNum = WLZ_ERR_VALUES_NULL;
    }
    else if(WlzGreyTableIsTiled(tlObj->values.core->type) == 0)
    {
      errNum = WLZ_ERR_VALUES_TYPE;
    }
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
                     "%s: invalid tiled object in file %s (%s).\n",
		     *argv, tlFileStr, errMsg);
    }
  }
  if(ok)
  {
    int	idx;

    for(idx = 0; idx < nFiles; ++idx)
    {
      char	*inFileStr;

      if((inFileStr = *(argv + optind + idx)) != NULL)
      {
        FILE	*fP = NULL;

        if((fP = (strcmp(inFileStr, "-")?
	         fopen(inFileStr, "r"): stdin)) == NULL)
        {
	  ok = 0;
	  (void )fprintf(stderr,
	                 "%s: Failed to open input file %s.\n",
			 argv[0], inFileStr);
	}
	if(ok)
	{
	  WlzObject	*obj1 = NULL,
	  		*obj2 = NULL,
			*inObj = NULL;

	  inObj = WlzAssignObject(WlzReadObj(fP, &errNum), NULL);
	  if(errNum == WLZ_ERR_NONE)
	  {
	    if(inObj == NULL)
	    {
	      errNum = WLZ_ERR_OBJECT_NULL;
	    }
	    else
	    {
	      switch(inObj->type)
	      {
	        case WLZ_2D_DOMAINOBJ:
		  if(tlObj->type == WLZ_3D_DOMAINOBJ)
		  {
		    obj1 = WlzConstruct3DObjFromObj(1, &inObj, 0,
						    1.0f, 1.0f, 1.0f,
						    &errNum);
		  }
		  else
		  {
		    obj1 = WlzAssignObject(inObj, NULL);
		  }
		  break;
	        case WLZ_3D_DOMAINOBJ:
		  obj1 = WlzAssignObject(inObj, NULL);
		  break;
	        default:
		  errNum = WLZ_ERR_OBJECT_TYPE;
		  break;
	      }
	    }
	  }
	  if(errNum == WLZ_ERR_NONE)
	  {
	    obj2 = WlzShiftObject(obj1, offset.vtX, offset.vtY, offset.vtZ,
	                          &errNum);
	  }
	  if(errNum == WLZ_ERR_NONE)
	  {
	    errNum = WlzCopyObjectGreyValues(tlObj, obj2);
	  }
          (void )WlzFreeObj(obj1);
          (void )WlzFreeObj(obj2);
          (void )WlzFreeObj(inObj);
	}
      }
    }
  }
  (void )WlzFreeObj(tlObj);
  if(usage)
  {
    (void )fprintf(stderr,
    "Usage: %s%s%s%s",
    *argv,
    " [-h] [-t <tiled object>] [-x #] [-y #] [-z #]\n"
    "                         [<input objects>]\n"
    "Sets the values in the tiled object using the values in the given\n"
    "input object(s).\n"
    "Version: ",
    WlzVersion(),
    "\n"
    "Options:\n"
    "  -h  Prints this usage information.\n"
    "  -t  The tiled object.\n"
    "  -x  Column offset.\n"
    "  -y  Line offset.\n"
    "  -z  Plane offset.\n");
  }
  return(!ok);
}
Example #16
0
/*! 
* \ingroup      WlzValuesUtils
* \brief        Makes a dithered object from the given grey-level Woolz
 object. The destination bits are determined by the number of shades in
 the dithered image (usually 1 bit) and the bit planes to use (typically
 to match the bit-planes of a display mask).
*
* \return       Object with dithered grey values.
* \param    o	Input object.
* \param    destBits	Destination bit planes for dithered values.
* \param    dstErr	Error return.
* \par      Source:
*                WlzGreyDitherObj.c
*/
WlzObject *WlzGreyDitherObj(
  WlzObject	*o,
  unsigned int  destBits,
  WlzErrorNum	*dstErr)
{
  WlzObject	*obj=NULL;
  WlzIntervalWSpace	iwsp1, iwsp2;
  WlzGreyWSpace		gwsp1, gwsp2;
  int		i, j, m, g, G;
  int		n_to;
  int		bit_val[8], permute_val[256];
  int		factor_from, factor_to, mask_start;
  WlzErrorNum	errNum=WLZ_ERR_NONE;

  /* check object type - 1 only */
  if( o == NULL ){
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else {
    switch( o->type ){
    case WLZ_2D_DOMAINOBJ:
      /* check it has a valuetable */
      if( o->values.core == NULL ){
	errNum = WLZ_ERR_VALUES_NULL;
      }
      else if( WlzGreyTableIsTiled(o->values.core->type) ){
	errNum = WLZ_ERR_VALUES_TYPE;
      }
      break;

    case WLZ_3D_DOMAINOBJ:
    case WLZ_TRANS_OBJ:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;

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

    default:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;
    }
  }

  if( !obj && (errNum == WLZ_ERR_NONE) ){
    /* count the bits in the mask */
    for(i=1, n_to=0; i <= destBits; i <<= 1 )
    {
      if( i & destBits )
	n_to++;
    }
    
    /* check numbers of bits */
    if( n_to == 0 ){
      errNum = WLZ_ERR_PARAM_DATA;
    }
    else {
      /* make a new object with the same domain */
      if((obj = WlzNewGrey(o, &errNum)) != NULL){
	if( n_to < 8 ){

	  /* set up some factors */
	  factor_from = 255;
	  factor_to = (1<<n_to) - 1;
	  mask_start = (1 << (8-n_to)) - 1;

	  /* set up bit permute lut */
	  for(i=0, j=1, m=destBits; i < n_to; i++)
	  {
	    while( !(m&1) )
	    {
	      m = m >> 1;
	      j = j << 1;
	    }
	    m = m >> 1;
	    bit_val[i] = j;
	  }

	  for(i=0; i < (1<<n_to); i++)
	  {
	    permute_val[i] = 0;
	    for(j=0, m=1; j < n_to; j++, m = m<<1 ){
	      permute_val[i] += (i&m) * bit_val[j];
	    }
	  }

	  for(;i < 256; i++){
	    permute_val[i] = 0;
	  }

	  /* now scan the objects */
	  WlzInitGreyScan(o,&iwsp1,&gwsp1);
	  WlzInitGreyScan(obj,&iwsp2,&gwsp2);
	  while((WlzNextGreyInterval(&iwsp1) == WLZ_ERR_NONE) && 
		(WlzNextGreyInterval(&iwsp2) == WLZ_ERR_NONE ) )
	  {
	    j = iwsp1.linpos;
	    G = rand() & mask_start;
	    switch(  gwsp1.pixeltype )
	    {
	    case WLZ_GREY_INT:
	      for(i=iwsp1.lftpos; i<=iwsp1.rgtpos; i++,
		    gwsp1.u_grintptr.inp++,
		    gwsp2.u_grintptr.inp++ )
	      {
		G += (*gwsp1.u_grintptr.inp) & 255;
		g = (G * factor_to) / factor_from;
		(*gwsp2.u_grintptr.inp) = permute_val[g];
		G -= (g * factor_from) / factor_to;
	      }
	      break;

	    case WLZ_GREY_SHORT:
	      for(i=iwsp1.lftpos; i<=iwsp1.rgtpos; i++,
		    gwsp1.u_grintptr.shp++,
		    gwsp2.u_grintptr.shp++ )
	      {
		G += (*gwsp1.u_grintptr.shp) & 255;
		g = (G * factor_to) / factor_from;
		(*gwsp2.u_grintptr.shp) = (short )(permute_val[g]);
		G -= (g * factor_from) / factor_to;
	      }
	      break;

	    case WLZ_GREY_UBYTE:
	      for(i=iwsp1.lftpos; i<=iwsp1.rgtpos; i++,
		    gwsp1.u_grintptr.ubp++,
		    gwsp2.u_grintptr.ubp++ )
	      {
		G += (*gwsp1.u_grintptr.ubp);
		g = (G * factor_to) / factor_from;
		(*gwsp2.u_grintptr.ubp) = (WlzUByte )(permute_val[g]);
		G -= (g * factor_from) / factor_to;
	      }
	      break;

	    case WLZ_GREY_RGBA: /* RGBA to be done RAB */
	    default:
	      errNum = WLZ_ERR_GREY_TYPE;
	      break;
	    }
	  }
	}
      }
    }
  }
/*! 
* \ingroup      WlzValuesUtils
* \brief        Calculate the modulus of the grey-level gradient at each
 point. The gradient images are calculated using WlzGauss2() with width
parameter set to <tt>width</tt>. Will now calculate the modulus for each
object of a compound object if appropriate. 
*
* \return       Object with values set to the gradient modulus at each pixel.
* \param    obj	Input object.
* \param    width	Width parameter for the gaussian gradient operator.
* \param    dstErr	Error return.
* \par      Source:
*                WlzGreyModGradient.c
*/
WlzObject *WlzGreyModGradient(
  WlzObject	*obj,
  double	width,
  WlzErrorNum	*dstErr)
{
  WlzObject		*xobj, *yobj, *returnobj=NULL;
  WlzIntervalWSpace	iwsp1, iwsp2, iwsp3;
  WlzGreyWSpace		gwsp1, gwsp2, gwsp3;
  WlzCompoundArray	*cobj1, *cobj2;
  int			i;
  double		g1, g2, g3;
  WlzErrorNum		errNum=WLZ_ERR_NONE;

  /* check object */
  if( obj ){
    switch( obj->type ){
    case WLZ_2D_DOMAINOBJ:
      if( obj->domain.core ){
	switch( obj->domain.core->type ){
	case WLZ_EMPTY_DOMAIN:
	  returnobj = WlzMakeEmpty(&errNum);
	  break;

	default:
	  if( obj->values.core ){
	    if( (obj->values.core->type == WLZ_EMPTY_VALUES) ||
	        WlzGreyTableIsTiled(obj->values.core->type) ){
	      errNum = WLZ_ERR_VALUES_TYPE;
	    }
	  }
	  else {
	    errNum = WLZ_ERR_VALUES_NULL;
	  }
	  break;
	}
      }
      else {
	errNum = WLZ_ERR_DOMAIN_NULL;
      }
      /* one last check for rgb values */
      if(WlzGreyTableTypeToGreyType(obj->values.core->type, NULL)
	 == WLZ_GREY_RGBA){
	return WlzRGBAModGradient(obj, width, dstErr);
      }
      break;

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

    case WLZ_COMPOUND_ARR_1:
    case WLZ_COMPOUND_ARR_2:
      cobj1 = (WlzCompoundArray *) obj;
      if((cobj2 = WlzMakeCompoundArray(cobj1->type, 1, cobj1->n, NULL,
				       cobj1->otype, &errNum)) != NULL){
	/* transform each object, ignore type errors */
	for(i=0; i < cobj1->n; i++){
	  cobj2->o[i] =
	    WlzAssignObject(WlzGreyModGradient(cobj1->o[i],
					       width, &errNum), NULL);
	}
	return (WlzObject *) cobj2;
      }
      break;

    default:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;
    }
  }
  else {
    errNum = WLZ_ERR_OBJECT_NULL;
  }

  /* if WlzUByte grey values then copy to int */
  if( (errNum == WLZ_ERR_NONE) && !returnobj ){
    if(WlzGreyTableTypeToGreyType(obj->values.core->type,
                                  NULL) == WLZ_GREY_UBYTE)
    {
      returnobj = WlzConvertPix(obj, WLZ_GREY_INT, NULL);
    }
    else
    {
      returnobj = WlzMakeMain(WLZ_2D_DOMAINOBJ, obj->domain,
			      WlzCopyValues(obj->type, obj->values,
					    obj->domain, &errNum),
			      NULL, NULL, NULL);
    }

    /* calculate gradient images */
    xobj = WlzGauss2(returnobj, width, width, 1, 0, NULL);
    yobj = WlzGauss2(returnobj, width, width, 0, 1, NULL);

    /* calculate modulus  - lockstep raster scan assumes equal domains */
    errNum = WlzInitGreyScan(returnobj, &iwsp1, &gwsp1);
    errNum = WlzInitGreyScan(xobj, &iwsp2, &gwsp2);
    errNum = WlzInitGreyScan(yobj, &iwsp3, &gwsp3);
    while((errNum == WLZ_ERR_NONE) && 
	  (WlzNextGreyInterval(&iwsp1) == WLZ_ERR_NONE) )
    {
      (void) WlzNextGreyInterval(&iwsp2);
      (void) WlzNextGreyInterval(&iwsp3);

      switch( gwsp1.pixeltype )
      {
      default:
      case WLZ_GREY_INT:
	for(i=0; i < iwsp1.colrmn; i++)
	{
	  g2 = *gwsp2.u_grintptr.inp++;
	  g3 = *gwsp3.u_grintptr.inp++;
	  g1 = sqrt( g2*g2 + g3*g3 );
	  *gwsp1.u_grintptr.inp++ = (int) g1;
	}
	break;

      case WLZ_GREY_SHORT:
	for(i=0; i < iwsp1.colrmn; i++)
	{
	  g2 = *gwsp2.u_grintptr.shp++;
	  g3 = *gwsp3.u_grintptr.shp++;
	  g1 = sqrt( g2*g2 + g3*g3 );
	  *gwsp1.u_grintptr.shp++ = (short) g1;
	}
	break;

      case WLZ_GREY_UBYTE:
	for(i=0; i < iwsp1.colrmn; i++)
	{
	  g2 = *gwsp2.u_grintptr.ubp++;
	  g3 = *gwsp3.u_grintptr.ubp++;
	  g1 = sqrt( g2*g2 + g3*g3 );
	  *gwsp1.u_grintptr.ubp++ = (WlzUByte) g1;
	}
	break;

      case WLZ_GREY_FLOAT:
	for(i=0; i < iwsp1.colrmn; i++)
	{
	  g2 = *gwsp2.u_grintptr.flp++;
	  g3 = *gwsp3.u_grintptr.flp++;
	  g1 = sqrt( g2*g2 + g3*g3 );
	  *gwsp1.u_grintptr.flp++ = (float) g1;
	}
	break;

      case WLZ_GREY_DOUBLE:
	for(i=0; i < iwsp1.colrmn; i++)
	{
	  g2 = *gwsp2.u_grintptr.dbp++;
	  g3 = *gwsp3.u_grintptr.dbp++;
	  g1 = sqrt( g2*g2 + g3*g3 );
	  *gwsp1.u_grintptr.dbp++ = (double) g1;
	}
	break;

      case WLZ_GREY_RGBA: /* RGBA to be done - should not get here */
	errNum = WLZ_ERR_GREY_TYPE;
	break;

      }
    }

    /* check for normal return */
    if( errNum == WLZ_ERR_EOO ){
      errNum = WLZ_ERR_NONE;
    }

    /* clean up */
    WlzFreeObj( xobj );
    WlzFreeObj( yobj );
  }

  /* check error return */
  if( dstErr ){
    *dstErr = errNum;
  }
  return( returnobj );
}
Example #18
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);
}
Example #19
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;
}
Example #20
0
/*!
* \return	The background value. If the returned pixel value type is
* 		WLZ_GREY_ERROR then an error has occurred.
* \ingroup	WlzValuesUtils
* \brief	Gets the background value of the given object.
* \param	obj			Given object.
* \param	dstErr			Destination error pointer, may be NULL.
*/
WlzPixelV WlzGetBackground(
  WlzObject	*obj,
  WlzErrorNum	*dstErr)
{
  WlzPlaneDomain	*planedmn;
  WlzPixelV		bgd;
  WlzErrorNum		errNum=WLZ_ERR_NONE;

  /* set up an invalid background return */
  bgd.type = WLZ_GREY_ERROR;
  bgd.v.inv = 0;
  
  if( obj == NULL ){
    errNum = WLZ_ERR_OBJECT_NULL;
  }


  if( errNum == WLZ_ERR_NONE ){
    switch( obj->type ){

    case WLZ_2D_DOMAINOBJ:
      if( obj->domain.i == NULL ){
	errNum = WLZ_ERR_DOMAIN_NULL;
	break;
      }

      if( obj->values.v == NULL ){
	bgd.type = WLZ_GREY_INT;
	bgd.v.inv = 0;
	break;
      }
      
      switch( WlzGreyTableTypeToTableType(obj->values.core->type,
					  NULL) ){

      case WLZ_GREY_TAB_RAGR:
	bgd = obj->values.v->bckgrnd;
	break;

      case WLZ_GREY_TAB_RECT:
	bgd = obj->values.r->bckgrnd;
	break;

      case WLZ_GREY_TAB_INTL:
	bgd = obj->values.i->bckgrnd;
	break;

      default:
	errNum = WLZ_ERR_VALUES_TYPE;
	break;
      }
      break;

    case WLZ_3D_DOMAINOBJ:
      if( obj->domain.p == NULL ){
	errNum = WLZ_ERR_DOMAIN_NULL;
	break;
      }

      if( obj->values.core == NULL ){
	bgd.type = WLZ_GREY_INT;
	bgd.v.inv = 0;
	errNum = WLZ_ERR_NONE;
	break;
      }

      planedmn = obj->domain.p;
      if( planedmn->type != WLZ_PLANEDOMAIN_DOMAIN ){
	errNum = WLZ_ERR_PLANEDOMAIN_TYPE;
	break;
      }

      if(WlzGreyTableIsTiled(obj->values.core->type))
      {
        bgd = obj->values.t->bckgrnd;
      }
      else if(obj->values.core->type == WLZ_VOXELVALUETABLE_GREY)
      {
        bgd = obj->values.vox->bckgrnd;
      }
      else
      {
	errNum = WLZ_ERR_VALUES_TYPE;
      }
      break;

    case WLZ_TRANS_OBJ:
      return( WlzGetBackground(obj->values.obj, dstErr) );

    case WLZ_EMPTY_OBJ:
      bgd.type = WLZ_GREY_INT;
      bgd.v.inv = 0;
      errNum = WLZ_ERR_NONE;
      break;

    default:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;
    }
  }

  if( dstErr ){
    *dstErr = errNum;
  }
  return bgd;
}
Example #21
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;
}
Example #22
0
/*! 
* \ingroup      WlzValuesFilters
* \brief        Set new grey-range by simple linear interpolation. It
 assumes that the min and max values enclose the true range of
 grey-values in the object. Failure to check this could result in a
 segmentation fault.

The transform function is:
\f[g' = \frac{(gMax - gMin)}{(gmax - gmin)} (g - gmin) + gMin + \delta
\f]
Here \f$\delta\f$ is the dither value.
*
* \return       Woolz error number
* \param    obj	Input grey-level object whose values are to be reset.
* \param    min	Initial minimum value
* \param    max	Initial maximum value
* \param    Min	Final minimum value
* \param    Max	Final maximum value
* \param    Dither values if destination range is greater than source range
*           and this flag is non-zero.
* \par      Source:
*                WlzGreySetRange.c
*/
WlzErrorNum WlzGreySetRange(
  WlzObject	*obj,
  WlzPixelV	min,
  WlzPixelV	max,
  WlzPixelV	Min,
  WlzPixelV	Max,
  int		dither)
{
  double		gMin = 0.0,
  			gMax = 0.0,
			sigma = 0.0,
  			factor,
			val;
  WlzIntervalWSpace	iwsp;
  WlzGreyWSpace		gwsp;
  WlzGreyP		gptr;
  WlzObject		*tempobj;
  WlzValues 		*values;
  WlzDomain		*domains;
  int			i, j, nplanes;
  WlzErrorNum		errNum = WLZ_ERR_NONE;

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

  if( errNum == WLZ_ERR_NONE ){
    switch( obj->type ){

    case WLZ_2D_DOMAINOBJ:
      if( obj->domain.i == NULL ){
	return WLZ_ERR_DOMAIN_NULL;
      }
      if( obj->values.core == NULL ){
	return WLZ_ERR_VALUES_NULL;
      }
      if( WlzGreyTableIsTiled(obj->values.core->type) ){
	return WLZ_ERR_VALUES_TYPE;
      }
      break;

    case WLZ_3D_DOMAINOBJ:
      /* check planedomain and voxeltable */
      if( obj->domain.p == NULL ){
	return WLZ_ERR_DOMAIN_NULL;
      }
      if( obj->domain.p->type != WLZ_PLANEDOMAIN_DOMAIN ){
	return WLZ_ERR_PLANEDOMAIN_TYPE;
      }
      if( obj->values.vox == NULL ){
	return WLZ_ERR_VALUES_NULL;
      }
      if( obj->values.vox->type != WLZ_VOXELVALUETABLE_GREY ){
	return WLZ_ERR_VOXELVALUES_TYPE;
      }

      /* set range of each plane if non-empty - indicated by NULL */
      domains = obj->domain.p->domains;
      values = obj->values.vox->values;
      nplanes = obj->domain.p->lastpl - obj->domain.p->plane1 + 1;
      for(i=0; i < nplanes; i++, domains++, values++){

	if( (*domains).core == NULL || (*values).core == NULL ){
	  continue;
	}

	tempobj = WlzMakeMain(WLZ_2D_DOMAINOBJ,
			      *domains, *values, NULL, NULL,
			      &errNum);
	if((tempobj == NULL) && (errNum == WLZ_ERR_NONE) ){
	  errNum = WLZ_ERR_UNSPECIFIED;
	  break;
	}

	errNum = WlzGreySetRange(tempobj, min, max, Min, Max, dither);
	WlzFreeObj( tempobj );
	if( errNum != WLZ_ERR_NONE ){
	  break;
	}
      }
      
      return errNum;

    case WLZ_TRANS_OBJ:
      return WlzGreySetRange(obj->values.obj, min, max, Min, Max, dither);

    case WLZ_EMPTY_OBJ:
      return errNum;

    default:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;
    }
  }

  if( errNum == WLZ_ERR_NONE ){
    /* get conversion function - should use LUT
       use 4 LUTS for rgb type since bounded */
    if( WlzGreyTypeFromObj(obj, &errNum) == WLZ_GREY_RGBA ){
      WlzUByte	rgbaLut[4][256];
      WlzUInt	rgbamin[4], rgbaMin[4];
      double	rgbaFactor[4], val1;
      WlzUInt	red, green, blue, alpha;

      rgbamin[0] = WLZ_RGBA_RED_GET(min.v.rgbv);
      rgbaMin[0] = WLZ_RGBA_RED_GET(Min.v.rgbv);
      if(WLZ_RGBA_RED_GET(max.v.rgbv) > WLZ_RGBA_RED_GET(min.v.rgbv)){
	rgbaFactor[0] = (((double) WLZ_RGBA_RED_GET(Max.v.rgbv) - 
			  WLZ_RGBA_RED_GET(Min.v.rgbv))/
			 (WLZ_RGBA_RED_GET(max.v.rgbv) - 
			  WLZ_RGBA_RED_GET(min.v.rgbv)));
      }
      else {
	rgbaFactor[0] = 0.0;
      }

      rgbamin[1] = WLZ_RGBA_GREEN_GET(min.v.rgbv);
      rgbaMin[1] = WLZ_RGBA_GREEN_GET(Min.v.rgbv);
      if(WLZ_RGBA_GREEN_GET(max.v.rgbv) > WLZ_RGBA_GREEN_GET(min.v.rgbv)){
	rgbaFactor[1] = (((double) WLZ_RGBA_GREEN_GET(Max.v.rgbv) - 
			  WLZ_RGBA_GREEN_GET(Min.v.rgbv))/
			 (WLZ_RGBA_GREEN_GET(max.v.rgbv) - 
			  WLZ_RGBA_GREEN_GET(min.v.rgbv)));
      }
      else {
	rgbaFactor[1] = 0.0;
      }

      rgbamin[2] = WLZ_RGBA_BLUE_GET(min.v.rgbv);
      rgbaMin[2] = WLZ_RGBA_BLUE_GET(Min.v.rgbv);
      if(WLZ_RGBA_BLUE_GET(max.v.rgbv) > WLZ_RGBA_BLUE_GET(min.v.rgbv)){
	rgbaFactor[2] = (((double) WLZ_RGBA_BLUE_GET(Max.v.rgbv) - 
			  WLZ_RGBA_BLUE_GET(Min.v.rgbv))/
			 (WLZ_RGBA_BLUE_GET(max.v.rgbv) - 
			  WLZ_RGBA_BLUE_GET(min.v.rgbv)));
      }
      else {
	rgbaFactor[2] = 0.0;
      }

      rgbamin[3] = WLZ_RGBA_ALPHA_GET(min.v.rgbv);
      rgbaMin[3] = WLZ_RGBA_ALPHA_GET(Min.v.rgbv);
      if(WLZ_RGBA_ALPHA_GET(max.v.rgbv) > WLZ_RGBA_ALPHA_GET(min.v.rgbv)){
	rgbaFactor[3] = (((double) WLZ_RGBA_ALPHA_GET(Max.v.rgbv) - 
			  WLZ_RGBA_ALPHA_GET(Min.v.rgbv))/
			 (WLZ_RGBA_ALPHA_GET(max.v.rgbv) - 
			  WLZ_RGBA_ALPHA_GET(min.v.rgbv)));
      }
      else {
	rgbaFactor[3] = 0.0;
      }

      /* now set up the LUTS */
      for(i=0; i < 4; i++){
	for(j=0; j < 256; j++){
	  val1 = rgbaFactor[i] * (j - rgbamin[i]) + rgbaMin[i];
	  rgbaLut[i][j] = (WlzUByte )WLZ_CLAMP(val1, 0, 255);
	}
      }

      /* set values - can assume rgba grey-type */
      errNum = WlzInitGreyScan(obj, &iwsp, &gwsp);
      if(errNum == WLZ_ERR_NONE) {
	while( WlzNextGreyInterval(&iwsp) == WLZ_ERR_NONE ){

	  gptr = gwsp.u_grintptr;
	  for (i=0; i<iwsp.colrmn; i++, gptr.rgbp++){
	    red = rgbaLut[0][WLZ_RGBA_RED_GET(*gptr.rgbp)];
	    green = rgbaLut[0][WLZ_RGBA_GREEN_GET(*gptr.rgbp)];
	    blue = rgbaLut[0][WLZ_RGBA_BLUE_GET(*gptr.rgbp)];
	    alpha = rgbaLut[0][WLZ_RGBA_ALPHA_GET(*gptr.rgbp)];
	    WLZ_RGBA_RGBA_SET(*gptr.rgbp, red, green, blue, alpha);
	  }
	}
	(void )WlzEndGreyScan(&iwsp, &gwsp);
	if(errNum == WLZ_ERR_EOO){
	  errNum = WLZ_ERR_NONE;
	}
      }
    }
    else {
      WlzValueConvertPixel(&min, min, WLZ_GREY_DOUBLE);
      WlzValueConvertPixel(&max, max, WLZ_GREY_DOUBLE);
      WlzValueConvertPixel(&Min, Min, WLZ_GREY_DOUBLE);
      WlzValueConvertPixel(&Max, Max, WLZ_GREY_DOUBLE);
      if( fabs(max.v.dbv - min.v.dbv) < DBL_EPSILON ){
	return WLZ_ERR_FLOAT_DATA;
      }
      errNum = WlzInitGreyScan(obj, &iwsp, &gwsp);
      if(errNum == WLZ_ERR_NONE) {
	factor = (Max.v.dbv - Min.v.dbv) / (max.v.dbv - min.v.dbv);
	if(dither)
	{
	  if(fabs(factor) < 1.0 + DBL_EPSILON)
	  {
	    dither = 0;
	  }
	  else
	  {
	    sigma = fabs(2.0 / factor);
	    AlgRandSeed(101);
	    switch(gwsp.pixeltype) {
	      case WLZ_GREY_INT:
		gMin = ALG_MAX(Min.v.dbv, INT_MIN);
		gMax = ALG_MIN(Max.v.dbv, INT_MAX);
		break;
	      case WLZ_GREY_SHORT:
		gMin = ALG_MAX(Min.v.dbv, SHRT_MIN);
		gMax = ALG_MIN(Max.v.dbv, SHRT_MAX);
		break;
	      case WLZ_GREY_UBYTE:
		gMin = ALG_MAX(Min.v.dbv, 0);
		gMax = ALG_MIN(Max.v.dbv, 255);
		break;
	      case WLZ_GREY_FLOAT:
		gMin = ALG_MAX(Min.v.dbv, FLT_MIN);
		gMax = ALG_MIN(Max.v.dbv, FLT_MAX);
		break;
	      case WLZ_GREY_DOUBLE:
		gMin = Min.v.dbv;
		gMax = Max.v.dbv;
		break;
	      default:
		break;
	    }
	  }
	}
	while((errNum == WLZ_ERR_NONE) &&
	      ((errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE)){
	  gptr = gwsp.u_grintptr;
	  switch (gwsp.pixeltype) {
	    case WLZ_GREY_INT:
	      for (i=0; i<iwsp.colrmn; i++, gptr.inp++){
		if(dither){
		  val = factor * (*gptr.inp +
				  AlgRandZigNormal(0.0, sigma) -
				  min.v.dbv) + Min.v.dbv;
		  val = WLZ_CLAMP(val, gMin, gMax);
		} else {
		  val = factor * (*gptr.inp - min.v.dbv) + Min.v.dbv;
		}
		*gptr.inp = WLZ_NINT(val);
	      }
	      break;
	    case WLZ_GREY_SHORT:
	      for (i=0; i<iwsp.colrmn; i++, gptr.shp++){
		if(dither){
		  val = factor * (*gptr.shp +
				  AlgRandZigNormal(0.0, sigma) -
				  min.v.dbv) + Min.v.dbv;
		  val = WLZ_CLAMP(val, gMin, gMax);
		} else {
		  val = factor * (*gptr.shp - min.v.dbv) + Min.v.dbv;
		}
		*gptr.shp = (short )WLZ_NINT(val);
	      }
	      break;
	    case WLZ_GREY_UBYTE:
	      for (i=0; i<iwsp.colrmn; i++, gptr.ubp++){
		if(dither){
		  val = factor * (*gptr.ubp +
				  AlgRandZigNormal(0.0, sigma) -
				  min.v.dbv) + Min.v.dbv;
		  val = WLZ_CLAMP(val, gMin, gMax);
		} else {
		  val = factor * (*gptr.ubp - min.v.dbv) + Min.v.dbv;
		}
		*gptr.ubp = (WlzUByte )WLZ_NINT(val);
	      }
	      break;
	    case WLZ_GREY_FLOAT:
	      for (i=0; i<iwsp.colrmn; i++, gptr.flp++){
		if(dither){
		  val = factor * (*gptr.flp +
				  AlgRandZigNormal(0.0, sigma) -
				  min.v.dbv) + Min.v.dbv;
		  val = WLZ_CLAMP(val, gMin, gMax);
		} else {
		  val = factor * (*gptr.flp - min.v.dbv) + Min.v.dbv;
		}
		*gptr.flp = (float )val;
	      }
	      break;
	    case WLZ_GREY_DOUBLE:
	      for (i=0; i<iwsp.colrmn; i++, gptr.dbp++){
		if(dither){
		  val = factor * (*gptr.dbp +
				  AlgRandZigNormal(0.0, sigma) -
				  min.v.dbv) + Min.v.dbv;
		  val = WLZ_CLAMP(val, gMin, gMax);
		} else {
		  val = factor * (*gptr.dbp - min.v.dbv) + Min.v.dbv;
		}
		*gptr.dbp = val;
	      }
	      break;
	    default:
	      errNum = WLZ_ERR_GREY_TYPE;
	      break;
	  }
	}
	(void )WlzEndGreyScan(&iwsp, &gwsp);
	if(errNum == WLZ_ERR_EOO){
	  errNum = WLZ_ERR_NONE;
	}
      }
    }
  }
  return errNum;
}
Example #23
0
/*!
* \return	Coordinates of center of mass.
* \ingroup	WlzFeatures
* \brief	Calculates the centre of mass of a WLZ_3D_DOMAIN_OBJ.
*		If the object has values and the binary object flag is not set
*		then the centre of mass is calculated using the grey level
*		information.
*		\f[
                C_x = \frac{\sum_x{\sum_y{\sum_z{x G(x,y,z)}}}}
		           {\sum_x{\sum_y{\sum_z{G(x,y,z)}}}} ,
                C_y = \frac{\sum_x{\sum_y{\sum_z{y G(x,y,z)}}}}
		           {\sum_x{\sum_y{\sum_z{G(x,y,z)}}}}
                C_z = \frac{\sum_x{\sum_y{\sum_z{z G(x,y,z)}}}},
		           {\sum_x{\sum_y{\sum_z{G(x,y,z)}}}}
		\f]
*               Where \f$(C_x,C_y,C_z)\f$ are the coordinates of the centre of
*               mass.
*               If the given object does not have grey values or the
*               binary object flag is set (ie non zero) then every
*               pixel within the objects domain has the same mass.
* \param	srcObj			Given object.
* \param	binObjFlag		Binary object flag.
* \param	dstMass			Destination pointer for mass, may be
* 					NULL.
* \param	dstErr			Destination pointer for error, may be
* 					NULL.
*/
static WlzDVertex3 WlzCentreOfMassDom3D(WlzObject *srcObj, int binObjFlag,
				        double *dstMass, WlzErrorNum *dstErr)
{
  int		planeIdx,
  		planeCount;
  double        mass = 0.0,
  		mass2D;
  WlzDVertex2	cMass2D;
  WlzDVertex3	cMass,
  		sum;
  WlzDomain	srcDom,
  		dummyDom;
  WlzDomain	*srcDomains;
  WlzValues	dummyValues;
  WlzValues	*srcValues;
  WlzObject	*srcObj2D;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  sum.vtX = 0.0;
  sum.vtY = 0.0;
  sum.vtZ = 0.0;
  cMass.vtX = 0.0;
  cMass.vtY = 0.0;
  cMass.vtZ = 0.0;
  dummyDom.core = NULL;
  dummyValues.core = NULL;
  if((srcDom = srcObj->domain).core == NULL)
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if(srcDom.core->type != WLZ_PLANEDOMAIN_DOMAIN)
  {
    errNum = WLZ_ERR_DOMAIN_TYPE;
  }
  else if((srcDomains = srcDom.p->domains) == NULL)
  {
    errNum = WLZ_ERR_DOMAIN_DATA;
  }
  else if((binObjFlag == 0) && (srcObj->values.core != NULL) &&
          WlzGreyTableIsTiled(srcObj->values.core->type))
  {
    errNum = WLZ_ERR_VOXELVALUES_TYPE;
  }
  else
  {
    if((srcObj->values.core == NULL) ||
       ((srcValues = srcObj->values.vox->values) == NULL))
    {
      binObjFlag = 1;
    }
    srcObj2D = WlzMakeMain(WLZ_2D_DOMAINOBJ, dummyDom,
			   dummyValues, NULL, NULL, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    planeIdx =  0;
    planeCount = srcDom.p->lastpl - srcDom.p->plane1 + 1;
    while((errNum == WLZ_ERR_NONE) && (planeCount-- > 0))
    {
      srcObj2D->domain = *(srcDomains + planeIdx);
      if(binObjFlag)
      {
	srcObj2D->values.core = NULL;
      }
      else
      {
	srcObj2D->values = *(srcValues + planeIdx);
      }
      cMass2D = WlzCentreOfMass2D(srcObj2D, binObjFlag, &mass2D,
	  &errNum);
      sum.vtX += cMass2D.vtX * mass2D;
      sum.vtY += cMass2D.vtY * mass2D;
      sum.vtZ += (srcDom.p->plane1 + planeIdx) * mass2D;
      mass += mass2D;
      ++planeIdx;
    }
    srcObj2D->domain.core = NULL;
    srcObj2D->values.core = NULL;
    (void )WlzFreeObj(srcObj2D);
    if(errNum == WLZ_ERR_NONE)
    {
      if((mass > DBL_EPSILON) || (mass < (-(DBL_EPSILON))))
      {
	cMass.vtX = sum.vtX / mass;
	cMass.vtY = sum.vtY / mass;
	cMass.vtZ = sum.vtZ / mass;
      }
      if(dstMass)
      {
	*dstMass = mass;
      }
    }
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(cMass);
}