很久前写的,也其实就实现一个简单显示的问题,对于“窗位”,“窗宽”的取值问题,以前在CSDN上提问过,却没有得到很好的解决方案。
对与DICOM图片的打开也就实现了,“窗位”,“窗宽”标明的。把显示部分的代码放上来,希望对刚接触DICOM图片格式的人有点帮助,若有高手希望指点下,“窗宽”,“窗位”的取值问题。
我碰到过三种DICOM图片:1.窗位,窗宽的标识位后直接标明直接用就行,2.虽然有值确实一个很大的数值,直接引用显示效果不理想,3、没有标明数值。
代码是VS2003 C++ 写 的:
void CKlsMsgClientDlg::showdicom(CString filepath)//
{
unsigned char *m_pDibBits,*m_pDibBits_Save;
long DicomData,max,min,k,height,width;
BITMAPINFOHEADER *m_pBIH;
BITMAPFILEHEADER * m_pB;
CFile file;
CFileException fe;
if (!file.Open(filepath, CFile::modeRead | CFile::shareDenyWrite, &fe))
{//以“读”的方式打开文件;
AfxMessageBox("图像文件打不开!");
return;
}
if(GetFileAttributes(filepath) == FILE_ATTRIBUTE_DIRECTORY)
{
MessageBox("选择错误");
return;
}
DWORD dwDibSize;
dwDibSize = file.GetLength();
unsigned char *pDib;
pDib = new unsigned char[dwDibSize];
int w_c= 0;
int w_w =0;
try
{
if (file.Read(pDib, dwDibSize) != dwDibSize)
{
delete []pDib;
return;
}
}
catch (CFileException *e)
{
e->Delete();
delete []pDib;
return;
}
unsigned char tag1,tag2,tag3,tag4;
unsigned char *Info;
DWORD win;
DWORD winWidth;
int NameLen;
unsigned char *Name;
tag1 = 0xe0;
tag2 = 0x7f;
tag3 = 0x10;
tag4 = 0x00;
for(int i=0;i< dwDibSize;i++)
{
if(*(pDib+i) == tag1 && *(pDib+i+1) == tag2 && *(pDib+i+2) == tag3 && *(pDib+i+3) == tag4)
{
// InfoLen = (*(pDib+i+6))*65536+(*(pDib+i+5))*256+(*(pDib+i+4));
Info = pDib+i+8;
break;
}
}
dwDibSize -= i;
tag1 = 0x10;
tag2 = 0x00;
tag3 = 0x10;
tag4 = 0x00;
for(i=0;i<dwDibSize;i++)
{
if(*(pDib+i) == tag1 && *(pDib+i+1) == tag2 && *(pDib+i+2) == tag3 && *(pDib+i+3) == tag4)
{
//NameLen = (*(pDib+i+6))*65536+(*(pDib+i+5))*256+(*(pDib+i+4));
Name = (pDib+i+8);
break;
}
}
CString sname(Name);
CClientDC dc(this);
// dc.TextOut(400,10,sname);
tag1 =0x28;
tag2 = 0x00;
tag3 = 0x10;
tag4 = 0x00;//行数
for(i=0;i<dwDibSize;i++)
{
if(*(pDib+i) == tag1 && *(pDib+i+1) == tag2 && *(pDib+i+2) == tag3 && *(pDib+i+3) == tag4)
{
height = (*(pDib+i+9))*256+(*(pDib+i+8));
break;
}
}
tag1 =0x28;
tag2 = 0x00;
tag3 = 0x11;
tag4 = 0x00;//列数
for(i=0;i<dwDibSize;i++)
{
if(*(pDib+i) == tag1 && *(pDib+i+1) == tag2 && *(pDib+i+2) == tag3 && *(pDib+i+3) == tag4)
{
width = (*(pDib+i+9))*256+(*(pDib+i+8));
break;
}
}
tag1 =0x28;
tag2 = 0x00;
tag3 = 0x50;
tag4 = 0x10;//窗位
long datesize=0;
win=0;
for(int i=0;i<dwDibSize;i++)
{
if(*(pDib+i) == tag1 && *(pDib+i+1) == tag2 && *(pDib+i+2) == tag3 && *(pDib+i+3) == tag4)
{
NameLen=(*(pDib+i+7))*256+(*(pDib+i+6));
for(int j = 0;j<NameLen ;j++)
{
if(*(pDib+i+8+j) == 0x2E)
{
break;
}
w_c ++;
}
for(int j=0;j<w_c;j++)
{
win= win + ((*(pDib + i+8+j)-48) * pow(10,(w_c-1-j)));
}
break;
}
}
w_c=0;
/////////////
tag1 =0x28;
tag2 = 0x00;
tag3 = 0x51;
winWidth=0;
tag4 = 0x10;//窗宽
for(i=0;i<dwDibSize;i++)
{
if(*(pDib+i) == tag1 && *(pDib+i+1) == tag2 && *(pDib+i+2) == tag3 && *(pDib+i+3) == tag4)
{
NameLen=(*(pDib+i+7))*256+(*(pDib+i+6));
for(int j = 0;j<NameLen ;j++)
{
if(*(pDib+i+8+j) == 0x2E)
{
break;
}
w_w ++;
}
for(int j=0;j<w_w;j++)
{
winWidth= winWidth + ((*(pDib + i+8+j)-48) * pow(10,(w_w-1-j)));
}
break;
}
}
w_w=0;
//if(width>1024)
//{
// height = height/4;
// width = width/4;
//}
m_pDibBits = new unsigned char [width*height*3];
m_pDibBits_Save = new unsigned char[width*height*3];
m_pBIH = new BITMAPINFOHEADER;
m_pB = new BITMAPFILEHEADER;
m_pBIH->biSize = 40;
m_pBIH->biWidth = width;
m_pBIH->biHeight = height;
m_pBIH->biPlanes = 1;
m_pBIH->biBitCount = 24;
m_pBIH->biSizeImage = 0;
m_pBIH->biClrUsed = 0;
m_pBIH->biClrImportant = 0;
m_pBIH->biCompression = 0; //BI_RGB;
m_pBIH->biXPelsPerMeter = 3780;
m_pBIH->biYPelsPerMeter = 3780;
m_pB->bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
m_pB->bfReserved1=0;
m_pB->bfReserved2=0;
m_pB->bfSize =width*height*3 + (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
m_pB->bfType=0x4d42;
max=win+winWidth/2;
min=win-winWidth/2;
for(k=0;k<width*height;k++)
{
DicomData = (*(Info+k*2))+(*(Info+k*2+1))*256;
if(DicomData < min)
{
*(m_pDibBits+k*3) = 0;
*(m_pDibBits+k*3+1) = 0;
*(m_pDibBits+k*3+2) = 0;
}
else if(DicomData >max)
{
*(m_pDibBits+k*3) = 255;
*(m_pDibBits+k*3+1) = 255;
*(m_pDibBits+k*3+2) = 255;
}
else
{
*(m_pDibBits+k*3) = (DicomData+winWidth/2-win)*256/winWidth;
*(m_pDibBits+k*3+1) = (DicomData+winWidth/2-win)*256/winWidth;
*(m_pDibBits+k*3+2) = (DicomData+winWidth/2-win)*256/winWidth;
}
}
for(int i=0;i<height;i++)
{
for(int j=0;j<width*3;j++)
{
*(m_pDibBits_Save+height*width*3-width*3-i*width*3+j)=*(m_pDibBits+i*width*3 + j);
}
}
int nSize = sizeof(BITMAPFILEHEADER) + (width*height*3) +40;
BYTE* pBuffer = new BYTE[nSize];
memcpy(pBuffer,m_pB,sizeof(BITMAPFILEHEADER));
memcpy(pBuffer + sizeof(BITMAPFILEHEADER),m_pBIH,40);
memcpy(pBuffer +sizeof(BITMAPFILEHEADER) +40,m_pDibBits_Save,width*height*3);
CString sFilePathName = "d:\\AF.bmp";
CFile PictureFile;
CFileException e;
if(PictureFile.Open(sFilePathName, CFile::modeWrite |CFile::modeCreate| CFile::typeBinary, &e))
{
PictureFile.Write(pBuffer, nSize) ;
PictureFile.Close();
delete [] pBuffer;
}else
{
MessageBox("保存文件出错!");
}
m_PicShow.ShowPic(sFilePathName);
m_csPicPath = sFilePathName;
}