Exemplo n.º 1
0
static void	sceneAddObject(SceneClass *self, GeometricObjectClass *obj)
{
  LightClass	*light;

  if (obj->material && RTTI(obj->material) == RTTI(Emissive))
  {
    light = new(AreaLight, obj, obj->material);
    self->addAreaLight(self, light);
  }
Exemplo n.º 2
0
//
// MetaTable::removeString
//
// Removes the given field if it exists as a metastring_t.
// Only one object will be removed. If more than one such object 
// exists, you would need to call this routine until metaerrno is
// set to META_ERR_NOSUCHOBJECT.
//
// When calling this routine, the value of the object is returned 
// in case it is needed, and you will need to then free it yourself 
// using free(). If the return value is not needed, call
// MetaTable::removeStringNR instead and the string value will be destroyed.
//
char *MetaTable::removeString(const char *key)
{
   MetaObject *obj;
   MetaString *str;
   char *value;

   metaerrno = META_ERR_NOERR;

   if(!(obj = getObjectKeyAndType(key, RTTI(MetaString))))
   {
      metaerrno = META_ERR_NOSUCHOBJECT;
      return NULL;
   }

   removeObject(obj);

   // Destroying the MetaString will destroy the value inside it too, unless we
   // get and then nullify its value manually. This is one reason why MetaTable
   // is a friend to these basic types, as it makes some simple management 
   // chores like this more efficient. Otherwise I'd have to estrdup the string 
   // and that's stupid.

   str = static_cast<MetaString *>(obj);
   
   value = str->value;
   str->value = NULL; // destructor does nothing if this is cleared first

   delete str;

   return value;
}
Exemplo n.º 3
0
//
// MetaTable::setInt
//
// If the metatable already contains a metaint of the given name, it will
// be edited to have the provided value. Otherwise, a new metaint will be
// added to the table with that value.
//
void MetaTable::setInt(size_t keyIndex, int newValue)
{
   MetaObject *obj;

   if(!(obj = getObjectKeyAndType(keyIndex, RTTI(MetaInteger))))
      addInt(keyIndex, newValue);
   else
      static_cast<MetaInteger *>(obj)->value = newValue;
}
Exemplo n.º 4
0
//
// MetaTable::setConstString
//
// If the table already contains a MetaConstString with the provided key, its
// value will be set to newValue. Otherwise, a new MetaConstString will be
// created with this key and value and will be added to the table.
//
void MetaTable::setConstString(size_t keyIndex, const char *newValue)
{
   MetaObject *obj;

   if(!(obj = getObjectKeyAndType(keyIndex, RTTI(MetaConstString))))
      addConstString(keyIndex, newValue);
   else
      static_cast<MetaConstString *>(obj)->setValue(newValue);
}
Exemplo n.º 5
0
//
// MetaTable::setString
//
// If the metatable already contains a metastring of the given name, it will
// be edited to have the provided value. Otherwise, a new metastring will be
// added to the table with that value. 
//
void MetaTable::setString(const char *key, const char *newValue)
{
   MetaObject *obj;

   if(!(obj = getObjectKeyAndType(key, RTTI(MetaString))))
      addString(key, newValue);
   else
      static_cast<MetaString *>(obj)->setValue(newValue);
}
Exemplo n.º 6
0
//
// MetaTable::setDouble
//
// If the metatable already contains a metadouble of the given name, it will
// be edited to have the provided value. Otherwise, a new metadouble will be
// added to the table with that value.
//
void MetaTable::setDouble(const char *key, double newValue)
{
   MetaObject *obj;

   if(!(obj = getObjectKeyAndType(key, RTTI(MetaDouble))))
      addDouble(key, newValue);
   else
      static_cast<MetaDouble *>(obj)->value = newValue;
}
Exemplo n.º 7
0
//
// MetaTable::setInt
//
// If the metatable already contains a metaint of the given name, it will
// be edited to have the provided value. Otherwise, a new metaint will be
// added to the table with that value.
//
void MetaTable::setInt(const char *key, int newValue)
{
   MetaObject *obj;

   if(!(obj = getObjectKeyAndType(key, RTTI(MetaInteger))))
      addInt(key, newValue);
   else
      static_cast<MetaInteger *>(obj)->value = newValue;
}
Exemplo n.º 8
0
//
// MetaTable::removeStringNR
//
// As above, but the string value is not returned, but instead freed, to
// alleviate any need the user code might have to free string values in
// which it isn't interested.
//
void MetaTable::removeStringNR(const char *key)
{
   MetaObject *obj;

   metaerrno = META_ERR_NOERR;

   if(!(obj = getObjectKeyAndType(key, RTTI(MetaString))))
   {
      metaerrno = META_ERR_NOSUCHOBJECT;
      return;
   }

   removeObject(obj);

   delete obj;
}
Exemplo n.º 9
0
//
// MetaTable::getInt
//
// Get an integer from the metatable. This routine returns the value
// rather than a pointer to a metaint_t. If an object of the requested
// name doesn't exist in the table, defvalue is returned and metaerrno 
// is set to indicate the problem.
//
// Use of this routine only returns the first such value in the table.
// This routine is meant for singleton fields.
//
int  MetaTable::getInt(size_t keyIndex, int defValue)
{
   int retval;
   MetaObject *obj;

   metaerrno = META_ERR_NOERR;

   if(!(obj = getObjectKeyAndType(keyIndex, RTTI(MetaInteger))))
   {
      metaerrno = META_ERR_NOSUCHOBJECT;
      retval = defValue;
   }
   else
      retval = static_cast<MetaInteger *>(obj)->value;

   return retval;
}
Exemplo n.º 10
0
//
// MetaTable::getConstString
//
// Get a sharable string constant/literal value from the MetaTable. If the
// requested property does not exist as a MetaConstString, the value provided
// by the defValue parameter will be returned, and metaerrno will be set to
// META_ERR_NOSUCHOBJECT. Otherwise, the string constant value is returned and
// metaerrno is META_ERR_NOERR.
//
const char *MetaTable::getConstString(const char *key, const char *defValue)
{
   const char *retval;
   MetaObject *obj;

   metaerrno = META_ERR_NOERR;

   if(!(obj = getObjectKeyAndType(key, RTTI(MetaConstString))))
   {
      metaerrno = META_ERR_NOSUCHOBJECT;
      retval    = defValue;
   }
   else
      retval = static_cast<MetaConstString *>(obj)->value;

   return retval;
}
Exemplo n.º 11
0
//
// MetaTable::getDouble
//
// Get a double from the metatable. This routine returns the value
// rather than a pointer to a metadouble_t. If an object of the requested
// name doesn't exist in the table, defvalue is returned and metaerrno is set
// to indicate the problem.
//
// Use of this routine only returns the first such value in the table.
// This routine is meant for singleton fields.
//
double MetaTable::getDouble(const char *key, double defValue)
{
   double retval;
   MetaObject *obj;

   metaerrno = META_ERR_NOERR;

   if(!(obj = getObjectKeyAndType(key, RTTI(MetaDouble))))
   {
      metaerrno = META_ERR_NOSUCHOBJECT;
      retval = defValue;
   }
   else
      retval = static_cast<MetaDouble *>(obj)->value;

   return retval;
}
Exemplo n.º 12
0
//
// MetaTable::removeDouble
//
// Removes the given field if it exists as a metadouble_t.
// Only one object will be removed. If more than one such object 
// exists, you would need to call this routine until metaerrno is
// set to META_ERR_NOSUCHOBJECT.
//
// The value of the object is returned in case it is needed.
//
double MetaTable::removeDouble(const char *key)
{
   MetaObject *obj;
   double value;

   metaerrno = META_ERR_NOERR;

   if(!(obj = getObjectKeyAndType(key, RTTI(MetaDouble))))
   {
      metaerrno = META_ERR_NOSUCHOBJECT;
      return 0.0;
   }

   removeObject(obj);

   value = static_cast<MetaDouble *>(obj)->value;

   delete obj;

   return value;
}
Exemplo n.º 13
0
//
// MetaTable::removeInt
//
// Removes the given field if it exists as a metaint_t.
// Only one object will be removed. If more than one such object 
// exists, you would need to call this routine until metaerrno is
// set to META_ERR_NOSUCHOBJECT.
//
// The value of the object is returned in case it is needed.
//
int MetaTable::removeInt(const char *key)
{
   MetaObject *obj;
   int value;

   metaerrno = META_ERR_NOERR;

   if(!(obj = getObjectKeyAndType(key, RTTI(MetaInteger))))
   {
      metaerrno = META_ERR_NOSUCHOBJECT;
      return 0;
   }

   removeObject(obj);

   value = static_cast<MetaInteger *>(obj)->value;

   delete obj;

   return value;
}
Exemplo n.º 14
0
//
// MetaTable::removeConstString
//
// Removes a constant string from the table with the given key. If no such
// object exists, metaerrno will be META_ERR_NOSUCHOBJECT and NULL is returned.
// Otherwise, metaerrno is META_ERR_NOERR and the shared string value that 
// was in the MetaConstString instance is returned.
//
const char *MetaTable::removeConstString(const char *key)
{
   MetaObject *obj;
   MetaConstString *str;
   const char *value;

   metaerrno = META_ERR_NOERR;

   if(!(obj = getObjectKeyAndType(key, RTTI(MetaConstString))))
   {
      metaerrno = META_ERR_NOSUCHOBJECT;
      return NULL;
   }

   removeObject(obj);

   str = static_cast<MetaConstString *>(obj);
   value = str->value;
   delete str;

   return value;
}
Exemplo n.º 15
0
int main (int argc, char* argv[])
{
   VString        inname;            /* name of input images      */
   VString        outname;           /* name of output images     */
   VString        fieldname;         /* name of deformation field */
   VBoolean       verbose = TRUE;    /* verbose flag              */
   VOptionDescRec options[] =        /* options of program        */
   {
      {"in",      VStringRepn,  1, &inname,    VRequiredOpt, NULL, "Input image"},
      {"out",     VStringRepn,  1, &outname,   VRequiredOpt, NULL, "Deformed output image"},
      {"field",   VStringRepn,  1, &fieldname, VRequiredOpt, NULL, "3D deformation field"},
      {"verbose", VBooleanRepn, 1, &verbose,   VOptionalOpt, NULL, "Show status messages. Optional"}
   };

   VAttrList in_history=NULL;      /* history of input images      */
   VAttrList field_history=NULL;   /* history of deformation field */

   VAttrList In;           /* input images  */
   VImage    Dx, Dy, Dz;   /* field images  */

   VAttrListPosn pos;   /* position in list */
   VImage        in;    /* image in list    */

   float  fx, fy, fz;   /* scaling factors          */
   VImage dx, dy, dz;   /* scaled deformation field */

   VAttrListPosn rider;                         /* functional data rider   */
   int           bands, rows, columns, steps;   /* size of functional data */
   VImage        data;                          /* functional data         */
   VShort        *src, *dest;                   /* functional data pointer */

   VBoolean success;   /* success flag */

   int n, t, z;   /* indices */


   /* print information */
   char prg_name[100];
	char ver[100];
	getLipsiaVersion(ver, sizeof(ver));
	sprintf(prg_name, "vdeform V%s", ver);
  
   fprintf (stderr, "%s\n", prg_name); fflush (stderr);

   /* parse command line */
   if (!VParseCommand (VNumber (options), options, &argc, argv))
   {
      if (argc > 1) VReportBadArgs (argc, argv);
      VReportUsage (argv[0], VNumber (options), options, NULL);
      exit (1);
   }

   /* read input images */
   if (verbose) {fprintf (stderr, "Reading input image '%s' ...\n", inname); fflush (stderr);}
   ReadImages (inname, In, in_history);
   if (!In) exit (2);

   /* read deformation field */
   if (verbose) {fprintf (stderr, "Reading 3D deformation field '%s' ...\n", fieldname); fflush (stderr);}
   ReadField (fieldname, Dx, Dy, Dz, field_history);
   if (!Dx || !Dy || !Dz) exit (3);


   /* deform anatomical images */
   for (VFirstAttr (In, &pos); VAttrExists (&pos); VNextAttr (&pos))
   {
      /* get image */
      VGetAttrValue (&pos, NULL, VImageRepn, &in);
      if (VPixelRepn (in) != VUByteRepn) break;

      /* compare image and field */
      if (verbose) {fprintf (stderr, "Comparing anatomical image and deformation field ...\n"); fflush (stderr);}
      if (!Compatible (in, Dx)) exit (4);
      if (!Compatible (in, Dy)) exit (4);
      if (!Compatible (in, Dz)) exit (4);

      /* deform image */
      if (verbose) {fprintf (stderr, "Deforming anatomical image ...\n"); fflush (stderr);}
      RTTI (in, TrilinearInverseDeform, (in, Dx, Dy, Dz));
      VSetAttrValue (&pos, NULL, VImageRepn, in);
   }


   /* deform map images */
   for (; VAttrExists (&pos); VNextAttr (&pos))
   {
      /* get image */
      VGetAttrValue (&pos, NULL, VImageRepn, &in);
      if (VPixelRepn (in) != VFloatRepn) break;

      /* scale field */
      if (verbose) {fprintf (stderr, "Scaling deformation field ...\n"); fflush (stderr);}
      fx = (float) VImageNColumns (in) / (float) VImageNColumns (Dx);
      fy = (float) VImageNRows    (in) / (float) VImageNRows    (Dy);
      fz = (float) VImageNBands   (in) / (float) VImageNBands   (Dz);
      TrilinearScale<VFloat> (Dx, fx, fy, fz, dx); Multiply<VFloat> (dx, fx);
      TrilinearScale<VFloat> (Dy, fx, fy, fz, dy); Multiply<VFloat> (dy, fy);
      TrilinearScale<VFloat> (Dz, fx, fy, fz, dz); Multiply<VFloat> (dz, fz);

      /* compare image and field */
      if (verbose) {fprintf (stderr, "Comparing map image and deformation field ...\n"); fflush (stderr);}
      if (!Compatible (in, dx)) exit (5);
      if (!Compatible (in, dy)) exit (5);
      if (!Compatible (in, dz)) exit (5);

      /* deform image */
      if (verbose) {fprintf (stderr, "Deforming map image ...\n"); fflush (stderr);}
      RTTI (in, TrilinearInverseDeform, (in, dx, dy, dz));
      VSetAttrValue (&pos, NULL, VImageRepn, in);

      /* clean-up */
      VDestroyImage (dx);
      VDestroyImage (dy);
      VDestroyImage (dz);
   }


   /* deform functional images */
   if (VAttrExists (&pos))
   {
      /* get data size */
      bands = rows = columns = steps = 0;
      for (rider = pos; VAttrExists (&rider); VNextAttr (&rider))
      {
         /* get image */
         VGetAttrValue (&rider, NULL, VImageRepn, &data);
         if (VPixelRepn (data) != VShortRepn) break;

         /* store image size */
         if (VImageNBands   (data) > steps)   steps   = VImageNBands   (data);
         if (VImageNRows    (data) > rows)    rows    = VImageNRows    (data);
         if (VImageNColumns (data) > columns) columns = VImageNColumns (data);
         bands++;
      }
      in = VCreateImage (bands, rows, columns, VShortRepn);

      /* scale field */
      if (verbose) {fprintf (stderr, "Scaling deformation field ...\n"); fflush (stderr);}
      fx = (float) VImageNColumns (in) / (float) VImageNColumns (Dx);
      fy = (float) VImageNRows    (in) / (float) VImageNRows    (Dy);
      fz = (float) VImageNBands   (in) / (float) VImageNBands   (Dz);
      TrilinearScale<VFloat> (Dx, fx, fy, fz, dx); Multiply<VFloat> (dx, fx);
      TrilinearScale<VFloat> (Dy, fx, fy, fz, dy); Multiply<VFloat> (dy, fy);
      TrilinearScale<VFloat> (Dz, fx, fy, fz, dz); Multiply<VFloat> (dz, fz);

      /* compare image and field */
      if (verbose) {fprintf (stderr, "Comparing functional images and deformation field ...\n"); fflush (stderr);}
      if (!Compatible (in, dx)) exit (6);
      if (!Compatible (in, dy)) exit (6);
      if (!Compatible (in, dz)) exit (6);


      /* expand zero images */
      for (rider = pos, z = 0; z < bands; z++, VNextAttr (&rider))
      {
         VGetAttrValue (&rider, NULL, VImageRepn, &data);
         if (FunctionalZero (data))
         {
            FunctionalResize (data, steps, rows, columns);
            VSetAttrValue (&rider, NULL, VImageRepn, data);
         }
      }

      /* deform images */
      if (verbose) {fprintf (stderr, "Deforming functional images ...\n"); fflush (stderr);}
      for (t = 0; t < steps; t++)
      {
         /* collect data */
         dest = (VShort*) VPixelPtr (in, 0, 0, 0);
         for (rider = pos, z = 0; z < bands; z++, VNextAttr (&rider))
         {
            VGetAttrValue (&rider, NULL, VImageRepn, &data);
            src = (VShort*) VPixelPtr (data, t, 0, 0);
            for (n = 0; n < rows * columns; ++n)
               *(dest++) = *(src++);
         }

         /* deform image */
         if (verbose) {fprintf (stderr, "Timestep %d of %d ...\r", t + 1, steps); fflush (stderr);}
         RTTI (in, TrilinearInverseDeform, (in, dx, dy, dz));

         /* spread data */
         src = (VShort*) VPixelPtr (in, 0, 0, 0);
         for (rider = pos, z = 0; z < bands; z++, VNextAttr (&rider))
         {
            VGetAttrValue (&rider, NULL, VImageRepn, &data);
            dest = (VShort*) VPixelPtr (data, t, 0, 0);
            for (n = 0; n < rows * columns; ++n)
               *(dest++) = *(src++);
         }
      }

      /* collapse zero images */
      for (rider = pos, z = 0; z < bands; z++, VNextAttr (&rider))
      {
         VGetAttrValue (&rider, NULL, VImageRepn, &data);
         if (FunctionalZero (data))
         {
            FunctionalResize (data, 1, 1, 1);
            VSetAttrValue (&rider, NULL, VImageRepn, data);
         }
      }


      /* clean-up */
      VDestroyImage (in);
      VDestroyImage (dx);
      VDestroyImage (dy);
      VDestroyImage (dz);

      /* proceed */
      pos = rider;
   }


   /* check list */
   if (VAttrExists (&pos))
   {
      VError ("Remaining image does not contain valid data");
      exit (7);
   }

   /* Prepend History */
   VPrependHistory(VNumber(options),options,prg_name,&in_history);

   /* write output images */
   if (verbose) {fprintf (stderr, "Writing output image '%s' ...\n", outname); fflush (stderr);}
   success = WriteImages (outname, In, in_history);
   if (!success) exit (8);


   /* clean-up 
      VDestroyAttrList (inhistory);
      VDestroyAttrList (fieldhistory);
      VDestroyAttrList (In);
      VDestroyImage (Dx);
      VDestroyImage (Dy);
      VDestroyImage (Dz); */

   /* exit */
   if (verbose) {fprintf (stderr, "Finished.\n"); fflush (stderr);}
   return 0;

} /* main */
Exemplo n.º 16
0
VBoolean DemonMatch (VImage S, VImage M, VImage& Dx, VImage& Dy, VImage& Dz, VFloat Sigma, VLong Iter, VLong Scale, VBoolean Verbose)
{
   int Factor = 4;   /* scaling factor of iterations at each step */

   int scale;   /* scaling level       */
   int iter;    /* number of iteration */

   VImage *s, *m;                /* source and model pyramid   */
   VImage gsx, gsy, gsz,  gs2;   /* source gradient field      */
   VImage gmx, gmy, gmz,  gm2;   /* model gradient field       */
   VImage dsx, dsy, dsz;         /* source deformation field   */
   VImage dmx, dmy, dmz;         /* model deformation field    */
   VImage vx,  vy,  vz;          /* optical flow field         */
   VImage rx,  ry,  rz;          /* residual deformation field */

   int width = 2 * (2 * (int) floor (Sigma) + 1) + 1;   /* Lohmann, G. "Volumetric Image Analysis", p. 141, Teubner, 1998 */

   VImage tmp;   /* temporal storage */


   /* create multi-scale pyramids */
   s = (VImage*) malloc ((Scale + 1) * sizeof (VImage));
   m = (VImage*) malloc ((Scale + 1) * sizeof (VImage));

   /* compute multi-scale pyramids */
   s[0] = S;
   m[0] = M;
   for (scale = 1; scale <= Scale; scale++, Iter *= Factor)
   {
      RTTI (S, GaussianFilter, (s[scale-1], 0.5, 3, s[scale]));
      RTTI (S, TrilinearScale, (s[scale], 0.5, 0.5, 0.5));

      RTTI (M, GaussianFilter, (m[scale-1], 0.5, 3, m[scale]));
      RTTI (M, TrilinearScale, (m[scale], 0.5, 0.5, 0.5));
   }

   /* create deformation fields */
   dsx = VCreateImage (VImageNBands (s[Scale]), VImageNRows (s[Scale]), VImageNColumns (s[Scale]), VFloatRepn);
   dsy = VCreateImage (VImageNBands (s[Scale]), VImageNRows (s[Scale]), VImageNColumns (s[Scale]), VFloatRepn);
   dsz = VCreateImage (VImageNBands (s[Scale]), VImageNRows (s[Scale]), VImageNColumns (s[Scale]), VFloatRepn);
   dmx = VCreateImage (VImageNBands (m[Scale]), VImageNRows (m[Scale]), VImageNColumns (m[Scale]), VFloatRepn);
   dmy = VCreateImage (VImageNBands (m[Scale]), VImageNRows (m[Scale]), VImageNColumns (m[Scale]), VFloatRepn);
   dmz = VCreateImage (VImageNBands (m[Scale]), VImageNRows (m[Scale]), VImageNColumns (m[Scale]), VFloatRepn);

   /* initialize deformation fields */
   VFillImage (dsx, VAllBands, 0);
   VFillImage (dsy, VAllBands, 0);
   VFillImage (dsz, VAllBands, 0);
   VFillImage (dmx, VAllBands, 0);
   VFillImage (dmy, VAllBands, 0);
   VFillImage (dmz, VAllBands, 0);


   /* multi-scale scheme */
   for (scale = Scale; scale >= 0; scale--, Iter /= Factor)
   {
      /* print status */
      if (Verbose) {fprintf (stderr, "Working hard at scale %d ...                 \n", scale + 1); fflush (stderr);}

      /* compute gradients */
      RTTI (S, Gradient, (s[scale], gsx, gsy, gsz));
      SquaredGradient (gsx, gsy, gsz, gs2);
      RTTI (M, Gradient, (m[scale], gmx, gmy, gmz));
      SquaredGradient (gmx, gmy, gmz, gm2);

      /* diffusion process */
      for (iter = 1; iter <= Iter; iter++)
      {
         /* print status */
         if (Verbose) {fprintf (stderr, "Iteration %d of %d ...\r", iter, Iter); fflush (stderr);}


         /* FORWARD */

         /* interpolate deformed image */
         RTTI (S, TrilinearInverseDeform, (s[scale], dmx, dmy, dmz, tmp));

         /* compute deformation */
         RTTI (M, OpticalFlow, (m[scale], tmp, gmx, gm2, vx));
         RTTI (M, OpticalFlow, (m[scale], tmp, gmy, gm2, vy));
         RTTI (M, OpticalFlow, (m[scale], tmp, gmz, gm2, vz));
         Subtract<VFloat> (dmx, vx);
         Subtract<VFloat> (dmy, vy);
         Subtract<VFloat> (dmz, vz);

         /* clean-up */
         VDestroyImage (tmp);
         VDestroyImage (vx);
         VDestroyImage (vy);
         VDestroyImage (vz);


         /* BACKWARD */

         /* interpolate deformed image */
         RTTI (M, TrilinearInverseDeform, (m[scale], dsx, dsy, dsz, tmp));

         /* compute deformation */
         RTTI (S, OpticalFlow, (s[scale], tmp, gsx, gs2, vx));
         RTTI (S, OpticalFlow, (s[scale], tmp, gsy, gs2, vy));
         RTTI (S, OpticalFlow, (s[scale], tmp, gsz, gs2, vz));
         Subtract<VFloat> (dsx, vx);
         Subtract<VFloat> (dsy, vy);
         Subtract<VFloat> (dsz, vz);

         /* clean-up */
         VDestroyImage (tmp);
         VDestroyImage (vx);
         VDestroyImage (vy);
         VDestroyImage (vz);


         /* BIJECTIVE */

         /* compute residual deformation */
         TrilinearInverseDeform<VFloat> (dsx, dmx, dmy, dmz, rx);
         TrilinearInverseDeform<VFloat> (dsy, dmx, dmy, dmz, ry);
         TrilinearInverseDeform<VFloat> (dsz, dmx, dmy, dmz, rz);
         Add<VFloat> (rx, dmx);
         Add<VFloat> (ry, dmy);
         Add<VFloat> (rz, dmz);
         Multiply<VFloat> (rx, 0.5);
         Multiply<VFloat> (ry, 0.5);
         Multiply<VFloat> (rz, 0.5);

         /* update deformation fields */
         Subtract<VFloat> (dmx, rx);
         Subtract<VFloat> (dmy, ry);
         Subtract<VFloat> (dmz, rz);
         TrilinearInverseDeform<VFloat> (rx, dsx, dsy, dsz);
         TrilinearInverseDeform<VFloat> (ry, dsx, dsy, dsz);
         TrilinearInverseDeform<VFloat> (rz, dsx, dsy, dsz);
         Subtract<VFloat> (dsx, rx);
         Subtract<VFloat> (dsy, ry);
         Subtract<VFloat> (dsz, rz);

         /* clean-up */
         VDestroyImage (rx);
         VDestroyImage (ry);
         VDestroyImage (rz);


         /* regularize deformation fields */
         GaussianFilter<VFloat> (dsx, Sigma, width);
         GaussianFilter<VFloat> (dsy, Sigma, width);
         GaussianFilter<VFloat> (dsz, Sigma, width);
         GaussianFilter<VFloat> (dmx, Sigma, width);
         GaussianFilter<VFloat> (dmy, Sigma, width);
         GaussianFilter<VFloat> (dmz, Sigma, width);
      }

      if (scale > 0)
      {
         /* downscale deformation fields */
         TrilinearScale<VFloat> (dsx, 2.0, 2.0, 2.0); Multiply<VFloat> (dsx, 2.0);
         TrilinearScale<VFloat> (dsy, 2.0, 2.0, 2.0); Multiply<VFloat> (dsy, 2.0);
         TrilinearScale<VFloat> (dsz, 2.0, 2.0, 2.0); Multiply<VFloat> (dsz, 2.0);
         TrilinearScale<VFloat> (dmx, 2.0, 2.0, 2.0); Multiply<VFloat> (dmx, 2.0);
         TrilinearScale<VFloat> (dmy, 2.0, 2.0, 2.0); Multiply<VFloat> (dmy, 2.0);
         TrilinearScale<VFloat> (dmz, 2.0, 2.0, 2.0); Multiply<VFloat> (dmz, 2.0);

         /* clean-up */
         VDestroyImage (s[scale]);
         VDestroyImage (m[scale]);
      }

      /* clean-up */
      VDestroyImage (gsx);
      VDestroyImage (gsy);
      VDestroyImage (gsz);
      VDestroyImage (gs2);
      VDestroyImage (gmx);
      VDestroyImage (gmy);
      VDestroyImage (gmz);
      VDestroyImage (gm2);
   }

   /* return inverse deformation field */
   Dx = dsx;
   Dy = dsy;
   Dz = dsz;

   /* clean-up */
   VDestroyImage (dmx);
   VDestroyImage (dmy);
   VDestroyImage (dmz);
   free (s);
   free (m);

   return TRUE;

} /* DemonMatch */