Exemplo n.º 1
0
/*!
* \return	Compound array.
* \ingroup	WlzTransform
* \brief	Computes a compound array of three objects, the objects 
                representing the t11, t12 qnd t22 componemts of a tensor.
* \param	inobj			Given object.
* \param        basisTensorTr           Basis Function tensor transform
* \param	dstErr			Destination error pointer, may be
*					NULL.
*/
static WlzCompoundArray *WlzBasisFnTensorTransformObjPrv(WlzObject *inObj, 
					 WlzBasisFnTransform *basisTr, 
					 WlzErrorNum *dstErr)
{
  WlzObject 		*objT11 = NULL,
                        *objT12 = NULL,
                        *objT22 = NULL;
  WlzCompoundArray	*cArray = NULL;
  WlzValues		valuesT11,
                        valuesT12,
                        valuesT22;
  WlzIntervalWSpace     iWsp,
                        iWspT11,
                        iWspT12,
                        iWspT22;
  WlzGreyWSpace	        gWspT11,
                        gWspT12,
                        gWspT22;
  WlzDVertex2           sVtx;
  WlzErrorNum		errNum=WLZ_ERR_NONE;
  WlzObjectType           vType;
  WlzGreyP	        gPixT11,
                        gPixT12,
                        gPixT22;
  WlzPixelV 		backgrnd;
  WlzFnType             basisFnType;
  double                t11Partial,
                        t12APartial,
                        t12BPartial,
                        t22Partial;
  int 		        k,
                        l;
 
  valuesT11.core = NULL;
  valuesT12.core = NULL;  
  valuesT22.core = NULL;
  basisFnType = basisTr->basisFn->type;
  /* Create value tables for the two objects */
  vType = WlzGreyTableType(WLZ_GREY_TAB_RAGR, WLZ_GREY_FLOAT, NULL);
  backgrnd.type = WLZ_GREY_FLOAT;
  backgrnd.v.inv = 0;
  if((valuesT11.v = WlzNewValueTb(inObj, vType, backgrnd, &errNum)) != NULL)
  {
    if((valuesT12.v = WlzNewValueTb(inObj, vType, backgrnd, &errNum)) != NULL)
    {
      valuesT22.v = WlzNewValueTb(inObj, vType, backgrnd, &errNum);
    }
    else
    {
      WlzFreeValueTb(valuesT11.v);
      WlzFreeValueTb(valuesT12.v);
    }
  }
  else
  {
    WlzFreeValueTb(valuesT11.v);
  }
  /* create three Wlz objects to hold t11, t22 and t12 tensor components */
  if (errNum == WLZ_ERR_NONE)
  {
    if ((objT11 = WlzMakeMain(inObj->type, inObj->domain, valuesT11, NULL, 
			      NULL, &errNum)) != NULL) 
    {
      if ((objT12 = WlzMakeMain(inObj->type, inObj->domain, valuesT12, NULL, 
			        NULL, &errNum)) != NULL) 
      {
	if ((objT22 = WlzMakeMain(inObj->type, inObj->domain, valuesT22, 
				   NULL, NULL, &errNum)) == NULL)
	{
	  WlzFreeObj(objT11);
	  objT11 = NULL;
	  WlzFreeObj(objT12);
	  objT12 = NULL;
	}
      }
      else
      {
	WlzFreeObj(objT11);
	objT11 = NULL;
      }
    }
  }
  /* initialise workspaces */
  if (errNum == WLZ_ERR_NONE)
  {
    if ((errNum = WlzInitRasterScan(inObj, &iWsp, WLZ_RASTERDIR_ILIC)) == 
	WLZ_ERR_NONE)
    {
      if ((errNum = WlzInitGreyScan(objT11, &iWspT11, &gWspT11)) == 
	  WLZ_ERR_NONE)
      {
	if ((errNum = WlzInitGreyScan(objT12, &iWspT12, &gWspT12)) == 
	  WLZ_ERR_NONE)
	{
	  errNum = WlzInitGreyScan(objT22, &iWspT22, &gWspT22);
	}
      }
    }
  }
  /* Calculate tensor components for MQ2 only */
  if (errNum == WLZ_ERR_NONE)
  {
    switch (basisFnType)
    {
      case WLZ_FN_BASIS_2DMQ:
	while(((errNum = WlzNextInterval(&iWsp)) == WLZ_ERR_NONE) &&
	      ((errNum = WlzNextGreyInterval(&iWspT11)) == WLZ_ERR_NONE) &&
	      ((errNum = WlzNextGreyInterval(&iWspT12)) == WLZ_ERR_NONE) &&
	      ((errNum = WlzNextGreyInterval(&iWspT22)) == WLZ_ERR_NONE))
	{
	  gPixT11 = gWspT11.u_grintptr;
	  gPixT12 = gWspT12.u_grintptr;
	  gPixT22 = gWspT22.u_grintptr;
	  l = iWsp.linpos;
	  for (k = iWsp.lftpos; k <= iWsp.rgtpos; k++)
	  {
	    sVtx.vtX = k;
	    sVtx.vtY = l;
	    t11Partial = WlzBasisFnValueMQ2DPrv(basisTr->basisFn, sVtx, 0);
	    *(gPixT11.flp) = (float)t11Partial;
	    ++(gPixT11.flp);
	    t22Partial = WlzBasisFnValueMQ2DPrv(basisTr->basisFn, sVtx, 1);
	    *(gPixT22.flp) = (float)t22Partial;
	    ++(gPixT22.flp);
	    t12APartial = WlzBasisFnValueMQ2DPrv(basisTr->basisFn, sVtx, 2);
	    t12BPartial = WlzBasisFnValueMQ2DPrv(basisTr->basisFn, sVtx, 3);
	    *(gPixT12.flp) = 0.5 * ((float)t12APartial + (float)t12BPartial);
	    ++(gPixT12.flp);
	  }
	}
        if(errNum == WLZ_ERR_EOO)        
	{
	  errNum = WLZ_ERR_NONE;
	}
	break;
      case WLZ_FN_BASIS_2DTPS:
	while(((errNum = WlzNextInterval(&iWsp)) == WLZ_ERR_NONE) &&
	      ((errNum = WlzNextGreyInterval(&iWspT11)) == WLZ_ERR_NONE) &&
	      ((errNum = WlzNextGreyInterval(&iWspT12)) == WLZ_ERR_NONE) &&
	      ((errNum = WlzNextGreyInterval(&iWspT22)) == WLZ_ERR_NONE))
	{
	  gPixT11 = gWspT11.u_grintptr;
	  gPixT12 = gWspT12.u_grintptr;
	  gPixT22 = gWspT22.u_grintptr;
	  l = iWsp.linpos;
	  for (k = iWsp.lftpos; k <= iWsp.rgtpos; k++)
	  {
	    sVtx.vtX = k;
	    sVtx.vtY = l;
	    t11Partial = WlzBasisFnValueTPS2DPrv(basisTr->basisFn, sVtx, 0);
	    *(gPixT11.flp) = (float)t11Partial;
	    ++(gPixT11.flp);
	    t22Partial = WlzBasisFnValueTPS2DPrv(basisTr->basisFn, sVtx, 1);
	    *(gPixT22.flp) = (float)t22Partial;
	    ++(gPixT22.flp);
	    t12APartial = WlzBasisFnValueTPS2DPrv(basisTr->basisFn, sVtx, 2);
	    t12BPartial = WlzBasisFnValueTPS2DPrv(basisTr->basisFn, sVtx, 3);
	    *(gPixT12.flp) = 0.5 * ((float)t12APartial + (float)t12BPartial);
	    ++(gPixT12.flp);
	  }
	}
        if(errNum == WLZ_ERR_EOO)        
	{
	  errNum = WLZ_ERR_NONE;
	}
	break;
      default:
        errNum = WLZ_ERR_TRANSFORM_TYPE;
      break;
    }
  }
  /* create compound object */
  if (errNum == WLZ_ERR_NONE)
  {
    cArray = WlzMakeCompoundArray(WLZ_COMPOUND_ARR_1, 1, 3, NULL, 
				  objT11->type, &errNum);
    if (errNum == WLZ_ERR_NONE) 
    {
      cArray->o[0] = WlzAssignObject(objT11, NULL);
      cArray->o[1] = WlzAssignObject(objT22, NULL);
      cArray->o[2] = WlzAssignObject(objT12, NULL);
    }
  }

  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(cArray);
}
Exemplo n.º 2
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 );
}
Exemplo n.º 3
0
/*!
* \return	New woolz object or NULL on error.
* \ingroup	WlzArithmetic
* \brief	Scales the values of the given 2D Woolz object so that
* 		\f$v_{new} = m v_{given} + a.\f$ The input object is known
* 		to be a valid 2D domain object with grey values.
* \param	iObj			Given object.
* \param	m			Value to multiply object values by.
* \param	a			Value to add to product.
* \param	rGType			Required grey type for returned object.
* \param	dstErr			Destination error pointer, may be NULL.
*/
static WlzObject *WlzScalarMulAdd2D(WlzObject *iObj, WlzPixelV m, WlzPixelV a,
				WlzGreyType rGType, WlzErrorNum *dstErr)
{
  WlzValues	rValues;
  WlzObjectType rVType;
  WlzPixelV	bgdV;
  WlzObject	*rObj = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  rValues.core = NULL;
  bgdV = WlzGetBackground(iObj, &errNum);
  if(errNum == WLZ_ERR_NONE)
  {
    rVType = WlzGreyTableTypeToTableType(iObj->values.v->type, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    rVType = WlzGreyTableType(rVType, rGType, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    rValues.v = WlzNewValueTb(iObj, rVType, bgdV, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    rObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, iObj->domain, rValues,
    		       iObj->plist, iObj->assoc, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    switch(rGType)
    {
      case WLZ_GREY_INT:   /* FALLTHROUGH */
      case WLZ_GREY_SHORT: /* FALLTHROUGH */
      case WLZ_GREY_UBYTE: /* FALLTHROUGH */
      case WLZ_GREY_RGBA:  /* FALLTHROUGH */
      case WLZ_GREY_FLOAT: /* FALLTHROUGH */
      case WLZ_GREY_DOUBLE:
	WlzValueConvertPixel(&m, m, WLZ_GREY_DOUBLE);
	WlzValueConvertPixel(&a, a, WLZ_GREY_DOUBLE);
	errNum = WlzScalarMulAddSet2D(rObj, iObj, m.v.dbv, a.v.dbv);
	break;
      default:
        errNum = WLZ_ERR_GREY_TYPE;
	break;
    }
  }
  if(errNum != WLZ_ERR_NONE)
  {
    if(rObj == NULL)
    {
      (void )WlzFreeValueTb(rValues.v);
    }
    else
    {
      (void )WlzFreeObj(rObj);
      rObj = NULL;
    }
  }
  if(dstErr != NULL)
  {
    *dstErr = errNum;
  }
  return(rObj);
}
Exemplo n.º 4
0
/*!
* \return	Shade corrected object or NULL on error.
* \ingroup	WlzValueFilters
* \brief	Shade corrects the given 2D domain object with grey
*               values. Grey value types known to be the same.
* \param	srcObj			Given object to be shade
*                                       corrected.
* \param	shdObj			Given bright field object.
* \param	nrmVal			Normalization value.
* \param	inPlace			Modify the grey values of the
*                                       given object if non-zero.
* \param	dstErr			Destination error pointer, may
*                                       be null.
*/
static WlzObject *WlzShadeCorrect2DG(WlzObject *srcObj, WlzObject *shdObj,
				     double nrmVal, int inPlace,
				     WlzErrorNum *dstErr)
{
  int		tI0,
  		iCnt, red, green, blue;
  double	tD0;
  WlzUInt	tUI0, tUI1;
  WlzObject	*uObj = NULL,
		*uSrcObj = NULL,
		*uShdObj = NULL,
  		*rtnObj = NULL;
  WlzGreyP	srcPix,
  		shdPix,
		rtnPix;
  WlzValues	newVal;
  WlzIntervalWSpace srcIWSp,
  		shdIWSp,
		rtnIWSp;
  WlzGreyWSpace	srcGWSp,
  		shdGWSp,
		rtnGWSp;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  /* Find intersection of the given and shade objects. */
  uObj = WlzIntersect2(srcObj, shdObj, &errNum);
  /* Make new objects with the values of the given and shade objects
   * but the domain of their intersection. */
  if(errNum == WLZ_ERR_NONE)
  {
    uSrcObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, uObj->domain, srcObj->values,
    			  NULL, NULL, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    uShdObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, uObj->domain, shdObj->values,
    			  NULL, NULL, &errNum);
  }
  /* Make a new object, again using the union for the domain, but this time
   * either sharing the given objects values or creating a new value table. */
  if(errNum == WLZ_ERR_NONE)
  {
    if(inPlace)
    {
      rtnObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, uObj->domain, srcObj->values,
      			   NULL, NULL, &errNum);
    }
    else
    {
      newVal.v = WlzNewValueTb(uObj, srcObj->values.core->type,
      			       WlzGetBackground(srcObj, NULL), &errNum);
      if(errNum == WLZ_ERR_NONE)
      {
        if((rtnObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, uObj->domain, newVal,
			         NULL, NULL, &errNum)) == NULL)
        {
	  (void )WlzFreeValueTb(newVal.v);
	}
      }
    }
  }

  /* Work through the intervals setting the grey values. */
  if(errNum == WLZ_ERR_NONE)
  {
    if(((errNum = WlzInitGreyScan(uSrcObj, &srcIWSp,
    				  &srcGWSp)) == WLZ_ERR_NONE) &&
       ((errNum = WlzInitGreyScan(uShdObj, &shdIWSp,
    				  &shdGWSp)) == WLZ_ERR_NONE) &&
       ((errNum = WlzInitGreyScan(rtnObj, &rtnIWSp,
    				  &rtnGWSp)) == WLZ_ERR_NONE))
    {
      while(((errNum = WlzNextGreyInterval(&srcIWSp)) == WLZ_ERR_NONE) &&
            ((errNum = WlzNextGreyInterval(&shdIWSp)) == WLZ_ERR_NONE) &&
            ((errNum = WlzNextGreyInterval(&rtnIWSp)) == WLZ_ERR_NONE))
      {
	srcPix = srcGWSp.u_grintptr;
	shdPix = shdGWSp.u_grintptr;
	rtnPix = rtnGWSp.u_grintptr;
	iCnt = rtnIWSp.rgtpos - rtnIWSp.lftpos + 1;
        switch(rtnGWSp.pixeltype)
	{
	  case WLZ_GREY_INT:
	    while(iCnt-- > 0)
	    {
	      tD0 = (*(srcPix.inp)++ * nrmVal) / (*(shdPix.inp)++ + 1.0);
	      *(rtnPix.inp)++ = WLZ_NINT(tD0);
	    }
	    break;
	  case WLZ_GREY_SHORT:
	    while(iCnt-- > 0)
	    {
	      tD0 = (*(srcPix.shp)++ * nrmVal) / (*(shdPix.shp)++ + 1.0);
	      tI0 = WLZ_NINT(tD0);
	      *(rtnPix.shp)++ = (short )WLZ_CLAMP(tI0, SHRT_MIN, SHRT_MAX);
	    }
	    break;
	  case WLZ_GREY_UBYTE:
	    while(iCnt-- > 0)
	    {
	      tD0 = (*(srcPix.ubp)++ * nrmVal) / (*(shdPix.ubp)++ + 1.0);
	      tI0 = WLZ_NINT(tD0);
	      *(rtnPix.ubp)++ = (WlzUByte )WLZ_CLAMP(tI0, 0, 255);
	    }
	    break;
	  case WLZ_GREY_FLOAT:
	    while(iCnt-- > 0)
	    {
	      tD0 = (*(srcPix.flp)++ * nrmVal) / (*(shdPix.flp)++ + 1.0);
	      *(rtnPix.flp)++ = (float )tD0;
	    }
	    break;
	  case WLZ_GREY_DOUBLE:
	    while(iCnt-- > 0)
	    {
	      tD0 = (*(srcPix.dbp)++ * nrmVal) / (*(shdPix.dbp)++ + 1.0);
	      *(rtnPix.dbp)++ = tD0;
	    }
	    break;
	  case WLZ_GREY_RGBA:
	    while(iCnt-- > 0)
	    {
	      /* slightly different logic here. Avoid divide by zero
		 by explicit check */
	      tUI0 = *(srcPix.rgbp)++;
	      tUI1 = *(shdPix.rgbp)++;
	      red = WLZ_RGBA_RED_GET(tUI1);
	      red = (red)?
		    (int )(((WLZ_RGBA_RED_GET(tUI0) * nrmVal))/red):
		    (int )nrmVal;
	      red = WLZ_CLAMP(red, 0, 255);
	      green = WLZ_RGBA_GREEN_GET(tUI1);
	      green = (green)?
	              (int )(((WLZ_RGBA_GREEN_GET(tUI0) * nrmVal))/green):
		      (int )nrmVal;
	      green = WLZ_CLAMP(green, 0, 255);
	      blue = WLZ_RGBA_BLUE_GET(tUI1);
	      blue = (blue)?
	             (int )(((WLZ_RGBA_BLUE_GET(tUI0) * nrmVal))/blue):
	             (int )nrmVal;
	      blue = WLZ_CLAMP(blue, 0, 255);
	      WLZ_RGBA_RGBA_SET(tUI0, red, green, blue, 255);
	      *(rtnPix.rgbp)++ = tUI0;
	    }
	    break;
	  default:
	    errNum = WLZ_ERR_GREY_TYPE;
	    break;
	}
      }
      if(errNum == WLZ_ERR_EOO)         /* Reset error from end of intervals */
      {
        errNum = WLZ_ERR_NONE;
      }
    }
  }
  (void )WlzFreeObj(uObj);
  (void )WlzFreeObj(uSrcObj);
  (void )WlzFreeObj(uShdObj);
  if(errNum != WLZ_ERR_NONE)
  {
    (void )WlzFreeObj(rtnObj);
    rtnObj = NULL;
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(rtnObj);
}