Fix charset bug for chinese.

This commit is contained in:
Krad
2022-09-14 14:17:09 +08:00
parent a92a3c2016
commit 19a6718665
2 changed files with 49 additions and 264 deletions

View File

@@ -5,13 +5,13 @@
#include "DICOMHeaderHelper.h" #include "DICOMHeaderHelper.h"
#include "dcmtk/dcmdata/dcfilefo.h" #include "dcmtk/dcmdata/dcfilefo.h"
#include "dcmtk/dcmdata/dcdatset.h" #include "dcmtk/dcmdata/dcdatset.h"
#include "dcmtk/dcmdata/dcspchrs.h"
#include "ExtendMedicalImageProperties.h" #include "ExtendMedicalImageProperties.h"
#include <vtkDirectory.h> #include <vtkDirectory.h>
#include <vtkNew.h> #include <vtkNew.h>
#include <unordered_map> #include <unordered_map>
#include <algorithm> #include <algorithm>
#include <vtkMath.h> #include <vtkMath.h>
#include <vtkMatrix4x4.h>
#include <QtCore/qvarlengtharray.h> #include <QtCore/qvarlengtharray.h>
struct DICOMTag{ struct DICOMTag{
@@ -50,153 +50,9 @@ DICOMTag dicom_tags[] = {
{0x0028, 0x1052, "pixel offset"} {0x0028, 0x1052, "pixel offset"}
}; };
void DICOMHeaderHelper::getDirectoryProperties(const char * rootPath, SeriesMap& 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 DICOMHeaderHelper::getFileProperty(const std::string &path, SeriesMap& result) {
DcmFileFormat file;
// read success!
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);
// series be firstly loaded
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(PatientAge, 0x0010, 0x1010)
ReadTAGToProperty(StudyDate, 0x0008, 0x0020)
ReadTAGToProperty(AcquisitionDate, 0x0008, 0x0022)
ReadTAGToProperty(StudyTime, 0x0008, 0x0030)
ReadTAGToProperty(AcquisitionTime, 0x0008, 0x0032)
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);
std::string uniqueID;
uniqueID.append(PatientName);
uniqueID.append("_");
uniqueID.append(StudyUID);
uniqueID.append("_");
uniqueID.append(SeriesUID);
seriesProperty->SetUniqueID(uniqueID);
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[3] = {0.0, 0.0, 1.0};
dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x0030), Spacing[0], 0);
dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x0030), Spacing[1], 1);
seriesProperty->SetSpacing(Spacing);
double orientation[6] = {.0, .0, .0, .0, .0, .0};
dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0037), orientation[0], 0);
dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0037), orientation[1], 1);
dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0037), orientation[2], 2);
dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0037), orientation[3], 3);
dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0037), orientation[4], 4);
dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0037), orientation[5], 5);
seriesProperty->SetDirectionCosine(orientation);
double position[3] = {.0, .0, .0};
dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0032), position[0], 0);
dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0032), position[1], 1);
dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0032), position[2], 2);
seriesProperty->SetPosition(position);
unsigned short SamplePerPixel = 0;
dataset->findAndGetUint16(DcmTagKey(0x0028, 0x0002), SamplePerPixel);
seriesProperty->SetSamplePerPixel(SamplePerPixel);
//TODO:暂时不考虑颜色空间的事(只与缩略图相关!!!)
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] = {path, "",SeriesNumber, AcquisitionNumber, InstanceNumber};
}
}
void DICOMHeaderHelper::Update() { void DICOMHeaderHelper::Update() {
ReadHeader(); ReadHeader();
ArrangeSeriesProperty(); ArrangeSeriesProperty();
// std::unordered_map<std::string, std::unordered_map<std::string,DICOMFileHeader>> series;
// if (!this->dirName.empty()){
// getDirectoryProperties(this->dirName.c_str(), series);
// }
// else{
// getFileProperty(fileName, 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()){
// std::vector<std::string> files;
// std::vector<DICOMFileHeader> vector;
// for (auto f : pair.second) {
// vector.emplace_back(std::move(f.second));
// }
// std::sort(vector.begin(), vector.end(), [](const DICOMFileHeader &v1, const DICOMFileHeader &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){
// files.emplace_back(std::move(v.FilePath));
// });
// (*iterator)->SetFileNames(files);
// readImageProperty(*iterator);
// }
// }
SeriesCount = seriesProperties.size(); SeriesCount = seriesProperties.size();
} }
@@ -224,96 +80,6 @@ void DICOMHeaderHelper::Clear() {
SeriesCount = 0; SeriesCount = 0;
} }
void DICOMHeaderHelper::readImageProperty(ExtendMedicalImageProperties* property) {
const std::vector<std::string>& files = property->GetFileNames();
DcmFileFormat file1;
// read success!
if (file1.loadFile(files.at(0)).good()) {
DcmDataset *dataset = file1.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);
std::cout<<"file1:"<<SeriesUID<<", "<<SeriesNumber<<", "<<AcquisitionNumber<<", "<<InstanceNumber<<std::endl;
double Spacing[3] = {0.0, 0.0, -1.0};
dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x0030), Spacing[0], 0);
dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x0030), Spacing[1], 1);
property->SetSpacing(Spacing);
double orientation[6] = {.0, .0, .0, .0, .0, .0};
dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0037), orientation[0], 0);
dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0037), orientation[1], 1);
dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0037), orientation[2], 2);
dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0037), orientation[3], 3);
dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0037), orientation[4], 4);
dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0037), orientation[5], 5);
property->SetDirectionCosine(orientation);
double position[3] = {.0, .0, .0};
dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0032), position[0], 0);
dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0032), position[1], 1);
dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0032), position[2], 2);
property->SetPosition(position);
// get orientation transform matrix and MToW WToM transform matrix
property->ComputeTransformMatrix();
}
if (files.size()>1){
DcmFileFormat file2;
// read success!
if (file2.loadFile(files.at(1)).good()) {
DcmDataset *dataset = file2.getDataset();
std::string SeriesUID;
dataset->findAndGetOFString(DcmTagKey(0x0020, 0x000e), SeriesUID);
std::string SeriesDes;
dataset->findAndGetOFString(DcmTagKey(0x0008, 0x103e), SeriesDes);
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);
double position[3] = {.0, .0, .0};
dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0032), position[0], 0);
dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0032), position[1], 1);
dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0032), position[2], 2);
double position0[3] ={property->GetPosition()[0], property->GetPosition()[1] , property->GetPosition()[2]};
double zVector_real[3] = {
position[0] - position0[0],
position[1] - position0[1],
position[2] - position0[2]
};
// get slice real distance as space[2]
double space2 = sqrt(vtkMath::Distance2BetweenPoints(position, property->GetPosition()));
vtkMath::Normalize(zVector_real);
double Spacing[3] = {.0, .0, .0};
property->GetSpacing(Spacing);
double* zVector = property->GetZVector();
// if zVector_real is same direction with zVector, the negativeFlag must be true, otherwise will be false.
bool negativeFlag = (zVector_real[0] * zVector[0]) < 0
|| (zVector_real[1] * zVector[1]) < 0
|| (zVector_real[2] * zVector[2]) < 0 ;
// the space[2] will decide the z Axis image heap up direction
Spacing[2] = negativeFlag?(-1.0*space2):space2;
property->SetSpacing(Spacing);
}
}
else{
double Spacing[3] = {.0, .0, .0};
property->GetSpacing(Spacing);
Spacing[2] = 1.0;
property->SetSpacing(Spacing);
}
}
void DICOMHeaderHelper::readHeaderFromDir(const char * rootPath){ void DICOMHeaderHelper::readHeaderFromDir(const char * rootPath){
vtkNew<vtkDirectory> dir; vtkNew<vtkDirectory> dir;
dir->Open(rootPath); dir->Open(rootPath);
@@ -366,8 +132,20 @@ void DICOMHeaderHelper::readHeaderFromFile(const char * filePath){
dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x1050), header.WindowCenter); dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x1050), header.WindowCenter);
dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x1051), header.WindowWidth); dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x1051), header.WindowWidth);
dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x0030), header.Spacing[0], 0); auto spacingResult =
dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x0030), header.Spacing[0], 0);
dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x0030), header.Spacing[1], 1); dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x0030), header.Spacing[1], 1);
//No Pixel spacing , try use Imager Pixel Spacing to instead
if (!spacingResult.good()){
spacingResult =
dataset->findAndGetFloat64(DcmTagKey(0x0018, 0x1164), header.Spacing[0], 0);
dataset->findAndGetFloat64(DcmTagKey(0x0018, 0x1164), header.Spacing[1], 1);
}
//No Imager Pixel Spacing, use default 1.0
if (!spacingResult.good()){
header.Spacing[0] = 1.0;
header.Spacing[1] = 1.0;
}
dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0037), header.Orientation[0], 0); dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0037), header.Orientation[0], 0);
dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0037), header.Orientation[1], 1); dataset->findAndGetFloat64(DcmTagKey(0x0020, 0x0037), header.Orientation[1], 1);
@@ -455,13 +233,11 @@ void DICOMHeaderHelper::ArrangeSeriesProperty() {
beginOffset = splitIndex[j]; beginOffset = splitIndex[j];
imageSetNumber++; imageSetNumber++;
} }
printf("first file:%s",item.second[0].FilePath.c_str());
//sort the last image set //sort the last image set
std::sort(item.second.begin() + beginOffset, item.second.end(), std::sort(item.second.begin() + beginOffset, item.second.end(),
[](auto v1, auto v2) { [](auto v1, auto v2) {
return v1.image_position < v2.image_position; return v1.image_position < v2.image_position;
}); });
// printf("new first file:%s\r\n",item.second[0].FilePath.c_str());
auto p = createProperty(item.second, item.second.size(), beginOffset); auto p = createProperty(item.second, item.second.size(), beginOffset);
p->SetImageSetNumber(imageSetNumber); p->SetImageSetNumber(imageSetNumber);
p->GenerateUniqueID(); p->GenerateUniqueID();
@@ -498,8 +274,7 @@ ExtendMedicalImageProperties* DICOMHeaderHelper::createProperty(const std::vecto
dataset->findAndGetOFString(DcmTagKey(group, element), Name);\ dataset->findAndGetOFString(DcmTagKey(group, element), Name);\
property->Set##Name(Name.c_str()); property->Set##Name(Name.c_str());
ReadTAGToProperty(PatientID, 0x0010, 0x0020)
ReadTAGToProperty(PatientName, 0x0010, 0x0010)
ReadTAGToProperty(PatientBirthDate, 0x0010, 0x0030) ReadTAGToProperty(PatientBirthDate, 0x0010, 0x0030)
ReadTAGToProperty(PatientSex, 0x0010, 0x0040) ReadTAGToProperty(PatientSex, 0x0010, 0x0040)
ReadTAGToProperty(PatientAge, 0x0010, 0x1010) ReadTAGToProperty(PatientAge, 0x0010, 0x1010)
@@ -508,16 +283,38 @@ ExtendMedicalImageProperties* DICOMHeaderHelper::createProperty(const std::vecto
ReadTAGToProperty(StudyTime, 0x0008, 0x0030) ReadTAGToProperty(StudyTime, 0x0008, 0x0030)
ReadTAGToProperty(AcquisitionTime, 0x0008, 0x0032) ReadTAGToProperty(AcquisitionTime, 0x0008, 0x0032)
ReadTAGToProperty(Modality, 0x0008, 0x0060) ReadTAGToProperty(Modality, 0x0008, 0x0060)
ReadTAGToProperty(InstitutionName, 0x0008, 0x0080)
ReadTAGToProperty(StudyDescription, 0x0008, 0x1030)
ReadTAGToProperty(SeriesDescription, 0x0008, 0x103E)
ReadTAGToProperty(StudyUID, 0x0020, 0x000d) ReadTAGToProperty(StudyUID, 0x0020, 0x000d)
ReadTAGToProperty(StudyID, 0x0020, 0x0010) ReadTAGToProperty(StudyID, 0x0020, 0x0010)
std::string charSet = "";
auto needConvert = dataset->findAndGetOFString(DcmTagKey(0x0008, 0x0005), charSet);
if (needConvert.good()){
DcmSpecificCharacterSet charSetConvert;
charSetConvert.selectCharacterSet(charSet);
#define ReadTAGToPropertyConvert(Name, group, element)\
std::string Name;\
std::string Name##Convert;\
dataset->findAndGetOFString(DcmTagKey(group, element), Name);\
charSetConvert.convertString(Name,Name##Convert);\
property->Set##Name(Name##Convert.c_str());
ReadTAGToPropertyConvert(PatientID, 0x0010, 0x0020)
ReadTAGToPropertyConvert(PatientName, 0x0010, 0x0010)
ReadTAGToPropertyConvert(InstitutionName, 0x0008, 0x0080)
ReadTAGToPropertyConvert(StudyDescription, 0x0008, 0x1030)
ReadTAGToPropertyConvert(SeriesDescription, 0x0008, 0x103E)
} else{
ReadTAGToProperty(PatientID, 0x0010, 0x0020)
ReadTAGToProperty(PatientName, 0x0010, 0x0010)
ReadTAGToProperty(InstitutionName, 0x0008, 0x0080)
ReadTAGToProperty(StudyDescription, 0x0008, 0x1030)
ReadTAGToProperty(SeriesDescription, 0x0008, 0x103E)
}
double thickness= 1.0; double thickness= 1.0;
dataset->findAndGetFloat64(DcmTagKey(0x0008, 0x0050), thickness); dataset->findAndGetFloat64(DcmTagKey(0x0008, 0x0050), thickness);
double RescaleSlope= 1.0; double RescaleSlope= 1.0;
dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x1053), RescaleSlope); dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x1053), RescaleSlope);
double RescaleOffset= 1.0; double RescaleOffset= 0.0;
dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x1052), RescaleOffset); dataset->findAndGetFloat64(DcmTagKey(0x0028, 0x1052), RescaleOffset);
unsigned short bitsAllocated= 1; unsigned short bitsAllocated= 1;
dataset->findAndGetUint16(DcmTagKey(0x0028, 0x0100), bitsAllocated); dataset->findAndGetUint16(DcmTagKey(0x0028, 0x0100), bitsAllocated);
@@ -547,9 +344,4 @@ ExtendMedicalImageProperties* DICOMHeaderHelper::createProperty(const std::vecto
return property; return property;
} }
//void DICOMDirectoryHelper::GetImageData(int index, void *imgData) {
//
//
//}

View File

@@ -75,10 +75,6 @@ public:
void Update(); void Update();
void ReadHeader();
void ArrangeSeriesProperty();
int GetSeriesCount() { int GetSeriesCount() {
return SeriesCount; return SeriesCount;
} }
@@ -92,18 +88,9 @@ public:
ExtendMedicalImageProperties *GetSeriesBySeriesUID(const char *seriesUID); ExtendMedicalImageProperties *GetSeriesBySeriesUID(const char *seriesUID);
private: private:
std::string dirName; void ReadHeader();
std::string fileName;
int SeriesCount = 0;
SeriesFileMap series;
std::vector<ExtendMedicalImageProperties *> seriesProperties;
void getDirectoryProperties(const char *rootPath, void ArrangeSeriesProperty();
SeriesMap &result);
void getFileProperty(const std::string &path, SeriesMap &result);
void readImageProperty(ExtendMedicalImageProperties *property);
void readHeaderFromDir(const char *rootPath); void readHeaderFromDir(const char *rootPath);
@@ -111,6 +98,12 @@ private:
ExtendMedicalImageProperties * ExtendMedicalImageProperties *
createProperty(const std::vector<DICOMFileHeader> &header, int splitIndex, int beginOffset); createProperty(const std::vector<DICOMFileHeader> &header, int splitIndex, int beginOffset);
std::string dirName;
std::string fileName;
int SeriesCount = 0;
SeriesFileMap series;
std::vector<ExtendMedicalImageProperties *> seriesProperties;
}; };