From 0a8255db5c217e9ccc77a4feab33393260fa2270 Mon Sep 17 00:00:00 2001 From: Krad Date: Fri, 25 Feb 2022 13:39:09 +0800 Subject: [PATCH] Simple DicomLoader, change DICOMDirectoryHelper set propties as output,use new thumbnail function from QDicomUtility --- src/include/base/DicomLoader.h | 34 +++-- src/src/QDicomViewer.cpp | 23 ++-- src/src/base/DICOMDirectoryHelper.h | 6 +- src/src/base/DicomLoader.cpp | 143 ++++++++++++++++---- src/src/base/ExtendMedicalImageProperties.h | 4 + src/src/view/viewcontainerwidget.cpp | 2 +- 6 files changed, 160 insertions(+), 52 deletions(-) diff --git a/src/include/base/DicomLoader.h b/src/include/base/DicomLoader.h index a526a71..5340c5a 100644 --- a/src/include/base/DicomLoader.h +++ b/src/include/base/DicomLoader.h @@ -32,9 +32,16 @@ public: DicomTagInfo_t* createDicomTagsInfo(); - void ItkPreReadSeries(const std::string &dicomName, SeriesOpenMode openMode); + /** + * 读取数据Tag + * @param dir + * @param openMode + */ + void preRead(const std::string &dir, SeriesOpenMode openMode); UniqueIDInfo_t* createUniqueID(const std::string &dicomName, SeriesOpenMode openMode); bool IsDuplicate(UniqueIDInfo_t* unique); + + //set imagedata from reader and set viewer SeriesInstance* createSeries(UniqueIDInfo_t* uniqueID, DicomTagInfo_t* tag_info, vtkGenericOpenGLRenderWindow* gl_rewin, bool copy = false); AddDicomType getAddDicomType()const @@ -53,6 +60,8 @@ public: bool deleteSeriesInstance(SeriesInstance* old); + + // load series data to m_patient SeriesInstance* addSeriesInstance(SeriesInstance* instance, bool copy =false); SeriesInfo_t* getSerieInfo(const UniqueIDInfo &uniqueID); @@ -69,22 +78,25 @@ public: private: explicit DicomLoader(); ~DicomLoader(); - static DicomLoader *instance; - //void copyDicomTagsInfo(SeriesInstance* origin, SeriesInstance* copy); + /** + * 本函数根据DICOM文件TagValue来构建一个树状的PSSI结构 + * 即:Patient-Study-Series-Image + * 主要用途是为左侧的thumbnail bar 做数据支撑 + * TODO:目前Image层暂缺 + */ + void readSeries(); + + static DicomLoader *instance; //once - DICOMDirectoryHelper * DICOMHelper; - ExtendMedicalImageProperties * currentImageProperty; - vtkDICOMImageReader2 * reader; -// ConnectorType::Pointer m_itkConnector; -// SeriesReaderType::Pointer m_itkSeriesReader; -// ImageIOType::Pointer m_gdcmIO; -// InputNamesGeneratorType::Pointer m_inputNames; + ExtendMedicalImageProperties * currentImageProperty = nullptr; + std::vector imageProperties; + vtkDICOMImageReader2 * reader = nullptr; AddDicomType m_addType; PatientsMapType m_patients; - + vtkObject* placeHolder; }; diff --git a/src/src/QDicomViewer.cpp b/src/src/QDicomViewer.cpp index 38d80ef..266064c 100644 --- a/src/src/QDicomViewer.cpp +++ b/src/src/QDicomViewer.cpp @@ -1,4 +1,4 @@ -#include "QDicomViewer.h" +#include "QDicomViewer.h" #include "global/include_all.h" #include "base/seriesinstance.h" #include "view/subview/gridpopwidget.h" @@ -1008,17 +1008,17 @@ void QDicomViewer::openAndDrawDICOM(const std::string& dicomName, SeriesOpenMode DicomLoader* helper = DicomLoader::GetInstance(); - helper->setDirObservers(this); - //call must in order! - //1.come first - helper->ItkPreReadSeries(dicomName, openMode); + //load image and tag + helper->preRead(dicomName, openMode); + - //2.using gdcm UniqueIDInfo_t* unique = helper->createUniqueID(dicomName, openMode); - - //When IsDuplicate()is called, AddDicomType is determined! - //You have to add series before delete, or encounter AddDicomType inconsistency problem! + if (!unique){ + this->statusBar()->showMessage(tr("Error unique data!")); + return; + } + //判断是否重复,并设置AddDicomType if (helper->IsDuplicate(unique)) { this->statusBar()->showMessage(tr("Already Exists!")); @@ -1028,10 +1028,9 @@ void QDicomViewer::openAndDrawDICOM(const std::string& dicomName, SeriesOpenMode return; } - + //read tag of first series DicomTagInfo_t* tag_info = helper->createDicomTagsInfo(); - //You have to judge AddDicomType first! AddDicomType type = helper->getAddDicomType(); @@ -1080,7 +1079,7 @@ void QDicomViewer::openAndDrawDICOM(const std::string& dicomName, SeriesOpenMode } else { - //Note: you dont have to deal with the replaced instance,let it go + //only add new data curV = ui->viewContainer->getCurrentView(); SeriesInstance* old = nullptr; diff --git a/src/src/base/DICOMDirectoryHelper.h b/src/src/base/DICOMDirectoryHelper.h index 4701403..37dee3f 100644 --- a/src/src/base/DICOMDirectoryHelper.h +++ b/src/src/base/DICOMDirectoryHelper.h @@ -38,9 +38,13 @@ public: int GetSeriesCount(){ return SeriesCount; } + const std::vector& GetSeriesProperties() + { + return seriesProperties; + } + ExtendMedicalImageProperties* GetSeries(int idx); ExtendMedicalImageProperties* GetSeriesBySeriesUID(const char* seriesUID); - private: std::string dirName; std::string fileName; diff --git a/src/src/base/DicomLoader.cpp b/src/src/base/DicomLoader.cpp index 141c024..0b8f592 100644 --- a/src/src/base/DicomLoader.cpp +++ b/src/src/base/DicomLoader.cpp @@ -13,6 +13,7 @@ #include #include #include +#include "util/QDicomUtility.h" #define ORIEN_NUM 4 #define SINGLE_INSTANCE 1 @@ -87,6 +88,28 @@ std::vector* orientationHelper::getOrientationStrList(const std::st return &(it->second); } +void copyDicomTasInfo(DicomTagInfo_t* dicom, ExtendMedicalImageProperties* properties){ + dicom->m_PatientID = properties->GetPatientID(); + dicom->m_PatientName = properties->GetPatientName(); + dicom->m_PatientBirth = properties->GetPatientBirthDate(); + dicom->m_Institution = properties->GetInstitutionName(); + dicom->m_Modality = properties->GetModality(); + dicom->m_SeriesNumber = properties->GetSeriesNumber(); + dicom->m_SeriesDescription = properties->GetSeriesDescription(); + dicom->m_StudyDate = properties->GetStudyDate(); + dicom->m_StudyDescription = properties->GetStudyDescription(); + dicom->m_StudyTime = properties->GetStudyTime(); + char buffer[16]={}; + dicom->m_SliceNumber = itoa(properties->GetFileNames()->size(),buffer,10); +} + +void copyUniqueInfo(UniqueIDInfo_t* unique, ExtendMedicalImageProperties* properties){ + unique->series_uid = properties->GetSeriesUID(); + unique->patient_name = properties->GetPatientName(); + unique->study_uid = properties->GetStudyUID(); + char buffer[16]={}; + unique->instance_num=itoa(properties->GetFileNames()->size(),buffer,10); +} DicomLoader* DicomLoader::instance = new DicomLoader(); DicomLoader* DicomLoader::GetInstance() { @@ -105,26 +128,31 @@ DicomLoader::DicomLoader():m_addType(AddDicomType::DUPLICATE_TYPE) { // m_gdcmIO = ImageIOType::New(); // m_inputNames = InputNamesGeneratorType::New(); - DICOMHelper = new DICOMDirectoryHelper; reader = nullptr; //transfer to series after! m_patients.clear(); - + placeHolder = vtkObject::New(); } DicomLoader::~DicomLoader() { - delete DICOMHelper; + if (reader)reader->Delete(); reader = nullptr; delete instance; +// for(auto item : imageProperties){ +// item->UnRegister(&placeHolder); +// } + placeHolder->Delete(); + imageProperties.clear(); } - +// 废止该函数, 因为overridde也好,add模式也好,实际上都不需要判定一下内容 +// 其中的相关逻辑移动到readSeries中去 bool DicomLoader::IsDuplicate(UniqueIDInfo_t* unique) { return false; } - +//该函数所在的逻辑分支暂时不存在!!! void DicomLoader::InitFromCopy(SeriesInstance* instance) { //copy data from existing instance! @@ -148,18 +176,19 @@ void DicomLoader::InitFromCopy(SeriesInstance* instance) void DicomLoader::InitFromRead(SeriesInstance* instance)//, DicomTagInfo_t* tag_info) { + if (reader) reader->Delete(); + reader = vtkDICOMImageReader2::New(); + reader->SetFileNames(*(currentImageProperty->GetFileNames())); + reader->Update(); + instance->m_image = reader->GetOutput(); - instance->m_image = reader->GetOutput(); - - if (instance->getUniqueID()->open_mode == DIR_OPEN_MODE) - { - auto files = reader->GetDICOMFileNames(); - std::for_each(files->begin(),files->end(),[=](auto v){ + if (instance->getUniqueID()->open_mode == DIR_OPEN_MODE) { + auto files = reader->GetDICOMFileNames(); + std::for_each(files->begin(), files->end(), [=](auto v) { instance->m_fileNames.push_back(v); }); - } + } reader->Delete(); - reader = nullptr; } @@ -336,35 +365,38 @@ SeriesInstance* DicomLoader::addSeriesInstance(SeriesInstance* instance,bool cop return nullptr; } -void DicomLoader::ItkPreReadSeries(const std::string &dicomName, SeriesOpenMode openMode) +void DicomLoader::preRead(const std::string &dir, SeriesOpenMode openMode) { - //m_itkSeriesReader->SetImageIO(gdcmIO); - + DICOMDirectoryHelper DICOMHelper; if (openMode == FILE_OPEN_MODE) { //m_itkSeriesReader->SetFileName(m_dicomName.toStdString()); - DICOMHelper->SetFileName(dicomName.c_str()); + DICOMHelper.SetFileName(dir.c_str()); } if (openMode == DIR_OPEN_MODE) { - DICOMHelper->SetDirName(dicomName.c_str()); + DICOMHelper.SetDirName(dir.c_str()); } - DICOMHelper->Update(); - if(DICOMHelper->GetSeriesCount()>0){ - currentImageProperty = DICOMHelper->GetSeries(0); - if (reader) reader->Delete(); - reader = vtkDICOMImageReader2::New(); - reader->SetFileNames(*(currentImageProperty->GetFileNames())); - reader->Update(); + DICOMHelper.Update(); + if ( DICOMHelper.GetSeriesCount()>0){ + for (auto item : DICOMHelper.GetSeriesProperties()) { + item->Register(placeHolder); + imageProperties.push_back(item); + } } + if ( imageProperties.size() > 0 ) { + currentImageProperty = imageProperties[0]; + } + + + readSeries(); } UniqueIDInfo_t* DicomLoader::createUniqueID(const std::string &dicomName, SeriesOpenMode openMode) { + if (!currentImageProperty) return nullptr; UniqueIDInfo_t* pUniqueID(new UniqueIDInfo_t()); - - pUniqueID->open_mode = openMode; pUniqueID->dicom_name = dicomName; if (openMode == FILE_OPEN_MODE) @@ -495,6 +527,7 @@ DicomTagInfo_t* DicomLoader::createDicomTagsInfo() return info; } + SeriesInstance* DicomLoader::createSeries(UniqueIDInfo_t* uniqueID, DicomTagInfo_t* tag_info, vtkGenericOpenGLRenderWindow* gl_rewin, bool copy) { @@ -514,3 +547,59 @@ SeriesInstance* DicomLoader::createSeries(UniqueIDInfo_t* uniqueID, DicomTagInfo return series; } +void DicomLoader::readSeries() { + + for (ExtendMedicalImageProperties* property: imageProperties){ + + UniqueIDInfo_t *unique = new UniqueIDInfo_t; + copyUniqueInfo(unique, property); + + //patient level + PatientInfo_t* patient = nullptr; + //get from store + if (m_patients.count(unique->patient_name)>0){ + patient = m_patients[unique->patient_name]; + } + else{ + //create new + patient = new PatientInfo_t(); + patient->patient_name = property->GetPatientName(); + patient->birth_date = property->GetPatientBirthDate(); + patient->studies = new StudiesMapType(); + m_patients[unique->patient_name] = patient; + } + StudyInfo_t* study = nullptr; + //get from store + if (patient->studies->count(unique->study_uid)>0){ + study = patient->studies->at(unique->study_uid); + } + else{ + //create new + study = new StudyInfo_t(); + patient->studies->insert({unique->study_uid, study}); + study->study_description = property->GetStudyDescription(); + study->study_date = property->GetStudyDate(); + study->study_time = property->GetStudyTime(); + study->series = new SeriesMapType(); + } + SeriesInfo_t* series = nullptr; + if (study->series->count(unique->series_uid)>0){ + series = study->series->at(unique->series_uid); + //TODO:need to add override logic!! + } + else { + series = new SeriesInfo_t(); + study->series->insert({unique->series_uid,series}); + DicomTagInfo_t *dicom = new DicomTagInfo_t; + copyDicomTasInfo(dicom, property); + series->tag_info = dicom; + series->unique_info = unique; + double *wlww = property->GetNthWindowLevelPreset(0); + int ww = wlww ? ((int) wlww[0]) : (512); + int wl = wlww ? ((int) wlww[1]) : (256); + series->series_pixmap = GetImageFormDcmFile(property->GetThumbnailFileName(), wl, ww, property->GetSamplePerPixel()); + } + + } +} + diff --git a/src/src/base/ExtendMedicalImageProperties.h b/src/src/base/ExtendMedicalImageProperties.h index 22b3335..846e929 100644 --- a/src/src/base/ExtendMedicalImageProperties.h +++ b/src/src/base/ExtendMedicalImageProperties.h @@ -55,6 +55,10 @@ public: vtkMedicalImageProperties::SetSeriesNumber(s); } + const char* GetThumbnailFileName(){ + if (FileNames.empty()) return nullptr; + return FileNames[FileNames.size()/2].data(); + } protected: ExtendMedicalImageProperties(); diff --git a/src/src/view/viewcontainerwidget.cpp b/src/src/view/viewcontainerwidget.cpp index 8126cb3..5dfbff2 100644 --- a/src/src/view/viewcontainerwidget.cpp +++ b/src/src/view/viewcontainerwidget.cpp @@ -427,7 +427,7 @@ void ViewContainerWidget::replaceViewWithSerie(UniqueIDInfo_t* unique_info, Dico DicomLoader *helper = DicomLoader::GetInstance(); vtkGenericOpenGLRenderWindow* grw = curV->getRenWin(); SeriesInstance* instance = helper->createSeries(unique_info, tag_info, grw, copy); - helper->addSeriesInstance(instance, copy); + curV->setDicomImageView(instance); curV->Render(); //delete old after new instance render