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

📄 gdcmfile.cxx

📁 DTMK软件开发包,此为开源软件,是一款很好的医学图像开发资源.
💻 CXX
📖 第 1 页 / 共 5 页
字号:
/*=========================================================================
                                                                                
  Program:   gdcm
  Module:    $RCSfile: gdcmFile.cxx,v $
  Language:  C++
  Date:      $Date: 2008-05-14 12:25:32 $
  Version:   $Revision: 1.24 $
                                                                                
  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
  l'Image). All rights reserved. See Doc/License.txt or
  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
                                                                                
     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.
                                                                                
=========================================================================*/

#if defined(__BORLANDC__)
#pragma warn -8004 /* assigned a value that is never used */
#endif

//
// --------------  Remember ! ----------------------------------
//
// Image Position (Patient)                            (0020,0032):
// If not found (ACR_NEMA) we try Image Position       (0020,0030)
// If not found (ACR-NEMA), we consider Slice Location (0020,1041)
//                                   or Location       (0020,0050) 
//                                   as the Z coordinate, 
// 0. for all the coordinates if nothing is found
//
// Image Position (Patient) (0020,0032) VM=3
// -->
//  The attribute Patient Orientation (0020,0020) from the General Image Module 
// is of type 2C and has the condition Required if image does not require 
// Image Orientation (0020,0037) and Image Position (0020,0032). 
// However, if the image does require the attributes 
// - Image Orientation (Patient) (0020,0037), VM=6
// - Image Position (Patient)    (0020,0032), VM=3
// then attribute Patient Orientation (0020,0020) should not be present
//  in the images.
//
// Remember also :
// Patient Position (0018,5100) values :

//  HFS   = Head First-Supine, where increasing (positive axis direction) :
//     X -> to the direction pointed to by the patient's oustretched left arm
//     Y -> to the anterior-to-posterior direction in the patient's body
//     Z -> to the feet-to-head direction in the patient's body

//  HFP   = Head First-Prone, where increasing (positive axis direction) :
//     X -> to the direction pointed to by the patient's oustretched left arm
//     Y -> to the anterior-to-posterior direction in the patient's body
//     Z -> to the feet-to-head direction in the patient's body

//  FFS  = Feet First-Supine, where increasing (positive axis direction) :
//     X -> to the direction pointed to by the patient's oustretched left arm
//     Y -> to the anterior-to-posterion direction in the patient's body
//     Z -> to the feet-to-head direction in the patient's body

//  FFP  = Feet First-Prone, where increasing (positive axis direction) :
//     X -> to the direction pointed to by the patient's oustretched left arm
//     Y -> to the posterior-to-anterior direction in the patient's body
//     Z -> to the feet-to-head direction in the patient's body

// HFDR = Head First-Decubitus Right
// HFDL = Head First-Decubitus Left
// FFDR = Feet First-Decubitus Right
// FFDL = Feet First-Decubitus Left

//  we can also find (non standard!)     

// SEMIERECT
// SUPINE

// CS 2 Patient Orientation (0020 0020)
//    When the coordinates of the image 
//    are always present, this field is almost never used.
//    Better we don't trust it too much ...
//    Found Values are :
//     L\P
//     L\FP
//     P\F
//     L\F
//     P\FR
//     R\F
//
// (0020|0037) [Image Orientation (Patient)] [1\0\0\0\1\0 ]

               
// ---------------------------------------------------------------
//
#include "gdcmFile.h"
#include "gdcmGlobal.h"
#include "gdcmUtil.h"
#include "gdcmDebug.h"
#include "gdcmTS.h"
#include "gdcmValEntry.h"
#include "gdcmBinEntry.h"
#include "gdcmSeqEntry.h"
#include "gdcmRLEFramesInfo.h"
#include "gdcmJPEGFragmentsInfo.h"
#include "gdcmSQItem.h"

#include <vector>
#include <stdio.h>  //sscanf
#include <stdlib.h> // for atoi

namespace gdcm 
{

//-----------------------------------------------------------------------------
// Constructor / Destructor

/**
 * \brief Constructor used when we want to generate dicom files from scratch
 */
File::File():
   Document()
{
   RLEInfo  = new RLEFramesInfo;
   JPEGInfo = new JPEGFragmentsInfo;
   GrPixel  = 0x7fe0;  // to avoid further troubles
   NumPixel = 0x0010;
   BasicOffsetTableItemValue = 0;
}


/**
 * \brief   Canonical destructor.
 */
File::~File()
{
   if ( RLEInfo )
      delete RLEInfo;
   if ( JPEGInfo )
      delete JPEGInfo;
   delete[] BasicOffsetTableItemValue;
}

//-----------------------------------------------------------------------------
// Public
/**
 * \brief   Loader  
 * @return false if file cannot be open or no swap info was found,
 *         or no tag was found.
 */
bool File::Load( ) 
{
   if ( ! this->Document::Load( ) )
      return false;

    return DoTheLoadingJob( );   
}

/**
 * \brief   Does the Loading Job (internal use only)
 * @return false if file cannot be open or no swap info was found,
 *         or no tag was found.
 */
bool File::DoTheLoadingJob( ) 
{
   // for some ACR-NEMA images GrPixel, NumPixel is *not* 7fe0,0010
   // We may encounter the 'RETired' (0x0028, 0x0200) tag
   // (Image Location") . This entry contains the number of
   // the group that contains the pixel data (hence the "Pixel Data"
   // is found by indirection through the "Image Location").
   // Inside the group pointed by "Image Location" the searched element
   // is conventionally the element 0x0010 (when the norm is respected).
   // When the "Image Location" is missing we default to group 0x7fe0.
   // Note: this IS the right place for the code
 
   // Image Location
   const std::string &imgLocation = GetEntryValue(0x0028, 0x0200);
   if ( imgLocation == GDCM_UNFOUND || imgLocation == GDCM_BINLOADED )
   {
      // default value
      GrPixel = 0x7fe0;
   }
   else
   {
      GrPixel = (uint16_t) atoi( imgLocation.c_str() );
   }   

   // sometimes Image Location value doesn't follow
   // the supposed processor endianness.
   // see gdcmData/cr172241.dcm
   if ( GrPixel == 0xe07f )
   {
      GrPixel = 0x7fe0;
   }

   if ( GrPixel != 0x7fe0 )
   {
      // This is a kludge for old dirty Philips imager.
      NumPixel = 0x1010;
   }
   else
   {
      NumPixel = 0x0010;
   }

   // Now, we know GrPixel and NumPixel.
   // Let's create a VirtualDictEntry to allow a further VR modification
   // and force VR to match with BitsAllocated.
   DocEntry *entry = GetDocEntry(GrPixel, NumPixel); 
   if ( entry != 0 )
   {
      // Compute the RLE or JPEG info
      OpenFile();
      const std::string &ts = GetTransferSyntax();
      Fp->seekg( entry->GetOffset(), std::ios::beg );
      if ( Global::GetTS()->IsRLELossless(ts) ) 
         ComputeRLEInfo();
      else if ( Global::GetTS()->IsJPEG(ts) )
         ComputeJPEGFragmentInfo();
      CloseFile();

      // Create a new BinEntry to change the DictEntry
      // The changed DictEntry will have 
      // - a correct PixelVR OB or OW)
      // - the name to "Pixel Data"
      BinEntry *oldEntry = dynamic_cast<BinEntry *>(entry);
      if (oldEntry)
      {
         std::string PixelVR;
         // 8 bits allocated is a 'O Bytes' , as well as 24 (old ACR-NEMA RGB)
         // more than 8 (i.e 12, 16) is a 'O Words'
         if ( GetBitsAllocated() == 8 || GetBitsAllocated() == 24 ) 
            PixelVR = "OB";
         else
            PixelVR = "OW";

         // Change only made if usefull
         if ( PixelVR != oldEntry->GetVR() )
         {
            DictEntry* newDict = NewVirtualDictEntry(GrPixel,NumPixel,
                                                     PixelVR,"1","Pixel Data");

            BinEntry *newEntry = new BinEntry(newDict);
            newEntry->Copy(entry);
            newEntry->SetBinArea(oldEntry->GetBinArea(),oldEntry->IsSelfArea());
            oldEntry->SetSelfArea(false);

            RemoveEntry(oldEntry);
            AddEntry(newEntry);
         }
      }
   }
   return true;
}
/**
 * \brief  This predicate, based on hopefully reasonable heuristics,
 *         decides whether or not the current File was properly parsed
 *         and contains the mandatory information for being considered as
 *         a well formed and usable Dicom/Acr File.
 * @return true when File is the one of a reasonable Dicom/Acr file,
 *         false otherwise. 
 */
bool File::IsReadable()
{
   if ( !Document::IsReadable() )
   {
      return false;
   }

   const std::string &res = GetEntryValue(0x0028, 0x0005);
   if ( res != GDCM_UNFOUND && atoi(res.c_str()) > 4 )
   {
      gdcmWarningMacro("Wrong Image Dimensions" << res);
      return false; // Image Dimensions
   }
   bool b0028_0100 = true;
   if ( !GetDocEntry(0x0028, 0x0100) )
   {
      gdcmWarningMacro("Bits Allocated (0028|0100) not found"); 
      //return false; // "Bits Allocated"
      b0028_0100 = false;
   }
   bool b0028_0101 = true;
   if ( !GetDocEntry(0x0028, 0x0101) )
   {
      gdcmWarningMacro("Bits Stored (0028|0101) not found");
      //return false; // "Bits Stored"
      b0028_0101 = false;
   }
   bool b0028_0102 = true;
   if ( !GetDocEntry(0x0028, 0x0102) )
   {
      gdcmWarningMacro("Hight Bit (0028|0102) not found"); 
      //return false; // "High Bit"
      b0028_0102 = false;
   }
   bool b0028_0103 = true;
   if ( !GetDocEntry(0x0028, 0x0103) )
   {
      gdcmWarningMacro("Pixel Representation (0028|0103) not found");
      //return false; // "Pixel Representation" i.e. 'Sign' ( 0 : unsigned, 1 : signed)
      b0028_0103 = false;
   }

   if ( !b0028_0100 && !b0028_0101 && !b0028_0102 && !b0028_0103)
   {
      gdcmWarningMacro("Too much mandatory Tags missing !");
      return false;
   }

   if ( !GetDocEntry(GrPixel, NumPixel) )
   {
      gdcmWarningMacro("Pixel Dicom Element " << std::hex <<
                        GrPixel << "|" << NumPixel << "not found");
      return false; // Pixel Dicom Element not found :-(
   }
   return true;
}

/**
 * \brief gets the info from 0020,0013 : Image Number else 0.
 * @return image number
 */
int File::GetImageNumber()
{
   //0020 0013 : Image Number
   std::string strImNumber = GetEntryValue(0x0020,0x0013);
   if ( strImNumber != GDCM_UNFOUND )
   {
      return atoi( strImNumber.c_str() );
   }
   return 0;   //Hopeless
}

/**
 * \brief gets the info from 0008,0060 : Modality
 * @return Modality Type
 */
ModalityType File::GetModality()
{
   // 0008 0060 : Modality
   std::string strModality = GetEntryValue(0x0008,0x0060);
   if ( strModality != GDCM_UNFOUND )
   {
           if ( strModality.find("AU")  < strModality.length()) return AU;
      else if ( strModality.find("AS")  < strModality.length()) return AS;
      else if ( strModality.find("BI")  < strModality.length()) return BI;
      else if ( strModality.find("CF")  < strModality.length()) return CF;
      else if ( strModality.find("CP")  < strModality.length()) return CP;
      else if ( strModality.find("CR")  < strModality.length()) return CR;
      else if ( strModality.find("CT")  < strModality.length()) return CT;
      else if ( strModality.find("CS")  < strModality.length()) return CS;
      else if ( strModality.find("DD")  < strModality.length()) return DD;
      else if ( strModality.find("DF")  < strModality.length()) return DF;
      else if ( strModality.find("DG")  < strModality.length()) return DG;
      else if ( strModality.find("DM")  < strModality.length()) return DM;
      else if ( strModality.find("DS")  < strModality.length()) return DS;
      else if ( strModality.find("DX")  < strModality.length()) return DX;
      else if ( strModality.find("ECG") < strModality.length()) return ECG;
      else if ( strModality.find("EPS") < strModality.length()) return EPS;
      else if ( strModality.find("FA")  < strModality.length()) return FA;
      else if ( strModality.find("FS")  < strModality.length()) return FS;
      else if ( strModality.find("HC")  < strModality.length()) return HC;
      else if ( strModality.find("HD")  < strModality.length()) return HD;
      else if ( strModality.find("LP")  < strModality.length()) return LP;
      else if ( strModality.find("LS")  < strModality.length()) return LS;
      else if ( strModality.find("MA")  < strModality.length()) return MA;
      else if ( strModality.find("MR")  < strModality.length()) return MR;
      else if ( strModality.find("NM")  < strModality.length()) return NM;
      else if ( strModality.find("OT")  < strModality.length()) return OT;
      else if ( strModality.find("PT")  < strModality.length()) return PT;
      else if ( strModality.find("RF")  < strModality.length()) return RF;
      else if ( strModality.find("RG")  < strModality.length()) return RG;
      else if ( strModality.find("RTDOSE")   
                                        < strModality.length()) return RTDOSE;
      else if ( strModality.find("RTIMAGE")  
                                        < strModality.length()) return RTIMAGE;
      else if ( strModality.find("RTPLAN")
                                        < strModality.length()) return RTPLAN;
      else if ( strModality.find("RTSTRUCT") 
                                        < strModality.length()) return RTSTRUCT;
      else if ( strModality.find("SM")  < strModality.length()) return SM;
      else if ( strModality.find("ST")  < strModality.length()) return ST;
      else if ( strModality.find("TG")  < strModality.length()) return TG;
      else if ( strModality.find("US")  < strModality.length()) return US;
      else if ( strModality.find("VF")  < strModality.length()) return VF;
      else if ( strModality.find("XA")  < strModality.length()) return XA;
      else if ( strModality.find("XC")  < strModality.length()) return XC;

      else
      {
         /// \todo throw error return value ???
         /// specified <> unknown in our database
         return Unknow;
      }
   }
   return Unknow;

⌨️ 快捷键说明

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