📄 readerwriterdicom.cpp
字号:
// Released under the OSGPL license, as part of the OpenSceneGraph distribution.//// ReaderWriter for sgi's .rgb format.// specification can be found at http://local.wasp.uwa.edu.au/~pbourke/dataformats/sgirgb/sgiversion.html#include <osg/Image>#include <osg/Notify>#include <osg/Geode>#include <osg/GL>#include <osg/io_utils>#include <osgDB/FileNameUtils>#include <osgDB/FileUtils>#include <osgDB/Registry>#include <osgVolume/Volume>#include <osgVolume/Brick>#include <osgVolume/ImageUtils>#ifdef USE_DCMTK #define HAVE_CONFIG_H #include <dcmtk/config/osconfig.h> #include <dcmtk/dcmdata/dcfilefo.h> #include <dcmtk/dcmdata/dcdeftag.h> #include <dcmtk/dcmimgle/dcmimage.h>#endif#ifdef USE_ITK #include <itkImageFileReader.h> #include <itkImageFileWriter.h> #include <itkImage.h> #include <itkImageRegionConstIterator.h> #include <itkMetaDataDictionary.h> #include <itkMetaDataObject.h> #include <itkGDCMImageIO.h>#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#include <memory>class ReaderWriterDICOM : public osgDB::ReaderWriter{ public: ReaderWriterDICOM() { supportsExtension("mag","dicom image format"); supportsExtension("ph","dicom image format"); supportsExtension("ima","dicom image format"); supportsExtension("dic","dicom image format"); supportsExtension("dcm","dicom image format"); supportsExtension("dicom","dicom image format"); // supportsExtension("*","dicom image format"); } std::ostream& warning() const { return osg::notify(osg::WARN); } std::ostream& notice() const { return osg::notify(osg::NOTICE); } std::ostream& info() const { return osg::notify(osg::NOTICE); } template<typename T> T* readData(std::istream& fin, unsigned int length, unsigned int& numComponents) const { numComponents = length/sizeof(T); T* data = new T[numComponents]; fin.read((char*)data, numComponents*sizeof(T)); // read over any padding length -= numComponents*sizeof(T); while(fin && length>0) { fin.get(); --length; } return data; } template<typename T> void printData(std::ostream& out, T* data, unsigned int numComponents) const { if (sizeof(T)==1) { for(unsigned int i=0; i<numComponents; ++i) { if (data[i]>32) out<<data[i]; else out<<"."; } } else { for(unsigned int i=0; i<numComponents; ++i) { if (i==0) out<<data[i]; else out<<", "<<data[i]; } } } virtual const char* className() const { return "DICOM Image Reader/Writer"; } virtual ReadResult readObject(std::istream& fin,const osgDB::ReaderWriter::Options* options =NULL) const { return readImage(fin, options); } virtual ReadResult readObject(const std::string& file, const osgDB::ReaderWriter::Options* options =NULL) const { return readImage(file, options); } virtual ReadResult readNode(std::istream& fin,const osgDB::ReaderWriter::Options* options =NULL) const { return readImage(fin, options); } virtual ReadResult readNode(const std::string& file, const osgDB::ReaderWriter::Options* options =NULL) const { ReadResult result = readImage(file, options); if (!result.validImage()) return result; osg::ref_ptr<osgVolume::Volume> volume = new osgVolume::Volume; osg::ref_ptr<osgVolume::Brick> brick = new osgVolume::Brick; brick->setVolume(volume.get()); brick->setImage(result.getImage()); // get matrix providing size of texels (in mm) osg::RefMatrix* matrix = dynamic_cast<osg::RefMatrix*>(result.getImage()->getUserData()); if (matrix) { // scale up to provide scale of complete brick osg::Vec3d scale(osg::Vec3(result.getImage()->s(),result.getImage()->t(), result.getImage()->r())); matrix->postMultScale(scale); brick->setLocator(matrix); result.getImage()->setUserData(0); notice()<<"Locator "<<*matrix<<std::endl; } volume->addChild(brick.get()); return volume.release(); } virtual ReadResult readImage(std::istream& fin,const osgDB::ReaderWriter::Options*) const { return 0; }#ifdef USE_ITK virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const { std::string ext = osgDB::getLowerCaseFileExtension(file); if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; std::string fileName = osgDB::findDataFile( file, options ); if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; notice()<<"Reading DICOM file "<<fileName<<std::endl; typedef unsigned short PixelType; const unsigned int Dimension = 3; typedef itk::Image< PixelType, Dimension > ImageType; typedef itk::ImageFileReader< ImageType > ReaderType; ReaderType::Pointer reader = ReaderType::New(); reader->SetFileName( fileName.c_str() ); typedef itk::GDCMImageIO ImageIOType; ImageIOType::Pointer gdcmImageIO = ImageIOType::New(); reader->SetImageIO( gdcmImageIO ); try { reader->Update(); } catch (itk::ExceptionObject & e) { std::cerr << "exception in file reader " << std::endl; std::cerr << e.GetDescription() << std::endl; std::cerr << e.GetLocation() << std::endl; return ReadResult::ERROR_IN_READING_FILE; } ImageType::Pointer inputImage = reader->GetOutput(); ImageType::RegionType region = inputImage->GetBufferedRegion(); ImageType::SizeType size = region.GetSize(); ImageType::IndexType start = region.GetIndex(); //inputImage->GetSpacing(); //inputImage->GetOrigin(); unsigned int width = size[0]; unsigned int height = size[1]; unsigned int depth = size[2]; osg::RefMatrix* matrix = new osg::RefMatrix; notice()<<"width = "<<width<<" height = "<<height<<" depth = "<<depth<<std::endl; for(unsigned int i=0; i<Dimension; ++i) { (*matrix)(i,i) = inputImage->GetSpacing()[i]; (*matrix)(3,i) = inputImage->GetOrigin()[i]; } osg::Image* image = new osg::Image; image->allocateImage(width, height, depth, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1); unsigned char* data = image->data(); typedef itk::ImageRegionConstIterator< ImageType > IteratorType; IteratorType it(inputImage, region); it.GoToBegin(); while (!it.IsAtEnd()) { *data = it.Get(); ++data; ++it; } image->setUserData(matrix); return image; }#endif#ifdef USE_DCMTK void convertPixelTypes(const DiPixel* pixelData, EP_Representation& pixelRep, unsigned int& numPlanes, GLenum& dataType, GLenum& pixelFormat, unsigned int& pixelSize) const { dataType = GL_UNSIGNED_BYTE; pixelRep = pixelData->getRepresentation(); switch(pixelRep) { case(EPR_Uint8): dataType = GL_UNSIGNED_BYTE; pixelSize = 1; break; case(EPR_Sint8): dataType = GL_BYTE; pixelSize = 1; break; case(EPR_Uint16): dataType = GL_UNSIGNED_SHORT; pixelSize = 2; break; case(EPR_Sint16): dataType = GL_SHORT; pixelSize = 2; break; case(EPR_Uint32): dataType = GL_UNSIGNED_INT; pixelSize = 4; break; case(EPR_Sint32): dataType = GL_INT; pixelSize = 4; break; default: dataType = 0; break; } pixelFormat = GL_INTENSITY; numPlanes = pixelData->getPlanes(); switch(numPlanes) { case(1): pixelFormat = GL_LUMINANCE; break; case(2): pixelFormat = GL_LUMINANCE_ALPHA; pixelSize *= 2; break; case(3): pixelFormat = GL_RGB; pixelSize *= 3; break; case(4): pixelFormat = GL_RGBA; pixelSize *= 4; break; } } typedef std::vector<std::string> Files; bool getDicomFilesInDirectory(const std::string& path, Files& files) const { osgDB::DirectoryContents contents = osgDB::getDirectoryContents(path); std::sort(contents.begin(), contents.end()); for(osgDB::DirectoryContents::iterator itr = contents.begin(); itr != contents.end(); ++itr) { std::string localFile = path + "/" + *itr; info()<<"contents = "<<localFile<<std::endl; if (acceptsExtension(osgDB::getLowerCaseFileExtension(localFile)) && osgDB::fileType(localFile) == osgDB::REGULAR_FILE) { files.push_back(localFile); } } return !files.empty(); } virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const { notice()<<"Reading DICOM file "<<file<<" using DCMTK"<<std::endl; std::string ext = osgDB::getLowerCaseFileExtension(file); if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; std::string fileName = file; if (ext=="dicom") { fileName = osgDB::getNameLessExtension(file); } fileName = osgDB::findDataFile( fileName, options ); if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; Files files; osgDB::FileType fileType = osgDB::fileType(fileName); if (fileType==osgDB::DIRECTORY) { getDicomFilesInDirectory(fileName, files); } else {#if 1 files.push_back(fileName);#else if (!getDicomFilesInDirectory(osgDB::getFilePath(fileName), files)) { files.push_back(fileName); }#endif } if (files.empty()) { return ReadResult::FILE_NOT_FOUND;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -