#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if VTK_VERSION_NUMBER >= 89000000000ULL #define VTK890 1 #endif #include #include int main(int argc, char** argv) { if (argc < 2) { cout << "Usage: " << argv[0] << " file.mhd" << endl; return EXIT_FAILURE; } // needed to ensure appropriate OpenGL context is created for VTK rendering. QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat()); QApplication app(argc, argv); QVTKOpenGLNativeWidget widget; vtkNew colors; vtkNew renderWindow; #if VTK890 widget.setRenderWindow(renderWindow); #else widget.SetRenderWindow(renderWindow); #endif widget.resize(600, 600); // The following reader is used to read a series of 2D slices (images) // that compose the volume. The slice dimensions are set, and the // pixel spacing. The data Endianness must also be specified. The reader // uses the FilePrefix in combination with the slice number to construct // filenames using the format FilePrefix.%d. (In this case the FilePrefix // is the root name of the file: quarter.) vtkSmartPointer reader = vtkSmartPointer::New(); reader->SetFileName(argv[1]); // The volume will be displayed by ray-cast alpha compositing. // A ray-cast mapper is needed to do the ray-casting. // vtkSmartPointer volumeMapper = // vtkSmartPointer::New(); vtkSmartPointer volumeMapper = vtkSmartPointer::New(); volumeMapper->SetInputConnection(reader->GetOutputPort()); // The color transfer function maps voxel intensities to colors. // It is modality-specific, and often anatomy-specific as well. // The goal is to one color for flesh (between 500 and 1000) // and another color for bone (1150 and over). vtkSmartPointer volumeColor = vtkSmartPointer::New(); volumeColor->AddRGBPoint(0, 0.0, 0.0, 0.0); volumeColor->AddRGBPoint(500, 1.0, 0.5, 0.3); volumeColor->AddRGBPoint(1000, 1.0, 0.5, 0.3); volumeColor->AddRGBPoint(1150, 1.0, 1.0, 0.9); // The opacity transfer function is used to control the opacity // of different tissue types. vtkSmartPointer volumeScalarOpacity = vtkSmartPointer::New(); volumeScalarOpacity->AddPoint(0, 0.00); volumeScalarOpacity->AddPoint(500, 0.15); volumeScalarOpacity->AddPoint(1000, 0.15); volumeScalarOpacity->AddPoint(1150, 0.85); // The gradient opacity function is used to decrease the opacity // in the "flat" regions of the volume while maintaining the opacity // at the boundaries between tissue types. The gradient is measured // as the amount by which the intensity changes over unit distance. // For most medical data, the unit distance is 1mm. vtkSmartPointer volumeGradientOpacity = vtkSmartPointer::New(); volumeGradientOpacity->AddPoint(0, 0.0); volumeGradientOpacity->AddPoint(90, 0.5); volumeGradientOpacity->AddPoint(100, 1.0); // The VolumeProperty attaches the color and opacity functions to the // volume, and sets other volume properties. The interpolation should // be set to linear to do a high-quality rendering. The ShadeOn option // turns on directional lighting, which will usually enhance the // appearance of the volume and make it look more "3D". However, // the quality of the shading depends on how accurately the gradient // of the volume can be calculated, and for noisy data the gradient // estimation will be very poor. The impact of the shading can be // decreased by increasing the Ambient coefficient while decreasing // the Diffuse and Specular coefficient. To increase the impact // of shading, decrease the Ambient and increase the Diffuse and Specular. vtkSmartPointer volumeProperty = vtkSmartPointer::New(); volumeProperty->SetColor(volumeColor); volumeProperty->SetScalarOpacity(volumeScalarOpacity); volumeProperty->SetGradientOpacity(volumeGradientOpacity); volumeProperty->SetInterpolationTypeToLinear(); volumeProperty->ShadeOn(); volumeProperty->SetAmbient(0.4); volumeProperty->SetDiffuse(0.6); volumeProperty->SetSpecular(0.2); // The vtkVolume is a vtkProp3D (like a vtkActor) and controls the position // and orientation of the volume in world coordinates. vtkSmartPointer volume = vtkSmartPointer::New(); volume->SetMapper(volumeMapper); volume->SetProperty(volumeProperty); vtkNew renderer; renderer->AddActor(volume); renderer->SetBackground(colors->GetColor3d("SteelBlue").GetData()); #if VTK890 widget.renderWindow()->AddRenderer(renderer); widget.renderWindow()->SetWindowName("RenderWindowNoUIFile"); #else widget.GetRenderWindow()->AddRenderer(renderer); widget.GetRenderWindow()->SetWindowName("RenderWindowNoUIFile"); #endif widget.show(); app.exec(); return EXIT_SUCCESS; }