/** * Requires a minimum of two images. The first image is transformed into the * second by a number of intervening images as specified by "number_images". * * Ruby usage: * - @verbatim ImageList#morph(number_images) @endverbatim * * Notes: * - Sets \@scenes to 0 * * @param self this object * @param nimages the number of images * @return a new image list with the images array set to the morph sequence. */ VALUE ImageList_morph(VALUE self, VALUE nimages) { Image *images, *new_images; ExceptionInfo *exception; long number_images; // Use a signed long so we can test for a negative argument. number_images = NUM2LONG(nimages); if (number_images <= 0) { rb_raise(rb_eArgError, "number of intervening images must be > 0"); } exception = AcquireExceptionInfo(); images = images_from_imagelist(self); new_images = MorphImages(images, (unsigned long)number_images, exception); rm_split(images); rm_check_exception(exception, new_images, DestroyOnError); (void) DestroyExceptionInfo(exception); rm_ensure_result(new_images); return rm_imagelist_from_images(new_images); }
/** * Compute a morph through time by generating appropriate values of t and * repeatedly calling MorphImages(). Saves the image sequence to disk. */ void GenerateMorphFrames(STImage *sourceImage, const std::vector<Feature> &sourceFeatures, STImage *targetImage, const std::vector<Feature> &targetFeatures, float a, float b, float p) { // iterate and generate each required frame for (int i = 0; i <= kFrames - 1; ++i) { std::cout << "Metamorphosizing frame #" << i << "..."; // ********** // CS148 TODO: Compute a t value for the current frame and generate // the morphed image here. // ********** float t = easeFunction(i, kFrames); printf("\n%f\n", t); // float t = (float)i / (kFrames-1); STImage *result = MorphImages(sourceImage, sourceFeatures, targetImage, targetFeatures, t, a, b, p); // generate a file name to save std::ostringstream oss; oss << "frame" << std::setw(3) << std::setfill('0') << i << ".png"; // write and deallocate the morphed image if (result) { result->Save(oss.str()); delete result; } std::cout << " done." << std::endl; } }
/** * Program entry point */ int main(int argc, char* argv[]) { glutInit(&argc, argv); glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB ); glutInitWindowPosition(20, 20); glutInitWindowSize(kWindowWidth, kWindowHeight); glutCreateWindow("Metamorphosis: CS148 Assignment 4"); glutDisplayFunc(DisplayCallback); glutReshapeFunc(ReshapeCallback); glutKeyboardFunc(KeyboardCallback); // // load the configuration from config.txt, or other file as specified // std::string configFile = "config.txt"; if (argc > 1) configFile = argv[1]; char sourceName[64], targetName[64]; char saveName[64], loadName[64]; STImage *sourceImage, *targetImage; parseConfigFile(configFile.c_str(), sourceName, targetName, saveName, loadName, &sourceImage, &targetImage); delete sourceImage; delete targetImage; // // load the features from the saved features file // loadLineEditorFile(loadName, AddFeatureCallback, sourceName, targetName, &sourceImage, &targetImage); // // run the full morphing algorithm before going into the main loop to // display an image // // these weighting parameters (Beier & Nelly 1992) can be changed if desired const float a = 0.5f, b = 2.0f, p = 0.2f; GenerateMorphFrames(sourceImage, gSourceFeatures, targetImage, gTargetFeatures, a, b, p); // // display a test or debug image here if desired // (note: comment this out if you call DisplayImage from elsewhere) // // STImage *result = sourceImage; // use this to test your image blending // STImage *result = BlendImages(sourceImage, targetImage, 0.5f); // use this to test your field morph /* STImage *result = FieldMorph(sourceImage, gSourceFeatures, gTargetFeatures, 0.5f, a, b, p); */ // use this to test your image morphing STImage *result = MorphImages(sourceImage, gSourceFeatures, targetImage, gTargetFeatures, 0.5f, a, b, p); DisplayImage(result); // enter the GLUT main loop glutMainLoop(); return 0; }