⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dicom.cpp

📁 医学数字影像和通讯_DICOM_编程最新介绍
💻 CPP
字号:
/////////
// Dicom.cpp: implementation of the Dicom class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Dicom.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define KK 10
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

int Dicom::frame_number = 0;
Dicom::Dicom()
{
	/////////////module0:给链表及链表中的char分配空间/////////	
	p_DcmData = (struct DcmData*)malloc(sizeof(struct DcmData));
	p_DcmData->pNext = NULL;
	p_DcmData->slice_location = 0;
	p_DcmData->window_center = NULL;
	p_DcmData->window_width = NULL;
	p_DcmData->pixelx_spacing = NULL;
	p_DcmData->pixely_spacing = NULL;
	p_DcmData->manufacture = NULL;
	p_DcmData->rescale_intercept = NULL;
	p_DcmData->rescale_slope = NULL;
	p_DcmData->rows = 0;
	p_DcmData->columns = 0;
	p_DcmData->transfer = NULL;
	p_DcmData->image_orderID = 0;	
    ///////////////module0:end/////////////////////////////
}

Dicom::~Dicom()
{
}
////////////////////读取DCM文件begin//////////////////////////
Dicom::readDcmfile(CString filename)
{
	int image_tempID;
	
	DcmData* pTemp;
	DcmData* pTemp2;
	CFile dcmfile;
	if (!dcmfile.Open(filename,CFile::modeRead))
		return FALSE;
	/////////////////////module1:判断DICM文件//////////////
	dcmfile.Seek(128,CFile::begin);
	char* dcm;
	dcm = new char(5);
	dcmfile.Read(dcm,4);dcm[4]=0;
	if (strcmp(dcm,"DICM"))
	{
		return FALSE;
	}
	frame_number++;//dicm图片的总数DICOM::frame_number;
	////////////////////module1:end//////////////////////	
	
	/////////////////////DcmData链表指到末尾///////////////
	image_tempID = 1;
	for(pTemp2=p_DcmData;pTemp2->pNext!=NULL;pTemp2=pTemp2->pNext)
		image_tempID++;
	if (Dicom::frame_number!=1)
	{
	pTemp = (struct DcmData*)malloc(sizeof(struct DcmData));
	pTemp->pNext = NULL;
	pTemp->slice_location = 0;
	pTemp->window_center = NULL;
	pTemp->window_width = NULL;
	pTemp->pixelx_spacing = NULL;
	pTemp->pixely_spacing = NULL;
	pTemp->manufacture = NULL;
	pTemp->rescale_intercept = NULL;
	pTemp->rescale_slope = NULL;
	pTemp->rows = 0;
	pTemp->columns = 0;
	pTemp->transfer = NULL;
	pTemp->image_orderID = 0;
	pTemp2->pNext = pTemp;
	pTemp->image_orderID = image_tempID+1;
	}
	else
	{
		pTemp = pTemp2;
		pTemp->image_orderID = image_tempID;
	}
	
	/////////////////////////////////end/////////////////////
	
	///////////////////module2:读取传输语法//////////////	
	unsigned short int gtag,etag;
	unsigned int len;
	BOOL len_ObOwSq;
	len=0;
	len_ObOwSq = FALSE;
	do
	{	
		dcmfile.Seek(len,CFile::current);
		dcmfile.Read(&gtag,2);
		dcmfile.Read(&etag,2);
		dcmfile.Seek(2,CFile::current);
		dcmfile.Read(&len,2);
	}while((gtag != TRANSFER_GROUP)||(etag != TRANSFER_ELEMENT));
	pTemp->transfer = new char[len+1];
	dcmfile.Read(pTemp->transfer,len);
	pTemp->transfer[len] = 0;	
	///////////////////module2:end///////////////////////

	//////////////////module3:根据传输语法读数据/////////
	char vr[3];
	if (!strcmp(pTemp->transfer,EXVR_LENDIAN))
	{
		len=0;gtag=0;etag=0;
		do
		{	
			dcmfile.Read(&gtag,2);
			dcmfile.Read(&etag,2);
			dcmfile.Read(vr,2);
			vr[2] = 0;
			if (!strcmp(vr,"OB")||(!strcmp(vr,"OW"))||(!strcmp(vr,"SQ")))
			{
				dcmfile.Seek(2,CFile::current);
				dcmfile.Read(&len,4);
			}
			else
			{
				dcmfile.Read(&len,2);
			}
			switch(gtag)
			{
			case SLICE_LOCATION_GROUP://image plane module
				switch(etag)
				{
				case SLICE_LOCATION_ELEMENT:
					pTemp->slice_location = new char[len+1];
					dcmfile.Read(pTemp->slice_location,len);
					pTemp->slice_location[len] = 0;
					break;
				case STUDY_NUMBER_ELEMENT:
					pTemp->study_number = new char[len+1];
					dcmfile.Read(pTemp->study_number,len);
					pTemp->study_number[len] = 0;
					break;
				default:
					dcmfile.Seek(len,CFile::current);
					break;
				}
				break;
			case CT_DATA_GROUP:	//ct值
				switch(etag)
				{
				case CT_DATA_ELEMENT:
					dcmfile.Read(&pTemp->ct,len);
					break;
				default:
					dcmfile.Seek(len,CFile::current);
					break;
				}
				break;
			case IMAGE_GROUP://image pixel module
				switch(etag)
				{
				case WINDOW_CENTER_ELEMENT:
					pTemp->window_center = new char[len+1];
					dcmfile.Read(pTemp->window_center,len);
					pTemp->window_center[len] = 0;
					break;
				case WINDOW_WIDTH_ELEMENT:
					pTemp->window_width = new char[len+1];
					dcmfile.Read(pTemp->window_width,len);
					pTemp->window_width[len] = 0;
					break;
				case PIXEL_SPACING_ELEMENT:
					char* temp;
					int i,k;
					temp = new char[len+1];
					dcmfile.Read(temp,len);
					temp[len] = 0;
					for (i=0;temp[i]!=92;i++);
					pTemp->pixelx_spacing = new char[i+1];
					pTemp->pixely_spacing = new char[len-i];
					for (k=0;k<i;k++)
					{
						pTemp->pixelx_spacing[k] = temp[k];
					}
					pTemp->pixelx_spacing[i] = 0;
					for (k=0;k<len-i-1;k++)
					{
						pTemp->pixely_spacing[k] = temp[k+i+1];
					}
					pTemp->pixely_spacing[len-i-1] = 0;
					break;
				case RESCALE_INTERCEPT_ELEMENT:
					pTemp->rescale_intercept = new char[len+1];
					dcmfile.Read(pTemp->rescale_intercept,len);
					pTemp->rescale_intercept[len] = 0;
					break;
				case RESCALE_SLOPE_ELEMENT:
					pTemp->rescale_slope = new char[len+1];
					dcmfile.Read(pTemp->rescale_slope,len);
					pTemp->rescale_slope[len] = 0;
					break;
				case ROWS_ELEMENT:
					dcmfile.Read(&pTemp->rows,len);
					break;
				case COLUMNS_ELEMENT:
					dcmfile.Read(&pTemp->columns,len);
					break;
				default:
					dcmfile.Seek(len,CFile::current);
					break;
				}
				break;
			case MANUFACTURE_GROUP://general equipment module
				switch(etag)
				{
				case MANUFACTURE_ELEMENT:
					pTemp->manufacture = new char[len+1];
					dcmfile.Read(pTemp->manufacture,len);
					pTemp->manufacture[len] = 0;
					break;
				case STUDY_DATA_ELEMENT:
					pTemp->study_data = new char[len+1];
					dcmfile.Read(pTemp->study_data,len);
					pTemp->study_data[len] = 0;
					break;
				default:
					dcmfile.Seek(len,CFile::current);
					break;
				}
				break;
			default:
				dcmfile.Seek(len,CFile::current);
				break;		
			}
		}while((gtag != CT_DATA_GROUP)||(etag != CT_DATA_ELEMENT));	
	}
	//////////////////module3:end////////////////////////

	//////////////////module4:计算窗宽窗位begin///////////////
	int max,min,i,j;
	min = 1001;
	max = -1001;
	for(i=0;i<256;i++)
		for(j=0;j<256;j++)
		{
			min = pTemp->ct[i][j]<min?pTemp->ct[i][j]:min;
			max = pTemp->ct[i][j]>max?pTemp->ct[i][j]:max;
		}
	pTemp->window_width = intTOstr(max-min);
	pTemp->window_center = intTOstr((max-min)/2);
	ctTOpixel(pTemp);//ct值到pixel值的转换
	/////////////////module4:end///////////////////////
	BmpInfor();//初始bmp文件头数据
	dcmfile.Close();
	return TRUE;
}
//////////////////////读取DCM文件end////////////////////////////////////


////////////////////////ct值到象素值的转换begin//////////////////////////////
void Dicom::ctTOpixel(DcmData* p_Temp)
{
	int i,j;
	int min,max;
	int pixel;
	double intercept,slope;
	if (p_Temp->rescale_intercept==NULL)
		intercept = 0;
	else intercept = strTOdouble(p_Temp->rescale_intercept);
	if (p_Temp->rescale_slope==NULL)
		slope = 1;
	else slope = strTOdouble(p_Temp->rescale_slope);
	for(i=0;i<256;i++)
		for(j=0;j<256;j++)
		{

			min = (2*strTOdouble(p_Temp->window_center) - strTOdouble(p_Temp->window_width))/2.0 + 0.5;
			max = (2*strTOdouble(p_Temp->window_center) + strTOdouble(p_Temp->window_width))/2.0 + 0.5;
			pixel = (p_Temp->ct[i][j]*slope+intercept-min)*255.0/(double)(max - min);
			p_Temp->pixel[i][j] = pixel;
			if (pixel>255)
				p_Temp->pixel[i][j] = 255;	
			if (pixel<0)
				p_Temp->pixel[i][j] = 0;

		}
}
////////////////////////ct值到象素值的转换end//////////////////////////////


////////////////////////字符到双精度的转换begin///////////////////////////////
double Dicom::strTOdouble(char* str)
{
	int i;
	char* pTemp;
	pTemp = str;
	double lalala;
	lalala = 0;
	for(i=0;(*pTemp!=46)&&(*pTemp!=0);pTemp++,i++);
	pTemp = str;
	for(;*pTemp!=0;pTemp++,i--)
	{

	int k;
		double d;
		d =0;
		if(i>0)
		{
			d = (*pTemp-48);
			for(k=i-1;k!=0;k--)
				d = d*10;
		}

		if(i<0)
		{
			d = (*pTemp-48);
			for(k=i;k!=0;k++)
				d = d*0.1;
		}
		lalala = lalala+d;
	}
	return (lalala);
}
/////////////////////////////字符到双精度的转换end/////////////////////////////////


/////////////////////////////整形到字符的转换begin////////////////////////////////
char* Dicom::intTOstr(int itemp)
{
	int b,temp;
	char* pctemp;
	temp = itemp;
	for(b=0;temp!=0;temp/=10,b++)
	pctemp = new char[b+1];
	pctemp[b] = 0;
	temp = itemp;
	for(;b>0;b--)
	{
		pctemp[b-1] = 48+temp%10;
		temp/=10;
	}
	return pctemp;
}
/////////////////////////////整形到字符的转换摁钉end////////////////////////////////


//////////////////////////////module5:给bmp信息赋值/////////////
void Dicom::BmpInfor()
{
	bmphead.bfType = 0x4D42;
	bmphead.bfSize = 66614;
	bmphead.bfReserved = 0;
	bmphead.bfOffBits = 0x436;
	bmphead.biSize = 0x28;
	bmphead.biWidth = 256;
	bmphead.biHeight = 256*frame_number; 
	bmphead.biPlanes = frame_number; 
	bmphead.biBitCount = 8; 
	bmphead.biCompression = 0; 
	bmphead.biSizeImage = 65536*frame_number;
	bmphead.biXPelsPerMeter = (int)1000/strTOdouble(p_DcmData->pixelx_spacing);
	bmphead.biYPelsPerMeter = (int)1000/strTOdouble(p_DcmData->pixely_spacing);
	bmphead.biClrUsed = 256;
	bmphead.biClrImportant = 0;
	int i;
	for (i=0;i<256;i++)
	{
		bmphead.bmiColors[i].rgbBlue = i; 
		bmphead.bmiColors[i].rgbGreen = i; 
		bmphead.bmiColors[i].rgbRed = i; 
		bmphead.bmiColors[i].rgbReserved = 0;

	}
}
///////////////////////////////module5:给bmp信息赋值/////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -