Added optional usage of DCMTK in the dicom plugin

This commit is contained in:
Robert Osfield 2008-09-15 19:59:12 +00:00
parent c7b66322be
commit d07f3d5662
6 changed files with 477 additions and 60 deletions

View File

@ -289,6 +289,7 @@ FIND_PACKAGE(ZLIB)
FIND_PACKAGE(GDAL) FIND_PACKAGE(GDAL)
FIND_PACKAGE(CURL) FIND_PACKAGE(CURL)
FIND_PACKAGE(ITK) FIND_PACKAGE(ITK)
FIND_PACKAGE(OurDCMTK)
SET(wxWidgets_USE_LIBS base core gl net) SET(wxWidgets_USE_LIBS base core gl net)
FIND_PACKAGE(wxWidgets) FIND_PACKAGE(wxWidgets)

View File

@ -0,0 +1,159 @@
# - find DCMTK libraries
#
# DCMTK_INCLUDE_DIR - Directories to include to use DCMTK
# DCMTK_LIBRARIES - Files to link against to use DCMTK
# DCMTK_FOUND - If false, don't try to use DCMTK
# DCMTK_DIR - (optional) Source directory for DCMTK
#
# DCMTK_DIR can be used to make it simpler to find the various include
# directories and compiled libraries if you've just compiled it in the
# source tree. Just set it to the root of the tree where you extracted
# the source.
#
# Written for VXL by Amitha Perera.
#
FIND_PATH( DCMTK_config_INCLUDE_DIR osconfig.h
${DCMTK_DIR}/config/include
${DCMTK_DIR}/include
/usr/local/include/dcmtk/config
/usr/include/dcmtk/config
)
FIND_PATH( DCMTK_ofstd_INCLUDE_DIR ofstdinc.h
${DCMTK_DIR}/ofstd/include
${DCMTK_DIR}/include/ofstd
/usr/local/include/dcmtk/ofstd
/usr/include/dcmtk/ofstd
)
FIND_LIBRARY( DCMTK_ofstd_LIBRARY ofstd
${DCMTK_DIR}/ofstd/libsrc
${DCMTK_DIR}/ofstd/libsrc/Release
${DCMTK_DIR}/ofstd/libsrc/Debug
${DCMTK_DIR}/ofstd/Release
${DCMTK_DIR}/ofstd/Debug
${DCMTK_DIR}/lib
/usr/local/lib64
/usr/lib64
/usr/local/lib
/usr/lib
)
FIND_PATH( DCMTK_dcmdata_INCLUDE_DIR dctypes.h
${DCMTK_DIR}/dcmdata/include
${DCMTK_DIR}/include/dcmdata
/usr/local/include/dcmtk/dcmdata
/usr/include/dcmtk/dcmdata
)
FIND_LIBRARY( DCMTK_dcmdata_LIBRARY dcmdata
${DCMTK_DIR}/dcmdata/libsrc
${DCMTK_DIR}/dcmdata/libsrc/Release
${DCMTK_DIR}/dcmdata/libsrc/Debug
${DCMTK_DIR}/dcmdata/Release
${DCMTK_DIR}/dcmdata/Debug
${DCMTK_DIR}/lib
/usr/local/lib64
/usr/lib64
/usr/local/lib
/usr/lib
)
FIND_PATH( DCMTK_dcmimgle_INCLUDE_DIR dcmimage.h
${DCMTK_DIR}/dcmimgle/include
${DCMTK_DIR}/include/dcmimgle
/usr/local/include/dcmtk/dcmimgle
/usr/include/dcmtk/dcmimgle
)
FIND_LIBRARY( DCMTK_dcmimgle_LIBRARY dcmimgle
${DCMTK_DIR}/dcmimgle/libsrc
${DCMTK_DIR}/dcmimgle/libsrc/Release
${DCMTK_DIR}/dcmimgle/libsrc/Debug
${DCMTK_DIR}/dcmimgle/Release
${DCMTK_DIR}/dcmimgle/Debug
${DCMTK_DIR}/lib
/usr/local/lib64
/usr/lib64
/usr/local/lib
/usr/lib
)
FIND_LIBRARY(DCMTK_imagedb_LIBRARY imagedb
${DCMTK_DIR}/imagectn/libsrc/Release
${DCMTK_DIR}/imagectn/libsrc/
${DCMTK_DIR}/imagectn/libsrc/Debug
/usr/local/lib64
/usr/lib64
/usr/local/lib
/usr/lib
)
FIND_LIBRARY(DCMTK_dcmnet_LIBRARY dcmnet
${DCMTK_DIR}/dcmnet/libsrc/Release
${DCMTK_DIR}/dcmnet/libsrc/Debug
${DCMTK_DIR}/dcmnet/libsrc/
/usr/local/lib64
/usr/lib64
/usr/local/lib
/usr/lib
)
IF( DCMTK_config_INCLUDE_DIR
AND DCMTK_ofstd_INCLUDE_DIR
AND DCMTK_ofstd_LIBRARY
AND DCMTK_dcmdata_INCLUDE_DIR
AND DCMTK_dcmdata_LIBRARY
AND DCMTK_dcmimgle_INCLUDE_DIR
AND DCMTK_dcmimgle_LIBRARY )
SET( DCMTK_FOUND "YES" )
SET( DCMTK_INCLUDE_DIR
${DCMTK_config_INCLUDE_DIR}
${DCMTK_ofstd_INCLUDE_DIR}
${DCMTK_dcmdata_INCLUDE_DIR}
${DCMTK_dcmimgle_INCLUDE_DIR}
)
SET( DCMTK_LIBRARIES
${DCMTK_dcmimgle_LIBRARY}
${DCMTK_dcmdata_LIBRARY}
${DCMTK_ofstd_LIBRARY}
${DCMTK_config_LIBRARY}
)
IF(DCMTK_imagedb_LIBRARY)
SET( DCMTK_LIBRARIES
${DCMTK_LIBRARIES}
${DCMTK_imagedb_LIBRARY}
)
ENDIF(DCMTK_imagedb_LIBRARY)
IF(DCMTK_dcmnet_LIBRARY)
SET( DCMTK_LIBRARIES
${DCMTK_LIBRARIES}
${DCMTK_dcmnet_LIBRARY}
)
ENDIF(DCMTK_dcmnet_LIBRARY)
IF( WIN32 )
SET( DCMTK_LIBRARIES ${DCMTK_LIBRARIES} netapi32 )
ENDIF( WIN32 )
ENDIF( DCMTK_config_INCLUDE_DIR
AND DCMTK_ofstd_INCLUDE_DIR
AND DCMTK_ofstd_LIBRARY
AND DCMTK_dcmdata_INCLUDE_DIR
AND DCMTK_dcmdata_LIBRARY
AND DCMTK_dcmimgle_INCLUDE_DIR
AND DCMTK_dcmimgle_LIBRARY )
IF( NOT DCMTK_FOUND )
SET( DCMTK_DIR "" CACHE PATH "Root of DCMTK source tree (optional)." )
MARK_AS_ADVANCED( DCMTK_DIR )
ENDIF( NOT DCMTK_FOUND )

View File

@ -437,6 +437,7 @@ osg::Image* createTexture3D(ImageList& imageList, ProcessRow& processRow,
osg::Image* image = itr->get(); osg::Image* image = itr->get();
GLenum pixelFormat = image->getPixelFormat(); GLenum pixelFormat = image->getPixelFormat();
if (pixelFormat==GL_ALPHA || if (pixelFormat==GL_ALPHA ||
pixelFormat==GL_INTENSITY ||
pixelFormat==GL_LUMINANCE || pixelFormat==GL_LUMINANCE ||
pixelFormat==GL_LUMINANCE_ALPHA || pixelFormat==GL_LUMINANCE_ALPHA ||
pixelFormat==GL_RGB || pixelFormat==GL_RGB ||
@ -519,6 +520,7 @@ osg::Image* createTexture3D(ImageList& imageList, ProcessRow& processRow,
GLenum pixelFormat = image->getPixelFormat(); GLenum pixelFormat = image->getPixelFormat();
if (pixelFormat==GL_ALPHA || if (pixelFormat==GL_ALPHA ||
pixelFormat==GL_LUMINANCE || pixelFormat==GL_LUMINANCE ||
pixelFormat==GL_INTENSITY ||
pixelFormat==GL_LUMINANCE_ALPHA || pixelFormat==GL_LUMINANCE_ALPHA ||
pixelFormat==GL_RGB || pixelFormat==GL_RGB ||
pixelFormat==GL_RGBA) pixelFormat==GL_RGBA)
@ -1849,54 +1851,59 @@ int main( int argc, char **argv )
if (!arguments.isOption(pos)) if (!arguments.isOption(pos))
{ {
std::string filename = arguments[pos]; std::string filename = arguments[pos];
if (osgDB::getLowerCaseFileExtension(filename)=="dicom")
osgDB::FileType fileType = osgDB::fileType(filename);
if (fileType == osgDB::FILE_NOT_FOUND)
{ {
filename = osgDB::findDataFile(filename);
fileType = osgDB::fileType(filename);
}
if (fileType == osgDB::DIRECTORY)
{
osgDB::DirectoryContents contents = osgDB::getDirectoryContents(filename);
std::sort(contents.begin(), contents.end());
ImageList imageList;
for(osgDB::DirectoryContents::iterator itr = contents.begin();
itr != contents.end();
++itr)
{
std::string localFile = filename + "/" + *itr;
std::cout<<"contents = "<<localFile<<std::endl;
if (osgDB::fileType(localFile) == osgDB::REGULAR_FILE)
{
// not an option so assume string is a filename.
osg::Image *image = osgDB::readImageFile(localFile);
if(image)
{
imageList.push_back(image);
}
}
}
// pack the textures into a single texture.
ProcessRow processRow;
image_3d = createTexture3D(imageList, processRow, numComponentsDesired, s_maximumTextureSize, t_maximumTextureSize, r_maximumTextureSize, resizeToPowerOfTwo);
}
else if (fileType == osgDB::REGULAR_FILE)
{
// not an option so assume string is a filename.
image_3d = osgDB::readImageFile( filename ); image_3d = osgDB::readImageFile( filename );
} }
else else
{ {
osg::notify(osg::NOTICE)<<"Error: could not find file: "<<filename<<std::endl; osgDB::FileType fileType = osgDB::fileType(filename);
return 1; if (fileType == osgDB::FILE_NOT_FOUND)
} {
filename = osgDB::findDataFile(filename);
fileType = osgDB::fileType(filename);
}
if (fileType == osgDB::DIRECTORY)
{
osgDB::DirectoryContents contents = osgDB::getDirectoryContents(filename);
std::sort(contents.begin(), contents.end());
ImageList imageList;
for(osgDB::DirectoryContents::iterator itr = contents.begin();
itr != contents.end();
++itr)
{
std::string localFile = filename + "/" + *itr;
std::cout<<"contents = "<<localFile<<std::endl;
if (osgDB::fileType(localFile) == osgDB::REGULAR_FILE)
{
// not an option so assume string is a filename.
osg::Image *image = osgDB::readImageFile(localFile);
if(image)
{
imageList.push_back(image);
}
}
}
// pack the textures into a single texture.
ProcessRow processRow;
image_3d = createTexture3D(imageList, processRow, numComponentsDesired, s_maximumTextureSize, t_maximumTextureSize, r_maximumTextureSize, resizeToPowerOfTwo);
}
else if (fileType == osgDB::REGULAR_FILE)
{
// not an option so assume string is a filename.
image_3d = osgDB::readImageFile( filename );
}
else
{
osg::notify(osg::NOTICE)<<"Error: could not find file: "<<filename<<std::endl;
return 1;
}
}
} }
} }

View File

@ -104,9 +104,9 @@ ENDIF(CURL_FOUND)
# #
# 3D Image plugins # 3D Image plugins
# #
IF(ITK_FOUND) IF (ITK_FOUND OR DCMTK_FOUND)
ADD_SUBDIRECTORY(dicom) ADD_SUBDIRECTORY(dicom)
ENDIF(ITK_FOUND) ENDIF(ITK_FOUND OR DCMTK_FOUND)
############################################################ ############################################################

View File

@ -1,14 +1,35 @@
INCLUDE(${ITK_USE_FILE}) IF (DCMTK_FOUND)
INCLUDE_DIRECTORIES( ITK_INCLUDE_DIRS ) INCLUDE_DIRECTORIES( DCMTK_INCLUDE_DIRS )
SET(TARGET_SRC ReaderWriterDICOM.cpp ) SET(TARGET_SRC ReaderWriterDICOM.cpp )
LINK_DIRECTORIES(${ITK_LIBRARY_DIRS}) LINK_LIBRARIES(${DCMTK_LIBRARIES})
# LINK_LIBRARIES(${ITK_LIBRARIES}) ADD_DEFINITIONS(-DUSE_DCMTK)
ELSE(DCMTK_FOUND)
IF (ITK_FOUND)
INCLUDE(${ITK_USE_FILE})
INCLUDE_DIRECTORIES( ITK_INCLUDE_DIRS )
SET(TARGET_SRC ReaderWriterDICOM.cpp )
LINK_DIRECTORIES(${ITK_LIBRARY_DIRS})
# LINK_LIBRARIES(${ITK_LIBRARIES})
LINK_LIBRARIES(ITKCommon ITKIO)
ADD_DEFINITIONS(-DUSE_ITK)
ENDIF(ITK_FOUND)
ENDIF(DCMTK_FOUND)
LINK_LIBRARIES(ITKCommon ITKIO)
#### end var setup ### #### end var setup ###
SETUP_PLUGIN(dicom) SETUP_PLUGIN(dicom)

View File

@ -5,23 +5,32 @@
#include <osg/Image> #include <osg/Image>
#include <osg/Notify> #include <osg/Notify>
#include <osg/Geode> #include <osg/Geode>
#include <osg/GL> #include <osg/GL>
#include <osg/io_utils>
#include <osgDB/FileNameUtils> #include <osgDB/FileNameUtils>
#include <osgDB/FileUtils> #include <osgDB/FileUtils>
#include <osgDB/Registry> #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 <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -91,6 +100,8 @@ class ReaderWriterDICOM : public osgDB::ReaderWriter
return 0; return 0;
} }
#ifdef USE_ITK
virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const
{ {
std::string ext = osgDB::getLowerCaseFileExtension(file); std::string ext = osgDB::getLowerCaseFileExtension(file);
@ -167,6 +178,224 @@ class ReaderWriterDICOM : public osgDB::ReaderWriter
return image; 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
}; };