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); }
// // 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; }
// // 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; }
// // 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); }
// // 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); }
// // 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; }
// // 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; }
// // 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; }
// // 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; }
// // 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; }
// // 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; }
// // 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; }
// // 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; }
// // 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; }
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 */
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 */