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

📄 gdcmdocument.cxx

📁 DTMK软件开发包,此为开源软件,是一款很好的医学图像开发资源.
💻 CXX
📖 第 1 页 / 共 5 页
字号:
   }
   else if ( s1 > s2 )
   {
      return false;
   }
   else
   {
      // Patient ID
      s1 = GetEntryValue(0x0010,0x0020);
      s2 = document.GetEntryValue(0x0010,0x0020);
      if ( s1 < s2 )
      {
         return true;
      }
      else if ( s1 > s2 )
      {
         return false;
      }
      else
      {
         // Study Instance UID
         s1 = GetEntryValue(0x0020,0x000d);
         s2 = document.GetEntryValue(0x0020,0x000d);
         if ( s1 < s2 )
         {
            return true;
         }
         else if ( s1 > s2 )
         {
            return false;
         }
         else
         {
            // Serie Instance UID
            s1 = GetEntryValue(0x0020,0x000e);
            s2 = document.GetEntryValue(0x0020,0x000e);    
            if ( s1 < s2 )
            {
               return true;
            }
            else if ( s1 > s2 )
            {
               return false;
            }
         }
      }
   }
   return false;
}

//-----------------------------------------------------------------------------
// Protected
/**
 * \brief Reads a supposed to be 16 Bits integer
 *       (swaps it depending on processor endianness) 
 * @return read value
 */
uint16_t Document::ReadInt16()
   throw( FormatError )
{
   uint16_t g;
   Fp->read ((char*)&g, (size_t)2);
   if ( Fp->fail() )
   {
      throw FormatError( "Document::ReadInt16()", " file error." );
   }
   if ( Fp->eof() )
   {
      throw FormatError( "Document::ReadInt16()", "EOF." );
   }
   g = SwapShort(g); 
   return g;
}

/**
 * \brief  Reads a supposed to be 32 Bits integer
 *        (swaps it depending on processor endianness)  
 * @return read value
 */
uint32_t Document::ReadInt32()
   throw( FormatError )
{
   uint32_t g;
   Fp->read ((char*)&g, (size_t)4);
   if ( Fp->fail() )
   {
      throw FormatError( "Document::ReadInt32()", " file error." );
   }
   if ( Fp->eof() )
   {
      throw FormatError( "Document::ReadInt32()", "EOF." );
   }
   g = SwapLong(g);
   return g;
}

/**
 * \brief skips bytes inside the source file 
 * \warning NOT end user intended method !
 * @return 
 */
void Document::SkipBytes(uint32_t nBytes)
{
   //FIXME don't dump the returned value
   Fp->seekg((long)nBytes, std::ios::cur);
}

/**
 * \brief   Re-computes the length of a ACR-NEMA/Dicom group from a DcmHeader
 */
int Document::ComputeGroup0002Length( /*FileType filetype*/ ) 
{
   uint16_t gr;
   std::string vr;
   
   int groupLength = 0;
   bool found0002 = false;   
  
   // for each zero-level Tag in the DCM Header
   DocEntry *entry = GetFirstEntry();
   while( entry )
   {
      gr = entry->GetGroup();

      if ( gr == 0x0002 )
      {
         found0002 = true;

         if ( entry->GetElement() != 0x0000 )
         {
            vr = entry->GetVR();

            //if ( (vr == "OB")||(vr == "OW")||(vr == "UT")||(vr == "SQ"))
            // (no SQ, OW, UT in group 0x0002;)
               if ( vr == "OB" ) 
               {
                  // explicit VR AND (OB, OW, SQ, UT) : 4 more bytes
                  groupLength +=  4;
               }
            groupLength += 2 + 2 + 4 + entry->GetLength();   
         }
      }
      else if (found0002 )
         break;

      entry = GetNextEntry();
   }
   return groupLength; 
}

//-----------------------------------------------------------------------------
// Private
/**
 * \brief Loads all the needed Dictionaries
 * \warning NOT end user intended method !
 */
void Document::Initialize() 
{
   RefPubDict = Global::GetDicts()->GetDefaultPubDict();
   RefShaDict = NULL;
   Filetype   = Unknown;
}

/**
 * \brief   Parses a DocEntrySet (Zero-level DocEntries or SQ Item DocEntries)
 * @param set DocEntrySet we are going to parse ('zero level' or a SQItem)
 * @param offset start of parsing
 * @param l_max  length to parse (meaningless when we are in 'delimitor mode')
 * @param delim_mode : whether we are in 'delimitor mode' (l=0xffffff) or not
 */ 
void Document::ParseDES(DocEntrySet *set, long offset, 
                        long l_max, bool delim_mode)
{
   DocEntry *newDocEntry;
   ValEntry *newValEntry;
   BinEntry *newBinEntry;
   SeqEntry *newSeqEntry;
   VRKey vr;
   bool used; // will be set to false when something wrong happens to an Entry.
              // (Entry will then be deleted)
   bool delim_mode_intern = delim_mode;
   bool first = true;
   gdcmDebugMacro( "Enter in ParseDES, delim-mode " <<  delim_mode
                     << " at offset " << std::hex << "0x(" << offset << ")" ); 
   while (true)
   {
      if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max)
      {
         break;
      }

      newDocEntry = ReadNextDocEntry( );

      // FIXME :
      // Private tag, in IMplicit VR are defaulted as a BinEntry,
      // Very often they are only composed of Printable characters, 
      // and could be defaulted as a ValEntry.
      // It's too late to do the Job
      // (we should check the value, but we know it after LoadDocEntry ...)
      // --> in next gdcm major release let's unify ValEntry and BinEntry !

      // Uncoment this printf line to be able to 'follow' the DocEntries
      // when something *very* strange happens

      if ( !newDocEntry )
      {
         break;
      }

       // an Item Starter found elsewhere but the first position
       // of a SeqEntry means previous entry was a Sequence
       // but we didn't get it (private Sequence + Implicit VR)
       // we have to backtrack.
      if ( !first && newDocEntry->IsItemStarter() )
      {
         // Debug message within the method !
         newDocEntry = Backtrack(newDocEntry);
      }
      else
      {
         PreviousDocEntry = newDocEntry;
      }

      used = true;
      newValEntry = dynamic_cast<ValEntry*>(newDocEntry);
      newBinEntry = dynamic_cast<BinEntry*>(newDocEntry);

      if ( newValEntry || newBinEntry )
      {
       //////////////////////////// ContentEntry
         if ( newBinEntry )
         {
            vr = newDocEntry->GetVR();
            if ( Filetype == ExplicitVR &&
                 !Global::GetVR()->IsVROfBinaryRepresentable(vr) )
            {
                ////// Neither ValEntry NOR BinEntry: should mean UNKOWN VR
                gdcmWarningMacro( std::hex << newDocEntry->GetGroup() 
                                  << "|" << newDocEntry->GetElement()
                                  << " : Neither Valentry, nor BinEntry." 
                                  "Probably unknown VR.");
            }

         //////////////////// BinEntry or UNKOWN VR:

            // When "this" is a Document the Key is simply of the
            // form ( group, elem )...
            //if ( set == this ) // ( dynamic_cast< Document* > ( set ) )
            //{
            //   newBinEntry->SetKey( newBinEntry->GetKey() );
            //}
            // but when "this" is a SQItem, we are inserting this new
            // valEntry in a sequence item, and the key has the
            // generalized form (refer to \ref BaseTagKey):

            // time waste hunting
            //if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) )
            //{
            //   newBinEntry->SetKey(  parentSQItem->GetBaseTagKey()
            //                       + newBinEntry->GetKey() );
            //}

            if ( !set->AddEntry( newBinEntry ) )
            {
               gdcmWarningMacro( "in ParseDES : cannot add a BinEntry "
                                   << newBinEntry->GetKey()
                                   << " (at offset : "
                                   << newBinEntry->GetOffset() << " )" );
               used=false;
            }
            else
            {
               // Load only if we can add (not a duplicate key)
               LoadDocEntry( newBinEntry );
            }
         }  // end BinEntry
         else
         {
         /////////////////////// ValEntry

            // When "set" is a Document, then we are at the top of the
            // hierarchy and the Key is simply of the form ( group, elem )...
            //if ( set == this ) // ( dynamic_cast< Document* > ( set ) )
            //{
            //   newValEntry->SetKey( newValEntry->GetKey() );
            //}
            // ...but when "set" is a SQItem, we are inserting this new
            // valEntry in a sequence item. Hence the key has the
            // generalized form (refer to \ref BaseTagKey):

            // time waste hunting
            //if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) )
            //{
            //   newValEntry->SetKey(  parentSQItem->GetBaseTagKey()
            //                      + newValEntry->GetKey() );
            //}

            if ( !set->AddEntry( newValEntry ) )
            {
              gdcmWarningMacro( "in ParseDES : cannot add a ValEntry "
                                  << newValEntry->GetKey()
                                  << " (at offset : " 
                                  << newValEntry->GetOffset() << " )" );   
              used=false;
            }
            else
            {
               // Load only if we can add (not a duplicate key)
               LoadDocEntry( newValEntry );
            }

            if ( newValEntry->GetElement() == 0x0000 ) // if on group length
            {
               if ( newValEntry->GetGroup()%2 != 0 )   // if Shadow Group
               {
                  if ( LoadMode & LD_NOSHADOW ) // if user asked to skip shad.gr
                  {
                     std::string strLgrGroup = newValEntry->GetValue();
                     int lgrGroup;
                     if ( strLgrGroup != GDCM_UNFOUND)
                     {
                        lgrGroup = atoi(strLgrGroup.c_str());
                        Fp->seekg(lgrGroup, std::ios::cur);
                        //used = false;  // never used
                        RemoveEntry( newDocEntry );  // Remove and delete
                        // bcc 5.5 is right "assigned a value that's never used"
                        // newDocEntry = 0;
                        continue;
                     }
                  }
               }
            }

            bool delimitor = newValEntry->IsItemDelimitor();

            if ( (delimitor) || 
                (!delim_mode && ((long)(Fp->tellg())-offset) >= l_max) )
            {
               if ( !used )
                  delete newDocEntry;
               break;
            }
         }

         // Just to make sure we are at the beginning of next entry.
         SkipToNextDocEntry(newDocEntry);
      }
      else
      {
         /////////////////////// SeqEntry :  VR = "SQ"

         unsigned long l = newDocEntry->GetReadLength();          
         if ( l != 0 ) // don't mess the delim_mode for 'zero-length sequence'
         {
            if ( l == 0xffffffff )
            {
              delim_mode_intern = true;
            }
            else
            {
              delim_mode_intern = false;
            }
         }

         if ( (LoadMode & LD_NOSHADOWSEQ) && ! delim_mode_intern )
         { 
           // User asked to skip SeQuences *only* if they belong to Shadow Group
            if ( newDocEntry->GetGroup()%2 != 0 )
            {
                Fp->seekg( l, std::ios::cur);
                RemoveEntry( newDocEntry );  // Remove and delete
                continue;  
            } 
         } 
         if ( (LoadMode & LD_NOSEQ) && ! delim_mode_intern ) 
         {
           // User asked to skip *any* SeQuence
            Fp->seekg( l, std::ios::cur);
            RemoveEntry( newDocEntry );  // Remove and delete
            continue;
         }
         // delay the dynamic cast as late as possible
         newSeqEntry = dynamic_cast<SeqEntry*>(newDocEntry);
         
         // no other way to create the Delimitor ...
         newSeqEntry->SetDelimitorMode( delim_mode_intern );

         // At the top of the hierarchy, stands a Document. When "set"
         // is a Document, then we are building the first depth level.
         // Hence the SeqEntry we are building simply has a depth
         // level of one:
        if ( set == this ) // ( dynamic_cast< Document* > ( set ) )
         {
            newSeqEntry->SetDepthLevel( 1 );
         }
         // But when "set" is already a SQItem, we are building a nested
         // sequence, and hence the depth level of the new SeqEntry
         // we are building, is one level deeper:

         // time waste hunting
         else if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) )
         {
            newSeqEntry->SetDepthLevel( parentSQItem->GetDepthLevel() + 1 );
         }

         if ( l != 0 )
         {  // Don't try to parse zero-length sequences

            gdcmDebugMacro( "Entry in ParseSQ, delim " << delim_mode_intern
                               << " at offset 0x(" << std::hex

⌨️ 快捷键说明

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