/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2011 Mathieu Malaterre All rights reserved. See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ /* * TODO: vtkPlaybackWidget would be cool for 4D images... * should I do it here, or a specified 4Dviewer application that will reexecute the reader (TIME* * stuff in vtk) */ #include "vtkGDCMImageReader.h" #include "vtkVersion.h" #include "vtkErrorCode.h" #include "vtkMedicalImageProperties.h" #include "vtkXMLImageDataWriter.h" #include "vtkInteractorStyleImage.h" #include "vtkCornerAnnotation.h" #include "vtkPNGWriter.h" #include "vtkImageShiftScale.h" #include "vtkOutlineFilter.h" #include "vtkMath.h" #include "vtkPolyDataMapper2D.h" #include "vtkImageReslice.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderWindow.h" #include "vtkPointData.h" #include "vtkImageMapToColors.h" #include "vtkLookupTable.h" #include "vtkActor2D.h" #include "vtkImageMapToWindowLevelColors.h" #include "vtkImageActor.h" #include "vtkWindowToImageFilter.h" #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) #include "vtkImageMapToColors16.h" #include "vtkBalloonWidget.h" #include "vtkBalloonRepresentation.h" #include "vtkLogoWidget.h" #include "vtkLogoRepresentation.h" #include "vtkAngleWidget.h" #include "vtkAngleRepresentation2D.h" #include "vtkBiDimensionalWidget.h" #include "vtkBiDimensionalRepresentation2D.h" #include "vtkDistanceWidget.h" #include "vtkContourWidget.h" #include "vtkOrientedGlyphContourRepresentation.h" #include "vtkPointHandleRepresentation2D.h" #include "vtkDistanceRepresentation2D.h" #include "vtkLegendScaleActor.h" #include "vtkProperty2D.h" #else class vtkLogoWidget; class vtkBiDimensionalWidget; class vtkDistanceWidget; class vtkLogoRepresentation; class vtkContourWidget; class vtkAngleWidget; #endif #if VTK_MAJOR_VERSION >= 5 #include "vtkImageYBRToRGB.h" #include "vtkImageColorViewer.h" #else #include "vtkImageViewer2.h" #endif #include "vtkImageData.h" #include "vtkCommand.h" #include "vtkRenderer.h" #include "vtkStringArray.h" #include "vtkDebugLeaks.h" #include "vtkWorldPointPicker.h" #include "vtkMultiThreader.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmDirectory.h" #include "gdcmImageHelper.h" #include "gdcmReader.h" #include "gdcmTrace.h" #include "gdcmVersion.h" #include #include #ifndef vtkFloatingPointType #define vtkFloatingPointType double #endif #if VTK_MAJOR_VERSION >= 5 #else class vtkImageColorViewer : public vtkImageViewer2 { public: vtkTypeMacro(vtkImageColorViewer,vtkImageViewer2); static vtkImageColorViewer *New() { #ifdef VTK_DEBUG_LEAKS vtkDebugLeaks::ConstructClass("vtkImageColorViewer"); #endif return new vtkImageColorViewer; } vtkImageColorViewer() { OverlayImageActor = vtkImageActor::New(); } ~vtkImageColorViewer() { OverlayImageActor->Delete(); } double GetOverlayVisibility() { return 0; } void SetOverlayVisibility(double vis) {} void AddInput(vtkImageData * input) { vtkRenderWindow *renwin = this->GetRenderWindow (); renwin->SetNumberOfLayers(2); vtkRenderer *Renderer = vtkRenderer::New(); Renderer->SetLayer(0); //OverlayImageActor->SetOpacity(0.5); //OverlayImageActor->GetProperty()->SetOpacity(1.0); vtkImageMapToWindowLevelColors *WindowLevel = vtkImageMapToWindowLevelColors::New(); WindowLevel->SetInput(input); OverlayImageActor->SetInput(WindowLevel->GetOutput()); Renderer->AddProp(OverlayImageActor); OverlayImageActor->SetVisibility(1); renwin->AddRenderer(Renderer); Renderer->Delete(); WindowLevel->Delete(); } private: vtkImageActor *OverlayImageActor; }; //vtkCxxRevisionMacro(vtkImageColorViewer, "$Revision: 1.30 $") vtkInstantiatorNewMacro(vtkImageColorViewer) #endif //---------------------------------------------------------------------------- // Callback for the interaction template class vtkGDCMObserver : public vtkCommand { public: static vtkGDCMObserver *New() { return new vtkGDCMObserver; } vtkGDCMObserver() { ImageViewer = NULL; IconWidget = NULL; DistanceWidget = NULL; BiDimWidget = NULL; AngleWidget = NULL; ContourWidget = NULL; picker = vtkWorldPointPicker::New(); } ~vtkGDCMObserver() { picker->Delete(); } virtual void Execute(vtkObject *caller, unsigned long event, void* /*calldata*/) { if ( this->ImageViewer ) { vtkRenderWindowInteractor * rwi = vtkRenderWindowInteractor::SafeDownCast( caller ); if ( event == vtkCommand::CharEvent ) { char keycode = 0; if( rwi ) keycode = rwi->GetKeyCode(); // 'o' is a special key for overlay visibility if ( keycode == 'o' ) { ImageViewer->SetOverlayVisibility( 1 - ImageViewer->GetOverlayVisibility() ); ImageViewer->Render(); //std::cerr << ImageViewer->GetOverlayVisibility() << std::endl; } else if ( keycode == 's' ) { vtkPNGWriter * writer = vtkPNGWriter::New(); vtkWindowToImageFilter * w2i = vtkWindowToImageFilter::New(); w2i->SetInput( rwi->GetRenderWindow() ); #if VTK_MAJOR_VERSION >= 6 writer->SetInputConnection( w2i->GetOutputPort() ); #else writer->SetInput( w2i->GetOutput() ); #endif writer->SetFileName( "snapshot.png" ); writer->Write(); writer->Delete(); w2i->Delete(); //std::cerr << "Screenshort saved to snapshot.png" << std::endl; } #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) else if ( keycode == 'l' ) { IconWidget->Off(); } else if ( keycode == 'a' ) { AngleWidget->On(); } else if ( keycode == 'b' ) { BiDimWidget->On(); } else if ( keycode == 'c' ) { ContourWidget->On(); } else if ( keycode == 'd' ) { DistanceWidget->On(); } else if ( keycode == 'p' ) { } #endif else { #if VTK_MAJOR_VERSION >= 5 || (VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5) int max = ImageViewer->GetSliceMax(); int slice = (ImageViewer->GetSlice() + 1) % ++max; ImageViewer->SetSlice( slice ); ImageViewer->GetRenderer()->ResetCamera(); #else int max = ImageViewer->GetWholeZMax(); int slice = (ImageViewer->GetZSlice() + 1 ) % ++max; ImageViewer->SetZSlice( slice ); ImageViewer->GetRenderer()->ResetCameraClippingRange(); #endif ImageViewer->Render(); } } else if ( event == vtkCommand::EndPickEvent ) { //std::cerr << "EndPickEvent" << std::endl; int *pick = rwi->GetEventPosition(); vtkRenderer *ren1 = ImageViewer->GetRenderer(); picker->Pick((double)pick[0], (double)pick[1], 0.0, ren1); vtkFloatingPointType *pos = picker->GetPickPosition (); std::cout << pos[0] << "," << pos[1] << "," << pos[2] << std::endl; } else { std::cerr << "Unhandled even:" << event << std::endl; } } } TViewer *ImageViewer; vtkWorldPointPicker *picker; vtkLogoWidget *IconWidget; vtkDistanceWidget *DistanceWidget; vtkAngleWidget *AngleWidget; vtkBiDimensionalWidget *BiDimWidget; vtkContourWidget *ContourWidget; }; int verbose; #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) class vtkBalloonCallback : public vtkCommand { public: static vtkBalloonCallback *New() { return new vtkBalloonCallback; } virtual void Execute(vtkObject *caller, unsigned long, void*) { vtkBalloonWidget *balloonWidget = reinterpret_cast(caller); if ( balloonWidget->GetCurrentProp() != NULL ) { cout << "Prop selected\n"; } } }; #endif void FillCornerFromMedProp( vtkCornerAnnotation *ca, vtkMedicalImageProperties *medprop ) { std::string bottomleft = "S: "; if( medprop->GetSeriesNumber() ) bottomleft += medprop->GetSeriesNumber(); bottomleft += "\nI: "; if( medprop->GetImageNumber() ) bottomleft += medprop->GetImageNumber(); bottomleft += "\n"; ca->SetText(0, bottomleft.c_str()); if( medprop->GetStationName() ) { const std::string bottomright = medprop->GetStationName(); ca->SetText(1, bottomright.c_str()); } std::string topleft; if( medprop->GetInstitutionName() ) topleft += medprop->GetInstitutionName(); topleft += "\n"; if( medprop->GetPatientName() ) topleft += medprop->GetPatientName(); ca->SetText(2, topleft.c_str()); std::string topright; if( medprop->GetStudyDate() ) topright += medprop->GetStudyDate(); topright += "\n"; if( medprop->GetAcquisitionTime() ) topright += medprop->GetAcquisitionTime(); ca->SetText(3, topright.c_str()); } // A feature in VS6 make it painfull to write template code // that do not contain the template parameter in the function // signature. Thus always pass parameter in the function: template void ExecuteViewer(TViewer *viewer, vtkStringArray *filenames) { vtkGDCMImageReader *reader = vtkGDCMImageReader::New(); if( filenames->GetSize() == 1 ) // Backward compatible... { reader->SetFileName( filenames->GetValue(0) ); } else { reader->SetFileNames( filenames ); } vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); // For a single medical image, it would be more efficient to use // 0028|1050 [DS] [Window Center] // 0028|1051 [DS] [Window Width] // but gdcmviewer doesn't know about them :-( //reader->FileLowerLeftOn(); reader->Update(); if( reader->GetErrorCode() ) { std::cerr << "There was an error: " << vtkErrorCode:: GetStringFromErrorCode(reader->GetErrorCode()) << std::endl; return; } //reader->Print( cout ); if( verbose ) reader->GetOutput()->Print( cout ); //reader->GetOutput(1)->Print( cout ); vtkFloatingPointType range[2]; reader->GetOutput()->GetScalarRange(range); #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) viewer->SetInputConnection ( reader->GetOutputPort(0) ); // Technically we could just simple always call AddInputConnection on the overlay // but there is something wrong going on, when overlay visibility is set to 0 at startup // thus we need to make it visible by default which is annoying, so activate only // if overlays are found: if( reader->GetNumberOfOverlays() ) { // Add first overlay: // WARNING: gdcmviewer2 only ! viewer->AddInputConnection ( reader->GetOverlayPort(0) ); } // TODO: Icon can be added using the vtkLogoWidget #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) vtkPointHandleRepresentation2D *handle = vtkPointHandleRepresentation2D::New(); handle->GetProperty()->SetColor(1,0,0); vtkDistanceRepresentation2D *drep = vtkDistanceRepresentation2D::New(); drep->SetHandleRepresentation(handle); handle->Delete(); vtkDistanceWidget *dwidget = vtkDistanceWidget::New(); dwidget->SetInteractor(iren); dwidget->CreateDefaultRepresentation(); dwidget->SetRepresentation(drep); drep->Delete(); vtkAngleRepresentation2D *anglerep = vtkAngleRepresentation2D::New(); vtkAngleWidget *anglewidget = vtkAngleWidget::New(); anglewidget->SetInteractor(iren); anglewidget->SetRepresentation(anglerep); anglerep->Delete(); vtkBiDimensionalRepresentation2D *brep = vtkBiDimensionalRepresentation2D::New(); vtkBiDimensionalWidget *bwidget = vtkBiDimensionalWidget::New(); bwidget->SetInteractor(iren); bwidget->SetRepresentation(brep); brep->Delete(); vtkOrientedGlyphContourRepresentation *contourRep = vtkOrientedGlyphContourRepresentation::New(); vtkContourWidget *contourWidget = vtkContourWidget::New(); contourWidget->SetInteractor(iren); contourWidget->SetRepresentation(contourRep); contourRep->Delete(); vtkBalloonRepresentation *balloonrep = vtkBalloonRepresentation::New(); balloonrep->SetBalloonLayoutToImageRight(); vtkBalloonWidget *balloonwidget = vtkBalloonWidget::New(); balloonwidget->SetInteractor(iren); balloonwidget->SetRepresentation(balloonrep); balloonrep->Delete(); //balloonwidget->AddBalloon(viewer->GetImageActor(),"This is a DICOM image",NULL); vtkBalloonCallback *cbk = vtkBalloonCallback::New(); balloonwidget->AddObserver(vtkCommand::WidgetActivateEvent,cbk); vtkLogoWidget * iconwidget = 0; if( reader->GetNumberOfIconImages() ) { vtkLogoRepresentation *rep = vtkLogoRepresentation::New(); rep->SetImage(reader->GetIconImage()); //reader->GetIconImage()->Print( std::cout ); if( reader->GetIconImage()->GetPointData()->GetScalars() && reader->GetIconImage()->GetPointData()->GetScalars()->GetLookupTable() ) { vtkLookupTable *lut = reader->GetIconImage()->GetPointData()->GetScalars()->GetLookupTable(); vtkImageMapToColors *map = vtkImageMapToColors::New (); #if (VTK_MAJOR_VERSION >= 6) map->SetInputData(reader->GetIconImage()); #else map->SetInput (reader->GetIconImage()); #endif map->SetLookupTable ( lut ); //FIXME there is no way to know the type of LUT the icon is using: //if( reader->GetImageFormat() == VTK_LOOKUP_TABLE ) { map->SetOutputFormatToRGB(); } //else if( reader->GetImageFormat() == VTK_INVERSE_LUMINANCE ) // { // map->SetOutputFormatToLuminance(); // } map->Update(); //map->GetOutput()->GetScalarRange(range); //viewer->SetInput( map->GetOutput() ); //map->GetOutput()->Print( std::cout ); rep->SetImage( map->GetOutput() ); map->Delete(); //vtkPNGWriter *iconw = vtkPNGWriter::New(); //iconw->SetInput( map->GetOutput() ); //iconw->SetFileName( "/tmp/icon.png" ); //iconw->Write(); //iconw->Delete(); } //reader->GetIconImage()->Print( std::cout ); //vtkPropCollection *pc = vtkPropCollection::New(); //rep->GetActors2D(pc); //balloonwidget->AddBalloon(pc->GetLastProp(),"This is a DICOM thumbnail image",NULL); vtkLogoWidget *widget = vtkLogoWidget::New(); widget->SetInteractor(iren); widget->SetRepresentation(rep); iconwidget = widget; //widget->Delete(); rep->Delete(); //viewer->AddInputConnection ( reader->GetIconImagePort() ); } #endif #else viewer->SetInput( reader->GetOutput(0) ); if( reader->GetNumberOfOverlays() ) { viewer->AddInput( reader->GetOverlay(0) ); } #endif /*(VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )*/ // IconImage: //if( reader->GetNumberOfIconImages() ) // { // std::cerr << "NumberOfIconImages:" << reader->GetNumberOfIconImages() << std::endl; // reader->GetIconImage()->Print( std::cerr ); // vtkPNGWriter *writer = vtkPNGWriter::New(); // writer->SetInput( reader->GetIconImage() ); // writer->SetFileName( "icon.png" ); // //writer->Write(); // writer->Delete(); // } // In case of palette color, let's tell VTK to map color: // MONOCHROME1 is also implemented with a lookup table if( reader->GetImageFormat() == VTK_LOOKUP_TABLE || reader->GetImageFormat() == VTK_INVERSE_LUMINANCE ) { #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) assert( reader->GetOutput()->GetPointData()->GetScalars() && reader->GetOutput()->GetPointData()->GetScalars()->GetLookupTable() ); #endif //convert to color: vtkLookupTable *lut = reader->GetOutput()->GetPointData()->GetScalars()->GetLookupTable(); if( !lut ) { // This must be a Segmented Palette and on VTK 4.4 this is not supported std::cerr << "Not implemented. You will not see the Color LUT" << std::endl; } #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) if( lut->IsA( "vtkLookupTable16" ) ) { vtkImageMapToColors16 *map = vtkImageMapToColors16::New (); #if VTK_MAJOR_VERSION >= 6 map->SetInputConnection (reader->GetOutputPort()); #else map->SetInput (reader->GetOutput()); #endif map->SetLookupTable (reader->GetOutput()->GetPointData()->GetScalars()->GetLookupTable()); if( reader->GetImageFormat() == VTK_LOOKUP_TABLE ) { map->SetOutputFormatToRGB(); } else if( reader->GetImageFormat() == VTK_INVERSE_LUMINANCE ) { map->SetOutputFormatToLuminance(); } map->Update(); map->GetOutput()->GetScalarRange(range); #if VTK_MAJOR_VERSION >= 6 viewer->SetInputConnection( map->GetOutputPort() ); #else viewer->SetInput( map->GetOutput() ); #endif map->Delete(); } else #endif { vtkImageMapToColors *map = vtkImageMapToColors::New (); #if VTK_MAJOR_VERSION >= 6 map->SetInputConnection (reader->GetOutputPort()); #else map->SetInput (reader->GetOutput()); #endif map->SetLookupTable (reader->GetOutput()->GetPointData()->GetScalars()->GetLookupTable()); if( reader->GetImageFormat() == VTK_LOOKUP_TABLE ) { map->SetOutputFormatToRGB(); } else if( reader->GetImageFormat() == VTK_INVERSE_LUMINANCE ) { map->SetOutputFormatToLuminance(); } map->Update(); map->GetOutput()->GetScalarRange(range); #if VTK_MAJOR_VERSION >= 6 viewer->SetInputConnection( map->GetOutputPort() ); #else viewer->SetInput( map->GetOutput() ); #endif map->Delete(); } } else if( reader->GetImageFormat() == VTK_YBR ) { #if VTK_MAJOR_VERSION >= 5 vtkImageYBRToRGB *filter = vtkImageYBRToRGB::New(); #if VTK_MAJOR_VERSION >= 6 filter->SetInputConnection( reader->GetOutputPort() ); #else filter->SetInput( reader->GetOutput() ); #endif filter->Update(); filter->GetOutput()->GetScalarRange(range); #if VTK_MAJOR_VERSION >= 6 viewer->SetInputConnection( filter->GetOutputPort() ); #else viewer->SetInput( filter->GetOutput() ); #endif filter->Delete(); #else std::cerr << "Not implemented" << std::endl; #endif } else if( reader->GetImageFormat() == VTK_RGB || reader->GetImageFormat() == VTK_RGBA ) { // easy case ! } // vtkImageShiftScale *ss = vtkImageShiftScale::New(); // ss->SetInput( reader->GetOutput() ); // ss->SetShift( -1024 ); // ss->SetOutputScalarTypeToShort(); // ss->Update(); // ss->GetOutput()->GetScalarRange(range); // viewer->SetInput( ss->GetOutput() ); // ss->Delete(); if( reader->GetCurve() ) { vtkPolyDataMapper2D * rectMapper = vtkPolyDataMapper2D::New(); #if VTK_MAJOR_VERSION >= 6 rectMapper->SetInputData( reader->GetCurve() ); #else rectMapper->SetInput( reader->GetCurve() ); #endif vtkActor2D * rectActor = vtkActor2D::New(); rectActor->SetMapper( rectMapper ); viewer->GetRenderer()->AddActor2D( rectActor ); rectActor->Delete(); rectMapper->Delete(); } #if 0 vtkImageReslice * slicer = vtkImageReslice::New(); slicer->SetInput( reader->GetOutput() ); slicer->InterpolateOn(); //slicer->SetResliceAxesOrigin(0, 0, 0); //slicer->SetResliceAxesOrigin( reader->GetImagePositionPatient() ); //slicer->SetResliceAxes( reader->GetDirectionCosines() ); const double *dircos = reader->GetImageOrientationPatient(); double dcos[9]; for(int i=0;i<6;++i) dcos[i] = dircos[i]; dcos[6] = dircos[1] * dircos[5] - dircos[2] * dircos[4]; dcos[7] = dircos[2] * dircos[3] - dircos[0] * dircos[5]; dcos[8] = dircos[0] * dircos[4] - dircos[3] * dircos[1]; double dummy[3]; double dot = vtkMath::Dot(dircos, dircos+3); std::cout << dot << std::endl; vtkMath::Cross(dircos, dircos+3, dummy); std::cout << dcos[6] << "," << dcos[7] << "," << dcos[8] << std::endl; std::cout << dummy[0] << "," << dummy[1] << "," << dummy[2] << std::endl; dot = vtkMath::Dot(dircos, dummy); std::cout << dot << std::endl; dot = vtkMath::Dot(dircos+3, dummy); std::cout << dot << std::endl; slicer->SetResliceAxesDirectionCosines(dcos); slicer->Update(); slicer->GetOutput()->Print( std::cout ); //viewer->SetInput( slicer->GetOutput() ); vtkOutlineFilter * outline = vtkOutlineFilter::New(); outline->SetInput( slicer->GetOutput() ); outline->GetOutput()->Print( std::cout ); //slicer->AddInput( (vtkPolyData*)outline->GetOutput() ); #endif // Always overwriting default is not always nice looking... viewer->SetColorLevel (0.5 * (range[1] + range[0])); viewer->SetColorWindow (range[1] - range[0]); if( verbose ) std::cout << "Range: " << range[0] << " " << range[1] << std::endl; viewer->SetupInteractor (iren); // vtkInteractorStyleImage *is = viewer->GetInteractorStyle(); // viewer->GetInteractorStyle()->AutoAdjustCameraClippingRangeOn(); vtkCornerAnnotation * ca = vtkCornerAnnotation::New(); ca->SetImageActor( viewer->GetImageActor() ); ca->SetWindowLevel( (vtkImageMapToWindowLevelColors*)viewer->GetWindowLevel() ); vtkMedicalImageProperties * medprop = reader->GetMedicalImageProperties(); FillCornerFromMedProp( ca, medprop ); #if VTK_MAJOR_VERSION >= 5 viewer->GetRenderer()->AddViewProp( ca ); #else viewer->GetRenderer()->AddProp( ca ); #endif int dims[3]; reader->GetOutput()->GetDimensions(dims); // Make sure to display on most screen dims[0] = (dims[0] < 600 ) ? dims[0] : 600; dims[1] = (dims[1] < 600 ) ? dims[1] : 600; viewer->Render(); // EXTREMELY IMPORTANT for vtkImageViewer2 viewer->GetRenderer()->ResetCamera(); viewer->SetSize( dims ); // Here is where we setup the observer, vtkGDCMObserver *obs = vtkGDCMObserver::New(); obs->ImageViewer = viewer; #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) if(iconwidget) iconwidget->On(); obs->IconWidget = iconwidget; obs->DistanceWidget = dwidget; obs->AngleWidget = anglewidget; obs->BiDimWidget = bwidget; obs->ContourWidget = contourWidget; balloonwidget->On(); #endif iren->AddObserver(vtkCommand::CharEvent,obs); iren->AddObserver(vtkCommand::EndPickEvent,obs); obs->Delete(); //vtkLegendScaleActor *legend = vtkLegendScaleActor::New(); //viewer->GetRenderer()->AddActor( legend ); iren->Initialize(); iren->Start(); //if you wish you can export dicom to a vtk file #if 0 vtkXMLImageDataWriter *writer = vtkXMLImageDataWriter::New(); writer->SetInputConnection( reader->GetOutputPort()); writer->SetFileName( "debug.vtk" ); writer->SetDataModeToBinary(); writer->Write(); writer->Delete(); #endif #if 0 vtkPNGWriter *writer = vtkPNGWriter::New(); //writer->SetInputConnection( reader->GetOutputPort() ); writer->SetInputConnection( reader->GetOutputPort(1) ); //range = overlay->GetScalarRange(); //std::cerr << "Range: " << range[0] << " " << range[1] << std::endl; //overlay->Print( std::cout ); //writer->SetInput( overlay ); writer->SetFileName( "debug.png" ); writer->Write(); writer->Delete(); #endif reader->Delete(); #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) cbk->Delete(); dwidget->Off(); balloonwidget->Off(); balloonwidget->Delete(); dwidget->Delete(); anglewidget->Off(); anglewidget->Delete(); bwidget->Off(); bwidget->Delete(); contourWidget->Off(); contourWidget->Delete(); if( iconwidget ) { iconwidget->Off(); iconwidget->Delete(); } #endif iren->Delete(); viewer->Delete(); } void PrintVersion() { std::cout << "gdcmviewer: gdcm " << gdcm::Version::GetVersion() << " "; const char date[] = "$Date$"; std::cout << date << std::endl; //std::cout << " VTK " << vtkVersion::GetVTKVersion() << std::endl; std::cout << " " << vtkVersion::GetVTKSourceVersion() << std::endl; } void PrintHelp() { PrintVersion(); std::cout << "Usage: gdcmviewer [OPTION] filename1.dcm [filename2.dcm...]" << std::endl; std::cout << "or : gdcmviewer [OPTION] directory" << std::endl; std::cout << "Display a DICOM image file.\n"; std::cout << "Options:" << std::endl; std::cout << " --force-rescale force rescale." << std::endl; std::cout << " --force-spacing force spacing." << std::endl; std::cout << " -r --recursive Recursively descend directory." << std::endl; std::cout << "General Options:" << std::endl; std::cout << " -V --verbose more verbose (warning+error)." << std::endl; std::cout << " -W --warning print warning info." << std::endl; std::cout << " -D --debug print debug info." << std::endl; std::cout << " -E --error print error info." << std::endl; std::cout << " -h --help print help." << std::endl; std::cout << " -v --version print version." << std::endl; } int main(int argc, char *argv[]) { int c; //int digit_optind = 0; std::vector filenames; int forcerescale = 0; int forcespacing = 0; int recursive = 0; verbose = 0; int warning = 0; int debug = 0; int error = 0; int help = 0; int version = 0; while (1) { //int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"force-rescale", 0, &forcerescale, 1}, {"force-spacing", 0, &forcespacing, 1}, {"recursive", 0, &recursive, 1}, // General options ! {"verbose", 0, &verbose, 1}, {"warning", 0, &warning, 1}, {"debug", 0, &debug, 1}, {"error", 0, &error, 1}, {"help", 0, &help, 1}, {"version", 0, &version, 1}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "rVWDEhv", long_options, &option_index); if (c == -1) { break; } switch (c) { case 0: { const char *s = long_options[option_index].name; (void)s; //printf ("option %s", s); if (optarg) { if( option_index == 0 ) /* input */ { assert( strcmp(s, "input") == 0 ); //assert( filename.empty() ); //filename = optarg; } printf (" with arg %s", optarg); } //printf ("\n"); } break; case 'r': recursive = 1; break; case 'V': verbose = 1; break; case 'W': warning = 1; break; case 'D': debug = 1; break; case 'E': error = 1; break; case 'h': help = 1; break; case 'v': version = 1; break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { //printf ("non-option ARGV-elements: "); while (optind < argc) { //printf ("%s ", argv[optind]); filenames.push_back( argv[optind++] ); } //printf ("\n"); } if( version ) { //std::cout << "version" << std::endl; PrintVersion(); return 0; } if( help ) { //std::cout << "help" << std::endl; PrintHelp(); return 0; } // Debug is a little too verbose gdcm::Trace::SetDebug( debug ); gdcm::Trace::SetWarning( warning ); gdcm::Trace::SetError( error ); // when verbose is true, make sure warning+error are turned on: if( verbose ) { gdcm::Trace::SetWarning( verbose ); gdcm::Trace::SetError( verbose); } //vtkMultiThreader::SetGlobalMaximumNumberOfThreads(1); gdcm::ImageHelper::SetForceRescaleInterceptSlope(forcerescale); gdcm::ImageHelper::SetForcePixelSpacing(forcespacing); if( filenames.empty() ) { PrintHelp(); return 1; } gdcm::Reader testreader; vtkStringArray *names = vtkStringArray::New(); { // Is it a single directory ? If so loop over all files contained in it: //const char *filename = argv[1]; if( filenames.size() == 1 && gdcm::System::FileIsDirectory( filenames[0].c_str() ) ) { if( verbose ) std::cout << "Loading directory: " << filenames[0] << std::endl; gdcm::Directory d; d.Load(filenames[0].c_str(), recursive); gdcm::Directory::FilenamesType const &files = d.GetFilenames(); for( gdcm::Directory::FilenamesType::const_iterator it = files.begin(); it != files.end(); ++it ) { testreader.SetFileName( it->c_str() ); if( testreader.CanRead() ) { names->InsertNextValue( it->c_str() ); } else { if(verbose) std::cerr << "Discarding non DICOM file: " << it->c_str() << std::endl; } } } else // list of files passed directly on the cmd line: // discard non-existing or directory { //for(int i=1; i < argc; ++i) for(std::vector::const_iterator it = filenames.begin(); it != filenames.end(); ++it) { //filename = argv[i]; const std::string & filename = *it; if( gdcm::System::FileExists( filename.c_str() ) ) { if( gdcm::System::FileIsDirectory( filename.c_str() ) ) { if(verbose) std::cerr << "Discarding directory: " << filename << std::endl; } else { testreader.SetFileName( filename.c_str() ); if( testreader.CanRead() ) { names->InsertNextValue( filename.c_str() ); } else { if(verbose) std::cerr << "Discarding non DICOM file: " << filename.c_str() << std::endl; } } } else { if(verbose) std::cerr << "Discarding non existing file: " << filename << std::endl; } } } //names->Print( std::cout ); } vtkImageColorViewer *viewer = vtkImageColorViewer::New(); ExecuteViewer(viewer, names); names->Delete(); return 0; }