把DICOM文件中的图像部分提取到BMP文件的函数

原创 2006年06月23日 13:24:00

首先建立一个对话框矿类CDicomBMPDlg ,然后写函数

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;

 BOOL bGroup2Done = FALSE, bGroup28Done = FALSE, bPixelDataDone = 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.

   if (bGroup2Done)
      break;

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

    // 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;

    bGroup2Done = TRUE;

   break;

   }
   break;

       case 0x0008: // First non-Meta group
         fread(&eTag, sizeof(short), 1, fp);
       if (nDataEndian == BIG_ENDIAN)
      SwapWord((char *) &eTag, 1);

   if ((eTag == 0x0005) || (eTag == 0x0008))
    bGroup2Done = TRUE;
   break;

       case 0x0028: // Image pixel data info group
         fread(&eTag, sizeof(short), 1, fp);

   if (bGroup28Done)
      break;

       if (nDataEndian == BIG_ENDIAN)
      SwapWord((char *) &eTag, 1);

         switch(eTag)
          {
            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 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 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);
    bGroup28Done = TRUE;
    break;

   default:
    // do nothing
    break;
           }
         break;
        case 0x7fe0:
         fread(&eTag, sizeof(short), 1, fp);
   if (bPixelDataDone)
    break;

       if (nDataEndian == BIG_ENDIAN)
      SwapWord((char *) &eTag, 1);

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

    // Don't try to parse grup 2 and group 28 any more
    bGroup2Done = TRUE;
    bGroup28Done = TRUE;

    // Parse pixel data
    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.");
     }
     bPixelDataDone = TRUE;
     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.");

  }

}

版权声明:本文为博主原创文章,未经博主允许不得转载。

Matlab下DICOM文件根据窗位、窗宽的显示和BMP格式的保存

一、DICOM简介 DICOM即数字影像和通信标准。在医学影像信息学的发展和PACS的研究过程中,由于医疗设备生产厂商的不同,造成与各种设备有关的医学图像存储格式、传输方式千差万别,使得医学影像及其相...
  • ymqq1
  • ymqq1
  • 2013年04月07日 00:50
  • 5671

DCMTK开源库的学习笔记1:将DCM文件保存成BMP文件或数据流(即数组)

背景介绍: DCMTK是目前最全面实现DICOM3.0标准的开源库,通过结合DCMTK开源库和CxImage图像开源库,能够很方便的开发属于自己的DCM文件编辑浏览软件。 在此利用DCMTK与CxIm...
  • zssureqh
  • zssureqh
  • 2013年04月10日 20:47
  • 11608

DICOM医学图像处理:WEB PACS初谈二,图像的传输

背景: 如前一篇专栏博文所述,借助于CGI或FastCGI技术转发浏览器发送过来的用户请求,启动本地的DCMTK和CxImage库响应,然后将处理结果转换成常规图像返回到浏览器来实现Web PACS。...
  • zssureqh
  • zssureqh
  • 2014年10月27日 22:22
  • 8812

利用靶区勾画的RT struct文件分析相关联的Dicom图像中肿瘤部分的CT(HU)值分布(升级版)

利用靶区勾画的RT struct文件分析相关联的Dicom图像中肿瘤部分的CT(HU)值分布(升级版) % =========================================...
  • wangxiao7474
  • wangxiao7474
  • 2017年12月13日 11:17
  • 197

DICOM医学图像处理:DICOM存储操作之“多幅BMP图像数据存入DCM文件”

背景:         本专栏“DICOM医学图像处理”受众较窄,起初只想作为自己学习积累和工作经验的简单整理。前几天无聊浏览了一下,发现阅读量两极化严重,主要集中在“关于BMP(JPG)与DC...
  • qq_26499769
  • qq_26499769
  • 2016年07月23日 13:02
  • 460

DICOM医学图像处理:DICOM存储操作之“多幅BMP图像数据存入DCM文件”

背景: 本专栏“DICOM医学图像处理”受众较窄,起初只想作为自己学习积累和工作经验的简单整理。前几天无聊浏览了一下,发现阅读量两极化严重,主要集中在“关于BMP(JPG)与DCM格式转换”和“DI...
  • zssureqh
  • zssureqh
  • 2014年12月24日 08:28
  • 13690

dicom文件批量另存为bmp jpg png ,支持多选,拖放,目录(含或不含子目录)

  • 2009年07月08日 17:02
  • 2.02MB
  • 下载

dicom文件与bmp和jpg文件的相互转化

前面工作需要,将dicom医学文件转化为普通图像,如bmp,jpg等,中间应用到了CxImage_x64和dcmtk包。实现过程中,遇到了不少麻烦,现将相关过程分享如下,希望能给需要的人提供参考,以及...
  • Streamzhangjun
  • Streamzhangjun
  • 2017年04月09日 19:26
  • 205

从DICOM开始入门医学图像处理-3-DICOMDIR文件解析

前言 上一篇文章给出了VTK+V+QT的安装方法,其余的两个库,也就是ITK和DCMTK的安装很简单,有一定的CMake使用经验就能很容易的成功编译出我们需要的库.这篇文章主要讲DICOM文件档案的...
  • Angle_Cal
  • Angle_Cal
  • 2017年11月21日 17:24
  • 268

android 解析并显示dicom文件的数据和图像

android解析并显示dicom文件的数据和图像Dicom全称是医学数字图像与通讯,这里android程序代码解析diocm格式文件并显示dicom的图片和数据。 这里解析dicom使用的是dcm...
  • wenzhi20102321
  • wenzhi20102321
  • 2017年07月12日 19:31
  • 1451
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:把DICOM文件中的图像部分提取到BMP文件的函数
举报原因:
原因补充:

(最多只允许输入30个字)