예제 #1
0
/*! 
* \ingroup      WlzValuesUtils
* \brief        Gets a single grey value/pointer for the given point
*		from the 3D values and domain in the work space.
*
* \param    gVWSp	grey-value work space
* \param    plane	plane coordinate
* \param    line	line coordinate
* \param    kol	column coordinate
*/
void		WlzGreyValueGetDir(WlzGreyValueWSpace *gVWSp,
				   int plane, int line, int kol)
{
  int		pln0,
  		pln1,
  		valSet = 0;
  WlzDomain	*domP;
  WlzValues	*valP;

  pln0 = plane - gVWSp->domain.p->plane1;
  pln1 = gVWSp->domain.p->lastpl - gVWSp->domain.p->plane1;
#ifdef WLZ_FAST_CODE
  if((unsigned int)(pln0) <= (unsigned int)(pln1))
#else
  if((plane >= gVWSp->domain.p->plane1) &&
     (plane <= gVWSp->domain.p->lastpl))
#endif
  {
    if(gVWSp->gTabType == (WlzObjectType )WLZ_GREY_TAB_TILED)
    {
      WlzGreyValueGet(gVWSp, plane, line, kol);
      valSet = 1;
    }
    else
    {
      if(gVWSp->plane == plane)
      {
	WlzGreyValueGet2D1(gVWSp, line, kol);
	valSet = 1;
      }
      else
      {
	domP = gVWSp->domain.p->domains + pln0;
	valP = gVWSp->values.vox->values + pln0;
	/* check for non-NULL domain and valuetable
	   pointers until empty obj consistently implemented */
	if((*domP).core && (*valP).core)
	{
	  gVWSp->plane = plane;
	  gVWSp->iDom2D = (*domP).i;
	  gVWSp->values2D = (*valP);
	  gVWSp->gTabType2D = gVWSp->gTabTypes3D[pln0];
	  WlzGreyValueGet2D1(gVWSp, line, kol);
	  valSet = 1;
	}
      }
    }
  }
  if(valSet == 0)
  {
    WlzGreyValueSetBkdP(gVWSp->gVal, gVWSp->gPtr, gVWSp->gType, gVWSp->gBkd);
  }
}
예제 #2
0
파일: WlzProfile.c 프로젝트: ma-tech/Woolz
/*!
* \return	Woolz error code.
* \ingroup	WlzTransform
* \brief	Sets the profile value for walk function.
* \param	obj		Given object from which to set the value.
* \param	pos		Position of value in given object.
* \param	pWSp		Profile workspace.
*/
static WlzErrorNum WlzProfileSetPixels(
  WlzObject *obj,
  WlzIVertex3 pos,
  WlzProfileWalkWSp *pWSp)
{
  WlzGreyP	gP;
  WlzGreyV	gV;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  WlzGreyValueGet(pWSp->gVWSp, pos.vtZ, pos.vtY, pos.vtX);
  gP = pWSp->values.r->values;
  gV = pWSp->gVWSp->gVal[0];
  switch(pWSp->gVWSp->gType)
  {
    case WLZ_GREY_LONG:
      *(gP.lnp + pWSp->index) = gV.lnv;
      break;
    case WLZ_GREY_INT:
      *(gP.inp + pWSp->index) = gV.inv;
      break;
    case WLZ_GREY_SHORT:
      *(gP.shp + pWSp->index) = gV.shv;
      break;
    case WLZ_GREY_UBYTE:
      *(gP.ubp + pWSp->index) = gV.ubv;
      break;
    case WLZ_GREY_FLOAT:
      *(gP.flp + pWSp->index) = gV.flv;
      break;
    case WLZ_GREY_DOUBLE:
      *(gP.dbp + pWSp->index) = gV.dbv;
      break;
    case WLZ_GREY_RGBA:
      *(gP.rgbp + pWSp->index) = gV.rgbv;
      break;
    default:
      errNum = WLZ_ERR_GREY_TYPE;
      break;
  }
  return(errNum);
}
예제 #3
0
/*!
* \return	The grey value as a double.
* \ingroup	WlzAccess
* \brief	Gets a single grey value for the given point from the
*               object with which the given work space was initialised.
* \param	gVWSp			Grey value work space.
* \param	plane			Plane (z) coordinate of point.
* \param	line			Line (y) coordinate of point.
* \param	kol			Column (x) coordinate of point.
*/
double		WlzGreyValueGetD(WlzGreyValueWSpace *gVWSp,
				 double plane, double line, double kol)
{
  double		val = 0;

  if(gVWSp)
  {
    WlzGreyValueGet(gVWSp, plane, line, kol);
    switch(gVWSp->gType)
    {
      case WLZ_GREY_LONG:
        val = gVWSp->gVal[0].lnv;
        break;
      case WLZ_GREY_INT:
        val = gVWSp->gVal[0].inv;
        break;
      case WLZ_GREY_SHORT:
        val = gVWSp->gVal[0].shv;
        break;
      case WLZ_GREY_UBYTE:
        val = gVWSp->gVal[0].ubv;
        break;
      case WLZ_GREY_FLOAT:
        val = gVWSp->gVal[0].flv;
	break;
      case WLZ_GREY_DOUBLE:
        val = gVWSp->gVal[0].dbv;
	break;
      case WLZ_GREY_RGBA:
        val = gVWSp->gVal[0].rgbv;
	break;
      default:
        break;
    }
  }
  return(val);
}
예제 #4
0
/*!
* \return	New Woolz object without holes or NULL on error.
* \ingroup	WlzDomainOps
* \brief	Fills the holes in the given object's domain (which are by
* 		definition not connected to the outside). When the given
* 		object's domain has more than one component part, the
* 		object should first be labeled, this function should then be
* 		called for each of the labeled parts and then the union of
* 		the filled domains should be formed.
* \param	srcObj			Given 3D domain object.
* \param	dstErr			Destination error pointer, may be NULL.
*/
WlzObject 			*WlzDomainFill3D(
  				  WlzObject *srcObj,
    				  WlzErrorNum *dstErr)
{
  int		nPln = 0;
  WlzObject	*bndObj = NULL,
  		*filObj = NULL,
  		*gvnObj = NULL,
		*sedObj = NULL,
		*shlObj = NULL;
  WlzPixelV	zeroV;
  WlzValues 	nullVal;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      /* Put back any isolated voxels this function has removed. */
      tObj0 = WlzAssignObject(
              WlzMakeMain(srcObj->type, filDom, nullVal,
      			  NULL, NULL, &errNum), NULL);
      if(errNum == WLZ_ERR_NONE)
      {
        tObj1 = WlzUnion2(gvnObj, tObj0, &errNum);
      }
      if(errNum == WLZ_ERR_NONE)
      {
	filObj = WlzMakeMain(tObj1->type, tObj1->domain, nullVal,
			     NULL, NULL, &errNum);
      }
      (void )WlzFreeObj(tObj0);
      (void )WlzFreeObj(tObj1);
    }
  }
  (void )WlzFreeObj(bndObj);
  (void )WlzFreeObj(gvnObj);
  (void )WlzFreeObj(shlObj);
  (void )WlzFreeObj(sedObj);
  if((errNum != WLZ_ERR_NONE) && (filObj != NULL))
  {
    (void )WlzFreeObj(filObj);
    filObj = NULL;
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(filObj);
}
예제 #5
0
XImage *HGU_XmObjToXImageLut2D(
    XWindowAttributes	*win_att,
    WlzObject	*obj,
    HGU_XmLut	lut,
    WlzErrorNum	*dstErr)
{
    XImage		*rtnImage=NULL;
    Dimension		width, height;
    WlzUByte			*data, *dst_data;
    WlzGreyValueWSpace	*gVWSp = NULL;
    WlzErrorNum		errNum=WLZ_ERR_NONE;
    int			i, j;
    int			rIndx=0, gIndx=0, bIndx=0, aIndx=0;
    WlzUInt		r, g, b, a;

    /* allocate space for the data */
    width = obj->domain.i->lastkl - obj->domain.i->kol1 + 1;
    height = obj->domain.i->lastln - obj->domain.i->line1 + 1;
    if( (gVWSp = WlzGreyValueMakeWSp(obj, &errNum)) ) {
        if( (data = (WlzUByte *) AlcMalloc(((win_att->depth == 8)?1:4)
                                           *width*height*sizeof(char))) ) {
            dst_data = data;
            if( (rtnImage = XCreateImage(DisplayOfScreen(win_att->screen),
                                         win_att->visual, win_att->depth,
                                         ZPixmap, 0, (char *) dst_data,
                                         width, height, 8, 0)) ) {

                /* establish rgb index values if 24 bit */
                if( win_att->depth == 24 ) {
                    rIndx = HGU_XmGetColorIndexFromMask24(win_att->visual->red_mask,
                                                          rtnImage->byte_order);
                    gIndx = HGU_XmGetColorIndexFromMask24(win_att->visual->green_mask,
                                                          rtnImage->byte_order);
                    bIndx = HGU_XmGetColorIndexFromMask24(win_att->visual->blue_mask,
                                                          rtnImage->byte_order);
                    aIndx = HGU_XmGetColorIndexFromMask24(~(win_att->visual->red_mask|
                                                            win_att->visual->green_mask|
                                                            win_att->visual->blue_mask),
                                                          rtnImage->byte_order);
                }

                /* fill in the values */
                a = 0xff;
                for(j=0; j < height; j++) {
                    for(i=0; i < width; i++, data++) {
                        WlzGreyValueGet(gVWSp, 0, j + obj->domain.i->line1,
                                        i + obj->domain.i->kol1);
                        switch( gVWSp->gType ) {
                        default:
                        case WLZ_GREY_INT:
                            r = *(gVWSp->gPtr[0].inp);
                            g = b = r;
                            break;
                        case WLZ_GREY_SHORT:
                            r = *(gVWSp->gPtr[0].shp);
                            g = b = r;
                            break;
                        case WLZ_GREY_UBYTE:
                            r = *(gVWSp->gPtr[0].ubp);
                            g = b = r;
                            break;
                        case WLZ_GREY_FLOAT:
                            r = *(gVWSp->gPtr[0].flp);
                            g = b = r;
                            break;
                        case WLZ_GREY_DOUBLE:
                            r = *(gVWSp->gPtr[0].dbp);
                            g = b = r;
                            break;
                        case WLZ_GREY_RGBA:
                            b = *(gVWSp->gPtr[0].rgbp);
                            r = WLZ_RGBA_RED_GET(b);
                            g = WLZ_RGBA_GREEN_GET(b);
                            b = WLZ_RGBA_BLUE_GET(b);
                            break;
                        }

                        switch( lut.core->type ) {
                        case HGU_XmLUT_GREY:
                            r = lut.g->lut[r - lut.g->min];
                            g = lut.g->lut[g - lut.g->min];
                            b = lut.g->lut[b - lut.g->min];
                            break;

                        case HGU_XmLUT_RGB:
                            r = lut.rgb->lut[0][r - lut.rgb->min[0]];
                            g = lut.rgb->lut[1][g - lut.rgb->min[1]];
                            b = lut.rgb->lut[2][b - lut.rgb->min[2]];
                            break;

                        case HGU_XmLUT_COMPOUND:
                            break;
                        }
                        switch( win_att->depth ) {
                        case 24:
                            data[rIndx] = r;
                            data[gIndx] = g;
                            data[bIndx] = b;
                            data[aIndx] = a;
                            data += 3;
                            break;

                        case 8:
                            data[0] = r;
                            break;
                        }
                    }
                }
            }
            else {
                errNum = WLZ_ERR_UNSPECIFIED;
                AlcFree((void *) dst_data);
            }
        }
        else {
            errNum = WLZ_ERR_MEM_ALLOC;
        }
        WlzGreyValueFreeWSp(gVWSp);
    }

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


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

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

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

        default:
            errNum = WLZ_ERR_OBJECT_TYPE;
            break;
        }
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            }

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

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

        }

    }

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

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

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

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

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

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

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

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

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

        WlzGreyValueFreeWSp(gVWSp);
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  if( dstErr ){
    *dstErr = errNum;
  }
  return rtnObj;
}
예제 #8
0
double WlzMixtureValue(
  WlzObject	*obj1,
  WlzObject	*obj2,
  int		numCatRows,
  int		numCatCols,
  double	**mixing,
  double	**contrib,
  WlzErrorNum	*dstErr)
{
  double	val, con;
  WlzObject	*tmpObj, *tmpObj1, *tmpObj2;
  WlzIntervalWSpace	iwsp;
  WlzGreyWSpace		gwsp;
  WlzGreyP		gptr;
  WlzGreyValueWSpace	*gVWSp;
  WlzPixelV		minP, maxP;
  int		i;
  WlzErrorNum	errNum=WLZ_ERR_NONE;

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

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

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

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

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

  if( dstErr ){
    *dstErr = errNum;
  }
  if( con > 0.0 ){
    return val/con;
  }
  else {
    return 0.0;
  }
}
예제 #9
0
/*!
* \return	New filtered object with new values or NULL on error.
* \ingroup	WlzValuesFilters
* \brief	Applies a seperable filter along the z axis (planes)
* 		to the given object using the given convolution kernel.
* \param	inObj			Input 3D spatial domain object to be
* 					filtered which must have scalar values.
* \param	bBox			Object's bounding box.
* \param	maxThr			Maximum number of threads to use.
* \param	iBuf			Working buffers large enough for any
* 				        column in the image with one for each
* 				        thread.
* \param	rBuf			Buffers as for iBuf. 			
* \param	cBufSz			Convolution kernel size.
* \param	cBuf			Convolution kernel buffer.
* \param	pad			Type of padding.
* \param	padVal			Padding value.
* \param	dstErr			Destination error pointer may be NULL.
*/
static WlzObject		*WlzSepFilterZ(WlzObject *inObj,
				  WlzIBox3 bBox,
				  int maxThr,
				  double **iBuf,
				  double **rBuf,
				  int cBufSz,
				  double *cBuf,
				  AlgPadType pad,
				  double padVal,
				  WlzErrorNum *dstErr)
{
  WlzObjectType	rGTT;
  WlzPixelV	zV;
  WlzObject	*rnObj = NULL;
  WlzGreyValueWSpace **iVWSp = NULL,
	             **rVWSp = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  		
  zV.v.dbv = 0.0;
  zV.type = WLZ_GREY_DOUBLE;
  rGTT = WlzGreyTableType(WLZ_GREY_TAB_RAGR, WLZ_GREY_DOUBLE, NULL);
  rnObj = WlzNewObjectValues(inObj, rGTT, zV, 1, zV, &errNum);
  if(errNum == WLZ_ERR_NONE)
  {
    if(((iVWSp = (WlzGreyValueWSpace **)
                 AlcCalloc(maxThr, sizeof(WlzGreyValueWSpace *))) == NULL) ||
       ((rVWSp = (WlzGreyValueWSpace **)
                 AlcCalloc(maxThr, sizeof(WlzGreyValueWSpace *))) == NULL))
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    int		idt;

    for(idt = 0; (idt < maxThr) && (errNum == WLZ_ERR_NONE); ++idt)
    {
      iVWSp[idt] = WlzGreyValueMakeWSp(inObj, &errNum);
      if(errNum == WLZ_ERR_NONE)
      {
	rVWSp[idt] = WlzGreyValueMakeWSp(rnObj, &errNum);
      }
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    int		idy;

#ifdef _OPENMP
#pragma omp parallel for num_threads(maxThr)
#endif
    for(idy = bBox.yMin; idy <= bBox.yMax; ++idy)
    {
      int	idx,
      		thrId = 0;
      WlzGreyValueWSpace *iVWSpT,
			 *rVWSpT;

#ifdef _OPENMP
      thrId = omp_get_thread_num();
#endif
      iVWSpT = iVWSp[thrId];
      rVWSpT = rVWSp[thrId];
      for(idx = bBox.xMin; idx <= bBox.xMax; ++idx)
      {
	int 	z0,
	      z1,
	      idz;
	WlzUByte in = 0;

	for(idz = bBox.zMin; idz <= bBox.zMax + 1; ++idz)
	{
	  WlzGreyValueGet(iVWSpT, idz, idy, idx);
	  if(iVWSpT->bkdFlag == 0)
	  {
	   double	*ibp;

	   if(in == 0)
	   {
	     z0 = idz;
	     in = 1;
	   }
	   z1 = idz;
	   ibp = iBuf[thrId] + (z1  - z0);
	   switch(iVWSpT->gType)
	   {
	     case WLZ_GREY_INT:
	       *ibp = iVWSpT->gVal[0].inv;
	       break;
	     case WLZ_GREY_SHORT:
	       *ibp = iVWSpT->gVal[0].shv;
	       break;
	     case WLZ_GREY_UBYTE:
	       *ibp = iVWSpT->gVal[0].ubv;
	       break;
	     case WLZ_GREY_FLOAT:
	       *ibp = iVWSpT->gVal[0].flv;
	       break;
	     case WLZ_GREY_DOUBLE:
	       *ibp = iVWSpT->gVal[0].dbv;
	       break;
	     default:
	       break;
	   }
	  }
	  else if(in)
	  {
	    int	idr,
		len;

	    len = z1 - z0 + 1;
	    AlgConvolveD(len, rBuf[thrId], cBufSz * 2 + 1, cBuf,
			 len, iBuf[thrId], pad, padVal);
	    for(idr = z0; idr <= z1; ++idr)
	    {
	      WlzGreyValueGet(rVWSpT, idr, idy, idx);
	      *(rVWSpT->gPtr[0].dbp) = rBuf[thrId][idr - z0];
	    }
	  }
	}
      }
    }
  }
  if(iVWSp)
  {
    int		idt;

    for(idt = 0; idt < maxThr; ++idt)
    {
      WlzGreyValueFreeWSp(iVWSp[idt]);
    }
    AlcFree(iVWSp);
  }
  if(rVWSp)
  {
    int		idt;

    for(idt = 0; idt < maxThr; ++idt)
    {
      WlzGreyValueFreeWSp(rVWSp[idt]);
    }
    AlcFree(rVWSp);
  }
  if(errNum != WLZ_ERR_NONE)
  {
    (void )WlzFreeObj(rnObj);
    rnObj = NULL;
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(rnObj);
}
예제 #10
0
/*!
* \return	New filtered object with new values or NULL on error.
* \ingroup	WlzValuesFilters
* \brief	Applies a seperable filter along the y axis (lines)
* 		to the given object using the given convolution kernel.
* \param	inObj			Input 2 or 3D spatial domain object
* 					to be filtered which must have scalar
* 					values.
* \param	dim			Object's dimension.
* \param	maxThr			Maximum number of threads to use.
* \param	iBuf			Working buffers large enough for any
* 				        column in the image with one for each
* 				        thread.
* \param	rBuf			Buffers as for iBuf. 			
* \param	cBufSz			Convolution kernel size.
* \param	cBuf			Convolution kernel buffer.
* \param	pad			Type of padding.
* \param	padVal			Padding value.
* \param	dstErr			Destination error pointer may be NULL.
*/
static WlzObject		*WlzSepFilterY(WlzObject *inObj,
				  int dim,
				  int maxThr,
				  double **iBuf,
				  double **rBuf,
				  int cBufSz,
				  double *cBuf,
				  AlgPadType pad,
				  double padVal,
				  WlzErrorNum *dstErr)
{
  int		idp,
		poff,
  		nPln;
  WlzObjectType	rGTT;
  WlzDomain	*domains;
  WlzValues	*iVal,
  		*rVal;
  WlzPixelV	zV;
  WlzObject	*rnObj = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  		
  zV.v.dbv = 0.0;
  zV.type = WLZ_GREY_DOUBLE;
  rGTT = WlzGreyTableType(WLZ_GREY_TAB_RAGR, WLZ_GREY_DOUBLE, NULL);
  if(dim == 3)
  {
    WlzPlaneDomain *pDom;
    WlzVoxelValues *vVal;

    pDom = inObj->domain.p;
    vVal = inObj->values.vox;
    nPln = pDom->lastpl - pDom->plane1 + 1;
    domains = pDom->domains;
    iVal = vVal->values;
    poff = pDom->plane1 - vVal->plane1;
    rnObj = WlzNewObjectValues(inObj, rGTT, zV, 1, zV, &errNum);
    if(errNum == WLZ_ERR_NONE)
    {
      rVal = rnObj->values.vox->values;
    }
  }
  else
  {
    nPln = 1;
    poff = 0;
    domains = &(inObj->domain);
    iVal = &(inObj->values);
    rnObj = WlzNewObjectValues(inObj, rGTT, zV, 1, zV, &errNum);
    if(errNum == WLZ_ERR_NONE)
    {
      rVal = &(rnObj->values);
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
#ifdef _OPENMP
#pragma omp parallel for num_threads(maxThr)
#endif
    for(idp = 0; idp < nPln; ++idp)
    {
      if(errNum == WLZ_ERR_NONE)
      {
	if(domains[idp].core != NULL)
	{
	  int		thrId = 0;
	  WlzIBox2	bBox;
	  WlzObject	*iObj = NULL,
			*rObj = NULL;
	  WlzGreyValueWSpace *iVWSp = NULL,
			     *rVWSp = NULL;
          WlzErrorNum	errNum2 = WLZ_ERR_NONE;

#ifdef _OPENMP
          thrId = omp_get_thread_num();
#endif
	  iObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, domains[idp], iVal[idp + poff],
			     NULL, NULL, &errNum);
	  if(errNum == WLZ_ERR_NONE)
	  {
	    rObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, domains[idp], rVal[idp],
			       NULL, NULL, &errNum);
	  }
	  if(errNum == WLZ_ERR_NONE)
	  {
	    bBox = WlzBoundingBox2I(iObj, &errNum);
	  }
	  if((errNum == WLZ_ERR_NONE) &&
	     ((iVWSp = WlzGreyValueMakeWSp(iObj, &errNum)) != NULL) &&
	     ((rVWSp = WlzGreyValueMakeWSp(rObj, &errNum)) != NULL))
	  {
	    int		idx;

	    for(idx = bBox.xMin; idx <= bBox.xMax; ++idx)
	    {
	      int		y0,
			  y1,
			  idy;
	      WlzUByte	in = 0;

	      for(idy = bBox.yMin; idy <= bBox.yMax + 1; ++idy)
	      {
		WlzGreyValueGet(iVWSp, 0, idy, idx);
		if(iVWSp->bkdFlag == 0)
		{
		 double	*ibp;

		 if(in == 0)
		 {
		   y0 = idy;
		   in = 1;
		 }
		 y1 = idy;
		 ibp = iBuf[thrId] + (y1  - y0);
		 switch(iVWSp->gType)
		 {
		   case WLZ_GREY_INT:
		     *ibp = iVWSp->gVal[0].inv;
		     break;
		   case WLZ_GREY_SHORT:
		     *ibp = iVWSp->gVal[0].shv;
		     break;
		   case WLZ_GREY_UBYTE:
		     *ibp = iVWSp->gVal[0].ubv;
		     break;
		   case WLZ_GREY_FLOAT:
		     *ibp = iVWSp->gVal[0].flv;
		     break;
		   case WLZ_GREY_DOUBLE:
		     *ibp = iVWSp->gVal[0].dbv;
		     break;
		   default:
		     break;
		 }
		}
		else if(in)
		{
		  int 	idr,
			len;

		  len = y1 - y0 + 1;
		  AlgConvolveD(len, rBuf[thrId], cBufSz * 2 + 1, cBuf,
		               len, iBuf[thrId], pad, padVal);
		  for(idr = y0; idr <= y1; ++idr)
		  {
		    WlzGreyValueGet(rVWSp, 0, idr, idx);
		    *(rVWSp->gPtr[0].dbp) = rBuf[thrId][idr - y0];
		  }
		}
	      }
	    }
	  }
	  WlzGreyValueFreeWSp(iVWSp);
	  WlzGreyValueFreeWSp(rVWSp);
	  (void )WlzFreeObj(iObj);
	  (void )WlzFreeObj(rObj);
	  if(errNum2 != WLZ_ERR_NONE)
	  {
#ifdef _OPENMP
#pragma omp critical
	    {
#endif
	      if(errNum == WLZ_ERR_NONE)
	      {
	        errNum = errNum2;
	      }
#ifdef _OPENMP
	    }
#endif
	  }
	}
      }
    }
  }
  if(errNum != WLZ_ERR_NONE)
  {
    (void )WlzFreeObj(rnObj);
    rnObj = NULL;
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(rnObj);
}
예제 #11
0
int             main(int argc, char *argv[])
{
  int		option,
		nReg = 0,
		tNReg = 0,
  		ok = 1,
		usage = 0,
		verbose = 0,
		threshSet = 0,
		centreSet = 0;
  double	minArea = 2;
  char		*inExt,
		*dbgExt,
		*inDir,
		*dbgDir,
		*inFile,
		*dbgFile,
  		*inPath = NULL,
		*dbgPath = NULL,
		*outFile = NULL;
  WlzRadDistVal distSort = WLZ_RADDISTVAL_AREA;
  WlzRadDistRec	*distData = NULL;
  WlzPixelV	thrVal;
  WlzDVertex2	centre;
  WlzCompThreshType thrMtd = WLZ_COMPTHRESH_OTSU;
  WlzThresholdType thrMod = WLZ_THRESH_HIGH;
  WlzEffFormat	inFmt = WLZEFF_FORMAT_NONE,
  		dbgFmt = WLZEFF_FORMAT_NONE;
  WlzObject	*inObj = NULL,
		*disObj = NULL,
  		*segObj = NULL;
  WlzGreyValueWSpace *disGVWSp = NULL;
  WlzObject	**regObjs = NULL;
  FILE		*fP = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  const int	maxObj = 1000000;
  char		pathBuf[FILENAME_MAX];
  const double	eps = 1.0e-06;
  const char	*errMsg;
  static char	optList[] = "hvAGDHELR:c:d:n:o:t:",
		defFile[] = "-";

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

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

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

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

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

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

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

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

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

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

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

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

    for(idR = 0; idR < nReg; ++idR)
    {
      (void )WlzFreeObj(regObjs[idR]);
    }
    AlcFree(regObjs);
  }
  if(usage)
  {
    (void )fprintf(stderr,
    "Usage: %s [-h] [-v] [-A] [-D] [-G] [-H] [-E] [-L] [-R]\n"
    "\t\t[-c #,#] [-d <debug image>] [-n #]  [-o <out file>]\n"
    "\t\t[-t #] [<input image>]\n"
    "Segments the given object using a threshold value and outputs the \n"
    "radial distribution of the thresholded components.\n"
    "Version: %s\n"
    "Options:\n"
    "  -h  Help - prints this usage masseage.\n"
    "  -v  Verbose output.\n"
    "  -A  Sort output by area (default).\n"
    "  -D  Sort output by distance from boundary.\n"
    "  -G  Sort output by angle.\n"
    "  -H  Threshold high, use pixels at or above threshold (default).\n"
    "  -E  Threshold equal, use pixels at threshold.\n"
    "  -L  Threshold low, use pixels below threshold.\n"
    "  -R  Sort output by radial distance from centre.\n"
    "  -c  Centre (default is image centre).\n"
    "  -d  Debug image.\n"
    "  -n  Minimum area (default %g).\n"
    "  -t  Threshold value (default is to compute using Otsu's method).\n"
    "By default the input image object is read from the standard input and\n"
    "the radial distribution is written to the standard output.\n"
    "The image formats understood include wlz, jpg and tif.\n"
    "The output format is:\n"
    "  <angle> <dist from centre> <area> <x pos>,<y pos> <dist form boundary>\n"
    "Example:\n"
    "  %s -o out.txt -d debug.jpg in.tif\n"
    "The input image is read from in.tif, a debug image showing the\n"
    "segmented regions is written to debug.jpg and the radial distribution\n"
    "statistics are written to the file out.txt. With the output in\n"
    "out.txt, the following R code would plot the data as a set of circles\n"
    "with radius proportional to the square root of the component area:\n"
    "  data <- read.table(\"out.txt\")\n"
    "  attach(data)\n"
    "  symbols(x=data$V1, y=data$V2, circles=sqrt(data$V3))\n",
    argv[0],
    WlzVersion(),
    minArea,
    argv[0]);
  }
  return(!ok);
}
예제 #12
0
/*!
* \return	New 3D domain object with corresponding WLZ_GREY_RGBA values.
* \ingroup      WlzValuesUtils
* \brief	Creates a WLZ_GREY_RGBA valued object from the given compound
* 		array. This is a static function which will always be called
* 		with valid parameters so they aren't checked.
* \param	cObj			Compound array object.
* \param	cSpc 			The colour space.
* \param	dstErr			Destination error pointer may be NULL.
*/
static WlzObject *WlzCompoundToRGBA2D(WlzCompoundArray *cObj,
  				WlzRGBAColorSpace cSpc, WlzErrorNum *dstErr)
{
  int		i,
  		j;
  WlzObject	*rtnObj=NULL;
  WlzPixelV	bckgrnd;
  WlzObject	*objs[4];
  WlzObjectType vType;
  WlzUInt	b[4];
  WlzErrorNum	errNum=WLZ_ERR_NONE;

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

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

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

      for(j = iwsp.lftpos; j <= iwsp.rgtpos; j++)
      {
	for(i = 0; i < 3; i++)
	{
	  if(gValWSpc[i] == NULL)
	  {
	    pix.v.ubv = (i < 2)? 0: 255;
	  }
	  else
	  {
	    WlzGreyValueGet(gValWSpc[i], 0, iwsp.linpos, j);
	    pix.type = gValWSpc[i]->gType;
	    pix.v = gValWSpc[i]->gVal[0];
	    WlzValueConvertPixel(&pix, pix, WLZ_GREY_UBYTE);
	  }
	  b[i] = pix.v.ubv;
	}
	WLZ_RGBA_RGBA_SET(gval.rgbv, b[0], b[1], b[2], b[3]);
	*gwsp.u_grintptr.rgbp = gval.rgbv;
	gwsp.u_grintptr.rgbp++;
      }
    }
    if(errNum == WLZ_ERR_EOO)
    {
      errNum = WLZ_ERR_NONE;
    }
    for(i=0; i < 3; i++)
    {
      WlzGreyValueFreeWSp(gValWSpc[i]);
    }
  }
  if(dstErr != NULL)
  {
    *dstErr = errNum;
  }
  return(rtnObj);
}
예제 #13
0
void installViewDomains(
  ThreeDViewStruct	*view_struct)
{
  WlzThreeDViewStruct	*wlzViewStr= view_struct->wlzViewStr;
  WlzIntervalWSpace	iwsp;
  WlzGreyWSpace		gwsp;
  WlzGreyValueWSpace	*gVWSp = NULL;
  float			x, y, z;
  int			xp, yp;
  int			i;
  ViewListEntry		*vl = global_view_list;
  WlzErrorNum		errNum=WLZ_ERR_NONE;

  /* all domains on this plane will already have been
     checked for consistency, dominance etc. therefore
     simply set the corresponding domains in the painted
     object */
  /* this is the set version of get section and should be in the
     woolz library. This is probably faster because many assumptions
     are made, mainly the grey-type */
  gVWSp = WlzGreyValueMakeWSp(globals.obj, &errNum);
  if( errNum == WLZ_ERR_NONE ){
    errNum = WlzInitGreyScan( view_struct->painted_object, &iwsp, &gwsp );
    while((errNum == WLZ_ERR_NONE) &&
	  ((errNum = WlzNextGreyInterval( &iwsp )) == WLZ_ERR_NONE) )
    {
      yp = iwsp.linpos - WLZ_NINT(wlzViewStr->minvals.vtY);
      for(i=iwsp.lftpos; i <= iwsp.rgtpos; i++){
	xp = i - WLZ_NINT(wlzViewStr->minvals.vtX);
	x = wlzViewStr->xp_to_x[xp] + wlzViewStr->yp_to_x[yp];
	y = wlzViewStr->xp_to_y[xp] + wlzViewStr->yp_to_y[yp];
	z = wlzViewStr->xp_to_z[xp] + wlzViewStr->yp_to_z[yp];

	WlzGreyValueGet(gVWSp, WLZ_NINT(z), WLZ_NINT(y), WLZ_NINT(x));
	*(gVWSp->gPtr[0].ubp) = *(gwsp.u_grintptr.ubp);
	gwsp.u_grintptr.ubp++;
      }
    }
    if( errNum == WLZ_ERR_EOO ){
      errNum = WLZ_ERR_NONE;
    }
    WlzGreyValueFreeWSp(gVWSp);
  }

  /* copy the new domains to the previous domains */
  if( errNum == WLZ_ERR_NONE ){
    for(i=0; i < 33; i++){
      if( view_struct->prev_domain[i] ){
	WlzFreeObj(view_struct->prev_domain[i]);
	view_struct->prev_domain[i] = NULL;
      }
      if( view_struct->curr_domain[i] ){
	view_struct->prev_domain[i] =
	  WlzAssignObject(view_struct->curr_domain[i], NULL);
      }
    }
  }

  /* set the previous distance and view object  - calculate when needed */
  if( errNum == WLZ_ERR_NONE ){
    view_struct->prev_dist = wlzViewStr->dist;
    if( view_struct->prev_view_obj ){
      WlzFreeObj(view_struct->prev_view_obj);
      view_struct->prev_view_obj = NULL;
    }
    if( view_struct->view_object ){
      view_struct->prev_view_obj = WlzAssignObject(view_struct->view_object,
						   NULL);
    }
    else {
      view_struct->prev_view_obj = NULL;
    }
  }
  
  /* display all views to update the new domains */
  if( errNum == WLZ_ERR_NONE ){
    while( vl != NULL ){
      if( vl->view_struct != paint_key ){
	if( vl->view_struct == view_struct ){
	  redisplay_view_cb(view_struct->canvas,
			    (XtPointer) vl->view_struct, NULL);
	}
	else {
	  display_view_cb(view_struct->canvas,
			  (XtPointer) vl->view_struct, NULL);
	}
      }
      vl = vl->next;
    }
  }

  if( errNum != WLZ_ERR_NONE ){
    MAPaintReportWlzError(globals.topl, "installViewDomains", errNum);
  }
  return;
}
예제 #14
0
/*! 
* \return       projection object
* \ingroup      WlzTransform
* \brief        Use the view transform to define a projection from
*		3D to 2D. Currently only the domain is projected as
*		an opaque shadow.
*		This is old code temporarily kept for compatibility.
* \param    obj	source 3D object
* \param    viewStr	view structure defining the projection
* \param    intFunc	grey-value summation function
* \param    intFuncData data to be passed to the integration function
* \param    dstErr	error return
*/
WlzObject *WlzGetProjectionFromObject(
  WlzObject		*obj,
  WlzThreeDViewStruct 	*viewStr,
  Wlz3DProjectionIntFn 	intFunc,
  void			*intFuncData,
  WlzErrorNum		*dstErr)
{
  WlzObject		*rtnObj=NULL,
  			*obj1;
  WlzThreeDViewStruct	*viewStr1=NULL;
  WlzDomain		domain;
  WlzValues		values;
  WlzGreyType		srcGType = WLZ_GREY_UBYTE,
  			dstGType = WLZ_GREY_UBYTE;
  WlzPixelV		pixval;
  WlzPixelP		pixptr;
  WlzIntervalWSpace	iwsp;
  WlzGreyWSpace		gwsp;
  WlzGreyValueWSpace	*gVWSp = NULL;
  WlzDVertex3		vtx, vtx1;
  double		x, y, z;
  double		*s_to_x=NULL;
  double		*s_to_y=NULL;
  double		*s_to_z=NULL;
  int			k, xp, yp, s, sp;
  int			length = 0, size = 0, occupiedFlg;
  WlzErrorNum 	errNum=WLZ_ERR_NONE;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  /* check error and return */
  if( dstErr ){
    *dstErr = errNum;
  }
  return rtnObj;
}
예제 #15
0
/*!
* \ingroup	WlzTransform
* \brief	Increments values in the array on the straight line segment
* 		between (x0, y0) and (x1, y1) using the given look up table
* 		and the corresponding grey value as an index into this look
* 		up table.
* \param	ary			Rectangular array of ints to set
* 					projected line values in.
* \param	lut			Value density look up table with
* 					256 entries.
* \param	gP			Grey pointer for access to the
* 					object's grey values.
* \param	gVWSp			Grey value workspace for access to
* 					the object grey values, not used if
* 					the grey pointer is non null.
* \param	vMat			View transform matrix.
* \param	vMZX			Precomputed matrix z -> x.
* \param	vMZY			Precomputed matrix z -> y.
* \param	p0			Line segment start.
* \param	p1			Line segment end.
*/
static void	WlzProjectObjLineVal(int **ary, WlzUByte lut[256],
  				     WlzUByte *gP,
				     WlzGreyValueWSpace *gVWSp,
				     double **vMat, double vMZX, double vMZY,
				     WlzIVertex3 p0, WlzIVertex3 p1)
{
#ifdef WLZ_FAST_CODE
  int		v00,
  		v01,
		vMZXI,
		vMZYI;
#else
  WlzDVertex2	q;
#endif
  WlzIVertex2	u;

  vMZX += vMat[0][1] * p0.vtY;
  vMZY += vMat[1][1] * p0.vtY;
#ifdef WLZ_FAST_CODE
  /*
   * Use integer arithmetic for evaluating the transform instead of floating
   * point and then rounding to the nearest integer, which saves about 20% of
   * the execution time for the grey pointer code (mainly be avoiding nint()).
   * Integer multiplication and division are used with a factor of 2^10 which
   * the compiller should recognise and be able to do an arithmetic shift
   * right for division, we can't use >> as it's behaviour for signed ints
   * is platfrom dependant.
   */
  vMZXI = WLZ_NINT(vMZX);
  vMZYI = WLZ_NINT(vMZY);
  v00 = WLZ_NINT(vMat[0][0] * 1024.0);
  v01 = WLZ_NINT(vMat[1][0] * 1024.0);
#endif
  if(gP)
  {
    /* Use the interval of values given by the grey pointer. */
    if(lut)
    {
      while(1)
      {
#ifdef WLZ_FAST_CODE
	u.vtX = ((v00 * p0.vtX) / 1024) + vMZXI;
	u.vtY = ((v01 * p0.vtX) / 1024) + vMZYI;
#else
	q.vtX = (vMat[0][0] * p0.vtX) + vMZX;
	q.vtY = (vMat[1][0] * p0.vtY) + vMZY;
	WLZ_VTX_2_NINT(u, q);
#endif
	*(*(ary + u.vtY) + u.vtX) += lut[*gP++];
	if(++(p0.vtX) > p1.vtX)
	{
	  break;
	}
      }
    }
    else
    {
      while(1)
      {
#ifdef WLZ_FAST_CODE
	u.vtX = ((v00 * p0.vtX) / 1024) + vMZXI;
	u.vtY = ((v01 * p0.vtX) / 1024) + vMZYI;
#else
	q.vtX = (vMat[0][0] * p0.vtX) + vMZX;
	q.vtY = (vMat[1][0] * p0.vtY) + vMZY;
	WLZ_VTX_2_NINT(u, q);
#endif
	*(*(ary + u.vtY) + u.vtX) += 255 - *gP++;
	if(++(p0.vtX) > p1.vtX)
	{
	  break;
	}
      }
    }
  }
  else
  {
    /* Need to use random access to the grey values since no grey pointer. */
    if(lut)
    {
      while(1)
      {
	WlzGreyValueGet(gVWSp, p0.vtZ, p0.vtY, p0.vtX);
#ifdef WLZ_FAST_CODE
	u.vtX = ((v00 * p0.vtX) / 1024) + vMZXI;
	u.vtY = ((v01 * p0.vtX) / 1024) + vMZYI;
#else
	q.vtX = (vMat[0][0] * p0.vtX) + vMZX;
	q.vtY = (vMat[1][0] * p0.vtY) + vMZY;
	WLZ_VTX_2_NINT(u, q);
#endif
	*(*(ary + u.vtY) + u.vtX) += lut[gVWSp->gVal[0].ubv];
	if(++(p0.vtX) > p1.vtX)
	{
	  break;
	}
      }
    }
    else
    {
      while(1)
      {
	WlzGreyValueGet(gVWSp, p0.vtZ, p0.vtY, p0.vtX);
#ifdef WLZ_FAST_CODE
	u.vtX = ((v00 * p0.vtX) / 1024) + vMZXI;
	u.vtY = ((v01 * p0.vtX) / 1024) + vMZYI;
#else
	q.vtX = (vMat[0][0] * p0.vtX) + vMZX;
	q.vtY = (vMat[1][0] * p0.vtY) + vMZY;
	WLZ_VTX_2_NINT(u, q);
#endif
	*(*(ary + u.vtY) + u.vtX) += 255 - gVWSp->gVal[0].ubv;
	if(++(p0.vtX) > p1.vtX)
	{
	  break;
	}
      }
    }
  }
}