//************************************************************************
// 函数名称: LoadDcmDataSet
// 访问权限: public
// 创建日期: 2016/11/28
// 创 建 人:
// 函数说明: 加载Dcm图像返回它的DicomImage
// 函数参数: std::string file_path 文件的路径
// 返 回 值: DicomImage* $
//************************************************************************
DicomImage* CLoadMutiFrameDcm::LoadDcmDataSet(std::string file_path)
{
this->filepath = file_path;
DcmFileFormat fileformat;
OFCondition oc = fileformat.loadFile(file_path.c_str()); //读取Dicom图像
if (!oc.good()) //判断Dicom文件是否读取成功
{
std::cout << "file Load error" << std::endl;
return nullptr;
}
DcmDataset *dataset = fileformat.getDataset(); //得到Dicom的数据集
E_TransferSyntax xfer = dataset->getOriginalXfer(); //得到传输语法
OFString patientname;
dataset->findAndGetOFString(DCM_PatientName, patientname); //获取病人姓名
unsigned short bit_count(0);
dataset->findAndGetUint16(DCM_BitsStored, bit_count); //获取像素的位数 bit
OFString isRGB;
dataset->findAndGetOFString(DCM_PhotometricInterpretation, isRGB); //DCM图片的图像模式
unsigned short img_bits(0);
dataset->findAndGetUint16(DCM_SamplesPerPixel, img_bits); //单个像素占用多少byte
this->Img_bitCount = (int)img_bits;
OFString framecount;
dataset->findAndGetOFString(DCM_NumberOfFrames, framecount); //DCM图片的帧数
//DicomImage* img_xfer = new DicomImage(xfer, 0, 0, 1); //由传输语法得到图像的帧
unsigned short m_width; //获取图像的窗宽高
unsigned short m_height;
dataset->findAndGetUint16(DCM_Rows, m_height);
dataset->findAndGetUint16(DCM_Columns, m_width);
/////////////////////////////////////////////////////////////////////////
const char* transferSyntax = NULL;
fileformat.getMetaInfo()->findAndGetString(DCM_TransferSyntaxUID, transferSyntax); //获得传输语法字符串
string losslessTransUID = "1.2.840.10008.1.2.4.70";
string lossTransUID = "1.2.840.10008.1.2.4.51";
string losslessP14 = "1.2.840.10008.1.2.4.57";
string lossyP1 = "1.2.840.10008.1.2.4.50";
string lossyRLE = "1.2.840.10008.1.2.5";
if (transferSyntax == losslessTransUID || transferSyntax == lossTransUID ||
transferSyntax == losslessP14 || transferSyntax == lossyP1)
{
DJDecoderRegistration::registerCodecs();
dataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL); //对压缩的图像像素进行解压
DJDecoderRegistration::cleanup();
}
else if (transferSyntax == lossyRLE)
{
DcmRLEDecoderRegistration::registerCodecs();
dataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL);
DcmRLEDecoderRegistration::cleanup();
}
else
{
dataset->chooseRepresentation(xfer, NULL);
}
DicomImage* m_dcmImage = new DicomImage((DcmObject*)dataset, xfer); //利用dataset生成DicomImage,需要上面的解压方法;
return m_dcmImage;
}
//************************************************************************
// 函数名称: GetImageFromDcmDataSet
// 访问权限: public
// 创建日期: 2016/11/28
// 创 建 人:
// 函数说明: 从DicomImage中获取所有的图像帧
// 函数参数: DicomImage * m_dcmImage DCM文件的DicomImage对象
// 返 回 值: std::vector
//************************************************************************
std::vector CLoadMutiFrameDcm::GetImageFromDcmDataSet(DicomImage* m_dcmImage)
{
std::vector output_img; //输出图像向量
int framecount(m_dcmImage->getFrameCount()); //获取这个文件包含的图像的帧数
for (int k=0; kgetOutputData(8, k, 0)); //获得8位的图像数据指针
if (pixelData != NULL)
{
int m_height = m_dcmImage->getHeight();
int m_width = m_dcmImage->getWidth();
if (3 == this->Img_bitCount)
{
cv::Mat dst2(m_height, m_width, CV_8UC3, cv::Scalar::all(0));
for (int i = 0; i < m_height; i++)
{
for (int j = 0; j < m_width; j++)
{
dst2.at(i, j)[0] = *(pixelData + i*m_width * 3 + j * 3 + 2); //B channel
dst2.at(i, j)[1] = *(pixelData + i*m_width * 3 + j * 3 + 1); //G channel
dst2.at(i, j)[2] = *(pixelData + i*m_width * 3 + j * 3); //R channel
}
}
output_img.push_back(dst2);
}
else if (1 == this->Img_bitCount)
{
cv::Mat dst2(m_height, m_width, CV_8UC1, cv::Scalar::all(0));
uchar* data = nullptr;
for (int i = 0; i < m_height; i++)
{
data = dst2.ptr(i);
for (int j = 0; j < m_width; j++)
{
data[j] = *(pixelData + i*m_width + j);
}
}
output_img.push_back(dst2);
}
/*cv::imshow("image", dst2);
cv::waitKey(0);*/
}
}
return output_img;
}
//************************************************************************
// 函数名称: WriteMat2Dcm
// 访问权限: public
// 创建日期: 2016/11/28
// 创 建 人:
// 函数说明: 将Mat类型的数据转换为单个的dcm文件进行存储,使用原来的存储格式
// 函数参数: std::vector & source_img 输入的图像资源
// 函数参数: std::string output_path 输出dcm文件的路径
// 返 回 值: bool
//************************************************************************
bool CLoadMutiFrameDcm::WriteMat2Dcm(std::vector& source_img, std::string output_path)
{
if (source_img.size()<=0)
{
cout << "No source image! error" << endl;
return false;
}
if (!this->filepath.length())
{
cout << "No No parent dcm filepath! error" << endl;
return false;
}
DcmFileFormat fileformat;
OFCondition oc = fileformat.loadFile(this->filepath.c_str()); //读取Dicom图像
if (!oc.good()) //判断Dicom文件是否读取成功
{
std::cout << "file Load error" << std::endl;
return nullptr;
}
DcmDataset *dataset = fileformat.getDataset(); //得到Dicom的数据集
E_TransferSyntax xfer = dataset->getOriginalXfer(); //得到传输语法
unsigned short img_bits(0);
dataset->findAndGetUint16(DCM_SamplesPerPixel, img_bits); //单个像素占用多少byte
unsigned short bit_count(0);
dataset->findAndGetUint16(DCM_BitsStored, bit_count); //获取像素的位数 bit
OFString isRGB;
dataset->findAndGetOFString(DCM_PhotometricInterpretation, isRGB); //DCM图片的图像模式
for (int i = 0; i < (int)source_img.size(); i++)
{
DcmFileFormat *fileFormat = new DcmFileFormat();
DcmDataset *dataSet = fileFormat->getDataset();
int rows(source_img[i].rows);
int cols(source_img[i].cols);
int img_channels(source_img[i].channels());
int length(rows*cols*img_channels);
uchar* img_pixel = new uchar[length];
memset(img_pixel, 0, length);
uchar* Mat_data = nullptr;
cv::Mat temp = source_img[i];
if (3 == img_channels)
{
for (int j = 0; j < rows; j++)
{
for (int k = 0; k < cols; k++)
{
img_pixel[j * 3 * cols + 3*k] = source_img[i].at(j, k)[2];
img_pixel[j * 3 * cols + 3*k + 1] = source_img[i].at(j, k)[1];
img_pixel[j * 3 * cols + 3*k + 2] = source_img[i].at(j, k)[0];
}
}
}
else if (1 == img_channels)
{
for (int j = 0; j < rows; j++)
{
Mat_data = source_img[i].ptr(j);
for (int k = 0; k < cols; k++)
{
img_pixel[j * cols + k] = Mat_data[k];
}
}
}
dataSet->putAndInsertUint8Array(DCM_PixelData, OFreinterpret_cast(Uint8*, img_pixel), length);
dataSet->putAndInsertString(DCM_NumberOfFrames, "1");
dataSet->putAndInsertUint16(DCM_Rows, rows);
dataSet->putAndInsertUint16(DCM_Columns, cols);
dataSet->putAndInsertUint16(DCM_SamplesPerPixel, img_bits);
dataSet->putAndInsertUint16(DCM_BitsStored, bit_count);
dataSet->putAndInsertOFStringArray(DCM_PhotometricInterpretation, isRGB);
//dataSet->putAndInsertString();
//保存文件
char t[10];
string filename;
sprintf(t, "%d", i);
filename = t;
filename = output_path + filename + ".dcm";
OFCondition status = fileFormat->saveFile(filename.c_str(), xfer);
if (status.bad())
cout << "Error: cannot write DICOM file (" << status.text() << ")" << endl;
delete fileFormat;
delete[] img_pixel;
this->ShowImage(filename);
}
return true;
}
//************************************************************************
// 函数名称: ShowImage
// 访问权限: public
// 创建日期: 2016/11/28
// 创 建 人:
// 函数说明: 读取自己保存的Dcm图片查看是否能读取成功
// 函数参数: std::string filepath 保存的文件的路径
// 返 回 值: bool
//************************************************************************
bool CLoadMutiFrameDcm::ShowImage(std::string filepath)
{
if (!filepath.length())
{
cout << "No No parent dcm filepath! error" << endl;
return false;
}
DcmFileFormat fileformat;
OFCondition oc = fileformat.loadFile(filepath.c_str()); //读取Dicom图像
if (!oc.good()) //判断Dicom文件是否读取成功
{
std::cout << "file Load error" << std::endl;
return false;
}
DcmDataset *dataset = fileformat.getDataset(); //得到Dicom的数据集
E_TransferSyntax xfer = dataset->getOriginalXfer(); //得到传输语法
OFString patientname;
dataset->findAndGetOFString(DCM_PatientName, patientname); //获取病人姓名
unsigned short bit_count(0);
dataset->findAndGetUint16(DCM_BitsStored, bit_count); //获取像素的位数 bit
OFString isRGB;
dataset->findAndGetOFString(DCM_PhotometricInterpretation, isRGB); //DCM图片的图像模式
unsigned short img_bits(0);
dataset->findAndGetUint16(DCM_SamplesPerPixel, img_bits); //单个像素占用多少byte
//DicomImage* img_xfer = new DicomImage(xfer, 0, 0, 1); //由传输语法得到图像的帧
unsigned short m_width; //获取图像的窗宽高
unsigned short m_height;
dataset->findAndGetUint16(DCM_Rows, m_height);
dataset->findAndGetUint16(DCM_Columns, m_width);
/////////////////////////////////////////////////////////////////////////
const char* transferSyntax = NULL;
fileformat.getMetaInfo()->findAndGetString(DCM_TransferSyntaxUID, transferSyntax); //获得传输语法字符串
string losslessTransUID = "1.2.840.10008.1.2.4.70";
string lossTransUID = "1.2.840.10008.1.2.4.51";
string losslessP14 = "1.2.840.10008.1.2.4.57";
string lossyP1 = "1.2.840.10008.1.2.4.50";
string lossyRLE = "1.2.840.10008.1.2.5";
if (transferSyntax == losslessTransUID || transferSyntax == lossTransUID ||
transferSyntax == losslessP14 || transferSyntax == lossyP1)
{
DJDecoderRegistration::registerCodecs();
dataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL); //对压缩的图像像素进行解压
DJDecoderRegistration::cleanup();
}
else if (transferSyntax == lossyRLE)
{
DcmRLEDecoderRegistration::registerCodecs();
dataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL);
DcmRLEDecoderRegistration::cleanup();
}
else
{
dataset->chooseRepresentation(xfer, NULL);
}
DcmElement* element = NULL;
OFCondition result = dataset->findAndGetElement(DCM_PixelData, element); //获取图像数据
if (result.bad() || element == NULL)
return false;
const Uint8* image_data = nullptr;
Uint16* image16_data = nullptr;
//if (8 == bit_count)
//{
// result = element->getUint8Array(image_data); //获取8位的图像数据
//}
//else if (8 < bit_count)
//{
// result = element->getUint16Array(image16_data); //获取>8位的图像数据
//}
dataset->findAndGetUint8Array(DCM_PixelData, image_data);
if (image_data != NULL || image16_data != NULL)
{
if (1 == img_bits) //1 byte per pixel
{
cv::Mat dst(m_height, m_width, CV_8UC1, cv::Scalar::all(0));
unsigned char* data = nullptr;
for (int i = 0; i < m_height; i++)
{
data = dst.ptr(i); //取得每一行的头指针 也可使用dst2.at(i, j) = ?
for (int j = 0; j < m_width; j++)
{
*data++ = image_data[i*m_width + j];
}
}
cv::imshow("gray", dst);
cv::waitKey(0);
}
else if (3 == img_bits) //3 bytes per pixel
{
cv::Mat dst(m_height, m_width, CV_8UC3, cv::Scalar::all(0));
unsigned short* data = nullptr;
for (int i = 0; i < m_height; i++)
{
for (int j = 0; j < m_width; j++)
{
dst.at(i, j)[0] = image_data[i*m_width * 3 + j * 3 + 2]; //B channel
dst.at(i, j)[1] = image_data[i*m_width * 3 + j * 3 + 1]; //G channel
dst.at(i, j)[2] = image_data[i*m_width * 3 + j * 3]; //R channel
}
}
//cv::imshow("colored", dst);
//cv::waitKey(0);
}
}
return true;
}