Data loader 2.

This commit is contained in:
Krad
2022-09-13 09:30:03 +08:00
parent 755d791a2a
commit 43cef56e5f
8 changed files with 279 additions and 162 deletions

View File

@@ -2,7 +2,7 @@
// Created by Krad on 2022/2/8. // Created by Krad on 2022/2/8.
// //
#include "DICOMDirectoryHelper.h" #include "DICOMHeaderHelper.h"
#include "dcmtk/dcmdata/dcfilefo.h" #include "dcmtk/dcmdata/dcfilefo.h"
#include "dcmtk/dcmdata/dcdatset.h" #include "dcmtk/dcmdata/dcdatset.h"
#include "ExtendMedicalImageProperties.h" #include "ExtendMedicalImageProperties.h"
@@ -50,7 +50,7 @@ DICOMTag dicom_tags[] = {
{0x0028, 0x1052, "pixel offset"} {0x0028, 0x1052, "pixel offset"}
}; };
void DICOMDirectoryHelper::getDirectoryProperties(const char * rootPath, SeriesMap& result){ void DICOMHeaderHelper::getDirectoryProperties(const char * rootPath, SeriesMap& result){
vtkNew<vtkDirectory> dir; vtkNew<vtkDirectory> dir;
dir->Open(rootPath); dir->Open(rootPath);
vtkIdType fileCount = dir->GetNumberOfFiles(); vtkIdType fileCount = dir->GetNumberOfFiles();
@@ -72,7 +72,7 @@ void DICOMDirectoryHelper::getDirectoryProperties(const char * rootPath, SeriesM
} }
} }
void DICOMDirectoryHelper::getFileProperty(const std::string &path, SeriesMap& result) { void DICOMHeaderHelper::getFileProperty(const std::string &path, SeriesMap& result) {
DcmFileFormat file; DcmFileFormat file;
// read success! // read success!
if (file.loadFile(path).good()) { if (file.loadFile(path).good()) {
@@ -157,11 +157,11 @@ void DICOMDirectoryHelper::getFileProperty(const std::string &path, SeriesMap& r
char buffer[256] = {0}; char buffer[256] = {0};
sprintf(buffer, "%ld-%ld", AcquisitionNumber, InstanceNumber); sprintf(buffer, "%ld-%ld", AcquisitionNumber, InstanceNumber);
printf("%s\r\n", path.c_str()); printf("%s\r\n", path.c_str());
result[SeriesUID][buffer] = {path, SeriesNumber, AcquisitionNumber, InstanceNumber}; result[SeriesUID][buffer] = {path, "",SeriesNumber, AcquisitionNumber, InstanceNumber};
} }
} }
void DICOMDirectoryHelper::Update() { void DICOMHeaderHelper::Update() {
ReadHeader(); ReadHeader();
ArrangeSeriesProperty(); ArrangeSeriesProperty();
// std::unordered_map<std::string, std::unordered_map<std::string,DICOMFileHeader>> series; // std::unordered_map<std::string, std::unordered_map<std::string,DICOMFileHeader>> series;
@@ -200,12 +200,12 @@ void DICOMDirectoryHelper::Update() {
SeriesCount = seriesProperties.size(); SeriesCount = seriesProperties.size();
} }
ExtendMedicalImageProperties* DICOMDirectoryHelper::GetSeries(int idx) { ExtendMedicalImageProperties* DICOMHeaderHelper::GetSeries(int idx) {
if (seriesProperties.size() <= idx) return nullptr; if (seriesProperties.size() <= idx) return nullptr;
return seriesProperties[idx]; return seriesProperties[idx];
} }
ExtendMedicalImageProperties *DICOMDirectoryHelper::GetSeriesBySeriesUID(const char* seriesUID) { ExtendMedicalImageProperties *DICOMHeaderHelper::GetSeriesBySeriesUID(const char* seriesUID) {
for (int i = 0; i < seriesProperties.size(); ++i) { for (int i = 0; i < seriesProperties.size(); ++i) {
if (0==strcmp(seriesProperties[i]->GetSeriesUID(), seriesUID)){ if (0==strcmp(seriesProperties[i]->GetSeriesUID(), seriesUID)){
return seriesProperties[i]; return seriesProperties[i];
@@ -214,7 +214,7 @@ ExtendMedicalImageProperties *DICOMDirectoryHelper::GetSeriesBySeriesUID(const c
return nullptr; return nullptr;
} }
void DICOMDirectoryHelper::Clear() { void DICOMHeaderHelper::Clear() {
dirName.clear(); dirName.clear();
fileName.clear(); fileName.clear();
for (auto property : seriesProperties) { for (auto property : seriesProperties) {
@@ -224,7 +224,7 @@ void DICOMDirectoryHelper::Clear() {
SeriesCount = 0; SeriesCount = 0;
} }
void DICOMDirectoryHelper::readImageProperty(ExtendMedicalImageProperties* property) { void DICOMHeaderHelper::readImageProperty(ExtendMedicalImageProperties* property) {
const std::vector<std::string>& files = property->GetFileNames(); const std::vector<std::string>& files = property->GetFileNames();
DcmFileFormat file1; DcmFileFormat file1;
// read success! // read success!
@@ -314,7 +314,7 @@ void DICOMDirectoryHelper::readImageProperty(ExtendMedicalImageProperties* prope
} }
void DICOMDirectoryHelper::readHeaderFromDir(const char * rootPath){ void DICOMHeaderHelper::readHeaderFromDir(const char * rootPath){
vtkNew<vtkDirectory> dir; vtkNew<vtkDirectory> dir;
dir->Open(rootPath); dir->Open(rootPath);
vtkIdType fileCount = dir->GetNumberOfFiles(); vtkIdType fileCount = dir->GetNumberOfFiles();
@@ -336,12 +336,13 @@ void DICOMDirectoryHelper::readHeaderFromDir(const char * rootPath){
} }
} }
void DICOMDirectoryHelper::readHeaderFromFile(const char * filePath){ void DICOMHeaderHelper::readHeaderFromFile(const char * filePath){
DcmFileFormat file; DcmFileFormat file;
// read success! // read success!
if (file.loadFile(filePath).good()) { if (file.loadFile(filePath).good()) {
DcmDataset *dataset = file.getDataset(); DcmDataset *dataset = file.getDataset();
DICOMFileHeader header; DICOMFileHeader header;
header.FilePath = filePath;
std::string SeriesUID; std::string SeriesUID;
dataset->findAndGetOFString(DcmTagKey(0x0020, 0x000e), SeriesUID); dataset->findAndGetOFString(DcmTagKey(0x0020, 0x000e), SeriesUID);
@@ -359,8 +360,8 @@ void DICOMDirectoryHelper::readHeaderFromFile(const char * filePath){
ReadTAGToProperty(PatientName, 0x0010, 0x0010) ReadTAGToProperty(PatientName, 0x0010, 0x0010)
ReadTAGToProperty(StudyUID, 0x0020, 0x000d) ReadTAGToProperty(StudyUID, 0x0020, 0x000d)
dataset->findAndGetSint32(DcmTagKey(0x0028, 0x0010), header.Rows); dataset->findAndGetUint16(DcmTagKey(0x0028, 0x0010), header.Rows);
dataset->findAndGetSint32(DcmTagKey(0x0028, 0x0011), header.Columns); dataset->findAndGetUint16(DcmTagKey(0x0028, 0x0011), header.Columns);
dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x1050), header.WindowCenter); dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x1050), header.WindowCenter);
dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x1051), header.WindowWidth); dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x1051), header.WindowWidth);
@@ -386,8 +387,9 @@ void DICOMDirectoryHelper::readHeaderFromFile(const char * filePath){
uniqueID.append(StudyUID); uniqueID.append(StudyUID);
uniqueID.append("_"); uniqueID.append("_");
uniqueID.append(SeriesUID); uniqueID.append(SeriesUID);
header.SeriesUID = SeriesUID;
// series be firstly loaded // series be firstly loaded
if (!series.count(SeriesUID)) { if (series.count(uniqueID)==0) {
series.emplace(uniqueID,DICOMFileList()); series.emplace(uniqueID,DICOMFileList());
} }
header.calculateImagePosition(); header.calculateImagePosition();
@@ -395,7 +397,7 @@ void DICOMDirectoryHelper::readHeaderFromFile(const char * filePath){
} }
} }
void DICOMDirectoryHelper::ReadHeader() { void DICOMHeaderHelper::ReadHeader() {
if (!this->dirName.empty()){ if (!this->dirName.empty()){
vtkNew<vtkDirectory> dir; vtkNew<vtkDirectory> dir;
@@ -422,7 +424,7 @@ void DICOMDirectoryHelper::ReadHeader() {
} }
} }
void DICOMDirectoryHelper::ArrangeSeriesProperty() { void DICOMHeaderHelper::ArrangeSeriesProperty() {
for (auto item : series) { for (auto item : series) {
//sort by series, instance, AcquisitionNumber //sort by series, instance, AcquisitionNumber
std::sort(item.second.begin(), item.second.end(), [](auto v1, auto v2) { std::sort(item.second.begin(), item.second.end(), [](auto v1, auto v2) {
@@ -445,21 +447,22 @@ void DICOMDirectoryHelper::ArrangeSeriesProperty() {
[](auto v1,auto v2){ [](auto v1,auto v2){
return v1.image_position<v2.image_position; return v1.image_position<v2.image_position;
}); });
seriesProperties.push_back(createProperty(item.second, splitIndex[j], beginOffset)); auto p = createProperty(item.second, splitIndex[j], beginOffset);
if (p)seriesProperties.push_back(p);
beginOffset = splitIndex[j]; beginOffset = splitIndex[j];
} }
//sort the last image set //sort the last image set
if (splitIndex.size()>0) {
std::sort(item.second.begin() + beginOffset, item.second.end(), std::sort(item.second.begin() + beginOffset, item.second.end(),
[](auto v1, auto v2) { [](auto v1, auto v2) {
return v1.image_position < v2.image_position; return v1.image_position < v2.image_position;
}); });
seriesProperties.push_back(createProperty(item.second, item.second.size()-1, beginOffset)); auto p = createProperty(item.second, item.second.size(), beginOffset);
} if (p)seriesProperties.push_back(p);
} }
} }
ExtendMedicalImageProperties* DICOMDirectoryHelper::createProperty(const std::vector<DICOMFileHeader>& headerList, int splitIndex, int beginOffset) { ExtendMedicalImageProperties* DICOMHeaderHelper::createProperty(const std::vector<DICOMFileHeader>& headerList, int splitIndex, int beginOffset) {
auto property = ExtendMedicalImageProperties::New(); auto property = ExtendMedicalImageProperties::New();
std::vector<std::string> files; std::vector<std::string> files;
for (int i = beginOffset; i < splitIndex; ++i) { for (int i = beginOffset; i < splitIndex; ++i) {
@@ -506,20 +509,28 @@ ExtendMedicalImageProperties* DICOMDirectoryHelper::createProperty(const std::ve
double thickness= 1.0; double thickness= 1.0;
dataset->findAndGetFloat64(DcmTagKey(0x0008, 0x0050), thickness); dataset->findAndGetFloat64(DcmTagKey(0x0008, 0x0050), thickness);
double RescaleSlope= 1.0; double RescaleSlope= 1.0;
dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x1052), RescaleSlope); dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x1053), RescaleSlope);
double RescaleOffset= 1.0; double RescaleOffset= 1.0;
dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x1053), RescaleOffset); dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x1052), RescaleOffset);
unsigned short bitsAllocated= 1; unsigned short bitsAllocated= 1;
dataset->findAndGetUint16(DcmTagKey(0x0028, 0x1000), bitsAllocated); dataset->findAndGetUint16(DcmTagKey(0x0028, 0x0100), bitsAllocated);
unsigned short PixelRepresentation= 0; unsigned short PixelRepresentation= 0;
dataset->findAndGetUint16(DcmTagKey(0x0028, 0x1000), PixelRepresentation); dataset->findAndGetUint16(DcmTagKey(0x0028, 0x0103), PixelRepresentation);
property->SetSeriesUID(header.SeriesUID.c_str());
property->SetRows(header.Rows);
property->SetColumns(header.Columns);
property->SetSpacing(header.Spacing[0],header.Spacing[1],thickness); property->SetSpacing(header.Spacing[0],header.Spacing[1],thickness);
property->SetRescaleSlope(RescaleSlope); property->SetRescaleSlope(RescaleSlope);
property->SetRescaleOffset(RescaleOffset); property->SetRescaleOffset(RescaleOffset);
property->SetBitsAllocated(bitsAllocated); property->SetBitsAllocated(bitsAllocated);
property->SetPixelRepresentation(PixelRepresentation); property->SetPixelRepresentation(PixelRepresentation);
} }
if (headerList.size()>1){ else{
printf( " file:%s load error!\r\b", header.FilePath.c_str() );
property->Delete();
return nullptr;
}
if (splitIndex-beginOffset>1){
const DICOMFileHeader& header2 = headerList[beginOffset+1]; const DICOMFileHeader& header2 = headerList[beginOffset+1];
double spacing2 = sqrt(vtkMath::Distance2BetweenPoints(header.Position,header2.Position)); double spacing2 = sqrt(vtkMath::Distance2BetweenPoints(header.Position,header2.Position));
property->SetSpacing(property->GetSpacing()[0],property->GetSpacing()[1],spacing2); property->SetSpacing(property->GetSpacing()[0],property->GetSpacing()[1],spacing2);

View File

@@ -14,12 +14,13 @@ class ExtendMedicalImageProperties;
struct DICOMFileHeader { struct DICOMFileHeader {
std::string FilePath; std::string FilePath;
std::string SeriesUID;
long SeriesNumber = 0; long SeriesNumber = 0;
long AcquisitionNumber = 0; long AcquisitionNumber = 0;
long InstanceNumber = 0; long InstanceNumber = 0;
double Spacing[2] = {1., 1.}; double Spacing[2] = {1., 1.};
long Rows; unsigned short Rows;
long Columns; unsigned short Columns;
unsigned short SamplePerPixel; unsigned short SamplePerPixel;
double WindowCenter = 0; double WindowCenter = 0;
double WindowWidth = 0; double WindowWidth = 0;
@@ -52,11 +53,11 @@ typedef std::vector<DICOMFileHeader> DICOMFileList;
typedef std::unordered_map<std::string, DICOMFileMap> SeriesMap; typedef std::unordered_map<std::string, DICOMFileMap> SeriesMap;
typedef std::unordered_map<std::string, DICOMFileList> SeriesFileMap; typedef std::unordered_map<std::string, DICOMFileList> SeriesFileMap;
class DICOMDirectoryHelper { class DICOMHeaderHelper {
public: public:
DICOMDirectoryHelper() = default; DICOMHeaderHelper() = default;
~DICOMDirectoryHelper() { ~DICOMHeaderHelper() {
Clear(); Clear();
} }

View File

@@ -0,0 +1,166 @@
//
// Created by Krad on 2022/9/9.
//
#include "DICOMPixelDataHelper.h"
#include <dcmtk/dcmdata/dcrledrg.h>
#include <dcmtk/dcmjpeg/djdecode.h>
#include <dcmtk/dcmjpls/djdecode.h>
#include <dcmtk/dcmdata/dcfilefo.h>
#include <dcmtk/dcmimgle/dcmimage.h>
#include <dcmtk/dcmimgle/dipixel.h>
#include "ExtendMedicalImageProperties.h"
#ifdef OPENJPEG
#include "openjpeg-2.3/openjpeg.h"
#endif
void DICOMPixelDataHelper::InitCodecs() {
DcmRLEDecoderRegistration::registerCodecs(OFFalse, OFTrue);//注册解码器
/// register JPEG decompression codecs
DJDecoderRegistration::registerCodecs();//注册解码器
DJLSDecoderRegistration::registerCodecs();
#ifdef OPENJPEG
FMJPEG2KDecoderRegistration::registerCodecs();//jpeg2000
#endif
}
void DICOMPixelDataHelper::FinalizeCodecs() {
DcmRLEDecoderRegistration::cleanup();
DJDecoderRegistration::cleanup();
DJLSDecoderRegistration::cleanup();
#ifdef OPENJPEG
FMJPEG2KDecoderRegistration::cleanup();
#endif
}
void DICOMPixelDataHelper::GetThumbnailData(ExtendMedicalImageProperties *property, unsigned char* data,
unsigned long& length) {
double *wlww = property->GetNthWindowLevelPreset(0);
int ww = wlww ? ((int) wlww[0]) : (512);
int wl = wlww ? ((int) wlww[1]) : (256);
int sample = property->GetSamplePerPixel();
DcmFileFormat *fileFormat = new DcmFileFormat();//读取文件获取传输语法
if (fileFormat->loadFile(property->GetThumbnailFileName()).good()) {
DcmDataset *dset = fileFormat->getDataset();
DicomImage dcmImage(fileFormat, dset->getOriginalXfer(), CIF_MayDetachPixelData);
DicomImage *sdcmImage = dcmImage.createScaledImage(100.0, 0.0, 0, 1);
sdcmImage->setWindow(wl, ww);
sdcmImage->showAllOverlays();
length = sdcmImage->getOutputDataSize(8);
unsigned char *outputData = (unsigned char *) sdcmImage->getOutputData(8);//按8位的位宽取数据
data = new unsigned char[length];
memcpy(data, outputData, length);
delete sdcmImage;
}
delete fileFormat;
}
void DICOMPixelDataHelper::GetPixelData(const char * path, void *data, unsigned long& length) {
DcmFileFormat *fileFormat = new DcmFileFormat();//读取文件获取传输语法
if (fileFormat->loadFile(path).good()) {
DcmDataset *dset = fileFormat->getDataset();
DicomImage* dcmImage = new DicomImage(fileFormat, dset->getOriginalXfer(),CIF_MayDetachPixelData);
const DiPixel* pixelData = dcmImage->getInterData();//rescaled
unsigned long dataBits = 1;
switch (pixelData->getRepresentation()){
case EPR_Uint8:
case EPR_Sint8:
break;
case EPR_Uint16:
case EPR_Sint16:
dataBits = 2;
break;
case EPR_Uint32:
case EPR_Sint32:
dataBits = 4;
break;
}
const void * dd = pixelData->getData();
length = pixelData->getCount() ;
length = length*dataBits;
memcpy(data,dd, length);
delete dcmImage;
} else{
length=-1;
}
delete fileFormat;
}
template<class T>
void convertAndRescale(const void* input, void* output, double slope, double intercept, unsigned long length)
{
const T* in = static_cast<const T*>(input);
float* out = static_cast<float*>(output);
for (int i = 0; i <length ; ++i) {
*(out++) = static_cast<float>(static_cast<double>(*(in++))*slope+intercept);
}
}
void* DICOMPixelDataHelper::GetPixelDataFloat(const char *path, unsigned long &length) {
void* data = nullptr;
DcmFileFormat *fileFormat = new DcmFileFormat();
if (fileFormat->loadFile(path).good()) {
DcmDataset *dataset = fileFormat->getDataset();
DicomImage dcmImage(fileFormat, dataset->getOriginalXfer(), CIF_IgnoreModalityTransformation);
const DiPixel* pixelData = dcmImage.getInterData();//no rescaled
length = pixelData->getCount();
const void* pData = pixelData->getData();
data = new float [length];
double slope= 1.0;
dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x1053), slope);
double intercept= 0.0;
dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x1052), intercept);
switch (pixelData->getRepresentation()){
case EPR_Uint8:
convertAndRescale<Uint8>(pData,data,slope,intercept,length);
break;
case EPR_Sint8:
convertAndRescale<Sint8>(pData,data,slope,intercept,length);
break;
case EPR_Uint16:
convertAndRescale<Uint16>(pData,data,slope,intercept,length);
break;
case EPR_Sint16:
convertAndRescale<Sint16>(pData,data,slope,intercept,length);
break;
case EPR_Uint32:
convertAndRescale<Uint32>(pData,data,slope,intercept,length);
break;
case EPR_Sint32:
convertAndRescale<Sint32>(pData,data,slope,intercept,length);
break;
}
} else{
length=-1;
}
delete fileFormat;
return data;
}
void DICOMPixelDataHelper::GetOverlayData(const char *path, void *data,
unsigned int& width, unsigned int& height, unsigned int plane) {
DcmFileFormat *fileFormat = new DcmFileFormat();//读取文件获取传输语法
if (fileFormat->loadFile(path).good()) {
DcmDataset *dset = fileFormat->getDataset();
DicomImage dcmImage(fileFormat, dset->getOriginalXfer(), CIF_MayDetachPixelData);
if(dcmImage.getOverlayCount()>plane){
const void * overlay = dcmImage.getFullOverlayData(plane,width, height);
int dataLength = width*height;
data = new unsigned char[dataLength];
memcpy(data, overlay,dataLength);
}
else{
width=-1;
height=-1;
}
}
else{
width=-1;
height=-1;
}
delete fileFormat;
}

View File

@@ -0,0 +1,29 @@
//
// Created by Krad on 2022/9/9.
//
#ifndef OMEGAV_DICOMPIXELDATAHELPER_H
#define OMEGAV_DICOMPIXELDATAHELPER_H
class ExtendMedicalImageProperties;
class DICOMPixelDataHelper {
public:
DICOMPixelDataHelper() = default;
~DICOMPixelDataHelper() {
}
static void GetThumbnailData(ExtendMedicalImageProperties *property, unsigned char* data,
unsigned long& length);
static void GetPixelData(const char * path, void* data,unsigned long& length);
static void* GetPixelDataFloat(const char * path,unsigned long& length);
static void GetOverlayData(const char * path, void* data,
unsigned int& width, unsigned int& height,unsigned int plane = 0);
static void InitCodecs();
static void FinalizeCodecs();
};
#endif //OMEGAV_DICOMPIXELDATAHELPER_H

View File

@@ -1,7 +1,7 @@
#include "DicomLoader.h" #include "DicomLoader.h"
#include "Common/SeriesImageSet.h" #include "Common/SeriesImageSet.h"
#include "DICOMDirectoryHelper.h" #include "DICOMHeaderHelper.h"
#include "ExtendMedicalImageProperties.h" #include "ExtendMedicalImageProperties.h"
#include "vtkDICOMImageReader2.h" #include "vtkDICOMImageReader2.h"
#include "vtkImageData.h" #include "vtkImageData.h"
@@ -131,7 +131,8 @@ SeriesImageSet* DicomLoader::getSeriesImageSet(const std::string& uniqueID)//, D
}); });
if (iter==imageProperties.end()) return nullptr; if (iter==imageProperties.end()) return nullptr;
reader->SetFileNames((*iter)->GetFileNames()); // reader->SetFileNames((*iter)->GetFileNames());
reader->SetImageProperties((*iter));
reader->Update(); reader->Update();
auto imageData = reader->GetOutput(); auto imageData = reader->GetOutput();
SeriesImageSet* result = new SeriesImageSet((*iter),imageData); SeriesImageSet* result = new SeriesImageSet((*iter),imageData);
@@ -145,7 +146,7 @@ SeriesImageSet* DicomLoader::getSeriesImageSet(const std::string& uniqueID)//, D
void DicomLoader::readTags(const std::string &dir, SeriesOpenMode openMode) void DicomLoader::readTags(const std::string &dir, SeriesOpenMode openMode)
{ {
DICOMDirectoryHelper DICOMHelper; DICOMHeaderHelper DICOMHelper;
if (openMode == FILE_OPEN_MODE) if (openMode == FILE_OPEN_MODE)
{ {
//m_itkSeriesReader->SetFileName(m_dicomName.toStdString()); //m_itkSeriesReader->SetFileName(m_dicomName.toStdString());

View File

@@ -19,7 +19,7 @@ public:
class SeriesImageSet; class SeriesImageSet;
class DICOMDirectoryHelper; class DICOMHeaderHelper;
class ExtendMedicalImageProperties; class ExtendMedicalImageProperties;
class vtkDICOMImageReader2; class vtkDICOMImageReader2;
typedef std::map<std::string, SeriesImageSet*> ImageSetStore; typedef std::map<std::string, SeriesImageSet*> ImageSetStore;

View File

@@ -85,7 +85,7 @@ public:
const char* GetThumbnailFileName(){ const char* GetThumbnailFileName(){
if (FileNames.empty()) return nullptr; if (FileNames.empty()) return nullptr;
return FileNames[FileNames.size()/2].data(); return FileNames[0].data();
} }
unsigned long long GetSliceCount(){ unsigned long long GetSliceCount(){
return FileNames.size(); return FileNames.size();

View File

@@ -9,13 +9,10 @@
#include "vtkObjectFactory.h" #include "vtkObjectFactory.h"
#include "vtkPointData.h" #include "vtkPointData.h"
#include "DICOMAppHelper.h" #include "IO/DICOM/DICOMPixelDataHelper.h"
#include "DICOMParser.h"
vtkStandardNewMacro(vtkDICOMImageReader2); vtkStandardNewMacro(vtkDICOMImageReader2);
vtkDICOMImageReader2::vtkDICOMImageReader2():vtkDICOMImageReader() { vtkDICOMImageReader2::vtkDICOMImageReader2():vtkDICOMImageReader() {
} }
@@ -80,124 +77,51 @@ void vtkDICOMImageReader2::ExecuteInformation() {
} }
void vtkDICOMImageReader2::ExecuteDataWithInformation(vtkDataObject *output, void vtkDICOMImageReader2::ExecuteDataWithInformation(vtkDataObject *output,
vtkInformation *outInfo) vtkInformation *outInfo) {
{
vtkImageData *data = this->AllocateOutputData(output, outInfo); vtkImageData *data = this->AllocateOutputData(output, outInfo);
if (!properties) {
if (!properties) vtkErrorMacro(<< "No image properties set for the reader.");
{ this->SetErrorCode(vtkErrorCode::FileNotFoundError);
vtkErrorMacro( << "No image properties set for the reader.");
this->SetErrorCode( vtkErrorCode::FileNotFoundError );
return; return;
} }
data->GetPointData()->GetScalars()->SetName("DICOMImage"); data->GetPointData()->GetScalars()->SetName("DICOMImage");
this->ComputeDataIncrements(); this->ComputeDataIncrements();
void *buffer = data->GetScalarPointer();
if (this->FileName) if (buffer == nullptr) {
{ vtkErrorMacro(<< "No memory allocated for image data!");
vtkDebugMacro( << "Single file : " << this->FileName); return;
this->Parser->ClearAllDICOMTagCallbacks();
this->Parser->OpenFile(this->FileName);
this->AppHelper->Clear();
this->AppHelper->RegisterCallbacks(this->Parser);
this->AppHelper->RegisterPixelDataCallback(this->Parser);
this->Parser->ReadHeader();
void* imgData = nullptr;
DICOMParser::VRTypes dataType;
unsigned long imageDataLength;
this->AppHelper->GetImageData(imgData, dataType, imageDataLength);
if( !imageDataLength )
{
vtkErrorMacro( << "There was a problem retrieving data from: " << this->FileName );
this->SetErrorCode( vtkErrorCode::FileFormatError );
return;
}
void* buffer = data->GetScalarPointer();
if (buffer == nullptr)
{
vtkErrorMacro(<< "No memory allocated for image data!");
return;
}
// DICOM stores the upper left pixel as the first pixel in an
// image. VTK stores the lower left pixel as the first pixel in
// an image. Need to flip the data.
vtkIdType rowLength;
rowLength = this->DataIncrements[1];
unsigned char *b = (unsigned char *)buffer;
unsigned char *iData = (unsigned char *)imgData;
memcpy(b,imgData,imageDataLength);
// iData += (imageDataLength - rowLength); // beginning of last row
// for (int i=0; i < this->AppHelper->GetHeight(); ++i)
// {
// memcpy(b, iData, rowLength);
// b += rowLength;
// iData -= rowLength;
// }
} }
else if (!this->DICOMFileNames->empty()) for (int i = 0; i < properties->GetFileNames().size(); ++i) {
{ const std::string& path = properties->GetFileNames()[i];
vtkDebugMacro( << "Multiple files (" << static_cast<int>(this->DICOMFileNames->size()) << ")"); if (this->DataScalarType == VTK_FLOAT)
this->Parser->ClearAllDICOMTagCallbacks();
this->AppHelper->Clear();
this->AppHelper->RegisterCallbacks(this->Parser);
this->AppHelper->RegisterPixelDataCallback(this->Parser);
void* buffer = data->GetScalarPointer();
if (buffer == nullptr)
{ {
vtkErrorMacro(<< "No memory allocated for image data!"); void *imgData = nullptr;
return;
}
std::vector<std::string>::iterator fiter; unsigned long imageDataLength;
int count = 0; imgData = DICOMPixelDataHelper::GetPixelDataFloat(path.c_str(),imageDataLength);
vtkIdType numFiles = static_cast<int>(this->DICOMFileNames->size()); if(imgData){
//calc size of float
for (fiter = this->DICOMFileNames->begin(); imageDataLength = imageDataLength * sizeof(float);
fiter != this->DICOMFileNames->end(); unsigned char *b = (unsigned char *) buffer;
++fiter) unsigned char *iData = (unsigned char *) imgData;
{ memcpy(b, imgData, imageDataLength);
count++; buffer = ((char*) buffer) + imageDataLength;
const char *file = fiter->c_str(); }
vtkDebugMacro( << "File : " << file ); else{
this->Parser->OpenFile( file ); vtkErrorMacro(<< "Can't read data from path:"<<path.c_str()<<"!");
this->Parser->ReadHeader();
void* imgData = nullptr;
DICOMParser::VRTypes dataType;
unsigned long imageDataLengthInBytes;
this->AppHelper->GetImageData(imgData, dataType, imageDataLengthInBytes);
if( !imageDataLengthInBytes )
{
vtkErrorMacro( << "There was a problem retrieving data from: " << file );
this->SetErrorCode( vtkErrorCode::FileFormatError );
return; return;
} }
}
else{
void *imgData = nullptr;
// DICOM stores the upper left pixel as the first pixel in an unsigned long imageDataLength;
// image. VTK stores the lower left pixel as the first pixel in unsigned char *b = (unsigned char *) buffer;
// an image. Need to flip the data. DICOMPixelDataHelper::GetPixelData(path.c_str(), buffer,imageDataLength);
vtkIdType rowLength; buffer = ((char*) buffer) + imageDataLength;
rowLength = this->DataIncrements[1];
unsigned char *b = (unsigned char *)buffer;
unsigned char *iData = (unsigned char *)imgData;
memcpy(b,imgData,imageDataLengthInBytes);
buffer = ((char*) buffer) + imageDataLengthInBytes;
this->UpdateProgress(float(count)/float(numFiles));
int len = static_cast<int> (strlen((const char*) (*fiter).c_str()));
char* filename = new char[len+1];
strcpy(filename, (const char*) (*fiter).c_str());
this->SetProgressText(filename);
delete[] filename;
} }
} }
} }
@@ -210,10 +134,6 @@ double* vtkDICOMImageReader2::GetPixelSpacing()
void vtkDICOMImageReader2::SetFileNames(const std::vector<std::string>& files) { void vtkDICOMImageReader2::SetFileNames(const std::vector<std::string>& files) {
this->DICOMFileNames->clear(); this->DICOMFileNames->clear();
this->AppHelper->Clear();
this->DirectoryName = nullptr;
this->FileName = nullptr;
for (vtkIdType i = 0; i < files.size(); i++) for (vtkIdType i = 0; i < files.size(); i++)
{ {
if (strcmp(files[i].c_str(), ".") == 0 || if (strcmp(files[i].c_str(), ".") == 0 ||
@@ -223,18 +143,7 @@ void vtkDICOMImageReader2::SetFileNames(const std::vector<std::string>& files) {
} }
std::string fileString = files[i]; std::string fileString = files[i];
vtkDebugMacro( << "Adding " << fileString.c_str() << " to DICOMFileNames.");
int val = this->CanReadFile(fileString.c_str()); this->DICOMFileNames->push_back(fileString);
if (val == 1)
{
vtkDebugMacro( << "Adding " << fileString.c_str() << " to DICOMFileNames.");
this->DICOMFileNames->push_back(fileString);
}
else
{
vtkDebugMacro( << fileString.c_str() << " - DICOMParser CanReadFile returned : " << val);
}
} }
} }