Ejemplo n.º 1
0
/*! 
* \ingroup      WlzBinaryOps
* \brief        Segment a domain into connected parts. Connectivity
 is defined by the connect parameter and can be 4- or 8-connected for
 2D objects and 6-, 18- or 26-connected for 3D objects. Note this
 version requires that there is sufficient space in the objects array
 defined by maxNumObjs and this is not extended. This should be changed
 in future so that the array is extended as required.
*
* \return       Error number.
* \param    obj	input object to be segmented
* \param    mm	number of objects return
* \param    dstArrayObjs	object array return, allocated in the
 procedure.
* \param    maxNumObjs	maximum number of object to return (determines
 the size of the array)
* \param    ignlns	ignore objects with num lines <= ignlns
* \param    connect	connectivity to determine connected regions
* \par      Source:
*                WlzLabel.c
*/
WlzErrorNum WlzLabel(
  WlzObject	*obj,
  int		*mm,
  WlzObject	***dstArrayObjs,
  int		maxNumObjs,
  int		ignlns,
  WlzConnectType connect)
{ 
  WlzIntervalDomain 	*jdp;
  WlzRagRValues 	*jvp;
  WlzIntervalWSpace 	iwsp;
  WlzInterval 		*itvl;
  WlzInterval 		*jtvl;
  WlzLAllocBuf 		*crntal, *altemp;
  WlzLAllocBuf		*al, *crntst, *crlast;
  WlzLAllocBuf		*precal, *precst, *prlast;
  int			nints, mkl;
  int			maxinline,nob,line,ended,lend,chainlistsize;
  WlzLLink		*freechain, *alprec, *alloc, *link1, *link2;
  int			lftcrn, lftprc, rtcrn, rtprec;
  int			jrtcrn, mxkl, jl, jr;
  int			oll, ofl, jjj;
  WlzDomain		domain;
  WlzValues		values;
  int			jdqt;
  WlzErrorNum		errNum=WLZ_ERR_NONE;
  WlzObject		**objlist;

  /* see HISTORY for comments from the FORTRAN version */

  /* now we allocate space for the objects */
  if( (objlist = (WlzObject **)AlcMalloc(sizeof(WlzObject *) * maxNumObjs))
     == NULL ){
    errNum = WLZ_ERR_MEM_ALLOC;
  }
  else {
    *dstArrayObjs = objlist;
  }
  

  /* check object note *mm is always set to zero on error
     return because the "Too many objects" error can return
     nobj valid objects therefore if *mm != 0 there are valid objects
     in objlist which must be freed */
  if( obj == NULL ){
    *mm = 0;
    return WLZ_ERR_OBJECT_NULL;
  }

  /* check types */
  switch( obj->type ){

  case WLZ_2D_DOMAINOBJ:
    if( obj->domain.core == NULL ){
      *mm = 0;
      return WLZ_ERR_DOMAIN_NULL;
    }

    switch( obj->domain.core->type ){

    case WLZ_INTERVALDOMAIN_INTVL:
      break;

    case WLZ_INTERVALDOMAIN_RECT:
      if( (obj->domain.i->lastln - obj->domain.i->line1) < ignlns ){
	*mm = 0;
	return( WLZ_ERR_NONE );
      }

      if( maxNumObjs < 1 ){
	*mm = 0;
	return( WLZ_ERR_INT_DATA );
      }

      objlist[0] = WlzAssignObject(
	WlzMakeMain(obj->type, obj->domain,
		    obj->values, NULL, NULL, &errNum), NULL);
      *mm = 1;
      return WLZ_ERR_NONE;
      
    default:
      *mm = 0;
      return WLZ_ERR_DOMAIN_TYPE;

    }
    break;

  case WLZ_3D_DOMAINOBJ:
    if( obj->domain.core == NULL ){
      *mm = 0;
      return WLZ_ERR_DOMAIN_NULL;
    }

    return WlzLabel3d(obj, mm, objlist, maxNumObjs, ignlns, connect);

  case WLZ_EMPTY_OBJ:
    *mm = 0;
    return WLZ_ERR_NONE;

  case WLZ_TRANS_OBJ:
    /* should be able to do this quite easily */
  default:
    *mm = 0;
    return WLZ_ERR_OBJECT_TYPE;

  }

  /* check connectivity parameter */
  switch( connect ){

  default:
    return WLZ_ERR_INT_DATA;

  case WLZ_8_CONNECTED:
    jdqt = 0;
    break;

  case WLZ_4_CONNECTED:
    jdqt = 1;
    break;

  }
    
  /*
   * Allocate and initialise the working spaces.
   *
   * The chain store size is not easily predictable.
   * Here we use ((twice the number of lines) plus (one third the
   * number of intervals)), very much smaller than the
   * previous allocation, but apparently adequate to
   * segment both metaphase spreads and single connected objects.
   * In any case, this version of label can if necessary allocate
   * more space when the original chain store fills up.
   */
  chainlistsize = mintcount(obj->domain.i, &maxinline) / 3;
  chainlistsize += (1 + obj->domain.i->lastln - obj->domain.i->line1)*2;
  if( (freechain = chainalloc(0,chainlistsize)) == NULL ){
    *mm = 0;
    return WLZ_ERR_MEM_ALLOC;
  }
  buckle(freechain, freechain, chainlistsize);
  /*
   * The allocation list size is determined as twice
   * (1 + maximum number of intervals in a line of input object).
   */
  if( (al = (WlzLAllocBuf *)
       AlcCalloc(2 * (maxinline+1), sizeof(WlzLAllocBuf))) == NULL ){
    chainFree();
    *mm = 0;
    return WLZ_ERR_MEM_ALLOC;
  }
  jvp = obj->values.v;

  /* initialise interval scanning */
  WlzInitRasterScan (obj, &iwsp, WLZ_RASTERDIR_ILIC);
  line = iwsp.linpos;
  ended = 0 ;
  lend = 0 ;
  WlzNextInterval(&iwsp);
  crntst = al + 1 + maxinline;
  nob = 0 ;
  prlast = al ;
  precst = al + 1 ;

  /* commence new line */
  while (!ended) {
    crntal = crntst-1 ;

    line++;
    if (lend) { 
      ended = 1 ;
      lend = 0 ;
    }
    else {
      /* read the intervals into the allocation buffer */
      while (iwsp.linpos <= line) {
	crntal++;
	crntal->a_int.ileft = iwsp.lftpos;
	crntal->a_int.iright = iwsp.rgtpos;
	if (WlzNextInterval(&iwsp) != 0) {
	  lend = 1 ;
	  break ;
	}
      }
    }
    crlast = crntal ;
    crntal = crntst ;
    precal = precst ;
    alloc = NULL ;

    /* test whether last interval in current line dealt with */
    while (crntal <= crlast) {
      lftcrn = crntal->a_int.ileft ;
      jrtcrn = crntal->a_int.iright ;
      rtcrn = jrtcrn+2 ;
      alprec = precal->a_link;
      lftprc = precal->a_int.ileft ;
      rtprec = precal->a_int.iright +2 ;

      /* test whether last interval in preceeding line dealt with */
      if (precal > prlast || rtcrn <= lftprc + jdqt) { 
	/* is interval in current line already allocated */
	if (!alloc) { 
	  /* start a new object and allocate this interval to it */
	  /* interval list */
	  link1 = newchain2(freechain,lftcrn,jrtcrn);
	  /* line-of-intervals list */
	  link2 = newchain1(freechain, (unsigned long) link1);
	  /* "object" -- first line, last line, line-of-intervals pointer */
	  crntal->a_link  = newchain1(freechain,line) ;
	  crntal->a_link = addlink1 (freechain, crntal->a_link, (unsigned long)line);
	  crntal->a_link = addlink1 (freechain, crntal->a_link, (unsigned long) link2);
	}
	/* move on to next interval in current line */
	crntal++ ;
	alloc = NULL;
      }
      else {
	if (rtprec > lftcrn+ (int )jdqt) { 
	  /* case of overlapping intervals: */
	  /* is intvl in current line already allocated ? */
	  if (!alloc) { 
	    /* allocate this interval and add to object list */
	    alloc = alprec ;
	    link1 = alloc->l_link ;
	    crntal->a_link = alloc ;
	    /* test whether this line has already been started for this object */
	    if (link1->l_u.line != line) {
	      /* update last line */
	      link1->l_u.line = line;
	      /* add a link to the line list for this line */
	      link1 = newchain2(freechain,lftcrn,jrtcrn);
	      alloc->l_u.u_link = addlink1 (freechain, alloc->l_u.u_link, (unsigned long) link1);
	    }
	    else {
	      /* add interval to interval list for last line */
	      link1 = alloc->l_u.u_link;
	      link1->l_u.u_link = addlink2 (freechain, link1->l_u.u_link, lftcrn, jrtcrn);
	    }
	  }
	  else {
	    /* merge lists and reallocate intervals */
	    /* test whether both already allocated to same object */
	    if (alprec != alloc) { 
	      merge (&alprec, &alloc, freechain);
	      /* reallocate intervals in preceding line */
	      for (altemp = precst; altemp <= prlast; altemp++)	{
		if (altemp->a_link == alloc) { 
		  altemp->a_link = alprec ;	
		}	
	      }
	      /* reallocate intervals in current line */
	      for (altemp = crntst; altemp <= crntal; altemp++)	{
		if (altemp->a_link == alloc) { 
		  altemp->a_link = alprec ;	
		}	
	      }
	      alloc = alprec ;
	    }
	  }
	  if (rtcrn < rtprec) { 
	    /* move to next interval in this line */
	    crntal++;
	    alloc = NULL ;
	    continue;	/* the outer while loop */
	  }
	}
	/* move on to next interval in preceding line */
	precal++ ;
      }
    }

    /* all intervals in current line dealt with: */
    /* find and construct any finished objects */
    if (precst <= prlast) { 
      for (precal = precst; precal <= prlast; precal++) {
	alprec = precal->a_link ;
	/* has the object to which this interval was allocated been dealt with */
	if (alprec) { 
	  /* remove any later intervals allocated to the same object */
	  for (altemp = precal; altemp <= prlast; altemp++) {
	    if (altemp->a_link == alprec) { 
	      altemp->a_link  = NULL ;	
	    }	
	  }
	  /* test if this object has intervals in the current line */
	  /* and if so skip to end of outer loop */
	  if (crntst <= crlast) { 
	    for (altemp = crntst; altemp <= crlast; altemp++)	{
	      if (altemp->a_link == alprec)
		goto loopend;
	    }
	  }
	  /* construct object - first find line and column bounds */
	  link1 = alprec->l_link;
	  oll = (int) link1->l_u.line;
	  link1 = link1->l_link;
	  ofl = (int) link1->l_u.line;
	  link1 = alprec->l_u.u_link;
	  mkl = 0; /* Just to keep lint happy. */
	  mxkl = 0; /* Just to keep lint happy. */
	  nints = 0;
	  for (jjj=ofl; jjj<=oll; jjj++) {
	    link1 = link1->l_link;
	    link2 = link1->l_u.u_link;
	    do {
	      link2 = link2->l_link;
	      jl = link2->l_u.intv.ileft;
	      jr = link2->l_u.intv.iright;
	      if (nints == 0 || jl < mkl)
		mkl = jl ;	
	      if (nints == 0 || jr > mxkl)
		mxkl = jr ;	
	      nints++;
	      /* test for end of line */
	    } 
	    while (link2 != link1->l_u.u_link);
	  }
	  /* test whether object large enough, if not ignore it */
	  /* test for height or width less than threshold */
	  if (oll-ofl < ignlns || mxkl-mkl < ignlns) {
	    for (jjj = ofl; jjj <= oll; jjj++)	{
	      link1 = link1->l_link;
	      link2 = link1->l_u.u_link;
	      /* recover chain space */
	      join (freechain, link2) ;
	    }
	  }
	  else {

	    /* test for object array overflow */
	    if (nob >= maxNumObjs) {
	      AlcFree((void *) al);
	      chainFree();
	      *mm = nob;
	      return(WLZ_ERR_INT_DATA);
	    }
	    link1 = alprec->l_u.u_link;
	    /* set up domain and object, and update counts
	       need to test successful space allocation here */
	    jdp = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_INTVL,
					ofl,oll,mkl,mxkl, &errNum);
	    domain.i = jdp;
	    values.v = jvp;
	    *objlist = WlzAssignObject(
	      WlzMakeMain(WLZ_2D_DOMAINOBJ,
			  domain,values,NULL,obj,&errNum), NULL);
	    objlist++;
	    nob++;
	    /* get the size correct here !!! */
	    itvl = (WlzInterval *) AlcMalloc (nints * sizeof(WlzInterval));
	    jdp->freeptr = AlcFreeStackPush(jdp->freeptr, (void *)itvl, NULL);
	    /* write intervals and interval pointers lists */
	    for (jjj=ofl; jjj<=oll; jjj++) {
	      jtvl = itvl;
	      nints = 0;
	      link1 = link1->l_link;
	      link2 = link1->l_u.u_link;
	      do {
		/*
		 * the following increment since the interval
		 * list is circular, monotone increasing,
		 * but link2 originally points at the
		 * rightmost interval (see comment at top).
		 */
		link2 = link2->l_link;
		itvl->ileft = link2->l_u.intv.ileft - mkl;
		itvl->iright = link2->l_u.intv.iright - mkl;
		itvl++;
		nints++;
		/* test for end of line */
	      } 
	      while (link2 != link1->l_u.u_link);
	      WlzMakeInterval(jjj,jdp,nints,jtvl);
	      join (freechain, link2) ;
	    }
	  }
	  /* return line list etc to free-list store */
	  join (freechain, alprec->l_u.u_link);
	  join (freechain, alprec) ;
	}
      loopend:			 
	;
      }
    }

    /* update pointers - swap the two halves of the allocation list */
    /* before getting the intervals in the next line */
    altemp = crntst ;
    crntst = precst ;
    precst = altemp ;
    prlast = crlast ;
  }

  *mm = nob ;
  AlcFree((void *) al);
  chainFree();

  return WLZ_ERR_NONE;
} 
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
void warpSetSignalDomain(
  WlzIVertex2	*selVtx)
{
  WlzErrorNum	errNum=WLZ_ERR_NONE;
  WlzPixelV	threshV, threshV1;
  WlzObject	*obj, *obj1;
  WlzUInt	combineMode;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  if( errNum != WLZ_ERR_NONE ){
    MAPaintReportWlzError(globals.topl, "warpSetSignalDomain", errNum);
  }
  return;
}
Ejemplo n.º 4
0
/*!
* \return	Object with domain equal to the set difference between the
*		first and second object, with valuetable from the first
*		object.
* \ingroup	WlzDomainOps
* \brief	Calculates the domain difference between two objects.
* \param	obj1			First object.
* \param	obj2			Second object.
* \param	dstErr			Destination error pointer, may be NULL.
*/
WlzObject *WlzDiffDomain(
  WlzObject *obj1,
  WlzObject *obj2,
  WlzErrorNum	*dstErr)
{
  WlzIntervalWSpace	iwsp2, iwsp1;
  WlzInterval		*intp;
  WlzInterval 		*jntp;
  WlzDomain 		diffdom;
  WlzValues		values;
  WlzIntervalDomain 	*idom1;
  int 			k1, dfinished, intervalcount;
  WlzObject 		*diff=NULL;
  WlzErrorNum		errNum=WLZ_ERR_NONE;

  diffdom.core = NULL;
  /* check object 1 */
  if( obj1 == NULL ){
    errNum = WLZ_ERR_OBJECT_NULL;
  }

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

    case WLZ_2D_DOMAINOBJ:
    case WLZ_3D_DOMAINOBJ:
      if( obj1->domain.core == NULL ){
	errNum = WLZ_ERR_DOMAIN_NULL;
      }
      break;

    case WLZ_EMPTY_OBJ:
      diffdom.i = NULL;
      values.v = NULL;
      return WlzMakeMain(WLZ_EMPTY_OBJ, diffdom, values, NULL,
			 NULL, dstErr);

    default:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;

    }
  }

  /* check object 2 - obj2 == NULL is now an error */
  if( (errNum == WLZ_ERR_NONE) && (obj2 == NULL) ){
    errNum = WLZ_ERR_OBJECT_NULL;
  }

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

    case WLZ_2D_DOMAINOBJ:
    case WLZ_3D_DOMAINOBJ:
      if( obj2->type != obj1->type ){
	errNum = WLZ_ERR_OBJECT_TYPE;
	break;
      }
      if( obj2->domain.core == NULL ){
	errNum = WLZ_ERR_OBJECT_NULL;
	break;
      }
      break;

    case WLZ_EMPTY_OBJ:
      return WlzMakeMain(obj1->type, obj1->domain, obj1->values,
			 NULL, NULL, dstErr);

    default:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;

    }
  }

  /* switch for 3D objects */
  if( (errNum == WLZ_ERR_NONE) && (obj1->type == WLZ_3D_DOMAINOBJ) ){
    return WlzDiffDomain3d( obj1, obj2, dstErr );
  }

  /*
   * make a new interval table that is big enough
   */
  if( errNum == WLZ_ERR_NONE ){
    idom1 = obj1->domain.i;
    k1 = idom1->kol1;
    if( (intp = (WlzInterval *)
	 AlcCalloc(WlzIntervalCount(idom1, NULL) +
		   WlzIntervalCount(obj2->domain.i, NULL),
		   sizeof(WlzInterval))) == NULL ){
      errNum = WLZ_ERR_MEM_ALLOC;
    }
    jntp = intp;
  }

  if( errNum == WLZ_ERR_NONE ){
    if( (diffdom.i = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_INTVL,
					   idom1->line1, idom1->lastln,
					   k1, idom1->lastkl,
					   &errNum)) == NULL ){
      AlcFree((void *) intp);
    }
    else {
      diffdom.i->freeptr = AlcFreeStackPush(diffdom.i->freeptr, (void *)intp,
					    NULL);
    }
  }

  if( errNum == WLZ_ERR_NONE ){
    if( (diff = WlzMakeMain(WLZ_2D_DOMAINOBJ, diffdom, obj1->values,
			    NULL, NULL, &errNum)) == NULL ){
      WlzFreeIntervalDomain(diffdom.i);
    }
  }

  /*
   * initialise interval scanning
   */
  if( errNum == WLZ_ERR_NONE ){
    errNum = WlzInitRasterScan(obj1, &iwsp1, WLZ_RASTERDIR_ILIC);
  }
  if( errNum == WLZ_ERR_NONE ){
    errNum = WlzInitRasterScan(obj2, &iwsp2, WLZ_RASTERDIR_ILIC);
    dfinished = 0;
    intervalcount = 0;
  }

  /*
   * scan object constructing intervals after subtraction of obj2
   */
  if( (errNum == WLZ_ERR_NONE) &&
     ((errNum = WlzNextInterval(&iwsp2)) == WLZ_ERR_NONE) ){

    while( (errNum = WlzNextInterval(&iwsp1)) == WLZ_ERR_NONE ){
      /*
       * case 1 - interval in obj1 succedes interval in obj2 -
       *	    get next interval of obj2
       */
      while( (errNum == WLZ_ERR_NONE) && (dfinished == 0) &&
	     (iwsp1.linpos > iwsp2.linpos ||
	      (iwsp1.linpos == iwsp2.linpos &&
	       iwsp1.lftpos > iwsp2.rgtpos))){
	switch( errNum = WlzNextInterval(&iwsp2) ){
	case WLZ_ERR_NONE:
	  dfinished = 0;
	  break;
	case WLZ_ERR_EOO:
	  errNum = WLZ_ERR_NONE;
	  dfinished = 1;
	  break;
	default:
	  break;
	}
      }
      if( errNum != WLZ_ERR_NONE ){
	break;
      }
      /*
     * case 2 - interval in obj1 precedes interval in obj2
     *	    or obj2 finished - just copy interval
     */
      if( (dfinished != 0) ||
	 (iwsp1.linpos < iwsp2.linpos ||
	  ((iwsp1.linpos == iwsp2.linpos) &&
	   (iwsp1.rgtpos < iwsp2.lftpos))
	   )
	){
	jntp->ileft = iwsp1.lftpos - k1;
	jntp->iright = iwsp1.rgtpos - k1;
	intervalcount++;
	jntp++;
      }
      /*
     * case 3 - intervals overlap.
     * there may be more than one obj2 interval.
     */
      else {
	/*
	 * test left end of obj1 interval < left
	 * end of obj2 interval, when complete
	 * interval can be constructed immediately
	 */
	if (iwsp2.lftpos > iwsp1.lftpos) {
	  jntp->ileft = iwsp1.lftpos - k1;
	  jntp->iright = iwsp2.lftpos -1 - k1;
	  intervalcount++;
	  jntp++;
	}
	do {
	  /*
	   * if right end of obj2 interval <
	   * right end of obj1 interval can
	   * plant left end of new interval
	   */
	  if (iwsp2.rgtpos < iwsp1.rgtpos) {
	    jntp->ileft = iwsp2.rgtpos +1 - k1;
	    switch( errNum = WlzNextInterval(&iwsp2) ){
	    case WLZ_ERR_NONE:
	      dfinished = 0;
	      break;
	    case WLZ_ERR_EOO:
	      errNum = WLZ_ERR_NONE;
	      dfinished = 1;
	      break;
	    default:
	      break;
	    }
	    if( errNum != WLZ_ERR_NONE ){
	      break;
	    }
	    
	    /*
	     * check if next obj2 interval
	     * still overlaps this obj1 interval
	     */
	    if( (dfinished == 0) &&
	       (iwsp1.linpos == iwsp2.linpos) &&
	       (iwsp1.rgtpos >= iwsp2.lftpos))
	      jntp->iright = iwsp2.lftpos -1 -k1;
	    else
	      jntp->iright = iwsp1.rgtpos - k1;
	    intervalcount++;
	    jntp++;
	  }
	} while( (dfinished == 0) && 
		(iwsp1.linpos == iwsp2.linpos) &&
		(iwsp1.rgtpos > iwsp2.rgtpos) );
      }
      if( errNum != WLZ_ERR_NONE ){
	break;
      }

      /*
     * is this obj1 interval the last in the line ?
     * if so, load up the new intervals into the
     * diff domain.
     */
      if (iwsp1.intrmn == 0) {
	errNum = WlzMakeInterval(iwsp1.linpos, diffdom.i,
				 intervalcount, intp);
	intervalcount = 0;
	intp = jntp;
      }
      if( errNum != WLZ_ERR_NONE ){
	break;
      }
    }
  }
  if(errNum == WLZ_ERR_EOO) 	        /* Reset error from end of intervals */ 
  {
    errNum = WLZ_ERR_NONE;
  }

  /* this checks the area and returns NULL if zero
     in principle it should return an "empty object" */
  if(errNum == WLZ_ERR_NONE) {
    if(WlzIntervalCount(diffdom.i, NULL) == 0){
      WlzFreeObj(diff);
      diffdom.i = NULL;
      values.v = NULL;
      diff = WlzMakeEmpty(&errNum);
    }
    else {
      WlzStandardIntervalDomain(diff->domain.i);
    }
  }
  else {
    WlzFreeObj(diff);
    diff = NULL;
  }

  if( dstErr ){
    *dstErr = errNum;
  }
  return diff;
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
0
/*!
* \return	New Woolz object.
* \ingroup	WlzAllocation
* \brief	Creates a new 2D spatial domain object by adding a
* 		rectangular buffer of values to the given current
* 		object (which may be NULL or empty).
* \param	cObj			Given current object.
* \param	og			Origin of rectangular buffer.
* \param	sz			Buffer size.
* \param	gType			Grey type which must be consistent
* 					with the current object and the
* 					buffer of values.
* \param	bufSz			Number of values in the buffer.
* \param	bufP			Given buffer of values.
* \param	dstErr			Destination error pointer, may be NULL.
*/
static WlzObject *WlzBuildObj2(WlzObject *cObj,
                               WlzIVertex2 og, WlzIVertex2 sz,
                               WlzGreyType gType, int bufSz, WlzGreyP bufP,
                               WlzErrorNum *dstErr)
{
    WlzDomain	bDom;
    WlzValues	bVal,
                nVal;
    WlzObject	*bObj = NULL,
                 *nObj = NULL;
    WlzPixelV	bgdV;
    WlzErrorNum	errNum = WLZ_ERR_NONE;

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

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

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

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

                /* Copy existing values to new object. */
                tObj = WlzGreyTransfer(nObj, cObj, &errNum);
                (void )WlzFreeObj(nObj);
                nObj = tObj;
                /* Then copy buffer values to new object. */
                if(errNum == WLZ_ERR_NONE)
                {
                    tObj = WlzGreyTransfer(nObj, bObj, &errNum);
                    (void )WlzFreeObj(nObj);
                    nObj = tObj;
                }
            }
        }
    }
    (void )WlzFreeObj(bObj);
    if(dstErr)
    {
        *dstErr = errNum;
    }
    return(nObj);
}
Ejemplo n.º 7
0
/*!
* \return	New Woolz interval domain or NULL on error.
* \ingroup	WlzTransform
* \brief	Creates a new 2D Woolz interval domain with a single line
* 		which is the profile from the given start position to the
* 		given end position for the given spatial domain object.
* \param	gObj		Given Woolz object.
* \param	sPos		Start position.
* \param	ePos		End position.
* \param	dstErr		Destination error pointer, may be NULL.
*/
WlzIntervalDomain *WlzProfileLineIDom(
  WlzObject *gObj,
  WlzIVertex3 sPos,
  WlzIVertex3 ePos,
  WlzErrorNum *dstErr)
{
  WlzIntervalDomain *iDom = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  /* Check given object. */
  if(gObj == NULL)
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else
  {
    switch(gObj->type)
    {
      case WLZ_2D_DOMAINOBJ:
      case WLZ_3D_DOMAINOBJ:
	if(gObj->domain.core == NULL)
	{
	  errNum = WLZ_ERR_DOMAIN_NULL;
	}
        break;
      default:
	errNum = WLZ_ERR_OBJECT_TYPE;
        break;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    int		len;
    WlzIVertex3	dPos;
    WlzProfileWalkWSp pWSp = {0};
    WlzInterval *rItv = NULL;

    WLZ_VTX_3_SUB(dPos, ePos, sPos);
    len = (int )ceil(WLZ_VTX_3_LENGTH(dPos));
    /* Create return object. */
    iDom = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_INTVL,
                                 0, 0, 0, len - 1, &errNum);
    if(errNum == WLZ_ERR_NONE)
    {
      if((rItv = (WlzInterval *)
		 AlcCalloc((len / 2) + 1, sizeof(WlzInterval))) == NULL)
      {
	errNum = WLZ_ERR_MEM_ALLOC;
	(void )WlzFreeIntervalDomain(iDom);
	iDom = NULL;
      }
    }
    if(errNum == WLZ_ERR_NONE)
    {
      WlzIntervalLine *itvLn;

      iDom->freeptr = AlcFreeStackPush(iDom->freeptr, (void *)rItv, NULL);
      pWSp.start = sPos;
      pWSp.end = ePos;
      pWSp.domain.i = iDom;
      itvLn = pWSp.domain.i->intvlines + 0;
      itvLn->intvs = rItv;
      itvLn->nintvs = 0;
      errNum = WlzProfileWalk(gObj, WlzProfileSetIDom, &pWSp);
    }
  }
  if(errNum != WLZ_ERR_NONE)
  {
    iDom = NULL;
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(iDom);
}
Ejemplo n.º 8
0
/*! 
* \ingroup      WlzBinaryOps
* \brief        Calculate the set union of an array of domain objects.
 Domians only unless uvt non-zero in which case make an average grey
 table. Note background values are used in the averaging process. All
 objects must be domain objects of the same type (2D or 3D) unless
 WLZ_EMPTY_OBJ, NULL input objects are an error.

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

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

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

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

    case WLZ_2D_DOMAINOBJ:
      break;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	default:
	  break;

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

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

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

  tmpVal.core = NULL;
  pool.itvBlock = NULL;
  dstDom.core = NULL;
  if((grdM->type != WLZ_2D_DOMAINOBJ) ||
     (grdY->type != WLZ_2D_DOMAINOBJ) ||
     (grdX->type != WLZ_2D_DOMAINOBJ))
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if((grdM->domain.core == NULL) ||
          (grdY->domain.core == NULL) ||
          (grdX->domain.core == NULL))
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if((grdM->values.core == NULL) ||
  	  (grdY->values.core == NULL) ||
	  (grdX->values.core == NULL))
  {
    errNum = WLZ_ERR_VALUES_NULL;
  }
  else
  {
    /* Find required buffer type (WLZ_GREY_DOUBLE or WLZ_GREY_INT). */
    bufType = WLZ_GREY_INT;
    gType = WlzGreyTableTypeToGreyType(grdM->values.core->type, &errNum);
    if(errNum == WLZ_ERR_NONE)
    {
      if((gType == WLZ_GREY_FLOAT) || (gType == WLZ_GREY_DOUBLE))
      {
	bufType = WLZ_GREY_DOUBLE;
      }
      else
      {
	gType = WlzGreyTableTypeToGreyType(grdY->values.core->type, &errNum);
	if(errNum == WLZ_ERR_NONE)
	{
	  if((gType == WLZ_GREY_FLOAT) || (gType == WLZ_GREY_DOUBLE))
	  {
	    bufType = WLZ_GREY_DOUBLE;
	  }
	  else
	  {
	    gType = WlzGreyTableTypeToGreyType(grdX->values.core->type,
	    				       &errNum);
	    if(errNum == WLZ_ERR_NONE)
	    {
	      if((gType == WLZ_GREY_FLOAT) || (gType == WLZ_GREY_DOUBLE))
	      {
		bufType = WLZ_GREY_DOUBLE;
	      }
	    }
	  }
	}
      }
    }
  }
  /* Convert minimum gradient threshold value. */
  if(errNum == WLZ_ERR_NONE)
  {
    if(bufType == WLZ_GREY_INT)
    {
      errNum = WlzValueConvertPixel(&minThrV, minThrV, WLZ_GREY_INT);
    }
    else /* bufType == WLZ_GREY_DOUBLE */
    {
      errNum = WlzValueConvertPixel(&minThrV, minThrV, WLZ_GREY_DOUBLE);
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    grdDom = grdM->domain;
    /* Make destination object with WLZ_GREY_UBYTE greys. */
    zeroV.type = WLZ_GREY_UBYTE;
    zeroV.v.inv = 0;
    tmpVal.v = WlzNewValueTb(grdM, WlzGreyTableType(WLZ_GREY_TAB_RAGR,
						    WLZ_GREY_UBYTE, NULL),
			     zeroV, &errNum);
    if(errNum == WLZ_ERR_NONE)
    {
      /* Use the input domain while calculating the new maximal domain. */
      tmpObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, grdM->domain, tmpVal,
			   NULL, NULL, &errNum);
    }
  }
  /* Initialize the memory pool with some size of block. Any +ve number
   * greater than the maximum number of intervals in any destination line
   * would work but the fewer allocations then the more efficient the code,
   * hence this attempt to guess the required number of intervals in the
   * destination domain. */
  if(errNum == WLZ_ERR_NONE)
  {
    pool.itvsInBlock = (((grdDom.i->lastkl - grdDom.i->kol1 + 1) *
			(grdDom.i->lastln - grdDom.i->line1 + 1)) / 64) +
		       grdDom.i->lastkl - grdDom.i->kol1 + 1024;
  }
  /* Make gradient buffers. */
  if(errNum == WLZ_ERR_NONE)
  {
    bufSz.vtY = 3;
    bufSz.vtX = grdDom.i->lastkl - grdDom.i->kol1 + 1;
    if(bufType == WLZ_GREY_INT)
    {
      if((AlcInt2Malloc((int ***)&grdMBuf,
			bufSz.vtY, bufSz.vtX) != ALC_ER_NONE) ||
	 ((grdYBuf = AlcMalloc(sizeof(int) * bufSz.vtX)) == NULL) ||
	 ((grdXBuf = AlcMalloc(sizeof(int) * bufSz.vtX)) == NULL))
      {
	errNum = WLZ_ERR_MEM_ALLOC;
      }
      else
      {
	grdYBufGP.inp = (int *)grdYBuf;
	grdXBufGP.inp = (int *)grdXBuf;
      }
    }
    else /* bufType == WLZ_GREY_DOUBLE */
    {
      if((AlcDouble2Malloc((double ***)&grdMBuf,
			   bufSz.vtY, bufSz.vtX) != ALC_ER_NONE) ||
	 ((grdYBuf = AlcMalloc(sizeof(double) * bufSz.vtX)) == NULL) ||
	 ((grdXBuf = AlcMalloc(sizeof(double) * bufSz.vtX)) == NULL))
      {
	errNum = WLZ_ERR_MEM_ALLOC;
      }
      else
      {
	grdYBufGP.dbp = (double *)grdYBuf;
	grdXBufGP.dbp = (double *)grdXBuf;
      }
    }
  }
  /* Make destination interval domain with interval lines but not intervals. */
  if(errNum == WLZ_ERR_NONE)
  {
    dstDom.i = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_INTVL,
    				     grdDom.i->line1, grdDom.i->lastln,
				     grdDom.i->kol1, grdDom.i->lastkl,
				     &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    /* Scan down through the gradient objects. */
    if(((errNum = WlzInitGreyScan(tmpObj,
    				  &tmpIWSp, &tmpGWSp)) == WLZ_ERR_NONE) &&
       ((errNum = WlzInitGreyScan(grdM,
    				  &grdMIWSp, &grdMGWSp)) == WLZ_ERR_NONE) &&
       ((errNum = WlzInitGreyScan(grdY,
    				  &grdYIWSp, &grdYGWSp)) == WLZ_ERR_NONE) &&
       ((errNum = WlzInitGreyScan(grdX,
    				  &grdXIWSp, &grdXGWSp)) == WLZ_ERR_NONE))
    {
      orgPos.vtX = grdDom.i->kol1;
      orgPos.vtY = grdDom.i->line1;
      while((errNum == WLZ_ERR_NONE) &&
            ((errNum = WlzNextGreyInterval(&grdMIWSp)) == WLZ_ERR_NONE))
      {
        inLen = grdMIWSp.rgtpos - grdMIWSp.lftpos + 1;
	inPos.vtX = grdMIWSp.lftpos - orgPos.vtX;
	/* Process any lines between this and the last by clearing the
	 * gradient magnitude buffer . */
	if(grdMIWSp.nwlpos > 0)
	{
	  idN = (grdMIWSp.nwlpos >= 3)? 3: grdMIWSp.nwlpos;
	  while(--idN >= 0)
	  {
	    inPos.vtY = grdMIWSp.linpos - orgPos.vtY - idN;
	    inLnIdx = (3 + inPos.vtY) % 3;
	    if(bufType == WLZ_GREY_INT)
	    {
	      WlzValueSetInt(*((int **)grdMBuf + inLnIdx), 0,
	      		     bufSz.vtX);
	    }
	    else /* bufType == WLZ_GREY_DOUBLE */
	    {
	      WlzValueSetDouble(*((double **)grdMBuf + inLnIdx), 0,
	      			bufSz.vtX);
	    }
	  }
	}
	/* Copy intervals to values buffers. */
	if(bufType == WLZ_GREY_INT)
	{
	  grdMBufGP.inp = *((int **)grdMBuf + inLnIdx);
	}
	else /* bufType == WLZ_GREY_DOUBLE */
	{
	  grdMBufGP.dbp = *((double **)grdMBuf + inLnIdx);
	}
	WlzValueCopyGreyToGrey(grdMBufGP, inPos.vtX, bufType,
			       grdMGWSp.u_grintptr, 0, grdMGWSp.pixeltype,
			       inLen);
	if(grdMIWSp.intrmn == 0)
	{
	  while((errNum == WLZ_ERR_NONE) &&
	        (tmpIWSp.linpos < grdMIWSp.linpos))
	  {
	    outPos.vtY = tmpIWSp.linpos - orgPos.vtY;
	    if(outPos.vtY >= 0)
	    {
	      outLen = tmpIWSp.rgtpos - tmpIWSp.lftpos + 1;
	      outPos.vtX = tmpIWSp.lftpos - orgPos.vtX;
	      WlzValueCopyGreyToGrey(grdYBufGP, 0, bufType,
				     grdYGWSp.u_grintptr, 0,
				     grdYGWSp.pixeltype, outLen);
	      WlzValueCopyGreyToGrey(grdXBufGP, 0, bufType,
				     grdXGWSp.u_grintptr, 0,
				     grdXGWSp.pixeltype, outLen);
	      if(bufType == WLZ_GREY_INT)
	      {
		errNum = WlzNMSuppress2DBufI(dstDom.i,
					     (int **)grdMBuf,
					     (int *)grdYBuf,
					     (int *)grdXBuf,
					     &pool,
					     tmpGWSp.u_grintptr.ubp,
					     outLen, outPos, orgPos,
					     minThrV.v.inv);
	      }
	      else /* bufType == WLZ_GREY_DOUBLE */
	      {
		errNum = WlzNMSuppress2DBufD(dstDom.i,
				    	     (double **)grdMBuf,
				    	     (double *)grdYBuf,
					     (double *)grdXBuf,
					     &pool,
					     tmpGWSp.u_grintptr.ubp,
					     outLen, outPos, orgPos,
					     minThrV.v.dbv);
	      }
	    }
	    if(errNum == WLZ_ERR_NONE)
	    {
	      errNum = WlzNextGreyInterval(&tmpIWSp);
	    }
	    if(errNum == WLZ_ERR_NONE)
	    {
	      errNum = WlzNextGreyInterval(&grdYIWSp);
	    }
	    if(errNum == WLZ_ERR_NONE)
	    {
	      errNum = WlzNextGreyInterval(&grdXIWSp);
	    }
	  }
        }
      }
      if(errNum == WLZ_ERR_EOO)
      {
        errNum = WLZ_ERR_NONE;
      }
    }
    if(tmpIWSp.gryptr == &tmpGWSp)
    {
      (void )WlzEndGreyScan(&tmpIWSp, &tmpGWSp);
    }
    if(grdMIWSp.gryptr == &grdMGWSp)
    {
      (void )WlzEndGreyScan(&grdMIWSp, &grdMGWSp);
    }
    if(grdYIWSp.gryptr == &grdYGWSp)
    {
      (void )WlzEndGreyScan(&grdYIWSp, &grdYGWSp);
    }
    if(grdXIWSp.gryptr == &grdXGWSp)
    {
      (void )WlzEndGreyScan(&grdXIWSp, &grdXGWSp);
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if((errNum = WlzStandardIntervalDomain(dstDom.i)) == WLZ_ERR_NONE)
    {
      dstObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, dstDom, tmpVal,
			   NULL, NULL, &errNum);
    }
  }
  if(tmpObj)
  {
    WlzFreeObj(tmpObj);
  }
  if(errNum != WLZ_ERR_NONE)
  {
    if(tmpObj == NULL)
    {
      if(dstDom.core)
      {
        (void )WlzFreeDomain(dstDom);
      }
      if(tmpVal.core)
      {
        (void )WlzFreeValues(tmpVal);
      }
    }
  }
  if(grdMBuf)
  {
    Alc2Free(grdMBuf);
  }
  if(grdYBuf)
  {
    AlcFree(grdYBuf);
  }
  if(grdXBuf)
  {
    AlcFree(grdXBuf);
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(dstObj);
}
Ejemplo n.º 10
0
WlzObject *WlzCbThreshold(
  WlzObject	*obj,
  WlzThreshCbFn	threshCb,
  void		*clientData,
  WlzErrorNum	*dstErr)
{
  WlzObject		*nobj=NULL;
  WlzIntervalDomain	*idom = NULL;
  WlzGreyP		g;
  WlzThreshCbStr	callData;
  int			colno, nints;
  int			over;
  int			nl1,nll,nk1,nkl;
  WlzIntervalWSpace	iwsp;
  WlzGreyWSpace		gwsp;
  WlzInterval		*itvl = NULL, *jtvl = NULL;
  WlzDomain		domain;
  WlzValues		values;
  WlzErrorNum		errNum=WLZ_ERR_NONE;

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

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

    case WLZ_3D_DOMAINOBJ:
      return WlzCbThreshold3d(obj, threshCb, clientData, dstErr);

    case WLZ_TRANS_OBJ:
      if((nobj = WlzCbThreshold(obj->values.obj, threshCb, clientData,
				&errNum)) != NULL){
	values.obj = nobj;
	return WlzMakeMain(obj->type, obj->domain, values,
			   NULL, obj, dstErr);
      }
      break;

    case WLZ_EMPTY_OBJ:
      return WlzMakeEmpty(dstErr);

    default:
      errNum = WLZ_ERR_OBJECT_TYPE;
    }
  }

  /*
   * first pass - find line and column bounds of thresholded
   * object and number of intervals.
   */
  if( errNum == WLZ_ERR_NONE ){
    idom = obj->domain.i;
    nl1 = idom->lastln;
    nll = idom->line1;
    nk1 = idom->lastkl;
    nkl = idom->kol1;
    callData.pix.type = gwsp.pixeltype;
    (void) WlzInitGreyScan(obj, &iwsp, &gwsp);
  }
  if( errNum == WLZ_ERR_NONE ){
    nints = 0;
    while( (errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE ){
      callData.pos.vtY = iwsp.linpos;
      g = gwsp.u_grintptr;
      over = 0;

      for (colno = iwsp.lftpos; colno <= iwsp.rgtpos; colno++) {
	callData.pix.p = g;
	callData.pos.vtX = colno;
	if((*threshCb)(obj, clientData, &callData) ){
	  if (over == 0) {
	    over = 1;
	    if (iwsp.linpos < nl1)
	      nl1 = iwsp.linpos;
	    if (iwsp.linpos > nll)
	      nll = iwsp.linpos;
	    if (colno < nk1)
	      nk1 = colno;
	  }
	} else {
	  if (over == 1) {
	    if (colno > nkl)
	      nkl = colno;
	    over = 0;
	    nints++;
	  }
	}

	switch( gwsp.pixeltype ){
	case WLZ_GREY_INT:
	  g.inp++;
	  break;
	case WLZ_GREY_SHORT:
	  g.shp++;
	  break;
	case WLZ_GREY_UBYTE:
	  g.ubp++;
	  break;
	case WLZ_GREY_FLOAT:
	  g.flp++;
	  break;
	case WLZ_GREY_DOUBLE:
	  g.dbp++;
	  break;
	case WLZ_GREY_RGBA:
	  g.rgbp++;
	  break;
	default:
	  break;
	}
      }

      if (over == 1) {
	if (colno > nkl)
	  nkl = colno;
	over = 0;
	nints++;
      }
    }
    nkl--;	/* since we have looked at points beyond interval ends */
    (void )WlzEndGreyScan(&iwsp, &gwsp);
    if( errNum == WLZ_ERR_EOO ){
      errNum = WLZ_ERR_NONE;
    }
  }

  /* domain structure */
  if( errNum == WLZ_ERR_NONE ){
    if( nints > 0 ){
      if((idom = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_INTVL,
				       nl1, nll, nk1, nkl, &errNum)) != NULL){
	if( (itvl = (WlzInterval *)
	     AlcMalloc(nints * sizeof(WlzInterval))) == NULL ){
	  errNum = WLZ_ERR_MEM_ALLOC;
	  WlzFreeIntervalDomain(idom);
	}
	else {
	  idom->freeptr = AlcFreeStackPush(idom->freeptr, (void *)itvl, NULL);
	}
      }

      /*
       * second pass - construct intervals
       */
      if( errNum == WLZ_ERR_NONE ){
	errNum = WlzInitGreyScan(obj, &iwsp, &gwsp);
	callData.pix.type = gwsp.pixeltype;
	nints = 0;
	jtvl = itvl;
      }

      /* find thresholded endpoints */
      if( errNum == WLZ_ERR_NONE ){
	while( (errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE ){
	  if( iwsp.linpos < nl1 || iwsp.linpos > nll ){
	    continue;
	  }
	  callData.pos.vtY = iwsp.linpos;
	  g = gwsp.u_grintptr;
	  over = 0;

	  for (colno = iwsp.lftpos; colno <= iwsp.rgtpos; colno++) {
	    callData.pix.p = g;
	    callData.pos.vtX = colno;
	    if((*threshCb)(obj, clientData, &callData) ){
	      if (over == 0) {
		over = 1;
		itvl->ileft = colno - nk1;
	      }
	    } else {
	      if (over == 1) {
		over = 0;
		itvl->iright = colno - nk1 - 1;
		nints++;
		itvl++;
	      }
	    }

	    switch( gwsp.pixeltype ){
	    case WLZ_GREY_INT:
	      g.inp++;
	      break;
	    case WLZ_GREY_SHORT:
	      g.shp++;
	      break;
	    case WLZ_GREY_UBYTE:
	      g.ubp++;
	      break;
	    case WLZ_GREY_FLOAT:
	      g.flp++;
	      break;
	    case WLZ_GREY_DOUBLE:
	      g.dbp++;
	      break;
	    case WLZ_GREY_RGBA:
	      g.rgbp++;
	      break;
	    default:
	      break;
	    }
	  }

	  if (over == 1) {
	    over = 0;
	    itvl->iright = colno - nk1 - 1;
	    nints++;
	    itvl++;
	  }
	  /*
	   * end of line ?
	   */
	  if (iwsp.intrmn == 0) {
	    WlzMakeInterval(iwsp.linpos, idom, nints, jtvl);
	    jtvl = itvl;
	    nints = 0;
	  }
	}
	if( errNum == WLZ_ERR_EOO ){
	  errNum = WLZ_ERR_NONE;
	}
      }
    } else {
      /* no thresholded points - make a dummy domain anyway */
      return WlzMakeEmpty(dstErr);
    }
  }

  /* main object */
  if( errNum == WLZ_ERR_NONE ){
    domain.i = idom;
    nobj = WlzMakeMain(WLZ_2D_DOMAINOBJ, domain, obj->values,
		       obj->plist, obj, &errNum);
  }

  if( dstErr ){
    *dstErr = errNum;
  }
  return(nobj);
}
Ejemplo n.º 11
0
/*! 
* \ingroup      WlzBinaryOps
* \brief        Calculate the intersection of a set of objects. If
 uvt=0 calculate domain only, uvt=1 calculate the mmean grey-value at
 each point. Input objects must be all non-NULL and domain objects of
 the same type i.e. either 2D or 3D otherwise an error is returned.
*
* \return       Intersection object with grey-table as required, if the intersection is empty returns WLZ_EMPTY_OBJ, NULL on error.
* \param    n	number of input objects
* \param    objs	input object array
* \param    uvt	grey-table copy flag (1 - copy, 0 - no copy)
* \param    dstErr	error return.
* \par      Source:
*                WlzIntersectN.c
*/
WlzObject *WlzIntersectN(
  int 	n,
  WlzObject **objs,
  int 	uvt,
  WlzErrorNum *dstErr)
{
  WlzObject 		*obj = NULL;
  WlzIntervalDomain 	*idom;
  WlzInterval 		*itvl, *jtvl;
  WlzIntervalWSpace 	*iwsp;
  WlzIntervalWSpace 	*biwsp,*tiwsp,niwsp;
  WlzGreyWSpace 	*gwsp,ngwsp;
  WlzDomain		domain;
  WlzValues		values;
  WlzObjectType		type;
  WlzPixelV		backg;
  WlzGreyP		greyptr;
  WlzGreyV		gv;
  int 			i, j, k, l, inttot, change, lwas, nints;
  int 			line1, lastln;
  int 			kol1, lastkl;
  WlzErrorNum		errNum = WLZ_ERR_NONE;

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

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

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

  case WLZ_2D_DOMAINOBJ:
    break;

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

  case WLZ_EMPTY_OBJ:
    return WlzMakeEmpty(dstErr);

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

  }

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

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

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

  /*
   * Find the line and column bounds of the intersection.
   */
  line1 = objs[0]->domain.i->line1;
  lastln = objs[0]->domain.i->lastln;
  kol1 = objs[0]->domain.i->kol1;
  lastkl = objs[0]->domain.i->lastkl;
  for (i=1; i<n; i++) {
    idom = objs[i]->domain.i;
    if (line1 < idom->line1)
    {
      line1 = idom->line1;
    }
    if (lastln > idom->lastln)
    {
      lastln = idom->lastln;
    }
    if (kol1 < idom->kol1)
    {
      kol1 = idom->kol1;
    }
    if (lastkl > idom->lastkl)
    {
      lastkl = idom->lastkl;
    }
  }
  if( lastkl < kol1 || lastln < line1 ){
    return WlzMakeEmpty(dstErr);
  }

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

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

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

  idom->freeptr = AlcFreeStackPush(idom->freeptr, (void *)itvl, NULL);
  lwas = line1;
  jtvl = itvl;
  nints = 0;
  domain.i = idom;
  values.v = NULL;
  if( (obj = WlzMakeMain(WLZ_2D_DOMAINOBJ,
			 domain, values, NULL, NULL, &errNum)) == NULL ){
    WlzFreeIntervalDomain(idom);
    if(dstErr) {
      *dstErr = errNum;
    }
    return NULL;
  }

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

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

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

  jumpline:
    ;
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

      default:
	errNum = WLZ_ERR_GREY_TYPE;
	break;

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

  if(dstErr) {
    *dstErr = errNum;
  }
  return obj;
}
Ejemplo n.º 12
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;
}