Exemplo n.º 1
0
/*!
* \return	Woolz error code.
* \ingroup	WlzExtFF
* \brief	Writes the given Woolz 3D domain object with values to
*		the given file using the Amira lattice (.am file) format.
* \param	fP			Output file pointer
* \param	obj			Object to be written.
*/
static WlzErrorNum	WlzEffAmWrite3DDomObj(FILE *fP, WlzObject *obj)
{
  size_t	dataCnt,
  		dataSz;
  WlzDBox3	bbD;
  WlzIBox3	bbI;
  WlzIVertex3	sz,
  		org;
  WlzDVertex3	vSz;
  char		*dateS,
  		*dataTypeS;
  time_t	tTime;
  WlzGreyType	gType;
  void		***data = NULL;
  WlzErrorNum	errNum = WLZ_ERR_UNIMPLEMENTED;

  if(obj->domain.core->type != WLZ_PLANEDOMAIN_DOMAIN)
  {
    errNum = WLZ_ERR_DOMAIN_TYPE;
  }
  else if(obj->values.core == NULL)
  {
     errNum = WLZ_ERR_VALUES_NULL;
  }
  else if(obj->values.core->type != WLZ_VOXELVALUETABLE_GREY)
  {
    errNum = WLZ_ERR_VALUES_TYPE;
  }
  else
  {
    bbI = WlzBoundingBox3I(obj, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    tTime = time(NULL);
    dateS = ctime(&tTime);
    *(dateS + strlen(dateS) - 1) = '\0';
  }
  if(errNum == WLZ_ERR_NONE)
  {
    vSz = WlzVozelSz(obj, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    bbD.xMin = bbI.xMin * vSz.vtX;
    bbD.xMax = bbI.xMax * vSz.vtX;
    bbD.yMin = bbI.yMin * vSz.vtY;
    bbD.yMax = bbI.yMax * vSz.vtY;
    bbD.zMin = bbI.zMin * vSz.vtZ;
    bbD.zMax = bbI.zMax * vSz.vtZ;
    sz.vtX = bbI.xMax - bbI.xMin + 1;
    sz.vtY = bbI.yMax - bbI.yMin + 1;
    sz.vtZ = bbI.zMax - bbI.zMin + 1;
    org.vtX = bbI.xMin;
    org.vtY = bbI.yMin;
    org.vtZ = bbI.zMin;
    gType = WlzGreyTypeFromObj(obj, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    switch(gType)
    {
      case WLZ_GREY_SHORT:
	dataTypeS = "short";
        break;
      case WLZ_GREY_UBYTE:
	dataTypeS = "byte";
        break;
      default:
	errNum = WLZ_ERR_GREY_TYPE;
        break;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if(fprintf(fP,
               "# AmiraMesh 3D BINARY 2.0\n"
               "# WlzExtFF\n"
               "# CreationDate: %s\n"
               "\n"
               "define Lattice %d %d %d\n"
               "\n"
               "Parameters {\n"
               "    Content \"%dx%dx%d %s, uniform coordinates\",\n"
               "    BoundingBox %g %g %g %g %g %g,\n"
               "    CoordType \"uniform\"\n"
               "}\n"
	       "\n"
               "Lattice { %s Data } @1\n"
	       "\n"
               "# Data section follows\n"
               "@1\n",
	       dateS,
	       sz.vtX, sz.vtY, sz.vtZ,
	       sz.vtX, sz.vtY, sz.vtZ, dataTypeS,
	       bbD.xMin, bbD.xMax, bbD.yMin, bbD.yMax, bbD.zMin, bbD.zMax,
	       dataTypeS) <= 0)
    {
      errNum = WLZ_ERR_WRITE_INCOMPLETE;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    errNum = WlzToArray3D(&data, obj, sz, org, 0, gType);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    dataCnt = sz.vtX * sz.vtY * sz.vtZ;
    switch(gType)
    {
      case WLZ_GREY_SHORT:
	dataSz = 2;
	break;
      case WLZ_GREY_UBYTE:
	dataSz = 1;
	break;
      default:
	break;
    }
    if(fwrite(**data, dataSz, dataCnt, fP) != dataSz * dataCnt)
    {
      errNum = WLZ_ERR_WRITE_INCOMPLETE;
    }
  }
  (void )Alc3Free(data);
  return(errNum);
}
Exemplo n.º 2
0
/*!
* \return	New Woolz object without holes or NULL on error.
* \ingroup	WlzDomainOps
* \brief	Fills the holes in the given object's domain (which are by
* 		definition not connected to the outside). When the given
* 		object's domain has more than one component part, the
* 		object should first be labeled, this function should then be
* 		called for each of the labeled parts and then the union of
* 		the filled domains should be formed.
* \param	srcObj			Given 3D domain object.
* \param	dstErr			Destination error pointer, may be NULL.
*/
WlzObject 			*WlzDomainFill3D(
  				  WlzObject *srcObj,
    				  WlzErrorNum *dstErr)
{
  int		nPln = 0;
  WlzObject	*bndObj = NULL,
  		*filObj = NULL,
  		*gvnObj = NULL,
		*sedObj = NULL,
		*shlObj = NULL;
  WlzPixelV	zeroV;
  WlzValues 	nullVal;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      /* Put back any isolated voxels this function has removed. */
      tObj0 = WlzAssignObject(
              WlzMakeMain(srcObj->type, filDom, nullVal,
      			  NULL, NULL, &errNum), NULL);
      if(errNum == WLZ_ERR_NONE)
      {
        tObj1 = WlzUnion2(gvnObj, tObj0, &errNum);
      }
      if(errNum == WLZ_ERR_NONE)
      {
	filObj = WlzMakeMain(tObj1->type, tObj1->domain, nullVal,
			     NULL, NULL, &errNum);
      }
      (void )WlzFreeObj(tObj0);
      (void )WlzFreeObj(tObj1);
    }
  }
  (void )WlzFreeObj(bndObj);
  (void )WlzFreeObj(gvnObj);
  (void )WlzFreeObj(shlObj);
  (void )WlzFreeObj(sedObj);
  if((errNum != WLZ_ERR_NONE) && (filObj != NULL))
  {
    (void )WlzFreeObj(filObj);
    filObj = NULL;
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(filObj);
}
Exemplo n.º 3
0
/*!
* \return	Woolz error code.
* \ingroup	WlzBinaryOps
* \brief	Splits the reference object into component objects cliped
*		from the reference object, with the bounding box of each
*		of the component objects determined using the pre-processed
*		object. The component objects are returned in size order.
* \param	refObj			Reference object.
* \param	ppObj			Pre-processed object which is
*					normalised to values in the range
*					0 - 255 as WlzUByte greys.
* \param	bWidth			Border width.
* \param	bgdFrac			Minimum fraction of values which are
* 					background values, with range
*					[0.0+ - 1.0-].
* \param	sigma			Histogram smoothing parameter used
*					by WlzHistogramCnvGauss().
* \param	compThrMethod		Method for computing threshold, used
*					in call to WlzCompThresholdVT().
* \param	nReqComp		Number of required components.
* \param	dstNComp		Destination pointer for the number of
*					components extracted, must not be NULL.
* \param	dstComp			Destination pointer for the extracted
*					components, must not be NULL.
*/
WlzErrorNum	WlzSplitObj(WlzObject *refObj, WlzObject *ppObj,
			      int bWidth, double bgdFrac, double sigma,
			      WlzCompThreshType compThrMethod,
			      int nReqComp, int *dstNComp,
			      WlzObject ***dstComp)
{
  int		dim,
  		idC;
  WlzObject	*hObj = NULL,
  		*tObj = NULL;
  WlzObject 	**comp = NULL;
  WlzBox	box;
  WlzPixelV	tV;
  WlzSplitObjData split;
  WlzThresholdType tType;
  WlzConnectType lCon;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  const int	maxComp = 1024;

  split.nLComp = 0;
  split.compI = NULL;
  split.lCompSz = NULL;
  split.lComp = NULL;
  if((refObj == NULL) || (ppObj == NULL))
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if((refObj->domain.core == NULL) || (ppObj->domain.core == NULL))
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if((refObj->values.core == NULL) || (ppObj->values.core == NULL))
  {
    errNum = WLZ_ERR_VALUES_NULL;
  }
  else if(refObj->type != ppObj->type)
  {
    errNum = WLZ_ERR_OBJECT_TYPE;
  }
  else if((dstNComp == NULL) || (dstComp == NULL))
  {
    errNum = WLZ_ERR_PARAM_NULL;
  }
  else if((bgdFrac < DBL_EPSILON) || (bgdFrac > (1.0 - DBL_EPSILON)))
  {
    errNum = WLZ_ERR_PARAM_DATA;
  }
  else
  {
    switch(refObj->type)
    {
      case WLZ_2D_DOMAINOBJ:
	dim = 2;
        lCon = WLZ_8_CONNECTED;
	break;
      case WLZ_3D_DOMAINOBJ:
	dim = 3;
        lCon = WLZ_26_CONNECTED;
	break;
      default:
        errNum = WLZ_ERR_OBJECT_TYPE;
	break;
    }
  }
  /* Compute threshold value and type from histogram. */
  if(errNum == WLZ_ERR_NONE)
  {
    hObj = WlzAssignObject(
    	   WlzHistogramObj(ppObj, 256, 0.0, 1.0, &errNum), NULL);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    errNum = WlzHistogramCnvGauss(hObj, sigma, 0);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    errNum = WlzCompThresholdVT(hObj, compThrMethod, bgdFrac, 0.0,
    			        0.0, &tV, &tType);
  }
  (void )WlzFreeObj(hObj); hObj = NULL;
  /* Threshold object. */
  if(errNum == WLZ_ERR_NONE)
  {
    tObj = WlzAssignObject(
     	   WlzThreshold(ppObj, tV, tType, &errNum), NULL);
  }
  /* Label to get connected components. */
  if(errNum == WLZ_ERR_NONE)
  {
    errNum = WlzLabel(tObj, &(split.nLComp), &(split.lComp), maxComp, 0, lCon);
  }
  /* Sort connected components by size. */
  if(errNum == WLZ_ERR_NONE)
  {
    if(split.nLComp < nReqComp)
    {
      nReqComp = split.nLComp;
    }
    if(((split.compI = (int *)AlcMalloc(sizeof(int) *
                                        split.nLComp)) == NULL) ||
       ((split.lCompSz = (int *)AlcMalloc(sizeof(int) *
                                          split.nLComp)) == NULL))
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    idC = 0; 
    while((errNum == WLZ_ERR_NONE) && (idC < split.nLComp))
    {
      split.compI[idC] = idC;
      split.lCompSz[idC] = (dim == 2)? WlzArea(split.lComp[idC], &errNum):
      				       WlzVolume(split.lComp[idC], &errNum);
      ++idC;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    /* Sort component indices by component size. */
    AlgQSort(split.compI, split.nLComp, sizeof(int), &split,
    	     WlzSplitObjSortSzFn);
    /* Allocate array for cliped component objects. */
    if((comp = (WlzObject **)AlcCalloc(sizeof(WlzObject *),
    				       split.nLComp)) == NULL)
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  /* Compute bounding box and clip objects from the reference object. */
  if(errNum == WLZ_ERR_NONE)
  {
    idC = 0;
    while((errNum == WLZ_ERR_NONE) && (idC < nReqComp))
    {
      if(dim == 2)
      {
        box.i2 = WlzBoundingBox2I(split.lComp[split.compI[idC]], &errNum);
	if(errNum == WLZ_ERR_NONE)
	{
	  box.i2.xMin -= bWidth;
	  box.i2.yMin -= bWidth;
	  box.i2.xMax += bWidth;
	  box.i2.yMax += bWidth;
	  comp[idC] = WlzClipObjToBox2D(refObj, box.i2, &errNum);
	}
      }
      else /* dim == 3 */
      {
        box.i3 = WlzBoundingBox3I(split.lComp[split.compI[idC]], &errNum);
	if(errNum == WLZ_ERR_NONE)
	{
	  box.i3.xMin -= bWidth;
	  box.i3.yMin -= bWidth;
	  box.i3.zMin -= bWidth;
	  box.i3.xMax += bWidth;
	  box.i3.yMax += bWidth;
	  box.i3.zMax += bWidth;
	  comp[idC] = WlzClipObjToBox3D(refObj, box.i3, &errNum);
	}
      }
      ++idC;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    *dstNComp = nReqComp;
    *dstComp = comp;
  }
  /* Free temporary storage. */
  if(split.lComp)
  {
    for(idC = 0; idC < split.nLComp; ++idC)
    {
      (void )WlzFreeObj(split.lComp[idC]);
    }
    AlcFree(split.lComp);
  }
  AlcFree(split.compI);
  AlcFree(split.lCompSz);
  (void )WlzFreeObj(tObj);
  return(errNum);
}
Exemplo n.º 4
0
/*!
* \return	Woolz error code.
* \ingroup	WlzBinaryOps
* \brief	Splits the given montage object into component objects
*		clipped from the montage object.  The montage object
*		must be composed of component images embedded in a
*		background, with little variation in the background
*		values.
* \param	mObj			Montage object, which must be either
*					a WLZ_2D_DOMAINOBJ or a
*					WLZ_3D_DOMAINOBJ with values.
* \param	gapV			Value for the uniform background.
*					Must be either WLZ_GREY_INT or
*					WLZ_GREY_RGBA.
* \param	tol			Tolerance (fraction) for the
*					variation in background values.
* \param	bWidth			Additional boundary width added
*					to detected images before they are
*					clipped.
* \param	minArea			Minimum area for a valid component
*					image, must be greater than zero.
* \param	maxComp			Maximum number of components.
* \param	dstNComp		Destination pointer for the number of
*					components extracted, must not be NULL.
* \param	dstComp			Destination pointer for the extracted
*					components, must not be NULL.
*/
WlzErrorNum 	WlzSplitMontageObj(WlzObject *mObj, WlzPixelV gapV,
				      double tol, int bWidth, int minArea,
				      int maxComp,
				      int *dstNComp, WlzObject ***dstComp)
{
  int		id0,
  		id1,
		area,
		nLComp = 0;
  WlzObject	*gObj = NULL,
  		*tObj = NULL;
  WlzObject	**lComp;
  WlzGreyType	objG;
  WlzBox	box;
  WlzPixelV	gapLV,
  		gapHV;
  WlzConnectType lCon;
  int		tI[8];
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  tol = WLZ_CLAMP(tol, 0.0, 1.0);
  if(mObj == NULL)
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if(minArea < 1)
  {
    errNum = WLZ_ERR_PARAM_DATA;
  }
  else
  {
    switch(mObj->type)
    {
      case WLZ_2D_DOMAINOBJ:
	lCon = WLZ_4_CONNECTED;
        break;
      case WLZ_3D_DOMAINOBJ:
	lCon = WLZ_6_CONNECTED;
        break;
      default:
        errNum = WLZ_ERR_OBJECT_TYPE;
	break;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    objG = WlzGreyTypeFromObj(mObj, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    switch(gapV.type)
    {
      case WLZ_GREY_INT: /* FALLTHROUGH */
      case WLZ_GREY_RGBA:
        break;
      default:
	errNum = WLZ_ERR_GREY_TYPE;
	break;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if(objG == WLZ_GREY_RGBA)
    {
      if(gapV.type != WLZ_GREY_RGBA)
      {
        (void )WlzValueConvertPixel(&gapV, gapV, WLZ_GREY_RGBA);
      }
    }
    else
    {
      if(gapV.type != WLZ_GREY_INT)
      {
        (void )WlzValueConvertPixel(&gapV, gapV, WLZ_GREY_INT);
      }
    }
    gapLV.type = gapHV.type = gapV.type;
    if(gapV.type == WLZ_GREY_INT)
    {
      tI[0] = gapV.v.inv * tol;
      gapLV.v.inv = gapV.v.inv - tI[0];
      gapHV.v.inv = gapV.v.inv + tI[0];
      tObj = WlzThreshold(mObj, gapLV, WLZ_THRESH_HIGH, &errNum);
      if((errNum == WLZ_ERR_NONE) && (tObj != NULL))
      {
	gObj = WlzThreshold(tObj, gapHV, WLZ_THRESH_LOW, &errNum);
      }
      (void )WlzFreeObj(tObj);
      tObj = NULL;
    }
    else /* gapV.type == WLZ_GREY_RGBA */
    {
	tI[0] = WLZ_RGBA_RED_GET(gapV.v.rgbv);
	tI[1] = (int )floor((double )(tI[0]) * tol);
	tI[2] = tI[0] - tI[1];
	tI[5] = tI[0] + tI[1];
	tI[0] = WLZ_RGBA_GREEN_GET(gapV.v.rgbv);
	tI[1] = (int )floor((double )(tI[0]) * tol);
	tI[3] = tI[0] - tI[1];
	tI[6] = tI[0] + tI[1];
	tI[0] = WLZ_RGBA_BLUE_GET(gapV.v.rgbv);
	tI[1] = (int )floor((double )(tI[0]) * tol);
	tI[4] = tI[0] - tI[1];
	tI[7] = tI[0] + tI[1];
	tI[2] = WLZ_CLAMP(tI[2], 0, 255);
	tI[3] = WLZ_CLAMP(tI[3], 0, 255);
	tI[4] = WLZ_CLAMP(tI[4], 0, 255);
	WLZ_RGBA_RGBA_SET(gapLV.v.rgbv, tI[2], tI[3], tI[4], 255);
	tI[5] = WLZ_CLAMP(tI[5], 0, 255);
	tI[6] = WLZ_CLAMP(tI[6], 0, 255);
	tI[7] = WLZ_CLAMP(tI[7], 0, 255);
	WLZ_RGBA_RGBA_SET(gapHV.v.rgbv, tI[5], tI[6], tI[7], 255);
        gObj = WlzRGBABoxThreshold(mObj, gapLV, gapHV, &errNum);
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    tObj = WlzDiffDomain(mObj, gObj, &errNum);
  }
  (void )WlzFreeObj(gObj);
  if(errNum == WLZ_ERR_NONE)
  {
    errNum = WlzLabel(tObj, &nLComp, &lComp, maxComp, 0, lCon);
  }
  (void )WlzFreeObj(tObj);
  if(errNum == WLZ_ERR_NONE)
  {
    /* Get rid of small objects using minArea as the threshold. */
    id0 = 0;
    id1 = 0;
    while(id0 < nLComp)
    {
      switch((*(lComp + id0))->type)
      {
        case WLZ_2D_DOMAINOBJ:
	  area = WlzArea(*(lComp + id0), NULL);
	  break;
        case WLZ_3D_DOMAINOBJ:
	  area = WlzVolume(*(lComp + id0), NULL);
	  break;
        default:
          area = 0;
	  break;
      }
      if(area >= minArea)
      {
        *(lComp + id1) = *(lComp + id0);
        ++id1;
      }
      else
      {
        (void )WlzFreeObj(*(lComp + id0));
	*(lComp + id0) = NULL;
      }
      ++id0;
    }
    nLComp = id1;
  }
  if(errNum == WLZ_ERR_NONE)
  {
    /* Clip rectangular objects from the montage object. */
    id0 = 0;
    while((errNum == WLZ_ERR_NONE) && (id0 < nLComp))
    {
      if(tObj->type == WLZ_2D_DOMAINOBJ)
      {
        box.i2 = WlzBoundingBox2I(*(lComp + id0), &errNum);
	box.i2.xMin -= bWidth;
	box.i2.yMin -= bWidth;
	box.i2.xMax += bWidth;
	box.i2.yMax += bWidth;
	(void )WlzFreeObj(*(lComp + id0));
	*(lComp + id0) = WlzClipObjToBox2D(mObj, box.i2, &errNum);
      }
      else /* tObj->type == WLZ_3D_DOMAINOBJ */
      {
        box.i3 = WlzBoundingBox3I(*(lComp + id0), &errNum);
	box.i3.xMin -= bWidth;
	box.i3.yMin -= bWidth;
	box.i3.zMin -= bWidth;
	box.i3.xMax += bWidth;
	box.i3.yMax += bWidth;
	box.i3.zMax += bWidth;
	(void )WlzFreeObj(*(lComp + id0));
	*(lComp + id0) = WlzClipObjToBox3D(mObj, box.i3, &errNum);
      }
      ++id0;
    }
  }
  *dstNComp = nLComp;
  *dstComp = lComp;
  return(errNum);
}
Exemplo n.º 5
0
int             main(int argc, char **argv)
{
  int           option,
                ok = 1,
                usage = 0,
		dim = 0,
		transform = 0;
  WlzIBox3	bBox[2];
  WlzEffFormat  outFmt = WLZEFF_FORMAT_NONE;
  WlzEffFormat  inFmt[2] = {WLZEFF_FORMAT_NONE};
  WlzObject     *outObj = NULL;
  WlzObject	*inObj[2] = {NULL};
  char          *outFileStr;
  char		*inFileStr[2] = {NULL};
  WlzAffineTransform *tr = NULL;
  WlzErrorNum   errNum = WLZ_ERR_NONE;
  const char    *errMsg;
  static char   optList[] = "s:t:o:u:hT",
                fileStrDef[] = "-";

  opterr = 0;
  inFileStr[0] = fileStrDef;
  inFileStr[1] = fileStrDef;
  outFileStr = fileStrDef;
  while((usage == 0) && ((option = getopt(argc, argv, optList)) != -1))
  {
    switch(option)
    {
      case 's':
	if((inFmt[0] = WlzEffStringExtToFormat(optarg)) == 0)
	{
	  usage = 1;
	  ok = 0;
	}
	break;
      case 't':
	if((inFmt[1] = WlzEffStringExtToFormat(optarg)) == 0)
	{
	  usage = 1;
	  ok = 0;
	}
	break;
      case 'u':
	if((outFmt = WlzEffStringExtToFormat(optarg)) == 0)
	{
	  usage = 1;
	  ok = 0;
	}
	break;
      case 'o':
	outFileStr = optarg;
	break;
      case 'T':
	transform = 1;
	break;
      case 'h': /* FALLTHROUGH */
      default:
	usage = 1;
	break;
    }
  }
  if(usage == 0)
  {
    usage = (optind + 2 != argc);
  }
  if(usage == 0)
  {
    inFileStr[0] = *(argv + optind);
    inFileStr[1] = *(argv + optind + 1);
  }
  if(usage == 0)
  {
    if(inFmt[0] == WLZEFF_FORMAT_NONE)
    {
      inFmt[0] = WlzEffStringFormatFromFileName(inFileStr[0]);
    }
    if(inFmt[1] == WLZEFF_FORMAT_NONE)
    {
      inFmt[1] = WlzEffStringFormatFromFileName(inFileStr[1]);
    }
    if(outFmt == WLZEFF_FORMAT_NONE)
    {
      outFmt = WlzEffStringFormatFromFileName(outFileStr);
    }
    if((inFmt[0] == WLZEFF_FORMAT_NONE) || (inFmt[1] == WLZEFF_FORMAT_NONE) ||
       (outFmt == WLZEFF_FORMAT_NONE))
    {
      usage = 1;
    }
  }
  ok = (usage == 0);
  /* Read source and target objects. */
  if(ok)
  {
    int		idx;

    for(idx = 0; ok && (idx < 2); ++idx)
    {
      char *fStr;
      FILE *fP;

      if(strcmp(inFileStr[idx], "-") == 0)
      {
        fP = stdin;
	fStr = NULL;
      }
      else
      {
        fP = NULL;
	fStr = inFileStr[idx];
      }
      if((inObj[idx] = WlzAssignObject(WlzEffReadObj(fP, fStr, inFmt[idx],
                                       0, 0, 0, &errNum), NULL)) == NULL)
      {
	ok = 0;
	(void )WlzStringFromErrorNum(errNum, &errMsg);
	(void )fprintf(stderr,
	    "%s: Failed to read object from file(s) %s (%s)\n",
	    *argv, inFileStr[idx], errMsg);
      }
    }
  }
  /* Check object dimension */
  if(ok)
  {
    int		idx;
    int		d[2];

    d[0] = 0;
    for(idx = 0; ok && (idx < 2); ++idx)
    {
      d[idx] = WlzObjectDimension(inObj[idx], &errNum);
      ok = (errNum == WLZ_ERR_NONE);
    }
    if(errNum == WLZ_ERR_NONE)
    {
      if((d[0] == 0) || (d[0] != d[1]))
      {
	ok = 0;
        errNum = WLZ_ERR_OBJECT_TYPE;
      }
    }
    dim = d[0];
    if(errNum != WLZ_ERR_NONE)
    {
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
          "%s: Failed to establish object dimensions (%s)\n",
	  *argv, errMsg);
    }
  }
  /* Compute the bounding box of the source and target objects. */
  if(ok)
  {
    int		idx;

    for(idx = 0; ok && (idx < 2); ++idx)
    {
      bBox[idx] = WlzBoundingBox3I(inObj[idx], &errNum);
      if(errNum != WLZ_ERR_NONE)
      {
        ok = 0;
	(void )WlzStringFromErrorNum(errNum, &errMsg);
	(void )fprintf(stderr,
	    "%s: Failed to compute bounding box of object read from file\n"
	    "%s (%s).\n",
	    *argv, inFileStr[idx], errMsg);
      }
    }
  }
  /* Compute affine transform which will register the source to target
   * bounding box. */
  if(ok)
  {
    int		idx,
    		nVtx;
    WlzVertexType vType;
    WlzTransformType tType;
    WlzVertexP vP[2];
    WlzDVertex3	wSp[48];

    vP[0].d3 = wSp;
    vP[1].d3 = wSp + 24;
    if(dim == 2)
    {
      nVtx = 4;
      vType = WLZ_VERTEX_D2;
      tType = WLZ_TRANSFORM_2D_AFFINE;
      for(idx = 0; idx < 2; ++idx)
      {
        (vP[idx].d2)[0].vtX = bBox[idx].xMin;
	(vP[idx].d2)[0].vtY = bBox[idx].yMin;
        (vP[idx].d2)[1].vtX = bBox[idx].xMax;
	(vP[idx].d2)[1].vtY = bBox[idx].yMin;
        (vP[idx].d2)[2].vtX = bBox[idx].xMax;
	(vP[idx].d2)[2].vtY = bBox[idx].yMax;
        (vP[idx].d2)[3].vtX = bBox[idx].xMin;
	(vP[idx].d2)[3].vtY = bBox[idx].yMax;
      }
    }
    else /* dim == 3 */
    {
      nVtx = 8;
      vType = WLZ_VERTEX_D3;
      tType = WLZ_TRANSFORM_3D_AFFINE;
      for(idx = 0; idx < 2; ++idx)
      {
        (vP[idx].d3)[0].vtX = bBox[idx].xMin;
	(vP[idx].d3)[0].vtY = bBox[idx].yMin;
	(vP[idx].d3)[0].vtZ = bBox[idx].zMin;
        (vP[idx].d3)[1].vtX = bBox[idx].xMax;
	(vP[idx].d3)[1].vtY = bBox[idx].yMin;
	(vP[idx].d3)[1].vtZ = bBox[idx].zMin;
        (vP[idx].d3)[2].vtX = bBox[idx].xMax;
	(vP[idx].d3)[2].vtY = bBox[idx].yMax;
	(vP[idx].d3)[2].vtZ = bBox[idx].zMin;
        (vP[idx].d3)[3].vtX = bBox[idx].xMin;
	(vP[idx].d3)[3].vtY = bBox[idx].yMax;
	(vP[idx].d3)[3].vtZ = bBox[idx].zMin;
        (vP[idx].d3)[4].vtX = bBox[idx].xMin;
	(vP[idx].d3)[4].vtY = bBox[idx].yMin;
	(vP[idx].d3)[4].vtZ = bBox[idx].zMax;
        (vP[idx].d3)[5].vtX = bBox[idx].xMax;
	(vP[idx].d3)[5].vtY = bBox[idx].yMin;
	(vP[idx].d3)[5].vtZ = bBox[idx].zMax;
        (vP[idx].d3)[6].vtX = bBox[idx].xMax;
	(vP[idx].d3)[6].vtY = bBox[idx].yMax;
	(vP[idx].d3)[6].vtZ = bBox[idx].zMax;
        (vP[idx].d3)[7].vtX = bBox[idx].xMin;
	(vP[idx].d3)[7].vtY = bBox[idx].yMax;
	(vP[idx].d3)[7].vtZ = bBox[idx].zMax;
      }
    }
    tr = WlzAffineTransformLSq(vType, nVtx, vP[1], nVtx, vP[0], 0, NULL,
                               tType, &errNum);
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
	  "%s: Failed to compute affine transform (%s).\n",
	  *argv, errMsg);
    }
  }
  /* Create affine transform object or affine transform the source object
   * as required. */
  if(ok)
  {
    int		idx,
    		idy;
    const double eps = 1.0e-12;

    /* Tidy up the transform, |t_{ij}| < eps => t_{ij} = 0.0. */
    for(idy = 0; idy < 4; ++idy)
    {
      for(idx = 0; idx < 4; ++idx)
      {
        if(fabs(tr->mat[idy][idx]) < eps)
	{
	  tr->mat[idy][idx] = 0.0;
	}
      }
    }
    if(transform)
    {
      outObj = WlzAffineTransformObj(inObj[0], tr, WLZ_INTERPOLATION_NEAREST,
                                     &errNum);
      if(outObj)
      {
        tr = NULL;
      }
    }
    else
    {
      WlzDomain dom;
      WlzValues val;

      dom.t = tr;
      val.core = NULL;
      outObj = WlzMakeMain(WLZ_AFFINE_TRANS, dom, val, NULL, NULL, &errNum);
    }
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
                     "%s: Failed to %saffine transform object (%s).\n",
		     *argv, (transform)? "create ": "", errMsg);
    }
  }
  /* Write the output object. */
  if(ok)
  {
    char *fStr;
    FILE *fP;

    if(strcmp(outFileStr, "-") == 0)
    {
      fP = stdout;
      fStr = NULL;
    }
    else
    {
      fP = NULL;
      fStr = outFileStr;
    }
    errNum = WlzEffWriteObj(fP, fStr, outObj, outFmt);
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
	  "%s: Failed to write object to file %s (%s)\n",
	  *argv, outFileStr, errMsg);
    }
  }
  (void )WlzFreeObj(inObj[0]);
  (void )WlzFreeObj(inObj[1]);
  (void )WlzFreeObj(outObj);
  if(usage)
  {
    char *fmtStr = NULL;

    fmtStr = WlzEffFormatTable(2, 50, 10, NULL);
    (void )fprintf(
        stderr,
	"Usage: %s%s%s%s%s%s%s%s\n",
	*argv,
	" [-h] [-T]\n"
	"\t\t[-o<out file>] [-s<src fmt>] [-t<tgt fmt>] [-u<out fmt>]\n"
	"\t\t<source object> <target object>\n"
        "Computes the Woolz affine transform which makes the bounding box of\n"
	"the source object equal to that of the target object.\n"
	"Version: ",
	WlzVersion(),
	"\n"
	"  -h Help, prints this usage information.\n"
	"  -o Output file.\n"
	"  -s Source file format.\n"
	"  -t Target file format.\n"
	"  -u Output file format.\n"
	"  -T Transform the source object and write it to the output file\n"
	"     rather than the affine transform.\n"
        "The known file formats are:\n"
	"  Description                                       Extension\n"
	"  ***********                                       *********\n",
	fmtStr,
	"Simple example:\n  ",
	*argv,
	"-o out.wlz small.vtk big.stl\n"
	"Reads the source object from the file small.vtk and the target\n"
	"object from big.stl then computes the affine transform which scales\n"
	"the source objects bounding box to fit that of the target object.\n"
	"The output transform is written to the file out.wlz.\n");
  }
  return(!ok);
}
Exemplo n.º 6
0
/*!
* \return	New filtered object with new values or NULL on error.
* \ingroup	WlzValuesFilters
* \brief	Applies a seperable filter to the given object using the given
* 		convolution kernels.
* \param	inObj			Input 2 or 3D spatial domain object
* 					to be filtered which must have scalar
* 					values.
* \param	cBufSz			Convolution kernel sizes (sz), each
* 					kernel buffer is sized (2 * sz) + 1
* 					with the centre indexed sz into the
* 					buffer.
* \param	cBuf			Convolution kernel buffers.
* \param	direc			Set to non-zero in directions for which
* 					the filter is to be applied.
* \param	gType			Required return object grey type.
* 					Passing in WLZ_GREY_ERROR will
* 					request the given input object's grey
* 					type.
* \param	pad			Type of padding.
* \param	padVal			Padding value, only used when
* 					pad == ALG_PAD_VALUE.
* \param	dstErr			Destination error pointer may be NULL.
*/
WlzObject			*WlzSepFilter(WlzObject *inObj,
				  WlzIVertex3 cBufSz,
				  double *cBuf[],
				  WlzIVertex3 direc,
				  WlzGreyType gType,
				  AlgPadType pad,
				  double padVal,
				  WlzErrorNum *dstErr)
{
  int		dim = 0,
  		vSz = 0,
  		nThr = 1;
  double	**iBuf = NULL,
  		**rBuf = NULL;
  double	*vBuf = NULL;
  WlzObject	*rnObj = NULL;
  WlzIVertex3	vBufSz = {0};
  WlzIBox3	bBox = {0};
  WlzErrorNum	errNum = WLZ_ERR_NONE;

#ifdef _OPENMP
#pragma omp parallel
  {
#pragma omp master
    {
      nThr = omp_get_num_threads();
    }
  }
#endif
  if(inObj == NULL)
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if(inObj->domain.core == NULL)
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if(inObj->values.core == NULL)
  {
    errNum = WLZ_ERR_VALUES_NULL;
  }
  else
  {
    switch(inObj->type)
    {
      case WLZ_2D_DOMAINOBJ:
        dim = 2;
	break;
      case WLZ_3D_DOMAINOBJ:
        dim = 3;
        break;
      default:
        errNum = WLZ_ERR_OBJECT_TYPE;
	break;
    }
  }
  if((errNum == WLZ_ERR_NONE) && (gType == WLZ_GREY_ERROR))
  {
    gType = WlzGreyTypeFromObj(inObj, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if(errNum == WLZ_ERR_NONE)
    {
      switch(gType)
      {
        case WLZ_GREY_INT:    /* FALLTHROUGH */
        case WLZ_GREY_SHORT:  /* FALLTHROUGH */
        case WLZ_GREY_UBYTE:  /* FALLTHROUGH */
        case WLZ_GREY_FLOAT:  /* FALLTHROUGH */
        case WLZ_GREY_DOUBLE:
	  break;
        default:
	  errNum = WLZ_ERR_GREY_TYPE;
	  break;
      }
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    bBox = WlzBoundingBox3I(inObj, &errNum);
    if(errNum == WLZ_ERR_NONE)
    {
      vBufSz.vtX = bBox.xMax - bBox.xMin + 1;
      vBufSz.vtY = bBox.yMax - bBox.yMin + 1;
      if(dim == 3)
      {
	vBufSz.vtZ = bBox.zMax - bBox.zMin + 1;
      }
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    vSz = ALG_MAX3(vBufSz.vtX, vBufSz.vtY, vBufSz.vtZ);
    if(((iBuf = (double **)AlcMalloc(sizeof(double *) * 2 * nThr)) == NULL) ||
       ((vBuf = (double *)AlcMalloc(sizeof(double) * 2 * nThr * vSz)) == NULL))
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
    else
    {
      int	idt;

      rBuf = iBuf + nThr;
      for(idt = 0; idt < nThr; ++idt)
      {
        iBuf[idt] = vBuf + (idt * vSz);
	rBuf[idt] = vBuf + ((nThr + idt) * vSz);
      }
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    /* Convolve the object values. */
    if(direc.vtX)
    {
      rnObj = WlzSepFilterX(inObj, dim, nThr,
			    iBuf, rBuf, cBufSz.vtX, cBuf[0],
			    pad, padVal, &errNum);
    }
    if((errNum == WLZ_ERR_NONE) && direc.vtY)
    {
      WlzObject *tObj;

      tObj = WlzSepFilterY((rnObj)? rnObj: inObj, dim, nThr,
                            iBuf, rBuf, cBufSz.vtY, cBuf[1],
			    pad, padVal, &errNum);
      (void )WlzFreeObj(rnObj);
      rnObj = tObj;
    }
    if((errNum == WLZ_ERR_NONE) && (dim == 3) && direc.vtZ)
    {
      WlzObject *tObj;

      tObj = WlzSepFilterZ((rnObj)? rnObj: inObj, bBox, nThr,
                            iBuf, rBuf, cBufSz.vtZ, cBuf[2],
			    pad, padVal, &errNum);
      (void )WlzFreeObj(rnObj);
      rnObj = tObj;
    }
  }
  if((errNum == WLZ_ERR_NONE) && (rnObj != NULL) && (gType != WLZ_GREY_DOUBLE))
  {
    WlzObject *tObj;

    /* Convert object values to the required grey type. */
    tObj = WlzConvertPix((rnObj)? rnObj: inObj, gType, &errNum);
    (void )WlzFreeObj(rnObj);
    rnObj = tObj;
  }
  if(errNum != WLZ_ERR_NONE)
  {
    (void )WlzFreeObj(rnObj);
    rnObj = NULL;
  }
  AlcFree(iBuf);
  AlcFree(vBuf);
  return(rnObj);
}
Exemplo n.º 7
0
/*!
* \return	New 3D domain object with corresponding WLZ_GREY_RGBA values.
* \ingroup      WlzValuesUtils
* \brief	Creates a WLZ_GREY_RGBA valued object from the given compound
* 		array. This is a static function which will always be called
* 		with valid parameters so they aren't checked.
* \param	cObj			Compound array object.
* \param	cSpc 			The colour space.
* \param	dstErr			Destination error pointer may be NULL.
*/
static WlzObject *WlzCompoundToRGBA3D(WlzCompoundArray *cObj,
  				WlzRGBAColorSpace cSpc, WlzErrorNum *dstErr)
{
  WlzIBox3 	bBox;
  WlzDomain	dom;
  WlzValues	val;
  WlzPixelV	bgd;
  WlzObject	*rObj = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  
  dom.core = NULL;
  val.core = NULL;
  bgd.v.rgbv = 0;
  bgd.type = WLZ_GREY_RGBA;
  bBox = WlzBoundingBox3I((WlzObject *)cObj, &errNum);
  if(errNum == WLZ_ERR_NONE)
  {
    dom.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN, bBox.zMin, bBox.zMax,
		               bBox.yMin, bBox.yMax, bBox.xMin, bBox.xMax,
			       &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    val.vox = WlzMakeVoxelValueTb(WLZ_VOXELVALUETABLE_GREY,
                                  bBox.zMin, bBox.zMax, bgd, NULL,
			          &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    rObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, dom, val, NULL, NULL, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    int		idP,
    		nPl;

    nPl = bBox.zMax - bBox.zMin + 1;
    for(idP = 0; idP < nPl; ++idP)
    {
      if(errNum == WLZ_ERR_NONE)
      {
	int	idC;
	WlzObject *rObj2 = NULL;
	WlzCompoundArray *cObj2 = NULL;
	WlzErrorNum errNum2 = WLZ_ERR_NONE;

	cObj2 = WlzMakeCompoundArray(WLZ_COMPOUND_ARR_2, 1, cObj->n,
	                             NULL, WLZ_2D_DOMAINOBJ, &errNum2);

	idC = 0;
	while((errNum2 == WLZ_ERR_NONE) && (idC < cObj->n))
	{
	  int		idP2,
	  		nPl2;
	  WlzDomain	dom2;
	  WlzValues	val2;

	  dom2.core = NULL;
	  val2.core = NULL;
	  if((cObj->o[idC] != NULL) &&
	     (cObj->o[idC]->type == WLZ_3D_DOMAINOBJ))
	  {
	    idP2 = bBox.zMin + idP - cObj->o[idC]->domain.p->plane1;
	    nPl2 = cObj->o[idC]->domain.p->lastpl - 
	           cObj->o[idC]->domain.p->plane1 + 1;
	    if((idP2 >= 0) && (idP2 <= nPl2))
	    {
	      dom2 = *(cObj->o[idC]->domain.p->domains + idP2);
	      val2 = *(cObj->o[idC]->values.vox->values + idP2);
	    }
	  }
	  cObj2->o[idC] = (dom2.core == NULL)?
	                  WlzMakeEmpty(&errNum2):
	                  WlzMakeMain(WLZ_2D_DOMAINOBJ, dom2, val2,
	                              NULL, NULL, &errNum2);
	  ++idC;
	}
	if(errNum2 == WLZ_ERR_NONE)
	{
	  rObj2 = WlzCompoundToRGBA2D(cObj2, cSpc, &errNum2);
	}
	if(errNum2 == WLZ_ERR_NONE)
	{
	  dom.p->domains[idP] = WlzAssignDomain(rObj2->domain, NULL);
	  val.vox->values[idP] = WlzAssignValues(rObj2->values, NULL);
	}
	(void )WlzFreeObj(rObj2);
	(void )WlzFreeObj((WlzObject *)cObj2);
	if(errNum2 != WLZ_ERR_NONE)
	{
	  errNum = errNum2;
	}
      }
    }
  }
  if(errNum != WLZ_ERR_NONE)
  {
    if(rObj != NULL)
    {
      (void )WlzFreeObj(rObj);
      rObj = NULL;
    }
    else
    {
      (void )WlzFreePlaneDomain(dom.p);
      (void )WlzFreeVoxelValueTb(val.vox);
    }
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(rObj);
}