#include "vtkKWAnimationWidget.h" #include "vtkObjectFactory.h" #include "vtkKWApplication.h" #include "vtkCamera.h" #include "vtkImageData.h" #include "vtkKWComboBoxWithLabel.h" #include "vtkKWComboBox.h" #include "vtkKWIcon.h" #include "vtkKWInternationalization.h" #include "vtkKWLabel.h" #include "vtkKWLabelWithLabel.h" #include "vtkKWLoadSaveDialog.h" #include "vtkKWMenu.h" #include "vtkKWMessageDialog.h" #include "vtkKWProgressGauge.h" #include "vtkKWPushButton.h" #include "vtkKWPushButtonSet.h" #include "vtkRenderer.h" #include "vtkKWScaleWithEntry.h" #include "vtkKWScaleWithEntrySet.h" #include "vtkRenderWindow.h" #include "vtkKWRenderWidget.h" #include "vtkWindowToImageFilter.h" #include "vtkKWWindowBase.h" #include "vtkToolkits.h" #include "vtkImageWriter.h" #include "vtkJPEGWriter.h" #include "vtkTIFFWriter.h" #include "vtkGenericMovieWriter.h" #include #include #include #include #ifdef VTK_USE_VIDEO_FOR_WINDOWS #include "vtkKWWidgetsBuildConfigure.h" #include "vtkAVIWriter.h" #else #ifdef VTK_USE_FFMPEG_ENCODER #include "vtkFFMPEGWriter.h" #endif #endif #ifdef VTK_USE_MPEG2_ENCODER #include "vtkMPEG2Writer.h" #endif #include #include //---------------------------------------------------------------------------- #define VTK_VV_ANIMATION_BUTTON_PREVIEW_ID 0 #define VTK_VV_ANIMATION_BUTTON_CREATE_ID 1 #define VTK_VV_ANIMATION_BUTTON_CANCEL_ID 2 #define VTK_VV_ANIMATION_SCALE_NB_OF_FRAMES_ID 0 #define VTK_VV_ANIMATION_SCALE_SLICE_START_ID 1 #define VTK_VV_ANIMATION_SCALE_SLICE_END_ID 2 #define VTK_VV_ANIMATION_SCALE_AZIMUTH_ID 3 #define VTK_VV_ANIMATION_SCALE_ELEVATION_ID 4 #define VTK_VV_ANIMATION_SCALE_ROLL_ID 5 #define VTK_VV_ANIMATION_SCALE_ZOOM_ID 6 #define VTK_VV_ANIMATION_SCALE_NB_FRAMES 500 //---------------------------------------------------------------------------- vtkStandardNewMacro( vtkKWAnimationWidget ); vtkCxxRevisionMacro(vtkKWAnimationWidget, "$Revision: 1.7 $"); //---------------------------------------------------------------------------- vtkKWAnimationWidget::vtkKWAnimationWidget() { this->SequenceUpdateCommand = NULL; this->SequenceRange[0] = 0; this->SequenceRange[1] = 0; this->NumFrames = 0; this->ParentObject = NULL; } //---------------------------------------------------------------------------- vtkKWAnimationWidget::~vtkKWAnimationWidget() { if (this->SequenceUpdateCommand) { delete [] this->SequenceUpdateCommand; this->SequenceUpdateCommand = NULL; } } //---------------------------------------------------------------------------- void vtkKWAnimationWidget::CreateWidget() { if (this->IsCreated()) { vtkErrorMacro("vtkKWAnimationWidget already created."); return; } // Call the superclass to create the whole widget this->Superclass::CreateWidget(); this->HelpLabel->GetWidget()->SetText( k_("No text thank's")); vtkKWScaleWithEntry* scale = this->Parameters->GetWidget(VTK_VV_ANIMATION_SCALE_NB_OF_FRAMES_ID); if (scale) this->Script("pack forget %s", scale->GetWidgetName()); } //---------------------------------------------------------------------------- void vtkKWAnimationWidget::SetAnimationType(int val) { if (val < vtkKWAnimationWidget::AnimationTypeCamera) { val = vtkKWAnimationWidget::AnimationTypeCamera; } if (val > vtkKWAnimationWidget::AnimationTypeSequence) { val = vtkKWAnimationWidget::AnimationTypeSequence; } if (this->AnimationType == val) { return; } this->AnimationType = val; this->Modified(); this->Update(); } //---------------------------------------------------------------------------- void vtkKWAnimationWidget::Update() { this->Superclass::Update(); if (this->AnimationButtonSet && vtkKWAnimationWidget::AnimationTypeSequence) { this->AnimationButtonSet->SetEnabled(1); } } //---------------------------------------------------------------------------- void vtkKWAnimationWidget::SetSequenceUpdateCommand( vtkObject *object, const char *method) { this->SetObjectMethodCommand( &this->SequenceUpdateCommand, object, method); this->Update(); } //---------------------------------------------------------------------------- void vtkKWAnimationWidget::InvokeSequenceUpdateCommand(double t) { if (this->SequenceUpdateCommand && *this->SequenceUpdateCommand && this->GetApplication()) { this->Script("%s %f", this->SequenceUpdateCommand, t); } } //---------------------------------------------------------------------------- void vtkKWAnimationWidget::PreviewAnimationCallback() { if (this->ParentObject && this->ParentObject->GetCurrentPage()) { this->SetRenderWidget(this->ParentObject->GetCurrentPage()->GetActiveRenderWidget()); } if (!this->IsCreated() || !this->RenderWidget) { return; } if (!this->IsCreated()) { return; } // Disable buttons but preview this->DisableButtonsButCancel(); // Run preview if (this->AnimationType == vtkKWAnimationWidget::AnimationTypeCamera) { this->PreviewCameraAnimation(); } else if (this->AnimationType == vtkKWAnimationWidget::AnimationTypeSlice) { this->PreviewSliceAnimation(); } else if (this->AnimationType == vtkKWAnimationWidget::AnimationTypeSequence) { this->PreviewSequenceAnimation(); } // Reenable buttons this->EnableButtonsButCancel(); } //---------------------------------------------------------------------------- void vtkKWAnimationWidget::CreateAnimationCallback() { if (this->ParentObject && this->ParentObject->GetCurrentPage()) { this->SetRenderWidget(this->ParentObject->GetCurrentPage()->GetActiveRenderWidget()); } if (!this->IsCreated() || !this->RenderWidget || !this->NumFrames) { return; } int res; vtksys_stl::string filename; vtksys_stl::string filetypes("{{JPEG} {.jpg}} {{TIFF} {.tif}}"); vtksys_stl::string defaultExtension(".jpg"); vtkKWLoadSaveDialog *save_dialog = vtkKWLoadSaveDialog::New(); save_dialog->SetParent(this->GetParentTopLevel()); save_dialog->RetrieveLastPathFromRegistry("SavePath"); save_dialog->Create(); save_dialog->SetTitle( ks_("Animation|Save Animation Dialog|Title|Save Animation")); save_dialog->SaveDialogOn(); #if defined(VTK_USE_MPEG2_ENCODER) filetypes = vtksys_stl::string("{{MPEG2} {.mpg}} ") + filetypes; defaultExtension = ".mpg"; #endif #if defined(VTK_USE_VIDEO_FOR_WINDOWS) || defined(VTK_USE_FFMPEG_ENCODER) filetypes = vtksys_stl::string("{{AVI} {.avi}} ") + filetypes; defaultExtension = ".avi"; #endif save_dialog->SetFileTypes(filetypes.c_str()); save_dialog->SetDefaultExtension(defaultExtension.c_str()); res = save_dialog->Invoke(); if (res) { filename = save_dialog->GetFileName(); save_dialog->SaveLastPathToRegistry("SavePath"); } save_dialog->Delete(); if (!res) { return; } // Split into root and extension. vtksys_stl::string ext = vtksys::SystemTools::GetFilenameLastExtension(filename.c_str()); vtksys_stl::string filename_path = vtksys::SystemTools::GetFilenamePath(filename.c_str()); vtksys_stl::string file_root(filename_path); file_root += '/'; file_root += vtksys::SystemTools::GetFilenameWithoutLastExtension(filename.c_str()); if (!ext.size()) { vtkErrorMacro(<< "Could not find extension in " << filename.c_str()); return; } int orig_width = this->RenderWidget->GetRenderWindow()->GetSize()[0]; int orig_height = this->RenderWidget->GetRenderWindow()->GetSize()[1]; int width, height; // Is this a video format int is_mpeg = (!strcmp(ext.c_str(), ".mpg") || !strcmp(ext.c_str(), ".mpeg") || !strcmp(ext.c_str(), ".MPG") || !strcmp(ext.c_str(), ".MPEG") || !strcmp(ext.c_str(), ".MP2") || !strcmp(ext.c_str(), ".mp2")); int is_avi = (!strcmp(ext.c_str(), ".avi") || !strcmp(ext.c_str(), ".AVI")); // Prompt for the size of the movie vtkKWMessageDialog *msg_dialog = vtkKWMessageDialog::New(); msg_dialog->SetMasterWindow(this->GetParentTopLevel()); msg_dialog->SetTitle( ks_("Animation|Create Animation Dialog|Title|Frame Size")); msg_dialog->SetStyleToOkCancel(); msg_dialog->Create(); vtksys_stl::string msg( k_("Specify the width and height of each frame to be saved from this " "animation.")); if (is_mpeg) { msg += " "; msg += k_("The width must be a multiple of 32 and the height a " "multiple of 8. Each will be resized to the next smallest multiple " "if it does not meet this criterion. The maximum size allowed is " "1920 by 1080."); } else if (is_avi) { msg += " "; msg += k_("Each dimension must be a multiple of 4. Each will be " "resized to the next smallest multiple of 4 if it does not meet this " "criterion."); } msg_dialog->SetText(msg.c_str()); vtkKWFrame *frame = vtkKWFrame::New(); frame->SetParent(msg_dialog->GetTopFrame()); frame->Create(); char buffer[1024]; int nb_scanned = 0, key_w, key_h; vtkKWApplication *app = this->GetApplication(); if (app->HasRegistryValue(2, "RunTime", "AnimationSize") && app->GetRegistryValue(2, "RunTime", "AnimationSize", buffer)) { nb_scanned = sscanf(buffer, "%dx%d", &key_w, &key_h); } vtkKWComboBox *combobox; vtkKWComboBoxWithLabel *width_combobox = vtkKWComboBoxWithLabel::New(); width_combobox->SetParent(frame); width_combobox->Create(); width_combobox->SetLabelText( ks_("Animation|Create Animation Dialog|Frame Size|Width:")); combobox = width_combobox->GetWidget(); combobox->SetValueAsInt(orig_width); if (nb_scanned == 2) { combobox->AddValueAsInt(key_w); } combobox->AddValueAsInt(640); combobox->AddValueAsInt(800); combobox->AddValueAsInt(1024); combobox->AddValueAsInt(1280); combobox->AddValueAsInt(1680); vtkKWComboBoxWithLabel *height_combobox = vtkKWComboBoxWithLabel::New(); height_combobox->SetParent(frame); height_combobox->Create(); height_combobox->SetLabelText( ks_("Animation|Create Animation Dialog|Frame Size|Height:")); combobox = height_combobox->GetWidget(); combobox->SetValueAsInt(orig_height); if (nb_scanned == 2) { combobox->AddValueAsInt(key_h); } combobox->AddValueAsInt(600); combobox->AddValueAsInt(768); combobox->AddValueAsInt(800); combobox->AddValueAsInt(1024); combobox->AddValueAsInt(1050); this->Script("pack %s %s -side left -fill both -expand t", width_combobox->GetWidgetName(), height_combobox->GetWidgetName()); this->Script("pack %s -side top -pady 5", frame->GetWidgetName()); res = msg_dialog->Invoke(); width = width_combobox->GetWidget()->GetValueAsInt(); height = height_combobox->GetWidget()->GetValueAsInt(); width_combobox->Delete(); height_combobox->Delete(); frame->Delete(); msg_dialog->Delete(); if (!res) { return; } app->SetRegistryValue( 2, "RunTime", "AnimationSize", "%dx%d", width, height); // Fix the size if (is_mpeg) { if ((width % 32) > 0) { width -= width % 32; } if ((height % 8) > 0) { height -= height % 8; } if (width > 1920) { width = 1920; } if (height > 1080) { height = 1080; } } else if (is_avi) { if ((width % 4) > 0) { width -= width % 4; } if ((height % 4) > 0) { height -= height % 4; } } // Disable buttons but preview this->DisableButtonsButCancel(); // Create the animation if (this->AnimationType == vtkKWAnimationWidget::AnimationTypeCamera) { this->CreateCameraAnimation(file_root.c_str(), ext.c_str(), width, height); } else if (this->AnimationType == vtkKWAnimationWidget::AnimationTypeSlice) { this->CreateSliceAnimation(file_root.c_str(), ext.c_str(), width, height); } else if (this->AnimationType == vtkKWAnimationWidget::AnimationTypeSequence) { this->CreateSequenceAnimation(file_root.c_str(), ext.c_str(), width, height); } // Reenable buttons this->EnableButtonsButCancel(); } //---------------------------------------------------------------------------- void vtkKWAnimationWidget::PreviewSequenceAnimation() { this->PerformSequenceAnimation(NULL, NULL, -1, -1); } //---------------------------------------------------------------------------- void vtkKWAnimationWidget::CreateSequenceAnimation(const char *file_root, const char *ext, int width, int height) { this->PerformSequenceAnimation(file_root, ext, width, height); } //---------------------------------------------------------------------------- void vtkKWAnimationWidget::PerformSequenceAnimation(const char *file_root, const char *ext, int width, int height) { if (!this->IsCreated() || !this->RenderWidget) { return; } std::cout<<"performing"<GetParentTopLevel()); int old_render_mode = 0, old_size[2], status; vtkWindowToImageFilter *w2i = NULL; vtkGenericMovieWriter *movie_writer = NULL; vtkImageWriter *image_writer = 0; char *image_filename = 0; if (previewing) { old_render_mode = this->RenderWidget->GetRenderMode(); this->RenderWidget->SetRenderModeToInteractive(); if (win) { win->SetStatusText(ks_("Progress|Previewing animation")); } status = vtkKWAnimationWidget::AnimationPreviewing; } else { if (ext) { if (!strcmp(ext, ".jpg")) { image_writer = vtkJPEGWriter::New(); } #ifdef VTK_USE_MPEG2_ENCODER else if (!strcmp(ext, ".mpg")) { movie_writer = vtkMPEG2Writer::New(); } #endif #ifdef VTK_USE_VIDEO_FOR_WINDOWS else if (!strcmp(ext, ".avi")) { movie_writer = vtkAVIWriter::New(); vtkAVIWriter* aviwriter = vtkAVIWriter::SafeDownCast(movie_writer); double res = (this->SequenceRange[1]-this->SequenceRange[0])/(double)this->NumFrames; if (res > 0.0) { int rate = (int)(1.0/res); // only in VTK-CVS version : //aviwriter->SetRate(rate); } } #else #ifdef VTK_USE_FFMPEG_ENCODER else if (!strcmp(ext, ".avi")) { movie_writer = vtkFFMPEGWriter::New(); } #endif #endif else if (!strcmp(ext, ".tif")) { image_writer = vtkTIFFWriter::New(); } } this->RenderWidget->OffScreenRenderingOn(); old_size[0] = this->RenderWidget->GetRenderWindow()->GetSize()[0]; old_size[1] = this->RenderWidget->GetRenderWindow()->GetSize()[1]; if (width > 0) { this->RenderWidget->GetRenderWindow()->SetSize(width, height); } if (win) { win->SetStatusText( ks_("Progress|Generating animation (rendering to memory; please wait)")); } status = vtkKWAnimationWidget::AnimationCreating; w2i = vtkWindowToImageFilter::New(); w2i->SetInput(this->RenderWidget->GetRenderWindow()); if(movie_writer) { movie_writer->SetInput(w2i->GetOutput()); vtksys_stl::string filename(file_root); filename += ext; movie_writer->SetFileName(filename.c_str()); movie_writer->Start(); } else if(image_writer) { image_writer->SetInput(w2i->GetOutput()); image_filename = new char[strlen(file_root) + strlen(ext) + 25]; } } this->AnimationStatus = status; // Save the camera state double pos[3], view_up[3], angle, parallel_scale; vtkCamera *cam = this->RenderWidget->GetRenderer()->GetActiveCamera(); cam->GetPosition(pos); cam->GetViewUp(view_up); angle = cam->GetViewAngle(); parallel_scale = cam->GetParallelScale(); double firsttime = this->SequenceRange[0]; // Get the animation parameters vtkKWScaleWithEntry *scale; scale = this->Parameters->GetWidget(VTK_VV_ANIMATION_SCALE_NB_OF_FRAMES_ID); int num_frames = this->NumFrames; double resolution = (this->SequenceRange[1]-this->SequenceRange[0])/(double)num_frames; scale = this->Parameters->GetWidget(VTK_VV_ANIMATION_SCALE_AZIMUTH_ID); double azimuth = scale->GetValue() / (double)num_frames; scale = this->Parameters->GetWidget(VTK_VV_ANIMATION_SCALE_ELEVATION_ID); double elev = scale->GetValue() / (double)num_frames; scale = this->Parameters->GetWidget(VTK_VV_ANIMATION_SCALE_ROLL_ID); double roll = scale->GetValue() / (double)num_frames; scale = this->Parameters->GetWidget(VTK_VV_ANIMATION_SCALE_ZOOM_ID); double zoom = pow(scale->GetValue(), (double)1.0 / (double)num_frames); // Perform the animation if (!movie_writer || movie_writer->GetError() == 0) { for (int i = 0; i < num_frames && this->AnimationStatus != vtkKWAnimationWidget::AnimationCanceled; i++) { if (win) { win->GetProgressGauge()->SetValue((int)(100.0 * i / num_frames)); } // process pending events... necessary for being able to interrupt this->GetApplication()->ProcessPendingEvents(); double t_time = firsttime + (double)(i)*resolution; this->InvokeSequenceUpdateCommand (t_time); this->RenderWidget->Render(); if (w2i) { w2i->Modified(); if (movie_writer) { movie_writer->Write(); } else if(image_writer) { sprintf(image_filename, "%s.%04d%s", file_root, i, ext); image_writer->SetFileName(image_filename); image_writer->Write(); } } } if (movie_writer) { movie_writer->End(); movie_writer->SetInput(0); } } // Update status if (win) { vtksys_stl::string end_msg(win->GetStatusText()); end_msg += " -- "; if (this->AnimationStatus != status) { end_msg += ks_("Progress|Canceled"); } else { end_msg += ks_("Progress|Done"); } win->SetStatusText(end_msg.c_str()); win->GetProgressGauge()->SetValue(0); } this->AnimationStatus = vtkKWAnimationWidget::AnimationStopped; // Restore camera state cam->SetPosition(pos); cam->SetViewUp(view_up); cam->SetViewAngle(angle); cam->SetParallelScale(parallel_scale); // Switch back to the previous render mode / widget state if (previewing) { this->RenderWidget->SetRenderMode(old_render_mode); } else { this->RenderWidget->GetRenderWindow()->SetSize(old_size); this->RenderWidget->OffScreenRenderingOff(); } this->InvokeCameraPostAnimationCommand(); this->RenderWidget->Render(); // Cleanup if (w2i) { w2i->Delete(); } if (movie_writer) { movie_writer->Delete(); } if (image_writer) { delete [] image_filename; image_writer->Delete(); } }