Esempio n. 1
0
/*!
* \return	Error code.
* \ingroup	AlcArray
* \brief	Allocates a 1 dimensional zero'd array of pointers to void.
* \note		Should be free'd using AlcFree().
* \note		Array size is limited only by address space.
* \param	dest 			Destination for allocated array
*					pointer.
* \param	mElem 	 		Number of elements in array.
*/
AlcErrno	AlcPtr1Calloc(void ***dest, size_t mElem)
{
  AlcErrno	alcErrno = ALC_ER_NONE;
  
  /* Template doesn't work for pointer types. */
  if((dest) == NULL)
  {
    alcErrno = ALC_ER_NULLPTR;
  }
  else if(mElem < 1)
  {
    alcErrno = ALC_ER_NUMELEM;
  }
  else if((*(dest) = (void **)AlcCalloc(mElem, sizeof(void *))) == NULL)
  {
    alcErrno = ALC_ER_ALLOC;
  }
  if(alcErrno != ALC_ER_NONE)
  {
    if(dest)
    {
      *(dest) = NULL;
    }
  }
  return(alcErrno);
}
Esempio n. 2
0
/*!
* \return	New Amira file header data structure or NULLon error.
* \ingroup	WlzExtFF
* \brief	Allocates a new Amira file header data structure with
*		all fields cleared.
* \param        <void>
*/
static WlzEffAmHead *WlzEffAmNewHead(void)
{
  WlzEffAmHead	*head;

  head = AlcCalloc(1, sizeof(WlzEffAmHead));
  return(head);
}
Esempio n. 3
0
/*!
* \return	Error code.
* \ingroup	AlcArray
* \brief	Allocates a 3 dimensional array of pointers to void.
* \note		Should be free'd using Alc3Free().
* \note		Array size is limited only by address space.
* \param	dest 			Destination for allocated array
*					pointer.
* \param	mElem 	 		Number of 2D arrays.
* \param	nElem 	 		Number of 1D arrays.
* \param	oElem 	 		Number of elements in each 1D
*					array.
*/
AlcErrno	AlcPtr3Calloc(void *****dest, size_t mElem, size_t nElem,
			       size_t oElem)
{
  size_t	index0,
  		index1;
  void		**dump0 = NULL,
  		***dump1 = NULL,
		****dump2 = NULL;
  AlcErrno	alcErrno = ALC_ER_NONE;

  if((dest) == NULL)
  {
    alcErrno = ALC_ER_NULLPTR;
  }
  else if((mElem < 1) || (nElem < 1) || (oElem < 1))
  {
    alcErrno = ALC_ER_NUMELEM;
  }
  else if(((dump0 = (void **)AlcCalloc(mElem * nElem * oElem,
  				       sizeof(void *))) == NULL) ||
          ((dump1 = (void ***)AlcMalloc(mElem * nElem *
	                                sizeof(void **))) == NULL) ||
          ((dump2 = (void ****)AlcMalloc(mElem * sizeof(void ***))) == NULL))
  {
    alcErrno = ALC_ER_ALLOC;
  }
  if(alcErrno == ALC_ER_NONE)
  {
    *(dest) = dump2;
    for(index0 = 0; index0 < mElem; ++index0)
    {
      for(index1=0; index1 < nElem; ++index1)
      {
	dump1[index1] = dump0;
	dump0 += oElem;
      }
      (*(dest))[index0] = dump1;
      dump1 += nElem;
    }
  }
  else
  {
    if(dest)
    {
      *(dest) = NULL;
    }
    AlcFree(dump2);
    AlcFree(dump1);
    AlcFree(dump0);
  }
  return(alcErrno);
}
Esempio n. 4
0
/*!
* \return     	KD-tree data structure, or NULL on error.
* \ingroup	AlcKDTree
* \brief        Creates a KD-tree data structure.
* \param        type			Type of tree node key.
* \param	dim			Dimension of tree (must be >= 1).
* \param	tol			Tollerance for key comparision,
*					only used if the tree has floating
*					point keys. If the tolerance is
*					negative it is set to a default
*					value.
* \param	nNodes			Expected number of nodes in the
*					tree,  0 if unknown. This
*					can be used to optimise node
*					allocation.
* \param        dstErr		    	Destination pointer for error
*                                       code, may be NULL.
*/
AlcKDTTree	*AlcKDTTreeNew(AlcPointType type, int dim, double tol,
			       size_t nNodes, AlcErrno *dstErr)
{
  size_t	keySz;
  AlcKDTTree	*tree = NULL;
  AlcErrno	errNum = ALC_ER_NONE;
  const size_t	minNodeBlockSz = 1024;
  const double	defTol = 1.0E-06;

  if(dim < 1)
  {
    errNum = ALC_ER_PARAM;
  }
  else
  {
    switch(type)
    {
      case ALC_POINTTYPE_INT:
	keySz = sizeof(int) * dim;
	break;
      case ALC_POINTTYPE_DBL:
	keySz = sizeof(double) * dim;
	break;
      default:
	errNum = ALC_ER_PARAM;
	break;
    }
  }
  if(errNum == ALC_ER_NONE)
  {
    if((tree = (AlcKDTTree *)AlcCalloc(1, sizeof(AlcKDTTree))) == NULL)
    {
      errNum = ALC_ER_ALLOC;
    }
    else
    {
      tree->type = type;
      tree->dim = dim;
      tree->keySz = keySz;
      tree->tol = (tol < 0.0)? defTol: tol;
      if((tree->nodeBlockSz = nNodes / 10) < minNodeBlockSz)
      {
	tree->nodeBlockSz = minNodeBlockSz;
      }
    }
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(tree);
}
/*!
* \return	New affine transform initialized to the identity transform.
* \ingroup	WlzTransform
* \brief	Allocates and initialises space for a 2D or 3D affine
*               transform. Sufficient space is always allocated for a
*               3D transform.
*		The transform should be freed using WlzFreeAffineTransform().
* \param	type			Transform type.
* \param	dstErr			Destination error pointer, may
*                                       be null.
*/
WlzAffineTransform *WlzMakeAffineTransform(WlzTransformType type,
  				           WlzErrorNum *dstErr)
{
  WlzAffineTransform *trans=NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  switch(type)
  {
    case WLZ_TRANSFORM_2D_AFFINE:
    case WLZ_TRANSFORM_2D_REG:
    case WLZ_TRANSFORM_2D_TRANS:
    case WLZ_TRANSFORM_2D_NOSHEAR:
    case WLZ_TRANSFORM_3D_AFFINE:
    case WLZ_TRANSFORM_3D_REG:
    case WLZ_TRANSFORM_3D_TRANS:
    case WLZ_TRANSFORM_3D_NOSHEAR:
      break;
    default:
      errNum = WLZ_ERR_TRANSFORM_TYPE;
      break;
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if(((trans = (WlzAffineTransform *)
                 AlcCalloc(1, sizeof(WlzAffineTransform))) == NULL) ||
       (AlcDouble2Calloc(&trans->mat, 4, 4) != ALC_ER_NONE))
    {
      if(trans)
      {
        AlcFree(trans);
	trans = NULL;
      }
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    trans->type = type;
    /* Initialize to the identity transform */
    trans->mat[0][0] = 1.0;
    trans->mat[1][1] = 1.0;
    trans->mat[2][2] = 1.0;
    trans->mat[3][3] = 1.0;
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(trans);
}
Esempio n. 6
0
/*!
* \return	Error code.
* \ingroup	AlcArray
* \brief	Allocates a 2 dimensional zero'd array of pointers to void.
* \note		Should be free'd using Alc2Free().
* \note		Array size is limited only by address space.
* \param	dest 	 		Destination for allocated array
*					pointer.
* \param	mElem 	 		Number of 1D arrays.
* \param	nElem 	 		Number of elements in each 1D
*					array.
*/
AlcErrno	AlcPtr2Calloc(void ****dest, size_t mElem, size_t nElem)
{
  size_t	index;
  void		**dump0 = NULL;
  void		***dump1 = NULL;
  AlcErrno	alcErrno = ALC_ER_NONE;
 
  /* Template doesn't work for pointer types. */
  if(dest == NULL)
  {
    alcErrno = ALC_ER_NULLPTR;
  }
  else if((mElem < 1) || (nElem < 1))
  {
    alcErrno = ALC_ER_NUMELEM;
  }
  else if(((dump0 = (void **)AlcCalloc(mElem * nElem,
  				       sizeof(void *))) == NULL) ||
          ((dump1 = (void ***)AlcMalloc(mElem * sizeof(void **))) == NULL))
  {
    alcErrno = ALC_ER_ALLOC;
  }
  if(alcErrno == ALC_ER_NONE)
  {
    *dest = dump1;
    for(index = 0; index < mElem; ++index)
    {
      (*dest)[index] = dump0;
      dump0 += nElem;
    }
  }
  else
  {
    if(dest)
    {
      *dest = NULL;
    }
    if(dump0)
    {
      AlcFree(dump0);
    }
    if(dump1)
    {
      AlcFree(dump1);
    }
  }
  return(alcErrno);
}
Esempio n. 7
0
/*!
* \return	Duplicated section, NULL on error.
* \ingroup	Reconstruct
* \brief	Duplicates the given section.
* \param	sec			Section to be duplicated.
*/
RecSection	*RecSecDup(RecSection *sec)
{
  RecSection	*newSec = NULL;
  WlzErrorNum	wlzErr = WLZ_ERR_NONE;

  REC_DBG((REC_DBG_SEC|REC_DBG_LVL_FN|REC_DBG_LVL_1),
	  ("RecSecDup FE 0x%lx\n",
	   (unsigned long )sec));
  if(sec)
  {
    if(((newSec = (RecSection *)AlcCalloc(1, sizeof(RecSection))) != NULL) &&
       sec->imageFile &&
       ((newSec->imageFile = AlcStrDup(sec->imageFile)) != NULL) &&
       sec->transform &&
       ((newSec->transform = WlzAssignAffineTransform(
			 WlzAffineTransformFromMatrix(sec->transform->type,
       					      sec->transform->mat, &wlzErr),
					      NULL)) != NULL) &&
       (wlzErr == WLZ_ERR_NONE))
    {
      newSec->index = sec->index;
      newSec->iterations = sec->iterations;
      newSec->correl = sec->correl;
    }
    else
    {
      if(newSec)
      {
        if(newSec->imageFile)
	{
	  AlcFree(newSec->imageFile);
	}
        AlcFree(newSec);
        newSec = NULL;
      }
    }
  }
  REC_DBG((REC_DBG_SEC|REC_DBG_LVL_FN|REC_DBG_LVL_1),
	  ("RecSecDup FX 0x%lx\n",
	   (unsigned long )newSec));
  return(newSec);
}
Esempio n. 8
0
/*!
* \return	New secton list or NULL on error.
* \ingroup	Reconstruct
* \brief	Creates a new empty section list with default settings.
* \param	dstErr			Destination error pointer, may
*                                       be NULL.
*/
RecSectionList	*RecSecNewSectionList(RecError *dstErr)
{
  RecSectionList *newSecList = NULL;
  RecError	errFlag = REC_ERR_NONE;

  if((newSecList = (RecSectionList *)
  		   AlcCalloc(1, sizeof(RecSectionList))) == NULL)
  {
    errFlag = REC_ERR_MALLOC;
  }
  else
  {
    /* Set fields to default values. */
    newSecList->list = NULL;
    newSecList->attributes.trMode = REC_TRMODE_REL;
    newSecList->attributes.currentItem = NULL;
    RecSecRecSetDefaults(&(newSecList->reconstruction));
  }
  if(dstErr)
  {
    *dstErr = errFlag;
  }
  return(newSecList);
}
/*! 
* \ingroup      WlzAllocation
* \brief        Make in interval values table to match the input object
The table will have linkcount set to zero.
*
* \return       New interval values table.
* \param    type	Required table type.
* \param    obj	Input object.
* \param    bckgrnd	Values table background value.
* \param    dstErr	Error return.
* \par Constraints
 The woolz object type must resolve to WLZ_GREY_TAB_INTL using
 WlzGreyTableTypeToTableType()or an error will be reported and NULL
 returned.  For historical reasons
 the type encodes the table type as well as the grey-value type.
 
* \par      Source:
*                WlzMakeIntervalValues.c
*/
WlzIntervalValues *
WlzMakeIntervalValues(WlzObjectType	type,
		      WlzObject 	*obj,
		      WlzPixelV		bckgrnd,
		      WlzErrorNum	*dstErr)
{
  WlzValues 		v;
  WlzValueIntervalLine 	*vil;
  WlzValueLine 		*val;
  WlzGreyP 		g;
  WlzIntervalWSpace 	iwsp;
  WlzIntervalDomain 	*idom;
  WlzErrorNum		errNum=WLZ_ERR_NONE;

  /* check the values table type */
  v.i = NULL;
  (void) WlzGreyTableTypeToTableType(type, &errNum);
  if( errNum == WLZ_ERR_NONE ){
    (void) WlzGreyTableTypeToGreyType(type, &errNum);
  }

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

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

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

    case WLZ_EMPTY_OBJ:
    default:
      errNum = WLZ_ERR_DOMAIN_TYPE;
      break;
    }
  }

  /*
   * allocate space for basic, per line and per interval structures
   */
  if((errNum == WLZ_ERR_NONE) &&
     ((v.i = (WlzIntervalValues *) 
      AlcCalloc(sizeof(WlzIntervalValues)
		+ (idom->lastln - idom->line1 + 1)
		* sizeof(WlzValueIntervalLine) +
		WlzIntervalCount(idom, NULL) * sizeof(WlzValueLine), 1))
     == NULL) ){
    errNum = WLZ_ERR_MEM_ALLOC;
  }

  if( errNum == WLZ_ERR_NONE ){
    vil = (WlzValueIntervalLine *) (v.i + 1);
    val = (WlzValueLine *) (vil + idom->lastln - idom->line1 + 1);
    v.i->bckgrnd = bckgrnd;
    switch( WlzGreyTableTypeToGreyType(type, NULL) ){

    case WLZ_GREY_INT:
      g.inp = (int *) AlcCalloc(WlzArea(obj, NULL), sizeof(int));
      break;

    case WLZ_GREY_SHORT:
      g.shp = (short *) AlcCalloc(WlzArea(obj, NULL), sizeof(short));
      break;

    case WLZ_GREY_UBYTE:
      g.ubp = (WlzUByte *) AlcCalloc(WlzArea(obj, NULL), sizeof(WlzUByte));
      break;

    case WLZ_GREY_FLOAT:
      g.flp = (float *) AlcCalloc(WlzArea(obj, NULL), sizeof(float));
      break;

    case WLZ_GREY_DOUBLE:
      g.dbp = (double *) AlcCalloc(WlzArea(obj, NULL), sizeof(double));
      break;

    case WLZ_GREY_RGBA:
      g.rgbp = (WlzUInt *) AlcCalloc(WlzArea(obj, NULL), sizeof(WlzUInt));
      break;

    default:
      WlzFreeValues( v );
      v.i = NULL;
      errNum = WLZ_ERR_GREY_TYPE;
      break;
    }
  }
  if( (errNum == WLZ_ERR_NONE) && (g.inp == NULL) ){
    WlzFreeValues( v );
    v.i = NULL;
    errNum = WLZ_ERR_MEM_ALLOC;
  }

  /*
   * fill in structure values and initialise scanning
   */
  if( errNum == WLZ_ERR_NONE ){
    v.i->type = type;
    v.i->freeptr = AlcFreeStackPush(v.i->freeptr, (void *)g.inp, NULL);
    v.i->line1 = idom->line1;
    v.i->lastln = idom->lastln;
    v.i->kol1 = idom->kol1;
    v.i->width = idom->lastkl - idom->kol1 + 1;
    v.i->vil = vil;
    v.i->linkcount = 0;
    v.i->original_table.core = NULL;
    vil--;
    if((errNum = WlzInitRasterScan(obj, &iwsp,
    				   WLZ_RASTERDIR_ILIC)) != WLZ_ERR_NONE ){
      WlzFreeValues( v );
      v.i = NULL;
    }
  }

  /*
   * fill in the line and interval structures,
     note grey-type already checked.
   */
  if( errNum == WLZ_ERR_NONE ){
    while((errNum == WLZ_ERR_NONE) &&
          (errNum = WlzNextInterval(&iwsp)) == WLZ_ERR_NONE){
      if (iwsp.nwlpos != 0) {
	vil += iwsp.nwlpos;
	vil->vtbint = val;
      }
      vil->nintvs++;
      val->vkol1 = iwsp.lftpos - v.i->kol1;
      val->vlastkl = iwsp.rgtpos - v.i->kol1;
      switch( WlzGreyTableTypeToGreyType(type, NULL) ){

      case WLZ_GREY_INT:
	val->values.inp = g.inp;
	g.inp += iwsp.colrmn;
	break;

      case WLZ_GREY_SHORT:
	val->values.shp = g.shp;
	g.shp += iwsp.colrmn;
	break;

      case WLZ_GREY_UBYTE:
	val->values.ubp = g.ubp;
	g.ubp += iwsp.colrmn;
	break;

      case WLZ_GREY_FLOAT:
	val->values.flp = g.flp;
	g.flp += iwsp.colrmn;
	break;

      case WLZ_GREY_DOUBLE:
	val->values.dbp = g.dbp;
	g.dbp += iwsp.colrmn;
	break;

      case WLZ_GREY_RGBA:
	val->values.rgbp = g.rgbp;
	g.rgbp += iwsp.colrmn;
	break;

      default:
        errNum = WLZ_ERR_GREY_TYPE;
	break;
      }
      val++;
    }
    switch( errNum ){
    case WLZ_ERR_NONE:
    case WLZ_ERR_EOO:
      errNum = WLZ_ERR_NONE;
      break;
    default:
      WlzFreeValues( v );
      v.i = NULL;
      break;
    }
  }

  if( dstErr ){
    *dstErr = errNum;
  }
  return(v.i);
}
Esempio n. 10
0
/*!
* \return	Affine transform which brings the two objects into register.
* \ingroup	WlzRegistration
* \brief	Registers the two given 2D domain objects using a
*               frequency domain cross correlation.  An affine transform
*               is computed, which when applied to the source object
*               takes it into register with the target object.
*               A resolution pyramid is built from the given objects
*               and used to register the objects, progressing from
*               a low resolution towards the full resolution objects.
* \param	tObj			The target object. Must have
*                                       been assigned.
* \param	sObj			The source object to be
*                                       registered with target object.
* \param	initTr			Initial affine transform
*                                       to be applied to the source
*                                       object prior to registration.
*                                       Only translations in x and y
*                                       and rotation about the z axis
*                                       are used. May be NULL which is
*                                       equivalent to an identity transform.
* \param	trType			Required transform type.
* \param	maxTran			Maximum translation.
* \param	maxRot			Maximum rotation.
* \param	maxItr			Maximum number of iterations,
*                                       if \f$leq\f$ 0 then infinite iterations
*                                       are allowed.
* \param	winFn			Window function.
* \param	noise			Use Gaussian noise if non-zero.
* \param	dstConv			Destination ptr for the
*                                       convergence flag (non zero
*                                       on convergence), may be NULL.
* \param	dstCCor			Destination ptr for the cross
*                                       correlation value, may be NULL.
* \param	dstErr			Destination error pointer,
*                                       may be NULL.
*/
static WlzAffineTransform *WlzRegCCorObjs2D(WlzObject *tObj, WlzObject *sObj,
					    WlzAffineTransform *initTr,
					    WlzTransformType trType,
					    WlzDVertex2 maxTran, double maxRot,
					    int maxItr,
					    WlzWindowFnType winFn, int noise,
					    int *dstConv, double *dstCCor,
					    WlzErrorNum *dstErr)
{
  int		tI1,
		samIdx,
  		nSam,
		conv;
  double	cCor,
  		rot0,
		rot1,
		sMaxRot;
  WlzPixelV	gV[4];
  WlzIVertex2	tIV0,
  		tIV1;
  WlzIVertex3	samFacV;
  WlzDVertex2	tran0,
  		tran1,
		sMaxTran;
  WlzIBox2	sBox,
  		tBox;
  int		*samFac = NULL;
  WlzObject	**sTObj = NULL,
  		**sSObj = NULL;
  WlzAffineTransform *samRegTr0 = NULL,
  		*samRegTr1 = NULL,
		*regTr = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  WlzAffineTransformPrim trPrim;
  WlzPixelV	zeroBgd;
  const int	samFacStep = 4,
  		maxSam = 16,
  		minSamSz = 100;

  zeroBgd.type = WLZ_GREY_INT;
  zeroBgd.v.inv = 0;
  gV[0].type = gV[1].type = gV[2].type = gV[3].type = WLZ_GREY_DOUBLE;
  /* Compute the number of x4 subsampling operations to use. */
  sBox = WlzBoundingBox2I(sObj, &errNum);
  if(errNum == WLZ_ERR_NONE)
  {
    tBox = WlzBoundingBox2I(tObj, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    tIV0.vtX = sBox.xMax - sBox.xMin + 1;
    tIV0.vtY = sBox.yMax - sBox.yMin + 1;
    tIV1.vtX = tBox.xMax - tBox.xMin + 1;
    tIV1.vtY = tBox.yMax - tBox.yMin + 1;
    tIV0.vtX = WLZ_MIN(tIV0.vtX, tIV1.vtX);
    tIV0.vtY = WLZ_MIN(tIV0.vtY, tIV1.vtY);
    nSam = 1;
    tI1 = WLZ_MIN(tIV0.vtX, tIV0.vtY);
    while((nSam < maxSam) && (tI1 > minSamSz))
    {
      ++nSam;
      tI1 /= samFacStep;
    }
  }
  /* Allocate space for subsampled objects. */
  if(errNum == WLZ_ERR_NONE)
  {
    if(((samFac = (int *)AlcMalloc(nSam * sizeof(int))) == NULL) ||
       ((sTObj = (WlzObject **)AlcCalloc(nSam,
    				         sizeof(WlzObject *))) == NULL) ||
       ((sSObj = (WlzObject **)AlcCalloc(nSam,
       					 sizeof(WlzObject *))) == NULL))
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  /* Compute subsampled objects and make sure the background value is zero. */
  if(errNum == WLZ_ERR_NONE)
  {
    samIdx = 0;
    *samFac = 1;
    samFacV.vtX = samFacV.vtY = samFacStep;
    *(sTObj + 0) = WlzAssignObject(tObj, NULL);
    *(sSObj + 0) = WlzAssignObject(sObj, NULL);
    while((errNum == WLZ_ERR_NONE) && (++samIdx < nSam))
    {
      *(samFac + samIdx) = *(samFac + samIdx - 1) * samFacStep;
      *(sTObj + samIdx) = WlzAssignObject(
      			  WlzSampleObj(*(sTObj + samIdx - 1), samFacV,
      				       WLZ_SAMPLEFN_GAUSS, &errNum), NULL);
      if(errNum == WLZ_ERR_NONE)
      {
	(void )WlzSetBackground(*(sTObj + samIdx), zeroBgd);
        *(sSObj + samIdx) = WlzAssignObject(
			    WlzSampleObj(*(sSObj + samIdx - 1), samFacV,
			       	         WLZ_SAMPLEFN_GAUSS, &errNum), NULL);
      }
      if(errNum == WLZ_ERR_NONE)
      {
        (void )WlzSetBackground(*(sSObj + samIdx), zeroBgd);
      }
    }
  }
  /* Register the subsampled objects starting with the lowest resolution
   * (highest subsampling) and progressing to the unsampled objects. */
  if(errNum == WLZ_ERR_NONE)
  {
    if(initTr == NULL)
    {
      rot0 = 0.0;
      tran0.vtX = 0.0;
      tran0.vtY = 0.0;
    }
    else
    {
      errNum = WlzAffineTransformPrimGet(initTr, &trPrim);
      rot0 = trPrim.theta;
      tran0.vtX = trPrim.tx;
      tran0.vtY = trPrim.ty;
    }
    conv = 1;
    samIdx = nSam - 1;
    sMaxRot = maxRot;
    sMaxTran.vtX =  maxTran.vtX / *(samFac + nSam - 1);
    sMaxTran.vtY =  maxTran.vtY / *(samFac + nSam - 1);
    while((errNum == WLZ_ERR_NONE) && conv && (samIdx >= 0))
    {
      /* Compute initial transform. */
      rot1 = rot0;
      tran1.vtX = tran0.vtX / *(samFac + samIdx);
      tran1.vtY = tran0.vtY / *(samFac + samIdx);
      samRegTr0 = WlzAffineTransformFromPrimVal(WLZ_TRANSFORM_2D_AFFINE,
      					        tran1.vtX, tran1.vtY, 0.0, 1.0, 
						rot1, 0.0, 0.0, 0.0, 0.0, 0,
						&errNum);
      /* Compute registration transform. */
      if(errNum == WLZ_ERR_NONE)
      {
	samRegTr1 = WlzRegCCorObjs2D1(*(sTObj + samIdx), *(sSObj + samIdx),
				      samRegTr0,
				      trType, sMaxTran, sMaxRot, maxItr,
				      winFn, noise,
				      &conv, &cCor, &errNum);
        
      }
      if(samRegTr0)
      {
        (void )WlzFreeAffineTransform(samRegTr0);
	samRegTr0 = NULL;
      }
      if(samRegTr1)
      {
        samRegTr0 = samRegTr1;
	samRegTr1 = NULL;
      }
      if(errNum == WLZ_ERR_NONE)
      {
        errNum = WlzAffineTransformPrimGet(samRegTr0, &trPrim);
      }
      if(errNum == WLZ_ERR_NONE)
      {
	rot0 = trPrim.theta;
	tran0.vtX = trPrim.tx * *(samFac + samIdx);
	tran0.vtY = trPrim.ty * *(samFac + samIdx);
      }
      /* Set registration limits. */
      sMaxRot = WLZ_M_PI / 24.0;
      sMaxTran.vtX = samFacStep * 3;
      sMaxTran.vtY = samFacStep * 3;
      --samIdx;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if(dstConv)
    {
      *dstConv = conv;
    }
    if(dstCCor)
    {
      *dstCCor = cCor;
    }
    regTr = samRegTr0;
  }
  AlcFree(samFac);
  /* Free subsampled objects. */
  if(sTObj)
  {
    for(samIdx = 0; samIdx < nSam; ++samIdx)
    {
      (void )WlzFreeObj(*(sTObj + samIdx));
    }
    AlcFree(sTObj);
  }
  if(sSObj)
  {
    for(samIdx = 0; samIdx < nSam; ++samIdx)
    {
      (void )WlzFreeObj(*(sSObj + samIdx));
    }
    AlcFree(sSObj);
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(regTr);
}
Esempio n. 11
0
/*!
* \return	Woolz object read from jpeg image.
* \ingroup	WlzExtFF
* \brief	Reads a jpeg image frm the given file stream and returns a
*		Woolz object.
* \param	fP			Given file stream.
* \param	dstErr			Destination error pointer, may be NULL.
*/
WlzObject *WlzEffReadObjJpeg(
  FILE 		*fP,
  WlzErrorNum 	*dstErr)
{
  WlzObject	*rtnObj=NULL;
  struct 	jpeg_decompress_struct cinfo;
  struct 	my_error_mgr jerr;
  JSAMPARRAY 	buffer;		/* Output row buffer */
  int 		row_stride;	/* physical row width in output buffer */
  int		width, height;
  /* int		depth; */
  int		wlzDepth;
  WlzGreyType	newpixtype;
  WlzPixelV	bckgrnd;
  int		i, rOff;
  WlzGreyP	wlzData;
  WlzErrorNum	errNum=WLZ_ERR_NONE;

  /* check input */
  if( fP == NULL ){
    errNum = WLZ_ERR_PARAM_NULL;
  }

  /* We set up the normal JPEG error routines, then override error_exit. */
  if( errNum == WLZ_ERR_NONE ){
    cinfo.err = jpeg_std_error(&jerr.pub);
    jerr.pub.error_exit = my_error_exit;
    /* Establish the setjmp return context for my_error_exit to use. */
    if (setjmp(jerr.setjmp_buffer)) {
      /* If we get here, the JPEG code has signaled an error.
       * We need to clean up the JPEG object, close the input file, and return.
       */
      jpeg_destroy_decompress(&cinfo);
      if( rtnObj ){
	WlzFreeObj(rtnObj);
	rtnObj = NULL;
      }
      errNum = WLZ_ERR_READ_INCOMPLETE;
    }
  }

  if( errNum == WLZ_ERR_NONE ){
    /* initialize the JPEG decompression object. */
    jpeg_create_decompress(&cinfo);

    /* specify data source (eg, a file) */
    jpeg_stdio_src(&cinfo, fP);

    /* read file parameters with jpeg_read_header() */
    (void) jpeg_read_header(&cinfo, TRUE);
    /* We can ignore the return value from jpeg_read_header since
     *   (a) suspension is not possible with the stdio data source, and
     *   (b) we passed TRUE to reject a tables-only JPEG file as an error.
     * See libjpeg.doc for more info.
     */

    /* default set parameters for decompression */
    (void) jpeg_start_decompress(&cinfo);

    /* JSAMPLEs per row in output buffer */
    row_stride = cinfo.output_width * cinfo.output_components;
    /* Make a one-row-high sample array that will go away when done with image */
    buffer = (*cinfo.mem->alloc_sarray)
      ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);

    /* create the appropriate woolz object, read scanlines and copy data */
    switch( cinfo.jpeg_color_space ){
    default:
    case JCS_UNKNOWN:
      errNum = WLZ_ERR_READ_INCOMPLETE;
      break;

    case JCS_GRAYSCALE:
      bckgrnd.type = WLZ_GREY_UBYTE;
#if BITS_IN_JSAMPLE == 8
      if( cinfo.data_precision != 8 ){
	errNum = WLZ_ERR_FILE_FORMAT;
      }
      else {
	wlzDepth = sizeof(char);
	newpixtype = WLZ_GREY_UBYTE;
	/* depth = cinfo.num_components * 8; */
	bckgrnd.v.ubv = 0;
      }
#endif /* BITS_IN_SAMPLE == 8 */
#if BITS_IN_JSAMPLE == 12
      if( cinfo.data_precision != 12 ){
	errNum = WLZ_ERR_FILE_FORMAT;
      }
      else {
	wlzDepth = sizeof(short);
	newpixtype = WLZ_GREY_SHORT;
	/* depth = cinfo.num_components * 12; */
	bckgrnd.v.shv = 0;
      }
#endif /* BITS_IN_SAMPLE == 12 */
      break;

    case JCS_YCbCr:
    case JCS_CMYK:
    case JCS_YCCK:
    case JCS_RGB:
      bckgrnd.type = WLZ_GREY_RGBA;
      cinfo.out_color_space = JCS_RGB;
#if BITS_IN_JSAMPLE == 8
      if( cinfo.data_precision != 8 ){
	errNum = WLZ_ERR_FILE_FORMAT;
      }
      else {
	wlzDepth = sizeof(int);
	newpixtype = WLZ_GREY_RGBA;
	/* depth = cinfo.num_components * 8; */
	bckgrnd.v.inv = 0;
      }
#endif /* BITS_IN_SAMPLE == 8 */
#if BITS_IN_JSAMPLE == 12
      errNum = WLZ_ERR_UNIMPLEMENTED;
#endif /* BITS_IN_SAMPLE == 8 */
      break;

    }

    if( errNum == WLZ_ERR_NONE ){
      /* make the woolz object */
      width = cinfo.image_width;
      height = cinfo.image_height;
      if((wlzData.ubp = (WlzUByte *)AlcCalloc(width*height,
                                               wlzDepth)) != NULL){
	if((rtnObj = WlzMakeRect(0, height-1, 0, width-1, newpixtype,
				  wlzData.inp, bckgrnd,
				  NULL, NULL, &errNum)) != NULL){
	  AlcErrno	errAlcNum;
	  rtnObj->values.r->freeptr = 
	    AlcFreeStackPush(rtnObj->values.r->freeptr,
			     (void *) wlzData.ubp, &errAlcNum);
	  if( errAlcNum != ALC_ER_NONE ){
	    errNum = WLZ_ERR_MEM_ALLOC;
	  }
	}
	else{
	  AlcFree((void *) wlzData.ubp);
	}
      }
      else {
	errNum = WLZ_ERR_MEM_ALLOC;
      }
    }
  }

  /* Here we use the library's state variable cinfo.output_scanline as the
   * loop counter, so that we don't have to keep track ourselves.
   * scan object copying in scanline values */
  if( errNum == WLZ_ERR_NONE ){
    while (cinfo.output_scanline < cinfo.output_height) {
      /* jpeg_read_scanlines expects an array of pointers to scanlines.
       * Here the array is only one element long, but you could ask for
       * more than one scanline at a time if that's more convenient.
       */
      (void) jpeg_read_scanlines(&cinfo, buffer, 1);
      /* copy to the woolz object buffer */
      switch( newpixtype ){
      case WLZ_GREY_UBYTE:
	memcpy((void *) wlzData.ubp, (const void *) buffer[0],
	       sizeof(char) * width);
	wlzData.ubp += width;
	break;

      case WLZ_GREY_SHORT:
	memcpy((void *) wlzData.shp, (const void *) buffer[0],
	       sizeof(short) * width);
	wlzData.shp += width;
	break;

      case WLZ_GREY_RGBA:
	/* this we need to decode */
	rOff = 0;
	for(i=0; i < width; i++, wlzData.rgbp++, rOff += 3){
	  WLZ_RGBA_RGBA_SET(*wlzData.rgbp,
			    buffer[0][rOff],
			    buffer[0][rOff+1],
			    buffer[0][rOff+2],
			    255);
	}
	break;
      default:
        break;
      }
    }

    /* Finish decompression */
    (void) jpeg_finish_decompress(&cinfo);

    /* Release JPEG decompression object */
    jpeg_destroy_decompress(&cinfo);
  }

  if( dstErr ){
    *dstErr = errNum;
  }
  return rtnObj;
}
Esempio n. 12
0
/* options_menu initialisation procedure */
void options_menu_init(
Widget	topl)
{
    Widget	widget;
    String	filestr, dirstr;
    char	lineBuf[1024], fileBuf[512], dateBuf[64];
    char	authorBuf[64], stageBuf[16];
    MAPaintExpressMapStatus	status;
    MAPaintExpressMapQuality	quality;
    int		bibfileStartIndex=0;

    /* create the tool controls dialog */
    tool_controls_dialog = create_tool_controls_dialog( topl );
    
    /* create the surgery controls dialog */
    surgeryDialog = createDomainSurgeryDialog( topl );
    XtManageChild( surgeryDialog );
    HGU_XmSaveRestoreAddWidget( surgeryDialog, NULL, NULL, NULL, NULL );

    /* create the review controls dialog */
    reviewDialog = createDomainReviewDialog( topl );
    XtManageChild( reviewDialog );
    HGU_XmSaveRestoreAddWidget( reviewDialog, NULL, NULL, NULL, NULL );

    /* create the colormap controls */
    colormap_dialog = create_colormap_dialog( topl );
    XtManageChild( colormap_dialog );
    HGU_XmSaveRestoreAddWidget( colormap_dialog, NULL, NULL, NULL, NULL );

    /* get option menu resources */
    XtGetApplicationResources(globals.topl, &globals,
			      autosave_res, XtNumber(autosave_res),
			      NULL, 0);

    /* add an autosave timeout */
    filestr = globals.autosave_file;
    dirstr = globals.autosave_dir;
    if( strlen(dirstr) < 1 ){
      globals.autosave_file = (String)
	AlcMalloc(sizeof(char) * (strlen(filestr) + 16 ));
      sprintf(globals.autosave_file, "%s.%d", filestr, getpid());
    }
    else {
      globals.autosave_file = (String)
	AlcMalloc(sizeof(char) * (strlen(dirstr) + strlen(filestr) + 16 ));
      sprintf(globals.autosave_file, "%s/%s.%d", dirstr, filestr, getpid());
    }
    
    /* no autosave in sectionView mode */
    if( globals.sectViewFlg ){
      globals.autosavetimeoutID = 0;
    }
    else {
      globals.autosavetimeoutID =
	XtAppAddTimeOut(globals.app_con, globals.autosave_time*1000,
			autosavetimeout_cb, NULL);
    }

    /* create the autosave controls */
    autosave_dialog = create_autosave_dialog( topl );
    XtManageChild( autosave_dialog );
    HGU_XmSaveRestoreAddWidget( autosave_dialog, NULL, NULL, NULL, NULL );

    globals.stipple                = (Pixmap) 0;
    globals.paint_action_quit_flag = 0;
    globals.currentPaintAction = MAPAINT_PAINT_BALL_2D;
    globals.currentPaintActionCbFunc = MAPaintPaintBall2DCb;
    globals.currentPaintActionInitFunc = MAPaintPaintBall2DInit;
    globals.currentPaintActionQuitFunc = MAPaintPaintBall2DQuit;
    globals.review_domain_obj = NULL;

    /* remove the editing options in sectionView mode */
    if( globals.sectViewFlg ){
      char nameBuf[64];
      int i;
      for(i=0; options_menu_itemsP[i].name != NULL; i++){
	if( strstr(options_menu_itemsP[i].name, "colormap") ){
	  continue;
	}
	else if( options_menu_itemsP[i].name ){
	  sprintf(nameBuf, "*.options_menu*%s",
		  options_menu_itemsP[i].name);
	  if((widget = XtNameToWidget(topl, nameBuf))){
	    XtSetSensitive(widget, False);
	  }
	}
      }
    }

    /* create the save sequence controls */
    save_seq_dialog = create_save_seq_dialog( topl );
    XtManageChild( save_seq_dialog );
    HGU_XmSaveRestoreAddWidget( save_seq_dialog, NULL, NULL, NULL, NULL );

    /* get the current working directory */
    if((dirstr = getcwd(lineBuf, 256))){
      globals.origDir = AlcStrDup(dirstr);
    }
    else {
      globals.origDir = NULL;
    }

    /* check for rapid-map or express-map */
    if( globals.rapidMapFlg || globals.expressMapFlg ){

      /* check for bibfile list file */
      if( globals.bibfileListFile ){
	FILE	*fp;
	int		i, j, linecount, csvCount;
	WlzObject	*dummyObj;
	WlzPixelV	bgdV;
	Widget		toggle, notebook, matrix, textField;
	XmNotebookPageInfo	pageInfo;
	XmToggleButtonCallbackStruct	cbs;

	/* set the default csv file */
	if( globals.bibfileListFile[0] == '/' ){
	  if( strstr(globals.bibfileListFile, ".csv") ){
	    sprintf(lineBuf, "%s", globals.bibfileListFile);
	  }
	  else {
	    sprintf(lineBuf, "%s.csv", globals.bibfileListFile);
	  }
	}
	else {
	  if( strstr(globals.bibfileListFile, ".csv") ){
	    sprintf(lineBuf, "%s/%s", globals.origDir, globals.bibfileListFile);
	  }
	  else {
	    sprintf(lineBuf, "%s/%s.csv", globals.origDir, globals.bibfileListFile);
	  }
	}
	warpGlobals.bibfileListCSVFile = AlcStrDup(lineBuf);

	/* read file and create lists */
	if((fp = fopen(globals.bibfileListFile, "r"))){
	  /* count lines */
	  linecount = 1;
	  while( fgets(lineBuf, 1024, fp) ){
	    linecount++;
	  }
	  warpGlobals.bibfileList = (char **) AlcCalloc(linecount, sizeof(char *));
	  warpGlobals.statusList = (MAPaintExpressMapStatus *)
	    AlcCalloc(linecount, sizeof(MAPaintExpressMapStatus));
	  warpGlobals.dateList = (char **) AlcCalloc(linecount, sizeof(char *));
	  warpGlobals.authorList = (char **) AlcCalloc(linecount, sizeof(char *));
	  warpGlobals.stageList = (char **) AlcCalloc(linecount, sizeof(char *));
	  warpGlobals.qualityList = (MAPaintExpressMapQuality *)
	    AlcCalloc(linecount, sizeof(MAPaintExpressMapQuality));
	  rewind(fp);
	  linecount = 0;
	  while( fgets(lineBuf, 1024, fp) ){
	    int	statusTmp, qualityTmp;
	    csvCount = sscanf(lineBuf, "%[^,\n], %d, %[^,\n], %[^,\n], %[^,\n], %d", fileBuf,
			      &statusTmp, dateBuf, authorBuf, stageBuf, &qualityTmp);
	    status = statusTmp;
	    quality = qualityTmp;
	    if( csvCount > 0 ){
	      if((fileBuf[0] != '/') && globals.origDir ){
		warpGlobals.bibfileList[linecount] = 
		  (char *) AlcMalloc(sizeof(char)*
				     (strlen(fileBuf) +
				      strlen(globals.origDir) + 4));
		sprintf(warpGlobals.bibfileList[linecount],
			"%s/%s", globals.origDir, fileBuf);
	      }
	      else {
		warpGlobals.bibfileList[linecount] = AlcStrDup(fileBuf);
	      }
	    }
	    if( csvCount > 1 ){
		warpGlobals.statusList[linecount] = status;
	    }
	    else {
	      warpGlobals.statusList[linecount] = MA_EXPRESSMAP_STATUS_NONE;
	    }
	    if( csvCount > 2 ){
		warpGlobals.dateList[linecount] = AlcStrDup(dateBuf);
	    }
	    else {
	      warpGlobals.dateList[linecount] = AlcStrDup("Unknown");
	    }
	    if( csvCount > 3 ){
		warpGlobals.authorList[linecount] = AlcStrDup(authorBuf);
	    }
	    else {
	      warpGlobals.authorList[linecount] = AlcStrDup("Unknown");
	    }
	    if( csvCount > 4 ){
		warpGlobals.stageList[linecount] = AlcStrDup(stageBuf);
	    }
	    else {
	      warpGlobals.stageList[linecount] = AlcStrDup("TS23");
	    }
	    if( csvCount > 5 ){
		warpGlobals.qualityList[linecount] = quality;
	    }
	    else {
	      warpGlobals.qualityList[linecount] = MA_EXPRESSMAP_QUALITY_NONE;
	    }
	    linecount++;
	  }
	  warpGlobals.bibfileListCount = linecount;
	  fclose(fp);
	}

	/* create dummy reference object and install */
	bgdV.type = WLZ_GREY_UBYTE;
	bgdV.v.ubv = 255;
	dummyObj = WlzAssignObject(WlzMakeCuboid(0, 5, 0, 5, 0, 5,
						 WLZ_GREY_UBYTE, bgdV,
						 NULL, NULL, NULL), NULL);
	set_topl_title("dummy");
	globals.file = NULL;
	globals.origObjType = WLZ_3D_DOMAINOBJ;
	install_paint_reference_object(dummyObj);
	WlzFreeObj(dummyObj);

	/* create warp input dialog */
	warpInput2DCb(globals.topl, NULL, NULL);

	/* get the warp controls toggle */
	if((toggle = XtNameToWidget(globals.topl, "*warp_input_2d_frame_title"))){
	  XtVaSetValues(toggle, XmNset, True, NULL);
	  cbs.set = True;
	  XtCallCallbacks(toggle, XmNvalueChangedCallback, &cbs);
	}

	/* set the files names etc in the table widget */
	if((matrix = XtNameToWidget(globals.topl, "*expressmap_matrix"))){
	  String	*rows, bibfileStr, tailStr, *labels;
	  int		numRows;
	  Boolean	*rowButtonLabels;

	  XtVaGetValues(matrix,
			XmNrows, &numRows,
			XmNtextField, &textField,
			NULL);
	  if( numRows > 0 ){
	    XbaeMatrixDeleteRows(matrix, 0, numRows);
	  }
	  rows = (String *) AlcMalloc(sizeof(String) * warpGlobals.bibfileListCount * 6);
	  labels = (String *) AlcMalloc(sizeof(String) * warpGlobals.bibfileListCount);
	  rowButtonLabels  = (Boolean *)AlcMalloc(sizeof(Boolean) *
						  warpGlobals.bibfileListCount);
       
	  bibfileStartIndex = -1;
	  for(i=0; i < warpGlobals.bibfileListCount; i++){
	    bibfileStr = tailStr = warpGlobals.bibfileList[i];
	    for(j=0; j < strlen(bibfileStr); j++){
	      if( bibfileStr[j] == '/' ){
		tailStr = bibfileStr + (j + 1);
	      }
	    }
	    rows[i*6 + 0] = tailStr;
	    rows[i*6 + 1] = expressMapStatusStrs[warpGlobals.statusList[i]];
	    rows[i*6 + 2] = warpGlobals.dateList[i];
	    rows[i*6 + 3] = warpGlobals.authorList[i];
	    rows[i*6 + 4] = warpGlobals.stageList[i];
	    rows[i*6 + 5] = expressMapQualityStrs[warpGlobals.qualityList[i]];
	    labels[i] = "->";
	    rowButtonLabels[i] = True;

	    /* check for first "None" */
	    if((bibfileStartIndex == -1) &&
	       (warpGlobals.statusList[i] == MA_EXPRESSMAP_STATUS_NONE)){
	      bibfileStartIndex = i;
	    }
	  }
	  XbaeMatrixAddRows(matrix, 0, rows, labels, NULL, i);
	  for(i=0; i < warpGlobals.bibfileListCount; i++){
	    XbaeMatrixSetRowUserData(matrix, i, (XtPointer) (long) i);
	  }
	  XtVaSetValues(matrix,
			XmNbuttonLabels, True,
			XmNrowButtonLabels, rowButtonLabels,
			XmNrowLabelAlignment, XmALIGNMENT_CENTER,
			NULL);
	  AlcFree(rows);
	  AlcFree(labels);
	  AlcFree(rowButtonLabels);
	  XtVaSetValues(textField, XmNeditable, False, NULL);
	}
	

	/* set rapidMap mode */
	if( globals.rapidMapFlg ){
	  if((notebook = XtNameToWidget(globals.topl,
					"*warp_cntrl_notebook"))){
	    XtVaSetValues(notebook,
			  XmNcurrentPageNumber, 2,
			  NULL);

	    /* call the activate callback */
	    if( XmNotebookGetPageInfo(notebook, 2,
				      &pageInfo) == XmPAGE_FOUND ){
	      XmPushButtonCallbackStruct cbs;

	      cbs.reason = XmCR_ACTIVATE;
	      cbs.event = NULL;
	      cbs.click_count = 1;
	      XtCallCallbacks(pageInfo.major_tab_widget,
			      XmNactivateCallback, &cbs);
	    }
	  }
	}
	else {
	  if((notebook = XtNameToWidget(globals.topl,
					"*warp_cntrl_notebook"))){
	    XtVaSetValues(notebook,
			  XmNcurrentPageNumber, 3,
			  NULL);

	    /* call the activate callback */
	    if( XmNotebookGetPageInfo(notebook, 3,
				      &pageInfo) == XmPAGE_FOUND ){
	      XmPushButtonCallbackStruct cbs;

	      cbs.reason = XmCR_ACTIVATE;
	      cbs.event = NULL;
	      cbs.click_count = 1;
	      XtCallCallbacks(pageInfo.major_tab_widget,
			      XmNactivateCallback, &cbs);
	    }
	  }
	}

	/* read first bibfile */
	warpGlobals.bibfileSavedFlg = 1;
	if( bibfileStartIndex < 0 ){
	  bibfileStartIndex = 0;
	}
	warpGlobals.bibfileListIndex = bibfileStartIndex - 1;
	if( globals.rapidMapFlg ){
	  if((toggle = XtNameToWidget(globals.topl, "*warp_input_rapid_form*next"))){
	    XtCallCallbacks(toggle, XmNactivateCallback, NULL);
	  }
	}
	else {
	  if((toggle = XtNameToWidget(globals.topl, "*warp_input_express_form*next"))){
	    XtCallCallbacks(toggle, XmNactivateCallback, NULL);
	  }
	}
      }
      else {
	warpGlobals.bibfileListCSVFile = NULL;
	/* should report an error here */
      }
    }
    else {
      warpGlobals.matrix = NULL;
    }

    return;
}
Esempio n. 13
0
/*!
* \return	Error code.
* \ingroup      AlgMatrix
* \brief	Solves the matrix equation A.x = b for x, where A is a
*		matrix with at least as many rows as columns.
*		On return the matrix A is overwritten by the matrix U
*		in the singular value decomposition:
*		  A = U.W.V'
* \param	aMat			Matrix A.
* \param	bVec			Column matrix b, overwritten
*					by matrix x on return.
* \param	tol			Tolerance for singular values,
*					1.0e-06 should be suitable as
*					a default value.
* \param	dstIC			Destination pointer for
*					ill-conditioned flag, which may
*					be NULL, but if not NULL is set
*					to the number of singular values
*					which are smaller than the maximum
*					singular value times the given
*					threshold.
*/
AlgError	AlgMatrixSVSolve(AlgMatrix aMat, double *bVec, double tol,
                                 int *dstIC)
{
  int		cnt0 = 0,
  		cntIC = 0;
  size_t	nM,
  		nN;
  double	thresh,
  		wMax = 0.0;
  double	*tDP0,
  		*wVec = NULL;
  AlgMatrix	vMat;
  AlgError	errCode = ALG_ERR_NONE;

  nM = aMat.core->nR;
  nN = aMat.core->nC;
  vMat.core = NULL;
  if((aMat.core == NULL) || (aMat.core->type != ALG_MATRIX_RECT) ||
     (aMat.core->nR <= 0) || (aMat.core->nR < aMat.core->nC) ||
     (bVec == NULL))
  {
    errCode = ALG_ERR_FUNC;
  }
  else if((wVec = (double *)AlcCalloc(sizeof(double), aMat.rect->nC)) == NULL)
  {
    errCode = ALG_ERR_MALLOC;
  }
  else
  {
    vMat.rect = AlgMatrixRectNew(nM, nN, &errCode);
  }
  if(errCode == ALG_ERR_NONE)
  {
    errCode = AlgMatrixSVDecomp(aMat, wVec, vMat);
  }
  if(errCode == ALG_ERR_NONE)
  {
    /* Find maximum singular value. */
    cnt0 = nN;
    cntIC = 0;
    tDP0 = wVec;
    while(cnt0-- > 0)
    {
      if(*tDP0 > wMax)
      {
	++cntIC;
        wMax = *tDP0;
      }
      ++tDP0;
    }
    /* Edit the singular values, replacing any less than tol * max singular
       value with 0.0. */
    cnt0 = nN;
    tDP0 = wVec;
    thresh = tol * wMax;
    while(cnt0-- > 0)
    {
      if(*tDP0 < thresh)
      {
	*tDP0 = 0.0;
      }
      ++tDP0;
    }
    errCode = AlgMatrixSVBackSub(aMat, wVec, vMat, bVec);
  }
  AlcFree(wVec);
  AlgMatrixRectFree(vMat.rect);
  if(dstIC)
  {
    *dstIC = cntIC;
  }
  ALG_DBG((ALG_DBG_LVL_FN|ALG_DBG_LVL_1),
	  ("AlgMatrixSVSolve FX %d\n",
	   (int )errCode));
  return(errCode);
}
Esempio n. 14
0
/*!
* \return	Grey value work space or NULL on error.
* \ingroup	WlzAccess
* \brief	Creates a grey value work space from the given object.
*		The resulting grey value work space should be freed
*		using WlzGreyValueFreeWSp().
* \param	obj			Given object.
* \param	dstErrNum		Destination error pointer, may be NULL.
*/
WlzGreyValueWSpace *WlzGreyValueMakeWSp(WlzObject *obj,
					WlzErrorNum *dstErrNum)
{
  int		planeIdx, numPlanes;
  WlzDomain	*planeDomains;
  WlzValues	*planeValues;
  WlzObjectType	gTabType0,
	        gTabType1 = WLZ_DUMMY_ENTRY;
  WlzGreyType	gType0 = WLZ_GREY_ERROR,
		gType1 = WLZ_GREY_ERROR;
  WlzPixelV	bkdPix;
  WlzAffineTransform *trans0,
  		*trans1;
  WlzGreyValueWSpace *gVWSp = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

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

	      gVWSp->values2D.core = NULL;
	      planeIdx = obj->domain.p->plane1;
	      planeDomains = obj->domain.p->domains;
	      planeValues = obj->values.vox->values;
	      gTabTypes3D = gVWSp->gTabTypes3D;
	      while((planeIdx <= obj->domain.p->lastpl) &&
		    (errNum == WLZ_ERR_NONE))
	      {
		if(((*planeValues).core) &&
		   ((*planeValues).core->type != WLZ_EMPTY_OBJ))
		{
		  gType0 = WlzGreyTableTypeToGreyType(
		      (*planeValues).core->type, &errNum);
		  if(errNum == WLZ_ERR_NONE)
		  {
		    gTabType0 = WlzGreyTableTypeToTableType((*planeValues).
			                                    core->type,
							    &errNum);
		    *gTabTypes3D = gTabType0;
		  }
		  if(errNum == WLZ_ERR_NONE)
		  {
		    if((gType0 != gType1) && (gType1 != WLZ_GREY_ERROR))
		    {
		      errNum = WLZ_ERR_VALUES_DATA;
		    }
		    else
		    {
		      gType1 = gType0;
		      gTabType1 = gTabType0;
		      if(gVWSp->values2D.core == NULL)
		      {
			gVWSp->plane = planeIdx;
			gVWSp->iDom2D = (*planeDomains).i;
			gVWSp->values2D = *planeValues;
		      }
		    }
		  }
		}
		++planeIdx;
		++planeDomains;
		++planeValues;
		++gTabTypes3D;
	      }
	      if((gType1 == WLZ_GREY_ERROR) || (gTabType1 == WLZ_DUMMY_ENTRY))
	      {
		errNum = WLZ_ERR_VALUES_DATA;
	      }
	    }
	    if(errNum == WLZ_ERR_NONE)
	    {
	      gVWSp->gType = gType0;
	      gVWSp->gTabType2D = gVWSp->gTabTypes3D[0];
	      switch(gVWSp->gTabType2D)
	      {
		case WLZ_GREY_TAB_RAGR:
		  bkdPix = gVWSp->values2D.v->bckgrnd;
		  break;
		case WLZ_GREY_TAB_RECT:
		  bkdPix = gVWSp->values2D.r->bckgrnd;
		  break;
		case WLZ_GREY_TAB_INTL:
		  bkdPix = gVWSp->values2D.i->bckgrnd;
		  break;
		case WLZ_GREY_TAB_TILED:
		  bkdPix = gVWSp->values2D.t->bckgrnd;
		  break;
		default:
		  errNum = WLZ_ERR_VALUES_TYPE;
		  break;
	      }
	      if((gVWSp->gType != bkdPix.type) && (errNum == WLZ_ERR_NONE))
	      {
		errNum = WLZ_ERR_VALUES_DATA;
	      }
	      else if((gVWSp->iDom2D->type != WLZ_INTERVALDOMAIN_INTVL) &&
		      (gVWSp->iDom2D->type != WLZ_INTERVALDOMAIN_RECT))
	      {
		errNum = WLZ_ERR_DOMAIN_TYPE;
	      }
	      else
	      {
		gVWSp->gBkd = bkdPix.v;
	      }
	    }
	  }
	}
	break;
      case WLZ_TRANS_OBJ:
	trans0 = NULL;
	while((errNum == WLZ_ERR_NONE) && (obj->type == WLZ_TRANS_OBJ))
	{
	  if(trans0 == NULL)
	  {
	    trans0 = WlzAffineTransformCopy(obj->domain.t, &errNum);
	  }
	  else
	  {
	    if((trans1 = WlzAffineTransformProduct(trans0, obj->domain.t,
	    				           &errNum)) != NULL)
	    {
	      WlzFreeAffineTransform(trans0);
	      trans0 = trans1;
	      trans1 = NULL;
	    }
	  }
	  if((obj = obj->values.obj) == NULL)
	  {
	    errNum = WLZ_ERR_OBJECT_NULL;
	  }
	}
	if(errNum == WLZ_ERR_NONE)
	{
	  gVWSp = WlzGreyValueMakeWSp(obj, &errNum);
	}
	if(errNum == WLZ_ERR_NONE)
	{
	  gVWSp->invTrans = WlzAffineTransformInverse(trans0, &errNum);
	}
	if(trans0)
	{
	  WlzFreeAffineTransform(trans0);
	}
	break;
      default:
	errNum = WLZ_ERR_OBJECT_TYPE;
	break;
    }
  }
  if((errNum != WLZ_ERR_NONE) && (gVWSp != NULL))
  {
    WlzGreyValueFreeWSp(gVWSp);
    gVWSp = NULL;
  }
  if(dstErrNum)
  {
    *dstErrNum = errNum;
  }
  WLZ_DBG((WLZ_DBG_LVL_FN|WLZ_DBG_LVL_1),
  	  ("WlzGreyValueMakeWSp FX %p\n",
	   gVWSp));
  return(gVWSp);
}
Esempio n. 15
0
/*!
* \return	Woolz error code.
* \ingroup	WlzExtFF
* \brief	Reads the materials list from the file into the file header
*		data structure.
*		There are two formats for materials lists:
*		\verbatim
		  {
		    { Id 0, Name "Exterior" )
		    { Id 4, Name "Somites" }
		  }
		\endverbatim
*		and		
*		\verbatim
		  {
		    Exterior {
		    }
		    Inside {
		    }
		    Somites {
		      Id 4,
		      Color 0.2 0.8 0.4
		    }
		    Ventricles
		  }
		\endverbatim
*		Dispite id's being given in the file they are ignored and
*		the id's are given values from 0, incrementing by 1 with
*		each material parsed.
*		The default colour is 0.0 0.0 0.0 for the first material
*		and 1.0 1.0 1.0 for all others.
*		This function has been written to parse either of these
*		materials formats, to generate a materials list in the
*		header data structure.
* \param	fP			Given file.
* \param	buf			Buffer for workspace.
* \param	bufLen			Buffer length.
* \param	head			The Amira lattice header data
*					structure.
*/
static WlzErrorNum WlzEffAmReadMaterials(FILE *fP, char *buf, const int bufLen,
				  WlzEffAmHead *head)
{

  int		tmpI;
  WlzEffAmToken	tok;
  WlzEffAmMaterial *lastMat = NULL,
  		*newMat = NULL;
  WlzErrorNum   errNum;
  const char	tokSepDQ[] = "\"",
  		tokSepWS[] = " \t\n\r\f\v",
            	tokSepWSC[] = " \t\n,\r\f\v",
            	tokSepWSCQ[] = " \t\n,\"\r\f\v";

  errNum =  WlzEffAmReadAndCheckAToken(fP, tokSepWS, buf, bufLen, "{");
  if(errNum == WLZ_ERR_NONE)
  {
    errNum = WlzEffAmReadAToken(fP, tokSepWS, buf, bufLen);
  }
  do
  {
    if((errNum == WLZ_ERR_NONE) && (strcmp(buf, "}")))
    {
      /* Create a new material and set the defaults. */
      if((newMat = (WlzEffAmMaterial *)
      		   AlcCalloc(1, sizeof(WlzEffAmMaterial))) == NULL)
      {
        errNum = WLZ_ERR_MEM_ALLOC;
      }
      else if(head->matCount > 0)
      {
        newMat->color[0] = newMat->color[1] = newMat->color[2] = 1.0;
      }
    }
    if(errNum == WLZ_ERR_NONE)
    {
      if(strcmp(buf, "{"))
      {
	if((newMat->name = AlcStrDup(buf)) == NULL)
	{
	  errNum = WLZ_ERR_MEM_ALLOC;
	}
	else
	{
	  errNum = WlzEffAmReadAToken(fP, tokSepWS, buf, bufLen);
	}
      }
    }
    if((errNum == WLZ_ERR_NONE) && strcmp(buf, "{") && strcmp(buf, "}"))
    {
      errNum = WLZ_ERR_READ_INCOMPLETE;
    }
    if((errNum == WLZ_ERR_NONE) && strcmp(buf, "}"))
    {
      do
      {
	errNum = WlzEffAmReadAToken(fP, tokSepWS, buf, bufLen);
	if((errNum == WLZ_ERR_NONE) && (strcmp(buf, "}")))
	{
	  tok = WLZEFF_AM_TOKEN_NONE;
	  (void )WlzStringMatchValue((int *)&tok, buf,
				     "Color", WLZEFF_AM_TOKEN_COLOR,
				     "Id", WLZEFF_AM_TOKEN_ID,
				     "Name", WLZEFF_AM_TOKEN_NAME,
				     NULL);
	  switch(tok)
	  {
	    case WLZEFF_AM_TOKEN_COLOR:

	      errNum = WlzEffAmReadAValD(fP, tokSepWS, buf, bufLen,
	      				 &(newMat->color[0]));
	      if(errNum == WLZ_ERR_NONE)
	      {
		errNum = WlzEffAmReadAValD(fP, tokSepWS, buf, bufLen,
					   &(newMat->color[1]));
	      }
	      if(errNum == WLZ_ERR_NONE)
	      {
		errNum = WlzEffAmReadAValD(fP, tokSepWS, buf, bufLen,
					   &(newMat->color[2]));
	      }
	      break;
	    case WLZEFF_AM_TOKEN_ID:
	      errNum = WlzEffAmReadAValI(fP, tokSepWSC, buf, bufLen, &tmpI);
	      if(errNum == WLZ_ERR_NONE)
	      {
                errNum = WlzEffAmSkip(fP, tokSepWSC);
	      }
	      break;
	    case WLZEFF_AM_TOKEN_NAME:
	      errNum = WlzEffAmSkip(fP, tokSepWS);
	      if(errNum == WLZ_ERR_NONE)
	      {
	        errNum = WlzEffAmReadAToken(fP, tokSepDQ, buf, bufLen);
	      }
	      if(errNum == WLZ_ERR_NONE)
	      {
	        errNum = WlzEffAmSkip(fP, tokSepWSCQ);
	      }
	      if((errNum == WLZ_ERR_NONE) &&
	      	 ((newMat->name = AlcStrDup(buf)) == NULL))
	      {
		errNum = WLZ_ERR_MEM_ALLOC;
	      }
	      break;
	    default:
	      errNum = WLZ_ERR_READ_INCOMPLETE;
	      break;
	  }
	}
      }while((errNum == WLZ_ERR_NONE) && strcmp(buf, "}"));
      *buf = '\0';
    }
    if(errNum == WLZ_ERR_NONE)
    {
      /* Insert new material into list keeping the order of the materials
       * in which they were read from the file. */
      newMat->id = (head->matCount)++;
      if(lastMat == NULL)
      {
	head->materials = newMat;
      }
      else
      {
        lastMat->next = newMat;
	newMat->prev = lastMat;
      }
      lastMat = newMat;
      newMat = NULL;
    }
    if((errNum == WLZ_ERR_NONE) && strcmp(buf, "}"))
    {
      errNum = WlzEffAmReadAToken(fP, tokSepWS, buf, bufLen);
    }
  } while((errNum == WLZ_ERR_NONE) && strcmp(buf, "}"));
  if(newMat)
  {
    AlcFree(newMat->name);
    AlcFree(newMat);
  }
  return(errNum);
}
Esempio n. 16
0
/*!
* \return	New filtered object with new values or NULL on error.
* \ingroup	WlzValuesFilters
* \brief	Applies a seperable filter along the z axis (planes)
* 		to the given object using the given convolution kernel.
* \param	inObj			Input 3D spatial domain object to be
* 					filtered which must have scalar values.
* \param	bBox			Object's bounding box.
* \param	maxThr			Maximum number of threads to use.
* \param	iBuf			Working buffers large enough for any
* 				        column in the image with one for each
* 				        thread.
* \param	rBuf			Buffers as for iBuf. 			
* \param	cBufSz			Convolution kernel size.
* \param	cBuf			Convolution kernel buffer.
* \param	pad			Type of padding.
* \param	padVal			Padding value.
* \param	dstErr			Destination error pointer may be NULL.
*/
static WlzObject		*WlzSepFilterZ(WlzObject *inObj,
				  WlzIBox3 bBox,
				  int maxThr,
				  double **iBuf,
				  double **rBuf,
				  int cBufSz,
				  double *cBuf,
				  AlgPadType pad,
				  double padVal,
				  WlzErrorNum *dstErr)
{
  WlzObjectType	rGTT;
  WlzPixelV	zV;
  WlzObject	*rnObj = NULL;
  WlzGreyValueWSpace **iVWSp = NULL,
	             **rVWSp = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  		
  zV.v.dbv = 0.0;
  zV.type = WLZ_GREY_DOUBLE;
  rGTT = WlzGreyTableType(WLZ_GREY_TAB_RAGR, WLZ_GREY_DOUBLE, NULL);
  rnObj = WlzNewObjectValues(inObj, rGTT, zV, 1, zV, &errNum);
  if(errNum == WLZ_ERR_NONE)
  {
    if(((iVWSp = (WlzGreyValueWSpace **)
                 AlcCalloc(maxThr, sizeof(WlzGreyValueWSpace *))) == NULL) ||
       ((rVWSp = (WlzGreyValueWSpace **)
                 AlcCalloc(maxThr, sizeof(WlzGreyValueWSpace *))) == NULL))
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    int		idt;

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

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

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

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

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

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

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

    for(idt = 0; idt < maxThr; ++idt)
    {
      WlzGreyValueFreeWSp(rVWSp[idt]);
    }
    AlcFree(rVWSp);
  }
  if(errNum != WLZ_ERR_NONE)
  {
    (void )WlzFreeObj(rnObj);
    rnObj = NULL;
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(rnObj);
}
Esempio n. 17
0
Widget HGU_XmCreateImageView(
    String	name,
    Widget	parent,
    int		mappingDialogFlg)
{
    Widget	image_form, form, button, text, scrolled_window, canvas;
    HGU_XmImageViewDataStruct	*data;
    String			titleStr;
    XmString			choiceStr;

    /* create the top-level form */
    image_form = XtVaCreateManagedWidget(name, xmFormWidgetClass,
                                         parent,
                                         XmNwidth, 400,
                                         XmNheight, 400,
                                         NULL);
    data = (HGU_XmImageViewDataStruct *)
           AlcCalloc(sizeof(HGU_XmImageViewDataStruct), 1);
    XtVaSetValues(image_form, XmNuserData, data, NULL);
    data->imageForm = image_form;
    data->srcMin = -10000;
    data->srcMax = 10000;
    data->min = -10000;
    data->max = 10000;
    data->Min = 0;
    data->Max = 255;
    data->width = 696;
    data->height = 520;
    data->depth = 12;
    data->byteOrder = 1;
    data->magVal = 1.0;
    data->transType = WLZ_GREYTRANSFORMTYPE_LINEAR;
    data->gamma = 1.0;
    data->invert = 0;
    data->lut.g = (HGU_XmLutGrey *) AlcMalloc(sizeof(HGU_XmLutGrey));
    data->lut.g->lut = NULL;
    data->lut.g->min = data->Min;
    data->lut.g->max = data->Max;

    /* create file-selector dialog */
    XtGetApplicationResources(image_form, &titleStr,
                              HGU_XmImageViewReadTitleResources, 1, NULL, 0);
    data->fileSelector = XmCreateFileSelectionDialog(image_form,
                         "image_select", NULL, 0);
    XtVaSetValues(XtParent(data->fileSelector), XmNtitle, titleStr, NULL);
    XtAddCallback(data->fileSelector, XmNokCallback,
                  HGU_XmImageViewReadImageCb, (XtPointer) data);
    XtAddCallback(data->fileSelector, XmNokCallback,
                  PopdownCallback, NULL);
    XtAddCallback(data->fileSelector, XmNcancelCallback,
                  PopdownCallback, NULL);

    form = XtVaCreateManagedWidget("read_file_form", xmFormWidgetClass,
                                   data->fileSelector,
                                   XmNborderWidth,	0,
                                   NULL);

    /* add a file type selection menu */
    XtGetApplicationResources(image_form, &choiceStr,
                              HGU_XmImageViewReadChoiceResources, 1, NULL, 0);
    data->typeMenu = HGU_XmBuildMenu(form, XmMENU_OPTION,
                                     "file_type", 0, XmTEAR_OFF_DISABLED,
                                     file_type_menu_itemsP);
    XtVaSetValues(data->typeMenu,
                  XmNtopAttachment,	XmATTACH_FORM,
                  XmNleftAttachment,	XmATTACH_FORM,
                  XmNrightAttachment,	XmATTACH_FORM,
                  XmNlabelString, 	choiceStr,
                  NULL);
    XtManageChild(data->typeMenu);

    /* create the mapping dialog */
    XtGetApplicationResources(parent, &titleStr,
                              HGU_XmGreyMappingDialogTitleResources, 1, NULL, 0);
    data->greyMapping = HGU_XmCreateGreyMappingDialog("grey_mapping", parent,
                        data);
    XtVaSetValues(XtParent(data->greyMapping), XmNtitle, titleStr, NULL);

    /* add the button row for mag+, mag-, I/O and re-mapping */
    form = XtVaCreateManagedWidget("image_buttons_form", xmFormWidgetClass,
                                   image_form,
                                   XmNleftAttachment, XmATTACH_FORM,
                                   XmNrightAttachment, XmATTACH_FORM,
                                   XmNbottomAttachment, XmATTACH_FORM,
                                   NULL);
    button = XtVaCreateManagedWidget("Read", xmPushButtonWidgetClass, form,
                                     XmNleftAttachment, XmATTACH_FORM,
                                     XmNtopAttachment, XmATTACH_FORM,
                                     XmNbottomAttachment, XmATTACH_FORM,
                                     NULL);
    XtAddCallback(button, XmNactivateCallback, HGU_XmMapDialogCb,
                  data->fileSelector);
    button = XtVaCreateManagedWidget("Mag+", xmPushButtonWidgetClass, form,
                                     XmNleftAttachment, XmATTACH_WIDGET,
                                     XmNleftWidget, button,
                                     XmNtopAttachment, XmATTACH_FORM,
                                     XmNbottomAttachment, XmATTACH_FORM,
                                     NULL);
    XtAddCallback(button, XmNactivateCallback,
                  HGU_XmImageViewMagPlusCb, data);
    button = XtVaCreateManagedWidget("Mag-", xmPushButtonWidgetClass, form,
                                     XmNleftAttachment, XmATTACH_WIDGET,
                                     XmNleftWidget, button,
                                     XmNtopAttachment, XmATTACH_FORM,
                                     XmNbottomAttachment, XmATTACH_FORM,
                                     NULL);
    XtAddCallback(button, XmNactivateCallback,
                  HGU_XmImageViewMagMinusCb, data);
    text = XtVaCreateManagedWidget("image_fb", xmTextFieldWidgetClass, form,
                                   XmNleftAttachment, XmATTACH_WIDGET,
                                   XmNleftWidget, button,
                                   XmNtopAttachment, XmATTACH_FORM,
                                   XmNbottomAttachment, XmATTACH_FORM,
                                   XmNcolumns, 10,
                                   NULL);
    button = XtVaCreateManagedWidget("Map greys", xmPushButtonWidgetClass,
                                     form,
                                     XmNrightAttachment, XmATTACH_FORM,
                                     XmNtopAttachment, XmATTACH_FORM,
                                     XmNbottomAttachment, XmATTACH_FORM,
                                     NULL);
    XtAddCallback(button, XmNactivateCallback,
                  HGU_XmMapDialogCb, data->greyMapping);

    /* add scrolling window and canvas */
    scrolled_window = XtVaCreateManagedWidget("image_sc",
                      xmScrolledWindowWidgetClass,
                      image_form,
                      XmNscrollingPolicy, XmAUTOMATIC,
                      XmNleftAttachment, XmATTACH_FORM,
                      XmNrightAttachment, XmATTACH_FORM,
                      XmNtopAttachment, XmATTACH_FORM,
                      XmNbottomAttachment, XmATTACH_WIDGET,
                      XmNbottomWidget, form,
                      NULL);
    data->width = 512;
    data->height = 512;
    canvas = XtVaCreateManagedWidget("canvas", xmDrawingAreaWidgetClass,
                                     scrolled_window,
                                     XmNwidth,  data->width,
                                     XmNheight, data->height,
                                     NULL);
    XtAddCallback(canvas, XmNexposeCallback, HGU_XmImageViewCanvasExposeCb, data);
    XtAddCallback(canvas, XmNinputCallback, HGU_XmImageViewCanvasInputCb, data);
    XtAddEventHandler(canvas, PointerMotionMask,
                      False, HGU_XmImageViewCanvasMotionEventHandler, data);
    data->canvas = canvas;


    return image_form;
}
Esempio n. 18
0
/*!
* \return	Woolz error code.
* \ingroup	WlzTransform
* \brief	Fits a plane to the given vertices using singular value
* 		decomposition. The best fit plane is returned (provided
* 		there is no error) as a unit normal \f$n\f$ and the
* 		centroid of the given vertices ( \f$r_0\f$ ) which in a
* 		point in the plane, with the plane equation
* 		\f[
		\vec{n}\cdot(\vec{r} - \vec{r_0}) = \vec{0}
 		\f]
* \param	vtxType			Given vertex type.
* \param	nVtx			Number of given vertices.
* \param	vtx			Given vertices.
* \param	dstPinP			Destination pointer for the return
* 					of the median point (\f$r_0\f$) in
* 					the plane.
* \param	dstNrm			Destination pointer for the unit
*   					normal to the plane (\f$n\f$).
*/
WlzErrorNum WlzFitPlaneSVD(WlzVertexType vtxType, int nVtx, WlzVertexP vtx,
			   WlzDVertex3 *dstPinP, WlzDVertex3 *dstNrm)
{
  AlgMatrix     aMat,
  		vMat;
  WlzDVertex3	centroid,
                normal;
  double	*sVec = NULL;
  AlgError	algErr = ALG_ERR_NONE;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  aMat.core = NULL;
  vMat.core = NULL;
  if(nVtx < 0)
  {
    errNum = WLZ_ERR_PARAM_DATA;
  }
  else if(vtx.v == NULL)
  {
    errNum = WLZ_ERR_PARAM_NULL;
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if(((sVec = (double *)AlcCalloc(sizeof(double), 3)) == NULL) ||
       ((aMat.rect = AlgMatrixRectNew(nVtx, 3, NULL)) == NULL) ||
       ((vMat.rect = AlgMatrixRectNew(3, 3, NULL)) == NULL))
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  /* Compute a Nx3 matrix from the given vertices then subtract their
   * centroid. */
  if(errNum == WLZ_ERR_NONE)
  {
    int		i;
    double	*row;
    
    WLZ_VTX_3_ZERO(centroid);
    switch(vtxType)
    {
      case WLZ_VERTEX_I3:
	for(i = 0; i < nVtx; ++i)
	{
	  WlzIVertex3 *v;

	  v = vtx.i3 + i;
          row = aMat.rect->array[i];
	  centroid.vtX += row[0] = v->vtX;
	  centroid.vtY += row[1] = v->vtY;
	  centroid.vtZ += row[2] = v->vtZ;
	}
	break;
      case WLZ_VERTEX_F3:
	for(i = 0; i < nVtx; ++i)
	{
	  WlzFVertex3 *v;

	  v = vtx.f3 + i;
          row = aMat.rect->array[i];
	  centroid.vtX += row[0] = v->vtX;
	  centroid.vtY += row[1] = v->vtY;
	  centroid.vtZ += row[2] = v->vtZ;
	}
	break;
      case WLZ_VERTEX_D3:
	for(i = 0; i < nVtx; ++i)
	{
	  WlzDVertex3 *v;

	  v = vtx.d3 + i;
          row = aMat.rect->array[i];
	  centroid.vtX += row[0] = v->vtX;
	  centroid.vtY += row[1] = v->vtY;
	  centroid.vtZ += row[2] = v->vtZ;
	}
	break;
      default:
	errNum = WLZ_ERR_PARAM_TYPE;
        break;
    }
    if(errNum == WLZ_ERR_NONE)
    {
      WLZ_VTX_3_SCALE(centroid, centroid, (1.0 / nVtx));
      for(i = 0; i < nVtx; ++i)
      {
	row = aMat.rect->array[i];
	row[0] -= centroid.vtX;
	row[1] -= centroid.vtY;
	row[2] -= centroid.vtZ;
      }
    }
  }
  /* Compute SVD. */
  if(errNum == WLZ_ERR_NONE)
  {
    algErr = AlgMatrixSVDecomp(aMat, sVec, vMat);
    errNum = WlzErrorFromAlg(algErr);
  }
  /* Find the vector corresponding to the least singular value. */
  if(errNum == WLZ_ERR_NONE)
  {
    int		i,
    		m;
    double	len;
    double	**ary;
    const double eps = 1.0e-06;

    m  = 0;
    for(i = 1; i < 3; ++i)
    {
      if(sVec[i] < sVec[m])
      {
        m = i;
      }
    }
    ary = vMat.rect->array;
#ifdef WLZ_FITPLANESVD_DEBUG
    (void )fprintf(stderr,
                   "WlzFitPlaneSVD() singular values = {%lg, %lg, %lg}\n",
		   sVec[0], sVec[1], sVec[2]);
    (void )fprintf(stderr,
                   "WlzFitPlaneSVD() index of min singular value = %d\n",
		   m);
    (void )fprintf(stderr,
                   "WlzFitPlaneSVD() singular vectors = \n"
		   "{\n");
    for(i = 0; i < 3; ++i)
    {
      (void )fprintf(stderr,
                     " {%lg, %lg, %lg}\n",
		     ary[i][0], ary[i][1], ary[i][2]);
    }
    (void )fprintf(stderr,
		   "}\n");
#endif /* WLZ_FITPLANESVD_DEBUG */
    normal.vtX = ary[0][m];
    normal.vtY = ary[1][m];
    normal.vtZ = ary[2][m];
    len = WLZ_VTX_3_LENGTH(normal);
    if(len < eps)
    {
      errNum = WLZ_ERR_ALG_SINGULAR;
    }
    else
    {
      WLZ_VTX_3_SCALE(normal, normal, (1.0 / len));
    }
  }
  AlgMatrixRectFree(aMat.rect);
  AlgMatrixRectFree(vMat.rect);
  AlcFree(sVec);
  if(errNum == WLZ_ERR_NONE)
  {
    if(dstNrm)
    {
      *dstNrm = normal;
    }
    if(dstPinP)
    {
      *dstPinP = centroid;
    }
  }
  return(errNum);
}
Esempio n. 19
0
/*!
* \return	New recursive filter.
* \ingroup      WlzValueFilters
* \brief	Creates a new recursive filter.
* \param	name			Name of filter.
* \param	prm			Parameter is alpha for Deriche's
*                                       operators and sigma for
*                                       Gaussians, must be \f$\geq\f$ 0.0.
* \param	dstErr			Destination error pointer, may
*                                       be null.
*/
WlzRsvFilter *WlzRsvFilterMakeFilter(WlzRsvFilterName name,
				       double prm, WlzErrorNum *dstErr)
{
  int		idx;
  double	tD0,
		tAS,
		tWS,
  		tExp,
  		tExp2,
		tNorm,
		tCos,
		tSin;
  WlzRsvFilter *ftr = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  const double	cGauss = 2.4726;
  const double	aGauss[3] = { 1.2600,  0.9338,  0.6134},
  		bGauss[3] = { 0.9629, -0.1051,  1.2280},
		gGauss[3] = { 1.9420,  1.8980, -0.2976},
		wGauss[3] = { 0.8448,  0.9459,  1.3320};

  if((ftr = (WlzRsvFilter *)AlcCalloc(sizeof(WlzRsvFilter),
  					  1)) == NULL)
  {
    errNum = WLZ_ERR_MEM_ALLOC;
  }
  else if(name == WLZ_RSVFILTER_NAME_NONE)
  {
    ftr->name = WLZ_RSVFILTER_NAME_NONE;
  }
  else if(prm < DBL_EPSILON)
  {
    errNum = WLZ_ERR_PARAM_DATA;
  }
  else
  {
    switch(name)
    {
      case WLZ_RSVFILTER_NAME_DERICHE_0: /* FALLTHROUGH */
      case WLZ_RSVFILTER_NAME_DERICHE_1: /* FALLTHROUGH */
      case WLZ_RSVFILTER_NAME_DERICHE_2:
	tExp = exp(-prm);
	tExp2 = tExp * tExp;
	tD0 = 1.0 - tExp;
	tNorm = (tD0 * tD0) / (1.0 + (2.0 * prm * tExp) - tExp2);
	ftr->name = name;
	ftr->b[0] = -2.0 * tExp;
	ftr->b[1] = tExp2;
	switch(name)
	{
	  case WLZ_RSVFILTER_NAME_DERICHE_0:
	    ftr->a[0] = 1.0;
	    ftr->a[1] = (prm - 1.0) * tExp;
	    ftr->a[2] = (prm + 1.0) * tExp;
	    ftr->a[3] = -tExp2;
	    ftr->c = tNorm;
	    break;
	  case WLZ_RSVFILTER_NAME_DERICHE_1:
	    ftr->a[0] = 0.0;
	    tD0 = (prm * prm) * tExp;
	    ftr->a[1] = -tD0;
	    ftr->a[2] = tD0;
	    ftr->a[3] = 0.0;
	    ftr->c = -tNorm;
	    break;
	  case WLZ_RSVFILTER_NAME_DERICHE_2:
	    tD0 = (prm * prm);
	    ftr->a[0] = -tD0;
	    ftr->a[1] = (prm + 1) * tD0 * tExp;
	    ftr->a[2] = (prm - 1) * tD0 * tExp;
	    ftr->a[3] = tD0 * tExp2;
	    ftr->c = tNorm;
	    break;
	  default:
	    break;
	}
        break;
      case WLZ_RSVFILTER_NAME_GAUSS_0: /* FALLTHROUGH */
      case WLZ_RSVFILTER_NAME_GAUSS_1: /* FALLTHROUGH */
      case WLZ_RSVFILTER_NAME_GAUSS_2:
	ftr->name = name;
	switch(name)
	{
	  case WLZ_RSVFILTER_NAME_GAUSS_0:
	    idx = 0;
	    break;
	  case WLZ_RSVFILTER_NAME_GAUSS_1:
	    idx = 1;
	    break;
	  case WLZ_RSVFILTER_NAME_GAUSS_2:
	    idx = 2;
	    break;
	  default:
	    break;
	}
	tWS = wGauss[idx] / prm;
	tAS = aGauss[idx] / prm;
	tCos = cos(tWS);
	tSin = sin(tWS);
	tExp = exp(-tAS);
	tExp2 = tExp * tExp;
        tNorm = 1.0 / (cGauss * prm);
	ftr->a[0] = bGauss[idx];
	tD0 = ((-bGauss[idx] * tCos) + (gGauss[idx] * tSin)) * tExp;
	ftr->a[1] = tD0;
	ftr->b[0] = -2.0 * tCos * tExp;
	ftr->b[1] = tExp2;
	if(name == WLZ_RSVFILTER_NAME_GAUSS_1) 	        /* Asymetric */
	{
	  ftr->a[3] = -(tD0 + (2.0 * bGauss[idx] * tCos * tExp));
	  ftr->a[2] = bGauss[idx] * tExp2;
	}
	else
	{
	  ftr->a[2] = tD0 + (2.0 * bGauss[idx] * tCos * tExp);
	  ftr->a[3] = -(bGauss[idx] * tExp2);
	}
	ftr->c = tNorm;
        break;
      default:
        errNum = WLZ_ERR_PARAM_DATA;
	break;
    }
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(ftr);
}
Esempio n. 20
0
/*!
* \return	The filtered object, maybe NULL on error.
* \ingroup	WlzValueFilters
* \brief	WlzSeqPar performs a sequential or parallel local
*               transform. A distance transform is an example of a
*               sequential transform and a laplacian is an example of
*               a parallel transform.
*               Only WLZ_2D_DOMAINOBJ objects with values may be passed
*               to WlzSeqPar().
* \note		If the point to be transformed is at line l and col k,
*               there is an array of pointers spWSpace->adrptr[-7:7],
*               whose i'th entry gives the address of the point
*               (l + (i * spWSpace->ldelta), k), but which is only
*               meaningful for lines within bdrSz of the point.
*               For example: spWSpace->adrptr[-3] and
*               spWSpace->adrptr[3] are undefined if bdrSz < 3.
* \param	srcObj			The given WLZ_2D_DOMAINOBJ object.
* \param	newObjFlag		If zero then the given object is
*					overwritten otherwise a new object is
*					created.
* \param	sequentialFlag		If non zero the transform is
*                                       seqential and transformed
*                                       values are used in calculating
*                                       the neighbouring values.
*                                       If zero the transform always
*                                       works on the original grey
*                                       values.
* \param	rasterDir		Direction of raster scan.
* \param	bdrSz			Local transform kernel half-size,
*					must be in range 0 - 7.
*                                       The usual 8 immediate neighbors
*                                       correspond to bdrSz == 1.
* \param	bkgVal			Background grey value.
* \param	transformData		Data supplied to the transform
*                                       function.
* \param	transformFn		Supplied transform function.
* \param	dstErr			Destination error pointer, may
*                                       be NULL.
*/
WlzObject	*WlzSeqPar(WlzObject *srcObj,
			   int newObjFlag, int sequentialFlag,
			   WlzRasterDir rasterDir, int bdrSz, int bkgVal,
			   void *transformData,
			   int (*transformFn)(WlzSeqParWSpace *, void *),
			   WlzErrorNum *dstErr)
{
  int 		tI0,
  		curLine,
  		howManyLn,
		bdrP1,
		numBufs,
		kol,
		kol1,
		lineSz, 		/* lineSz is the maximally sized line,
					   including borders */
		lineOffset, 		/* lineOffset is difference in line
					   numbers between that being
					   transformed and that needed in the
					   input buffer for use in the
					   transform */
		nextLine,
		inLine,
		needed,
		idx,
		itop,
		minLine;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  int 		*lineBufSpace = NULL, 	/* lineBufSpace is the current line
  					   buffer */
  		*firstColP,
  		*lastColP,
		*dstBuf,
		*lastLnP,
		*tIP0;
  WlzIntervalDomain *jdp;
  WlzObject 	*dstObj = NULL;
  WlzSeqParWSpace spWSpace;		/* Work space which is passed on to
  					   the transform function. */
  WlzIntervalWSpace srcIWsp,
  		dstIWsp;
  WlzGreyWSpace srcGWsp,
  		dstGWsp;
  int		*lineBufs[15],      	/* lineBufs is the array of line
  					   buffers needed to obtain
					   neighbouring points. */
		*adrbase[15];

  WLZ_DBG((WLZ_DBG_LVL_FN|WLZ_DBG_LVL_1),
  	  ("WlzSeqPar FE %p %d %d %d %d %d %p %p %p\n",
	   srcObj, newObjFlag, sequentialFlag, (int )rasterDir, bdrSz, bkgVal,
	   transformData, transformFn, dstErr));
  if(srcObj == NULL)
  {
    errNum = WLZ_ERR_OBJECT_NULL;
    if(dstErr)
    {
      *dstErr = errNum;
    }
    return(NULL);
  }
  if((srcObj->type != WLZ_2D_DOMAINOBJ) || (srcObj->values.core == NULL) ||
     (srcObj->domain.core == NULL))
  {
    errNum = WLZ_ERR_OBJECT_TYPE;
    if(dstErr)
    {
      *dstErr = errNum;
    }
    return(NULL);
  }
  /*
   * Make an array spWSpace.adrptr of pointers with range [-7,7]
   */
  spWSpace.adrptr = adrbase + 7;
  spWSpace.brdrsz = bdrSz;
  jdp = srcObj->domain.i;
  bdrP1 = -bdrSz - 1;
  /*
   * The buffer must contain both the current line and bdrSz lines each side.
   */
  numBufs = (bdrSz * 2) + 1;
  kol1 = kol = jdp->kol1;
  lineSz = jdp->lastkl - kol + numBufs;
  /*
   * Some pointers to first/last line and column positions
   * to accomodate different rasters
   */
  firstColP = &dstIWsp.lftpos;
  lastColP = &dstIWsp.rgtpos;
  lastLnP = &jdp->lastln;
  /*
   * spWSpace.kdelta is increment to adrs when processing points
   * if positive, procede left to right in lines
   * if negative procede right to left
   * spWSpace.ldelta is increment to line number
   * if positive, the raster is proceeding in increasing line numbers
   * if negative the raster is procceding with decreasing line numbers
   */
  spWSpace.kdelta = 1;
  spWSpace.ldelta = 1;
  /*
   * Alter parameters for right to left rasters
   */
  if(!sequentialFlag)
  {
    rasterDir = WLZ_RASTERDIR_ILIC;
  }
  if((rasterDir == WLZ_RASTERDIR_ILDC) || (rasterDir == WLZ_RASTERDIR_DLDC))
  {
    tIP0 = firstColP;
    firstColP = lastColP;
    lastColP = tIP0;
    spWSpace.kdelta = -1;
  }
  /*
   * Alter parameters for bottom to top rasters
   */
  if((rasterDir == WLZ_RASTERDIR_DLIC) || (rasterDir == WLZ_RASTERDIR_DLDC))
  {
    spWSpace.ldelta = -1;
    lastLnP = &jdp->line1;
  }
  lineOffset = bdrSz * spWSpace.ldelta;
  /* 
   * Allocate space to buffers 
   */
  lineBufSpace = (int *)AlcCalloc(lineSz * (numBufs + 1), sizeof(int));
  for(idx = 0; idx < numBufs; ++idx)
  {
    lineBufs[idx] = lineBufSpace + (idx + 1) * lineSz;
  }
  /*
   * Either use existing object or create a new grey table object
   * according to the newObjFlag.
   * If a new object is required then it is created with the SAME interval
   * list and property list and a DIFFERENT but IDENTICAL grey table.
   */
  if(newObjFlag)
  {
    dstObj = WlzNewGrey(srcObj, &errNum);
  }
  else
  {
    dstObj = srcObj;
  }
  /*
   * Use nxxiv in transplant mode, placing and taking grey values
   * from the line buffers
   * srcIWsp is the workspace for entering values into the line buffers
   * dstIWsp is the workspace for processing the intervals and replacing
   * the transformed values into the grey table
   */
  srcGWsp.gvio = 1;		  /* output (since we are specifying tranpl) */
  dstGWsp.gvio = 0;						    /* input */
  errNum = WlzInitGreyRasterScan(srcObj, &srcIWsp, &srcGWsp, rasterDir, 1);
  if(errNum == WLZ_ERR_NONE)
  {
    errNum = WlzInitGreyRasterScan(dstObj, &dstIWsp, &dstGWsp, rasterDir, 1);
  }
  if(errNum != WLZ_ERR_NONE)
  {
    if(dstErr)
    {
      *dstErr = errNum;
    }
    return(NULL);
  }
  /*
   * curLine is the line currently being processed
   * inLine is the last line entered into the line buffers
   * initialize it to an imaginary line just before the first border line
   */
  (void )WlzNextInterval(&srcIWsp);
  nextLine = srcIWsp.linpos;
  inLine = srcIWsp.linpos - (spWSpace.ldelta * (bdrSz + 1));
  /*
   * Process the next interval
   */
  while((errNum == WLZ_ERR_NONE) &&
        ((errNum = WlzNextGreyInterval(&dstIWsp)) == WLZ_ERR_NONE))
  {
    /*
     * When processing curLine, the line buffer must contain
     * lines upto needed=curLine+border width
     */
    curLine = dstIWsp.linpos;
    needed = curLine + lineOffset;
    /*
     * Next action depends which lines are aleady in the line buffers
     */
    howManyLn = (needed - inLine) * spWSpace.ldelta;
    WLZ_DBG((WLZ_DBG_LVL_3),
  	    ("WlzSeqPar 01 %d %d\n",
	     inLine, curLine));
    if(howManyLn < 0)
    {
      /*
       * This is an error it is impossible to have input a line before needed
       */
      errNum = WLZ_ERR_DOMAIN_DATA;
      if(dstErr)
      {
        *dstErr = errNum;
      }
      return(NULL);
    }
    else if(howManyLn > 0)
    {
      /*
       * If howManyLn > 0 we need to input some lines to input buffer
       * routine to fill the input buffers used to determine the value
       * of the transform needed = maximal(minimal)line needed to be filled
       * into the buffer
       * if backwards raster, needed = curLine - bdrSz
       * if forwards raster, needed = curLine + bdrSz
       * nextLine = line number of the next interval to be filed by nxxiv
       */
      while(1)
      {
	if((needed - nextLine) * spWSpace.ldelta < 0)
	{
	  /*
	   * Next line needed less far away than next line available
	   * from nxxint fill required buffer lines with bkgVal and return
	   * minLine = WlzSeqParPosMod(inLine, numBufs), i.e. the remainder
	   * of inLine when divided by numBufs.
	   * It thus can be used as the offset into the array of
	   * logical line addresses to determine which line in the
	   * circular buffer inLine is being stored
	   */
	  while(inLine != needed)
	  {
	    inLine += spWSpace.ldelta;
	    minLine = WlzSeqParPosMod(inLine, numBufs);
	    WlzValueSetInt(lineBufs[minLine], bkgVal, lineSz);
	  }
	  break;
	}
	/*
	 * Line(s) needed include some real lines, i.e. obtained from nxxiv
	 * first fill buffer with bkgVal
	 */
	while(inLine != nextLine)
	{
	  inLine += spWSpace.ldelta;
	  minLine = WlzSeqParPosMod(inLine, numBufs);
	  WlzValueSetInt(lineBufs[minLine], bkgVal, lineSz);
	}
	/*
	 * nxxint interval to be put into buffer calculate adrs in
	 * buffer by adding leftcol to logical adrs stored in
	 * lineBufs[minLine]. then insert with nxxiv
	 */
	do
	{
	  srcGWsp.u_grintptr.inp = lineBufs[minLine] +
	  			   srcIWsp.lftpos + bdrSz - kol1;
	  WlzGreyInterval(&srcIWsp);
	  /*
	   * Call nxxint to get next interval if in same line store in buffer
	   */
	  if(WlzNextInterval(&srcIWsp) != 0)
	  {
	    /*
	     * When nxxint has finished all interval set a high value into
	     * nextLine, so all future lines input will be dummy lines
	     */
	    nextLine = (*lastLnP) - (bdrP1 * spWSpace.ldelta);
	    goto filledLABEL;
	  }
	} while(srcIWsp.nwlpos == 0);
	/*
	 * If next interval in new line,store new line number and
	 * jump to start of routine to see what sort of line buffer
	 * processing is required next
	 */
	nextLine = srcIWsp.linpos;
      }
    }
    /*
     * Line buffers filled for processing of this line either from above call
     * or buffer filled for previous intervals processed on this line
     * kol is the first point in the interval to be processed
     * itop is the last point to be processed
     */
filledLABEL: 					    /* LABEL! see goto above */
    kol = *firstColP;
    itop = *lastColP;
    /*
     * First load spWSpace.adrptr with addresses of required neighbors
     */
    idx = bdrP1;
    while(idx++ < bdrSz)
    {
      tI0 = idx * spWSpace.ldelta;
      spWSpace.adrptr[idx] = lineBufs[WlzSeqParPosMod(curLine + tI0,
      						      numBufs)] +
			     kol + bdrSz - kol1;
    }
    /*
     * Then set the pointer where the transformed value will be placed
     * if parallel mode, adrs is in current line buffer
     * if sequential mode, adrs is in input buffer
     * dstGWsp.grintptr is the location in the nxxiv workspace
     * giving the location from which nxxiv will transplant
     * values into the grey table
     */
    if(sequentialFlag)
    {
      dstBuf = spWSpace.adrptr[0];
    }
    else
    {
      dstBuf = lineBufSpace + bdrSz;
    }
    dstGWsp.u_grintptr.inp = dstBuf + dstIWsp.lftpos - kol;
    /*
     * Procede thru interval,calling the transforming function
     * at each point and storing the result where required
     */
    kol -= spWSpace.kdelta;
    while(kol != itop)
    {
      kol += spWSpace.kdelta;
      *dstBuf = (*transformFn)(&spWSpace, transformData);
      /*
       * after each point, update the neighbor adrs and the output adrs
       */
      idx = bdrP1;
      while(idx++ < bdrSz)
      {
	spWSpace.adrptr[idx] += spWSpace.kdelta;
      }
      dstBuf += spWSpace.kdelta;
    }
    /*
     * Having finished this interval proceed to the next
     */
  }
  if(errNum == WLZ_ERR_EOO)
  {
    errNum = WLZ_ERR_NONE;
  }
  if(lineBufSpace)
  {
    AlcFree((void *)lineBufSpace);
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  WLZ_DBG((WLZ_DBG_LVL_FN|WLZ_DBG_LVL_1),
  	  ("WlzSeqPar FX %p\n",
	   dstObj));
  return(dstObj);
}
Esempio n. 21
0
/*!
* \return	Woolz error code.
* \ingroup	WlzExtFF
* \brief	Reads an IPL header from the given file stream.
* \param	header			Given header data structure to be
*					filled in.
* \param	fP			Given input file stream.
*/
static WlzErrorNum WlzEffHeadReadIPL(WlzEffIPLHeader *header, FILE *fP)
{
  WlzGreyP	p;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  double	dBuf[4];
  
  p.dbp = dBuf;
  /* version, format and datatype */
  if( fread(p.v, sizeof(char), 6, fP) != 6 ){
    errNum = WLZ_ERR_READ_INCOMPLETE;
  }
  else {
    /* should test this version */
    strncpy(&(header->version[0]), (const char *)(p.ubp), 4);
    if( (header->format = p.ubp[4]) != 0 ){
      errNum = WLZ_ERR_PARAM_TYPE;
    }
    switch(p.ubp[5]){
    case 0:
      header->dType = WLZEFF_IPL_TYPE_UBYTE;
      break;
    case 1:
      header->dType = WLZEFF_IPL_TYPE_SHORT;
      break;
    case 2:
      header->dType = WLZEFF_IPL_TYPE_INT;
      break;
    case 3:
      header->dType = WLZEFF_IPL_TYPE_FLOAT;
      break;
    case 4:
      header->dType = WLZEFF_IPL_TYPE_COL_16;
      break;
    case 5:
      header->dType = WLZEFF_IPL_TYPE_COL_24;
      break;
    case 6:
      header->dType = WLZEFF_IPL_TYPE_U_16;
      break;
    default:
      errNum = WLZ_ERR_PARAM_TYPE;
      break;
    }
  }

  /* height and width */
  if( errNum == WLZ_ERR_NONE ){
    if( fread(p.v, sizeof(char), 4, fP) != 4 ){
      errNum = WLZ_ERR_READ_INCOMPLETE;
    }
    header->nWidth = *(p.inp);
  }
  if( errNum == WLZ_ERR_NONE ){
    if( fread(p.v, sizeof(char), 4, fP) != 4 ){
      errNum = WLZ_ERR_READ_INCOMPLETE;
    }
    header->nHeight = *(p.inp);
  }

  /* various id's and modes */
  if( errNum == WLZ_ERR_NONE ){
    if( fread(p.v, sizeof(char), 6, fP) != 6 ){
      errNum = WLZ_ERR_READ_INCOMPLETE;
    }
    header->fileClutID    = p.ubp[0];
    header->overlayInFile = p.ubp[1];
    header->viewMode      = p.ubp[4];
  }

  /* number of sections */
  if( errNum == WLZ_ERR_NONE ){
    if( fread(p.v, sizeof(char), 2, fP) != 2 ){
      errNum = WLZ_ERR_READ_INCOMPLETE;
    }
    header->nFrames = *(p.shp);
  }

  /* delta? plus reserved space */
  if( errNum == WLZ_ERR_NONE ){
    if( fread(p.v, sizeof(char), 8, fP) != 8 ){
      errNum = WLZ_ERR_READ_INCOMPLETE;
    }
    header->delta = *(p.dbp);
  }
  if( errNum == WLZ_ERR_NONE ){
    if( fread(p.v, sizeof(char), 4, fP) != 4 ){
      errNum = WLZ_ERR_READ_INCOMPLETE;
    }
  }

  /* units string */
  if( errNum == WLZ_ERR_NONE ){
    if( fread(p.v, sizeof(char), 10, fP) != 10 ){
      errNum = WLZ_ERR_READ_INCOMPLETE;
    }
    strncpy(&(header->units[0]), (const char *) p.v, 10);
  }

  /* normalisation data */
  if( errNum == WLZ_ERR_NONE ){
    if( fread(p.v, sizeof(char), 4, fP) != 4 ){
      errNum = WLZ_ERR_READ_INCOMPLETE;
    }
    header->normType    = p.ubp[1];
    header->normSource  = p.ubp[2];
    header->numRegNarks = p.ubp[3];
  }
  if( errNum == WLZ_ERR_NONE ){
    if( fread(p.v, sizeof(char), 8, fP) != 8 ){
      errNum = WLZ_ERR_READ_INCOMPLETE;
    }
    header->normMin = *(p.dbp);
  }
  if( errNum == WLZ_ERR_NONE ){
    if( fread(p.v, sizeof(char), 4, fP) != 4 ){
      errNum = WLZ_ERR_READ_INCOMPLETE;
    }
  }
  if( errNum == WLZ_ERR_NONE ){
    if( fread(p.v, sizeof(char), 8, fP) != 8 ){
      errNum = WLZ_ERR_READ_INCOMPLETE;
    }
    header->normMax = *(p.dbp);
  }
  if( errNum == WLZ_ERR_NONE ){
    if( fread(p.v, sizeof(char), 4, fP) != 4 ){
      errNum = WLZ_ERR_READ_INCOMPLETE;
    }
  }

  /* now read the color table */
  if( errNum == WLZ_ERR_NONE ){
    if( (header->colorTable = (void *) AlcCalloc(2048, sizeof(char))) == NULL ){
      errNum = WLZ_ERR_MEM_ALLOC;
    }
    else {
      if( fread(header->colorTable, sizeof(char), 2048, fP) != 2048 ){
	errNum = WLZ_ERR_READ_INCOMPLETE;
      }
    }
  }

  return(errNum);
}
Esempio n. 22
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;
}
Esempio n. 23
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;
} 
Esempio n. 24
0
int             main(int argc, char *argv[])
{
  int           id0,
                id1,
                rpt,
                option,
                ok = 1,
		usage = 0,
		special = 0,
                sz = 10,
                nRpt = 1,
                itr = 1000,
		timer = 0,
                verbose = 0;
  long		seed = 0;
  double        del,
  		tol = 0.000001,
		zF = 0.9;
  double        *b0 = NULL,
                *b1 = NULL,
                *x0 = NULL,
                *i0 = NULL,
                *r0 = NULL;
  AlgMatrix     a0,
                a1,
                w;
  AlgMatrixTestMtd mtd = ALG_MATRIX_TST_MTD_CG;
  AlgMatrixType aType = ALG_MATRIX_RECT;
  AlgError      errCode = ALG_ERR_NONE;
  struct timeval times[3];
  const char    *optList = "d:n:r:t:vz:CLPQSRTUY";

  a0.core = NULL;
  a1.core = NULL;
  w.core = NULL;
  while((usage == 0) && ((option = getopt(argc, argv, optList)) != -1))
  {
    switch(option)
    {
      case 'd':
        if(sscanf(optarg, "%ld", &seed) != 1)
	{
	  usage = 1;
	}
      case 'n':
        if((sscanf(optarg, "%d", &sz) != 1) || (sz < 1))
        {
          usage = 1;
        }
        break;
      case 'r':
        if((sscanf(optarg, "%d", &nRpt) != 1) || (nRpt < 0))
        {
          usage = 1;
        }
        break;
      case 't':
        if((sscanf(optarg, "%lg", &tol) != 1) || (tol < 0.0) || (tol > 0.1))
        {
          usage = 1;
        }
        break;
      case 'v':
        verbose = 1;
        break;
      case 'z':
        if((sscanf(optarg, "%lg", &zF) != 1) || (zF < 0.0) || (tol > 1.0))
        {
          usage = 1;
        }
        break;
      case 'C':
        mtd = ALG_MATRIX_TST_MTD_CG;
        break;
      case 'L':
        aType = ALG_MATRIX_LLR;
        break;
      case 'P':
        special = 1;
        break;
      case 'Q':
        mtd = ALG_MATRIX_TST_MTD_LSQR;
        break;
      case 'S':
        mtd = ALG_MATRIX_TST_MTD_SVD;
        break;
      case 'R':
        aType = ALG_MATRIX_RECT;
        break;
      case 'T':
        timer = 1;
        break;
      case 'U':
        mtd = ALG_MATRIX_TST_MTD_LU;
        break;
      case 'Y':
        aType = ALG_MATRIX_SYM;
        break;
      default:
        usage = 1;
        break;
    }
  }
  ok = (usage == 0);
  if(ok)
  {
    AlgRandSeed(seed);
    a0 = AlgMatrixNew(aType, sz, sz, sz * sz, tol, NULL);
    a1 = AlgMatrixNew(aType, sz, sz, sz * sz, tol, NULL);
    if(verbose)
    {
      r0 = (double *)AlcMalloc(sz * sizeof(double));
    }
    w.rect = AlgMatrixRectNew(4, sz, NULL);
    b0 = (double *)AlcCalloc(sz, sizeof(double));
    b1 = (double *)AlcCalloc(sz, sizeof(double));
    x0 = (double *)AlcCalloc(sz, sizeof(double));
    i0 = (double *)AlcCalloc(sz, sizeof(double));
    for(id1 = 0; id1 < sz; ++id1)
    {
      double v;

      for(id0 = 0; id0 < id1; ++id0)
      {
	v = AlgRandUniform();
	if((v > zF) && (zF < 0.999999))
	{
	  v = 0.5 * (v - zF) / (1.0 - zF);
	  AlgMatrixSet(a0, id1, id0, v);
	  AlgMatrixSet(a0, id0, id1, v);
	}
      }
      v = ((2 * id1) % 5) * 0.2 + 1.0;
      AlgMatrixSet(a0, id1, id1, v);
      *(b0 + id1) = ((id1) % 3) * AlgRandUniform();
      *(i0 + id1) = 1.0;
    }
    if(verbose != 0)
    {
      AlgVectorCopy(b1, b0, sz);
      (void )fprintf(stderr, "A = [\n");
      (void )AlgMatrixWriteAscii(a0, stderr);
      (void )fprintf(stderr, "]\nb = [\n");
      for(id0 = 0; id0 < sz; ++id0)
      {
        if(id0 < (sz - 1))
        {
          (void )fprintf(stderr, "%g;\n",  b0[id0]);
        }
        else
        {
          (void )fprintf(stderr, "%g]\n",  b0[id0]);
        }
      }
    }
    for(rpt = 0; rpt < nRpt; ++rpt)
    {
      long tL;

      switch(mtd)
      {
        case ALG_MATRIX_TST_MTD_CG:
          del = tol;
          AlgVectorCopy(x0, i0, sz);
	  gettimeofday(times + 0, NULL);
          errCode = AlgMatrixCGSolve(a0, x0, b0, w, NULL, NULL,
                                     tol, itr, &del, &itr);
	  gettimeofday(times + 1, NULL);
          break;
        case ALG_MATRIX_TST_MTD_LSQR:
	  gettimeofday(times + 0, NULL);
          errCode = AlgMatrixSolveLSQR(a0, b0, x0,
                                       1.0e-10, 1.0e-10, 1.0e-10, itr, 0,
                                       NULL, &tL, NULL, NULL, NULL,
                                       NULL, NULL);
	  gettimeofday(times + 1, NULL);
          itr = tL;
          break;
	case ALG_MATRIX_TST_MTD_LU:
          AlgVectorCopy(x0, b0, sz);
          (void )AlgMatrixCopy(a1, a0);
	  if((special != 0) && ((sz == 3) || (sz == 4)) &&
	     (aType == ALG_MATRIX_RECT))
	  {
	    if(sz == 3)
	    {
	      gettimeofday(times + 0, NULL);
	      errCode = AlgMatrixLUSolveRaw3(a1.rect->array, x0, 1);
	      gettimeofday(times + 1, NULL);
	    }
	    else /* sz == 4 */
	    {
	      gettimeofday(times + 0, NULL);
	      errCode = AlgMatrixLUSolveRaw4(a1.rect->array, x0, 1);
	      gettimeofday(times + 1, NULL);
	    }
	  }
	  else
	  {
	    gettimeofday(times + 0, NULL);
	    errCode = AlgMatrixLUSolve(a1, x0, 1);
	    gettimeofday(times + 1, NULL);
	  }
	  break;
        case ALG_MATRIX_TST_MTD_SVD:
          AlgVectorCopy(x0, b0, sz);
          (void )AlgMatrixCopy(a1, a0);
	  gettimeofday(times + 0, NULL);
          errCode = AlgMatrixSVSolve(a1, x0, tol, NULL);
	  gettimeofday(times + 1, NULL);
          break;
        default:
          break;
      }
    }
    if(verbose != 0)
    {
      (void )fprintf(stderr, "x = [\n");
      for(id1 = 0; id1 < sz; ++id1)
      {
        (void )fprintf(stderr, "%g", *(x0 + id1));
        if(id1 < (sz - 1))
        {
          (void )fprintf(stderr, ";\n");
        }
        else
        {
          (void )fprintf(stderr, "]\n");
        }
      }
      AlgMatrixVectorMul(r0, a0, x0);
      AlgVectorSub(r0, r0, b1, sz);
      (void )fprintf(stderr, "r = [\n");
      for(id1 = 0; id1 < sz; ++id1)
      {
        (void )fprintf(stderr, "%g", *(r0 + id1));
        if(id1 < (sz - 1))
        {
          (void )fprintf(stderr, ";\n");
        }
        else
        {
          (void )fprintf(stderr, "]\n");
        }
      }
    }
    else
    {
      for(id1 = 0; id1 < sz; ++id1)
      {
        (void )printf("%g\n", *(x0 + id1));
      }
    }
    if(timer)
    {
      ALC_TIMERSUB(times + 1, times + 0, times + 2);
      (void )fprintf(stderr,
		     "%s: Elapsed time = %g\n",
		     *argv, times[2].tv_sec + (0.000001 * times[2].tv_usec));
    }
  }
  else
  {
    (void )fprintf(stderr,
                   "Usage: %s [-d#] [-n#] [-r#] [-t#] [-v] [-z#]\n"
		   "       [-C] [-S] [-R] [-T] [-Y]\n%s",
                   *argv,
                   "Test for timing solution of Ax = b using the Conjugate\n"
                   "Gradient and Singular Value Decomposition algorithms.\n"
		   "  -d  Seed value.\n"
                   "  -n  Matrix size.\n"
                   "  -r  Number of repeat solutions.\n"
		   "  -t  Tollerance value.\n"
                   "  -v  Verbose output (matching MATLAB) with residuals.\n"
		   "  -z  Fraction of zero entries.\n"
                   "  -C  Use the Conjugate Gradient algorithm.\n"
                   "  -L  Use a linked list row matrix.\n"
		   "  -P  Use special version code.\n"
                   "  -Q  Use the LSQR algorithm.\n"
                   "  -S  Use the Singular Value Decomposition algorithm.\n"
                   "  -T  Time solution.\n"
                   "  -R  Use a rectangular matrix.\n"
                   "  -Y  Use a symetric matrix.\n");
  }
  AlgMatrixFree(a0);
  AlgMatrixFree(a1);
  AlgMatrixFree(w);
  AlcFree(b0);
  AlcFree(b1);
  AlcFree(i0);
  AlcFree(r0);
  AlcFree(x0);
  exit(errCode);
}
Esempio n. 25
0
/*!
* \return	Array of interiority scores with a score for each of the
* 		test objects or NULL on error.
* \ingroup	WlzFeatures
* \brief	Computes an interiority score for each test object with
* 		respect to the reference object. See WlzInteriority().
		This function computes the distance transform for the
		reference domain once and then uses this for each of the
		test domains.
		If not NULL the returned array of scores should be freed
		using AlcFree().
* \param	refObj			Given reference object.
* \param 	nTstObj			Number of test objects.
* \param	tstObjs			Array of test objects.
* \param	dstErr			Destination error pointer, may be NULL.
*/
double				*WlzInteriorityN(
				  WlzObject *refObj,
				  int nTstObj,
				  WlzObject **tstObjs,
				  WlzErrorNum *dstErr)
{
  WlzObject	*dis = NULL;
  double	*scores = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  /* Check given objects. */
  if(refObj == NULL)
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if((refObj->type != WLZ_2D_DOMAINOBJ) &&
          (refObj->type != WLZ_3D_DOMAINOBJ) &&
	  (refObj->type != WLZ_EMPTY_OBJ))
  {
    errNum = WLZ_ERR_OBJECT_TYPE;
  }
  else if((refObj->type != WLZ_EMPTY_OBJ) &&
          (refObj->domain.core == NULL))
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if(nTstObj < 0)
  {
    errNum = WLZ_ERR_PARAM_DATA;
  }
  else if(tstObjs == NULL)
  {
    errNum = WLZ_ERR_PARAM_NULL;
  }
  else
  {
    int 	i;

    for(i = 0; (errNum == WLZ_ERR_NONE) && (i < nTstObj); ++i)
    {
      if(tstObjs[i] == NULL)
      {
        errNum = WLZ_ERR_OBJECT_NULL;
      }
      if(tstObjs[i]->type != WLZ_EMPTY_OBJ)
      {
	if(tstObjs[i]->type != refObj->type)
	{
	  errNum = WLZ_ERR_OBJECT_TYPE;
	}
	else if(tstObjs[i]->domain.core == NULL)
	{
	  errNum = WLZ_ERR_DOMAIN_NULL;
	}
      }
    }
  }
  /* Allocate the scores array. */
  if(errNum == WLZ_ERR_NONE)
  {
    if((scores = (double *)AlcCalloc(nTstObj, sizeof(double))) == NULL)
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  /* Compute the boundary distance object. */
  if((errNum == WLZ_ERR_NONE) && (refObj->type != WLZ_EMPTY_OBJ))
  {
    dis = WlzAssignObject(
          WlzInteriorityCompDisObj(refObj, &errNum), NULL);
  }
  /* For each test object compute it's interiority score with respect
   * to the distance object. */
  if(errNum == WLZ_ERR_NONE)
  {
    int		i;

#ifdef _OPENMP
#pragma omp parallel for
#endif
    for(i = 0; i < nTstObj; ++i)
    {
      if(errNum == WLZ_ERR_NONE)
      {
	WlzErrorNum errNum2 = WLZ_ERR_NONE;

	scores[i] = WlzInteriorityPrv(dis, tstObjs[i], &errNum2);
	if(errNum2 != WLZ_ERR_NONE)
	{
#ifdef _OPENMP
#pragma omp critical
	  {
#endif
            errNum = errNum2;
#ifdef _OPENMP
	  }
#endif
	}
      }
    }
  }

  (void )WlzFreeObj(dis);
  if(errNum != WLZ_ERR_NONE)
  {
    AlcFree(scores);
    scores = NULL;
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(scores);
}
Esempio n. 26
0
/*!
* \return	Error code.
* \ingroup      AlgMatrix
* \brief	Performs singular value decomposition of the given
*		matrix (A) and computes two additional matricies
*		(U and V) such that:
*		  A = U.W.V'
*		where V' is the transpose of V.
*		The code for AlgMatrixSVDecomp was derived from:
*		Numerical Recipies function svdcmp(), EISPACK
*		subroutine SVD(), CERN subroutine SVD() and ACM
*		algorithm 358.
*		See AlgMatrixSVSolve() for a usage example.
* \param	aMat			The given matrix A, and U on
*					return.
* \param	wVec			The diagonal matrix of singular
*					values, returned as a vector.
* \param	vMat			The matrix V (not it's
*					transpose).
*/
AlgError	AlgMatrixSVDecomp(AlgMatrix aMat, double *wVec, AlgMatrix vMat)
{
  int		cnt0,
  		flag,
  		idI,
		idJ,
		idK,
		idL = 0,
		its,
		nNL,
		nMI,
		nNM;
  double 	tD0,
  		c,
 		f,
		h,
		s,
		x,
		y,
		z,
		aNorm = 0.0,
		g = 0.0,
		scale = 0.0;
  double	*tDP0,
		*tDP1,
  		*tDVec = NULL;
  double	**tDPP0;
  const int	maxIts = 100;  /* Maximum iterations to find singular value. */
  const double	aScale = 0.01;  /* Used with aNorm to test for small values. */
  AlgError	errCode = ALG_ERR_NONE;

  ALG_DBG((ALG_DBG_LVL_FN|ALG_DBG_LVL_1),
	  ("AlgMatrixSVDecomp FE\n"));
  if((aMat.core == NULL) || (aMat.core->type != ALG_MATRIX_RECT) ||
     (vMat.core == NULL) || (aMat.core->type != vMat.core->type) ||
     (aMat.core->nR <= 0) || (aMat.core->nR < aMat.core->nC) ||
     (aMat.core->nR != vMat.core->nR) || (aMat.core->nC != vMat.core->nC) ||
     (wVec == NULL))
  {
    errCode = ALG_ERR_FUNC;
  }
  else if((tDVec = (double *)AlcCalloc(sizeof(double), aMat.rect->nC)) == NULL)
  {
    errCode = ALG_ERR_MALLOC;
  }
  else
  {
    int	   nM,
    	   nN;
    double **aAry,
    	   **vAry;

    nM = aMat.rect->nR;
    nN = aMat.rect->nC;
    aAry = aMat.rect->array;
    vAry = vMat.rect->array;
    /* Householder reduction to bidiagonal form */
    for(idI = 0; idI < nN; ++idI)
    {
      idL = idI + 1;
      nNL = nN - idL;
      nMI = nM - idI;
      tDVec[idI] = scale * g;
      g = s = scale = 0.0;
      if(idI < nM)
      {
        cnt0 = nMI;
	tDPP0 = aAry + idI;
	while(cnt0-- > 0)	/* for(idK = idI; idK < nM; ++idK) */
	{
	  tD0 = *(*tDPP0++ + idI);
	  scale += fabs(tD0);	/* scale += fabs(aMat[idK][idI]); */
	}
	if(scale > DBL_EPSILON)			   /* scale must always >= 0 */
	{
	  cnt0 = nMI;
	  tDPP0 = aAry + idI;
	  while(cnt0-- > 0)	/* for(idK = idI; idK < nM; ++idK) */
	  {
	    tDP0 = *tDPP0++ + idI;
	    *tDP0 /= scale;	/* aMat[idK][idI] /= scale; */
	    s += *tDP0 * *tDP0;	/* s += aMat[idK][idI] * aMat[idK][idI]; */
	  }
	  f = aAry[idI][idI];
	  g = (f > 0.0)? -(sqrt(s)): sqrt(s);
	  h = (f * g) - s;
	  aAry[idI][idI] = f - g;
	  if(idI != (nN - 1))
	  {
	    for(idJ = idL; idJ < nN; ++idJ)
	    {
	      s = 0.0;
	      cnt0 = nMI;
	      tDPP0 = aAry + idI;
	      while(cnt0-- > 0)	/* for(idK = idI; idK < nM; ++idK) */
	      {
	        s += *(*tDPP0 + idI) * *(*tDPP0 + idJ);
		++tDPP0;	/* s += aMat[idK][idI] * aMat[idK][idJ]; */
	      }
	      f = s / h;
	      cnt0 = nMI;
	      tDPP0 = aAry + idI;
	      while(cnt0-- > 0) /* for(idK = idI; idK < nM; ++idK) */
	      {
	        *(*tDPP0 + idJ) += f * *(*tDPP0 + idI);
		++tDPP0;	/* aMat[idK][idJ] += f * aMat[idK][idI]; */
	      }
	    }
	  }
	  cnt0 = nMI;
	  tDPP0 = aAry + idI;
	  while(cnt0-- > 0)	/* for(idK = idI; idK < nM; ++idK) */
	  {
	    *(*tDPP0++ + idI) *= scale; /* aMat[idK][idI] *= scale; */
	  }
	}
      }
      wVec[idI] = scale * g;
      g = s = scale = 0.0;
      if((idI < nM) && (idI != (nN - 1)))
      {
	cnt0 = nNL;
	tDP0 = *(aAry + idI) + idL;
	while(cnt0-- > 0)	/* for(idK = idL; idK < nN; ++idK) */
	{
	  scale += fabs(*tDP0++); /* scale += fabs(aMat[idI][idK]); */
	}
	if(scale > DBL_EPSILON)				/* scale always >= 0 */
	{
	  cnt0 = nNL;
	  tDP0 = *(aAry + idI) + idL;
	  while(cnt0-- > 0)	/* for(idK = idL; idK < nN; ++idK) */
	  {
	    *tDP0 /= scale;	/* aMat[idI][idK] /= scale; */
	    tD0 = *tDP0++;
	    s += tD0 * tD0;	/* s += aMat[idI][idK] * aMat[idI][idK]; */
	  }
	  f = aAry[idI][idL];
	  g = (f > 0.0)? -(sqrt(s)): sqrt(s);
	  h = (f * g) - s;
	  aAry[idI][idL] = f - g;
	  cnt0 = nNL;
	  tDP0 = *(aAry + idI) + idL;
	  tDP1 = tDVec + idL;
	  while(cnt0-- > 0)	/* for(idK = idL; idK < nN; ++idK) */
	  {
	    *tDP1++ = *tDP0++ / h; /* tDVec[idK] = aMat[idI][idK] / h; */
	  }
	  if(idI != (nM - 1))
	  {
	    for(idJ = idL; idJ < nM; ++idJ)
	    {
	      s = 0.0;
	      cnt0 = nNL;
	      tDP0 = *(aAry + idI) + idL;
	      tDP1 = *(aAry + idJ) + idL;
	      while(cnt0-- > 0)	/* for(idK = idL; idK < nN; ++idK) */
	      {
	        s += *tDP1++ * *tDP0++; /* s += aMat[idJ][idK] *
					        aMat[idI][idK]; */
	      }
	      cnt0 = nNL;
	      tDP0 = tDVec + idL; 
	      tDP1 = *(aAry + idJ) + idL;
	      while(cnt0-- > 0)	/* for(idK = idL; idK < nN; ++idK) */
	      {
	        *tDP1++ += s * *tDP0++; /* aMat[idJ][idK] += s * tDVec[idK]; */
	      }
	    }
	  }
	  cnt0 = nNL;
	  tDP0 = *(aAry + idI) + idL;
	  while(cnt0-- > 0)	/* for(idK = idL; idK < nN; ++idK) */
	  {
	    *tDP0++ *= scale;	/* aMat[idI][idK] *= scale; */
	  }
	}
      }
      if((tD0 = fabs(wVec[idI]) + fabs(tDVec[idI])) > aNorm)
      {
        aNorm = tD0;
      }
    }
    /* Accumulate right-hand transformations. */
    for(idI = nN - 1; idI >= 0; --idI)
    {
      if(idI < (nN - 1))
      {
	nNL = nN - idL;
	if(fabs(g) > DBL_EPSILON)
	{
	  cnt0 = nNL;
	  tDP0 = *(aAry + idI) + idL;
	  tD0 = *tDP0;
	  tDPP0 = vAry + idL;
	  while(cnt0-- > 0)	/* for(idJ = idL; idJ < nN; ++idJ) */
	  {
	    			/* vMat[idJ][idI] = (aMat[idI][idJ] /
				 		     aMat[idI][idL]) /g */
	    *(*tDPP0++ + idI) = (*tDP0++ / tD0) / g; /* Double division to try
	    						and avoid underflow */
	  }
	  for(idJ = idL; idJ < nN; ++idJ)
	  {
	    s = 0.0;
	    cnt0 = nNL;
	    tDP0 = *(aAry + idI) + idL;
	    tDPP0 = vAry + idL;
	    while(cnt0-- > 0)	/* for(idK = idL; idK < nN; ++idK) */
	    {
	      s += *tDP0++ * *(*tDPP0++ + idJ); /* s += aMat[idI][idK] *
	      						vMat[idK][idJ]; */
	    }
	    cnt0 = nNL;
	    tDPP0 = vAry + idL;
	    while(cnt0-- > 0)	
	    {
	      tDP0 = *tDPP0++;
	      *(tDP0 + idJ) += s * *(tDP0 + idI); /* vMat[idK][idJ] += s *
	      						     vMat[idK][idI]; */
	    }
	  }
	}
	cnt0 = nNL;
	tDP0 = *(vAry + idI) + idL;
	tDPP0 = vAry + idL;
	while(cnt0-- > 0)	/* for(idJ = idL; idJ < nN; ++idJ) */
	{
	  *tDP0++ = 0.0;	   /* vMat[idI][idJ] = 0.0 */
	  *(*tDPP0++ + idI) = 0.0; /* vMat[idJ][idI] = 0.0; */
	}
      }
      vAry[idI][idI] = 1.0;
      g = tDVec[idI];
      idL = idI;
    }
    /* Accumulate left-hand transformations. */
    for(idI = nN - 1; idI >= 0; --idI)
    {
      idL = idI + 1;
      nNL = nN - idL;
      nMI = nM - idI;
      g = wVec[idI];
      if(idI < (nN - 1))
      {
	cnt0 = nNL;
	tDP0 = *(aAry + idI) + idL;
	while(cnt0-- > 0)	/* for(idJ = idL; idJ < nN; ++idJ) */
	{
	  *tDP0++ = 0.0;	/* aMat[idI][idJ] = 0.0; */
	}
      }
      if(fabs(g) > DBL_EPSILON)
      {
	g = 1.0 / g;
	if(idI != (nN - 1))
	{
	  for(idJ = idL; idJ < nN; ++idJ)
	  {
	    s = 0.0;
	    cnt0 = nMI - 1;
	    tDPP0 = aAry + idL;
	    while(cnt0-- > 0)	/* for(idK = idL; idK < nM; ++idK) */
	    {
	      tDP0 = *tDPP0++;
	      s +=  *(tDP0 + idI) * *(tDP0 + idJ); /* s += aMat[idK][idI] * 
	      						   aMat[idK][idJ]; */
	    }
	    f = (s / aAry[idI][idI]) * g;
	    cnt0 = nMI;
	    tDPP0 = aAry + idI;
	    while(cnt0-- > 0)   /* for(idK = idI; idK < nM; ++idK) */
	    {
	      tDP0 = *tDPP0++;
	      *(tDP0 + idJ) += f * *(tDP0 + idI);
	    }
	  }
	}
	cnt0 = nMI;
	tDPP0 = aAry + idI;
	while(cnt0-- > 0)   /* for(idJ = idI; idJ < nM; ++idJ) */
	{
	  *(*tDPP0++ + idI) *= g; /* aMat[idJ][idI] *= g; */
	}
      } 
      else
      {
	cnt0 = nMI;
	tDPP0 = aAry + idI;
	while(cnt0-- > 0)	/* for(idJ = idI; idJ < nM; ++idJ) */
	{
	  *(*tDPP0++ + idI) = 0.0; /* aMat[idJ][idI] = 0.0; */
	}
      }
      aAry[idI][idI] += 1.0;
    }
    /* Diagonalize the bidiagonal form. */
    for(idK = nN - 1; (idK >= 0) && (errCode == ALG_ERR_NONE); --idK)
    {
      for(its = 1; its <= maxIts; ++its)
      {
	flag = 1;
	for(idL = idK; idL >= 0; --idL)
	{
	  nNM = idL - 1;
	  if(fabs((tDVec[idL] * aScale) + aNorm) == aNorm)
	  {
	    flag = 0;
	    break;
	  }
	  if((fabs(wVec[nNM] * aScale) + aNorm) == aNorm)
	  {
	    break;
	  }
	}
	if(flag)
	{
	  c = 0.0;
	  s = 1.0;
	  for(idI = idL; idI <= idK; ++idI)
	  {
	    f = s * tDVec[idI];

	    if(fabs(f * aScale) + aNorm != aNorm)
	    {
	      g = wVec[idI];
	      h = AlgMatrixSVPythag(f, g);
	      wVec[idI] = h;
	      h = 1.0 / h;
	      c = g * h;
	      s = (-f * h);
	      cnt0 = nM;
	      tDPP0 = aAry;
	      while(cnt0-- > 0)	/* for(idJ = 0; idJ < nM; ++idJ) */
	      {
	        tDP0 = *tDPP0 + nNM;
		tDP1 = *tDPP0++ + idI;
		y = *tDP0;	/* y = aMat[idJ][nNM]; */
		z = *tDP1;	/* z = aMat[idJ][idI]; */
		*tDP0 = (y * c) + (z * s); /* aMat[idJ][nNM] = (y * c) +
							       (z * s); */
		*tDP1 = (z * c) - (y * s); /* aMat[idJ][idI] = (z * c) -
							       (y * s); */
	      }
	    }
	  }
	}
	/* Test for convergence. */
	z = wVec[idK];
	if(idL == idK)
	{
	  if(z < 0.0)
	  {
	    wVec[idK] = -z;
	    cnt0 = nN;
	    tDPP0 = vAry;
	    while(cnt0-- > 0)	/* for(idJ = 0; idJ < nN; ++idJ) */
	    {
	      tDP0 = *tDPP0++ + idK;
	      *tDP0 = -*tDP0; /* vMat[idJ][idK] = -vMat[idJ][idK]; */
	    }
	  }
	  break;
	}
	if(its >= maxIts)
	{
	  errCode = ALG_ERR_MATRIX_SINGULAR;
	}
	else
	{
	  x = wVec[idL];
	  nNM = idK - 1;
	  y = wVec[nNM];
	  g = tDVec[nNM];
	  h = tDVec[idK];
	  f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y);
	  g = AlgMatrixSVPythag(f, 1.0);
	  f = (((x - z) * (x + z)) + 
	      (h * ((y / (f + ((f > 0)? g: -g))) - h))) / x;
	  c = s = 1.0;
	  for(idJ = idL; idJ <= nNM; ++idJ)
	  {
	    idI = idJ + 1;
	    g = tDVec[idI];
	    y = wVec[idI];
	    h = s * g;
	    g = c * g;
	    z = AlgMatrixSVPythag(f, h);
	    tDVec[idJ] = z;
	    c = f / z;
	    s = h / z;
	    f = (x * c) + (g * s);
	    g = (g * c) - (x * s);
	    h = y * s;
	    y = y * c;
	    cnt0 = nN;
	    tDPP0 = vAry;
	    while(cnt0-- > 0)	/* for(idM = 0; idM < nN; ++idM) */
	    {
	      tDP0 = *tDPP0 + idJ;
	      tDP1 = *tDPP0++ + idI;
	      x = *tDP0; 	/* x = vMat[idM][idJ]; */
	      z = *tDP1;	/* z = vMat[idM][idI]; */
	      *tDP0 = (x * c) + (z * s); /* vMat[idM][idJ] = (x * c) +
	      						     (z * s); */
	      *tDP1 = (z * c) - (x * s); /* vMat[idM][idI] = (z * c) -
	      						     (x * s); */
	    }
	    z = AlgMatrixSVPythag(f, h);
	    wVec[idJ] = z;
	    if(z > DBL_EPSILON)			       /* Can only be >= 0.0 */
	    {
	      z = 1.0 / z;
	      c = f * z;
	      s = h * z;
	    }
	    f = (c * g) + (s * y);
	    x = (c * y) - (s * g);
	    cnt0 = nM;
	    tDPP0 = aAry;
	    while(cnt0-- > 0)   /* for(idM = 0; idM < nM; ++idM) */
	    {
	      tDP0 = *tDPP0 + idJ;
	      tDP1 = *tDPP0++ + idI;
	      y = *tDP0;	/* y = aMat[idM][idJ]; */
	      z = *tDP1;	/* z = aMat[idM][idI]; */
	      *tDP0 = (y * c) + (z * s); /* aMat[idM][idJ] = (y * c) +
	      						     (z * s); */
	      *tDP1 = (z * c) - (y * s); /* aMat[idM][idI] = (z * c) -
	      						     (y * s); */
	    }
	  }
	  tDVec[idL] = 0.0;
	  tDVec[idK] = f;
	  wVec[idK] = x;
        }
      }
    }
    AlcFree(tDVec);
  }
  ALG_DBG((ALG_DBG_LVL_FN|ALG_DBG_LVL_1),
	  ("AlgMatrixSVDecomp FX %d\n",
	   (int )errCode));
  return(errCode);
}
Esempio n. 27
0
/*!
* \return	Woolz error code.
* \ingroup	WlzBinaryOps
* \brief	Computes a metric which quantifies the extent to which
* 		the domain of one of the given objects is offset from 
* 		the domain of the second. This is a symetric metric, ie
* 		\f$OST(\Omega_0, \Omega_1) \equiv OST(\Omega_0, \Omega_1)\f$.
*		A domain is computed which is equidistant from the domains
*		of the two given objects, is within maxDist of each object's
*		domain and is within the convex hull of the union of the
*		domains of the two given objects. Within this domain the
*		1st, 2nd and 3rd quantiles of the distance
*		(\f$q_0\f$, \f$q_1\f$ and \f$q_2\f$) are found.
*		The object's domains are classified as offset if
*		\f[
		frac{q_1}{q_1 + (q_1  - q_0) + (q_2 - q_1)} \geq 0.5
		\f]
*		ie
*		\f[
		frac{q_1}{q_1 + q_2 - q_0} \geq 0.5
		\f]
*		Small equi-distant domains with a volume less than half
*		the maximum distance do not classify the relationship as
*		an overlap.
* \param	o			Array with the two given spatial
* 					domain objects, must not be NULL
* 					and nor must the objects.
* \param	t			Array of temporary objects as in
* 					WlzRCCTOIdx.
* \param	maxDist			Maximum distance for offset. This
* 					is used to compute a distance object,
* 					large distances will significantly
* 					increase the processing time.
* \param	dQ0			Destination pointer for 1st quantile
* 					offset distance, must not be NULL.
* \param	dQ1			Destination pointer for 2nd quantile
* 					(ie median) offset distance,
* 					must not be NULL.
* \param	dQ2			Destination pointer for 3rd quantile
* 					offset distance, must not be NULL.
*/
static WlzErrorNum		WlzRCCOffset(
				  WlzObject **o,
				  WlzObject **t,
				  int maxDist,
				  int *dQ0,
				  int *dQ1,
				  int *dQ2)
{
  int		empty = 0;
  int		q[3] = {0};
  int		*dHist = NULL;
  WlzObject	*eObj = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  if(((o[0]->type == WLZ_2D_DOMAINOBJ) &&
      (o[1]->type == WLZ_2D_DOMAINOBJ)) ||
     ((o[0]->type == WLZ_3D_DOMAINOBJ) &&
      (o[1]->type == WLZ_3D_DOMAINOBJ)))
  {
    if((o[0]->domain.core == NULL) || (o[1]->domain.core == NULL))
    {
      errNum = WLZ_ERR_DOMAIN_NULL;
    }
  }
  else
  {
    errNum = WLZ_ERR_OBJECT_TYPE;
  }
  /* Compute distance transforms of the two given objects out to a given
   * maximum distance and then using these distances the equi-distant
   * domain between these two objects. The values of the eqi-distant object
   * are those of the distance between the objects.*/
  if(errNum == WLZ_ERR_NONE)
  {
    int		i;
    WlzObject	*sObj = NULL,
    		*cObj = NULL;
    WlzObject	*dObj[2];

    dObj[0] = dObj[1] = NULL;
    /* Create structuring element with which to dilate the given object
     * domains(by maxDist). */
    sObj = WlzAssignObject(
	   WlzMakeSphereObject(o[0]->type, maxDist, 0, 0, 0,
	                       &errNum), NULL);
    /* Create domain or convex hull of the union of the two given object
     * domains. */
    if(errNum == WLZ_ERR_NONE)
    {
      WlzObject	*uObj = NULL,
      		*xObj = NULL;

      errNum = WlzRCCMakeT(o, t, WLZ_RCCTOIDX_O0O1U);
      if(errNum == WLZ_ERR_NONE)
      {
	uObj = WlzAssignObject(t[WLZ_RCCTOIDX_O0O1U], NULL);
      }
      if(errNum == WLZ_ERR_NONE)
      {
        xObj = WlzAssignObject(
	       WlzObjToConvexHull(uObj, &errNum), NULL);
      }
      if(errNum == WLZ_ERR_NONE)
      {
        cObj = WlzAssignObject(
	       WlzConvexHullToObj(xObj, o[0]->type, &errNum), NULL);
      }
      (void )WlzFreeObj(xObj);
      (void )WlzFreeObj(uObj);
    }
    /* Dilate the two given objects and find the ntersection of the
     * dilated domains with each other and the convex hull computed
     * above. Within his domain compute the distances. */
    if(errNum == WLZ_ERR_NONE)
    {
      for(i = 0; i < 2; ++i)
      {
	WlzObject *tObj = NULL,
		  *rObj = NULL;

	tObj = WlzAssignObject(
	       WlzStructDilation(o[i], sObj, &errNum), NULL);
        if(errNum == WLZ_ERR_NONE)
	{
	  rObj = WlzAssignObject(
	         WlzIntersect2(tObj, cObj, &errNum), NULL);
	}
        (void )WlzFreeObj(tObj);
        if(errNum == WLZ_ERR_NONE)
	{
	  dObj[i] = WlzAssignObject(
		    WlzDistanceTransform(rObj, o[!i],
					 WLZ_OCTAGONAL_DISTANCE,
					 0.0, maxDist, &errNum), NULL);
	}
        (void )WlzFreeObj(rObj);
        if(errNum == WLZ_ERR_NONE)
	{
	  WlzPixelV bgdV;

	  bgdV.type = WLZ_GREY_INT;
	  bgdV.v.inv = maxDist;
	  errNum = WlzSetBackground(dObj[i], bgdV);
	}
        if(errNum != WLZ_ERR_NONE)
	{
	  break;
	}
      }
    }
    /* Find the domain which is equi-distant from the two given objects,
     * within the xDist range and within the convex hull of the union of
     * the two given object's domains. */
    (void )WlzFreeObj(sObj); sObj = NULL;
    if(errNum == WLZ_ERR_NONE)
    {
      WlzLong	vol = 0;
      WlzObject *qObj = NULL,
      		*tObj = NULL;

      qObj = WlzAssignObject(
             WlzImageArithmetic(dObj[0], dObj[1], WLZ_BO_EQ, 0, &errNum), NULL);
      if(errNum == WLZ_ERR_NONE)
      {
	WlzPixelV thrV;

	thrV.type = WLZ_GREY_INT;
	thrV.v.inv = 1;
        tObj = WlzAssignObject(
	       WlzThreshold(qObj, thrV, WLZ_THRESH_HIGH, &errNum), NULL);
      }
      /* Check that the eqi-distant domain is of a reasonable size ie has
       * a area or volume greater than half the maximum distance. */
      if(errNum == WLZ_ERR_NONE)
      {
        vol = WlzVolume(tObj, &errNum);
	if((maxDist / 2) >= vol)
	{
	  empty = 1;
	}
      }
      if((errNum == WLZ_ERR_NONE) && !empty)
      {
	WlzObject *mObj;
	WlzPixelV tmpV;

	tmpV.type = WLZ_GREY_INT;
	tmpV.v.inv = 0;
        mObj = WlzAssignObject(
	       WlzGreyTemplate(dObj[0], tObj, tmpV, &errNum), NULL);
        if(errNum == WLZ_ERR_NONE)
	{
	  tmpV.v.inv = 1;
	  eObj = WlzAssignObject(
	  	WlzThreshold(mObj, tmpV, WLZ_THRESH_HIGH, &errNum), NULL);
	}
	(void )WlzFreeObj(mObj);
      }
      (void )WlzFreeObj(tObj);
      (void )WlzFreeObj(qObj);
      if((errNum == WLZ_ERR_NONE) && !empty)
      {
	WlzLong vol;

	vol = WlzVolume(eObj, &errNum);
	if((maxDist / 2) >= vol)
	{
	  empty = 1;
	}
      }
    }
    (void )WlzFreeObj(cObj);
    (void )WlzFreeObj(sObj);
    (void )WlzFreeObj(dObj[0]);
    (void )WlzFreeObj(dObj[1]);
  }
  /* Compute a quantised distance histogram in which equi-distant distances
   * are quantized to integer values. */
  if((errNum == WLZ_ERR_NONE) && !empty)
  {
    if((dHist = (int *)AlcCalloc(maxDist + 1, sizeof(int))) == NULL)
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  if((errNum == WLZ_ERR_NONE) && !empty)
  {
    if(eObj->type == WLZ_2D_DOMAINOBJ)
    {
      errNum = WlzRCCCompDistHist2D(maxDist, dHist, eObj);
    }
    else
    {
      errNum = WlzRCCCompDistHist3D(maxDist, dHist, eObj);
    }
#ifdef WLZ_RCC_DEBUG_OST
    {
      FILE *fP;

      fP = fopen("WLZ_RCC_DEBUG_OST.wlz", "w");
      (void )WlzWriteObj(fP, eObj);
      (void )fclose(fP);
    }
#endif
  }
  WlzFreeObj(eObj);
  if((errNum == WLZ_ERR_NONE) && !empty)
  {
    int		i,
    		n,
		s,
		nq;
    /* Compute the median, first and third quantile offset distances,
     * the ratio of median to the median plus inner inter-quantile range. */
    n = 0;
    for(i = 0; i < maxDist; ++i)
    {
      n += dHist[i];
    }
    i = 0;
    s = 0;
    nq = n / 4;
    while(s < nq)
    {
      s += dHist[i++];
    }
    q[0] = i;
    nq = n / 2;
    while(s < nq)
    {
      s += dHist[i++];
    }
    q[1] = i;
    nq = (3 * n) / 4;
    while(s < nq)
    {
      s += dHist[i++];
    }
    q[2] = i;
  }
  AlcFree(dHist);
  *dQ0 = q[0];
  *dQ1 = q[1];
  *dQ2 = q[2];
  return(errNum);
}
Esempio n. 28
0
/*!
* \return	Error code.
* \ingroup      AlgMatrix
* \brief	Solves the set of of linear equations A.x = b where
*		A is input as its singular value decomposition in
*		the three matricies U, W and V, as returned by
*		AlgMatrixSVDecomp().
*		The code for AlgMatrixSVBackSub was derived from:
*		Numerical Recipies function svbksb().
* \param	uMat			Given matrix U with nM rows and nN
* 					columns..
* \param	wVec			The diagonal matrix of singular
*					values, returned as a vector with
*					nN elements.
* \param	vMat			The matrix V (not it's
*					transpose) with nN columns.
* \param	bVec			Column matrix b with nM elements,
* 					overwritten by column matrix x on
* 					return.
*/
AlgError	AlgMatrixSVBackSub(AlgMatrix uMat, double *wVec, AlgMatrix vMat,
				   double *bVec)
{
  int		cnt0,
  		idJ;
  double	s;
  double	*tDP0,
		*tDP1,
  		*tDVec = NULL;
  double	**tDPP0;
  AlgError	errCode = ALG_ERR_NONE;

  ALG_DBG((ALG_DBG_LVL_FN|ALG_DBG_LVL_1), ("AlgMatrixSVBackSub FE\n"));
  if((uMat.core == NULL) || (uMat.core->type != ALG_MATRIX_RECT) ||
     (vMat.core == NULL) || (vMat.core->type != vMat.core->type) ||
     (uMat.core->nR <= 0) || (uMat.core->nR < uMat.core->nC) ||
     (uMat.core->nR != vMat.core->nR) || (uMat.core->nC != vMat.core->nC) ||
     (wVec == NULL) || (bVec == NULL))
  {
    errCode = ALG_ERR_FUNC;
  }
  else if((tDVec = (double *)AlcCalloc(sizeof(double), uMat.rect->nC)) == NULL)
  {
    errCode = ALG_ERR_MALLOC;
  }
  else
  {
#ifndef ALG_FAST_CODE
    int	   	idI;
#endif
    int 	nM,
    	   	nN;
    double 	**uAry,
    	   	**vAry;

    nM = uMat.rect->nR;
    nN = uMat.rect->nC;
    uAry = uMat.rect->array;
    vAry = vMat.rect->array;
    for(idJ = 0; idJ < nN; ++idJ) 
    {
      s = 0.0;
      if(fabs(wVec[idJ]) > DBL_EPSILON)
      {
#ifdef ALG_FAST_CODE
	cnt0 = nM;
	tDPP0 = uAry;
	tDP0 = bVec;
	while(cnt0-- > 0)
	{
	  s += *(*tDPP0++ + idJ) * *tDP0++;
	}
#else
	for(idI = 0; idI < nM; ++idI)
	{
	  s += uAry[idI][idJ] * bVec[idI];
        }
#endif
	s /= wVec[idJ];
      }
      tDVec[idJ] = s;
    }
    for(idJ = 0; idJ < nN; ++idJ) 
    {
      s = 0.0;
#ifdef ALG_FAST_CODE
      cnt0 = nN;
      tDP0 = *(vAry + idJ);
      tDP1 = tDVec;
      while(cnt0-- > 0)
      {
        s += *tDP0++ * *tDP1++;
      }
#else
      for(idI = 0; idI < nN; ++idI)
      {
	s += vAry[idJ][idI] * tDVec[idI];
      }
#endif
      bVec[idJ] = s;
    }
    AlcFree(tDVec);
  }
  ALG_DBG((ALG_DBG_LVL_FN|ALG_DBG_LVL_1),
	  ("AlgMatrixSVBackSub FX %d\n",
	   (int )errCode));
  return(errCode);
}
Esempio n. 29
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);
}
Esempio n. 30
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);
}