用DMTK(dicom)实现DR设备的剂量报告(RDSR)

最近公司跟西门子合作,开发他们需要的DR采集工作站的软件。接到一个需求是新的法规标准需要生成累计剂量报告的功能,需求描述是:“该系统的辐射剂量结构报告应包含IEC 61910-1:2014之5.1.2中要求(应)的数据元素;辐射剂量结构报告宜包含IEC 61910-1:2014之5.1.2中要求(宜)的数据元素。”

看到需求时不明所以,找来标准的条款看,如下图所示,英文的看不太明白。于是再找来对应的中文翻译版本来看,还是不知道这个报告应该长什么样。

后面再问西门子,要他们的CT设备生成的剂量报告来作参考,是一个DCM文件。用软件打开来看,跟dcm格式的图像还是不一样的,如下图。 

这下终于有点眉目了,就要把标准里说的那个信息写到一个DCM文件里。接下来就是要研究用哪些DICOM标签来存放这些信息了。因为之前的软件能生成DCM格式的图像,知道一张图像里要用DICOM写入哪些数据,也用代码调用了哪些DCMTK函数可参考,于是信心大增。

用软件查看所有的DICOM标签,如下图。发现实在太多了,这么多要一个个写入,还要研究哪个标签要可以写入什么数据,标签要怎么嵌套。查了一下DICOM标准,看了一些标签的意思,如果要每个标签都自己写将会是很大的工作量。于在网上找看有没有实现类似报告的代码。还真找到了2个。链接如下:

Howto MammoCADSR - DCMTK - OFFIS DCMTK and DICOM ProjectsRedminehttps://support.dcmtk.org/redmine/projects/dcmtk/wiki/howto_mammocadsr#Howto-Create-a-Mammography-CAD-SR-DocumentDCMTK:使用dcmsr API创建示例结构化报告_C和C++技术博客-CSDN博客DCMTK:使用dcmsr API创建示例结构化报告使用dcmsr API创建示例结构化报告使用dcmsr API创建示例结构化报告#include "dcmtk/config/osconfig.h" #include "dcmtk/ofstd/ofconsol.h" #include "dcmtk/dcmsr/dsrdoc.h" #include "dcmtk/dcmsr/codes/ucum.h"#include "dcmtk/dcmdata/dctk.h" //https://cplusplus.blog.csdn.net/article/details/116811257?spm=1001.2101.3001.6650.6&utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~default-6.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~default-6.no_search_link

 其中第2个链接里的代码非常有用,后面就基于它来改的。后面还遇到2个问题,就是不能显示中文,另一个是怎么打开已生成的报告文件并追加新的内容。第一个问题是要把字符集设为DSRTypes::CS_UTF8,不能用例子里的DSRTypes::CS_Latin1。第2个问题就看代码吧。


#include <StdAfx.h>
#include "DoseStructuredReport.h"


// 写入剂量报告
void  DoseStructuredReport::WriteDSRDocument(DoseStructuredReport& DoseInfo, CString sFilePath)
{
	LOG_DEBUGGING("%s", sFilePath);

	// 剂量报告已经存在,就打开它,往后追加
	if (FileUtility::FileExists(sFilePath))
	{
		AppendDSRDocument(DoseInfo, sFilePath);
		return;
	}

	DSRDocument* pDoseDocument = new DSRDocument();

	if (pDoseDocument == NULL)
	{
		LOG_DEBUGGING("pDoseDocument == NULL");
		return;
	}

	WriteDSRDocumentHeadInfo(pDoseDocument, DoseInfo);
	WriteDSRDocumentAccumulatedDoseInfo(pDoseDocument, DoseInfo);
	StoreDSRDocumentToDcmFile(pDoseDocument, sFilePath);

	delete pDoseDocument;
	pDoseDocument = NULL;
}

// 追加内容到已有的剂量报告里
void DoseStructuredReport::AppendDSRDocument(DoseStructuredReport& DoseInfo, CString sFilePath)
{
	LOG_DEBUGGING("");

	DSRDocument* pDoseDocument = new DSRDocument();

	if (pDoseDocument == NULL)
	{
		LOG_DEBUGGING("pDoseDocument == NULL");
		return;
	}

	ReadDSRDocumentDcmFile(pDoseDocument, sFilePath);
	WriteDSRDocumentAccumulatedDoseInfo(pDoseDocument, DoseInfo, TRUE);
	StoreDSRDocumentToDcmFile(pDoseDocument, sFilePath);

	delete pDoseDocument;
	pDoseDocument = NULL;
}

// 读取剂量报告DCM文件
BOOL DoseStructuredReport::ReadDSRDocumentDcmFile(DSRDocument* pDoseDocument, CString sFilePath)
{
	LOG_DEBUGGING("");

	ASSERT(pDoseDocument != NULL);

	DcmFileFormat *pDcmFileFormat = new DcmFileFormat();

	if (pDcmFileFormat == NULL)
	{
		LOG_DEBUGGING("pDcmFileFormat == NULL");
		return FALSE;
	}

	if (pDcmFileFormat->loadFile(CT2A(sFilePath)).bad())
	{
		LOG_ERROR("加载文件失败");
		return FALSE;
	}

	BOOL bRet = FALSE;
	DcmDataset *pDcmDataset = pDcmFileFormat->getDataset();

	if (pDcmDataset != NULL)
	{
		pDoseDocument->getCodingSchemeIdentification().addPrivateDcmtkCodingScheme();

		OFCondition Condition = pDoseDocument->read(*pDcmDataset,
			DSRTypes::RF_readDigitalSignatures | DSRTypes::RF_acceptUnknownRelationshipType
			| DSRTypes::RF_ignoreRelationshipConstraints | DSRTypes::RF_ignoreContentItemErrors
			| DSRTypes::RF_skipInvalidContentItems);

		if (Condition.good())
		{
			//StoreDSRDocumentToDcmFile(pDoseDocument, sFilePath + "22");//测试用
			bRet = TRUE;
		}
		else
		{
			LOG_DEBUGGING("ERROR: could not read pDcmDataset into SR document [%s]", Condition.text());
		}
	}
	else
	{
		LOG_DEBUGGING("pDcmDataset == NULL");
	}

	delete pDcmFileFormat;
	pDcmFileFormat = NULL;

	return bRet;
}

// 把剂量报告保存到DCM文件中
BOOL DoseStructuredReport::StoreDSRDocumentToDcmFile(DSRDocument* pDoseDocument, CString sFilePath)
{
	LOG_DEBUGGING("%s", sFilePath);

	ASSERT(pDoseDocument != NULL);

	DcmFileFormat *pDcmFileFormat = new DcmFileFormat();

	if (pDcmFileFormat == NULL)
	{
		LOG_DEBUGGING("pDcmFileFormat == NULL");
		return FALSE;
	}

	BOOL bRet = FALSE;
	DcmDataset *pDcmDataset = pDcmFileFormat->getDataset();

	if (pDcmDataset != NULL)
	{
		pDoseDocument->getCodingSchemeIdentification().addPrivateDcmtkCodingScheme();

		if (pDoseDocument->write(*pDcmDataset).good())
		{
			//CString sSpecificCharacterSet;
			//LANGID lid = GetSystemDefaultLangID();

			 是中文系统就改变语言字符集,不然显示中文乱码
			//if (lid == 0x0804)
			//{
			//	sSpecificCharacterSet = _T("GB18030");
			//	pDcmDataset->putAndInsertString(DCM_SpecificCharacterSet, CT2A(sSpecificCharacterSet));
			//}
			//else//case 0x0409
			//{
			//	sSpecificCharacterSet = _T("ISO_IR 100");
			//}

			if (pDcmFileFormat->saveFile(CT2A(sFilePath), EXS_LittleEndianExplicit).good())
			{
				bRet = TRUE;
			}
			else
			{
				LOG_DEBUGGING("ERROR: could not save pDcmDataset to file");
			}
		}
		else
		{
			LOG_DEBUGGING("ERROR: could not write SR document into pDcmDataset");
		}
	}
	else
	{
		LOG_DEBUGGING("pDcmDataset == NULL");
	}

	delete pDcmFileFormat;
	pDcmFileFormat = NULL;

	return bRet;
}

// 写入剂量报告的头信息,从病人图像的DCM信息里获取
void DoseStructuredReport::WriteDSRDocumentHeadInfo(DSRDocument* pDoseDocument, DoseStructuredReport& DoseInfo)
{
	LOG_DEBUGGING("");

	ASSERT(pDoseDocument != NULL);

	pDoseDocument->createNewDocument(DSRTypes::DT_XRayRadiationDoseSR);
	// 默认字符集, 这里要设为UTF8不然没法显示中文, 不能设为CS_Latin1
	pDoseDocument->setSpecificCharacterSetType(DSRTypes::CS_UTF8);

	// Study Instance UID
	pDoseDocument->createNewSeriesInStudy(ConvertCStringToUTF8(DoseInfo.StudyInstanceUid).c_str());

	// 如果送诊医院为空就写入操作医生
	if (DoseInfo.ReferringPhysiciansName.IsEmpty())
	{
		pDoseDocument->setReferringPhysicianName(ConvertCStringToUTF8(DoseInfo.OperatorsName).c_str());
	}
	else
	{
		pDoseDocument->setReferringPhysicianName(ConvertCStringToUTF8(DoseInfo.ReferringPhysiciansName).c_str());
	}

	//pDoseDocument->setSeriesDescription(DoseInfo.SeriesDescription).c_str());
	pDoseDocument->setSeriesDescription("Radiation Dose Information");

	// 如果检查描述为空,就写入检查部位
	if (DoseInfo.StudyDescription.IsEmpty())
	{
		pDoseDocument->setStudyDescription(ConvertCStringToUTF8(DoseInfo.BodyPartExamined).c_str());
	}
	else
	{
		pDoseDocument->setStudyDescription(ConvertCStringToUTF8(DoseInfo.StudyDescription).c_str());
	}

	pDoseDocument->setManufacturer(ConvertCStringToUTF8(DoseInfo.Manufacturer).c_str());
	pDoseDocument->setManufacturerModelName(ConvertCStringToUTF8(DoseInfo.ManufacturersModelName).c_str());
	pDoseDocument->setDeviceSerialNumber(ConvertCStringToUTF8(DoseInfo.DeviceSerialNumber).c_str());
	pDoseDocument->setSoftwareVersions(ConvertCStringToUTF8(DoseInfo.SoftwareVersions).c_str());

	pDoseDocument->setPatientName(ConvertCStringToUTF8(DoseInfo.PatientName).c_str());
	pDoseDocument->setPatientSex(ConvertCStringToUTF8(DoseInfo.PatientSex).c_str());
	pDoseDocument->setPatientBirthDate(ConvertCStringToUTF8(DoseInfo.PatientBirthDate).c_str());
	pDoseDocument->setPatientID(ConvertCStringToUTF8(DoseInfo.PatientID).c_str());
}

// 写入累计剂量信息
void DoseStructuredReport::WriteDSRDocumentAccumulatedDoseInfo(DSRDocument* pDoseDocument, DoseStructuredReport& DoseInfo, BOOL bIsAppend)
{
	LOG_DEBUGGING("");

	ASSERT(pDoseDocument != NULL);

	OFString sPosition;

	if (!bIsAppend)
	{
		pDoseDocument->getTree().addContentItem(DSRTypes::RT_isRoot, DSRTypes::VT_Container);
		pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("DT.01", "DCM", "X-Ray Radiation Dose Report"));

		// 观察员内容 Observation Context
		pDoseDocument->getTree().addContentItem(DSRTypes::RT_hasObsContext, DSRTypes::VT_PName, DSRTypes::AM_belowCurrent);
		pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("IHE.02", OFFIS_CODING_SCHEME_DESIGNATOR, "Person Observer's Role in this Procedure"));
		pDoseDocument->getTree().getCurrentContentItem().setStringValue("Irradiation Administering");

		pDoseDocument->getTree().addContentItem(DSRTypes::RT_hasObsContext, DSRTypes::VT_Text);
		pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("IHE.04", OFFIS_CODING_SCHEME_DESIGNATOR, "Device Observer Manufacturer"));
		pDoseDocument->getTree().getCurrentContentItem().setStringValue(ConvertCStringToUTF8(DoseInfo.Manufacturer).c_str());

		pDoseDocument->getTree().addContentItem(DSRTypes::RT_hasObsContext, DSRTypes::VT_Text);
		pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("IHE.05", OFFIS_CODING_SCHEME_DESIGNATOR, "Recording Observer's Organization Name"));
		pDoseDocument->getTree().getCurrentContentItem().setStringValue(ConvertCStringToUTF8(DoseInfo.InstitutionName).c_str());
	}
	else
	{
		pDoseDocument->getTree().gotoRoot();
		pDoseDocument->getTree().goDown();

		size_t tt = pDoseDocument->getTree().gotoNode("1.3");
		// 由于医院名称是中文,读取后再写入就丢掉了,这里要重新写入
		pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("IHE.05", OFFIS_CODING_SCHEME_DESIGNATOR, "Recording Observer's Organization Name"));
		pDoseDocument->getTree().getCurrentContentItem().setStringValue(ConvertCStringToUTF8(DoseInfo.InstitutionName).c_str());

		LOG_DEBUGGING("追加剂量报告: %d", tt);
	}

	LOG_DEBUGGING("NodeID=%d, Level=%d, Position=%s, sPosition=%s", pDoseDocument->getTree().getNodeID(),
		pDoseDocument->getTree().getLevel(), pDoseDocument->getTree().getPosition(sPosition).c_str(), ConvertUTF8ToCString(sPosition.c_str()));

	// 累积投射的X射线剂量
	pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Container);
	pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("SH.06", OFFIS_CODING_SCHEME_DESIGNATOR,
		ConvertCStringToUTF8(StringUtility::Format("Accumulated X - Ray Dose Data (%s, %s)", DoseInfo.SeriesDate, DoseInfo.SeriesTime)).c_str()));

	pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Text, DSRTypes::AM_belowCurrent);
	pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("RE.05", OFFIS_CODING_SCHEME_DESIGNATOR, "Dose (RP) Total"));
	pDoseDocument->getTree().getCurrentContentItem().setStringValue(ConvertCStringToUTF8(StringUtility::Format(_T("%.10f Gy"), DoseInfo.DoseTotal)).c_str());

	pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Text);
	pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("RE.05", OFFIS_CODING_SCHEME_DESIGNATOR, "Dose Area Product Total"));
	pDoseDocument->getTree().getCurrentContentItem().setStringValue(ConvertCStringToUTF8(StringUtility::Format(_T("%.10f Gy.m2"), DoseInfo.DoseAreaProductTotal)).c_str());

	pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Text);
	pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("RE.05", OFFIS_CODING_SCHEME_DESIGNATOR, "Distance Source to Reference Point"));
	pDoseDocument->getTree().getCurrentContentItem().setStringValue(ConvertCStringToUTF8(StringUtility::Format(_T("%d mm"), DoseInfo.DistanceSourceToReferencePoint)).c_str());

	pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Text);
	pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("RE.05", OFFIS_CODING_SCHEME_DESIGNATOR, "Reference Point Definition"));
	pDoseDocument->getTree().getCurrentContentItem().setStringValue(ConvertCStringToUTF8(DoseInfo.ReferencePointDefinition).c_str());

	pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Text);
	pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("RE.05", OFFIS_CODING_SCHEME_DESIGNATOR, "Total Number of Radiographic Frames"));
	pDoseDocument->getTree().getCurrentContentItem().setStringValue(ConvertCStringToUTF8(StringUtility::Format(_T("%d"), DoseInfo.TotalNumOfRadiographicFrames)).c_str());

	pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Text);
	pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("RE.05", OFFIS_CODING_SCHEME_DESIGNATOR, "Total Fluoroscopy Time"));
	pDoseDocument->getTree().getCurrentContentItem().setStringValue(ConvertCStringToUTF8(StringUtility::Format(_T("%d s"), DoseInfo.TotalFluoroscopyTime)).c_str());

	pDoseDocument->getTree().goUp();

	// 辐照事件X射线数据
	pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Container);
	pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("SH.06", OFFIS_CODING_SCHEME_DESIGNATOR,
		ConvertCStringToUTF8(StringUtility::Format("Irradiation Event X - Ray Data (%s, %s)", DoseInfo.SeriesDate, DoseInfo.SeriesTime)).c_str()));

	// 采集协议,这里只写部位
	pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Text, DSRTypes::AM_belowCurrent);
	pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("RE.05", OFFIS_CODING_SCHEME_DESIGNATOR, "Acquisition Protocol"));
	pDoseDocument->getTree().getCurrentContentItem().setStringValue(ConvertCStringToUTF8(DoseInfo.BodyPartExamined).c_str());

	// 开始的日期和时间
	pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Text);
	pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("RE.05", OFFIS_CODING_SCHEME_DESIGNATOR, "DateTime Started"));
	pDoseDocument->getTree().getCurrentContentItem().setStringValue((ConvertCStringToUTF8(DoseInfo.SeriesDate + _T(" ") + DoseInfo.SeriesTime)).c_str());

	// 辐照事件类型
	pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Text);
	pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("RE.05", OFFIS_CODING_SCHEME_DESIGNATOR, "Irradiation Event Type"));

	CString IrradiationEventType;
	IrradiationEventType.Format(_T("%s %s %s"),
		(DoseInfo.IrradiationEventType & 0x01) == 0x01 ? "Radiography," : "",
		(DoseInfo.IrradiationEventType & 0x02) == 0x02 ? "SerialRadiography," : "",
		(DoseInfo.IrradiationEventType & 0x04) == 0x04 ? "Fluoroscopy" : "");

	IrradiationEventType.TrimRight(_T(", "));
	pDoseDocument->getTree().getCurrentContentItem().setStringValue(ConvertCStringToUTF8(IrradiationEventType).c_str());

	LOG_DEBUGGING("NodeID=%d, Level=%d, Position=%s, sPosition=%s", pDoseDocument->getTree().getNodeID(),
		pDoseDocument->getTree().getLevel(), pDoseDocument->getTree().getPosition(sPosition).c_str(), ConvertUTF8ToCString(sPosition.c_str()));

	//pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Image);
	//pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("IR.02", OFFIS_CODING_SCHEME_DESIGNATOR, "Acquired Image"));
	//pDoseDocument->getTree().getCurrentContentItem().setImageReference(DSRImageReferenceValue(UID_SecondaryCaptureImageStorage, "1.3.12.2.1107.5.8.1.123456789.199507271803030521934"));
	//pDoseDocument->getCurrentRequestedProcedureEvidence().addItem("1.3.12.2.1107.5.8.1.123456789.199507271803030520282", "1.3.12.2.1107.5.8.1.123456789.199507271803030521007", UID_SecondaryCaptureImageStorage, "1.3.12.2.1107.5.8.1.123456789.199507271803030521934");

	//pDoseDocument->completeDocument();
}

// CString转为UTF8
std::string DoseStructuredReport::ConvertCStringToUTF8(CString strValue)
{
	std::wstring wbuffer;
	int length = 0;

#ifdef _UNICODE
	wbuffer.assign(strValue.GetString(), strValue.GetLength());
#else
	// 预转换ANSI到UNICODE, 获取转换后长度
	length = ::MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, (LPCTSTR)strValue, -1, NULL, 0);
	wbuffer.resize(length);

	// 转换 
	MultiByteToWideChar(CP_ACP, 0, (LPCTSTR)strValue, -1, (LPWSTR)(wbuffer.data()), wbuffer.length());
#endif

	// 预转换UNICODE到UTF8, 获取转换后长度
	length = WideCharToMultiByte(CP_UTF8, 0, wbuffer.data(), wbuffer.size(), NULL, 0, NULL, NULL);

	// 转换UNICODE到UTF8, 获取转换后内容
	std::string buffer;
	buffer.resize(length);

	WideCharToMultiByte(CP_UTF8, 0, wbuffer.c_str(), -1, (LPSTR)(buffer.data()), length, NULL, NULL);

	return(buffer);
}

// UTF8转为CString
CString DoseStructuredReport::ConvertUTF8ToCString(std::string utf8str)
{
	// 预转换,得到所需空间的大小
	int nLen = ::MultiByteToWideChar(CP_UTF8, NULL, utf8str.data(), utf8str.size(), NULL, 0);

	// UTF8转换为Unicode
	std::wstring wbuffer;
	wbuffer.resize(nLen);

	::MultiByteToWideChar(CP_UTF8, NULL, utf8str.data(), utf8str.size(), (LPWSTR)(wbuffer.data()), wbuffer.length());

#ifdef UNICODE
	return (CString(wbuffer.data(), wbuffer.length()));
#else
	// Unicode转换为ANSI  得到转换后长度
	nLen = WideCharToMultiByte(CP_ACP, 0, wbuffer.data(), wbuffer.length(), NULL, 0, NULL, NULL);

	std::string ansistr;
	ansistr.resize(nLen);

	// unicode转成ansi
	WideCharToMultiByte(CP_ACP, 0, (LPWSTR)(wbuffer.data()), wbuffer.length(),
		(LPSTR)(ansistr.data()), ansistr.size(), NULL, NULL);

	return (CString(ansistr.data(), ansistr.length()));
#endif
}
#pragma once
#include "dcmtk/config/osconfig.h"    
#include "dcmtk/ofstd/ofconsol.h"    
#include "dcmtk/dcmsr/dsrdoc.h"    
#include "dcmtk/dcmdata/dctk.h"
#include <Entity/DcmInfo.h>


// 存储在报告里的一些剂量参数
class DoseStructuredReport : public CDcmImageInfo
{
public:
	// 写入剂量报告
	void WriteDSRDocument(DoseStructuredReport& DoseInfo, CString sFilePath);

private:
	// 追加内容到已有的剂量报告里
	void AppendDSRDocument(DoseStructuredReport& DoseInfo, CString sFilePath);

	// 读取剂量报告DCM文件
	BOOL ReadDSRDocumentDcmFile(DSRDocument* pDoseDocument, CString sFilePath);

	// 把剂量报告保存到DCM文件中
	BOOL StoreDSRDocumentToDcmFile(DSRDocument* pDoseDocument, CString sFilePath);

	// 写入剂量报告的头信息,从病人图像的DCM信息里获取
	void WriteDSRDocumentHeadInfo(DSRDocument* pDoseDocument, DoseStructuredReport& DoseInfo);

	// 写入累计剂量信息
	void WriteDSRDocumentAccumulatedDoseInfo(DSRDocument* pDoseDocument, DoseStructuredReport& DoseInfo, BOOL bIsAppend = FALSE);

	// CString转为UTF8
	std::string ConvertCStringToUTF8(CString strValue);

	// UTF8转为CString
	CString ConvertUTF8ToCString(std::string utf8str);

public:
	// 累计剂量,单位:Gy
	double DoseTotal = 0;

	// 累计DAP,单位:Gy.m2 
	double DoseAreaProductTotal = 0;

	// 射线源到基准点的距离,单位:mm
	UINT DistanceSourceToReferencePoint = 850;

	// 基准点定义,单位:cm
	CString ReferencePointDefinition = _T("30cm above table");

	// 辐照总帧数
	UINT TotalNumOfRadiographicFrames = 0;

	// 总透视时间,单位:s
	UINT TotalFluoroscopyTime = 0;

	// 辐照事件类型,包括3种及它们组合:Radiography,SerialRadiography,Fluoroscopy,
	// bit0 = 1表示Radiography,bit1 = 1表示SerialRadiography,bit2 = 1表示Fluoroscopy
	char IrradiationEventType = 0;
};

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值