Add multi-frame data Spliter

This commit is contained in:
Krad
2022-09-23 09:36:04 +08:00
parent ccb67f478d
commit 90ead1ce1a
3 changed files with 237 additions and 0 deletions

View File

@@ -9,9 +9,17 @@
#include "IO/Convert/DICOMToPNGConverter.h"
#include "IO/Convert/DICOMToJPEGConverter.h"
#include "IO/DICOM/MultiframeDICOMSpliter.h"
#include "DIDMainWindow.h"
int main(int argc, char* argv[]) {
MultiframeDICOMSpliter spliter;
spliter.SetInputFileName("F:\\Special DICOM\\112255\\b65b0956-c046-11ea-a50f-509a4c8d26e3_08870001_37445_112255_7328989.dcm");
spliter.SetOutputDirPath("D:\\mounttest");
spliter.SetOutputFilePattern("%d.dcm");
spliter.write();
return 0;
DICOMToBMPConverter converter;
converter.setOutputSize(300, 300);
converter.setFrame(2);
@@ -19,6 +27,7 @@ int main(int argc, char* argv[]) {
converter.save("D:\\test.bmp");
DICOMToPNGConverter pconverter;
pconverter.setFrame(2);
pconverter.setOutputSize(300, 300);
pconverter.setInputDICOMFile("D:\\TestData\\CT\\4905\\a8c5c508-06b8-11ea-9b1e-509a4c8d26e3_08870001_4905_10903_287571");
pconverter.save("D:\\test.png");

View File

@@ -0,0 +1,204 @@
//
// Created by Krad on 2022/9/22.
//
#include <dcmtk/dcmimgle/dcmimage.h>
#include "MultiframeDICOMSpliter.h"
#include "dcmtk/dcmdata/dcfilefo.h"
#include "dcmtk/dcmdata/dcdeftag.h"
#include "dcmtk/dcmdata/dcdatset.h"
#include "dcmtk/dcmdata/dcspchrs.h"
namespace {
const int BUFF_SIZE= 1024;
char buff[BUFF_SIZE];
}
void MultiframeDICOMSpliter::SetInputFileName(const char *filename) {
mInputFilename = filename;
}
void MultiframeDICOMSpliter::SetOutputFilePattern(const char *format) {
mOutputFilePattern.clear();
mOutputFilePattern.append("%s\\");
mOutputFilePattern.append(format);
}
void MultiframeDICOMSpliter::SetOutputDirPath(const char *dir) {
mOutputDirPath = dir;
}
void MultiframeDICOMSpliter::write() {
DcmFileFormat fileFormat;
if (fileFormat.loadFile(mInputFilename).good()){
DcmDataset* dataset = fileFormat.getDataset();
dataset->loadAllDataIntoMemory();
DcmDataset* newDs = (DcmDataset*)dataset->clone();
// remove frame about tags
DcmElement* e = nullptr;
newDs->findAndDeleteElement(DCM_NumberOfFrames);
newDs->findAndDeleteElement(DCM_SharedFunctionalGroupsSequence);
newDs->findAndDeleteElement(DCM_PerFrameFunctionalGroupsSequence);
newDs->findAndDeleteElement(DCM_FrameDimensionPointer);
newDs->findAndDeleteElement(DCM_FrameIncrementPointer);
newDs->findAndDeleteElement(DCM_FrameTime);
newDs->findAndDeleteElement(DCM_FrameTimeVector);
newDs->findAndDeleteElement(DCM_ConcatenationUID);
newDs->findAndDeleteElement(DCM_ConcatenationFrameOffsetNumber);
newDs->findAndDeleteElement(DCM_InConcatenationNumber);
newDs->findAndDeleteElement(DCM_StereoPairsPresent);
newDs->findAndDeleteElement(DCM_RepresentativeFrameNumber);
newDs->findAndDeleteElement(DCM_RepresentativeFrameNumber);
newDs->findAndDeleteElement(DCM_DimensionOrganizationSequence);
Uint8* d = nullptr;
newDs->putAndInsertUint8Array(DCM_PixelData, d,0);
std::string SOPInstanceUID;
dataset->findAndGetOFString(DCM_SOPInstanceUID,SOPInstanceUID);
//multi-frame data
long frameCount = 0;
auto frameRet = dataset->findAndGetSint32(DCM_NumberOfFrames, frameCount);
if (frameRet.good()) {
DcmItem* sharedGroup = nullptr;
if (dataset->findAndGetSequenceItem(DCM_SharedFunctionalGroupsSequence, sharedGroup, 0).good()) {
DcmItem* pixelMeasure = nullptr;
if (sharedGroup->findAndGetSequenceItem(DCM_PixelMeasuresSequence,pixelMeasure, 0).good()){
// use frame pixel spacing
double spacing[3] = {.0, .0, .0};
if(pixelMeasure->findAndGetFloat64(DCM_PixelSpacing,spacing[0],0).good()){
pixelMeasure->findAndGetFloat64(DCM_PixelSpacing,spacing[1],1);
snprintf(buff,BUFF_SIZE, "%f\\%f", spacing[0],spacing[1]);
newDs->putAndInsertString(DCM_PixelSpacing,buff);
}
// try get frame thickness
if (pixelMeasure->findAndGetFloat64(DCM_SliceThickness,spacing[2]).good()){
snprintf(buff,BUFF_SIZE, "%f", spacing[2]);
newDs->putAndInsertString(DCM_SliceThickness,buff);
}
if (pixelMeasure->findAndGetFloat64(DCM_SpacingBetweenSlices,spacing[2]).good()){
snprintf(buff,BUFF_SIZE, "%f", spacing[2]);
newDs->putAndInsertString(DCM_SliceThickness,buff);
}
}
// try to get frame window setting
DcmItem* frameLUT = nullptr;
if (sharedGroup->findAndGetSequenceItem(DCM_FrameVOILUTSequence,frameLUT, 0).good()){
double window[2] = {.0, .0};
if (frameLUT->findAndGetFloat64(DCM_WindowCenter,window[0]).good()){
frameLUT->findAndGetFloat64(DCM_WindowWidth,window[1]);
snprintf(buff,BUFF_SIZE, "%f", window[0]);
newDs->putAndInsertString(DCM_WindowCenter,buff);
snprintf(buff,BUFF_SIZE, "%f", window[1]);
newDs->putAndInsertString(DCM_WindowWidth,buff);
}
}
}
long instanceNumber = 0;
dataset->findAndGetSint32(DCM_InstanceNumber, instanceNumber);
for (int i = 0; i < frameCount; ++i) {
DcmDataset frameDs(*newDs);
DcmItem *perFrameGroup = nullptr;
if (dataset->findAndGetSequenceItem(DCM_PerFrameFunctionalGroupsSequence,
perFrameGroup, i).good()) {
//calc instance number for frame
DcmItem *frameContent = nullptr;
if (perFrameGroup->findAndGetSequenceItem(DCM_FrameContentSequence,
frameContent, 0).good()) {
unsigned long frameNumber = 0;
frameContent->findAndGetUint32(DCM_InStackPositionNumber, frameNumber);
int newInstanceNumber = (int)(frameNumber + instanceNumber);
snprintf(buff,BUFF_SIZE, "%d", newInstanceNumber);
frameDs.putAndInsertString(DCM_InstanceNumber, buff);
std::string newSOPInstanceUID ;
newSOPInstanceUID.append(SOPInstanceUID);
snprintf(buff,BUFF_SIZE, ".%d", newInstanceNumber);
newSOPInstanceUID.append(buff);
frameDs.putAndInsertString(DCM_SOPInstanceUID, newSOPInstanceUID.c_str());
}
// try to get frame position
DcmItem *framePosition = nullptr;
if (perFrameGroup->findAndGetSequenceItem(DCM_PlanePositionSequence,
framePosition, 0).good()) {
double position[3] = {.0, .0, .0};
if (framePosition->findAndGetFloat64(DCM_ImagePositionPatient,
position[0], 0).good()) {
framePosition->findAndGetFloat64(DCM_ImagePositionPatient,
position[1], 1);
framePosition->findAndGetFloat64(DCM_ImagePositionPatient,
position[2], 2);
snprintf(buff,BUFF_SIZE, "%f\\%f\\%f", position[0], position[1], position[2]);
frameDs.putAndInsertString(DCM_ImagePositionPatient,buff);
}
}
// try to get frame orientation
DcmItem *frameOrientation = nullptr;
if (perFrameGroup->findAndGetSequenceItem(DCM_PlaneOrientationSequence, frameOrientation,
0).good()) {
double orientation[6] = {.0, .0, .0, .0, .0, .0};
if (frameOrientation->findAndGetFloat64(DCM_ImageOrientationPatient,
orientation[0], 0).good()) {
frameOrientation->findAndGetFloat64(DCM_ImageOrientationPatient,
orientation[1], 1);
frameOrientation->findAndGetFloat64(DCM_ImageOrientationPatient,
orientation[2], 2);
frameOrientation->findAndGetFloat64(DCM_ImageOrientationPatient,
orientation[3], 3);
frameOrientation->findAndGetFloat64(DCM_ImageOrientationPatient,
orientation[4], 4);
frameOrientation->findAndGetFloat64(DCM_ImageOrientationPatient,
orientation[5], 5);
if(!frameDs.tagExists(DCM_ImageOrientationPatient)){
frameDs.insertEmptyElement(DCM_ImageOrientationPatient);
}
snprintf(buff,BUFF_SIZE, "%f\\%f\\%f\\%f\\%f\\%f", orientation[0], orientation[1], orientation[2]
, orientation[3], orientation[4], orientation[5]);
frameDs.putAndInsertString(DCM_ImageOrientationPatient,buff);
}
}
}
else{
int newInstanceNumber = (int)(i + instanceNumber);
snprintf(buff,BUFF_SIZE, "%d", newInstanceNumber);
frameDs.putAndInsertString(DCM_InstanceNumber, buff);
std::string newSOPInstanceUID ;
newSOPInstanceUID.append(SOPInstanceUID);
snprintf(buff,BUFF_SIZE, ".%d", newInstanceNumber);
newSOPInstanceUID.append(buff);
frameDs.putAndInsertString(DCM_SOPInstanceUID, newSOPInstanceUID.c_str());
}
DicomImage dcmImage(&fileFormat, dataset->getOriginalXfer(), CIF_UsePartialAccessToPixelData,
i, 1);
if (dcmImage.getStatus() == EIS_Normal) {
const DiPixel *pixelData = dcmImage.getInterData();//rescaled
const void *dd = pixelData->getData();
unsigned long length = pixelData->getCount();
unsigned long dataBits = 1;
switch (pixelData->getRepresentation()) {
case EPR_Uint8:
case EPR_Sint8:
break;
case EPR_Uint16:
case EPR_Sint16:
dataBits = 2;
break;
case EPR_Uint32:
case EPR_Sint32:
dataBits = 4;
break;
}
length= length*dataBits;
frameDs.putAndInsertUint8Array(DCM_PixelData, (Uint8*) dd, length);
DcmFileFormat newOne(&frameDs);
char buff[200]={0};
sprintf(buff,mOutputFilePattern.c_str(),mOutputDirPath.c_str(),i);
newOne.saveFile(buff);
}
}
}
}
}

View File

@@ -0,0 +1,24 @@
//
// Created by Krad on 2022/9/22.
//
#ifndef OMEGAV_MULTIFRAMEDICOMSPLITER_H
#define OMEGAV_MULTIFRAMEDICOMSPLITER_H
#include <string>
class MultiframeDICOMSpliter {
public:
void SetInputFileName(const char* filename);
void SetOutputFilePattern(const char* format);
void SetOutputDirPath(const char* dir);
void write();
private:
std::string mInputFilename;
std::string mOutputFilePattern;
std::string mOutputDirPath;
};
#endif //OMEGAV_MULTIFRAMEDICOMSPLITER_H