Change Reader, reset image pixel data order,change spacing[2] can be negative
This commit is contained in:
@@ -2,13 +2,12 @@
|
|||||||
// Created by Krad on 2022/2/8.
|
// Created by Krad on 2022/2/8.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <vtkErrorCode.h>
|
||||||
#include "vtkDICOMImageReader2.h"
|
#include "vtkDICOMImageReader2.h"
|
||||||
#include "vtkDataArray.h"
|
#include "vtkDataArray.h"
|
||||||
#include "vtkImageData.h"
|
#include "vtkImageData.h"
|
||||||
#include "vtkObjectFactory.h"
|
#include "vtkObjectFactory.h"
|
||||||
|
#include "vtkPointData.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "DICOMAppHelper.h"
|
#include "DICOMAppHelper.h"
|
||||||
#include "DICOMParser.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() {
|
void vtkDICOMImageReader2::ExecuteInformation() {
|
||||||
vtkDICOMImageReader::ExecuteInformation();
|
vtkDICOMImageReader::ExecuteInformation();
|
||||||
if (!this->DirectoryName && !this->FileName && !DICOMFileNames->empty()){
|
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<int>(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<std::string>::iterator fiter;
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
vtkIdType numFiles = static_cast<int>(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<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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//避免z轴被强行设置成正增长
|
||||||
|
double* vtkDICOMImageReader2::GetPixelSpacing()
|
||||||
|
{
|
||||||
|
std::vector<std::pair<float, std::string> > 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<float, std::string> p1 = sortedFiles[0];
|
||||||
|
std::pair<float, std::string> 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<std::string>& files) {
|
void vtkDICOMImageReader2::SetFileNames(const std::vector<std::string>& files) {
|
||||||
|
|
||||||
this->DICOMFileNames->clear();
|
this->DICOMFileNames->clear();
|
||||||
|
|||||||
@@ -28,10 +28,13 @@ public:
|
|||||||
vtkDICOMImageReaderVector* GetDICOMFileNames(){
|
vtkDICOMImageReaderVector* GetDICOMFileNames(){
|
||||||
return DICOMFileNames;
|
return DICOMFileNames;
|
||||||
}
|
}
|
||||||
|
double* GetPixelSpacing();
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
void SetupOutputInformation(int num_slices);
|
||||||
void ExecuteInformation() override;
|
void ExecuteInformation() override;
|
||||||
|
void vtkDICOMImageReader2::ExecuteDataWithInformation(vtkDataObject *output,
|
||||||
|
vtkInformation *outInfo) override ;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Constructor
|
// Constructor
|
||||||
|
|||||||
Reference in New Issue
Block a user