Files
DCMV/src/src/base/DICOMDirectoryHelper.cpp
2022-02-14 09:23:37 +08:00

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;
}