Added optional usage of DCMTK in the dicom plugin
This commit is contained in:
@@ -5,23 +5,32 @@
|
||||
|
||||
#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 <itkImageFileReader.h>
|
||||
#include <itkImageFileWriter.h>
|
||||
#include <itkImage.h>
|
||||
#include <itkImageRegionConstIterator.h>
|
||||
#include <itkMetaDataDictionary.h>
|
||||
#include <itkMetaDataObject.h>
|
||||
#include <itkGDCMImageIO.h>
|
||||
|
||||
#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>
|
||||
@@ -91,6 +100,8 @@ class ReaderWriterDICOM : public osgDB::ReaderWriter
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_ITK
|
||||
virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const
|
||||
{
|
||||
std::string ext = osgDB::getLowerCaseFileExtension(file);
|
||||
@@ -167,6 +178,224 @@ class ReaderWriterDICOM : public osgDB::ReaderWriter
|
||||
|
||||
return image;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_DCMTK
|
||||
|
||||
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;
|
||||
std::cout<<"contents = "<<localFile<<std::endl;
|
||||
if (osgDB::getLowerCaseFileExtension(localFile)=="dcm" &&
|
||||
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
|
||||
{
|
||||
osg::notify(osg::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;
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::RefMatrix> matrix = new osg::RefMatrix;
|
||||
osg::ref_ptr<osg::Image> image;
|
||||
unsigned int imageNum = 0;
|
||||
EP_Representation pixelRep;
|
||||
unsigned int numPlanes = 0;
|
||||
GLenum pixelFormat = 0;
|
||||
GLenum dataType = 0;
|
||||
unsigned int pixelSize = 0;
|
||||
|
||||
for(Files::iterator itr = files.begin();
|
||||
itr != files.end();
|
||||
++itr)
|
||||
{
|
||||
std::auto_ptr<DicomImage> dcmImage(new DicomImage((*itr).c_str()));
|
||||
if (dcmImage.get())
|
||||
{
|
||||
if (dcmImage->getStatus()==EIS_Normal)
|
||||
{
|
||||
// get the pixel data
|
||||
const DiPixel* pixelData = dcmImage->getInterData();
|
||||
if(!pixelData) return ReadResult::ERROR_IN_READING_FILE;
|
||||
|
||||
if (!image)
|
||||
{
|
||||
// read dicom file format to extra spacing info
|
||||
DcmFileFormat fileformat;
|
||||
OFCondition status = fileformat.loadFile((*itr).c_str());
|
||||
if(!status.good()) return ReadResult::ERROR_IN_READING_FILE;
|
||||
|
||||
// get the dimension of the dicom image
|
||||
OFString spacingString;
|
||||
if(fileformat.getDataset()->findAndGetOFString(DCM_PixelSpacing, spacingString).good())
|
||||
{
|
||||
float xy_spacing = atof(spacingString.c_str());
|
||||
(*matrix)(0,0) = xy_spacing;
|
||||
(*matrix)(1,1) = xy_spacing * dcmImage->getWidthHeightRatio();
|
||||
}
|
||||
|
||||
// Get slice thickness
|
||||
if(fileformat.getDataset()->findAndGetOFString(DCM_SliceThickness, spacingString).good())
|
||||
{
|
||||
(*matrix)(2,2) = atof(spacingString.c_str());
|
||||
}
|
||||
|
||||
|
||||
osg::notify(osg::NOTICE)<<"dicomImage->getWidth() = "<<dcmImage->getWidth()<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<"dicomImage->getHeight() = "<<dcmImage->getHeight()<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<"dicomImage->getFrameCount() = "<<dcmImage->getFrameCount()<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<"pixelData->getCount() = "<<pixelData->getCount()<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<"pixelFormat = ";
|
||||
|
||||
dataType = GL_UNSIGNED_BYTE;
|
||||
unsigned int pixelSize = 0;
|
||||
pixelRep = pixelData->getRepresentation();
|
||||
switch(pixelRep)
|
||||
{
|
||||
case(EPR_Uint8):
|
||||
dataType = GL_UNSIGNED_BYTE;
|
||||
pixelSize = 1;
|
||||
osg::notify(osg::NOTICE)<<"unsigned char"<<std::endl;
|
||||
break;
|
||||
case(EPR_Sint8):
|
||||
dataType = GL_BYTE;
|
||||
pixelSize = 1;
|
||||
osg::notify(osg::NOTICE)<<"char"<<std::endl;
|
||||
break;
|
||||
case(EPR_Uint16):
|
||||
dataType = GL_UNSIGNED_SHORT;
|
||||
pixelSize = 2;
|
||||
osg::notify(osg::NOTICE)<<"unsigned short"<<std::endl;
|
||||
break;
|
||||
case(EPR_Sint16):
|
||||
dataType = GL_SHORT;
|
||||
pixelSize = 2;
|
||||
osg::notify(osg::NOTICE)<<"short"<<std::endl;
|
||||
break;
|
||||
case(EPR_Uint32):
|
||||
dataType = GL_UNSIGNED_INT;
|
||||
pixelSize = 4;
|
||||
osg::notify(osg::NOTICE)<<"unsigned int"<<std::endl;
|
||||
break;
|
||||
case(EPR_Sint32):
|
||||
osg::notify(osg::NOTICE)<<"int"<<std::endl;
|
||||
dataType = GL_INT;
|
||||
pixelSize = 4;
|
||||
break;
|
||||
default:
|
||||
osg::notify(osg::NOTICE)<<"unidentified"<<std::endl;
|
||||
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;
|
||||
}
|
||||
|
||||
image = new osg::Image;
|
||||
image->setFileName(fileName.c_str());
|
||||
image->allocateImage(dcmImage->getWidth(), dcmImage->getHeight(), files.size() * dcmImage->getFrameCount(),
|
||||
pixelFormat, dataType);
|
||||
|
||||
}
|
||||
|
||||
if (pixelData->getPlanes()==numPlanes &&
|
||||
pixelData->getRepresentation()==pixelRep &&
|
||||
dcmImage->getWidth()==image->s() &&
|
||||
dcmImage->getHeight()==image->t())
|
||||
{
|
||||
int numFramesToCopy = std::min(static_cast<unsigned int>(image->r()-imageNum),
|
||||
static_cast<unsigned int>(dcmImage->getFrameCount()));
|
||||
unsigned int numPixels = dcmImage->getWidth() * dcmImage->getHeight() * numFramesToCopy;
|
||||
unsigned int dataSize = numPixels * pixelSize;
|
||||
memcpy(image->data(imageNum), pixelData->getData(), dataSize);
|
||||
imageNum += numFramesToCopy;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Error in reading dicom file "<<fileName.c_str()<<", error = "<<DicomImage::getString(dcmImage->getStatus())<<std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!image)
|
||||
{
|
||||
return ReadResult::ERROR_IN_READING_FILE;
|
||||
}
|
||||
|
||||
osg::notify(osg::NOTICE)<<"Spacing = "<<*matrix<<std::endl;
|
||||
|
||||
return image.get();
|
||||
}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user