Fix pixel data read logic.

This commit is contained in:
Krad
2022-09-14 14:03:24 +08:00
parent 2b919ec011
commit a92a3c2016
4 changed files with 90 additions and 57 deletions

View File

@@ -61,10 +61,10 @@ void DICOMPixelDataHelper::GetPixelData(const char * path, void *data, unsigned
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
DicomImage dcmImage(fileFormat, dset->getOriginalXfer(), CIF_MayDetachPixelData);
const DiPixel *pixelData = dcmImage.getInterData();//rescaled
unsigned long dataBits = 1;
switch (pixelData->getRepresentation()){
switch (pixelData->getRepresentation()) {
case EPR_Uint8:
case EPR_Sint8:
break;
@@ -77,12 +77,10 @@ void DICOMPixelDataHelper::GetPixelData(const char * path, void *data, unsigned
dataBits = 4;
break;
}
const void * dd = pixelData->getData();
length = pixelData->getCount() ;
length = length*dataBits;
memcpy(data,dd, length);
delete dcmImage;
const void *dd = pixelData->getData();
length = pixelData->getCount();
length = length * dataBits;
memcpy(data, dd, length);
} else{
length=-1;
}
@@ -100,8 +98,8 @@ void convertAndRescale(const void* input, void* output, double slope, double int
}
void* DICOMPixelDataHelper::GetPixelDataFloat(const char *path, unsigned long &length) {
void* data = nullptr;
void DICOMPixelDataHelper::GetPixelDataFloat(const char *path, void *data, unsigned long &length) {
void* temp = nullptr;
DcmFileFormat *fileFormat = new DcmFileFormat();
if (fileFormat->loadFile(path).good()) {
DcmDataset *dataset = fileFormat->getDataset();
@@ -109,36 +107,51 @@ void* DICOMPixelDataHelper::GetPixelDataFloat(const char *path, unsigned long &l
const DiPixel* pixelData = dcmImage.getInterData();//no rescaled
length = pixelData->getCount();
const void* pData = pixelData->getData();
data = new float [length];
double slope= 1.0;
double slope = 1.0;
dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x1053), slope);
double intercept= 0.0;
double intercept = 0.0;
dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x1052), intercept);
switch (pixelData->getRepresentation()){
case EPR_Uint8:
convertAndRescale<Uint8>(pData,data,slope,intercept,length);
convertAndRescale<Uint8>(pData, data, slope, intercept, length);
break;
case EPR_Sint8:
convertAndRescale<Sint8>(pData,data,slope,intercept,length);
convertAndRescale<Sint8>(pData, data, slope, intercept, length);
break;
case EPR_Uint16:
convertAndRescale<Uint16>(pData,data,slope,intercept,length);
convertAndRescale<Uint16>(pData, data, slope, intercept, length);
break;
case EPR_Sint16:
convertAndRescale<Sint16>(pData,data,slope,intercept,length);
convertAndRescale<Sint16>(pData, data, slope, intercept, length);
break;
case EPR_Uint32:
convertAndRescale<Uint32>(pData,data,slope,intercept,length);
convertAndRescale<Uint32>(pData, data, slope, intercept, length);
break;
case EPR_Sint32:
convertAndRescale<Sint32>(pData,data,slope,intercept,length);
convertAndRescale<Sint32>(pData, data, slope, intercept, length);
break;
}
length = length * sizeof(float);
} else{
length=-1;
}
delete fileFormat;
}
void DICOMPixelDataHelper::GetRGBPixelData(const char *path, void *data, unsigned long &length) {
DcmFileFormat *fileFormat = new DcmFileFormat();//读取文件获取传输语法
if (fileFormat->loadFile(path).good()) {
DcmDataset *dset = fileFormat->getDataset();
DicomImage dcmImage(fileFormat, dset->getOriginalXfer(), CIF_MayDetachPixelData);
dcmImage.hideAllOverlays();
length = dcmImage.getOutputDataSize(8);
const void *dd = dcmImage.getOutputData(8);
memcpy(data, dd, length);
dcmImage.deleteOutputData();
} else{
length=-1;
}
delete fileFormat;
return data;
}
void DICOMPixelDataHelper::GetOverlayData(const char *path, void *data,

View File

@@ -7,6 +7,9 @@
class ExtendMedicalImageProperties;
/**
* DICOM file Pixel Data read helper
*/
class DICOMPixelDataHelper {
public:
DICOMPixelDataHelper() = default;
@@ -15,13 +18,42 @@ public:
}
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);
/**
* Get Pixel Data with Rescaled, result is calculate as integer, and arrange as integer.
* @param path dcm file absolute path
* @param data output data buffer pointer
* @param length output data length
*/
static void GetPixelData(const char * path, void* data, unsigned long& length);
/**
* Get Pixel Data with Rescaled, result is calculate as Float, and arrange as Float.
* @param path dcm file absolute path
* @param data output data buffer pointer
* @param length output data length
*/
static void GetPixelDataFloat(const char * path, void* data, unsigned long& length);
/**
* Get colorful Pixel Data as three component R,G,B color value.
* @param path dcm file absolute path
* @param data output data buffer pointer
* @param length output data length
*/
static void GetRGBPixelData(const char * path, void* data, unsigned long& length);
static void GetOverlayData(const char * path, void* data,
unsigned int& width, unsigned int& height,unsigned int plane = 0);
/**
* Init decompress Codecs, must be called before other method.
*/
static void InitCodecs();
/**
* Finalize decompress Codecs, must be called after other method have done.
*/
static void FinalizeCodecs();
};

View File

@@ -98,11 +98,3 @@ void ExtendMedicalImageProperties::GenerateUniqueID() {
this->SetUniqueID(uniqueID.c_str());
}
bool ExtendMedicalImageProperties::RescaledImageDataIsUnsignedChar() {
bool charData = BitsAllocated == 8;
bool noScale = ((int)(this->RescaleOffset) == 0) && ((int)(this->RescaleSlope) == 1);
bool unSign = (this->PixelRepresentation == 0);
bool color = SamplePerPixel == 3;
return (color || (charData && unSign && noScale));
}

View File

@@ -93,37 +93,33 @@ void vtkDICOMImageReader2::ExecuteDataWithInformation(vtkDataObject *output,
vtkErrorMacro(<< "No memory allocated for image data!");
return;
}
// init codes to support compressed file
DICOMPixelDataHelper::InitCodecs();
for (int i = 0; i < properties->GetFileNames().size(); ++i) {
const std::string& path = properties->GetFileNames()[i];
if (this->DataScalarType == VTK_FLOAT)
{
void *imgData = nullptr;
const std::string &path = properties->GetFileNames()[i];
unsigned long imageDataLength;
unsigned long imageDataLength;
if (this->DataScalarType == VTK_FLOAT) {
DICOMPixelDataHelper::GetPixelDataFloat(path.c_str(), buffer, imageDataLength);
} else if (NumberOfScalarComponents > 1) {
DICOMPixelDataHelper::GetRGBPixelData(path.c_str(), buffer, imageDataLength);
} else {
DICOMPixelDataHelper::GetPixelData(path.c_str(), buffer, imageDataLength);
imgData = DICOMPixelDataHelper::GetPixelDataFloat(path.c_str(),imageDataLength);
if(imgData){
//calc size of float
imageDataLength = imageDataLength * sizeof(float);
unsigned char *b = (unsigned char *) buffer;
unsigned char *iData = (unsigned char *) imgData;
memcpy(b, imgData, imageDataLength);
buffer = ((char*) buffer) + imageDataLength;
}
else{
vtkErrorMacro(<< "Can't read data from path:"<<path.c_str()<<"!");
return;
}
}
else{
void *imgData = nullptr;
unsigned long imageDataLength;
unsigned char *b = (unsigned char *) buffer;
DICOMPixelDataHelper::GetPixelData(path.c_str(), buffer,imageDataLength);
buffer = ((char*) buffer) + imageDataLength;
}
buffer = ((char *) buffer) + imageDataLength;
}
// finalize codecs
DICOMPixelDataHelper::FinalizeCodecs();
}
double* vtkDICOMImageReader2::GetPixelSpacing()