Simple DicomLoader, change DICOMDirectoryHelper set propties as output,use new thumbnail function from QDicomUtility
This commit is contained in:
@@ -32,9 +32,16 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
DicomTagInfo_t* createDicomTagsInfo();
|
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);
|
UniqueIDInfo_t* createUniqueID(const std::string &dicomName, SeriesOpenMode openMode);
|
||||||
bool IsDuplicate(UniqueIDInfo_t* unique);
|
bool IsDuplicate(UniqueIDInfo_t* unique);
|
||||||
|
|
||||||
|
//set imagedata from reader and set viewer
|
||||||
SeriesInstance* createSeries(UniqueIDInfo_t* uniqueID, DicomTagInfo_t* tag_info,
|
SeriesInstance* createSeries(UniqueIDInfo_t* uniqueID, DicomTagInfo_t* tag_info,
|
||||||
vtkGenericOpenGLRenderWindow* gl_rewin, bool copy = false);
|
vtkGenericOpenGLRenderWindow* gl_rewin, bool copy = false);
|
||||||
AddDicomType getAddDicomType()const
|
AddDicomType getAddDicomType()const
|
||||||
@@ -53,6 +60,8 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
bool deleteSeriesInstance(SeriesInstance* old);
|
bool deleteSeriesInstance(SeriesInstance* old);
|
||||||
|
|
||||||
|
// load series data to m_patient
|
||||||
SeriesInstance* addSeriesInstance(SeriesInstance* instance, bool copy =false);
|
SeriesInstance* addSeriesInstance(SeriesInstance* instance, bool copy =false);
|
||||||
|
|
||||||
SeriesInfo_t* getSerieInfo(const UniqueIDInfo &uniqueID);
|
SeriesInfo_t* getSerieInfo(const UniqueIDInfo &uniqueID);
|
||||||
@@ -69,22 +78,25 @@ public:
|
|||||||
private:
|
private:
|
||||||
explicit DicomLoader();
|
explicit DicomLoader();
|
||||||
~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
|
//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<ExtendMedicalImageProperties*> imageProperties;
|
||||||
|
vtkDICOMImageReader2 * reader = nullptr;
|
||||||
|
|
||||||
AddDicomType m_addType;
|
AddDicomType m_addType;
|
||||||
PatientsMapType m_patients;
|
PatientsMapType m_patients;
|
||||||
|
vtkObject* placeHolder;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "QDicomViewer.h"
|
#include "QDicomViewer.h"
|
||||||
#include "global/include_all.h"
|
#include "global/include_all.h"
|
||||||
#include "base/seriesinstance.h"
|
#include "base/seriesinstance.h"
|
||||||
#include "view/subview/gridpopwidget.h"
|
#include "view/subview/gridpopwidget.h"
|
||||||
@@ -1008,17 +1008,17 @@ void QDicomViewer::openAndDrawDICOM(const std::string& dicomName, SeriesOpenMode
|
|||||||
|
|
||||||
|
|
||||||
DicomLoader* helper = DicomLoader::GetInstance();
|
DicomLoader* helper = DicomLoader::GetInstance();
|
||||||
helper->setDirObservers(this);
|
|
||||||
|
|
||||||
//call must in order!
|
//load image and tag
|
||||||
//1.come first
|
helper->preRead(dicomName, openMode);
|
||||||
helper->ItkPreReadSeries(dicomName, openMode);
|
|
||||||
|
|
||||||
//2.using gdcm
|
|
||||||
UniqueIDInfo_t* unique = helper->createUniqueID(dicomName, openMode);
|
UniqueIDInfo_t* unique = helper->createUniqueID(dicomName, openMode);
|
||||||
|
if (!unique){
|
||||||
//When IsDuplicate()is called, AddDicomType is determined!
|
this->statusBar()->showMessage(tr("Error unique data!"));
|
||||||
//You have to add series before delete, or encounter AddDicomType inconsistency problem!
|
return;
|
||||||
|
}
|
||||||
|
//判断是否重复,并设置AddDicomType
|
||||||
if (helper->IsDuplicate(unique))
|
if (helper->IsDuplicate(unique))
|
||||||
{
|
{
|
||||||
this->statusBar()->showMessage(tr("Already Exists!"));
|
this->statusBar()->showMessage(tr("Already Exists!"));
|
||||||
@@ -1028,10 +1028,9 @@ void QDicomViewer::openAndDrawDICOM(const std::string& dicomName, SeriesOpenMode
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//read tag of first series
|
||||||
DicomTagInfo_t* tag_info = helper->createDicomTagsInfo();
|
DicomTagInfo_t* tag_info = helper->createDicomTagsInfo();
|
||||||
|
|
||||||
|
|
||||||
//You have to judge AddDicomType first!
|
//You have to judge AddDicomType first!
|
||||||
AddDicomType type = helper->getAddDicomType();
|
AddDicomType type = helper->getAddDicomType();
|
||||||
|
|
||||||
@@ -1080,7 +1079,7 @@ void QDicomViewer::openAndDrawDICOM(const std::string& dicomName, SeriesOpenMode
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Note: you dont have to deal with the replaced instance,let it go
|
//only add new data
|
||||||
curV = ui->viewContainer->getCurrentView();
|
curV = ui->viewContainer->getCurrentView();
|
||||||
|
|
||||||
SeriesInstance* old = nullptr;
|
SeriesInstance* old = nullptr;
|
||||||
|
|||||||
@@ -38,9 +38,13 @@ public:
|
|||||||
int GetSeriesCount(){
|
int GetSeriesCount(){
|
||||||
return SeriesCount;
|
return SeriesCount;
|
||||||
}
|
}
|
||||||
|
const std::vector<ExtendMedicalImageProperties*>& GetSeriesProperties()
|
||||||
|
{
|
||||||
|
return seriesProperties;
|
||||||
|
}
|
||||||
|
|
||||||
ExtendMedicalImageProperties* GetSeries(int idx);
|
ExtendMedicalImageProperties* GetSeries(int idx);
|
||||||
ExtendMedicalImageProperties* GetSeriesBySeriesUID(const char* seriesUID);
|
ExtendMedicalImageProperties* GetSeriesBySeriesUID(const char* seriesUID);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string dirName;
|
std::string dirName;
|
||||||
std::string fileName;
|
std::string fileName;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include <qDebug>
|
#include <qDebug>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include "util/QDicomUtility.h"
|
||||||
|
|
||||||
#define ORIEN_NUM 4
|
#define ORIEN_NUM 4
|
||||||
#define SINGLE_INSTANCE 1
|
#define SINGLE_INSTANCE 1
|
||||||
@@ -87,6 +88,28 @@ std::vector<std::string>* orientationHelper::getOrientationStrList(const std::st
|
|||||||
return &(it->second);
|
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::instance = new DicomLoader();
|
||||||
DicomLoader* DicomLoader::GetInstance() {
|
DicomLoader* DicomLoader::GetInstance() {
|
||||||
@@ -105,26 +128,31 @@ DicomLoader::DicomLoader():m_addType(AddDicomType::DUPLICATE_TYPE) {
|
|||||||
// m_gdcmIO = ImageIOType::New();
|
// m_gdcmIO = ImageIOType::New();
|
||||||
// m_inputNames = InputNamesGeneratorType::New();
|
// m_inputNames = InputNamesGeneratorType::New();
|
||||||
|
|
||||||
DICOMHelper = new DICOMDirectoryHelper;
|
|
||||||
reader = nullptr;
|
reader = nullptr;
|
||||||
//transfer to series after!
|
//transfer to series after!
|
||||||
m_patients.clear();
|
m_patients.clear();
|
||||||
|
placeHolder = vtkObject::New();
|
||||||
}
|
}
|
||||||
DicomLoader::~DicomLoader() {
|
DicomLoader::~DicomLoader() {
|
||||||
delete DICOMHelper;
|
|
||||||
if (reader)reader->Delete();
|
if (reader)reader->Delete();
|
||||||
reader = nullptr;
|
reader = nullptr;
|
||||||
delete instance;
|
delete instance;
|
||||||
|
// for(auto item : imageProperties){
|
||||||
|
// item->UnRegister(&placeHolder);
|
||||||
|
// }
|
||||||
|
placeHolder->Delete();
|
||||||
|
imageProperties.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 废止该函数, 因为overridde也好,add模式也好,实际上都不需要判定一下内容
|
||||||
|
// 其中的相关逻辑移动到readSeries中去
|
||||||
bool DicomLoader::IsDuplicate(UniqueIDInfo_t* unique)
|
bool DicomLoader::IsDuplicate(UniqueIDInfo_t* unique)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//该函数所在的逻辑分支暂时不存在!!!
|
||||||
void DicomLoader::InitFromCopy(SeriesInstance* instance)
|
void DicomLoader::InitFromCopy(SeriesInstance* instance)
|
||||||
{
|
{
|
||||||
//copy data from existing instance!
|
//copy data from existing instance!
|
||||||
@@ -148,18 +176,19 @@ void DicomLoader::InitFromCopy(SeriesInstance* instance)
|
|||||||
|
|
||||||
void DicomLoader::InitFromRead(SeriesInstance* instance)//, DicomTagInfo_t* tag_info)
|
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();
|
||||||
if (instance->getUniqueID()->open_mode == DIR_OPEN_MODE)
|
std::for_each(files->begin(), files->end(), [=](auto v) {
|
||||||
{
|
|
||||||
auto files = reader->GetDICOMFileNames();
|
|
||||||
std::for_each(files->begin(),files->end(),[=](auto v){
|
|
||||||
instance->m_fileNames.push_back(v);
|
instance->m_fileNames.push_back(v);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
reader->Delete();
|
reader->Delete();
|
||||||
|
|
||||||
reader = nullptr;
|
reader = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,35 +365,38 @@ SeriesInstance* DicomLoader::addSeriesInstance(SeriesInstance* instance,bool cop
|
|||||||
return nullptr;
|
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)
|
if (openMode == FILE_OPEN_MODE)
|
||||||
{
|
{
|
||||||
//m_itkSeriesReader->SetFileName(m_dicomName.toStdString());
|
//m_itkSeriesReader->SetFileName(m_dicomName.toStdString());
|
||||||
DICOMHelper->SetFileName(dicomName.c_str());
|
DICOMHelper.SetFileName(dir.c_str());
|
||||||
}
|
}
|
||||||
if (openMode == DIR_OPEN_MODE)
|
if (openMode == DIR_OPEN_MODE)
|
||||||
{
|
{
|
||||||
DICOMHelper->SetDirName(dicomName.c_str());
|
DICOMHelper.SetDirName(dir.c_str());
|
||||||
}
|
}
|
||||||
DICOMHelper->Update();
|
DICOMHelper.Update();
|
||||||
if(DICOMHelper->GetSeriesCount()>0){
|
if ( DICOMHelper.GetSeriesCount()>0){
|
||||||
currentImageProperty = DICOMHelper->GetSeries(0);
|
for (auto item : DICOMHelper.GetSeriesProperties()) {
|
||||||
if (reader) reader->Delete();
|
item->Register(placeHolder);
|
||||||
reader = vtkDICOMImageReader2::New();
|
imageProperties.push_back(item);
|
||||||
reader->SetFileNames(*(currentImageProperty->GetFileNames()));
|
}
|
||||||
reader->Update();
|
|
||||||
}
|
}
|
||||||
|
if ( imageProperties.size() > 0 ) {
|
||||||
|
currentImageProperty = imageProperties[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
readSeries();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UniqueIDInfo_t* DicomLoader::createUniqueID(const std::string &dicomName, SeriesOpenMode openMode)
|
UniqueIDInfo_t* DicomLoader::createUniqueID(const std::string &dicomName, SeriesOpenMode openMode)
|
||||||
{
|
{
|
||||||
|
if (!currentImageProperty) return nullptr;
|
||||||
UniqueIDInfo_t* pUniqueID(new UniqueIDInfo_t());
|
UniqueIDInfo_t* pUniqueID(new UniqueIDInfo_t());
|
||||||
|
|
||||||
|
|
||||||
pUniqueID->open_mode = openMode;
|
pUniqueID->open_mode = openMode;
|
||||||
pUniqueID->dicom_name = dicomName;
|
pUniqueID->dicom_name = dicomName;
|
||||||
if (openMode == FILE_OPEN_MODE)
|
if (openMode == FILE_OPEN_MODE)
|
||||||
@@ -495,6 +527,7 @@ DicomTagInfo_t* DicomLoader::createDicomTagsInfo()
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SeriesInstance* DicomLoader::createSeries(UniqueIDInfo_t* uniqueID, DicomTagInfo_t* tag_info, vtkGenericOpenGLRenderWindow* gl_rewin, bool copy)
|
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;
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,6 +55,10 @@ public:
|
|||||||
vtkMedicalImageProperties::SetSeriesNumber(s);
|
vtkMedicalImageProperties::SetSeriesNumber(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* GetThumbnailFileName(){
|
||||||
|
if (FileNames.empty()) return nullptr;
|
||||||
|
return FileNames[FileNames.size()/2].data();
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ExtendMedicalImageProperties();
|
ExtendMedicalImageProperties();
|
||||||
|
|||||||
@@ -427,7 +427,7 @@ void ViewContainerWidget::replaceViewWithSerie(UniqueIDInfo_t* unique_info, Dico
|
|||||||
DicomLoader *helper = DicomLoader::GetInstance();
|
DicomLoader *helper = DicomLoader::GetInstance();
|
||||||
vtkGenericOpenGLRenderWindow* grw = curV->getRenWin();
|
vtkGenericOpenGLRenderWindow* grw = curV->getRenWin();
|
||||||
SeriesInstance* instance = helper->createSeries(unique_info, tag_info, grw, copy);
|
SeriesInstance* instance = helper->createSeries(unique_info, tag_info, grw, copy);
|
||||||
helper->addSeriesInstance(instance, copy);
|
|
||||||
curV->setDicomImageView(instance);
|
curV->setDicomImageView(instance);
|
||||||
curV->Render();
|
curV->Render();
|
||||||
//delete old after new instance render
|
//delete old after new instance render
|
||||||
|
|||||||
Reference in New Issue
Block a user