180 lines
7.0 KiB
C++
180 lines
7.0 KiB
C++
//
|
|
// Created by Krad on 2022/2/8.
|
|
//
|
|
|
|
#include "DICOMDirectoryHelper.h"
|
|
#include "dcmtk/dcmdata/dcfilefo.h"
|
|
#include "dcmtk/dcmdata/dcdatset.h"
|
|
#include "ExtendMedicalImageProperties.h"
|
|
#include <vtkDirectory.h>
|
|
#include <vtkNew.h>
|
|
#include <unordered_map>
|
|
#include <algorithm>
|
|
struct DICOMTag{
|
|
Uint16 group;
|
|
Uint16 element;
|
|
const char * des;
|
|
};
|
|
DICOMTag dicom_tags[] = {
|
|
{0x0002, 0x0002, "Media storage SOP class uid"},
|
|
{0x0002, 0x0003, "Media storage SOP inst uid"},
|
|
{0x0002, 0x0010, "Transfer syntax uid"},
|
|
{0x0002, 0x0012, "Implementation class uid"},
|
|
{0x0008, 0x0018, "Image UID"},
|
|
{0x0008, 0x0020, "Series date"},
|
|
{0x0008, 0x0030, "Series time"},
|
|
{0x0008, 0x0060, "Modality"},
|
|
{0x0008, 0x0070, "Manufacturer"},
|
|
{0x0008, 0x1060, "Physician"},
|
|
{0x0018, 0x0050, "slice thickness"},
|
|
{0x0018, 0x0060, "kV"},
|
|
{0x0018, 0x0088, "slice spacing"},
|
|
{0x0018, 0x1100, "Recon diameter"},
|
|
{0x0018, 0x1151, "mA"},
|
|
{0x0018, 0x1210, "Recon kernel"},
|
|
{0x0020, 0x000d, "Study UID"},
|
|
{0x0020, 0x000e, "Series UID"},
|
|
{0x0020, 0x0013, "Image number"},
|
|
{0x0020, 0x0032, "Patient position"},
|
|
{0x0020, 0x0037, "Patient position cosines"},
|
|
{0x0020, 0x1041, "Slice location"},
|
|
{0x0028, 0x0010, "Num rows"},
|
|
{0x0028, 0x0011, "Num cols"},
|
|
{0x0028, 0x0030, "pixel spacing"},
|
|
{0x0028, 0x0100, "Bits allocated"},
|
|
{0x0028, 0x0120, "pixel padding"},
|
|
{0x0028, 0x1052, "pixel offset"}
|
|
};
|
|
|
|
void DICOMDirectoryHelper::getDirectoryProperties(const char * rootPath, DICOMFileMap& result){
|
|
vtkNew<vtkDirectory> dir;
|
|
dir->Open(rootPath);
|
|
vtkIdType fileCount = dir->GetNumberOfFiles();
|
|
for (vtkIdType i = 0; i < fileCount; ++i) {
|
|
const char* file_path = dir->GetFile(i);
|
|
if (strcmp(".",file_path)==0 || strcmp("..",file_path)==0 ) continue;
|
|
std::string path(rootPath);
|
|
path.append("\\");
|
|
path.append(file_path);
|
|
std::cout<<"file path:"<<path<<std::endl;
|
|
|
|
if (dir->FileIsDirectory(path.c_str()))
|
|
{
|
|
getDirectoryProperties(path.c_str(), result);
|
|
}
|
|
else {
|
|
getFileProperty(path, result);
|
|
}
|
|
}
|
|
}
|
|
|
|
void DICOMDirectoryHelper::getFileProperty(const std::string &path, DICOMFileMap& result) {
|
|
DcmFileFormat file;
|
|
if (file.loadFile(path).good()) {
|
|
DcmDataset *dataset = file.getDataset();
|
|
std::string SeriesUID;
|
|
dataset->findAndGetOFString(DcmTagKey(0x0020, 0x000e), SeriesUID);
|
|
long SeriesNumber = 0;
|
|
dataset->findAndGetSint32(DcmTagKey(0x0020, 0x0011), SeriesNumber);
|
|
long AcquisitionNumber = 0;
|
|
dataset->findAndGetSint32(DcmTagKey(0x0020, 0x0012), AcquisitionNumber);
|
|
long InstanceNumber = 0;
|
|
dataset->findAndGetSint32(DcmTagKey(0x0020, 0x0013), InstanceNumber);
|
|
if (!result.count(SeriesUID)) {
|
|
ExtendMedicalImageProperties *seriesProperty = ExtendMedicalImageProperties::New();
|
|
|
|
#define ReadTAGToProperty(Name, group, element)\
|
|
std::string Name;\
|
|
dataset->findAndGetOFString(DcmTagKey(group, element), Name);\
|
|
seriesProperty->Set##Name(Name.c_str());
|
|
|
|
ReadTAGToProperty(PatientID, 0x0010, 0x0020);
|
|
ReadTAGToProperty(PatientName, 0x0010, 0x0010);
|
|
ReadTAGToProperty(PatientBirthDate, 0x0010, 0x0030);
|
|
ReadTAGToProperty(PatientSex, 0x0010, 0x0040);
|
|
ReadTAGToProperty(StudyDate, 0x0008, 0x0020);
|
|
ReadTAGToProperty(StudyTime, 0x0008, 0x0030);
|
|
ReadTAGToProperty(Modality, 0x0008, 0x0060);
|
|
ReadTAGToProperty(InstitutionName, 0x0008, 0x0080);
|
|
ReadTAGToProperty(StudyDescription, 0x0008, 0x1030);
|
|
ReadTAGToProperty(SeriesDescription, 0x0008, 0x103E);
|
|
ReadTAGToProperty(StudyUID, 0x0020, 0x000d);
|
|
ReadTAGToProperty(StudyID, 0x0020, 0x0010);
|
|
seriesProperty->SetSeriesUID(SeriesUID.c_str());
|
|
seriesProperty->SetSeriesNumber(SeriesNumber);
|
|
double WindowCenter = 0.0;
|
|
dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x1050), WindowCenter);
|
|
double WindowWidth = 0.0;
|
|
dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x1051), WindowWidth);
|
|
seriesProperty->AddWindowLevelPreset(WindowWidth, WindowCenter);
|
|
|
|
double Spacing[2] = {0.0,0.0};
|
|
dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x0030), Spacing[0], 0);
|
|
dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x0030), Spacing[1], 1);
|
|
seriesProperty->SetSpacing(Spacing);
|
|
|
|
seriesProperties.push_back(seriesProperty);
|
|
//暂时不考虑acqnumber的影响
|
|
//seriesProperty->SetAcquisitionNumber(AcquisitionNumber);
|
|
}
|
|
char buffer[256] = {0};
|
|
sprintf(buffer, "%ld-%ld", AcquisitionNumber, InstanceNumber);
|
|
printf("%s\r\n", path.c_str());
|
|
result[SeriesUID][buffer] = {std::move(path), SeriesNumber, AcquisitionNumber, InstanceNumber};
|
|
}
|
|
}
|
|
|
|
void DICOMDirectoryHelper::Update() {
|
|
|
|
std::unordered_map<std::string, std::unordered_map<std::string,DICOMFileRefValue>> series;
|
|
if (!this->dirName.empty()){
|
|
getDirectoryProperties(this->dirName.c_str(), series);
|
|
}
|
|
else{
|
|
getFileProperty(this->fileName.c_str(), series);
|
|
}
|
|
//sort files
|
|
for (auto &pair : series) {
|
|
auto iterator = std::find_if(seriesProperties.begin(),seriesProperties.end(),
|
|
[=](ExtendMedicalImageProperties* val){
|
|
return strcmp(val->GetSeriesUID(), pair.first.c_str()) == 0;
|
|
}
|
|
);
|
|
if (iterator < seriesProperties.end()){
|
|
auto files = (*iterator)->GetFileNames();
|
|
std::vector<DICOMFileRefValue> vector;
|
|
for (auto f : pair.second) {
|
|
// printf("%s\r\n",f.second.FilePath.c_str());
|
|
vector.emplace_back(std::move(f.second));
|
|
}
|
|
std::sort(vector.begin(), vector.end(), [](const DICOMFileRefValue &v1, const DICOMFileRefValue &v2) {
|
|
|
|
return v1.SeriesNumber != v2.SeriesNumber ? (v1.SeriesNumber < v2.SeriesNumber) :
|
|
(v1.AcquisitionNumber != v2.AcquisitionNumber ? (v1.AcquisitionNumber < v2.AcquisitionNumber) :
|
|
(v1.InstanceNumber < v2.InstanceNumber));
|
|
});
|
|
std::for_each(vector.begin(), vector.end(),[=](auto v){
|
|
// printf("%s\r\n",v.FilePath.c_str());
|
|
files->emplace_back(std::move(v.FilePath));
|
|
});
|
|
|
|
}
|
|
}
|
|
SeriesCount = seriesProperties.size();
|
|
}
|
|
|
|
ExtendMedicalImageProperties* DICOMDirectoryHelper::GetSeries(int idx) {
|
|
if (seriesProperties.size() <= idx) return nullptr;
|
|
return seriesProperties[idx];
|
|
}
|
|
|
|
void DICOMDirectoryHelper::Clear() {
|
|
dirName.clear();
|
|
fileName.clear();
|
|
for (auto property : seriesProperties) {
|
|
property->Delete();
|
|
}
|
|
seriesProperties.clear();
|
|
SeriesCount = 0;
|
|
}
|