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

📄 dicombmpdlg.cpp

📁 将医学上Dicom格式的图像转换为BMP格式的图像。
💻 CPP
📖 第 1 页 / 共 2 页
字号:

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CDicomBMPDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CDicomBMPDlg::OnModeChanged() 
{
	UpdateData();	// Get data from UI
	AfxGetApp()->WriteProfileInt("Defaults", "Mode", m_nConvertMode);

}

void CDicomBMPDlg::OnConvertFile() 
{
  int nIndex = 0;

  // Pop up the File Dialog for Open
  CFileDialog FileDlg( TRUE, NULL, NULL, OFN_ENABLESIZING,
		       szFilter_in );
  FileDlg.m_ofn.nFilterIndex = (DWORD) (m_nConvertMode+1);
  if (m_strFileDir.GetLength())
    FileDlg.m_ofn.lpstrInitialDir = m_strFileDir.GetBuffer(3);

  if( FileDlg.DoModal() == IDOK ){

    // Open and store the file name
    CString PathName = FileDlg.GetPathName();
    PathName.MakeUpper();

	m_strFileName = PathName;
    m_strFileDir = PathName;
    int index;
    if (((index = m_strFileDir.ReverseFind('\\')) != -1)
	&&  (m_strFileDir.GetAt(index-1) != ':'))
      m_strFileDir.SetAt(index, '\0');

    // Parse the file format
    nIndex = (int) FileDlg.m_ofn.nFilterIndex;

    // Save directory and file format into the registry
    AfxGetApp()->WriteProfileString("Defaults", "Dir", m_strFileDir);

	// Start convertsion
	switch(m_nConvertMode)
	{
	case MODE_DICOM2BMP:
		ConvertDicomToBMP();
		break;

	case MODE_BMP2DICOM:
		ConvertBmpToDicom();
		break;
	}


  }
	
}

/////////////////////////////////////////////////////////////////////////////
// CDicomBMPDlg Main Implementation methods

void CDicomBMPDlg::ConvertBmpToDicom()
{
	AfxMessageBox("ConvertBmpToDicom() not implemented");

	// To do: insert your BMP to DICOM conversion code here.
}

void CDicomBMPDlg::ConvertDicomToBMP()
{

	short int nCols = 0, nRows = 0;
    short int nBitsAllocated, nSamplesPerPixel = 1;
	short int nHighBit = 0;
	float fWindowWidth = 0, fWindowCenter = 0 , fRescaleSlope = 1, fRescaleIntercept = 0;
	BOOL bIsSigned = FALSE;

	int nBytesP = 0;
	int nFrameSize = 0;
	long int nLength;
	const char *pszFileName = m_strFileName.GetBuffer(3);
	char szPhotometric[32]="", szTemp[32]="", szTransferSyntaxUID[80]="";

	BOOL bImplicitVR = TRUE;
	COMPRESSION_MODE nCompressionMode = COMPRESS_NONE;
	DATA_ENDIAN nDataEndian = LITTLE_ENDIAN;
	int i;
	int nBytes;


   FILE *fp;
   char *pData = 0;
   short int gTag, eTag;
   int nNumFrames = 1;

   fp = fopen(pszFileName, "rb");
   if (!fp)
    {
       AfxMessageBox("Failed to open file for read.");
       return;
    }

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

      switch(gTag)
      {
	   case 0x0002: // Meta header. 

		 fread(&eTag, sizeof(short), 1, fp);
		 // Meta header is always in Little Endian Explicit VR syntax.
         switch(eTag)
          {
             case 0x0010: // Transfer syntax UID
				 readString(fp, szTransferSyntaxUID, FALSE, LITTLE_ENDIAN);

				// Check data endian.
				if (!strcmp(szTransferSyntaxUID, "1.2.840.10008.1.2.2")) // Explicit VR Big Endian 
					nDataEndian = BIG_ENDIAN; // Big Endian
				else
					nDataEndian = LITTLE_ENDIAN; // Little Endian

				// Check if it is implicit VR or Explicit VR
				if (!strcmp(szTransferSyntaxUID, "1.2.840.10008.1.2")) // Implicit VR Little Endian 
					bImplicitVR = TRUE; // Implicit VR
				else
					bImplicitVR = FALSE; // Explicit VR

				// Parse the encapsulation/compression
				if (!strcmp(szTransferSyntaxUID, "1.2.840.10008.1.2.4.50")) // JPEG lossy
					nCompressionMode = COMPRESS_JPEGLOSSY;
				else if (!strcmp(szTransferSyntaxUID, "1.2.840.10008.1.2.4.51")) // JPEG lossy 12bit
					nCompressionMode = COMPRESS_JPEGLOSSY12BIT;
				else if (!strcmp(szTransferSyntaxUID, "1.2.840.10008.1.2.4.70")) // JPEG lossless first order prediction
					nCompressionMode = COMPRESS_JPEGLOSSLESS;
				else if (!strcmp(szTransferSyntaxUID, "1.2.840.10008.1.2.4.57")) // JPEG lossless process 14
					nCompressionMode = COMPRESS_JPEGLOSSLESS2;
				else if (!strcmp(szTransferSyntaxUID, "1.2.840.10008.1.2.5")) // RLE
					nCompressionMode = COMPRESS_RLE;

			break;

		 }
		 break;
       case 0x0028: // Image pixel data info group
         fread(&eTag, sizeof(short), 1, fp);
 	     if (nDataEndian == BIG_ENDIAN)
			   SwapWord((char *) &eTag, 1);

         switch(eTag)
          {
             case 0x0010: // Rows
			   nRows = readUS(fp, nDataEndian);
               break;

            case 0x0011: // Columns
			   nCols = readUS(fp, nDataEndian);
               break;

            case 0x0100: // Bits allocated
			   nBitsAllocated = readUS(fp, nDataEndian);
               break;

			case 0x0102: // High bit
				nHighBit = readUS(fp, nDataEndian);
				break;

			case 0x0103: // Is signed?
				bIsSigned = readUS(fp, nDataEndian);
				break;


            case 0x0002: // Samples per Pixel
				nSamplesPerPixel = readUS(fp, nDataEndian);
               break;

            case 0x0004:  // Photometric Interpolation
				readString(fp, szPhotometric, bImplicitVR, nDataEndian);
               break;

            case 0x0008:  // Number of frames
				nNumFrames = readIS(fp, bImplicitVR, nDataEndian);
               break;

			case 0x1050: // Window Center
				fWindowCenter = readDS(fp, bImplicitVR, nDataEndian);
				break;

			case 0x1051: // Window Width
				fWindowWidth = readDS(fp, bImplicitVR, nDataEndian);
				break;

			case 0x1052: // Rescale intercept
				fRescaleIntercept = readDS(fp, bImplicitVR, nDataEndian);
				break;

			case 0x1053: // Rescale slope
				fRescaleSlope = readDS(fp, bImplicitVR, nDataEndian);
				break;

			default:
				// do nothing
				break;
           }
         break;
        case 0x7fe0:
         fread(&eTag, sizeof(short), 1, fp);
 	     if (nDataEndian == BIG_ENDIAN)
			   SwapWord((char *) &eTag, 1);

         if (eTag == 0x0010)
         {
			 nBytesP = nSamplesPerPixel*nBitsAllocated/8;
			 nFrameSize = nCols * nRows * nBytesP;
			 nLength = nNumFrames * nFrameSize;

			 switch(nCompressionMode)
			 {
			 case COMPRESS_NONE:
				 pData = new char[nLength + 16];
				 fseek(fp, 4, SEEK_CUR); // Skip 4 bytes (length bytes)
				 nBytes = fread(pData, 1, nLength, fp); 

				 if (nBytes != nLength)
				 {
					 AfxMessageBox("Failed to read all pixel data.");
				 }
				 break;

			 case COMPRESS_RLE:
				 AfxMessageBox("RLE compression not supported at this moment");
				 // To do:  
				 //   1. Read the offset table.
				 //   2. Read and uncompress RLE image frames into either RGB or monochrome format.
				 //   3. Put frames in the pData buffer, one frame after another.
				 //  Public domain RLE decompression source code is in Papyrus and dcmtk. 
				 break;
			 case COMPRESS_JPEGLOSSY:
				 AfxMessageBox("JPEG lossy compression not supported at this moment");
				 // To do:  
				 //   1. Read the offset table
				 //   2. Read and uncompress JPEG image frames into either RGB or monochrome format.
				 //   3. Put frames in the pData buffer, one frame after another.
				 //  Public domain JPEG decompression source code is in Papyrus and dcmtk. 
				 break;
			 case COMPRESS_JPEGLOSSY12BIT:
				 AfxMessageBox("JPEG lossy 12-bit compression not supported at this moment");
				 // To do:  
				 //   1. Read the offset table
				 //   2. Read and uncompress JPEG image frames into either RGB or monochrome format.
				 //   3. Put frames in the pData buffer, one frame after another.
				 //  Public domain JPEG decompression source code is in Papyrus and dcmtk. 
				 break;
			 case COMPRESS_JPEGLOSSLESS:
			 case COMPRESS_JPEGLOSSLESS2:
				 AfxMessageBox("JPEG lossless compression not supported at this moment");
				 // To do:  
				 //   1. Read the offset table
				 //   2. Read and uncompress JPEG image frames into either RGB or monochrome format.
				 //   3. Put frames in the pData buffer, one frame after another.
				 //  Public domain JPEG decompression source code is in Papyrus and dcmtk. 
				 break;
			 }

         }
         break;
	  }

	  if (pData) 
		  break; // We are done.
    }

  fclose(fp);

  if (pData) // Have we got the pixel data?
  {
	  // Need to do byte swap?
	  if (nDataEndian == BIG_ENDIAN)
	  {
		  if (nBitsAllocated > 8)
			SwapWord(pData, nLength/2);
	  }

	  if (nBitsAllocated > 8)
	  {
		  // We need to convert it to 8-bit.
		  char *pNewData;

		  pNewData = convertTo8Bit(pData, nLength/2, bIsSigned, nHighBit,
			  fRescaleSlope, fRescaleIntercept, fWindowCenter, fWindowWidth);

		  // Use the new 8-bit data.
		  if (pNewData)
		  {
			  delete [] pData;
			  pData = pNewData;
			  nBytesP = 1;
			  nFrameSize /= 2;

			  nLength /= 2;
		  }
	  }

	  // Write BMP files
	  for (i = 0; i < nNumFrames; i++)
		WriteBMPFile(pData + nFrameSize*i, nFrameSize, nCols, nRows, nBytesP, szPhotometric, i+1);

	  // Free the memory.
	  delete [] pData;

	  AfxMessageBox("Images successfully converted into BMP.");

  }

}

// pData is already converted to either 8-bit flat grayscale or 24-bit RGB.
int	CDicomBMPDlg::WriteBMPFile(char *pData, int nFrameSize, short nCols, short nRows, int nBytesP, char *pszPhotometric, int nFrameNum)
{

	BITMAPFILEHEADER bf;
	BITMAPINFOHEADER bi;
	int nPaletteSize = sizeof(RGBQUAD)*256;
	char szBMPFileName[512], *cc;
	FILE *fp;
	int i, j, nBytes, nRowPadding, nRowBytes;
	unsigned char oneLutSlot[4];
	char szPadding[4] = {'\0', '\0', '\0', '\0'};

	if (!strncmp(pszPhotometric, "RGB", 3) || !strncmp(pszPhotometric, "YBR", 3))
		nPaletteSize = 0;

	// Attention:
	//  1. BMP image rows need to be 4-byte aligned.
	//  2. BMP image is usually bottom up in reverse direction to DICOM images.
	nRowBytes = nCols*nBytesP;
	nRowPadding = nRowBytes%4;
 
	//here fill in the two info structure
	bf.bfType = 0x4D42; 
	bf.bfSize= sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + nPaletteSize + nFrameSize + nRowPadding*nRows;
	bf.bfReserved1 = 0; 
	bf.bfReserved2 = 0; 
	bf.bfOffBits=sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + nPaletteSize; 

	bi.biSize=sizeof(BITMAPINFOHEADER);
	bi.biWidth = nCols; 
	bi.biHeight = nRows; 
	bi.biPlanes = 1;
	if (nPaletteSize == 0)
	{
		bi.biBitCount = 24;
		bi.biClrUsed = 0; 
		bi.biClrImportant = 0;
	}
	else
	{
		bi.biBitCount = 8;
		bi.biClrUsed = 256; 
		bi.biClrImportant = 256;
	}
	bi.biCompression = 0; 
	bi.biSizeImage = nFrameSize;
	
  //
  // Resolutions are in pixels per meter.  Our IMAGES file uses
  // a resolution of 72 pixels per inch, which when multiplied by
  // 39.37 inches per meter, gives us 2835 pixels per meter.
  //
	bi.biXPelsPerMeter = 2835; 
	bi.biYPelsPerMeter = 2835;
	
	// Make file name and give it a .BMP extension.
	strcpy(szBMPFileName, m_strFileName.GetBuffer(3));

	if (!(cc = strrchr(szBMPFileName, '.'))) // Find the '.' or end of file name.
		cc = szBMPFileName + strlen(szBMPFileName);
	sprintf(cc, "_%04d.BMP", nFrameNum); // Append file number and extension.

	// Open the file for wirte.
	fp = fopen(szBMPFileName, "wb");
	if (fp == NULL)
		AfxMessageBox("Failed to open file for write.");

	// Write the BMP and DIB file headers.
	nBytes = fwrite((void *)&bf, 1, sizeof(BITMAPFILEHEADER), fp);
	// if (nBytes != sizeof(BITMAPFILEHEADER))
	//    post your error message here.

	nBytes = fwrite((void *)&bi, 1, sizeof(BITMAPINFOHEADER), fp);
	// if (nBytes != sizeof(BITMAPINFOHEADER))
	//    post your error message here.


	// Write the color palette if 8-bit
	if (nPaletteSize != 0)
		for (i = 0; i < 256; i++)
		{
			oneLutSlot[0] = oneLutSlot[1] = oneLutSlot[2] = i; // Grayscale LUT.
			oneLutSlot[3] = 0;
			fwrite(oneLutSlot, 1, 4, fp); // Write one color palette slot.
		}

	// Now write the actual pixel data.
	cc = pData + (nRows - 1)*nRowBytes;
	if (nPaletteSize != 0) // Grayscale
		for (i = 0; i < nRows; i ++)
		{
			nBytes = fwrite(cc, 1, nRowBytes, fp); // Write a row.
			//if (nBytes != nRowBytes)
			//    post your error message here.

			if (nRowPadding) // Pad the row.
				fwrite(szPadding, 1, nRowPadding, fp);

			cc -= nRowBytes;
		}
	else
		for (i = 0; i < nRows; i ++)
		{
			for (j = 0; j < nCols; j++, cc += 3)
			{
				fputc(*(cc + 2), fp); // B
				fputc(*(cc + 1), fp); // G
				fputc(*cc, fp);       // R
			}

			if (nRowPadding) // Pad the row.
				fwrite(szPadding, 1, nRowPadding, fp);

			cc -= 2*nRowBytes;
		}
		
	fclose(fp);

	return 0;
}

⌨️ 快捷键说明

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