Example #1
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;
}
Example #2
0
/*! 
* \ingroup      WlzValuesFilters
* \brief        Set new grey-range by simple linear interpolation. It
 assumes that the min and max values enclose the true range of
 grey-values in the object. Failure to check this could result in a
 segmentation fault.

The transform function is:
\f[g' = \frac{(gMax - gMin)}{(gmax - gmin)} (g - gmin) + gMin + \delta
\f]
Here \f$\delta\f$ is the dither value.
*
* \return       Woolz error number
* \param    obj	Input grey-level object whose values are to be reset.
* \param    min	Initial minimum value
* \param    max	Initial maximum value
* \param    Min	Final minimum value
* \param    Max	Final maximum value
* \param    Dither values if destination range is greater than source range
*           and this flag is non-zero.
* \par      Source:
*                WlzGreySetRange.c
*/
WlzErrorNum WlzGreySetRange(
  WlzObject	*obj,
  WlzPixelV	min,
  WlzPixelV	max,
  WlzPixelV	Min,
  WlzPixelV	Max,
  int		dither)
{
  double		gMin = 0.0,
  			gMax = 0.0,
			sigma = 0.0,
  			factor,
			val;
  WlzIntervalWSpace	iwsp;
  WlzGreyWSpace		gwsp;
  WlzGreyP		gptr;
  WlzObject		*tempobj;
  WlzValues 		*values;
  WlzDomain		*domains;
  int			i, j, nplanes;
  WlzErrorNum		errNum = WLZ_ERR_NONE;

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

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

    case WLZ_2D_DOMAINOBJ:
      if( obj->domain.i == NULL ){
	return WLZ_ERR_DOMAIN_NULL;
      }
      if( obj->values.core == NULL ){
	return WLZ_ERR_VALUES_NULL;
      }
      if( WlzGreyTableIsTiled(obj->values.core->type) ){
	return WLZ_ERR_VALUES_TYPE;
      }
      break;

    case WLZ_3D_DOMAINOBJ:
      /* check planedomain and voxeltable */
      if( obj->domain.p == NULL ){
	return WLZ_ERR_DOMAIN_NULL;
      }
      if( obj->domain.p->type != WLZ_PLANEDOMAIN_DOMAIN ){
	return WLZ_ERR_PLANEDOMAIN_TYPE;
      }
      if( obj->values.vox == NULL ){
	return WLZ_ERR_VALUES_NULL;
      }
      if( obj->values.vox->type != WLZ_VOXELVALUETABLE_GREY ){
	return WLZ_ERR_VOXELVALUES_TYPE;
      }

      /* set range of each plane if non-empty - indicated by NULL */
      domains = obj->domain.p->domains;
      values = obj->values.vox->values;
      nplanes = obj->domain.p->lastpl - obj->domain.p->plane1 + 1;
      for(i=0; i < nplanes; i++, domains++, values++){

	if( (*domains).core == NULL || (*values).core == NULL ){
	  continue;
	}

	tempobj = WlzMakeMain(WLZ_2D_DOMAINOBJ,
			      *domains, *values, NULL, NULL,
			      &errNum);
	if((tempobj == NULL) && (errNum == WLZ_ERR_NONE) ){
	  errNum = WLZ_ERR_UNSPECIFIED;
	  break;
	}

	errNum = WlzGreySetRange(tempobj, min, max, Min, Max, dither);
	WlzFreeObj( tempobj );
	if( errNum != WLZ_ERR_NONE ){
	  break;
	}
      }
      
      return errNum;

    case WLZ_TRANS_OBJ:
      return WlzGreySetRange(obj->values.obj, min, max, Min, Max, dither);

    case WLZ_EMPTY_OBJ:
      return errNum;

    default:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;
    }
  }

  if( errNum == WLZ_ERR_NONE ){
    /* get conversion function - should use LUT
       use 4 LUTS for rgb type since bounded */
    if( WlzGreyTypeFromObj(obj, &errNum) == WLZ_GREY_RGBA ){
      WlzUByte	rgbaLut[4][256];
      WlzUInt	rgbamin[4], rgbaMin[4];
      double	rgbaFactor[4], val1;
      WlzUInt	red, green, blue, alpha;

      rgbamin[0] = WLZ_RGBA_RED_GET(min.v.rgbv);
      rgbaMin[0] = WLZ_RGBA_RED_GET(Min.v.rgbv);
      if(WLZ_RGBA_RED_GET(max.v.rgbv) > WLZ_RGBA_RED_GET(min.v.rgbv)){
	rgbaFactor[0] = (((double) WLZ_RGBA_RED_GET(Max.v.rgbv) - 
			  WLZ_RGBA_RED_GET(Min.v.rgbv))/
			 (WLZ_RGBA_RED_GET(max.v.rgbv) - 
			  WLZ_RGBA_RED_GET(min.v.rgbv)));
      }
      else {
	rgbaFactor[0] = 0.0;
      }

      rgbamin[1] = WLZ_RGBA_GREEN_GET(min.v.rgbv);
      rgbaMin[1] = WLZ_RGBA_GREEN_GET(Min.v.rgbv);
      if(WLZ_RGBA_GREEN_GET(max.v.rgbv) > WLZ_RGBA_GREEN_GET(min.v.rgbv)){
	rgbaFactor[1] = (((double) WLZ_RGBA_GREEN_GET(Max.v.rgbv) - 
			  WLZ_RGBA_GREEN_GET(Min.v.rgbv))/
			 (WLZ_RGBA_GREEN_GET(max.v.rgbv) - 
			  WLZ_RGBA_GREEN_GET(min.v.rgbv)));
      }
      else {
	rgbaFactor[1] = 0.0;
      }

      rgbamin[2] = WLZ_RGBA_BLUE_GET(min.v.rgbv);
      rgbaMin[2] = WLZ_RGBA_BLUE_GET(Min.v.rgbv);
      if(WLZ_RGBA_BLUE_GET(max.v.rgbv) > WLZ_RGBA_BLUE_GET(min.v.rgbv)){
	rgbaFactor[2] = (((double) WLZ_RGBA_BLUE_GET(Max.v.rgbv) - 
			  WLZ_RGBA_BLUE_GET(Min.v.rgbv))/
			 (WLZ_RGBA_BLUE_GET(max.v.rgbv) - 
			  WLZ_RGBA_BLUE_GET(min.v.rgbv)));
      }
      else {
	rgbaFactor[2] = 0.0;
      }

      rgbamin[3] = WLZ_RGBA_ALPHA_GET(min.v.rgbv);
      rgbaMin[3] = WLZ_RGBA_ALPHA_GET(Min.v.rgbv);
      if(WLZ_RGBA_ALPHA_GET(max.v.rgbv) > WLZ_RGBA_ALPHA_GET(min.v.rgbv)){
	rgbaFactor[3] = (((double) WLZ_RGBA_ALPHA_GET(Max.v.rgbv) - 
			  WLZ_RGBA_ALPHA_GET(Min.v.rgbv))/
			 (WLZ_RGBA_ALPHA_GET(max.v.rgbv) - 
			  WLZ_RGBA_ALPHA_GET(min.v.rgbv)));
      }
      else {
	rgbaFactor[3] = 0.0;
      }

      /* now set up the LUTS */
      for(i=0; i < 4; i++){
	for(j=0; j < 256; j++){
	  val1 = rgbaFactor[i] * (j - rgbamin[i]) + rgbaMin[i];
	  rgbaLut[i][j] = (WlzUByte )WLZ_CLAMP(val1, 0, 255);
	}
      }

      /* set values - can assume rgba grey-type */
      errNum = WlzInitGreyScan(obj, &iwsp, &gwsp);
      if(errNum == WLZ_ERR_NONE) {
	while( WlzNextGreyInterval(&iwsp) == WLZ_ERR_NONE ){

	  gptr = gwsp.u_grintptr;
	  for (i=0; i<iwsp.colrmn; i++, gptr.rgbp++){
	    red = rgbaLut[0][WLZ_RGBA_RED_GET(*gptr.rgbp)];
	    green = rgbaLut[0][WLZ_RGBA_GREEN_GET(*gptr.rgbp)];
	    blue = rgbaLut[0][WLZ_RGBA_BLUE_GET(*gptr.rgbp)];
	    alpha = rgbaLut[0][WLZ_RGBA_ALPHA_GET(*gptr.rgbp)];
	    WLZ_RGBA_RGBA_SET(*gptr.rgbp, red, green, blue, alpha);
	  }
	}
	(void )WlzEndGreyScan(&iwsp, &gwsp);
	if(errNum == WLZ_ERR_EOO){
	  errNum = WLZ_ERR_NONE;
	}
      }
    }
    else {
      WlzValueConvertPixel(&min, min, WLZ_GREY_DOUBLE);
      WlzValueConvertPixel(&max, max, WLZ_GREY_DOUBLE);
      WlzValueConvertPixel(&Min, Min, WLZ_GREY_DOUBLE);
      WlzValueConvertPixel(&Max, Max, WLZ_GREY_DOUBLE);
      if( fabs(max.v.dbv - min.v.dbv) < DBL_EPSILON ){
	return WLZ_ERR_FLOAT_DATA;
      }
      errNum = WlzInitGreyScan(obj, &iwsp, &gwsp);
      if(errNum == WLZ_ERR_NONE) {
	factor = (Max.v.dbv - Min.v.dbv) / (max.v.dbv - min.v.dbv);
	if(dither)
	{
	  if(fabs(factor) < 1.0 + DBL_EPSILON)
	  {
	    dither = 0;
	  }
	  else
	  {
	    sigma = fabs(2.0 / factor);
	    AlgRandSeed(101);
	    switch(gwsp.pixeltype) {
	      case WLZ_GREY_INT:
		gMin = ALG_MAX(Min.v.dbv, INT_MIN);
		gMax = ALG_MIN(Max.v.dbv, INT_MAX);
		break;
	      case WLZ_GREY_SHORT:
		gMin = ALG_MAX(Min.v.dbv, SHRT_MIN);
		gMax = ALG_MIN(Max.v.dbv, SHRT_MAX);
		break;
	      case WLZ_GREY_UBYTE:
		gMin = ALG_MAX(Min.v.dbv, 0);
		gMax = ALG_MIN(Max.v.dbv, 255);
		break;
	      case WLZ_GREY_FLOAT:
		gMin = ALG_MAX(Min.v.dbv, FLT_MIN);
		gMax = ALG_MIN(Max.v.dbv, FLT_MAX);
		break;
	      case WLZ_GREY_DOUBLE:
		gMin = Min.v.dbv;
		gMax = Max.v.dbv;
		break;
	      default:
		break;
	    }
	  }
	}
	while((errNum == WLZ_ERR_NONE) &&
	      ((errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE)){
	  gptr = gwsp.u_grintptr;
	  switch (gwsp.pixeltype) {
	    case WLZ_GREY_INT:
	      for (i=0; i<iwsp.colrmn; i++, gptr.inp++){
		if(dither){
		  val = factor * (*gptr.inp +
				  AlgRandZigNormal(0.0, sigma) -
				  min.v.dbv) + Min.v.dbv;
		  val = WLZ_CLAMP(val, gMin, gMax);
		} else {
		  val = factor * (*gptr.inp - min.v.dbv) + Min.v.dbv;
		}
		*gptr.inp = WLZ_NINT(val);
	      }
	      break;
	    case WLZ_GREY_SHORT:
	      for (i=0; i<iwsp.colrmn; i++, gptr.shp++){
		if(dither){
		  val = factor * (*gptr.shp +
				  AlgRandZigNormal(0.0, sigma) -
				  min.v.dbv) + Min.v.dbv;
		  val = WLZ_CLAMP(val, gMin, gMax);
		} else {
		  val = factor * (*gptr.shp - min.v.dbv) + Min.v.dbv;
		}
		*gptr.shp = (short )WLZ_NINT(val);
	      }
	      break;
	    case WLZ_GREY_UBYTE:
	      for (i=0; i<iwsp.colrmn; i++, gptr.ubp++){
		if(dither){
		  val = factor * (*gptr.ubp +
				  AlgRandZigNormal(0.0, sigma) -
				  min.v.dbv) + Min.v.dbv;
		  val = WLZ_CLAMP(val, gMin, gMax);
		} else {
		  val = factor * (*gptr.ubp - min.v.dbv) + Min.v.dbv;
		}
		*gptr.ubp = (WlzUByte )WLZ_NINT(val);
	      }
	      break;
	    case WLZ_GREY_FLOAT:
	      for (i=0; i<iwsp.colrmn; i++, gptr.flp++){
		if(dither){
		  val = factor * (*gptr.flp +
				  AlgRandZigNormal(0.0, sigma) -
				  min.v.dbv) + Min.v.dbv;
		  val = WLZ_CLAMP(val, gMin, gMax);
		} else {
		  val = factor * (*gptr.flp - min.v.dbv) + Min.v.dbv;
		}
		*gptr.flp = (float )val;
	      }
	      break;
	    case WLZ_GREY_DOUBLE:
	      for (i=0; i<iwsp.colrmn; i++, gptr.dbp++){
		if(dither){
		  val = factor * (*gptr.dbp +
				  AlgRandZigNormal(0.0, sigma) -
				  min.v.dbv) + Min.v.dbv;
		  val = WLZ_CLAMP(val, gMin, gMax);
		} else {
		  val = factor * (*gptr.dbp - min.v.dbv) + Min.v.dbv;
		}
		*gptr.dbp = val;
	      }
	      break;
	    default:
	      errNum = WLZ_ERR_GREY_TYPE;
	      break;
	  }
	}
	(void )WlzEndGreyScan(&iwsp, &gwsp);
	if(errNum == WLZ_ERR_EOO){
	  errNum = WLZ_ERR_NONE;
	}
      }
    }
  }
  return errNum;
}
Example #3
0
WlzErrorNum	WlzGreyScalarDivValue(
  WlzObject	*obj,
  WlzPixelV	val)
{
  WlzObject		*tmpObj;
  WlzIntervalWSpace	iwsp;
  WlzGreyWSpace		gwsp;
  WlzGreyP		gptr;
  WlzPixelV		tmpVal;
  WlzDomain		*domains;
  WlzValues		*values;
  int			i, nplanes;
  int			red = 0, green = 0, blue = 0, alpha = 0;
  WlzErrorNum		errNum=WLZ_ERR_NONE;

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

    case WLZ_2D_DOMAINOBJ:
      if( obj->domain.i == NULL ){
	errNum = WLZ_ERR_DOMAIN_NULL;
      }
      else if( obj->values.v == NULL ){
	errNum = WLZ_ERR_VALUES_NULL;
      }
      break;

    case WLZ_3D_DOMAINOBJ:
      /* check planedomain and voxeltable */
      if( obj->domain.p == NULL ){
	errNum =  WLZ_ERR_DOMAIN_NULL;
      }
      else if( obj->domain.p->type != WLZ_PLANEDOMAIN_DOMAIN ){
	errNum = WLZ_ERR_DOMAIN_TYPE;
      }
      else if( obj->values.vox == NULL ){
	errNum = WLZ_ERR_VALUES_NULL;
      }
      else if( obj->values.vox->type != WLZ_VOXELVALUETABLE_GREY ){
	errNum = WLZ_ERR_VALUES_TYPE;
      }
      else {
	/* set range of each plane if non-empty - indicated by NULL */
	domains = obj->domain.p->domains;
	values = obj->values.vox->values;
	nplanes = obj->domain.p->lastpl - obj->domain.p->plane1 + 1;
	for(i=0; (errNum == WLZ_ERR_NONE) && (i < nplanes);
	    i++, domains++, values++){

	  if( (*domains).core == NULL || (*values).core == NULL ){
	    continue;
	  }

	  if((tmpObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, *values,
				    NULL, NULL,	NULL)) != NULL){
	    errNum = WlzGreyScalarDivValue(tmpObj, val);
	    WlzFreeObj( tmpObj );
	  }
	}
      }
      return errNum;

    case WLZ_TRANS_OBJ:
      return WlzGreyScalarDivValue(obj->values.obj, val);

    case WLZ_EMPTY_OBJ:
      return errNum;

    default:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;
    }
  }

  if( errNum == WLZ_ERR_NONE ){
    errNum = WlzInitGreyScan(obj, &iwsp, &gwsp);
    WlzValueConvertPixel(&tmpVal, val, WLZ_GREY_DOUBLE);
    while( (errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE ){

      gptr = gwsp.u_grintptr;
      switch (gwsp.pixeltype) {

      case WLZ_GREY_INT:
	for (i=0; i<iwsp.colrmn; i++, gptr.inp++)
	  *gptr.inp /= tmpVal.v.dbv;
	break;

      case WLZ_GREY_SHORT:
	for (i=0; i<iwsp.colrmn; i++, gptr.shp++)
	  *gptr.shp /= tmpVal.v.dbv;
	break;

      case WLZ_GREY_UBYTE:
	for (i=0; i<iwsp.colrmn; i++, gptr.ubp++)
	  *gptr.ubp /= tmpVal.v.dbv;
	break;

      case WLZ_GREY_FLOAT:
	for (i=0; i<iwsp.colrmn; i++, gptr.flp++)
	  *gptr.flp /= tmpVal.v.dbv;
	break;

      case WLZ_GREY_DOUBLE:
	for (i=0; i<iwsp.colrmn; i++, gptr.dbp++)
	  *gptr.dbp /= tmpVal.v.dbv;
	break;

      case WLZ_GREY_RGBA:
	for (i=0; i<iwsp.colrmn; i++, gptr.rgbp++)
	  red = WLZ_RGBA_RED_GET(*gptr.rgbp) / tmpVal.v.dbv;
	  green = WLZ_RGBA_GREEN_GET(*gptr.rgbp) / tmpVal.v.dbv;
	  blue = WLZ_RGBA_BLUE_GET(*gptr.rgbp) / tmpVal.v.dbv;
	  alpha = WLZ_RGBA_ALPHA_GET(*gptr.rgbp);
	  red = WLZ_CLAMP(red, 0, 255);
	  green = WLZ_CLAMP(red, 0, 255);
	  blue = WLZ_CLAMP(red, 0, 255);
	  WLZ_RGBA_RGBA_SET(*gptr.rgbp, red, green, blue, alpha);
	break;

      default:
	errNum = WLZ_ERR_GREY_TYPE;
	break;
      }
    }
    if( errNum == WLZ_ERR_EOO ){
      errNum = WLZ_ERR_NONE;
    }
  }

  return errNum;
}