vtkWindowToImageFilter で画像を取得し、vtkPNGWriterで画像を保存する。
以下はタイマーが起動するたびに画面更新し、その結果を連番画像にして保存している。
#pragma warning(disable:4996) #include <iostream> //VTK_MODULE_INITに必要 #include <vtkAutoInit.h> #include <vtkSmartPointer.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> //円筒とその表示に必要 #include <vtkCylinderSource.h> #include <vtkPolyDataMapper.h> #include <vtkActor.h> #include <vtkCubeSource.h> #include <vtkProperty.h> #include <vtkAssembly.h> #include <vtkTransform.h> #pragma comment(lib,"opengl32.lib") #pragma comment(lib,"psapi.lib") #pragma comment(lib,"dbghelp.lib") #pragma comment(lib,"ws2_32.lib") // コールバック関数を使用するのに必要 #include <vtkCallbackCommand.h> // スクリーンショットを取得するのに必要 #include <vtkWindowToImageFilter.h> #include <vtkPNGWriter.h> //必須 VTK_MODULE_INIT(vtkRenderingOpenGL2); VTK_MODULE_INIT(vtkInteractionStyle); /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
void GetClientImage(vtkRenderWindow* renderWindow) { // スクリーンショットを取得 vtkSmartPointer<vtkWindowToImageFilter> windowToImageFilter = vtkSmartPointer<vtkWindowToImageFilter>::New(); windowToImageFilter->SetInput(renderWindow); windowToImageFilter->SetScale(1); // スクリーンショットのサイズ(スケール)を設定 windowToImageFilter->SetInputBufferTypeToRGBA(); // バッファの種類を設定 windowToImageFilter->ReadFrontBufferOff(); // フロントバッファをオフに設定 windowToImageFilter->Update(); static int counter = 0; char filename[256]; sprintf(filename, "C:/test/ss/screenshot_%03d.png", counter++); // スクリーンショットを保存 vtkSmartPointer<vtkPNGWriter> writer = vtkSmartPointer<vtkPNGWriter>::New(); writer->SetFileName(filename); writer->SetInputConnection(windowToImageFilter->GetOutputPort()); writer->Write(); }
// コールバック関数に渡すデータ struct MyData { vtkSmartPointer<vtkAssembly> assembly; }; // タイマーのコールバック関数 void MyTimerCallbackFunction(vtkObject* caller, long unsigned int eventId, void* clientData, void* callData) { MyData* data = static_cast<MyData*>(clientData); static int angle = 0; vtkSmartPointer<vtkTransform> tra = vtkSmartPointer<vtkTransform>::New(); tra->RotateWXYZ(angle+=10, 0, 0, 1); tra->Update(); data->assembly->SetUserTransform(tra); // 画面更新 auto interactor = static_cast<vtkRenderWindowInteractor*>(caller); interactor->Render(); // スクリーンショットを保存 vtkRenderWindow* renderWindow = interactor->GetRenderWindow(); GetClientImage(renderWindow); } /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// vtkSmartPointer<vtkActor> createActor1(); vtkSmartPointer<vtkActor> createActor2(); int main(int /*argc*/, char** /*argv*/) { // アクタを作成 vtkSmartPointer<vtkActor> actor1 = createActor1(); vtkSmartPointer<vtkActor> actor2 = createActor2(); // アクタをまとめてアセンブリを作成 vtkSmartPointer<vtkAssembly> assembly = vtkSmartPointer<vtkAssembly>::New(); assembly->AddPart(actor1); assembly->AddPart(actor2); ////////////////////////////////////// auto renderer = vtkSmartPointer<vtkRenderer>::New(); renderer->ResetCamera(); // アセンブリをレンダラに追加 renderer->AddActor(assembly); ////////////////////////////////////// auto interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New(); auto renderWindow = vtkSmartPointer<vtkRenderWindow>::New(); renderWindow->AddRenderer(renderer); renderWindow->SetInteractor(interactor); renderWindow->Render(); ////////////////////////////////////// ////////////////////////////////////// // タイマーに渡す構造体の作成 MyData callbackData{ assembly }; // タイマー作成 auto timerCallback = vtkSmartPointer<vtkCallbackCommand>::New(); timerCallback->SetCallback(MyTimerCallbackFunction); // コールバック関数を設定 timerCallback->SetClientData(&callbackData); // コールバック関数に渡すデータを設定 interactor->AddObserver(vtkCommand::TimerEvent, timerCallback); // タイマーイベントにコールバック関数を設定 interactor->Initialize(); interactor->CreateRepeatingTimer(100); // 100msごとにタイマーイベントを発生させる ////////////////////////////////////// ////////////////////////////////////// interactor->Start(); //イベントループへ入る return 0; } vtkSmartPointer<vtkActor> createActor1() { // 1つ目の立方体を作成 vtkSmartPointer<vtkCubeSource> cubeSource1 = vtkSmartPointer<vtkCubeSource>::New(); vtkSmartPointer<vtkPolyDataMapper> mapper1 = vtkSmartPointer<vtkPolyDataMapper>::New(); mapper1->SetInputConnection(cubeSource1->GetOutputPort()); vtkSmartPointer<vtkActor> actor1 = vtkSmartPointer<vtkActor>::New(); actor1->SetMapper(mapper1); actor1->GetProperty()->SetColor(1, 0, 0); // 赤色 return actor1; } vtkSmartPointer<vtkActor> createActor2() { // 2つ目の立方体を作成 vtkSmartPointer<vtkCubeSource> cubeSource2 = vtkSmartPointer<vtkCubeSource>::New(); cubeSource2->SetCenter(1.2, 0, 0); // 位置を変更 vtkSmartPointer<vtkPolyDataMapper> mapper2 = vtkSmartPointer<vtkPolyDataMapper>::New(); mapper2->SetInputConnection(cubeSource2->GetOutputPort()); vtkSmartPointer<vtkActor> actor2 = vtkSmartPointer<vtkActor>::New(); actor2->SetMapper(mapper2); actor2->GetProperty()->SetColor(0, 1, 0); // 緑色 return actor2; }
背景色が必要な場合、SetInputBufferTypeToRGBに設定する。renderer->SetBackground で設定した背景色となる。
/* ... */
void GetClientImage(vtkRenderWindow* renderWindow) { // スクリーンショットを取得 vtkSmartPointer<vtkWindowToImageFilter> windowToImageFilter = vtkSmartPointer<vtkWindowToImageFilter>::New(); windowToImageFilter->SetInput(renderWindow); windowToImageFilter->SetScale(1); // スクリーンショットのサイズ(スケール)を設定 windowToImageFilter->SetInputBufferTypeToRGB(); // バッファの種類をRGBに設定 windowToImageFilter->ReadFrontBufferOff(); // フロントバッファをオフに設定 windowToImageFilter->Update(); static int counter = 0; char filename[256]; sprintf(filename, "C:/test/ss/screenshot_%03d.png", counter++); // スクリーンショットを保存 vtkSmartPointer<vtkPNGWriter> writer = vtkSmartPointer<vtkPNGWriter>::New(); writer->SetFileName(filename); writer->SetInputConnection(windowToImageFilter->GetOutputPort()); writer->Write(); }
/* ... */ int main(int /*argc*/, char** /*argv*/) { /* ... */ ////////////////////////////////////// auto renderer = vtkSmartPointer<vtkRenderer>::New();
/* ... */ // 背景色を設定 windowToImageFilter->SetInputBufferTypeToRGB();にすれば背景がこの色になる renderer->SetBackground(0.0, 0.0, 1.0); ////////////////////////////////////// auto interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New(); /* ... */ interactor->Start(); //イベントループへ入る return 0; } /* ... */
ImageMagickで、以下のコマンドでanimation gif 化できる。
背景が透明な場合、先に以下の方法で背景を黒に変換してからmagick convertする。