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

📄 dicombmpdlg.cpp

📁 将医学上Dicom格式的图像转换为BMP格式的图像。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// DicomBMPDlg.cpp : implementation file
//
/*************************************************************************BOFH**
* COPYRIGHT (C) JB Wang 2003
********************************************************************************
*
* FILE NAME: DicomBMPDlg.cpp
*
* ONE LINE SUMMARY: DICOM File into BMP and BMP File to DICOM converter
*
*   
* DESCRIPTION: 
*
* NOTES: This program is released to www.cnpacs.org as a teaching material. 
*        Anybody can use it freely for any intended purposes.
*        The software is released as it is without warantee.
*
* REVISION HISTORY:
* Rev           When        Who         What
*               05/26/2003  JB Wang     Created
*
**************************************************************************EOFH*/

#include "stdafx.h"
#include "DicomBMP.h"
#include "DicomBMPDlg.h"

#include <stdio.h>

enum CONVERSION_MODE
{
	MODE_DICOM2BMP = 0,
    MODE_BMP2DICOM
};

enum COMPRESSION_MODE
{
	COMPRESS_NONE = 0,
    COMPRESS_RLE,
    COMPRESS_JPEGLOSSY,
    COMPRESS_JPEGLOSSY12BIT,
    COMPRESS_JPEGLOSSLESS,
    COMPRESS_JPEGLOSSLESS2
};

static char szFilter_in[] = "DICOM File(*.dcm)|*.dcm|BMP File(*.bmp)|*.bmp|All files(*.*)|*.*||";


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDicomBMPDlg dialog

CDicomBMPDlg::CDicomBMPDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CDicomBMPDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CDicomBMPDlg)
	m_nConvertMode = 0;
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

    m_strFileDir = AfxGetApp()->GetProfileString("Defaults", "Dir", "");
	m_nFileFormat = AfxGetApp()->GetProfileInt("Defaults", "Format", 0);
	m_nConvertMode = AfxGetApp()->GetProfileInt("Defaults", "Mode", MODE_DICOM2BMP);

}

void CDicomBMPDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CDicomBMPDlg)
	DDX_Radio(pDX, IDC_BMPDICOM, m_nConvertMode);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CDicomBMPDlg, CDialog)
	//{{AFX_MSG_MAP(CDicomBMPDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BMPDICOM, OnModeChanged)
	ON_BN_CLICKED(IDC_BMPDICOM2, OnModeChanged)
	ON_BN_CLICKED(IDC_CONVERT_FILE, OnConvertFile)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDicomBMPDlg DICOM fields reading and translation methods

//static 
void CDicomBMPDlg::removeTailingSpace(char *pszStr)
{
	char *cc = pszStr + strlen(pszStr) - 1;

	while (((*cc == ' ') || (*cc == '\t')) && (cc != pszStr))
	{
		*cc -- = '\0';
	}
}

//static
void CDicomBMPDlg::SwapWord(char *pArray, int nWords)
{
	char *cc = pArray, c0;
	int i;

	// Swap every two bytes
	for (i = 0; i < nWords; i ++)
	{
		c0 = *cc;
		*cc = *(cc + 1);
		*(cc + 1)  = c0;

		cc += 2;
	}
}

//static
void CDicomBMPDlg::SwapDWord(char *pArray, int nDWords)
{
	char *cc = pArray, c0;
	int i;

	// Rotate every four bytes
	for (i = 0; i < nDWords; i ++)
	{

		// Swap first and last bytes
		c0 = *cc;
		*cc = *(cc + 3);
		*(cc + 3)  = c0;

		// Swap middle two bytes
		c0 = *(cc + 2);
		*(cc + 2) = *(cc + 1);
		*(cc + 1)  = c0;

		cc += 4;
	}
}

//static 
int CDicomBMPDlg::readUS(FILE *fp, DATA_ENDIAN nDataEndian)
{
   unsigned short nVal;

   fseek(fp, 4, SEEK_CUR); // Skip VR and Length bytes (4)
   fread(&nVal, 1, sizeof(short), fp); // read the unsigned short value
   if (nDataEndian == BIG_ENDIAN)
	   SwapWord((char *) &nVal, 1);

   return (int) nVal;

}

//static 
long int CDicomBMPDlg::readLength(FILE *fp, BOOL bImplicitVR, DATA_ENDIAN nDataEndian)
{
	long int nValLength = 0;
	short int nsLength;

	if (bImplicitVR)
	{
		fread(&nValLength, sizeof(long), 1, fp);
		if (nDataEndian == BIG_ENDIAN)
		   SwapDWord((char *) &nValLength, 1);
	}
	else
	{
		fseek(fp, 2, SEEK_CUR); // Skip 2 VR bytes

		fread(&nsLength, sizeof(short), 1, fp);
		if (nDataEndian == BIG_ENDIAN)
		   SwapWord((char *) &nsLength, 1);

		nValLength = nsLength;
	}

	return nValLength;
}

//static 
int CDicomBMPDlg::readIS(FILE *fp, BOOL bImplicitVR, DATA_ENDIAN nDataEndian)
{
	char szTemp[64]="";
	int nVal = 0;

	readString(fp, szTemp, bImplicitVR, nDataEndian);
	sscanf(szTemp, "%d", &nVal);

	return nVal;
}

//static 
float CDicomBMPDlg::readDS(FILE *fp, BOOL bImplicitVR, DATA_ENDIAN nDataEndian)
{
	char szTemp[64]="";
	float fVal = 0;

	readString(fp, szTemp, bImplicitVR, nDataEndian);
	sscanf(szTemp, "%f", &fVal);

	return fVal;
}

//static 
int CDicomBMPDlg::readString(FILE *fp, char *pszStr, BOOL bImplicitVR, DATA_ENDIAN nDataEndian)
{
	long int nValLength = 0;
	int nVal = 0;

	nValLength = readLength(fp, bImplicitVR, nDataEndian);

	fread(pszStr, 1, nValLength, fp); 
	pszStr[nValLength] = '\0';
	removeTailingSpace(pszStr);

	return nVal;
}

//static 
char *CDicomBMPDlg::convertTo8Bit(char *pData, long int nNumPixels, BOOL bIsSigned, short nHighBit, 
								  float fRescaleSlope, float fRescaleIntercept, 
								  float fWindowCenter, float fWindowWidth)
{
	unsigned char *pNewData = 0;
	long int nCount;
	short *pp;

	// 1. Clip the high bits.
	if (nHighBit < 15)
	{
		short nMask;
		short nSignBit;
		
		pp = (short *)pData;
		nCount = nNumPixels;

		if(bIsSigned == 0 ) // Unsigned integer
		{ 
		  nMask = 0xffff << (nHighBit + 1);
      
		  while( nCount-- > 0 )
			*(pp ++) &= ~nMask;
		}
		else
		{		
		 // 1's complement representation
		
			nSignBit = 1 << nHighBit;
			nMask = 0xffff << (nHighBit + 1);
			while( nCount -- > 0 )
			  {
					if ((*pp & nSignBit) != 0)
					  *(pp ++) |= nMask;
					else
					  *(pp ++) &= ~nMask;
			  }
		}
	}

	// 2. Rescale if needed (especially for CT)
	if ((fRescaleSlope != 1.0f) || (fRescaleIntercept != 0.0f))
	{
		float fValue;

		pp = (short *)pData;
		nCount = nNumPixels;

	    while( nCount-- > 0 ) 
		{
		  fValue = (*pp) * fRescaleSlope + fRescaleIntercept;
		  *pp ++ = (short)fValue;
		}

	}

	// 3. Window-level or rescale to 8-bit
	if ((fWindowCenter != 0) || (fWindowWidth != 0)) 
	{
		float fSlope;
		float fShift;
		float fValue;
		unsigned char *np = new unsigned char[nNumPixels+4];

		pNewData = np;

		// Since we have window level info, we will only map what are
		// within the Window.

		fShift = fWindowCenter - fWindowWidth / 2.0f;
		fSlope = 255.0f / fWindowWidth;

		nCount = nNumPixels;
		pp = (short *)pData;
    
		while (nCount-- > 0) 
		  {
			fValue = ((*pp ++) - fShift) * fSlope;
			if (fValue < 0)
			  fValue = 0;
			else if (fValue > 255)
			  fValue = 255;
			
			*np ++ = (unsigned char) fValue;
		  }

	}
	else
	{
		// We will map the whole dynamic range.
		float fSlope;
		float fValue;
		int nMin, nMax;
		unsigned char *np = new unsigned char[nNumPixels+4];

		pNewData = np;

		// First compute the min and max.
		nCount = nNumPixels;
		pp = (short *)pData;
		nMin = nMax = *pp;
		while (nCount-- > 0)
		{
			if (*pp < nMin)
				nMin = *pp;

			if (*pp > nMax)
				nMax = *pp;

			pp ++;
		}

		// Calculate the scaling factor.
		if (nMax != nMin)
			fSlope = 255.0f / (nMax - nMin);
		else
			fSlope = 1.0f;

		nCount = nNumPixels;
		pp = (short *)pData;
		while (nCount-- > 0) 
		  {
			fValue = ((*pp ++) - nMin) * fSlope;
			if (fValue < 0)
			  fValue = 0;
			else if (fValue > 255)
			  fValue = 255;
			
			*np ++ = (unsigned char) fValue;
		  }
	}

	return (char *)pNewData;
}

/////////////////////////////////////////////////////////////////////////////
// CDicomBMPDlg message handlers

BOOL CDicomBMPDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CDicomBMPDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CDicomBMPDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

⌨️ 快捷键说明

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