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

📄 gdcmdocument.cxx

📁 DTMK软件开发包,此为开源软件,是一款很好的医学图像开发资源.
💻 CXX
📖 第 1 页 / 共 5 页
字号:
/*=========================================================================
                                                                                
  Program:   gdcm
  Module:    $RCSfile: gdcmDocument.cxx,v $
  Language:  C++
  Date:      $Date: 2008-05-14 12:25:32 $
  Version:   $Revision: 1.29 $
                                                                                
  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.
                                                                                
=========================================================================*/

#include "gdcmDocument.h"
#include "gdcmValEntry.h"
#include "gdcmBinEntry.h"
#include "gdcmSeqEntry.h"
#include "gdcmGlobal.h"
#include "gdcmUtil.h"
#include "gdcmDebug.h"
#include "gdcmTS.h"
#include "gdcmDictSet.h"
#include "gdcmDocEntrySet.h"
#include "gdcmSQItem.h"

#include <vector>
#include <iomanip>
#include <fstream>
#include <ctype.h>  // for isdigit
#include <stdlib.h> // for atoi

#if defined(__BORLANDC__)
   #include <mem.h> // for memset
#endif 

namespace gdcm 
{
//-----------------------------------------------------------------------------

// Refer to Document::SetMaxSizeLoadEntry()
const unsigned int Document::MAX_SIZE_LOAD_ELEMENT_VALUE = 0xfff; // 4096

//-----------------------------------------------------------------------------
// Constructor / Destructor
// Constructors and destructors are protected to avoid user to invoke directly

/**
 * \brief This default constructor neither loads nor parses the file. 
 *        You should then invoke \ref Document::Load.
 *         
 */
Document::Document() 
         :ElementSet(-1)
{
   Fp = 0;

   SetMaxSizeLoadEntry(MAX_SIZE_LOAD_ELEMENT_VALUE);
   Initialize();
   SwapCode = 1234;
   Filetype = ExplicitVR;
   // Load will set it to true if sucessfull
   Group0002Parsed = false;
   IsDocumentAlreadyLoaded = false;
   IsDocumentModified = true;
   LoadMode = LD_ALL; // default : load everything, later
   SetFileName("");
}

#ifndef GDCM_LEGACY_REMOVE
/**
 * \brief   Constructor (DEPRECATED : not to break the API) 
 * @param   fileName 'Document' (File or DicomDir) to be open for parsing
 */
Document::Document( std::string const &fileName )
         :ElementSet(-1) 
{
   Fp = 0;

   SetMaxSizeLoadEntry(MAX_SIZE_LOAD_ELEMENT_VALUE);
   Initialize();
   SwapCode = 1234;
   Filetype = ExplicitVR;
   Group0002Parsed = false;
   LoadMode = LD_ALL; // Load everything, later

   // Load will set it to true if sucessfull
   IsDocumentAlreadyLoaded = false;
   IsDocumentModified = true;

   SetFileName(fileName);
   Load( );
}
#endif
/**
 * \brief   Canonical destructor.
 */
Document::~Document ()
{
   CloseFile();
}

//-----------------------------------------------------------------------------
// Public
/**
 * \brief   Loader. use SetLoadMode(), SetFileName() before ! 
 * @return false if file cannot be open or no swap info was found,
 *         or no tag was found.
 */
bool Document::Load(  ) 
{
   if ( GetFileName() == "" )
   {
      gdcmWarningMacro( "Use SetFileName, before !" );
      return false;
   }
   return DoTheLoadingDocumentJob( );
} 

#ifndef GDCM_LEGACY_REMOVE
/**
 * \brief   Loader. (DEPRECATED : not to break the API)   
 * @param   fileName 'Document' (File or DicomDir) to be open for parsing
 * @return false if file cannot be open or no swap info was found,
 *         or no tag was found.
 */
bool Document::Load( std::string const &fileName ) 
{
   Filename = fileName;
   return DoTheLoadingDocumentJob( );
}
#endif

/**
 * \brief   Performs 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 Document::DoTheLoadingDocumentJob(  ) 
{
   if ( ! IsDocumentModified ) // Nothing to do !
      return true;

   ClearEntry();

   Fp = 0;
   if ( !OpenFile() )
   {
      // warning already performed in OpenFile()
      Filetype = Unknown;
      return false;
   }

   Group0002Parsed = false;

   gdcmDebugMacro( "Starting parsing of file: " << Filename.c_str());

   // Computes the total length of the file
   Fp->seekg(0, std::ios::end);  // Once per Document !
   long lgt = Fp->tellg();       // Once per Document !   
   Fp->seekg(0, std::ios::beg);  // Once per Document !

   // CheckSwap returns a boolean 
   // (false if no swap info of any kind was found)
   if (! CheckSwap() )
   {
      gdcmWarningMacro( "Neither a DICOM V3 nor an ACR-NEMA file: " 
                   << Filename.c_str());
      CloseFile(); 
      return false;      
    }

   long beg = Fp->tellg();      // just after DICOM preamble (if any)

   lgt -= beg;                  // remaining length to parse    

   // Recursive call.
   // Loading is done during parsing
   ParseDES( this, beg, lgt, false); // delim_mode is first defaulted to false

   if ( IsEmpty() )
   { 
      gdcmErrorMacro( "No tag in internal hash table for: "
                        << Filename.c_str());
      CloseFile(); 
      return false;
   }
   IsDocumentAlreadyLoaded = true;

   //Fp->seekg(0, std::ios::beg);  // Once per Document!
   
   // Load 'non string' values
      
   std::string PhotometricInterpretation = GetEntryValue(0x0028,0x0004);   
   if ( PhotometricInterpretation == "PALETTE COLOR " )
   {
   // FIXME
   // Probabely this line should be outside the 'if'
   // Try to find an image sample holding a 'gray LUT'
      LoadEntryBinArea(0x0028,0x1200);  // gray LUT
   
      /// FIXME
      /// The tags refered by the three following lines used to be CORRECTLY
      /// defined as having an US Value Representation in the public
      /// dictionary. BUT the semantics implied by the three following
      /// lines state that the corresponding tag contents are in fact
      /// the ones of a BinEntry.
      /// In order to fix things "Quick and Dirty" the dictionary was
      /// altered on PURPOSE but now contains a WRONG value.
      /// In order to fix things and restore the dictionary to its
      /// correct value, one needs to decide of the semantics by deciding
      /// whether the following tags are either :
      /// - multivaluated US, and hence loaded as ValEntry, but afterwards
      ///   also used as BinEntry, which requires the proper conversion,
      /// - OW, and hence loaded as BinEntry, but afterwards also used
      ///   as ValEntry, which requires the proper conversion.
      // --> OB (byte aray) or OW (short int aray)
      // The actual VR has to be deduced from other entries.
      // Our way of loading them may fail in some cases :
      // We must or not SwapByte depending on other field values.
             
      LoadEntryBinArea(0x0028,0x1201);  // R    LUT
      LoadEntryBinArea(0x0028,0x1202);  // G    LUT
      LoadEntryBinArea(0x0028,0x1203);  // B    LUT
      
      // Segmented Red   Palette Color LUT Data
      LoadEntryBinArea(0x0028,0x1221);
      // Segmented Green Palette Color LUT Data
      LoadEntryBinArea(0x0028,0x1222);
      // Segmented Blue  Palette Color LUT Data
      LoadEntryBinArea(0x0028,0x1223);
   }
 
   //FIXME later : how to use it?
   SeqEntry *modLutSeq = GetSeqEntry(0x0028,0x3000); // Modality LUT Sequence
   if ( modLutSeq !=0 )
   {
      SQItem *sqi= modLutSeq->GetFirstSQItem();
      if ( sqi != 0 )
      {
         BinEntry *b = sqi->GetBinEntry(0x0028,0x3006);
         if ( b != 0 )
         {
            if ( b->GetLength() != 0 )
            {
               // FIXME : CTX dependent means : contexted dependant.
               //         see upper comment.
               LoadEntryBinArea(b);    //LUT Data (CTX dependent)
            }   
        }
     }      
   }

   // Force Loading some more elements if user asked to.

   gdcm::DocEntry *d;
   for (ListElements::iterator it = UserForceLoadList.begin();  
                               it != UserForceLoadList.end();
                             ++it)
   {
      gdcmDebugMacro( "Force Load " << std::hex 
                       << (*it).Group << "|" <<(*it).Elem );
  
      d = GetDocEntry( (*it).Group, (*it).Elem);
  
      if ( d == NULL)
      {
         gdcmWarningMacro( "You asked to ForceLoad "  << std::hex
                          << (*it).Group <<"|"<< (*it).Elem
                          << " that doesn't exist" );
         continue;
      }

      if ( dynamic_cast<ValEntry *>(d) )
      {
         LoadDocEntry(d, true);
         continue;
      }

      BinEntry *b = dynamic_cast<BinEntry *>(d);
      if ( b )
      {
         LoadEntryBinArea(b);
         b->SetValue(GDCM_BINLOADED);
         continue;
      }
 
      if ( dynamic_cast<SeqEntry *>(d) )
      {
         gdcmWarningMacro( "You cannot 'ForceLoad' a SeqEntry :" << std::hex
                           << (*it).Group <<"|"<< (*it).Elem );
         continue;
      }
   }

   CloseFile(); 
  
   // ----------------------------
   // Specific code to allow gdcm to read ACR-LibIDO formated images
   // Note: ACR-LibIDO is an extension of the ACR standard that was
   //       used at CREATIS. For the time being (say a couple of years)
   //       we keep this kludge to allow CREATIS users 
   //       reading their old images.
   //
   // if recognition code tells us we deal with a LibIDO image
   // we switch lineNumber and columnNumber
   //
   std::string RecCode;
   RecCode = GetEntryValue(0x0008, 0x0010); // recognition code (RET)
   if (RecCode == "ACRNEMA_LIBIDO_1.1" ||
       RecCode == "ACRNEMA_LIBIDO_1.0" ||
       RecCode == "CANRME_AILIBOD1_0." ||
       RecCode == "CANRME_AILIBOD1_1." )  // for brain-damaged softwares
                                          // with "little-endian strings"
   {
         Filetype = ACR_LIBIDO; 
         std::string rows    = GetEntryValue(0x0028, 0x0010);
         std::string columns = GetEntryValue(0x0028, 0x0011);
         SetValEntry(columns, 0x0028, 0x0010);
         SetValEntry(rows   , 0x0028, 0x0011);
   }
   // --- End of ACR-LibIDO kludge --- 
   return true;
}


/**
 * \brief Adds a new element we want to load anyway
 * @param   group  Group number of the target tag.
 * @param   elem Element number of the target tag.
 */
void Document::AddForceLoadElement (uint16_t group, uint16_t elem) 
{ 
   Element el;
   el.Group = group;
   el.Elem  = elem;
   UserForceLoadList.push_back(el); 
}
/**
 * \brief   Get the public dictionary used
 */
Dict *Document::GetPubDict()
{
   return RefPubDict;
}

/**
 * \brief   Get the shadow dictionary used
 */
Dict *Document::GetShaDict()
{
   return RefShaDict;
}

/**
 * \brief   Set the shadow dictionary used
 * @param   dict dictionary to use in shadow
 */
bool Document::SetShaDict(Dict *dict)
{
   RefShaDict = dict;
   return !RefShaDict;
}

/**
 * \brief   Set the shadow dictionary used
 * @param   dictName name of the dictionary to use in shadow
 */
bool Document::SetShaDict(DictKey const &dictName)
{
   RefShaDict = Global::GetDicts()->GetDict(dictName);
   return !RefShaDict;
}

/**
 * \brief  This predicate tells us whether or not the current Document 
 *         was properly parsed and contains at least *one* Dicom Element
 *         (and nothing more, sorry).
 * @return false when we're 150 % sure it's NOT a Dicom/Acr file,
 *         true otherwise. 
 */
bool Document::IsParsable()
{
   if ( Filetype == Unknown )
   {
      gdcmWarningMacro( "Wrong filetype for " << GetFileName());
      return false;
   }

   if ( IsEmpty() )
   { 
      gdcmWarningMacro( "No tag in internal hash table.");
      return false;
   }

   return true;
}
/**
 * \brief  This predicate tells us whether or not the current Document 
 *         was properly parsed and contains at least *one* Dicom Element
 *         (and nothing more, sorry).
 * @return false when we're 150 % sure it's NOT a Dicom/Acr file,
 *         true otherwise. 
 */
bool Document::IsReadable()
{

⌨️ 快捷键说明

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