diff --git a/src/src/base/vtkDICOMImageReader2.cpp b/src/src/base/vtkDICOMImageReader2.cpp index 33bde8a..0900355 100644 --- a/src/src/base/vtkDICOMImageReader2.cpp +++ b/src/src/base/vtkDICOMImageReader2.cpp @@ -2,13 +2,12 @@ // Created by Krad on 2022/2/8. // +#include #include "vtkDICOMImageReader2.h" #include "vtkDataArray.h" #include "vtkImageData.h" #include "vtkObjectFactory.h" - - - +#include "vtkPointData.h" #include "DICOMAppHelper.h" #include "DICOMParser.h" @@ -25,6 +24,51 @@ vtkDICOMImageReader2::~vtkDICOMImageReader2() { } +//---------------------------------------------------------------------------- +void vtkDICOMImageReader2::SetupOutputInformation(int num_slices) +{ + int width = this->AppHelper->GetWidth(); + int height = this->AppHelper->GetHeight(); + int bit_depth = this->AppHelper->GetBitsAllocated(); + int num_comp = this->AppHelper->GetNumberOfComponents(); + + this->DataExtent[0] = 0; + this->DataExtent[1] = width - 1; + this->DataExtent[2] = 0; + this->DataExtent[3] = height - 1; + this->DataExtent[4] = 0; + this->DataExtent[5] = num_slices - 1; + + bool isFloat = this->AppHelper->RescaledImageDataIsFloat(); + + bool sign = this->AppHelper->RescaledImageDataIsSigned(); + + if (isFloat) + { + this->SetDataScalarTypeToFloat(); + } + else if (bit_depth <= 8) + { + this->SetDataScalarTypeToUnsignedChar(); + } + else + { + if (sign) + { + this->SetDataScalarTypeToShort(); + } + else + { + this->SetDataScalarTypeToUnsignedShort(); + } + } + this->SetNumberOfScalarComponents(num_comp); + + this->GetPixelSpacing(); + + this->vtkImageReader2::ExecuteInformation(); +} + void vtkDICOMImageReader2::ExecuteInformation() { vtkDICOMImageReader::ExecuteInformation(); if (!this->DirectoryName && !this->FileName && !DICOMFileNames->empty()){ @@ -81,6 +125,155 @@ void vtkDICOMImageReader2::ExecuteInformation() { } } +void vtkDICOMImageReader2::ExecuteDataWithInformation(vtkDataObject *output, + vtkInformation *outInfo) +{ + vtkImageData *data = this->AllocateOutputData(output, outInfo); + + if (!this->FileName && this->DICOMFileNames->empty()) + { + vtkErrorMacro( << "Either a filename was not specified or the specified directory does not contain any DICOM images."); + this->SetErrorCode( vtkErrorCode::NoFileNameError ); + return; + } + + data->GetPointData()->GetScalars()->SetName("DICOMImage"); + + this->ComputeDataIncrements(); + + if (this->FileName) + { + vtkDebugMacro( << "Single file : " << this->FileName); + 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()) + { + vtkDebugMacro( << "Multiple files (" << static_cast(this->DICOMFileNames->size()) << ")"); + 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!"); + return; + } + + std::vector::iterator fiter; + + int count = 0; + vtkIdType numFiles = static_cast(this->DICOMFileNames->size()); + + for (fiter = this->DICOMFileNames->begin(); + fiter != this->DICOMFileNames->end(); + ++fiter) + { + count++; + const char *file = fiter->c_str(); + vtkDebugMacro( << "File : " << file ); + this->Parser->OpenFile( file ); + 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; + } + + // 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,imageDataLengthInBytes); + buffer = ((char*) buffer) + imageDataLengthInBytes; + + this->UpdateProgress(float(count)/float(numFiles)); + int len = static_cast (strlen((const char*) (*fiter).c_str())); + char* filename = new char[len+1]; + strcpy(filename, (const char*) (*fiter).c_str()); + this->SetProgressText(filename); + delete[] filename; + } + } +} + +//避免z轴被强行设置成正增长 +double* vtkDICOMImageReader2::GetPixelSpacing() +{ + std::vector > sortedFiles; + + this->AppHelper->GetImagePositionPatientFilenamePairs(sortedFiles, false); + + float* spacing = this->AppHelper->GetPixelSpacing(); + this->DataSpacing[0] = spacing[0]; + this->DataSpacing[1] = spacing[1]; + + if (sortedFiles.size() > 1) + { + std::pair p1 = sortedFiles[0]; + std::pair p2 = sortedFiles[1]; + this->DataSpacing[2] = (p1.first - p2.first); +// this->DataSpacing[2] = fabs(p1.first - p2.first); + } + else + { + this->DataSpacing[2] = spacing[2]; + } + + return this->DataSpacing; +} + void vtkDICOMImageReader2::SetFileNames(const std::vector& files) { this->DICOMFileNames->clear(); diff --git a/src/src/base/vtkDICOMImageReader2.h b/src/src/base/vtkDICOMImageReader2.h index c285a19..21bb441 100644 --- a/src/src/base/vtkDICOMImageReader2.h +++ b/src/src/base/vtkDICOMImageReader2.h @@ -28,10 +28,13 @@ public: vtkDICOMImageReaderVector* GetDICOMFileNames(){ return DICOMFileNames; } + double* GetPixelSpacing(); protected: - + void SetupOutputInformation(int num_slices); void ExecuteInformation() override; + void vtkDICOMImageReader2::ExecuteDataWithInformation(vtkDataObject *output, + vtkInformation *outInfo) override ; // // Constructor