DCM医学影像文件的格式与读取方法分享

本文介绍了一段用于解析医学影像DCM文件的代码,包括加载文件、解析DIB数据、获取宽高、窗宽窗位、像素间距等功能,并提供了反色DCM的实现。代码支持进一步扩充和集成到更大框架中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

医学影像DCM是个类似PNG的分块格式,内涵丰富医疗信息,由于应用领域较窄,OpenCV没有提供对其加载支持,一般采用dcmtk库进行加载。

博主本着研究探索的精神写了这段代码,并分享出来,提供了解析DCM的DIB数据、宽高、窗宽窗位、像素间距的功能,支持反色DCM。

将来可以参考spec文档进行扩充,可以在大框架中加入块的处理,从而抽取更多感兴趣的信息,也可以加入压缩DCM的支持。


// 输入:文件名
// 输出:宽高 窗宽窗位 像素间距 dib
unsigned short* dcmLoadImage(char* fn, int& width, int& height, int& windowWidth, int& windowLevel, double& pixelSpacing)
{
	// 读取整个文件到内存
	FILE* f = fopen(fn, "rb");
	fseek(f, 0, SEEK_END);
	int dcmSize = ftell(f);
	fseek(f, 0, SEEK_SET);
	unsigned char* dcm = new unsigned char[dcmSize];
	fread(dcm, dcmSize, 1, f);
	fclose(f);
	
	// 解析
	width = -1;
	height = -1;
	windowWidth = -1;
	windowLevel = -1;
	pixelSpacing = 0.0;
	bool invert = false;
	unsigned short* dib = NULL;
	int dibSize = -1;
	int p = 132;
	while( p<dcmSize )
	{
		short group = *(short*)(dcm+p);
		p+=2;
		short element = *(short*)(dcm+p);
		p+=2;
		//cout<<setfill('0')<<hex<<setw(4)<<group<<","<<setw(4)<<element<<setfill('\0')<<dec<<endl;


		if(group==0x0002)
		{
			if(element==0x0001)// 2,1
			{
				p+=10;
			}
			else// 2,*
			{
				char vr[3];
				vr[0] = dcm[p++];
				vr[1] = dcm[p++];
				vr[2] = '\0';
				short size = *(short*)(dcm+p);
				p+=2;
				p+=size;
			}
		}
		else// *
		{
			int size = *(int*)(dcm+p);
			p+=4;
			if(size==-1)
				size=0;
			if(group==0x0028&&element==0x0010)
				height = *(short*)(dcm+p);
			if(group==0x0028&&element==0x0030)
				pixelSpacing = atof((char*)dcm+p);
			if(group==0x0028&&element==0x0004)
				invert = !strncmp((char*)dcm+p, "MONOCHROME1", 11);
			else if(group==0x0028&&element==0x0011)
				width = *(short*)(dcm+p);
			else if(group==0x0028&&element==0x1050)
				windowLevel = atoi((char*)dcm+p);
			else if(group==0x0028&&element==0x1051)
				windowWidth = atoi((char*)dcm+p);
			else if(group==0x7FE0&&element==0x0010)
			{
				dibSize = size;
				dib = new unsigned short[dibSize];
				memcpy(dib, dcm+p, dibSize);
			}
			p+=size;
		}
	}
	assert(p==dcmSize);
	assert(width!=-1);
	assert(height!=-1);
	assert(windowLevel!=-1);
	assert(windowWidth!=-1);
	assert(dib!=NULL);
	assert(dibSize==width*height*2);
	
	// 反图做修正
	if(invert)
	{
		for(int i=0; i<width*height; i++)
			dib[i] ^= 0xFFFF;
		windowLevel = 65535-windowLevel;
	}
	
	delete[] dcm;
	return dib;
}


void dcmReleaseImage(unsigned short* dib)
{
	delete[] dib;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值