New export logic(with out annotation)

This commit is contained in:
Krad
2022-09-29 11:37:37 +08:00
parent 7b57cbd937
commit d3febde981
14 changed files with 314 additions and 611 deletions

View File

@@ -1,7 +1,17 @@
#include "dicomexporter.h"
#include "Common/SeriesImageSet.h"
#include <QImage>
#include "IO/DICOM/DICOMPixelDataHelper.h"
#include "IO/Convert/DICOMToQImageConverter.h"
namespace {
const char* FileExtention[3]={
"bmp","jpg","png"
};
}
DicomExporter::DicomExporter(QObject *parent)
: QObject(parent),
exportedNumber(0)
@@ -19,477 +29,101 @@ void DicomExporter::execute(ExportOptions options)
return;// to avoid exception
}
initVTK();
exportedNumber = 0;
totalCount = 0;
caculateExportTotalCount();//caculate the total count of file to be exported
if (exportOptions.exportFileFormat == ExportOptions::FileFormat::Dicom)
{
for (int i = 0; i < exportOptions.inputData.size(); i++)
{
//Note<74><65>When the smart pointer points to another variable, it is automatically
//released, you can move it to outside or not.
initDataReader();
exportDicom(exportOptions.inputData.at(i));
}
if (exportOptions.slice >= 0){
if (exportOptions.inputData.empty()
|| exportOptions.inputData[0]->GetFileNames().empty()) {
emit exportError();
return;
}
std::string fileName = exportOptions.inputData[0]->GetFileNames()[exportOptions.slice].first;
long frame = exportOptions.inputData[0]->GetFileNames()[exportOptions.slice].second;
DICOMToQImageConverter convert;
if (frame>=0){
convert.setFrame(frame);
}
convert.setInputDICOMFile(fileName.c_str());
convert.setWindow(exportOptions.windowLevel, exportOptions.windowWidth);
if (exportOptions.inputData[0]->GetSamplePerPixel()>1)
{
convert.setColorImage(exportOptions.inputData[0]->GetSamplePerPixel());
}
convert.save();
auto img = convert.getQImage();
bool ret = img->save(QString("%1/%2%3.%4")
.arg(exportOptions.exportDirectory,exportOptions.fileNamePrefix)
.arg(0).arg(getFileExtention()),getFileExtention());
delete img;
if(ret){
emit exportFinished();
}
else{
emit exportError();
return;
}
}
else
{
for (int i = 0; i < exportOptions.inputData.size(); i++)
{
initDataReader();
exportPicture(exportOptions.inputData.at(i));
}
else{
long successCount = 0;
long processCount = 0;
DICOMPixelDataHelper::InitCodecs();
for (int i = 0; i < exportOptions.inputData.size(); ++i) {
auto property = exportOptions.inputData[i];
if (property->GetFileNames().empty())continue;
QString savedir = QString("%1/%2").arg(exportOptions.exportDirectory,property->GetSeriesUID());
dir.mkpath(savedir);
for (int j = 0; j < property->GetFileNames().size(); ++j) {
std::string fileName = property->GetFileNames()[j].first;
long frame = property->GetFileNames()[j].second;
DICOMToQImageConverter convert;
if (frame>=0){
convert.setFrame(frame);
}
convert.setInputDICOMFile(fileName.c_str());
double * window = property->GetNthWindowLevelPreset(0);
convert.setWindow(window[1], window[0]);
if (property->GetSamplePerPixel()>1)
{
convert.setColorImage(property->GetSamplePerPixel());
}
convert.save();
auto img = convert.getQImage();
bool ret = img->save(QString("%1/%2%3.%4")
.arg(savedir,exportOptions.fileNamePrefix)
.arg(j).arg(getFileExtention()),getFileExtention());
delete img;
if (ret)++successCount;
++processCount;
emit exportProgress(totalCount,processCount);
}
}
DICOMPixelDataHelper::FinalizeCodecs();
DICOMPixelDataHelper::ClearFileObjectCache();
if(totalCount == successCount){
emit exportFinished();
}
else{
emit exportError();
}
}
emit exportFinished();
}
void DicomExporter::initVTK()
const char * DicomExporter::getFileExtention()
{
m_glrenWinExport = vtkSmartPointer<vtkRenderWindow>::New();
m_glrenWinExport->OffScreenRenderingOn();
m_imageViewerExport = vtkSmartPointer<DICOMImageViewer>::New();
m_imageViewerExport->SetRenderWindow(m_glrenWinExport);
m_imageViewerExport->SetupInteractor(m_glrenWinExport->GetInteractor());
return FileExtention[exportOptions.exportFileFormat];
}
void DicomExporter::initDataReader()
{
// m_gdcmIOExport = ImageIOTypeExport::New();
// m_itkSeriesReaderExport = SeriesReaderTypeExport::New();
// m_itkSeriesReaderExport->SetImageIO(m_gdcmIOExport);
// m_itkConnectorExport = ConnectorTypeExport::New();
// m_inputNamesExport = InputNamesGeneratorTypeExport::New();
}
void DicomExporter::loadDicomFileAndRender(int file_type)
{
// try
// {
// m_itkSeriesReaderExport->Update();
// }
// catch (itk::ExceptionObject &excp) {
// std::cerr << "Exception thrown while reading the series" << std::endl;
// std::cerr << excp << std::endl;
// }
//
// m_itkConnectorExport->SetInput(m_itkSeriesReaderExport->GetOutput());
// m_itkConnectorExport->Update();
//
// m_imageViewerExport->SetInputData(m_itkConnectorExport->GetOutput());
//
// m_imageViewerExport->Render();
// m_imageViewerExport->SetSlice(0);
//
// //m_imageViewerExport->GetRenderer()->ResetCamera();
//
//
// infinitiViewer *viewer = exportOptions.serie->getImageViewer2();
//
// if (exportOptions.windowLevel != -1)
// {
// m_imageViewerExport->SetColorLevel(exportOptions.windowLevel);
// }
//
// if (exportOptions.windowWidth != -1)
// {
// m_imageViewerExport->SetColorWindow(exportOptions.windowWidth);
// }
//
// if (exportOptions.cornerAnnotation != ExportOptions::CornerAnnotation::Disabled)
// {
// if (AnnoHelper::IsAnno()) {
// vtkCornerAnnotation* ann = m_imageViewerExport->GetvtkCornerAnnotation();
// ann->SetMaximumFontSize(20);
// ann->CopyAllTextsFrom(viewer->GetvtkCornerAnnotation());
// ann->SetText(BOTTOM_LEFT, "");
//
// std::string lbl_ser_num;
// std::string ser_num;
// itk::GDCMImageIO::GetLabelFromTag(USER_CONFIG::TAG_SERIES_NUMBER, lbl_ser_num);
// m_gdcmIOExport->GetValueFromTag(USER_CONFIG::TAG_SERIES_NUMBER, ser_num);
// m_imageViewerExport->initTopLeftCornerInfo(lbl_ser_num, ser_num);
// }
// }
//
//
// double vup[3];
// double vup2[3];
// vtkCamera *oriCamera = viewer->GetRenderer()->GetActiveCamera();
// double scale = exportOptions.serie->GetExtent();
// oriCamera->GetViewUp(vup);
//
// vtkCamera *expCamera = m_imageViewerExport->GetRenderer()->GetActiveCamera();
// expCamera->SetParallelScale(scale);
// expCamera->GetViewUp(vup2);
// expCamera->SetViewUp(vup);
//
// if (FlipExportHelper::GetFlip())
// {
// expCamera->Azimuth(180);
// m_imageViewerExport->GetRenderer()->ResetCameraClippingRange();
//
// }
// m_imageViewerExport->GetRenderWindow()->Render();
}
void DicomExporter::doExport(int file_type)
{
if (file_type == SingleFile)
{
exportedNumber++;//image number starts from 1
QString fileName = exportOptions.exportDirectory + "/" + exportOptions.fileNamePrefix + QString::number(exportedNumber) + getFileExtention();
writeToFile(fileName);
emit exportProgress(totalCount, exportedNumber);
}
else if(file_type == DirType)
{
int m_MinSliceExport = m_imageViewerExport->GetSliceMin();
int m_MaxSliceExport = m_imageViewerExport->GetSliceMax();
for (int i = m_MinSliceExport; i <= m_MaxSliceExport; i++)
{
m_imageViewerExport->SetSlice(i);
//m_imageViewerExport->Render();
exportedNumber++;//image number starts from 1
QString fileName = exportOptions.exportDirectory + "/" + exportOptions.fileNamePrefix + QString::number(exportedNumber) + getFileExtention();
writeToFile(fileName);
emit exportProgress(totalCount, exportedNumber);
}
}
else
{
return;
}
}
void DicomExporter::writeToFile(const QString& fileName)
{
// Screenshot
vtkSmartPointer<vtkWindowToImageFilter> windowToImageFilter = vtkSmartPointer<vtkWindowToImageFilter>::New();
windowToImageFilter->SetInput(m_glrenWinExport);
#if VTK_MAJOR_VERSION >= 8 || VTK_MAJOR_VERSION == 8 && VTK_MINOR_VERSION >= 90
windowToImageFilter->SetScale(2); // image quality
#else
windowToImageFilter->SetMagnification(2); //image quality
#endif
windowToImageFilter->Update();
switch (exportOptions.exportFileFormat)
{
case ExportOptions::FileFormat::Bmp:
writeToBmpFile(windowToImageFilter, fileName);
break;
case ExportOptions::FileFormat::Jpeg:
writeToJpgFile(windowToImageFilter, fileName);
break;
case ExportOptions::FileFormat::Png:
writeToPngFile(windowToImageFilter, fileName);
break;
case ExportOptions::FileFormat::Tiff:
writeToTiffFile(windowToImageFilter, fileName);
break;
default:
break;
}
}
QString DicomExporter::getFileExtention()
{
QString fileExtention = ".png";
switch (exportOptions.exportFileFormat)
{
case ExportOptions::FileFormat::Bmp:
fileExtention = ".bmp";
break;
case ExportOptions::FileFormat::Jpeg:
fileExtention = ".jpg";
break;
case ExportOptions::FileFormat::Png:
fileExtention = ".png";
break;
case ExportOptions::FileFormat::Tiff:
fileExtention = ".tiff";
break;
case ExportOptions::FileFormat::Dicom:
fileExtention = ".dcm";
break;
default:
break;
}
return fileExtention;
}
void DicomExporter::writeToPngFile(vtkSmartPointer<vtkWindowToImageFilter> windowToImageFilter, const QString& fileName)
{
QByteArray bafileName = fileName.toLocal8Bit();
vtkSmartPointer<vtkPNGWriter> writer = vtkSmartPointer<vtkPNGWriter>::New();
writer->SetFileName(bafileName.data());
writer->SetInputConnection(windowToImageFilter->GetOutputPort());
writer->Write();
}
void DicomExporter::writeToBmpFile(vtkSmartPointer<vtkWindowToImageFilter> windowToImageFilter, const QString& fileName)
{
QByteArray bafileName = fileName.toLocal8Bit();
vtkSmartPointer<vtkBMPWriter> writer = vtkSmartPointer<vtkBMPWriter>::New();
writer->SetFileName(bafileName.data());
writer->SetInputConnection(windowToImageFilter->GetOutputPort());
writer->Write();
}
void DicomExporter::writeToJpgFile(vtkSmartPointer<vtkWindowToImageFilter> windowToImageFilter, const QString& fileName)
{
QByteArray bafileName = fileName.toLocal8Bit();
vtkSmartPointer<vtkJPEGWriter> writer = vtkSmartPointer<vtkJPEGWriter>::New();
writer->SetFileName(bafileName.data());
writer->SetInputConnection(windowToImageFilter->GetOutputPort());
writer->Write();
}
void DicomExporter::writeToTiffFile(vtkSmartPointer<vtkWindowToImageFilter> windowToImageFilter, const QString& fileName)
{
QByteArray bafileName = fileName.toLocal8Bit();
vtkSmartPointer<vtkTIFFWriter> writer = vtkSmartPointer<vtkTIFFWriter>::New();
writer->SetFileName(bafileName.data());
writer->SetInputConnection(windowToImageFilter->GetOutputPort());
writer->Write();
}
void DicomExporter::exportPicture(const QString& fileName)
{
// int myFileType = NonType;
//
// QFileInfo fileInfo(fileName);
// QDir dir(fileName);
//
// if (fileInfo.isFile())
// {
// m_itkSeriesReaderExport->SetFileName(fileName.toStdString());
//
// myFileType = SingleFile;
// }
// else if (dir.exists())
// {
// m_inputNamesExport->SetInputDirectory(fileName.toStdString());
// const SeriesReaderTypeExport::FileNamesContainer & filenames = m_inputNamesExport->GetInputFileNames();
// m_itkSeriesReaderExport->SetFileNames(filenames);
//
// myFileType = DirType;
// }
//
// if (myFileType != NonType)
// {
// loadDicomFileAndRender(myFileType);
// doExport(myFileType);
// }
}
void DicomExporter::exportDicom(const QString& fileName)
{
// bool isFileValid = false;
//
// QFileInfo fileInfo(fileName);
// QDir dir(fileName);
//
// if (fileInfo.isFile())
// {
// m_itkSeriesReaderExport->SetFileName(fileName.toStdString());
//
// exportSingleDicomFile(fileName);
// }
// else if (dir.exists())
// {
// m_inputNamesExport->SetInputDirectory(fileName.toStdString());
// const SeriesReaderTypeExport::FileNamesContainer & filenames = m_inputNamesExport->GetInputFileNames();
// m_itkSeriesReaderExport->SetFileNames(filenames);
//
// exportDicomDirectory(fileName);
// }
}
void DicomExporter::exportSingleDicomFile(const QString& fileName)
{
// try
// {
// m_itkSeriesReaderExport->UpdateLargestPossibleRegion();
// m_itkSeriesReaderExport->Update();
// }
// catch (itk::ExceptionObject &excp) {
// std::cerr << "Exception thrown while reading the series" << std::endl;
// std::cerr << excp << std::endl;
// }
//
// exportedNumber++;//image number starts from 1
// QString exportedName = exportOptions.exportDirectory + "\\" + exportOptions.fileNamePrefix + QString::number(exportedNumber) + ".dcm";
// QByteArray bafileName = exportedName.toLocal8Bit();
//
//
// SeriesWriterType::Pointer seriesWriter = SeriesWriterType::New();
// seriesWriter->SetImageIO(m_gdcmIOExport);
// seriesWriter->SetInput(m_itkSeriesReaderExport->GetOutput());
// seriesWriter->SetFileName(std::string(bafileName));
//
// SeriesReaderTypeExport::DictionaryArrayRawPointer dicArray = m_itkSeriesReaderExport->GetMetaDataDictionaryArray();
// modifyDicomTags(dicArray);
// seriesWriter->SetMetaDataDictionaryArray(dicArray);
//
// try
// {
// seriesWriter->Update();
//
// emit exportProgress(totalCount, exportedNumber);
// }
// catch (itk::ExceptionObject & excp)
// {
// std::cerr << "Exception thrown while writing the series " << std::endl;
// std::cerr << excp << std::endl;
// }
}
void DicomExporter::exportDicomDirectory(const QString& fileName)
{
// try
// {
// m_itkSeriesReaderExport->Update();
// }
// catch (itk::ExceptionObject &excp) {
// std::cerr << "Exception thrown while reading the series" << std::endl;
// std::cerr << excp << std::endl;
// }
//
// m_inputNamesExport->SetOutputDirectory(exportOptions.exportDirectory.toStdString());
//
// itk::SerieUIDContainer newOutNames;
// itk::SerieUIDContainer oldOutputNames = m_inputNamesExport->GetOutputFileNames();
// for (int i = 0; i < oldOutputNames.size(); i++)
// {
// std::string originName = oldOutputNames.at(i);
// QFileInfo fileinfo(QString::fromStdString(originName));
// QString fName = fileinfo.fileName();
// QString fPath = fileinfo.absolutePath();
//
// exportedNumber++;//image number starts from 1
// QString newName = fPath + "\\" + exportOptions.fileNamePrefix + QString::number(exportedNumber) + ".dcm";
// QByteArray bafileName = newName.toLocal8Bit();
//
// newOutNames.push_back(std::string(bafileName));
// }
//
// SeriesWriterType::Pointer seriesWriter = SeriesWriterType::New();
// seriesWriter->SetImageIO(m_gdcmIOExport);
// seriesWriter->SetInput(m_itkSeriesReaderExport->GetOutput());
// seriesWriter->SetFileNames(newOutNames);
//
// SeriesReaderTypeExport::DictionaryArrayRawPointer dicArray = m_itkSeriesReaderExport->GetMetaDataDictionaryArray();
// modifyDicomTags(dicArray);
// seriesWriter->SetMetaDataDictionaryArray(dicArray);
//
// try
// {
// emit exportProgress(totalCount, exportedNumber / 2);
//
// seriesWriter->Update();
//
// emit exportProgress(totalCount, exportedNumber);
// }
// catch (itk::ExceptionObject & excp)
// {
// std::cerr << "Exception thrown while writing the series " << std::endl;
// std::cerr << excp << std::endl;
// }
}
//void DicomExporter::modifyDicomTags(SeriesReaderTypeExport::DictionaryArrayRawPointer dicArray)
//{
// for (int i = 0; i < (*dicArray).size(); i++)
// {
// itk::MetaDataDictionary *dic = (*dicArray).at(i);
//
// if (exportOptions.windowLevel != -1)
// {
// std::string entryId(TAG_WindowLevel);
// itk::EncapsulateMetaData<std::string>(*dic, entryId, std::to_string(exportOptions.windowLevel));
// }
//
// if (exportOptions.windowWidth != -1)
// {
// std::string entryId(TAG_WindowWidth);
// itk::EncapsulateMetaData<std::string>(*dic, entryId, std::to_string(exportOptions.windowWidth));
// }
//
// if (exportOptions.isAnonymization)
// {
// itk::EncapsulateMetaData<std::string>(*dic, TAG_InstitutionName, "anonymized");
// itk::EncapsulateMetaData<std::string>(*dic, TAG_InstitutionAddress, "anonymized");
// itk::EncapsulateMetaData<std::string>(*dic, TAG_ReferringPhysicianName, "anonymized");
// itk::EncapsulateMetaData<std::string>(*dic, TAG_OperatorsName, "anonymized");
// itk::EncapsulateMetaData<std::string>(*dic, TAG_PatientAddress, "anonymized");
// itk::EncapsulateMetaData<std::string>(*dic, TAG_PatientTelephoneNumbers, "anonymized");
// itk::EncapsulateMetaData<std::string>(*dic, TAG_OtherPatientNames, "anonymized");
// itk::EncapsulateMetaData<std::string>(*dic, TAG_OtherPatientIDs, "anonymized");
// itk::EncapsulateMetaData<std::string>(*dic, TAG_OtherPatientIDsSequence, "");
// itk::EncapsulateMetaData<std::string>(*dic, TAG_PatientName, "anonymized");
// itk::EncapsulateMetaData<std::string>(*dic, TAG_PatientBirthDate, "19000101");
// itk::EncapsulateMetaData<std::string>(*dic, TAG_PatientSex, "NA");
// itk::EncapsulateMetaData<std::string>(*dic, TAG_PatientAge, "NA");
// itk::EncapsulateMetaData<std::string>(*dic, TAG_PatientID, "anonymized");
// itk::EncapsulateMetaData<std::string>(*dic, TAG_AccessionNumber, "anonymized");
// }
//
// }//for end
//}
void DicomExporter::caculateExportTotalCount()
{
for (int i = 0; i < exportOptions.inputData.size(); i++)
{
QString fileName = exportOptions.inputData.at(i);
QFileInfo fileInfo(fileName);
QDir dir(fileName);
if (fileInfo.isFile())
{
totalCount++;
}
else if (dir.exists())
{
QStringList filter;
QFileInfoList fileList = dir.entryInfoList(filter);
totalCount += fileList.count();
totalCount -= 2;
}
auto property = exportOptions.inputData.at(i);
totalCount+= property->GetFileNames().size();
}
}

View File

@@ -3,12 +3,6 @@
#include <QObject>
#include "exportoptions.h"
//#include <itkImage.h>
//#include <itkGDCMImageIO.h>
//#include <itkImageSeriesReader.h>
//#include <itkImageSeriesWriter.h>
//#include <itkImageToVTKImageFilter.h>
//#include <itkGDCMSeriesFileNames.h>
#include <vtkRenderer.h>
#include <vtkSmartPointer.h>
#include <vtkRenderWindow.h>
@@ -24,8 +18,6 @@
#include <sstream>
#include "Rendering/Viewer/DICOMImageViewer.h"
//#include "itkMetaDataObject.h"
//#include "itkMetaDataDictionary.h"
class DicomExporter : public QObject
@@ -45,79 +37,18 @@ public:
signals:
void exportFinished();
void exportError();
void exportProgress(int total, int progress);
public slots:
private:
//dicom tags
const std::string TAG_WindowLevel = "0028|1050";
const std::string TAG_WindowWidth = "0028|1051";
//anonymization
const std::string TAG_InstitutionName = "0008|0080";
const std::string TAG_InstitutionAddress = "0008|0081";
const std::string TAG_ReferringPhysicianName = "0008|0090";
const std::string TAG_OperatorsName = "0008|1070";
const std::string TAG_PatientAddress = "0010|1040";
const std::string TAG_PatientTelephoneNumbers = "0010|2154";
const std::string TAG_OtherPatientNames = "0010|1001";
const std::string TAG_OtherPatientIDs = "0010|1000";
const std::string TAG_OtherPatientIDsSequence = "0010|1002";
const std::string TAG_PatientName = "0010|0010";
const std::string TAG_PatientBirthDate = "0010|0030";
const std::string TAG_PatientSex = "0010|0040";
const std::string TAG_PatientAge = "0010|1010";
const std::string TAG_PatientID = "0010|0020";
const std::string TAG_AccessionNumber = "0008|0050";
//bmp jpg png tiff exprt releated objects
static const unsigned int InputDimensionExport = 3;
typedef signed short PixelTypeExport;
// typedef itk::Image<PixelTypeExport, InputDimensionExport> InputImageTypeExport;
// typedef itk::GDCMImageIO ImageIOTypeExport;
// typedef itk::ImageSeriesReader<InputImageTypeExport> SeriesReaderTypeExport;
// typedef itk::ImageToVTKImageFilter<InputImageTypeExport> ConnectorTypeExport;
// typedef itk::GDCMSeriesFileNames InputNamesGeneratorTypeExport;
//dicom export releated objects
typedef signed short OutputPixelType;
static const unsigned int OutputDimension = 2;
// typedef itk::Image<OutputPixelType, OutputDimension> Image2DType;
// typedef itk::ImageSeriesWriter<InputImageTypeExport, Image2DType> SeriesWriterType;
private:
void initVTK();
void initDataReader();
void loadDicomFileAndRender(int file_type);
//void updateCornerInfo(int slice, int maxslice);
void doExport(int file_type);
QString getFileExtention();
void writeToFile(const QString& fileName);
void writeToPngFile(vtkSmartPointer<vtkWindowToImageFilter> windowToImageFilter, const QString& fileName);
void writeToBmpFile(vtkSmartPointer<vtkWindowToImageFilter> windowToImageFilter, const QString& fileName);
void writeToJpgFile(vtkSmartPointer<vtkWindowToImageFilter> windowToImageFilter, const QString& fileName);
void writeToTiffFile(vtkSmartPointer<vtkWindowToImageFilter> windowToImageFilter, const QString& fileName);
void exportPicture(const QString& fileName);
void exportDicom(const QString& fileName);
void exportSingleDicomFile(const QString& fileName);
void exportDicomDirectory(const QString& fileName);
// void modifyDicomTags(SeriesReaderTypeExport::DictionaryArrayRawPointer dicArray);
const char* getFileExtention();
void caculateExportTotalCount();
private:
ExportOptions exportOptions;
int totalCount;//the total count of image to be exported
int exportedNumber;//the exported image index
//itk vtk releated objects
// ImageIOTypeExport::Pointer m_gdcmIOExport;
// SeriesReaderTypeExport::Pointer m_itkSeriesReaderExport;
// ConnectorTypeExport::Pointer m_itkConnectorExport;
// InputNamesGeneratorTypeExport::Pointer m_inputNamesExport;
vtkSmartPointer<vtkRenderWindow> m_glrenWinExport;
vtkSmartPointer<DICOMImageViewer> m_imageViewerExport;
};
#endif // DICOMEXPORTER_H

View File

@@ -6,14 +6,16 @@
#include <qlist.h>
class SeriesImageSet;
class ExtendMedicalImageProperties;
class ExportOptions
{
public:
explicit ExportOptions();
QList<QString> inputData;//the fileName or directory list to export
QList<ExtendMedicalImageProperties*> inputData;
int slice = -1l;
int windowWidth;//exported window width
int windowLevel;//exported window level
@@ -41,7 +43,6 @@ public:
QSize customPictureSize;//apply when user choose customsize
SeriesImageSet *serie;
};
#endif // EXPORTOPTIONS_H

View File

@@ -6,7 +6,6 @@
#include <vtkImageData.h>
#include <vtkImageResize.h>
#include <vtkBMPWriter.h>
#include <vtkNew.h>
#include "IO/DICOM/DICOMPixelDataHelper.h"

View File

@@ -0,0 +1,39 @@
//
// Created by Krad on 2022/9/28.
//
#include "DICOMToQImageConverter.h"
#include <vtkImageData.h>
#include <QImage>
#include "IO/DICOM/DICOMPixelDataHelper.h"
void DICOMToQImageConverter::save(const char *filename) {
if (! m_DICOMFileName.empty()) {
void* data = nullptr;
int size[2] = {0, 0};
if (m_Frame < 0) {
DICOMPixelDataHelper::GetRenderedBuffer(m_DICOMFileName.c_str(),
data,size, m_Sample, m_Window[0], m_Window[1]);
} else {
DICOMPixelDataHelper::GetMultiFrameRenderedBuffer(m_DICOMFileName.c_str(),
data,size, m_Sample,m_Frame, m_Window[0], m_Window[1]);
}
if(data){
m_Image = new QImage((uchar*)data,size[0],size[1],QImage::Format_RGB888);
}
}
}
QImage *DICOMToQImageConverter::getQImage() {
return m_Image;
}
DICOMToQImageConverter::DICOMToQImageConverter():ConverterBase() {
}
DICOMToQImageConverter::~DICOMToQImageConverter() {
}

View File

@@ -0,0 +1,27 @@
//
// Created by Krad on 2022/9/28.
//
#ifndef OMEGAV_DICOMTOQIMAGECONVERTER_H
#define OMEGAV_DICOMTOQIMAGECONVERTER_H
#include "ConverterBase.h"
class QImage;
class DICOMToQImageConverter:public ConverterBase {
public:
DICOMToQImageConverter();
~DICOMToQImageConverter() override ;
/**
* 保存函数
* @param filename 输出的绝对路径
*/
void save(const char *filename = nullptr) override;
QImage* getQImage();
private:
QImage* m_Image = nullptr;
};
#endif //OMEGAV_DICOMTOQIMAGECONVERTER_H

View File

@@ -263,6 +263,67 @@ bool DICOMPixelDataHelper::GetRenderedData(const char *path, vtkImageData *data,
return false;
}
bool DICOMPixelDataHelper::GetMultiFrameRenderedData(const char *path, vtkImageData *data, int sample, int frame,
double windowLevel, double windowWidth) {
auto fileFormat = DICOMFileObjectCache::getInstance()->GetFileObject(path);
if (!fileFormat){
fileFormat = new DcmFileFormat;
if (fileFormat->loadFile(path).good() && fileFormat->loadAllDataIntoMemory().good()) {
DICOMFileObjectCache::getInstance()->store(path,fileFormat);
}
else{
return false;
}
}
DicomImage dcmImage(fileFormat, fileFormat->getDataset()->getOriginalXfer(), CIF_UsePartialAccessToPixelData,
frame, 1);
if (dcmImage.getStatus() == EIS_Normal) {
RenderToImageData(data, sample, windowLevel, windowWidth, dcmImage);
return true;
}
return false;
}
bool DICOMPixelDataHelper::GetRenderedBuffer(const char *path, void *&buffer, int*size, int sample, double windowLevel,
double windowWidth) {
DcmFileFormat fileFormat;
if (fileFormat.loadFile(path).good()) {
DcmDataset *dset = fileFormat.getDataset();
DicomImage dcmImage(&fileFormat, dset->getOriginalXfer(), CIF_MayDetachPixelData);
size[0] =dcmImage.getWidth();
size[1] =dcmImage.getHeight();
RenderToBuffer(buffer, sample, windowLevel, windowWidth, dcmImage);
return true;
}
return false;
}
bool DICOMPixelDataHelper::GetMultiFrameRenderedBuffer(const char *path, void *&buffer,int*size, int sample, int frame,
double windowLevel, double windowWidth) {
auto fileFormat = DICOMFileObjectCache::getInstance()->GetFileObject(path);
if (!fileFormat){
fileFormat = new DcmFileFormat;
if (fileFormat->loadFile(path).good() && fileFormat->loadAllDataIntoMemory().good()) {
DICOMFileObjectCache::getInstance()->store(path,fileFormat);
}
else{
return false;
}
}
auto dataset = fileFormat->getDataset();
DicomImage dcmImage(dataset, dataset->getOriginalXfer(), CIF_UsePartialAccessToPixelData,
frame, 1);
if (dcmImage.getStatus() == EIS_Normal) {
size[0] =dcmImage.getWidth();
size[1] =dcmImage.getHeight();
RenderToBuffer(buffer, sample, windowLevel, windowWidth, dcmImage);
return true;
}
return false;
}
void DICOMPixelDataHelper::RenderToImageData(vtkImageData *data, int sample, double windowLevel, double windowWidth,
DicomImage &dcmImage) {//flip for vtk writer
dcmImage.flipImage(0,1);
@@ -275,23 +336,12 @@ void DICOMPixelDataHelper::RenderToImageData(vtkImageData *data, int sample, dou
dcmImage.createWindowsDIB(d,dcmImage.getWidth()*dcmImage.getHeight()*3 );
}
bool DICOMPixelDataHelper::GetMultiFrameRenderedData(const char *path, vtkImageData *data, int sample, int frame,
double windowLevel, double windowWidth) {
auto fileFormat = DICOMFileObjectCache::getInstance()->GetFileObject(path);
if (!fileFormat){
fileFormat = new DcmFileFormat;
if (fileFormat->loadFile(path).good() && fileFormat->loadAllDataIntoMemory().good()) {
DICOMFileObjectCache::getInstance()->store(path,fileFormat);
DicomImage dcmImage(fileFormat, fileFormat->getDataset()->getOriginalXfer(), CIF_UsePartialAccessToPixelData,
frame, 1);
if (dcmImage.getStatus() == EIS_Normal) {
RenderToImageData(data, sample, windowLevel, windowWidth, dcmImage);
delete fileFormat;
return true;
}
}
void DICOMPixelDataHelper::RenderToBuffer(void *&data, int sample, double windowLevel, double windowWidth,
DicomImage &dcmImage) {
if (sample == 1){
dcmImage.setWindow(windowLevel, windowWidth);
}
delete fileFormat;
return false;
long length = dcmImage.getWidth()*dcmImage.getHeight()*3;
data = new uchar[length];
dcmImage.createWindowsDIB(data,length);
}

View File

@@ -44,6 +44,8 @@ public:
*/
static bool GetRenderedData(const char * path, vtkImageData* data, int sample, double windowLevel, double windowWidth);
static bool GetRenderedBuffer(const char * path, void*& buffer,int* size, int sample, double windowLevel, double windowWidth);
/**
* 从Multi-frame类型的DICOM文件中获取已渲染图像
* 至vtkImageData中主要用于DICOM数据的导出
@@ -58,6 +60,8 @@ public:
* @return
*/
static bool GetMultiFrameRenderedData(const char * path, vtkImageData* data, int sample,int frame, double windowLevel, double windowWidth);
static bool GetMultiFrameRenderedBuffer(const char * path, void*& data,int* size, int sample,int frame, double windowLevel, double windowWidth);
/**
* Get Pixel Data with Rescaled, result is calculate as integer, and arrange as integer.
*
@@ -172,6 +176,9 @@ public:
*/
static void
RenderToImageData(vtkImageData *data, int sample, double windowLevel, double windowWidth, DicomImage &dcmImage);
static void
RenderToBuffer(void *&data, int sample, double windowLevel, double windowWidth, DicomImage &dcmImage);
};

View File

@@ -1,12 +1,20 @@
#include "exportdialog.h"
#include "ui_exportdialog.h"
#include <QDesktopServices>
#include "UI/Manager/ImageViewManager.h"
#include "Deprecated/Export/dicomexporterthread.h"
ExportDialog::ExportDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::ExportDialog)
ui(new Ui::ExportDialog),
worker(nullptr)
{
ui->setupUi(this);
ui->progressBar->setVisible(false);
ui->rbDICOM->setVisible(false);
ui->rbTIFF->setVisible(false);
init();
}
@@ -63,33 +71,28 @@ void ExportDialog::onBtnExportClicked()
//export files
if (ui->rbCurrentImage->isChecked())//current image
{
if (cur_view->hasSeries())
if (m_Manager->getCurrentView()->hasSeries())
{
QString imageName(cur_view->getSeriesInstance()->getCurImageName());
options.inputData.push_back(imageName);
auto property = m_Manager->getCurrentView()->getSeriesInstance()->GetProperty();
options.inputData.push_back(property);
options.slice = m_Manager->getCurrentView()->getSlice();
}
}
else if (ui->rbCurrentSeries->isChecked())//current series
{
if (cur_view->hasSeries())
if (m_Manager->getCurrentView()->hasSeries())
{
QString serieName(cur_view->getSeriesInstance()->getSeriesName());
options.inputData.push_back(serieName);
auto property = m_Manager->getCurrentView()->getSeriesInstance()->GetProperty();
options.inputData.push_back(property);
}
}
else if (ui->rbAllOpendSeries->isChecked())// all opened series
{
//disable this function
// InstancesVecType instanceVec;
// DicomLoader::GetInstance()->getOpenedInstancesVec(instanceVec);
// for (int i = 0; i < instanceVec.size(); i++)
// {
// SeriesImageSet *instance = instanceVec.at(i);
// if (instance != nullptr)
// {
// options.inputData.push_back(instance->getSeriesName());
// }
// }
for(auto view:m_Manager->getViewList()){
if (view->hasSeries()){
options.inputData.push_back(view->getSeriesInstance()->GetProperty());
}
}
}
if (ui->rbJPEG->isChecked())
@@ -139,10 +142,10 @@ void ExportDialog::onBtnExportClicked()
options.isAnonymization = false;
}
options.windowLevel = cur_view->getImageViewer()->GetColorLevel();
options.windowWidth = cur_view->getImageViewer()->GetColorWindow();
options.serie = cur_view->getSeriesInstance();
DicomExporterThread *worker = new DicomExporterThread(options);
options.windowLevel = m_Manager->getCurrentView()->getImageViewer()->GetColorLevel();
options.windowWidth = m_Manager->getCurrentView()->getImageViewer()->GetColorWindow();
worker = new DicomExporterThread(options);
//disconnect(worker, SIGNAL(exportProgress(int, int)), this, SLOT(onExportProgress(int, int)));
connect(worker, SIGNAL(exportProgress(int, int)), this, SLOT(onExportProgress(int, int)));
@@ -169,14 +172,13 @@ void ExportDialog::onExportFinished()
{
ui->progressBar->setVisible(false);
ui->btnExport->setEnabled(true);
if (ui->cbShowAfterExport->isChecked()){
QDesktopServices::openUrl(QUrl(QString("file:///%1").arg(ui->edtExportFolder->text())));
}
}
void ExportDialog::setCurView(DicomImageView *view)
void ExportDialog::setViewManager(ImageViewManager *manager)
{
cur_view = view;
m_Manager = manager;
}
//void ExportDialog::setViewContainer(ViewContainerWidget *widget)
//{
// viewContainerWidget = widget;
//}

View File

@@ -4,13 +4,12 @@
#include <QDialog>
#include "Deprecated/Export/exportoptions.h"
#include "qdir.h"
#include "Deprecated/Export/dicomexporterthread.h"
#include "QFileDialog"
#include "IO/DICOM/DicomLoader.h"
#include "UI/Widget/ImageView/dicomimageview.h"
class DicomExporterThread;
class ImageViewManager;
namespace Ui {
class ExportDialog;
@@ -24,7 +23,7 @@ public:
explicit ExportDialog(QWidget *parent = nullptr);
~ExportDialog();
//void setViewContainer(ViewContainerWidget *widget)
void setCurView(DicomImageView *view);
void setViewManager(ImageViewManager *manager);
public slots:
void onBtnExportClicked();
@@ -40,7 +39,8 @@ private:
private:
Ui::ExportDialog *ui;
//ViewContainerWidget *viewContainerWidget;
DicomImageView *cur_view;
ImageViewManager *m_Manager;
DicomExporterThread *worker;
};
#endif // EXPORTDIALOG_H

View File

@@ -135,36 +135,9 @@
<string>Export Location</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Export Folder</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="edtExportFolder"/>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="btnSelectFolder">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>Choose Folder...</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>FileName Prefix</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="edtFileNamePrefix"/>
</item>
<item row="1" column="2">
<spacer name="horizontalSpacer">
<property name="orientation">
@@ -178,6 +151,40 @@
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Export Folder</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>FileName Prefix</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="edtFileNamePrefix"/>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="btnSelectFolder">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>Choose Folder...</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="cbShowAfterExport">
<property name="text">
<string>Show in Explorer after exported</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@@ -287,8 +294,8 @@
<resources/>
<connections/>
<buttongroups>
<buttongroup name="buttonGroup_2"/>
<buttongroup name="buttonGroup_3"/>
<buttongroup name="buttonGroup_2"/>
<buttongroup name="buttonGroup"/>
</buttongroups>
</ui>

View File

@@ -495,6 +495,9 @@ void DicomImageView::setSlice(int slice) {
mImageViewer->SetSlice(slice);
}
}
int DicomImageView::getSlice(){
return mImageViewer->GetSlice();
}
void DicomImageView::addSlice(int step) {
if (mImageViewer == nullptr) {

View File

@@ -113,6 +113,9 @@ public:
void setSlice(int slice);
int getSlice();
//Sync zoom
void setZoomScale(double scale);

View File

@@ -219,7 +219,7 @@ void QDicomViewer::initGeneralTool() {
connect(ui->toolBar, &DefaultToolBar::save, this, [=] {
if (nullptr == exportDialog) {
exportDialog = new ExportDialog(this);
exportDialog->setCurView(ui->viewContainer->getCurrentView());
exportDialog->setViewManager(ui->viewContainer->getViewManager());
exportDialog->setModal(false);
}
exportDialog->show();