Add dcm converter(BMP, PNG, JPG).

This commit is contained in:
Krad
2022-09-21 17:16:14 +08:00
parent e74292c361
commit ccb67f478d
12 changed files with 340 additions and 13 deletions

View File

@@ -0,0 +1,70 @@
//
// Created by Krad on 2022/9/21.
//
#include "ConverterBase.h"
#include <vtkImageData.h>
#include <vtkImageResize.h>
#include <vtkBMPWriter.h>
#include <vtkNew.h>
#include "IO/DICOM/DICOMPixelDataHelper.h"
void ConverterBase::setOutputSize(int height, int width) {
m_Size[0] = height;
m_Size[1] = width;
m_keepSize = false;
}
void ConverterBase::setInputDICOMFile(const char *filename) {
m_DICOMFileName = filename;
}
void ConverterBase::loadDICOMPixelData() {
if (! m_DICOMFileName.empty()){
m_ImageData = vtkImageData::New();
if (m_Frame<0){
DICOMPixelDataHelper::GetRenderedData(m_DICOMFileName.c_str(),
m_ImageData,m_Sample,m_Window[0],m_Window[1]);
}
else{
DICOMPixelDataHelper::GetMultiFrameRenderedData(m_DICOMFileName.c_str(),
m_ImageData,m_Frame,m_Sample,m_Window[0],m_Window[1]);
}
if (!m_keepSize){
vtkNew<vtkImageResize>resize;
resize->SetInputData(m_ImageData);
resize->SetInterpolate(true);
resize->SetResizeMethodToOutputDimensions();
resize->SetOutputDimensions(m_Size[0],m_Size[1], -1);
resize->Update();
m_ImageData->DeepCopy(resize->GetOutput());
}
}
}
void ConverterBase::setFileName(const char *filename) {
m_OutputFileName = filename;
}
ConverterBase::~ConverterBase() {
if (m_ImageData){
m_ImageData->Delete();
m_ImageData = nullptr;
}
}
void ConverterBase::setColorImage(int sample) {
m_Sample = sample;
}
void ConverterBase::setWindow(double windowLevel, double windowWidth) {
m_Window[0] = windowLevel;
m_Window[1] = windowWidth;
}
void ConverterBase::setFrame(int frame) {
m_Frame = frame;
}

View File

@@ -0,0 +1,41 @@
//
// Created by Krad on 2022/9/21.
//
#ifndef OMEGAV_CONVERTERBASE_H
#define OMEGAV_CONVERTERBASE_H
#include <string>
class vtkImageData;
class ConverterBase {
public:
ConverterBase() = default;
virtual ~ConverterBase();
void setOutputSize(int height, int width);
void setInputDICOMFile(const char* filename);
void setFileName(const char* filename);
void setColorImage(int sample);
void setWindow(double windowLevel, double windowWidth);
void setFrame(int frame);
virtual void save(const char* filename){};
protected:
void loadDICOMPixelData();
int m_Size[2] = {100,100};
double m_Window[2] = {128.0,256.0};
int m_Sample = 1;
int m_Frame = -1;
std::string m_DICOMFileName;
std::string m_OutputFileName;
bool m_keepSize = true;
vtkImageData* GetInputData(){
return m_ImageData;
}
private:
ConverterBase(const ConverterBase&) = delete;
ConverterBase operator=(const ConverterBase&) = delete;
vtkImageData* m_ImageData = nullptr;
};
#endif //OMEGAV_CONVERTERBASE_H

View File

@@ -0,0 +1,24 @@
//
// Created by Krad on 2022/9/21.
//
#include "DICOMToBMPConverter.h"
#include "vtkNew.h"
#include "vtkImageData.h"
#include "vtkBMPWriter.h"
void DICOMToBMPConverter::save(const char *filename) {
loadDICOMPixelData();
vtkNew<vtkBMPWriter> writer;
writer->SetInputData(GetInputData());
writer->SetFileName(filename);
writer->Update();
}
DICOMToBMPConverter::DICOMToBMPConverter() {
}
DICOMToBMPConverter::~DICOMToBMPConverter() {
}

View File

@@ -0,0 +1,18 @@
//
// Created by Krad on 2022/9/21.
//
#ifndef OMEGAV_DICOMTOBMPCONVERTER_H
#define OMEGAV_DICOMTOBMPCONVERTER_H
#include "ConverterBase.h"
class DICOMToBMPConverter:public ConverterBase {
public:
DICOMToBMPConverter();
~DICOMToBMPConverter();
void save(const char* filename) override ;
};
#endif //OMEGAV_DICOMTOBMPCONVERTER_H

View File

@@ -0,0 +1,26 @@
//
// Created by Krad on 2022/9/21.
//
#include "DICOMToJPEGConverter.h"
#include <vtkNew.h>
#include <vtkImageData.h>
#include <vtkJPEGWriter.h>
DICOMToJPEGConverter::DICOMToJPEGConverter() {
}
DICOMToJPEGConverter::~DICOMToJPEGConverter() {
}
void DICOMToJPEGConverter::save(const char *filename) {
loadDICOMPixelData();
vtkNew<vtkJPEGWriter> writer;
writer->SetQuality(m_Quality);
writer->SetInputData(GetInputData());
writer->SetFileName(filename);
writer->Write();
}

View File

@@ -0,0 +1,25 @@
//
// Created by Krad on 2022/9/21.
//
#ifndef OMEGAV_DICOMTOJPEGCONVERTER_H
#define OMEGAV_DICOMTOJPEGCONVERTER_H
#include "ConverterBase.h"
class DICOMToJPEGConverter: public ConverterBase {
public:
DICOMToJPEGConverter();
~DICOMToJPEGConverter();
void save(const char* filename) override;
void setQuality(int quality){
if (quality<0) quality = 0;
if (quality>100) quality = 100;
m_Quality = quality;
}
private:
int m_Quality = 100;
};
#endif //OMEGAV_DICOMTOJPEGCONVERTER_H

View File

@@ -0,0 +1,25 @@
//
// Created by Krad on 2022/9/21.
//
#include "DICOMToPNGConverter.h"
#include "vtkNew.h"
#include "vtkImageData.h"
#include "vtkPNGWriter.h"
DICOMToPNGConverter::DICOMToPNGConverter() {
}
DICOMToPNGConverter::~DICOMToPNGConverter() {
}
void DICOMToPNGConverter::save(const char *filename) {
loadDICOMPixelData();
vtkNew<vtkPNGWriter> writer;
writer->SetCompressionLevel(m_CompressionLevel);
writer->SetInputData(GetInputData());
writer->SetFileName(filename);
writer->Write();
}

View File

@@ -0,0 +1,26 @@
//
// Created by Krad on 2022/9/21.
//
#ifndef OMEGAV_DICOMTOPNGCONVERTER_H
#define OMEGAV_DICOMTOPNGCONVERTER_H
#include "ConverterBase.h"
class DICOMToPNGConverter:public ConverterBase {
public:
DICOMToPNGConverter();
~DICOMToPNGConverter();
void save(const char* filename) override;
void setCompressLevel(int level){
if (level<0) level = 0;
if (level>9) level = 9;
m_CompressionLevel = level;
}
private:
int m_CompressionLevel = 5;
};
#endif //OMEGAV_DICOMTOPNGCONVERTER_H

View File

@@ -3,12 +3,15 @@
//
#include "DICOMPixelDataHelper.h"
#include <dcmtk/dcmdata/dcrledrg.h>
#include <dcmtk/dcmjpeg/djdecode.h>
#include <dcmtk/dcmjpls/djdecode.h>
#include <dcmtk/dcmdata/dcfilefo.h>
#include <dcmtk/dcmimgle/dcmimage.h>
#include <dcmtk/dcmimgle/dipixel.h>
#include <vtkImageData.h>
#include "ExtendMedicalImageProperties.h"
#ifdef OPENJPEG
#include "openjpeg-2.3/openjpeg.h"
@@ -248,3 +251,47 @@ void DICOMPixelDataHelper::ClearFileObjectCache() {
bool DICOMPixelDataHelper::CheckFileObjectCache(const char *path) {
return DICOMFileObjectCache::getInstance()->contains(path);
}
bool DICOMPixelDataHelper::GetRenderedData(const char *path, vtkImageData *data,int sample,double windowLevel, double windowWidth) {
DcmFileFormat fileFormat;
if (fileFormat.loadFile(path).good()) {
DcmDataset *dset = fileFormat.getDataset();
DicomImage dcmImage(&fileFormat, dset->getOriginalXfer(), CIF_MayDetachPixelData);
RenderToImageData(data, 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);
if (sample == 1){
dcmImage.setWindow(windowLevel, windowWidth);
}
data->SetExtent(0, dcmImage.getWidth()-1,0,dcmImage.getHeight()-1, 0 ,0);
data->AllocateScalars(VTK_UNSIGNED_CHAR,3);
void* d = data->GetScalarPointer();
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;
}
}
}
delete fileFormat;
return false;
}

View File

@@ -5,8 +5,10 @@
#ifndef OMEGAV_DICOMPIXELDATAHELPER_H
#define OMEGAV_DICOMPIXELDATAHELPER_H
class ExtendMedicalImageProperties;
#include <dcmtk/dcmimgle/dcmimage.h>
class ExtendMedicalImageProperties;
class vtkImageData;
/**
* DICOM file Pixel Data read helper
*/
@@ -18,6 +20,9 @@ public:
}
static void GetThumbnailData(ExtendMedicalImageProperties *property, void*& data,
unsigned long& length,int& sample);
static bool GetRenderedData(const char * path, vtkImageData* data, int sample, double windowLevel, double windowWidth);
static bool GetMultiFrameRenderedData(const char * path, vtkImageData* data, int sample,int frame, double windowLevel, double windowWidth);
/**
* Get Pixel Data with Rescaled, result is calculate as integer, and arrange as integer.
* @param path dcm file absolute path
@@ -97,6 +102,9 @@ public:
* Finalize decompress Codecs, must be called after other method have done.
*/
static void FinalizeCodecs();
static void
RenderToImageData(vtkImageData *data, int sample, double windowLevel, double windowWidth, DicomImage &dcmImage);
};