Пример #1
0
int		main(int argc, char *argv[])
{
  int		idC,
  		idO,
		idP,
  		option,
		ok = 1,
  		usage = 0,
		mean = 0,
		stddev = 0,
		nObjs = 0,
		maxObjs = 0;
  FILE		*fP = NULL;
  char		*fStr,
  		*outObjFileStr;
  const char	*errMsgStr;
  WlzObject	*inObj = NULL,
  		*outObj = NULL;
  WlzObject	**objs = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  static char   optList[] = "hmso:";
  const char    fileStrDef[] = "-";
  const int	stepObjs = 1024;

  opterr = 0;
  outObjFileStr = (char *)fileStrDef;
  while(ok && ((option = getopt(argc, argv, optList)) != EOF))
  {
    switch(option)
    {
      case 'o':
        outObjFileStr = optarg;
	break;
      case 'm':
	mean = 1;
	break;
      case 's':
        stddev = 1;
	break;
      case 'h':
      default:
	usage = 1;
	break;
    }
  }
  ok = !usage;
  if(ok)
  {
    if((outObjFileStr == NULL) || (*outObjFileStr == '\0'))
    {
      ok = 0;
      usage = 1;
    }
  }
  if(ok)
  {
    maxObjs += stepObjs;
    if((objs = AlcMalloc(maxObjs * sizeof(WlzObject *))) == NULL)
    {
      ok = 0;
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  /* Read objects from the command line. */
  if(ok) 
  {
    int		nFiles;

    idO = 0;
    nFiles = argc - optind;
    while((errNum == WLZ_ERR_NONE) && (idO < nFiles))
    {
      if(nObjs >= maxObjs)
      {
        maxObjs += stepObjs;
	if((objs = AlcRealloc(objs, stepObjs * sizeof(WlzObject *))) == NULL)
	{
	  ok = 0;
	  errNum = WLZ_ERR_MEM_ALLOC;
	  break;
	}
      }
      if(ok)
      {
        fStr = *(argv + optind + idO);
	if((fP = (strcmp(fStr, "-")?  fopen(fStr, "rb"): stdin)) == NULL)
	{
	  errNum = WLZ_ERR_READ_EOF;
	}
	else
	{
	  objs[nObjs] = WlzAssignObject(
	  		WlzReadObj(fP, &errNum), NULL);
	  if(errNum == WLZ_ERR_NONE)
	  {
	    ++nObjs;
	  }
	  if(strcmp(fStr, "-"))
	  {
	    (void )fclose(fP);
	  }
	}
      }
      ++idO;
    }
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsgStr);
      (void )fprintf(stderr,
	       "%s: failed to read input objects from command line (%s).\n",
		     *argv, errMsgStr);
    }
  }
  /* Create a single compound object from the input objects. */
  if(ok)
  {
    int		oCnt = 0,
    		oType = 0;

    for(idO = 0; idO < nObjs; ++idO)
    {
      if(objs[idO])
      {
        switch(objs[idO]->type)
	{
	  case WLZ_2D_DOMAINOBJ:
	    ++oCnt;
	    if(oType == 0)
	    {
	      oType = 2;
	    }
	    else if(oType != 2)
	    {
	      errNum = WLZ_ERR_OBJECT_TYPE;
	    }
	    break;
	  case WLZ_3D_DOMAINOBJ:
	    ++oCnt;
	    if(oType == 0)
	    {
	      oType = 3;
	    }
	    else if(oType != 3)
	    {
	      errNum = WLZ_ERR_OBJECT_TYPE;
	    }
	    break;
	  case WLZ_COMPOUND_ARR_1: /* FALLTHOUGH */
	  case WLZ_COMPOUND_ARR_2:
	    oCnt += ((WlzCompoundArray *)(objs[idO]))->n;
	    break;
	  default:
	    errNum = WLZ_ERR_OBJECT_TYPE;
	    break;
	}
	if(errNum != WLZ_ERR_NONE)
	{
	  break;
	}
      }
    }
    if(errNum == WLZ_ERR_NONE)
    {
      inObj = (WlzObject *)WlzMakeCompoundArray(WLZ_COMPOUND_ARR_1,
      				1, oCnt, NULL, WLZ_NULL, &errNum);
    }
    if(errNum == WLZ_ERR_NONE)
    {
      idC = 0;
      for(idO = 0; idO < nObjs; ++idO)
      {
	if(objs[idO])
	{
	  switch(objs[idO]->type)
	  {
	    case WLZ_2D_DOMAINOBJ: /* FALLTHOUGH */
	    case WLZ_3D_DOMAINOBJ:
	      ((WlzCompoundArray *)inObj)->o[idC++] =
	        WlzAssignObject(objs[idO], NULL);
	      break;
	    case WLZ_COMPOUND_ARR_1: /* FALLTHOUGH */
	    case WLZ_COMPOUND_ARR_2:
	      for(idP = 0; idP < ((WlzCompoundArray *)(objs[idO]))->n; ++idP)
	      {
		((WlzCompoundArray *)inObj)->o[idC++] =
		  WlzAssignObject(((WlzCompoundArray *)(objs[idO]))->o[idP],
		                  NULL);
	      }
	      break;
	    default:
	      break;
	  }
	}
      }
      ((WlzCompoundArray *)(inObj))->n = idC;
      if((((WlzCompoundArray *)(inObj))->n < 1) ||
         (((WlzCompoundArray *)(inObj))->o[0] == NULL))
      {
        errNum = WLZ_ERR_OBJECT_NULL;
      }
      else
      {
        ((WlzCompoundArray *)(inObj))->otype = ((WlzCompoundArray *)
	                                        (inObj))->o[0]->type;
      }
    }
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsgStr);
      (void )fprintf(stderr,
	       "%s: Failed to create compound object of input object (%s).\n",
		     *argv, errMsgStr);
    }
  }
  if(objs)
  {
    for(idO = 0; idO < nObjs; ++idO)
    {
      (void )WlzFreeObj(objs[idO]);
    }
    AlcFree(objs);
    objs = NULL;
  }
  /* Create compound object for collecting thye statistics. */
  if(ok)
  {
    outObj = (WlzObject *)WlzMakeCompoundArray(WLZ_COMPOUND_ARR_1,
      				1, 4, NULL, 
				((WlzCompoundArray *)(inObj))->otype,
				&errNum);
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsgStr);
      (void )fprintf(stderr,
	   "%s: Failed to allocate compound object for output object (%s).\n",
		     *argv, errMsgStr);
    }
  }
  /* Compute the cross object statistics. */
  if(ok)
  {
    errNum = WlzNObjGreyStats(inObj, mean, stddev, NULL,
                              &(((WlzCompoundArray *)outObj)->o[0]),
                              &(((WlzCompoundArray *)outObj)->o[1]),
                              &(((WlzCompoundArray *)outObj)->o[2]),
                              &(((WlzCompoundArray *)outObj)->o[3]));
    if(errNum == WLZ_ERR_NONE)
    {
      for(idO = 0; idO < 4; ++idO)
      {
        (void )WlzAssignObject(((WlzCompoundArray *)outObj)->o[idO], NULL);
      }
    }
    else
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsgStr);
      (void )fprintf(stderr,
      "%s: Failed to compute cross object statistics (%s).\n",
                     *argv, errMsgStr);
    }
  }
  /* Output cross object statistics compound object. */
  if(ok)
  {
    if((fP = (strcmp(outObjFileStr, "-")?
	     fopen(outObjFileStr, "w"): stdout)) == NULL)
    {
      ok = 0;
      (void )fprintf(stderr,
		     "%s: Failed to open output file %s.\n",
		     argv[0], outObjFileStr);
    }
  }
  if(ok)
  {
    errNum = WlzWriteObj(fP, outObj);
    if(strcmp(outObjFileStr, "-"))
    {
      (void )fclose(fP);
    }
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsgStr);
      (void )fprintf(stderr,
                     "%s: Failed to write output object, %s.\n",
		     argv[0], errMsgStr);
    }
  }
  (void )WlzFreeObj(inObj);
  (void )WlzFreeObj(outObj);
  /* Report usage. */
  if(usage)
  {
    (void )fprintf(stderr,
    "Usage: %s [-h] [-m] [-s] [-o<output file>] [<input objects>]\n"
    "Version: %s\n"
    "Options:\n"
    "  -h  Output this usage message.\n"
    "  -o  Output file name, default is the standard output.\n"
    "  -m  Output mean instead of sum of values.\n"
    "  -s  Output standard deviation instead of sum of squares of values.\n"
    "Reads objects (including compound objects) from the given files in\n"
    "turn: First from the files specified on the commandline and then from\n"
    "the standard input. The output objects are written to a single compound\n"
    "object. Each object of the compound object will have the same domain\n"
    "(which is the intersection of the input object domains) and values for\n"
    "the simple statistics. The statistics generated are min value, max\n"
    "value, sum of values and sum of squares of values.\n"
    "Example:\n"
    "  cat obj1.wlz obj2.wlz obj3.wlz | %s -s -m obj4.wlz >out.wlz\n"
    "Creates a compound object with four component objects, the domains of\n"
    "which are all the intersection of the domains of the input objects\n"
    "(obj[1-4].wlz) and the values are the minimum, maximum, mean and\n"
    "standard deviation of the input object values across the objects within\n"
    "the intersection domain.\n",
    argv[0],
    WlzVersion(),
    argv[0]);
  }
  return(!ok);
}
Пример #2
0
/*!
* \return	Woolz compound array object.
* \ingroup	WlzExtFF
* \brief	Given an object in which distinct voxel values represent
*		different domains and each of these has a corresponding
*		material, this function creates a new compound array
*		object. Each of the materials has it's own domain and
*		the material properties are encoded in a simple ascii
*		property list of the domain.
*		The materials are known to have indices which increase
*		from 0.
* \param	gObj			Given index object.
* \param	head			Amira header data structure with the
*					list of materials.
* \param	dstErr			Destination pointer for error number,
*					may be NULL.
*/
static WlzCompoundArray *WlzEffAmSplitLabelObj(WlzObject *gObj,
					WlzEffAmHead *head,
					WlzErrorNum *dstErr)
{
  int		idx,
  		empty = 0;
  WlzPixelV	thrV;
  WlzObject	*tObj0 = NULL,
  		*tObj1 = NULL,
		*tObj2,
		*tObj3;
  WlzEffAmMaterial *mat;
  WlzPropertyList *pList = NULL;
  WlzCompoundArray *aObj = NULL;
  WlzDomain	nullDom;
  WlzValues	dValues,
  		nullVal;
  WlzErrorNum errNum = WLZ_ERR_NONE;
  const int	allEmptyAfterFirst = 0;

  idx = 0;
  nullDom.core = NULL;
  nullVal.core = NULL;
  dValues.core = NULL;
  mat = head->materials;
  thrV.type = WLZ_GREY_INT;
  /* Create compound array object. */
  aObj = WlzMakeCompoundArray(WLZ_COMPOUND_ARR_1, 1, head->matCount, NULL,
  			      WLZ_3D_DOMAINOBJ, &errNum);
  /* For each material create a new domain corresponding to the index. */
  while((errNum == WLZ_ERR_NONE) && (idx < head->matCount))
  {
    thrV.v.inv = mat->id + 1;
    pList = WlzEffAmMakeMaterialPropList(mat, &errNum);
    if(empty && allEmptyAfterFirst)
    {
      tObj3 = WlzMakeMain(WLZ_EMPTY_OBJ, nullDom, nullVal, pList,
      			  NULL, &errNum);
      
    }
    else
    {
      if(errNum == WLZ_ERR_NONE)
      {
	if(idx == 0)
	{
	  tObj1 = WlzAssignObject(
		  WlzThreshold(gObj, thrV, WLZ_THRESH_HIGH, &errNum), NULL);
	  if(errNum == WLZ_ERR_NONE)
	  {
	    tObj2 = WlzDiffDomain(gObj, tObj1, &errNum);
	  }
	}
	else
	{
	  tObj1 = WlzAssignObject(
		  WlzThreshold(tObj0, thrV, WLZ_THRESH_HIGH, &errNum), NULL);
	  if(errNum == WLZ_ERR_NONE)
	  {
	    tObj2 = WlzDiffDomain(tObj0, tObj1, &errNum);
	  }
	}
      }
      if(errNum == WLZ_ERR_NONE)
      {
        if(WlzIsEmpty(tObj1, &errNum) || WlzIsEmpty(tObj2, &errNum))
	{
	  empty = 1;
	  tObj3 = WlzMakeMain(WLZ_EMPTY_OBJ, nullDom, nullVal, pList,
	                      NULL, &errNum);
	}
	else
	{
	  tObj3 = WlzMakeMain(WLZ_3D_DOMAINOBJ, tObj2->domain,
			      dValues, pList, NULL, &errNum);
	}
      }
      (void )WlzFreeObj(tObj2); tObj2 = NULL;
      (void )WlzFreeObj(tObj0);
      tObj0 = tObj1;
      tObj1 = NULL;
    }
    if(errNum == WLZ_ERR_NONE)
    {
      aObj->o[idx] = WlzAssignObject(tObj3, NULL);
    }
    ++idx;
    mat = mat->next;
  }
  (void )WlzFreeObj(tObj0);
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(aObj);
}
Пример #3
0
/*! 
* \ingroup      WlzValuesFilters
* \brief        Perform 2D seperable transform on a 2D grey-level image.
* 		It is the users responsibility to ensure that the grey-value
* 		types are appropriate.
* 		Now extended to include compound objects.
*
* \return       Pointer to transformed object
* \param    obj	Input object pointer
* \param    x_fun	Convolution function to be applied in the x-direction (along the rows).
* \param    x_params	Parameter pointer to be passed to the x-function.
* \param    y_fun	Convolution function to be applied in the y-direction (down the columns).
* \param    y_params	Parameter pointer to be passed to the y-function.
* \param    dstErr	error return.
* \par      Source:
*                WlzSepTrans.c
*/
WlzObject *WlzSepTrans(
  WlzObject		*obj,
  WlzIntervalConvFunc	x_fun,
  void			*x_params,
  WlzIntervalConvFunc	y_fun,
  void			*y_params,
  WlzErrorNum		*dstErr)
{
  WlzIntervalWSpace	iwspace;
  WlzGreyWSpace		gwspace;
  WlzSepTransWSpace	stwspc;
  WlzValues		values;
  WlzObject		*obj1, *obj2;
  int			i, width, height;
  WlzCompoundArray	*cobj1, *cobj2;
  WlzErrorNum		errNum=WLZ_ERR_NONE;

  /* check object pointers and type */
  obj2 = NULL;
  stwspc.outbuf.p.dbp = NULL;
  if( obj == NULL ){
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else {
    switch( obj->type ){

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

    default:
    case WLZ_3D_DOMAINOBJ:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;

    case WLZ_TRANS_OBJ:
      if((obj1 = WlzSepTrans(obj->values.obj,
			     x_fun, x_params, y_fun, y_params,
			     &errNum)) != NULL){
	values.obj = obj1;
	return WlzMakeMain(obj->type, obj->domain, values,
			   NULL, obj, dstErr);
      }
      break;

    case WLZ_COMPOUND_ARR_1:
    case WLZ_COMPOUND_ARR_2:
      cobj1 = (WlzCompoundArray *) obj;
      if((cobj2 = WlzMakeCompoundArray(cobj1->type, 1, cobj1->n, NULL,
				       cobj1->otype, &errNum)) != NULL){
	/* transform each object, ignore type errors */
	for(i=0; i < cobj1->n; i++){
	  cobj2->o[i] =
	    WlzAssignObject(WlzSepTrans(cobj1->o[i],
					x_fun, x_params, y_fun, y_params,
					&errNum), NULL);
	}
	return (WlzObject *) cobj2;
      }
      break;

    case WLZ_EMPTY_OBJ:
      return WlzMakeEmpty(dstErr);
    }
  }

  /* make space for a calculation buffer - assume worst case of doubles */
  if( errNum == WLZ_ERR_NONE ){
    width  = obj->domain.i->lastkl - obj->domain.i->kol1 + 1;
    height = obj->domain.i->lastln - obj->domain.i->line1 + 1;
    stwspc.inbuf.type = WlzGreyTableTypeToGreyType(obj->values.core->type,
						   NULL);
    stwspc.bckgrnd = WlzGetBackground(obj, NULL);

    switch( stwspc.inbuf.type ){
    case WLZ_GREY_INT:
    case WLZ_GREY_SHORT:
    case WLZ_GREY_UBYTE:
      stwspc.outbuf.type = WLZ_GREY_INT;
      break;
    default:
      stwspc.outbuf.type = stwspc.inbuf.type;
      break;
    }

    if( (stwspc.outbuf.p.dbp = (double *) 
	 AlcMalloc(sizeof(double)*(width>height?width:height))) == NULL){
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }

  /* tranpose the object - interchange x & y coordinates */
  if( errNum == WLZ_ERR_NONE ){
    obj1 = WlzTransposeObj(obj, &errNum);
  }

  /* perform the y convolution */
  if((errNum == WLZ_ERR_NONE) &&
     ((errNum = WlzInitGreyScan(obj1, &iwspace, &gwspace)) == WLZ_ERR_NONE))
  {
    while( (errNum = WlzNextGreyInterval(&iwspace)) == WLZ_ERR_NONE ){
      stwspc.inbuf.p.inp = gwspace.u_grintptr.inp;
      stwspc.len = iwspace.rgtpos - iwspace.lftpos + 1;
      if((errNum = (*y_fun)(&stwspc, y_params)) == WLZ_ERR_NONE){
	switch(  stwspc.inbuf.type ){
	case WLZ_GREY_INT:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.inp++)
	    *stwspc.inbuf.p.inp = stwspc.outbuf.p.inp[i];
	  break;
	case WLZ_GREY_SHORT:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.shp++)
	    *stwspc.inbuf.p.shp = (short )(stwspc.outbuf.p.inp[i]);
	  break;
	case WLZ_GREY_UBYTE:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.ubp++)
	    *stwspc.inbuf.p.ubp = (WlzUByte )(stwspc.outbuf.p.inp[i]);
	  break;
	case WLZ_GREY_FLOAT:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.flp++)
	    *stwspc.inbuf.p.flp = stwspc.outbuf.p.flp[i];
	  break;
	case WLZ_GREY_DOUBLE:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.dbp++)
	    *stwspc.inbuf.p.dbp = stwspc.outbuf.p.dbp[i];
	  break;
	case WLZ_GREY_RGBA:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.rgbp++)
	    *stwspc.inbuf.p.rgbp = stwspc.outbuf.p.rgbp[i];
	  break;
	default:
	  errNum = WLZ_ERR_GREY_TYPE;
	  break;
	}
      }
      else {
	break; /* break from the while loop */
      }
    }
    if( errNum == WLZ_ERR_EOO ){
      errNum = WLZ_ERR_NONE;
    }
  }

  /* rotate back and free temporary object */
  if( errNum == WLZ_ERR_NONE ){
    obj2 = WlzTransposeObj(obj1, &errNum);
    WlzFreeObj(obj1);
  }

  /* perform x convolution */
  if((errNum == WLZ_ERR_NONE) &&
     ((errNum = WlzInitGreyScan(obj2, &iwspace, &gwspace)) == WLZ_ERR_NONE))
  {
    while((errNum = WlzNextGreyInterval(&iwspace)) == WLZ_ERR_NONE){
      stwspc.inbuf.p.inp = gwspace.u_grintptr.inp;
      stwspc.len = iwspace.rgtpos - iwspace.lftpos + 1;
      if( (errNum = (*x_fun)(&stwspc, x_params)) == WLZ_ERR_NONE ){
	switch(  gwspace.pixeltype ){
	case WLZ_GREY_INT:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.inp++)
	    *stwspc.inbuf.p.inp = stwspc.outbuf.p.inp[i];
	  break;
	case WLZ_GREY_SHORT:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.shp++)
	    *stwspc.inbuf.p.shp = (short )(stwspc.outbuf.p.inp[i]);
	  break;
	case WLZ_GREY_UBYTE:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.ubp++)
	    *stwspc.inbuf.p.ubp = (WlzUByte )(stwspc.outbuf.p.inp[i]);
	  break;
	case WLZ_GREY_FLOAT:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.flp++)
	    *stwspc.inbuf.p.flp = stwspc.outbuf.p.flp[i];
	  break;
	case WLZ_GREY_DOUBLE:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.dbp++)
	    *stwspc.inbuf.p.dbp = stwspc.outbuf.p.dbp[i];
	  break;
	case WLZ_GREY_RGBA:
	  for(i=0; i < stwspc.len; i++, stwspc.inbuf.p.rgbp++)
	    *stwspc.inbuf.p.rgbp = stwspc.outbuf.p.rgbp[i];
	  break;
	default:
	  errNum = WLZ_ERR_GREY_TYPE;
	  break;
	}
      }
      else {
	break; /* break from the while loop */
      }
    }
  }
  if( errNum == WLZ_ERR_EOO ){
    errNum = WLZ_ERR_NONE;
  }

  /* free the buffer and return transformed object */
  if( stwspc.outbuf.p.dbp ){
    AlcFree((void *) stwspc.outbuf.p.dbp);
  }

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

  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(cArray);
}
Пример #5
0
/*!
* \return	New Woolz object or NULL on error.
* \ingroup	WlzExtFF
* \brief	Reads a Woolz object from the given stream using the
*		ANALYZE 7.5 format. The given file name is used to
*		generate the '.hdr' and '.img' filenames.
* \param	gvnFileName		Given file name.
* \param	dstErr			Destination error code, may be NULL.
*/
WlzObject	*WlzEffReadObjAnl(const char *gvnFileName, WlzErrorNum *dstErr)
{
  int		idx,
  		timePoints = 0;
  FILE		*fP = NULL;
  char		*fileName = NULL,
  		*hdrFileName = NULL,
		*imgFileName = NULL;
  WlzVertex	org,
  		sz;
  WlzEffAnlDsr 	dsr;
  int 		swap = 0;
  WlzObject	*obj = NULL;
  WlzGreyType	gType = WLZ_GREY_ERROR;
  WlzPixelV	bgdV;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  sz.i3.vtX = sz.i3.vtY = sz.i3.vtZ = 0;
  /* Compute .hdr and .img file names. */
  if((gvnFileName == NULL) || (*gvnFileName == '\0'))
  {
    errNum = WLZ_ERR_PARAM_NULL;
  }
  else
  {
    errNum = WlzEffAnlFileNames(&fileName, &hdrFileName, &imgFileName,
				gvnFileName);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if((hdrFileName == NULL) || (*hdrFileName == '\0') ||
       ((fP = fopen(hdrFileName, "r")) == NULL))
    {
      errNum = WLZ_ERR_READ_EOF;
    }
#ifdef _WIN32
    else
    {
      if(fP != NULL)
      {
	if(_setmode(_fileno(fP), 0x8000) == -1)
	{
	  errNum = WLZ_ERR_READ_EOF;
	}
      }
    }
#endif
  }
  /* Read the .hdr (header) file. */
  if(errNum == WLZ_ERR_NONE)
  {
    (void )memset((void *)&dsr, 0, sizeof(WlzEffAnlDsr));
    errNum = WlzEffReadAnlHdrKey(fP, &dsr, &swap);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    errNum = WlzEffReadAnlHdrImageDim(fP, &dsr, swap);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    errNum = WlzEffReadAnlHdrDataHistory(fP, &dsr, swap);
  }
  if(fP)
  {
    (void )fclose(fP);
    fP = NULL;
  }
  /* Check header data is valid. */
  if(errNum == WLZ_ERR_NONE)
  {
    if('r' != dsr.hk.regular)
    {
      errNum = WLZ_ERR_OBJECT_DATA;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    switch(dsr.dim.bitPix)
    {
      case 8:  /* FALLTHROUGH */
      case 16: /* FALLTHROUGH */
      case 32: /* FALLTHROUGH */
      case 64:
        break;
      case 1:
      default:
        errNum = WLZ_ERR_OBJECT_DATA;
	break;
    }
  }
  /* Compute the image parameters. */
  if(errNum == WLZ_ERR_NONE)
  {
    switch(dsr.dim.dataType)
    {
      case WLZEFF_ANL_DT_UNSIGNED_CHAR:
        gType = WLZ_GREY_UBYTE;
	bgdV.type = gType;
	bgdV.v.ubv = 0;
	break;
      case WLZEFF_ANL_DT_SIGNED_SHORT:
        gType = WLZ_GREY_SHORT;
	bgdV.type = gType;
	bgdV.v.shv = 0;
	break;
      case WLZEFF_ANL_DT_SIGNED_INT:
        gType = WLZ_GREY_INT;
	bgdV.type = gType;
	bgdV.v.inv = 0;
	break;
      case WLZEFF_ANL_DT_FLOAT:
        gType = WLZ_GREY_FLOAT;
	bgdV.type = gType;
	bgdV.v.flv = 0.0;
	break;
      case WLZEFF_ANL_DT_DOUBLE:
        gType = WLZ_GREY_DOUBLE;
	bgdV.type = gType;
	bgdV.v.dbv = 0.0;
	break;
      default:
	errNum = WLZ_ERR_GREY_TYPE;
	break;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    switch(dsr.dim.dim[0])
    {
      case 2:
	org.i2.vtX = 0;
	org.i2.vtY = 0;
	sz.i2.vtX = dsr.dim.dim[1];
	sz.i2.vtY = dsr.dim.dim[2];
	timePoints = 1;
	if((sz.i2.vtX < 1) || (sz.i2.vtY < 1))
	{
	  errNum = WLZ_ERR_OBJECT_DATA;
	}
	break;
      case 3:
        org.i3.vtX = 0;
	org.i3.vtY = 0;
	org.i3.vtZ = 0;
	sz.i3.vtX = dsr.dim.dim[1];
	sz.i3.vtY = dsr.dim.dim[2];
	sz.i3.vtZ = dsr.dim.dim[3];
	if((sz.i3.vtX < 1) || (sz.i3.vtY < 1) || (sz.i3.vtZ < 1))
	{
	  errNum = WLZ_ERR_OBJECT_DATA;
	}
        break;
      case 4:
        org.i3.vtX = 0;
	org.i3.vtY = 0;
	org.i3.vtZ = 0;
	sz.i3.vtX = dsr.dim.dim[1];
	sz.i3.vtY = dsr.dim.dim[2];
	sz.i3.vtZ = dsr.dim.dim[3];
	timePoints = dsr.dim.dim[4];
	if((sz.i3.vtX < 1) || (sz.i3.vtY < 1) || (sz.i3.vtZ < 1) ||
	   (timePoints < 1))
	{
	  errNum = WLZ_ERR_OBJECT_DATA;
	}
        break;
      default:
	errNum = WLZ_ERR_OBJECT_DATA;
        break;
        
    }
  }
  /* Create object. */
  if(errNum == WLZ_ERR_NONE)
  {
    if(timePoints > 1)
    {
      obj = (WlzObject *)
            WlzMakeCompoundArray(WLZ_3D_DOMAINOBJ, 1, timePoints, NULL,
	                         WLZ_3D_DOMAINOBJ, &errNum);
      if(obj)
      {
        idx = 0;
	do
	{
	  ((WlzCompoundArray *)obj)->o[idx] = WlzAssignObject(
		WlzMakeCuboid(org.i3.vtZ, org.i3.vtZ + sz.i3.vtZ - 1,
			      org.i3.vtY, org.i3.vtY + sz.i3.vtY - 1,
			      org.i3.vtX, org.i3.vtX + sz.i3.vtX - 1,
			      gType, bgdV, NULL, NULL, &errNum), NULL);
	} while((++idx < timePoints) && (WLZ_ERR_NONE == errNum));
      }
    }
    else if(3 <= dsr.dim.dim[0])
    {
      obj = WlzMakeCuboid(org.i3.vtZ, org.i3.vtZ + sz.i3.vtZ - 1,
                          org.i3.vtY, org.i3.vtY + sz.i3.vtY - 1,
			  org.i3.vtX, org.i3.vtX + sz.i3.vtX - 1,
			  gType, bgdV, NULL, NULL, &errNum);
    }
    else /* 2 == dsr.dim.dim[0] */
    {
      obj = WlzMakeRect(org.i2.vtY, org.i2.vtY + sz.i2.vtY - 1,
			org.i2.vtX, org.i2.vtX + sz.i2.vtX - 1,
			gType, NULL, bgdV, NULL, NULL, &errNum);
    }
  }
  /* Open the .img (image data) file. */
  if(errNum == WLZ_ERR_NONE)
  {
    if((imgFileName == NULL) || (*imgFileName == '\0') ||
       ((fP = fopen(imgFileName, "r")) == NULL))
    {
      errNum = WLZ_ERR_READ_EOF;
    }
#ifdef _WIN32
    else
    {
      if(fP != NULL)
      {
	if(_setmode(_fileno(fP), 0x8000) == -1)
	{
	  errNum = WLZ_ERR_READ_EOF;
	}
      }
    }
#endif
  }
  /* Read the object values. */
  if(errNum == WLZ_ERR_NONE)
  {
    errNum = WlzEffReadAnlImgData(obj, gType, &dsr, fP, swap);
  }
  if(fP)
  {
    (void )fclose(fP);
  }
  (void )AlcFree(fileName);
  (void )AlcFree(hdrFileName);
  (void )AlcFree(imgFileName);
  if(errNum != WLZ_ERR_NONE)
  {
    (void )WlzFreeObj(obj);
    obj = NULL;
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(obj);
}
Пример #6
0
int main(int	argc,
	 char	**argv)
{
  char 		optList[] = "n:O:hv";
  int		option;
  /* int		verboseFlg=0; */
  int		rows=0, cols=0;
  int		overlap=50;
  int		rowShift, colShift;
  WlzErrorNum	errNum=WLZ_ERR_NONE;
  char		*tiffFile=NULL;
  WlzObject	*inObj=NULL, *outObj=NULL, *obj, **objVec;
  WlzCompoundArray	*outCmpnd;
  int		i, j, objVecCount, objIndx;

  /* read the argument list and check for an input file */
  opterr = 0;
  while( (option = getopt(argc, argv, optList)) != EOF ){
    switch( option ){

    case 'n':
      switch( sscanf(optarg, "%d,%d", &cols, &rows) ){
      default:
	usage(argv[0]);
	return 1;

      case 1:
	fprintf(stderr,
		"%s: number of rows not set and will be estimated\n",
		argv[0]);
	break;

      case 2:
	break;
      }
      break;

    case 'O':
      switch( sscanf(optarg, "%d", &overlap) ){
      default:
	fprintf(stderr,
		"%s: overlap not read", argv[0]);
	usage(argv[0]);
	return 1;

      case 1:
	break;
      }
      break;

    case 'v':
      /* verboseFlg = 1; */
      break;

    case 'h':
    default:
      usage(argv[0]);
      return WLZ_ERR_UNSPECIFIED;
    }
  }

  if( optind < argc ){
    tiffFile = *(argv+optind);
  }
  else {
    fprintf(stderr, "%s: input TIFF file required\n", argv[0]);
    usage(argv[0]);
    return WLZ_ERR_UNSPECIFIED;
  }

  /* read the TIFF file */
  if( (inObj = WlzAssignObject(
	 WlzEffReadObj(NULL, tiffFile, WLZEFF_FORMAT_TIFF,
	               0, 0, 0, &errNum), NULL)) == NULL ){
    usage(argv[0]);
    return errNum;
  }

  /* if 2D then there is only one patch, simply output as a compound object */
  switch( inObj->type ){
  case WLZ_2D_DOMAINOBJ:
    outCmpnd = WlzMakeCompoundArray(WLZ_COMPOUND_ARR_1, 3, 1, &inObj,
				    inObj->type, &errNum);
      outObj = (WlzObject *) outCmpnd;
    break;

  case WLZ_3D_DOMAINOBJ:
    if( (errNum = WlzExplode3D(&objVecCount, &objVec, inObj)) != WLZ_ERR_NONE ){
      usage(argv[0]);
      return errNum;
    }
    /* check if rows and columns plausible */
    if( cols && rows ){
      if( cols*rows != objVecCount ){
	fprintf(stderr,
		"%s: input columns and rows (%d,%d) does not match"
		"number of patches - %d\n Continuing anyway\n",
		argv[0], cols, rows, objVecCount);
      }
    }
    else if( cols ){
      rows = objVecCount / cols;
      if( cols*rows != objVecCount ){
	fprintf(stderr,
		"%s: input columns and estimated rows (%d,%d) does not match"
		"number of patches - %d\nContinuing anyway\n",
		argv[0], cols, rows, objVecCount);
      }
    }
    else {
      if( guessColsRows(objVecCount, &cols, &rows) ){
	fprintf(stderr,
		"%s: estimated cols and rows - (%d,%d)\nContinuing\n",
		argv[0], cols, rows);
      }
      else {
	fprintf(stderr, 
		"%s: cols,rows (%d, %d) estimated seems crazy,"
		"put values in explicitely\n",
		argv[0], cols, rows);
	usage(argv[0]);
	return WLZ_ERR_UNSPECIFIED;
      }
    }

    /* shift patch objects, assume patches all the same size */
    rowShift = (objVec[0]->domain.i->lastln - objVec[0]->domain.i->line1
		+ 1 - overlap);
    colShift = (objVec[0]->domain.i->lastkl - objVec[0]->domain.i->kol1
		+ 1 - overlap);
    objIndx = 0;
    for(j=0; j < rows; j++){
      for(i=0; i < cols; i++, objIndx++){
	if( objIndx < objVecCount ){
	  obj = WlzShiftObject(objVec[objIndx], 
			       colShift*i, rowShift*j, 0, &errNum);
	  WlzFreeObj(objVec[objIndx]);
	  objVec[objIndx] = WlzAssignObject(obj, &errNum);
	}
      }
    }

    /* make array */
    outCmpnd = WlzMakeCompoundArray(WLZ_COMPOUND_ARR_1, 2,
				    objVecCount, objVec,
				    objVec[0]->type, &errNum);
    outObj = (WlzObject *) outCmpnd;
    break;

  default:
    errNum = WLZ_ERR_OBJECT_TYPE;
  }
  WlzFreeObj(inObj);

  /* write compound object */
  if( errNum == WLZ_ERR_NONE ){
    WlzWriteObj(stdout, outObj);
    WlzFreeObj(outObj);
  }
  else {
    usage(argv[0]);
  }
  return errNum;
}
Пример #7
0
/*! 
* \ingroup      WlzValuesUtils
* \brief        Calculate the modulus of the grey-level gradient at each
 point. The gradient images are calculated using WlzGauss2() with width
parameter set to <tt>width</tt>. Will now calculate the modulus for each
object of a compound object if appropriate. 
*
* \return       Object with values set to the gradient modulus at each pixel.
* \param    obj	Input object.
* \param    width	Width parameter for the gaussian gradient operator.
* \param    dstErr	Error return.
* \par      Source:
*                WlzGreyModGradient.c
*/
WlzObject *WlzGreyModGradient(
  WlzObject	*obj,
  double	width,
  WlzErrorNum	*dstErr)
{
  WlzObject		*xobj, *yobj, *returnobj=NULL;
  WlzIntervalWSpace	iwsp1, iwsp2, iwsp3;
  WlzGreyWSpace		gwsp1, gwsp2, gwsp3;
  WlzCompoundArray	*cobj1, *cobj2;
  int			i;
  double		g1, g2, g3;
  WlzErrorNum		errNum=WLZ_ERR_NONE;

  /* check object */
  if( obj ){
    switch( obj->type ){
    case WLZ_2D_DOMAINOBJ:
      if( obj->domain.core ){
	switch( obj->domain.core->type ){
	case WLZ_EMPTY_DOMAIN:
	  returnobj = WlzMakeEmpty(&errNum);
	  break;

	default:
	  if( obj->values.core ){
	    if( (obj->values.core->type == WLZ_EMPTY_VALUES) ||
	        WlzGreyTableIsTiled(obj->values.core->type) ){
	      errNum = WLZ_ERR_VALUES_TYPE;
	    }
	  }
	  else {
	    errNum = WLZ_ERR_VALUES_NULL;
	  }
	  break;
	}
      }
      else {
	errNum = WLZ_ERR_DOMAIN_NULL;
      }
      /* one last check for rgb values */
      if(WlzGreyTableTypeToGreyType(obj->values.core->type, NULL)
	 == WLZ_GREY_RGBA){
	return WlzRGBAModGradient(obj, width, dstErr);
      }
      break;

    case WLZ_EMPTY_OBJ:
      returnobj = WlzMakeEmpty(&errNum);
      break;

    case WLZ_COMPOUND_ARR_1:
    case WLZ_COMPOUND_ARR_2:
      cobj1 = (WlzCompoundArray *) obj;
      if((cobj2 = WlzMakeCompoundArray(cobj1->type, 1, cobj1->n, NULL,
				       cobj1->otype, &errNum)) != NULL){
	/* transform each object, ignore type errors */
	for(i=0; i < cobj1->n; i++){
	  cobj2->o[i] =
	    WlzAssignObject(WlzGreyModGradient(cobj1->o[i],
					       width, &errNum), NULL);
	}
	return (WlzObject *) cobj2;
      }
      break;

    default:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;
    }
  }
  else {
    errNum = WLZ_ERR_OBJECT_NULL;
  }

  /* if WlzUByte grey values then copy to int */
  if( (errNum == WLZ_ERR_NONE) && !returnobj ){
    if(WlzGreyTableTypeToGreyType(obj->values.core->type,
                                  NULL) == WLZ_GREY_UBYTE)
    {
      returnobj = WlzConvertPix(obj, WLZ_GREY_INT, NULL);
    }
    else
    {
      returnobj = WlzMakeMain(WLZ_2D_DOMAINOBJ, obj->domain,
			      WlzCopyValues(obj->type, obj->values,
					    obj->domain, &errNum),
			      NULL, NULL, NULL);
    }

    /* calculate gradient images */
    xobj = WlzGauss2(returnobj, width, width, 1, 0, NULL);
    yobj = WlzGauss2(returnobj, width, width, 0, 1, NULL);

    /* calculate modulus  - lockstep raster scan assumes equal domains */
    errNum = WlzInitGreyScan(returnobj, &iwsp1, &gwsp1);
    errNum = WlzInitGreyScan(xobj, &iwsp2, &gwsp2);
    errNum = WlzInitGreyScan(yobj, &iwsp3, &gwsp3);
    while((errNum == WLZ_ERR_NONE) && 
	  (WlzNextGreyInterval(&iwsp1) == WLZ_ERR_NONE) )
    {
      (void) WlzNextGreyInterval(&iwsp2);
      (void) WlzNextGreyInterval(&iwsp3);

      switch( gwsp1.pixeltype )
      {
      default:
      case WLZ_GREY_INT:
	for(i=0; i < iwsp1.colrmn; i++)
	{
	  g2 = *gwsp2.u_grintptr.inp++;
	  g3 = *gwsp3.u_grintptr.inp++;
	  g1 = sqrt( g2*g2 + g3*g3 );
	  *gwsp1.u_grintptr.inp++ = (int) g1;
	}
	break;

      case WLZ_GREY_SHORT:
	for(i=0; i < iwsp1.colrmn; i++)
	{
	  g2 = *gwsp2.u_grintptr.shp++;
	  g3 = *gwsp3.u_grintptr.shp++;
	  g1 = sqrt( g2*g2 + g3*g3 );
	  *gwsp1.u_grintptr.shp++ = (short) g1;
	}
	break;

      case WLZ_GREY_UBYTE:
	for(i=0; i < iwsp1.colrmn; i++)
	{
	  g2 = *gwsp2.u_grintptr.ubp++;
	  g3 = *gwsp3.u_grintptr.ubp++;
	  g1 = sqrt( g2*g2 + g3*g3 );
	  *gwsp1.u_grintptr.ubp++ = (WlzUByte) g1;
	}
	break;

      case WLZ_GREY_FLOAT:
	for(i=0; i < iwsp1.colrmn; i++)
	{
	  g2 = *gwsp2.u_grintptr.flp++;
	  g3 = *gwsp3.u_grintptr.flp++;
	  g1 = sqrt( g2*g2 + g3*g3 );
	  *gwsp1.u_grintptr.flp++ = (float) g1;
	}
	break;

      case WLZ_GREY_DOUBLE:
	for(i=0; i < iwsp1.colrmn; i++)
	{
	  g2 = *gwsp2.u_grintptr.dbp++;
	  g3 = *gwsp3.u_grintptr.dbp++;
	  g1 = sqrt( g2*g2 + g3*g3 );
	  *gwsp1.u_grintptr.dbp++ = (double) g1;
	}
	break;

      case WLZ_GREY_RGBA: /* RGBA to be done - should not get here */
	errNum = WLZ_ERR_GREY_TYPE;
	break;

      }
    }

    /* check for normal return */
    if( errNum == WLZ_ERR_EOO ){
      errNum = WLZ_ERR_NONE;
    }

    /* clean up */
    WlzFreeObj( xobj );
    WlzFreeObj( yobj );
  }

  /* check error return */
  if( dstErr ){
    *dstErr = errNum;
  }
  return( returnobj );
}
Пример #8
0
/*! 
* \ingroup      WlzValuesUtils
* \brief        Convert a RGBA image to a compound object. The RGBA
*		 channels are at array indices 0,1,2,3 respectively
*		 and the sub-object grey types will be WLZ_GREY_UBYTE.
*
* \return       Compound array of rgba values
* \param    obj				Input domain object with value type
* 					WLZ_GREY_RGBA
* \param    colSpc			The colour space.
* \param    dstErr			Destination error ponyer, may be NULL.
*/
WlzCompoundArray *WlzRGBAToCompound(
  WlzObject	*obj,
  WlzRGBAColorSpace	colSpc,
  WlzErrorNum	*dstErr)
{
  WlzCompoundArray	*cobj=NULL;
  WlzErrorNum		errNum=WLZ_ERR_NONE;

  /* check object type, and value type */
  if( obj ){
    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( WlzGreyTypeFromObj(obj, &errNum) != WLZ_GREY_RGBA ){
	errNum = WLZ_ERR_VALUES_TYPE;
      }
      break;

    case WLZ_3D_DOMAINOBJ:
      if( obj->domain.core == NULL ){
	errNum = WLZ_ERR_DOMAIN_NULL;
      }
      else if( obj->domain.p->type != WLZ_PLANEDOMAIN_DOMAIN ){
	errNum = WLZ_ERR_DOMAIN_TYPE;
      }
      else if ( obj->values.core == NULL ){
	errNum = WLZ_ERR_VALUES_NULL;
      }
      else if( obj->values.vox->type != WLZ_VOXELVALUETABLE_GREY ){
	errNum = WLZ_ERR_VALUES_TYPE;
      }
      else if( WlzGreyTypeFromObj(obj, &errNum) != WLZ_GREY_RGBA ){
	errNum = WLZ_ERR_VALUES_TYPE;
      }
      return WlzRGBAToCompound3D(obj, colSpc, dstErr);

    case WLZ_TRANS_OBJ:
      /* not difficult, do it later */
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;

    case WLZ_COMPOUND_ARR_1:
    case WLZ_COMPOUND_ARR_2:
      /* bit recursive this ! */
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;

    case WLZ_EMPTY_OBJ:
      return (WlzCompoundArray *) WlzMakeEmpty(dstErr);

    default:
      errNum = WLZ_ERR_OBJECT_TYPE;
    }
  }
  else {
    errNum = WLZ_ERR_OBJECT_NULL;
  }

  /* check colour space */
  if( errNum == WLZ_ERR_NONE ){
    switch( colSpc ){
    case WLZ_RGBA_SPACE_RGB:
    case WLZ_RGBA_SPACE_HSB:
    case WLZ_RGBA_SPACE_CMY:
      break;

    default:
      errNum = WLZ_ERR_PARAM_DATA;
      break;
    }
  }

  /* create compound object return */
  if( errNum == WLZ_ERR_NONE ){
    WlzValues	values;
    WlzObject	*objs[4];
    WlzObjectType	type;
    WlzPixelV	oldBck, newBck;

    type = WlzGreyTableType(
      WlzGreyTableTypeToTableType(obj->values.core->type, &errNum),
      WLZ_GREY_UBYTE, &errNum);
    oldBck = WlzGetBackground(obj, &errNum);

    /* red */
    newBck.type = WLZ_GREY_UBYTE;
    newBck.v.ubv = (WlzUByte )WLZ_RGBA_RED_GET(oldBck.v.rgbv);
    values.v = WlzNewValueTb(obj, type, newBck, &errNum);
    objs[0] = WlzMakeMain(obj->type, obj->domain, values,
			  NULL, NULL, &errNum);
    /* green */
    newBck.v.ubv = (WlzUByte )WLZ_RGBA_GREEN_GET(oldBck.v.rgbv);
    values.v = WlzNewValueTb(obj, type, newBck, &errNum);
    objs[1] = WlzMakeMain(obj->type, obj->domain, values,
			  NULL, NULL, &errNum);
    /* blue */
    newBck.v.ubv = (WlzUByte )WLZ_RGBA_BLUE_GET(oldBck.v.rgbv);
    values.v = WlzNewValueTb(obj, type, newBck, &errNum);
    objs[2] = WlzMakeMain(obj->type, obj->domain, values,
			  NULL, NULL, &errNum);
    /* alpha */
    newBck.v.ubv = (WlzUByte )WLZ_RGBA_ALPHA_GET(oldBck.v.rgbv);
    values.v = WlzNewValueTb(obj, type, newBck, &errNum);
    objs[3] = WlzMakeMain(obj->type, obj->domain, values,
			  NULL, NULL, &errNum);

    /* create compound object, object pointers are assigned for mode=3
       so no need to free objects */
    cobj = WlzMakeCompoundArray(WLZ_COMPOUND_ARR_1, 3, 4, &(objs[0]),
				 obj->type, &errNum);
  }

  /* iterate through objects setting values */
  if( errNum == WLZ_ERR_NONE ){
    WlzIntervalWSpace	iwsp0, iwsp[4];
    WlzGreyWSpace	gwsp0, gwsp[4];
    int			i, j, k;
    int			a, col[3];

    errNum = WlzInitGreyScan(obj, &iwsp0, &gwsp0);
    for(i=0; i < 4; i++){
      errNum = WlzInitGreyScan(cobj->o[i], &(iwsp[i]), &(gwsp[i]));
    }
    while((errNum == WLZ_ERR_NONE) &&
	  ((errNum = WlzNextGreyInterval(&iwsp0)) == WLZ_ERR_NONE)){
      for(i=0; i < 4; i++){
	errNum = WlzNextGreyInterval(&(iwsp[i]));
      }
      switch( colSpc ){
      case WLZ_RGBA_SPACE_RGB:
	for(j=0, k=iwsp0.lftpos; k <= iwsp0.rgtpos; j++, k++,
	      gwsp0.u_grintptr.rgbp++){
	  *(gwsp[0].u_grintptr.ubp++) =
	    (WlzUByte )WLZ_RGBA_RED_GET(*(gwsp0.u_grintptr.rgbp));
	  *(gwsp[1].u_grintptr.ubp++) =
	    (WlzUByte )WLZ_RGBA_GREEN_GET(*(gwsp0.u_grintptr.rgbp));
	  *(gwsp[2].u_grintptr.ubp++) =
	    (WlzUByte )WLZ_RGBA_BLUE_GET(*(gwsp0.u_grintptr.rgbp));
	  *(gwsp[3].u_grintptr.ubp++) =
	    (WlzUByte )WLZ_RGBA_ALPHA_GET(*(gwsp0.u_grintptr.rgbp));
	}
	break;
      
      case WLZ_RGBA_SPACE_HSB: /* each normalised to [0,255] */
	for(j=0, k=iwsp0.lftpos; k <= iwsp0.rgtpos; j++, k++,
	      gwsp0.u_grintptr.rgbp++){
	  col[0] = WLZ_RGBA_RED_GET(*(gwsp0.u_grintptr.rgbp));
	  col[1] = WLZ_RGBA_GREEN_GET(*(gwsp0.u_grintptr.rgbp));
	  col[2] = WLZ_RGBA_BLUE_GET(*(gwsp0.u_grintptr.rgbp));
	  a = WLZ_RGBA_ALPHA_GET(*(gwsp0.u_grintptr.rgbp));
	  WlzRGBAConvertRGBToHSV_UBYTENormalised(col);
	  *(gwsp[0].u_grintptr.ubp++) = (WlzUByte )(col[0]);
	  *(gwsp[1].u_grintptr.ubp++) = (WlzUByte )(col[1]);
	  *(gwsp[2].u_grintptr.ubp++) = (WlzUByte )(col[2]);
	  *(gwsp[3].u_grintptr.ubp++) = (WlzUByte )a;
	    }
	break;
      
      case WLZ_RGBA_SPACE_CMY:
	for(j=0, k=iwsp0.lftpos; k <= iwsp0.rgtpos; j++, k++,
	      gwsp0.u_grintptr.rgbp++){
	  col[0] = WLZ_RGBA_RED_GET(*(gwsp0.u_grintptr.rgbp));
	  col[1] = WLZ_RGBA_GREEN_GET(*(gwsp0.u_grintptr.rgbp));
	  col[2] = WLZ_RGBA_BLUE_GET(*(gwsp0.u_grintptr.rgbp));
	  a = WLZ_RGBA_ALPHA_GET(*(gwsp0.u_grintptr.rgbp));
	  *(gwsp[0].u_grintptr.ubp++) = (WlzUByte )((col[1] + col[2]) / 2);
	  *(gwsp[1].u_grintptr.ubp++) = (WlzUByte )((col[2] + col[0]) / 2);
	  *(gwsp[2].u_grintptr.ubp++) = (WlzUByte )((col[0] + col[1]) / 2);
	  *(gwsp[3].u_grintptr.ubp++) = (WlzUByte )a;
	    }
	break;
      default:
        errNum = WLZ_ERR_GREY_TYPE;
	break;
      }
    }
    if( errNum == WLZ_ERR_EOO ){
      errNum = WLZ_ERR_NONE;
    }
  }
      

  if( dstErr ){
    *dstErr = errNum;
  }
  return cobj;
}
Пример #9
0
/*!
* \return	New 3D domain object with corresponding WLZ_GREY_RGBA values.
* \ingroup      WlzValuesUtils
* \brief	Creates a WLZ_GREY_RGBA valued object from the given compound
* 		array. This is a static function which will always be called
* 		with valid parameters so they aren't checked.
* \param	cObj			Compound array object.
* \param	cSpc 			The colour space.
* \param	dstErr			Destination error pointer may be NULL.
*/
static WlzObject *WlzCompoundToRGBA3D(WlzCompoundArray *cObj,
  				WlzRGBAColorSpace cSpc, WlzErrorNum *dstErr)
{
  WlzIBox3 	bBox;
  WlzDomain	dom;
  WlzValues	val;
  WlzPixelV	bgd;
  WlzObject	*rObj = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

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

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

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

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

	  dom2.core = NULL;
	  val2.core = NULL;
	  if((cObj->o[idC] != NULL) &&
	     (cObj->o[idC]->type == WLZ_3D_DOMAINOBJ))
	  {
	    idP2 = bBox.zMin + idP - cObj->o[idC]->domain.p->plane1;
	    nPl2 = cObj->o[idC]->domain.p->lastpl - 
	           cObj->o[idC]->domain.p->plane1 + 1;
	    if((idP2 >= 0) && (idP2 <= nPl2))
	    {
	      dom2 = *(cObj->o[idC]->domain.p->domains + idP2);
	      val2 = *(cObj->o[idC]->values.vox->values + idP2);
	    }
	  }
	  cObj2->o[idC] = (dom2.core == NULL)?
	                  WlzMakeEmpty(&errNum2):
	                  WlzMakeMain(WLZ_2D_DOMAINOBJ, dom2, val2,
	                              NULL, NULL, &errNum2);
	  ++idC;
	}
	if(errNum2 == WLZ_ERR_NONE)
	{
	  rObj2 = WlzCompoundToRGBA2D(cObj2, cSpc, &errNum2);
	}
	if(errNum2 == WLZ_ERR_NONE)
	{
	  dom.p->domains[idP] = WlzAssignDomain(rObj2->domain, NULL);
	  val.vox->values[idP] = WlzAssignValues(rObj2->values, NULL);
	}
	(void )WlzFreeObj(rObj2);
	(void )WlzFreeObj((WlzObject *)cObj2);
	if(errNum2 != WLZ_ERR_NONE)
	{
	  errNum = errNum2;
	}
      }
    }
  }
  if(errNum != WLZ_ERR_NONE)
  {
    if(rObj != NULL)
    {
      (void )WlzFreeObj(rObj);
      rObj = NULL;
    }
    else
    {
      (void )WlzFreePlaneDomain(dom.p);
      (void )WlzFreeVoxelValueTb(val.vox);
    }
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(rObj);
}
Пример #10
0
/*!
* \return	Compound array with vector displacements.
* \ingroup	WlzValueUtils
* \brief	Computes the 3D displacement field from the first to the
* 		second object, where both are 3D domain objects that are
* 		derived from the same 3D domain object with integer
* 		incremental grey values.
* \param	obj0			First object.
* \param	obj1			Second object.
* \param	dstErr			Destination error pointer, may be NULL.
*/
static WlzCompoundArray *WlzCompDispIncGrey3D(WlzObject *obj0, WlzObject *obj1,
				              WlzErrorNum *dstErr)
{
  int		idF,
  		idN,
  		idO,
		idP,
  		nAry,
		iWidth;
  int		*ary,
		*valF;
  int		*val[4];
  WlzObject	*objs[3],
  		*objs2D[4];
  WlzObjectType	gTT;
  WlzPlaneDomain *domP;
  WlzCompoundArray *dsp = NULL;
  WlzIntervalWSpace iWSp[4];
  WlzGreyWSpace gWSp[4];
  WlzPixelV     bgd;
  WlzValues     values;
  WlzErrorNum   errNum = WLZ_ERR_NONE;

  /* Create compound object for displacements from the first object. */
  objs[0] = objs[1] = objs[2] = NULL;
  bgd.type = WLZ_GREY_INT;
  bgd.v.inv = 0;
  gTT = WlzGreyTableType(WLZ_GREY_TAB_RAGR, WLZ_GREY_INT, &errNum);
  for(idN = 0; idN < 3; ++idN)
  {
    values.vox = WlzNewValuesVox(obj0, gTT, bgd, &errNum);
    if(errNum == WLZ_ERR_NONE)
    {
      objs[idN] = WlzMakeMain(obj0->type, obj0->domain, values, NULL, NULL,
      			      &errNum);
    }
    if(errNum != WLZ_ERR_NONE)
    {
      break;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
  }
  /* Create sorted (by grey value) array of values and positions for the
   * second object. */
  if(errNum == WLZ_ERR_NONE)
  {
    ary = WlzCompDispMakeValAry3D(obj1, &nAry, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    qsort(ary, nAry, 4 * sizeof(int), WlzCompDispArySortFn3D);
  }
  /* Scan through the first object computing displacements. */
  if(errNum == WLZ_ERR_NONE)
  {
    idF = 0;
    domP = obj0->domain.p;
    for(idP = domP->plane1; idP <= domP->lastpl; ++idP)
    {
      idO = idP - domP->plane1;
      objs2D[0] = objs2D[1] = objs2D[2];
      objs2D[3] = WlzMakeMain(WLZ_2D_DOMAINOBJ,
                            *(domP->domains + idO),
                            *(obj0->values.vox->values + idO),
			    NULL, NULL, &errNum);
      for(idN = 0; (errNum == WLZ_ERR_NONE) && (idN < 3); ++idN)
      {
	objs2D[idN] = WlzMakeMain(WLZ_2D_DOMAINOBJ,
			     *(objs[idN]->domain.p->domains + idO),
			     *(objs[idN]->values.vox->values + idO),
			     NULL, NULL, &errNum);
      }
      for(idN = 0; (errNum == WLZ_ERR_NONE) && (idN < 4); ++idN)
      {
        errNum = WlzInitGreyScan(objs2D[idN], iWSp + idN, gWSp + idN);
      }
      while(((errNum = WlzNextGreyInterval(iWSp + 0)) == WLZ_ERR_NONE) &&
	    ((errNum = WlzNextGreyInterval(iWSp + 1)) == WLZ_ERR_NONE) &&
	    ((errNum = WlzNextGreyInterval(iWSp + 2)) == WLZ_ERR_NONE) &&
	    ((errNum = WlzNextGreyInterval(iWSp + 3)) == WLZ_ERR_NONE))
      {
	iWidth = iWSp[0].rgtpos - iWSp[0].lftpos + 1;
	val[0] = gWSp[0].u_grintptr.inp;
	val[1] = gWSp[1].u_grintptr.inp;
	val[2] = gWSp[2].u_grintptr.inp;
	val[3] = gWSp[3].u_grintptr.inp;
	for(idN = 0; idN < iWidth; ++idN)
	{
	  /* Find value in array. */
	  idF = WlzCompDispFindDsp(nAry, ary, *(val[3]), 4);
	  if(idF >= 0)
	  {
	    valF = ary + (idF * 4);
	    *(val[0]) = valF[1] - (iWSp[0].lftpos + idN); /* x */
	    *(val[1]) = valF[2] - iWSp[0].linpos;         /* y */
	    *(val[2]) = valF[3] - idP;                    /* z */
	  }
	  else
	  {
	    *(val[0]) = INT_MAX;
	    *(val[1]) = INT_MAX;
	    *(val[2]) = INT_MAX;
	  }
	  ++(val[0]);
	  ++(val[1]);
	  ++(val[2]);
	  ++(val[3]);
	}
      }
      if(errNum == WLZ_ERR_EOO)
      {
        errNum = WLZ_ERR_NONE;
      }
      (void )WlzFreeObj(objs2D[0]);
      (void )WlzFreeObj(objs2D[1]);
      (void )WlzFreeObj(objs2D[2]);
      (void )WlzFreeObj(objs2D[3]);
    }
  }
  AlcFree(ary);
  if(errNum == WLZ_ERR_NONE)
  {
    dsp = WlzMakeCompoundArray(WLZ_COMPOUND_ARR_1, 3, 3, objs,
		               WLZ_3D_DOMAINOBJ, &errNum);
  }
  if(errNum != WLZ_ERR_NONE)
  {
    if(dsp != NULL)
    {
      (void )WlzFreeObj((WlzObject *)dsp);
    }
    else
    {
      for(idN = 0; idN < 3; ++idN)
      {
        (void )WlzFreeObj(objs[idN]);
      }
    }
  }
  if(dstErr != NULL)
  {
    *dstErr = errNum;
  }
  return(dsp);
}
Пример #11
0
/*!
* \return	Shade corrected object or NULL on error.
* \ingroup	WlzValueFilters
* \brief	Shade corrects the given domain object with grey
*               values.
*		\f[
		  p_i = n \frac{(o_i - d_i)}{(s_i - d_i}
		\f]
*               The shade corrected image P with values \f$p_i\f$ is
*		created by applying a correction factor to each image
*		value of the given image O with values \f$o_i\f$.
*		\f$s_i\f$ and \f$d_i\f$ are the bright and dark-field
*		shade image values respectively.
* \param	srcObj			Given object to be shade corrected.
* \param	shdObj			Given bright field object.
* \param	shdDFObj		Given dark field object (may be NULL).
* \param	nrmVal			Normalization value.
* \param	inPlace			Modify the grey values of the given
*					object in place if non-zero.
* \param	dstErr			Destination error pointer, may
*                                       be null.
*/
WlzObject	*WlzShadeCorrectBFDF(
  WlzObject 	*srcObj,
  WlzObject 	*shdObj,
  WlzObject 	*shdDFObj,
  double 	nrmVal,
  int 		inPlace,
  WlzErrorNum 	*dstErr)
{
  WlzObject	*rtnObj = NULL;
  WlzObject	*obj1, *obj2;
  WlzCompoundArray	*inCobj, *outCobj;
  WlzObject	**outArray;
  WlzValues	values;
  int		i;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  if((srcObj == NULL) || (shdObj == NULL))
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if((srcObj->domain.core == NULL) || (shdObj->domain.core == NULL))
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if((srcObj->values.core == NULL) || (shdObj->values.core == NULL))
  {
    errNum = WLZ_ERR_VALUES_NULL;
  }
  else if(WlzGreyTableIsTiled(srcObj->values.core->type) ||
          WlzGreyTableIsTiled(shdObj->values.core->type))
  {
    errNum = WLZ_ERR_VALUES_TYPE;
  }
  else
  {
    switch(srcObj->type)
    {
    case WLZ_2D_DOMAINOBJ:
      if(shdObj->type != srcObj->type)
      {
	errNum = WLZ_ERR_OBJECT_TYPE;
      }
      else if( shdDFObj ){
	if( WlzGreyTypeFromObj(srcObj, &errNum) == WLZ_GREY_RGBA ){
	  obj1 = WlzRGBAImageArithmetic(srcObj, shdDFObj, WLZ_BO_SUBTRACT,
					0, &errNum);
	  obj2 = WlzRGBAImageArithmetic(shdObj, shdDFObj, WLZ_BO_SUBTRACT,
					0, &errNum);
	}
	else {
	  obj1 = WlzImageArithmetic(srcObj, shdDFObj, WLZ_BO_SUBTRACT,
				    0, &errNum);
	  obj2 = WlzImageArithmetic(shdObj, shdDFObj, WLZ_BO_SUBTRACT,
				    0, &errNum);
	}
	rtnObj = WlzShadeCorrect2D(obj1, obj2, nrmVal, inPlace, &errNum);
	WlzFreeObj(obj1);
	WlzFreeObj(obj2);;
      }
      else {
	rtnObj = WlzShadeCorrect2D(srcObj, shdObj, nrmVal, inPlace, &errNum);
      }
      break;

    case WLZ_COMPOUND_ARR_1:
    case WLZ_COMPOUND_ARR_2:
      inCobj = (WlzCompoundArray *) srcObj;
      if( inCobj->n > 0 ){
	if( (outArray = (WlzObject **)
	     AlcCalloc(inCobj->n, sizeof(WlzObject *))) == NULL){
	  errNum = WLZ_ERR_MEM_ALLOC;
	}
	else {
	  for(i=0; (i < inCobj->n) && (errNum == WLZ_ERR_NONE); i++){
	    /* allow special behaviour of a non-compound shade image
	       to be used for each object in a compound but must align */
	    switch( shdObj->type ){
	    case WLZ_2D_DOMAINOBJ:
	    case WLZ_3D_DOMAINOBJ:
	      outArray[i] = WlzShadeCorrectBFDF(inCobj->o[i],
						shdObj, shdDFObj,
						nrmVal, inPlace, &errNum);
	      break;

	    case WLZ_COMPOUND_ARR_1:
	    case WLZ_COMPOUND_ARR_2:
	      outArray[i] =
		WlzShadeCorrectBFDF(inCobj->o[i],
				    ((WlzCompoundArray *) shdObj)->o[i],
				    shdDFObj?
				    ((WlzCompoundArray *) shdDFObj)->o[i]:NULL,
				    nrmVal, inPlace, &errNum);
	      break;
	    default:
	      errNum = WLZ_ERR_OBJECT_TYPE;
	      break;
	    }
	      
	  }
	  if( errNum == WLZ_ERR_NONE ){
	    outCobj = WlzMakeCompoundArray(srcObj->type, 3, inCobj->n,
					   outArray, outArray[0]->type,
					   &errNum);
	    rtnObj = (WlzObject *) outCobj;
	  }
	  else {
	    while( i >= 0 ){
	      WlzFreeObj(outArray[i--]);
	    }
	  }
	  AlcFree(outArray);
	}
      }
      else {
	errNum = WLZ_ERR_OBJECT_DATA;
      }
      break;

    case WLZ_3D_DOMAINOBJ:
      errNum = WLZ_ERR_UNIMPLEMENTED;
      break;

    case WLZ_TRANS_OBJ:
      if((rtnObj = WlzShadeCorrectBFDF(srcObj->values.obj,
                                       shdObj, shdDFObj, nrmVal,
				       inPlace, &errNum)) != NULL){
	values.obj = rtnObj;
	return WlzMakeMain(WLZ_TRANS_OBJ, srcObj->domain, values,
			   NULL, NULL, dstErr);
      }
      break;

    case WLZ_EMPTY_OBJ:
      return WlzMakeEmpty(dstErr);

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