Exemplo n.º 1
0
VImage VCombineBands (int nels, VImage src_images[], VBand src_bands[],
		      VImage dest)
{
  int n, i;
  VImage result, src = src_images[0];

  /* Count the number of bands needed in the destination image: */
  for (i = n = 0; i < nels; i++)
    n += (src_bands[i] == VAllBands) ? VImageNBands (src_images[i]) : 1;

  /* Check or allocate the destination image: */
  result = VSelectDestImage ("VCombineBands", dest, n,
			     VImageNRows (src), VImageNColumns (src), 
			     VPixelRepn (src));
  if (! result)
    return NULL;

  /* Copy each source band into the destination image: */
  for (i = n = 0; i < nels; i++) {
    if (! VCopyBand (src_images[i], src_bands[i], result, n)) {
      if (result != dest)
	VDestroyImage (result);
      return NULL;
    }
    n += (src_bands[i] == VAllBands) ? VImageNBands (src_images[i]) : 1;
  }
  return result;
}
Exemplo n.º 2
0
/*!
  \fn VImage VDTDilate(VImage src,VImage dest,VDouble radius)
  \brief 3D morphological dilation
  \param src   input image (bit repn)
  \param dest  output image (bit repn)
  \param radius radius of the spherical structural element
*/
VImage
VDTDilate(VImage src,VImage dest,VDouble radius)
{
  VImage float_image;
  VBit *bin_pp;
  VFloat *float_pp;
  int i,nbands,nrows,ncols,npixels;

  if (VPixelRepn(src) != VBitRepn) 
    VError("Input image must be of type VBit");

  nbands  = VImageNBands(src);
  nrows   = VImageNRows(src);
  ncols   = VImageNColumns(src);
  npixels = nbands * nrows * ncols;

  float_image = VChamferDist3d(src,NULL,VFloatRepn);
  if (! float_image) 
    VError("VDTDilate failed.\n");

  dest = VSelectDestImage("VDTDilate",dest,nbands,nrows,ncols,VBitRepn);
  if (! dest) return NULL;

  float_pp  = (VFloat *) VPixelPtr(float_image,0,0,0);
  bin_pp    = (VBit *) VPixelPtr(dest,0,0,0);
  for (i=0; i<npixels; i++)
    *bin_pp++ = ((*float_pp++ > radius) ? 0 : 1);

  VDestroyImage(float_image);

  VCopyImageAttrs (src,dest);
  return dest;
}
Exemplo n.º 3
0
/*!
\fn VImage VMapImageRange(VImage src,VImage dest,VRepnKind repn)
\brief
The minimum and maximum grey values of the input images are computed,
and a linear mapping is performed mapping the input minimum(maximum) 
of the input image to the min(max) value of the output pixel repn.
E.g. if the input image min is -17 and its max is +2376, and the output repn
is VUByteRepn, then the linear mapping function maps -17 to 0 and
+2376 to 255.
\param src   input image  (any repn)
\param dest  output image
\param repn  the output pixel repn (e.g. VUByteRepn)
*/
VImage
VMapImageRange(VImage src,VImage dest,VRepnKind repn)
{
  int i,nbands,nrows,ncols,npixels;
  float u,ymin,ymax,dmin,dmax,slope;

  if (repn == VDoubleRepn || repn == VLongRepn || repn == VSByteRepn)
    VError(" VMapImageRange: double, long and sbyte are not supported");

  nbands = VImageNBands(src);
  nrows  = VImageNRows(src);
  ncols  = VImageNColumns(src);
  npixels = VImageNPixels(src);

  dest = VSelectDestImage("VMapImageRange",dest,nbands,nrows,ncols,repn);
  if (! dest) VError(" err creating dest image");
  VFillImage(dest,VAllBands,0);


  ymin = VPixelMaxValue(src);
  ymax = VPixelMinValue(src);

  for (i=0; i<npixels; i++) {
    u = VGetPixelValue (src,i);
    if (u < ymin) ymin = u;
    if (u > ymax) ymax = u;
  }

  dmax = VPixelMaxValue(dest);
  dmin = VPixelMinValue(dest);

  slope = (dmax - dmin) / (ymax - ymin);

  for (i=0; i<npixels; i++) {
    u = VGetPixelValue (src,i);
    u = slope * (u - ymin);
    if (u < dmin) u = dmin;
    if (u > dmax) u = dmax;
    VSetPixelValue(dest,i,(VFloat) u);
  }

  VCopyImageAttrs (src, dest);
  return dest;
}
Exemplo n.º 4
0
VBoolean VCopyBand (VImage src, VBand src_band, VImage dest, VBand dest_band)
{
  int nbands, src_npixels, dest_npixels;
  VPointer src_pixels, dest_pixels;

  /* The destination image must exist: */
  if (! dest) {
    VWarning ("VCopyBand: No destination specified");
    return FALSE;
  }

  /* VAllBands not accepted for destination band: */
  if (dest_band < 0 || dest_band >= VImageNBands (dest)) {
    VWarning ("VCopyBand: Band %d referenced in image of %d bands",
	      (int) dest_band, (int) VImageNBands (dest));
    return FALSE;
  }

  /* Ensure that the destination image has the appropriate dimensions
     and pixel representation: */
  nbands = dest_band;
  if (src_band == VAllBands)
    nbands += VImageNBands (src) - 1;
  if (nbands < VImageNBands (dest))
    nbands = VImageNBands (dest);
  if (! VSelectDestImage ("VCopyBand", dest, nbands, VImageNRows (src),
			  VImageNColumns (src), VPixelRepn (src)))
    return FALSE;

  /* Locate the specified source and destination bands: */
  if (! VSelectBand ("VCopyBand", src, src_band,
		     & src_npixels, & src_pixels))
    return FALSE;
  if (! VSelectBand ("VCopyBand", dest, dest_band,
		     & dest_npixels, & dest_pixels))
    return FALSE;

  /* Copy from the source band to the destination band: */
  memcpy (dest_pixels, src_pixels, src_npixels * VPixelSize (src));

  return TRUE;
}
Exemplo n.º 5
0
VImage VCopyImagePixels (VImage src, VImage dest, VBand band)
{
  int npixels;
  VPointer src_pixels;
  VImage result;

  /* Locate the source and destination of the copy: */
  if (! VSelectBand ("VCopyImagePixels", src, band, & npixels, & src_pixels))
    return NULL;
  result = VSelectDestImage ("VCopyImagePixels", dest,
			     band == VAllBands ? VImageNBands (src) : 1,
			     VImageNRows (src), VImageNColumns (src),
			     VPixelRepn (src));
  if (! result)
    return NULL;

  /* Copy pixel values from src to dest: */
  memcpy (VImageData (result), src_pixels, npixels * VPixelSize (src));

  return result;
}
Exemplo n.º 6
0
VImage
VSConvolveCol (VImage src,VImage dest,VImage kernel)
{
  int b,r,c,nbands,nrows,ncols;
  int c0,c1,cc;
  float sum,x;
  VFloat *float_pp;
  int dim,d;

  nrows  = VImageNRows (src);
  ncols  = VImageNColumns (src);
  nbands = VImageNBands (src);

  dest = VSelectDestImage("VConvolveCol",dest,nbands,nrows,ncols,VFloatRepn);
  VFillImage(dest,VAllBands,0);
  dim  = VImageNColumns(kernel);
  d    = dim/2;

  for (b=0; b<nbands; b++) {
    for (r=0; r<nrows; r++) {
      for (c=d; c<ncols-d; c++) {

	float_pp = (VFloat *) VImageData(kernel);
	sum = 0;
	c0 = c-d;
	c1 = c+d;
	if (c0 < 0) c0 = 0;
	if (c1 >= ncols) c1 = ncols-1;
	for (cc=c0; cc<=c1; cc++) {
	  x = VPixel(src,b,r,cc,VFloat);
	  sum += x * (*float_pp++);
	}
	VPixel(dest,b,r,c,VFloat) = sum;
      }
    }
  }
  return dest;
}
Exemplo n.º 7
0
VImage
VSConvolveRow (VImage src,VImage dest,VImage kernel)
{
  int b,r,c,nbands,nrows,ncols;
  int r0,r1,rr;
  float sum,x;
  VFloat *float_pp;
  int d,dim;

  dim = VImageNColumns(kernel);
  d = dim/2;

  nrows  = VImageNRows (src);
  ncols  = VImageNColumns (src);
  nbands = VImageNBands (src);

  dest = VSelectDestImage("VConvolveRow",dest,nbands,nrows,ncols,VFloatRepn);

  for (b=0; b<nbands; b++) {
    for (r=d; r<nrows-d; r++) {
      for (c=0; c<ncols; c++) {

	float_pp = (VFloat *) VImageData(kernel);
	sum = 0;
	r0 = r-d;
	r1 = r+d;
	if (r0 < 0) r0 = 0;
	if (r1 >= nrows) r1 = nrows-1;
	for (rr=r0; rr<=r1; rr++) {
	  x = VPixel(src,b,rr,c,VFloat);
	  sum += x * (*float_pp++);
	}
	VPixel(dest,b,r,c,VFloat) = sum;
      }
    }
  }
  return dest;
}
Exemplo n.º 8
0
VImage
VSConvolveBand (VImage src,VImage dest,VImage kernel)
{
  int b,r,c,nbands,nrows,ncols;
  int b0,b1,bb;
  float sum,x;
  VFloat *float_pp;
  int d,dim;

  dim = VImageNColumns(kernel);
  d = dim/2;

  nrows  = VImageNRows (src);
  ncols  = VImageNColumns (src);
  nbands = VImageNBands (src);

  dest = VSelectDestImage("VConvolveBand",dest,nbands,nrows,ncols,VFloatRepn);

  for (b=d; b<nbands-d; b++) {
    for (r=0; r<nrows; r++) {
      for (c=0; c<ncols; c++) {

	float_pp = (VFloat *) VImageData(kernel);
	sum = 0;
	b0 = b-d;
	b1 = b+d;
	if (b0 < 0) b0 = 0;
	if (b1 >= nbands) b1 = nbands-1;
	for (bb=b0; bb<=b1; bb++) {
	  x = VPixel(src,bb,r,c,VFloat);
	  sum += x * (*float_pp++);
	}
	VPixel(dest,b,r,c,VFloat) = sum;
      }
    }
  }
  return dest;
}
Exemplo n.º 9
0
VImage VCombineBandsVa (VImage dest, ...)
{
  va_list args;
  VImage src, result;
  int nbands;
  VBand src_band, dest_band;

  /* Count the number of bands to be combined: */
  va_start (args, dest);
  for (nbands = 0; (src = va_arg (args, VImage)) != 0; nbands +=
	 (va_arg (args, VBand) == VAllBands) ? VImageNBands (src) : 1) ;
  va_end (args);

  /* Check or allocate the destination image: */
  va_start (args, dest);
  src = va_arg (args, VImage);
  va_end (args);
  result = VSelectDestImage ("VCombineBandsVa", dest, nbands,
			     VImageNRows (src), VImageNColumns (src),
			     VPixelRepn (src));
  if (! result)
    return NULL;

  /* Copy each source band into the destination image: */
  va_start (args, dest);
  for (dest_band = 0; (src = va_arg (args, VImage)) != 0; ) {
    src_band = va_arg (args, VBand);
    if (! VCopyBand (src, src_band, result, dest_band)) {
      if (result != dest)
	VDestroyImage (result);
      return NULL;
    }
    dest_band += (src_band == VAllBands) ? VImageNBands (src) : 1;
  }
  va_end (args);
  return result;
}
Exemplo n.º 10
0
/*
 *  Flip3dImage
 *
 */
VImage Flip3dImage(VImage src, VImage dest, VBand band, VBoolean x_axis, VBoolean y_axis, VBoolean z_axis) {
    int nx, ny, nz;
    int i, j, k;
    nx = VImageNColumns(src);
    ny = VImageNRows(src);
    nz = VImageNBands(src);
    /* Check the destination image.
       If it is NULL, then create one of the appropriate size and type. */
    dest = VSelectDestImage("Flip3dImage", dest,
                            nz, ny, nx, VPixelRepn(src));
    if(! dest)
        return NULL;
    for(i = 0; i < nx; i++)
        for(j = 0; j < ny; j++)
            for(k = 0; k < nz; k++) {
                if(! x_axis && ! y_axis && ! z_axis)
                    VSetPixel(dest, k, j, i, VGetPixel(src, k, j, i));
                if(x_axis && ! y_axis && ! z_axis)
                    VSetPixel(dest, k, j, i, VGetPixel(src, k, j, nx - i - 1));
                if(! x_axis &&   y_axis && ! z_axis)
                    VSetPixel(dest, k, j, i, VGetPixel(src, k, ny - j - 1, i));
                if(! x_axis && ! y_axis &&   z_axis)
                    VSetPixel(dest, k, j, i, VGetPixel(src, nz - k - 1, j, i));
                if(x_axis &&   y_axis && ! z_axis)
                    VSetPixel(dest, k, j, i, VGetPixel(src, k, ny - j - 1, nx - i - 1));
                if(x_axis && ! y_axis &&   z_axis)
                    VSetPixel(dest, k, j, i, VGetPixel(src, nz - k - 1, j, nx - i - 1));
                if(! x_axis &&   y_axis &&   z_axis)
                    VSetPixel(dest, k, j, i, VGetPixel(src, nz - k - 1, ny - j - 1, i));
                if(x_axis &&   y_axis &&   z_axis)
                    VSetPixel(dest, k, j, i, VGetPixel(src, nz - k - 1, ny - j - 1, nx - i - 1));
            };
    /* Let the destination inherit any attributes of the source image: */
    VCopyImageAttrs(src, dest);
    return dest;
};
Exemplo n.º 11
0
/*!
\fn VImage VBiLinearScale2d (VImage src,VImage dest,int dest_nrows,int dest_ncols,
                             VFloat yscale,VFloat xscale)
\brief Scale all slices of a 3D image using a 2D slicewise bilinear interpolation.
\param src         input image (any repn)
\param dest        output image (any repn)
\param dest_nrows  number of rows in output image
\param dest_ncols  number of columns in output image
\param shift[2]    translation vector (row,column)
\param scale[2]    scaling vector (row,column)

*/
VImage 
VBiLinearScale2d (VImage src,VImage dest,int dest_nrows,int dest_ncols,
		  VFloat shift[2], VFloat scale[2])
{
  int   b,r,c;
  float rp=0,cp=0,x,y,yscale,xscale;
  int   right,left,top,bottom;
  float p1,p2,p3,p4;
  float val;
  int   nrows,ncols,nbands; 
  VRepnKind repn;


  /* Extract data from source image */
  nrows  = VImageNRows(src);
  ncols  = VImageNColumns(src);
  nbands = VImageNBands(src);
  repn   = VPixelRepn(src);


  dest = VSelectDestImage("VBiLinearScale2d",dest,nbands,dest_nrows,dest_ncols,repn);
  if (! dest) return NULL;
  VFillImage(dest,VAllBands,0);


#define Top(r)    ( (int) (r) )
#define Bottom(r) ( (int) (r) + 1 )
#define Left(c)   ( (int) (c) )
#define Right(c)  ( (int) (c) + 1 )
    
  yscale = 1.0 / scale[0];
  xscale = 1.0 / scale[1];

  for (b = 0; b < nbands; b++) {

    for (r = 0; r < dest_nrows; r++) {
      rp = yscale * ((float) r - shift[0]);
      if (rp < 0 || rp >= nrows) continue;

      for (c = 0; c < dest_ncols; c++) {
	cp = xscale * ((float) c - shift[1]);
	if (cp < 0 || cp >= ncols) continue;
	
	right = Right(cp);
	left  = Left(cp);
	if (left < 0 || right >= ncols) continue;

	top     = Top(rp);
	bottom  = Bottom(rp);
	if (top < 0 || bottom >= nrows) continue;

	x = right - cp;
	y = bottom - rp;

	p1 = VGetPixel(src,b,top,left);
	p2 = VGetPixel(src,b,top,right);
	p3 = VGetPixel(src,b,bottom,left);
	p4 = VGetPixel(src,b,bottom,right);

	val = x * y * p1
	  + (1-x) * y * p2
	  + x * (1-y) * p3
	  + (1-x) * (1-y) * p4;

	if (repn == VUByteRepn) {
	  val = (int)(val + 0.5);
	  if (val <   0) val = 0;
	  if (val > 255) val = 255;
	}
	VSetPixel(dest,b,r,c,(VDouble) val);
      }
    }
  }

  VCopyImageAttrs (src, dest);
  return dest;
}
Exemplo n.º 12
0
/*!
  \fn VImage VDTClose(VImage src,VImage dest,VDouble radius)
  \brief 3D morphological closing (dilation+erosion)
  \param src   input image (bit repn)
  \param dest  output image (bit repn)
  \param radius radius of the spherical structural element
*/
VImage
VDTClose(VImage src,VImage dest,VDouble radius)
{
  VImage float_image=NULL,tmp=NULL;
  VBit *bin_pp;
  VFloat *float_pp;
  int i,nbands,nrows,ncols,npixels,b,r,c;
  int border = 7;

  border = (int) (radius - 1);

  if (VPixelRepn(src) != VBitRepn) 
    VError("Input image must be of type VBit");

  nbands  = VImageNBands(src) + 2*border;
  nrows   = VImageNRows(src) + 2*border;
  ncols   = VImageNColumns(src) + 2*border;
  npixels = nbands * nrows * ncols;

  tmp = VCreateImage(nbands,nrows,ncols,VBitRepn);

  for (b=border; b<nbands-border; b++) {
    for (r=border; r<nrows-border; r++) {
      for (c=border; c<ncols-border; c++) {
	VPixel(tmp,b,r,c,VBit) = VPixel(src,b-border,r-border,c-border,VBit);
      }
    }
  }

  float_image = VChamferDist3d(tmp,NULL,VFloatRepn);
  if (! float_image) 
    VError("VDTClose failed.\n");

  float_pp  = (VFloat *) VPixelPtr(float_image,0,0,0);
  bin_pp    = (VBit *) VPixelPtr(tmp,0,0,0);
  for (i=0; i<npixels; i++)
    *bin_pp++ = ((*float_pp++ > radius) ? 1 : 0);

  float_image = VChamferDist3d(tmp,float_image,VFloatRepn);
  if (! float_image) 
    VError("VDTClose failed.\n");

  float_pp = (VFloat *) VPixelPtr(float_image,0,0,0);
  bin_pp   = (VBit *) VPixelPtr(tmp,0,0,0);
  for (i=0; i<npixels; i++)
    *bin_pp++ = ((*float_pp++ > radius) ? 1 : 0);

  VDestroyImage(float_image);


  dest = VSelectDestImage("VDTClose",dest,VImageNBands(src),VImageNRows(src),VImageNColumns(src),
			  VBitRepn);
			  
  if (! dest) return NULL;

  for (b=border; b<nbands-border; b++) {
    for (r=border; r<nrows-border; r++) {
      for (c=border; c<ncols-border; c++) {
	VPixel(dest,b-border,r-border,c-border,VBit) = VPixel(tmp,b,r,c,VBit);
      }
    }
  }
  VDestroyImage(tmp);

  VCopyImageAttrs (src, dest);
  return dest;
}
Exemplo n.º 13
0
Arquivo: Shear.c Projeto: Rollmops/via
VImage VShearImageX (VImage src, VImage dest, VBand band, double shear)
{
  int src_nrows, src_ncols, src_nbands;
  int dest_nrows, dest_ncols, dest_nbands;
  VRepnKind src_repn, dest_repn;
  double skew, skewi, skewf, left, oleft;
  int x, y, b, src_curband, dest_curband;
  int extra_ncols, sdx, sdy, ddx, ddy;

  /* Read properties of "src": */
  src_nrows  = VImageNRows (src);
  src_ncols  = VImageNColumns (src);
  src_nbands = VImageNBands (src);
  src_repn   = VPixelRepn (src);

  /* Check to ensure that "band" exists: */
  if (band != VAllBands && (band < 0 || band >= src_nbands)) {
    VWarning ("VShearImageY: Band %d referenced in image of %d bands",
	      band, VImageNBands (src));
    return NULL;
  }
    
  /* Determine properties of "dest": */
  dest_nrows  = src_nrows;
  extra_ncols = (int) floor (shear * (src_nrows - 0.5));
  dest_ncols  = src_ncols + VMax (extra_ncols, -extra_ncols) + 1;
  dest_nbands = (band == VAllBands) ? src_nbands : 1;
  dest_repn   = src_repn;

  /* Calculate displacements in converting from xy-coord. to
     row/column-coord. : */
  sdx = 0;
  sdy = src_nrows - 1;
  ddx = (extra_ncols < 0) ? -extra_ncols : 0;
  ddy = dest_nrows - 1;
    
  /* Create dest image */
  dest = VSelectDestImage ("VShearImageX", dest,
			   dest_nbands, dest_nrows, dest_ncols, dest_repn);
    
  if (dest == NULL)
    return NULL;

  /* Set all dest pixels to zero: */
  VFillImage (dest, VAllBands, 0.0);
    
  /* Treat lower left-hand corner of image as origin, with
     y up and x to the right. */
    
  /*
   * Shear a row of an image of a particular type: 
   */
#define ShearRow(type)                                         \
    {                                                              \
	type pixel;                                                \
	for (x = 0; x < src_ncols; x++) {                          \
	    pixel = VPixel (src,                                   \
			    src_curband,                           \
			    XYToRow (x, y, sdx, sdy),              \
			    XYToCol (x, y, sdx, sdy),              \
			    type);                                 \
	    left = pixel * skewf;                                  \
	    pixel = pixel - left + oleft;                          \
	    VPixel (dest,                                          \
		    dest_curband,                                  \
		    XYToRow ((int) (x + skewi), y, ddx, ddy),      \
		    XYToCol ((int) (x + skewi), y, ddx, ddy),      \
		    type)                                          \
		= pixel;                                           \
	    oleft = left;                                          \
	}                                                          \
	VPixel (dest,                                              \
		dest_curband,                                      \
		XYToRow ((int) (src_ncols + skewi), y, ddx, ddy),  \
		XYToCol ((int) (src_ncols + skewi), y, ddx, ddy),  \
		type)                                              \
	    = (type) oleft;                                        \
    }

  /* For each band in the dest image do: */
  for (b = 0; b < dest_nbands; b++) {

    src_curband = (band == VAllBands) ? b : band;
    dest_curband = (band == VAllBands) ? b : 0;
	
    /* For each row in the source image do: */
    for (y = 0; y < src_nrows; y++) {
	    
      skew = shear * (y + 0.5);
      skewi = floor (skew);
      skewf = skew - skewi;

      oleft = 0.0;

      /* Shear a row according to pixel representation: */
      switch (src_repn) {
      case VBitRepn:      ShearRow (VBit);    break;
      case VUByteRepn:	ShearRow (VUByte);  break;
      case VSByteRepn:	ShearRow (VSByte);  break;
      case VShortRepn:	ShearRow (VShort);  break;
      case VLongRepn:	ShearRow (VLong);   break;
      case VFloatRepn:	ShearRow (VFloat);  break;
      case VDoubleRepn:	ShearRow (VDouble); break;
      default: break;
      }
    }
  }

  VCopyImageAttrs (src, dest);
  return dest;

#undef ShearRow
}
Exemplo n.º 14
0
VImage
VContrastAny(VImage src,VImage dest,VFloat low,VFloat high)
{
  int nbands,nrows,ncols;
  double xmin,xmax,slope,sum,a;
  float *histo;
  int b,r,c,j,dim;
  VUByte *dest_pp;
  double smin,smax,u,v,tiny;

  nbands = VImageNBands(src);
  nrows  = VImageNRows(src);
  ncols  = VImageNColumns(src);

  dest = VSelectDestImage("VContrastAny",dest,nbands,nrows,ncols,VUByteRepn);
  if (! dest) VError(" err creating dest image");
  VFillImage(dest,VAllBands,0);

  
  smin = VPixelMaxValue(src);
  smax = VPixelMinValue(src);

  for (b=0; b<nbands; b++) {
    for (r=0; r<nrows; r++) {
      for (c=0; c<ncols; c++) {
	u = VGetPixel(src,b,r,c);
	if (u < smin) smin = u;
	if (u > smax) smax = u;
      }
    }
  }
  
  dim = 10000;
  if (VPixelRepn(src) == VUByteRepn) dim = 256;
  histo = (float *) VCalloc(dim,sizeof(float));
  for (j=0; j<dim; j++) histo[j] = 0;
  tiny = 2.0/(double)dim;

  a = ((double) dim) / (smax - smin);

  for (b=0; b<nbands; b++) {
    for (r=0; r<nrows; r++) {
      for (c=0; c<ncols; c++) {
	u = VGetPixel(src,b,r,c);
	if (ABS(u) < tiny) continue;
	j = (int) (a * (u - smin) + 0.5);
	if (j < 0) j = 0;
	if (j >= dim) j = dim-1;
	histo[j]++;
      }
    }
  }

 
  sum = 0;
  for (j=0; j<dim; j++) sum += histo[j];
  for (j=0; j<dim; j++) histo[j] /= sum;

  xmin = 0;
  sum  = 0;
  for (j=0; j<dim; j++) {
    sum += histo[j];
    if (sum > low) break;
  }
  xmin = ((double)j)/a + smin;
  
  xmax = dim;
  sum = 0;
  for (j=dim; j>0; j--) {
    sum += histo[j];
    if (sum > high) break;
  }
  xmax = ((double)j)/a + smin;

  slope = 255.0 / (xmax - xmin);

  dest_pp = (VUByte *) VImageData(dest);
  for (b=0; b<nbands; b++) {
    for (r=0; r<nrows; r++) {
      for (c=0; c<ncols; c++) {
	u = VGetPixel(src,b,r,c);
	v = (int) (slope * (u - xmin) + 0.5);
	if (ABS(u) < tiny) v = 0;
	if (v < 0) v = 0;
	if (v > 255) v = 255;
	*dest_pp++ = (VUByte) v;
      }
    }
  }

  VCopyImageAttrs (src, dest);
  return dest;
}
Exemplo n.º 15
0
/*!
\fn VImage VContrast(VImage src,VImage dest,VRepnKind repn,VFloat alpha,VFloat background)
\param src   input image  (any repn)
\param dest  output image (any repn)
\param repn  the output pixel repn (e.g. VUByteRepn)
\param alpha contrast stretching factor. 
The function stretches grey values between mean-alpha*sigma and mean+alpha*sigma.
\param background input grey values with absolute values less than <background> are
assumed to be image background and are not used for computing the image mean and sigma.
If set to zero, it has no effect.
*/
VImage
VContrast(VImage src,VImage dest,VRepnKind repn,VFloat alpha,VFloat background)
{
  int i,nbands,nrows,ncols,npixels;
  float u,xmin,xmax,ymin,ymax,slope,smin,smax;
  float sum1,sum2,nx;
  float mean,sigma;

  if (repn == VDoubleRepn || repn == VLongRepn || repn == VSByteRepn)
    VError(" double, long and sbyte are not supported by VContrast");

  if (alpha <= 0) VError("alpha must be positive");


  nbands = VImageNBands(src);
  nrows  = VImageNRows(src);
  ncols  = VImageNColumns(src);
  npixels = VImageNPixels(src);

  dest = VSelectDestImage("VContrast",dest,nbands,nrows,ncols,repn);
  if (! dest) VError(" err creating dest image");
  VFillImage(dest,VAllBands,0);

  smin = VPixelMaxValue(src);
  smax = VPixelMinValue(src);

  sum1 = sum2 = nx = 0;
  for (i=0; i<npixels; i++) {
    u = VGetPixelValue (src,i);
    if (ABS(u) < background) continue;
    if (u < smin) smin = u;
    if (u > smax) smax = u;
    sum1 += u;
    sum2 += u*u;
    nx++;
  }
  if (nx < 2) VError(" no foreground pixels found");

  mean  = sum1/nx;
  sigma = sqrt((double)((sum2 - nx * mean * mean) / (nx - 1.0)));

  ymax = VPixelMaxValue(dest);
  ymin = VPixelMinValue(dest);

  xmax = mean + alpha * sigma;
  if (xmax > smax) xmax = smax;

  xmin = mean - alpha * sigma;
  if (xmin < smin) xmin = smin;

  slope = (ymax - ymin) / (xmax - xmin);

  for (i=0; i<npixels; i++) {
    u = VGetPixelValue (src,i);
    if (u != 0) u = slope * (u - xmin);
    if (u > ymax) u = ymax;
    if (u < ymin) u = ymin;
    VSetPixelValue(dest,i,(VFloat) u);
  }

  VCopyImageAttrs (src, dest);
  return dest;
}
Exemplo n.º 16
0
Arquivo: CDT3d.c Projeto: Rollmops/via
/*!
\fn VImage VCDT3d (VImage src,VImage dest, VLong inside,VLong outside,VLong obstacle,VRepnKind repn)
\param src      input image (VUByte)
\param dest     output image (VFloat)
\param inside   ubyte value representing inside voxels
\param outside  ubyte value representing outside voxels
\param obstacle ubyte value representing obstacle voxels
\param repn     output pixel repn (VShortRepn or VFloatRepn)
*/
VImage 
VCDT3d (VImage src,VImage dest,
	VLong inside,VLong outside,VLong obstacle,VRepnKind repn)
{
  int nbands,nrows,ncols,b,r,c;
  int i,n_new,n_old,iter,npixels;
  VFloat d1,d2,d3;
  VFloat u,x,y;
  VUByte *src_pp;
  VFloat *dest_pp,inf;
  VShort *short_pp;
  VImage result=NULL;


  if (repn != VShortRepn && repn != VFloatRepn)
    VError(" VCDT3d: illegal output pixel repn: %d,  short= %d, float= %d",
	   repn,VShortRepn,VFloatRepn);

  /* Check the input image */
  if (VPixelRepn(src) != VUByteRepn) 
    VError("VCDT3d: input image must be of type VUByte");

  
  nbands = VImageNBands(src);
  nrows  = VImageNRows (src);
  ncols  = VImageNColumns (src);
  npixels = nbands * nrows * ncols;

  dest = VSelectDestImage("VCDT3d",dest,nbands,nrows,ncols,VFloatRepn);
  VFillImage(dest,VAllBands,0);
  inf = VPixelMaxValue(dest) - 2;

  dest_pp = (VFloat *) VPixelPtr(dest,0,0,0);
  src_pp = (VUByte *) VPixelPtr(src,0,0,0);
  npixels = nbands * nrows * ncols;
  for (i=0; i<npixels; i++) {
    x = *src_pp++;
    if (x == (VFloat) inside)
      y = inf;
    else if (x == (VFloat) outside)
      y = 0;
    else
      y = -100.0;
    *dest_pp++ = y;
  }

 
  /* optimal chamfer distances (Borgefors,1984, p. 334) */
  d1 = 1.0;
  d2 = 1.314;
  d3 = 1.628;

  /* optimal distances (see Beckers, Smeulders, 1992). */

  d1 = 0.88750;
  d2 = 1.34224;
  d3 = 1.59772;

  /* optimal distances (see Verwer, 1991). */
/*
  d1 = 0.894;
  d2 = 1.3409;
  d3 = 1.5879;
  */

  /* optimal distances (see Kiryati, 1993). */
  /*
  d1 = 0.9016;
  d2 = 1.289;
  d3 = 1.615;
  */

  iter = 0;
  n_old = 1;
  n_new = 0;
  while (n_old != n_new && iter < 6) {

    /* forward scan */

    for (b=1; b<nbands; b++) {
      for (r=1; r<nrows-1; r++) {
	for (c=1; c<ncols-1; c++) {

	  if (VPixel(src,b,r,c,VUByte) != inside) continue;

	  u = VPixel(dest,b,r,c,VFloat);

	  x = VPixel(dest,b-1,r-1,c-1,VFloat) + d3;
	  if (x < u && x >= 0) u = x;

	  x = VPixel(dest,b-1,r-1,c,VFloat) + d2;
	  if (x < u && x >= 0) u = x;

	  x = VPixel(dest,b-1,r-1,c+1,VFloat) + d3;
	  if (x < u && x >= 0) u = x;

	  x = VPixel(dest,b-1,r,c-1,VFloat) + d2;
	  if (x < u && x >= 0) u = x;

	  x = VPixel(dest,b-1,r,c,VFloat) + d1;
	  if (x < u && x >= 0) u = x;

	  x = VPixel(dest,b-1,r,c+1,VFloat) + d2;
	  if (x < u && x >= 0) u = x;

	  x = VPixel(dest,b-1,r+1,c-1,VFloat) + d3;
	  if (x < u && x >= 0) u = x;

	  x = VPixel(dest,b-1,r+1,c,VFloat) + d2;
	  if (x < u && x >= 0) u = x;

	  x = VPixel(dest,b-1,r+1,c+1,VFloat) + d3;
	  if (x < u && x >= 0) u = x;


	  x = VPixel(dest,b,r-1,c-1,VFloat) + d2;
	  if (x < u && x >= 0) u = x;

	  x = VPixel(dest,b,r-1,c,VFloat) + d1;
	  if (x < u && x >= 0) u = x;

	  x = VPixel(dest,b,r-1,c+1,VFloat) + d2;
	  if (x < u && x >= 0) u = x;

	  x = VPixel(dest,b,r,c-1,VFloat) + d1;
	  if (x < u && x >= 0) u = x;

	  if (u >= 0)
	    VPixel(dest,b,r,c,VFloat) = u;
	}
      }
    }

    /* backward scan */

    for (b=nbands-2; b>=0; b--) {
      for (r=nrows-2; r>=1; r--) {
	for (c=ncols-2; c>=1; c--) {

	  if (VPixel(src,b,r,c,VUByte) != inside) continue;

	  u = VPixel(dest,b,r,c,VFloat);
	
	  x = VPixel(dest,b,r,c+1,VFloat) + d1;
	  if (x < u && x >= 0) u = x;

	  x = VPixel(dest,b,r+1,c-1,VFloat) + d2;
	  if (x < u && x >= 0) u = x;

	  x = VPixel(dest,b,r+1,c,VFloat) + d1;
	  if (x < u && x >= 0) u = x;

	  x = VPixel(dest,b,r+1,c+1,VFloat) + d2;
	  if (x < u && x >= 0) u = x;
	

	  x = VPixel(dest,b+1,r-1,c-1,VFloat) + d3;
	  if (x < u && x >= 0) u = x;

	  x = VPixel(dest,b+1,r-1,c,VFloat) + d2;
	  if (x < u && x >= 0) u = x;
	
	  x = VPixel(dest,b+1,r-1,c+1,VFloat) + d3;
	  if (x < u && x >= 0) u = x;


	  x = VPixel(dest,b+1,r,c-1,VFloat) + d2;
	  if (x < u && x >= 0) u = x;

	  x = VPixel(dest,b+1,r,c,VFloat) + d1;
	  if (x < u && x >= 0) u = x;

	  x = VPixel(dest,b+1,r,c+1,VFloat) + d2;
	  if (x < u && x >= 0) u = x;


	  x = VPixel(dest,b+1,r+1,c-1,VFloat) + d3;
	  if (x < u && x >= 0) u = x;

	  x = VPixel(dest,b+1,r+1,c,VFloat) + d2;
	  if (x < u && x >= 0) u = x;

	  x = VPixel(dest,b+1,r+1,c+1,VFloat) + d3;
	  if (x < u && x >= 0) u = x;

	  if (u >= 0)
	    VPixel(dest,b,r,c,VFloat) = u;
	}
      }
    }

    dest_pp = (VFloat *) VPixelPtr(dest,0,0,0);
    n_old = n_new;
    n_new = 0;
    for (i=0; i<npixels; i++) {
      if (*dest_pp++ >= 9999) n_new++;
    }
    iter++;
  }

  dest_pp = (VFloat *) VPixelPtr(dest,0,0,0);
  for (i=0; i<npixels; i++) {
    if (*dest_pp >= 9999 || *dest_pp < 0) *dest_pp = 0;
    dest_pp++;
  }

  /* copy to a short image */
  if (repn == VShortRepn) {
    result = VCreateImage(nbands,nrows,ncols,VShortRepn);
    dest_pp = (VFloat *) VPixelPtr(dest,0,0,0);
    short_pp = (VShort *) VPixelPtr(result,0,0,0);
    for (i=0; i<npixels; i++) {
      *short_pp = VRint((float)(*dest_pp * 10.0f));
      dest_pp++;
      short_pp++;
    }
    VDestroyImage(dest);
    VCopyImageAttrs (src, result);
    return result;
  }
  else if (repn == VFloatRepn) {
    VCopyImageAttrs (src, dest);
    return dest;
  }
  return NULL;
}
Exemplo n.º 17
0
VImage
VHistoEqualize(VImage src,VImage dest,VFloat exponent)
{
  int nbands,nrows,ncols,npixels;
  float u,v,sum;
  float *histo,*p;
  int i,j,dim;
  VShort *src_pp;
  VUByte *dest_pp;
  double smin,smax,x,y;


  if (VPixelRepn(src) != VShortRepn) VError(" input pixel repn must be short");
  if (exponent < 0.5) VError("parameter '-exponent' should be >= 0.5"); 
  if (exponent > 10) VWarning("parameter '-exponent' should be < 10"); 

  nbands = VImageNBands(src);
  nrows  = VImageNRows(src);
  ncols  = VImageNColumns(src);
  npixels = nbands * nrows * ncols;

  dest = VSelectDestImage("VContrastShort",dest,nbands,nrows,ncols,VUByteRepn);
  if (! dest) VError(" err creating dest image");
  VFillImage(dest,VAllBands,0);


  y = (double) exponent;
  smin = VRepnMinValue(VShortRepn);
  smax = VRepnMaxValue(VShortRepn);

  dim = 2.0 * smax + 1.0;
  histo = (float *) VCalloc(dim,sizeof(float));
  for (j=0; j<dim; j++) histo[j] = 0;

  p = (float *) VCalloc(dim,sizeof(float));


  src_pp = (VShort *) VImageData(src);
  for (i=0; i<npixels; i++) {
    j = *src_pp++;
    j -= smin;
    if (j == 0) continue;
    histo[j]++;
  }
 
  sum = 0;
  for (j=0; j<dim; j++) sum += histo[j];
  for (j=0; j<dim; j++) histo[j] /= sum;


  /* cumulative hist */
  for (i=0; i<dim; i++) {
    sum = 0;
    for (j=0; j<=i; j++) sum += histo[j];
    p[i] = sum;
  }


  /* make lut */
  for (i=0; i<dim; i++) {
    x = (double)p[i];
    if (x > 0)
      p[i] = (float)(pow(x,y) * 255.0);
  }

  /* apply lut */
  src_pp  = (VShort *) VImageData(src);
  dest_pp = (VUByte *) VImageData(dest);
  for (i=0; i<npixels; i++) {
    u = *src_pp++;
    j = (int) (u-smin);
    v = (double)p[j];
    if (v < 0) v = 0;
    if (v > 255) v = 255;
    *dest_pp++ = (VUByte) v;
  }

  VFree(p);
  VFree(histo);
  VCopyImageAttrs (src, dest);
  return dest;
}
Exemplo n.º 18
0
/*!
\fn VImage VContrastShort(VImage src,VImage dest,VFloat percent,VFloat background)
\param src   input image  (short repn)
\param dest  output image  (ubyte repn)
*/
VImage
VContrastShort(VImage src,VImage dest,VFloat low,VFloat high)
{
  int nbands,nrows,ncols,npixels;
  float u,v,xmin,xmax,slope,sum;
  float *histo;
  int i,j,dim;
  VShort *src_pp;
  VUByte *dest_pp;
  double smin,smax;
  double percent1,percent2;

  if (VPixelRepn(src) != VShortRepn) VError(" input pixel repn must be short");

  nbands = VImageNBands(src);
  nrows  = VImageNRows(src);
  ncols  = VImageNColumns(src);
  npixels = nbands * nrows * ncols;

  dest = VSelectDestImage("VContrastShort",dest,nbands,nrows,ncols,VUByteRepn);
  if (! dest) VError(" err creating dest image");
  VFillImage(dest,VAllBands,0);


  smin = VRepnMinValue(VShortRepn);
  smax = VRepnMaxValue(VShortRepn);

  percent1 = low;    /* unten  */
  percent2 = high;   /* oben   */


  dim = 2.0 * smax + 1.0;
  histo = (float *) VCalloc(dim,sizeof(float));
  for (j=0; j<dim; j++) histo[j] = 0;


  src_pp = (VShort *) VImageData(src);
  for (i=0; i<npixels; i++) {
    j = *src_pp++;
    j -= smin;
    histo[j]++;
  }
 
  sum = 0;
  for (j=0; j<dim; j++) sum += histo[j];
  for (j=0; j<dim; j++) histo[j] /= sum;

  xmin = 0;
  sum  = 0;
  for (j=0; j<dim; j++) {
    sum += histo[j];
    if (sum > percent1) break;
  }
  xmin = j+smin;

  xmax = dim;
  sum = 0;
  for (j=dim; j>0; j--) {
    sum += histo[j];
    if (sum > percent2) break;
  }
  xmax = j+smin;


  slope = 255.0f / (xmax - xmin);
  
  src_pp  = (VShort *) VImageData(src);
  dest_pp = (VUByte *) VImageData(dest);
  for (i=0; i<npixels; i++) {
    u = *src_pp++;
    v = (int) (slope * (u - xmin) + 0.5);
    if (v < 0) v = 0;
    if (v > 255) v = 255;
    *dest_pp++ = (VUByte) v;
  }

  VFree(histo);
  VCopyImageAttrs (src, dest);
  return dest;
}
Exemplo n.º 19
0
/*!
\fn VImage VContrastUByte(VImage src,VImage dest,VFloat percent,VFloat background)
\param src   input image  (ubyte repn)
\param dest  output image  (ubyte repn)
\param percent percentage of pixels to ignore at either end of the histogram.
\param background input grey values with absolute values less than <background> are
assumed to be image background.
*/
VImage
VContrastUByte(VImage src,VImage dest,VFloat low,VFloat high)
{
  int nbands,nrows,ncols,npixels;
  float u,v,xmin,xmax,slope,sum,background;
  float histo[256];
  int i,j;
  VUByte *src_pp,*dest_pp;

  if (VPixelRepn(src) != VUByteRepn) VError(" input pixel repn must be ubyte");

  nbands = VImageNBands(src);
  nrows  = VImageNRows(src);
  ncols  = VImageNColumns(src);
  npixels = nbands * nrows * ncols;

  dest = VSelectDestImage("VContrastUByte",dest,nbands,nrows,ncols,VUByteRepn);
  if (! dest) VError(" err creating dest image");
  VFillImage(dest,VAllBands,0);

  for (j=0; j<256; j++) histo[j] = 0;

  xmin = VPixelMaxValue(src);
  xmax = VPixelMinValue(src);
  background = xmin;
  
  src_pp = (VUByte *) VImageData(src);
  for (i=0; i<npixels; i++) {
    j = *src_pp++;
    if (j <= background) continue;
    histo[j]++;
  }
 
  sum = 0;
  for (j=0; j<256; j++) sum += histo[j];
  for (j=0; j<256; j++) histo[j] /= sum;

  xmin = 0;
  sum  = 0;
  for (j=0; j<256; j++) {
    if (j > background) sum += histo[j];
    if (sum > low) break;
  }
  xmin = j;

  xmax = 255.0;
  sum = 0;
  for (j=255; j>0; j--) {
    if (j > background) sum += histo[j];
    if (sum > high) break;
  }
  xmax = j;


  slope = (float) (255.0) / ((float) (xmax - xmin));
  
  src_pp  = (VUByte *) VImageData(src);
  dest_pp = (VUByte *) VImageData(dest);

  for (i=0; i<npixels; i++) {
    u = *src_pp;
 
    if (u <= background) {
      v = 0;
    }
    else {
      v = (int) (slope * (u - xmin) + 0.5);
      if (v <   0) v = 0;
      if (v > 255) v = 255;
    }

    *dest_pp = (VUByte) v;
    src_pp++;
    dest_pp++;
  }

  VFree(histo);
  VCopyImageAttrs (src, dest);
  return dest;
}
Exemplo n.º 20
0
/*!
\fn VImage VTriLinearSample3d (VImage src,VImage dest,VImage transform,
     float b0,float r0,float c0,int dst_nbands,int dst_nrows,int dst_ncolumns)
\brief Resample a 3D image using trilinear interpolation.

\param src   input image (any repn)
\param dest  output image (any repn)
\param transform  4x3 transformation image (float or double repn).
The first column of <transform> contains the translation vector.
The remaining three columns contains the 3x3 linear transformation matrix.
\param b0            slice address that remains fixed 
\param r0            row address that remains fixed 
\param c0            column address that remains fixed 
\param dst_nbands    number of output slices
\param dst_nrows     number of output rows
\param dst_ncolumns  number of output columns
*/
VImage 
VTriLinearSample3d(VImage src,VImage dest,VImage transform,
		   float b0,float r0,float c0,
		   int dst_nbands,int dst_nrows,int dst_ncolumns)
{
  int src_nrows, src_ncols, src_nbands; 
  VRepnKind repn;
  int   b,r,c;
  int   i,j,n;
  float bp,rp,cp,bx,rx,cx;
  float a[3][3],ainv[3][3],detA,signx;
  float shift[3];
  float val;

  int   sx, sy, sz;   /* origin of subcube    */
  float px, py, pz;   /* fractions of subcube */
  float qx, qy, qz;   /* fractions of subcube */
  float value;   /* value of voxel */
  int lx, ly, lz;   /* lengths */
  int ox, oy, oz;   /* offsets */
  int  x,  y,  z;   /* indices */



  if (VPixelRepn(transform) != VFloatRepn && VPixelRepn(transform) != VDoubleRepn)
    VError("transform image must be float or double repn");
  
  /* Extract data from source image */
  src_nrows   = VImageNRows(src);
  src_ncols   = VImageNColumns(src);
  src_nbands  = VImageNBands(src);
  repn = VPixelRepn(src);


  /* get transformation matrix : */
  for (i=0; i<3; i++) {
    for (j=0; j<3; j++) {
      a[i][j]  = VGetPixel(transform,0,i,j+1);
    }
  }


  /* get its inverse : */
  ainv[0][0] =  a[1][1]*a[2][2] - a[1][2]*a[2][1];
  ainv[1][0] = -a[1][0]*a[2][2] + a[1][2]*a[2][0];
  ainv[2][0] =  a[1][0]*a[2][1] - a[1][1]*a[2][0];

  ainv[0][1] = -a[0][1]*a[2][2] + a[0][2]*a[2][1];
  ainv[1][1] =  a[0][0]*a[2][2] - a[0][2]*a[2][0];
  ainv[2][1] = -a[0][0]*a[2][1] + a[0][1]*a[2][0];

  ainv[0][2] =  a[0][1]*a[1][2] - a[0][2]*a[1][1];
  ainv[1][2] = -a[0][0]*a[1][2] + a[0][2]*a[1][0];
  ainv[2][2] =  a[0][0]*a[1][1] - a[0][1]*a[1][0];

  /* determinant */
  detA = a[0][0]*ainv[0][0] + a[0][1]*ainv[1][0] + a[0][2]*ainv[2][0]; 
  if (detA == 0) VError(" VTriLinearSample3d: transformation matrix is singular");

  for (i=0; i<3; i++) {
    for (j=0; j<3; j++) {
      ainv[i][j] /= detA;
    }
  }


  /* get translation vector */
  shift[0] = VGetPixel(transform,0,0,0);
  shift[1] = VGetPixel(transform,0,1,0);
  shift[2] = VGetPixel(transform,0,2,0);



#define GetValues(type) \
{ \
  type *src_pp; \
  src_pp = (type *) VPixelPtr (src, sz, sy, sx); \
  val += (float) pz * py * px * *src_pp; src_pp += ox; \
  val += (float) pz * py * qx * *src_pp; src_pp += oy; \
  val += (float) pz * qy * px * *src_pp; src_pp += ox; \
  val += (float) pz * qy * qx * *src_pp; src_pp += oz; \
  val += (float) qz * py * px * *src_pp; src_pp += ox; \
  val += (float) qz * py * qx * *src_pp; src_pp += oy; \
  val += (float) qz * qy * px * *src_pp; src_pp += ox; \
  val += (float) qz * qy * qx * *src_pp; \
  VPixel(dest,b,r,c,type) = val; \
}


  /*
  ** create output image
  */
  dest = VSelectDestImage("VTriLinearSample3d",dest,dst_nbands,dst_nrows,dst_ncolumns,repn);
  if (! dest) return NULL;
  VFillImage(dest,VAllBands,0);

  /* Determines the value of each pixel in the destination image: */
  for (b=0; b<dst_nbands; b++) {
    for (r=0; r<dst_nrows; r++) {
      for (c=0; c<dst_ncolumns; c++) {

	bx = (float) b - shift[0];
	rx = (float) r - shift[1];
	cx = (float) c - shift[2];

	bp = ainv[0][0] * bx + ainv[0][1] * rx + ainv[0][2] * cx;
	rp = ainv[1][0] * bx + ainv[1][1] * rx + ainv[1][2] * cx;
	cp = ainv[2][0] * bx + ainv[2][1] * rx + ainv[2][2] * cx;
	
	bp += b0;
	rp += r0;
	cp += c0;
	
	if (bp < 0 || bp > src_nbands) continue;
	if (rp < 0 || rp > src_nrows) continue;
	if (cp < 0 || cp > src_ncols) continue;

	/* compute origin of subcube */
	sx = (int) (cp);
	sy = (int) (rp);
	sz = (int) (bp);

	/* check subcube */
	if ((sx < -1) || (sx > src_ncols  - 1)) continue;
	if ((sy < -1) || (sy > src_nrows  - 1)) continue;
	if ((sz < -1) || (sz > src_nbands - 1)) continue;

	/* compute fractions of subcube */
	qx = cp - sx; px = 1 - qx;
	qy = rp - sy; py = 1 - qy;
	qz = bp - sz; pz = 1 - qz;

	/* compute lengths and offsets */
	lx = 1;
	ly = src_ncols;
	lz = src_nrows * src_ncols;
	if (sx == -1) {sx = 0; lx = 0;};
	if (sy == -1) {sy = 0; ly = 0;};
	if (sz == -1) {sz = 0; lz = 0;};
	if (sx == src_ncols  - 1) lx = 0;
	if (sy == src_nrows  - 1) ly = 0;
	if (sz == src_nbands - 1) lz = 0;
	ox = lx;
	oy = ox + ly - 2 * lx;
	oz = oy + lz - 2 * ly;
	val = 0;

	switch(repn) {
	case VShortRepn:
	  GetValues(VShort);
	  break;
	case VUByteRepn:
	  GetValues(VUByte);
	  break;
	case VFloatRepn:
	  GetValues(VFloat);
	  break;
	case VSByteRepn:
	  GetValues(VSByte);
	  break;
	default:
	  VError(" illegal pixel repn");
	}

      }
    }
  }

  VCopyImageAttrs (src, dest);
  return dest;
}