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

📄 gdcmdocument.cxx

📁 DTMK软件开发包,此为开源软件,是一款很好的医学图像开发资源.
💻 CXX
📖 第 1 页 / 共 5 页
字号:
                               << newDocEntry->GetOffset() << ")");

            ParseSQ( newSeqEntry, 
                     static_cast< long >( newDocEntry->GetOffset() ),
                     l, delim_mode_intern);

            gdcmDebugMacro( "Exit from ParseSQ, delim " << delim_mode_intern);
 
         }
         if ( !set->AddEntry( newSeqEntry ) )
         {
            gdcmWarningMacro( "in ParseDES : cannot add a SeqEntry "
                                << newSeqEntry->GetKey()
                                << " (at offset : 0x(" 
                                << newSeqEntry->GetOffset() << ") )" ); 
            used = false;
         }
 
         if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max)
         {
            if ( !used )
               delete newDocEntry;  
            break;
         }
      }  // end SeqEntry : VR = "SQ"

      if ( !used )
      {
         delete newDocEntry;
      }
      first = false;
   }                               // end While
   gdcmDebugMacro( "Exit from ParseDES, delim-mode " << delim_mode );
}

/**
 * \brief   Parses a Sequence ( SeqEntry after SeqEntry)
 * @return  parsed length for this level
 */ 
void Document::ParseSQ( SeqEntry *seqEntry,
                        long offset, long l_max, bool delim_mode)
{
   int SQItemNumber = 0;
   bool dlm_mod;
   long offsetStartCurrentSQItem = offset;

   while (true)
   {
      // the first time, we read the fff0,e000 of the first SQItem
      DocEntry *newDocEntry = ReadNextDocEntry();

      if ( !newDocEntry )
      {
         gdcmWarningMacro("in ParseSQ : should never get here!");
         break;
      }
      if ( delim_mode )
      {
         if ( newDocEntry->IsSequenceDelimitor() )
         {
            seqEntry->SetDelimitationItem( newDocEntry ); 
            break;
         }
      }
      if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max)
      {
         delete newDocEntry;
         break;
      }
      // create the current SQItem
      SQItem *itemSQ = new SQItem( seqEntry->GetDepthLevel() );
      unsigned int l = newDocEntry->GetReadLength();
      
      if ( l == 0xffffffff )
      {
         dlm_mod = true;
      }
      else
      {
         dlm_mod = false;
      }

      // remove fff0,e000, created out of the SQItem
      delete newDocEntry;
      // fill up the current SQItem, starting at the beginning of fff0,e000

      ParseDES(itemSQ, offsetStartCurrentSQItem, l+8, dlm_mod);

      offsetStartCurrentSQItem = Fp->tellg();
 
      seqEntry->AddSQItem( itemSQ, SQItemNumber ); 
      SQItemNumber++;
      if ( !delim_mode && ((long)(Fp->tellg())-offset ) >= l_max )
      {
         break;
      }
   }
}

/**
 * \brief   When a private Sequence + Implicit VR is encountered
 *           we cannot guess it's a Sequence till we find the first
 *           Item Starter. We then backtrack to do the job.
 * @param   docEntry Item Starter that warned us 
 */
DocEntry *Document::Backtrack(DocEntry *docEntry)
{
   // delete the Item Starter, built erroneously out of any Sequence
   // it's not yet in the HTable/chained list
   delete docEntry;

   // Get all info we can from PreviousDocEntry
   uint16_t group = PreviousDocEntry->GetGroup();
   uint16_t elem  = PreviousDocEntry->GetElement();
   uint32_t lgt   = PreviousDocEntry->GetLength();
   long offset    = static_cast< long >( PreviousDocEntry->GetOffset() );

   gdcmDebugMacro( "Backtrack :" << std::hex << group 
                                 << "|" << elem
                                 << " at offset 0x(" <<offset << ")" );
   RemoveEntry( PreviousDocEntry );

   // forge the Seq Entry
   DocEntry *newEntry = NewSeqEntry(group, elem);
   newEntry->SetLength(lgt);
   newEntry->SetOffset(offset);

   // Move back to the beginning of the Sequence

   Fp->seekg(offset, std::ios::beg); // Only for Shadow Implicit VR SQ
   return newEntry;
}

/**
 * \brief   Loads (or not) the element content depending if its length exceeds
 *          or not the value specified with Document::SetMaxSizeLoadEntry()
 * @param   entry Header Entry (Dicom Element) to be dealt with
 * @param forceLoad whether you want to force loading of 'long' elements
 */
void Document::LoadDocEntry(DocEntry *entry, bool forceLoad)
{
   uint16_t group  = entry->GetGroup();
   uint16_t elem   = entry->GetElement();
   std::string  vr = entry->GetVR();
   uint32_t length = entry->GetLength();

   Fp->seekg((long)entry->GetOffset(), std::ios::beg);

   // A SeQuence "contains" a set of Elements.  
   //          (fffe e000) tells us an Element is beginning
   //          (fffe e00d) tells us an Element just ended
   //          (fffe e0dd) tells us the current SeQuence just ended
   //          (fffe 0000) is an 'impossible' tag value, 
   //                                    found in MR-PHILIPS-16-Multi-Seq.dcm
   if ( (group == 0xfffe && elem != 0x0000 ) || vr == "SQ" )
   {
      // NO more value field for SQ !
      return;
   }

   // When the length is zero things are easy:
   if ( length == 0 )
   {
      ((ValEntry *)entry)->SetValue("");
      return;
   }

   // The elements whose length is bigger than the specified upper bound
   // are not loaded. Instead we leave a short notice on the offset of
   // the element content and it's length.

   itksys_ios::ostringstream s;

   if (!forceLoad)
   {
      if (length > MaxSizeLoadEntry)
      {
         if (BinEntry *binEntryPtr = dynamic_cast< BinEntry* >(entry) )
         {  
            s << GDCM_NOTLOADED;
            s << " Ad.:" << (long)entry->GetOffset();
            s << " x(" << std::hex << entry->GetOffset() << ")";
            s << std::dec;
            s << " Lgt:"  << entry->GetLength();
            s << " x(" << std::hex << entry->GetLength() << ")";
            binEntryPtr->SetValue(s.str());
         }
         else if (ValEntry *valEntryPtr = dynamic_cast< ValEntry* >(entry) )
         {
            s << GDCM_NOTLOADED;  
            s << " Address:" << (long)entry->GetOffset();
            s << " Length:"  << entry->GetLength();
            s << " x(" << std::hex << entry->GetLength() << ")";
            valEntryPtr->SetValue(s.str());
         }
         else
         {
            // fusible
            gdcmErrorMacro( "MaxSizeLoadEntry exceeded, neither a BinEntry "
                         << "nor a ValEntry ?! Should never print that !" );
         }

       // to be sure we are at the end of the value ...
       //  Fp->seekg((long)entry->GetOffset()+(long)entry->GetLength(),
       //            std::ios::beg);
       return;
      }
   }

   // When we find a BinEntry not very much can be done :
   if (BinEntry *binEntryPtr = dynamic_cast< BinEntry* >(entry) )
   {
      s << GDCM_BINLOADED;
      binEntryPtr->SetValue(s.str());
      LoadEntryBinArea(binEntryPtr); // last one, not to erase length !
      return;
   }

   if ( IsDocEntryAnInteger(entry) )
   {   
      int nbInt;
      // When short integer(s) are expected, read and convert the following 
      // (n * 2) characters properly i.e. consider them as short integers as
      // opposed to strings.
      // Elements with Value Multiplicity > 1
      // contain a set of integers (not a single one)       
      if (vr == "US")
      {
         nbInt = length / 2;
         uint16_t NewInt = ReadInt16();
         s << NewInt;
         if (nbInt > 1)
         {
            for (int i=1; i < nbInt; i++)
            {
               s << '\\';
               NewInt = ReadInt16();
               s << NewInt;
            }
         }
      }
      else if (vr == "SS")
      {
         nbInt = length / 2;
         int16_t NewInt = ReadInt16();
         s << NewInt;
         if (nbInt > 1)
         {
            for (int i=1; i < nbInt; i++)
            {
               s << '\\';
               NewInt = ReadInt16();
               s << NewInt;
            }
         }
      }
      // See above comment on multiple integers (mutatis mutandis).
      else if (vr == "UL")
      {
         nbInt = length / 4;
         uint32_t NewInt = ReadInt32();
         s << NewInt;
         if (nbInt > 1)
         {
            for (int i=1; i < nbInt; i++)
            {
               s << '\\';
               NewInt = ReadInt32();
               s << NewInt;
            }
         }
      }
      else if (vr == "SL")
      {
         nbInt = length / 4;
         int32_t NewInt = ReadInt32();
         s << NewInt;
         if (nbInt > 1)
         {
            for (int i=1; i < nbInt; i++)
            {
               s << '\\';
               NewInt = ReadInt32();
               s << NewInt;
            }
         }
      }
#ifdef GDCM_NO_ANSI_STRING_STREAM
      s << std::ends; // to avoid oddities on Solaris
#endif //GDCM_NO_ANSI_STRING_STREAM

      ((ValEntry *)entry)->SetValue(s.str());
      return;
   }
   
  // FIXME: We need an additional byte for storing \0 that is not on disk
   char *str = new char[length+1];
   Fp->read(str, (size_t)length);
   str[length] = '\0'; //this is only useful when length is odd
   // Special DicomString call to properly handle \0 and even length
   std::string newValue;
   if ( length % 2 )
   {
      newValue = Util::DicomString(str, length+1);
      gdcmWarningMacro("Warning: bad length: " << length <<
                       " For string :" <<  newValue.c_str()); 
      // Since we change the length of string update it length
      //entry->SetReadLength(length+1);
   }
   else
   {
      newValue = Util::DicomString(str, length);
   }
   delete[] str;

   if ( ValEntry *valEntry = dynamic_cast<ValEntry* >(entry) )
   {
      if ( Fp->fail() || Fp->eof())
      {
         if ( Fp->fail() )
            gdcmWarningMacro("--> fail");

         gdcmWarningMacro("Unread element value " << valEntry->GetKey() 
                          << " lgt : " << valEntry->GetReadLength() 
                          << " at " << std::hex << valEntry->GetOffset());
         valEntry->SetValue(GDCM_UNREAD);
         return;
      }

//      if ( vr == "UI" )
//      {
//         // Because of correspondance with the VR dic
//         valEntry->SetValue(newValue);
//      }
//      else
//      {
//         valEntry->SetValue(newValue);
//      }

// Anybody remembers the genesis of strange previous (commented out) code?
      valEntry->SetValue(newValue);

   }
   else
   {
      gdcmWarningMacro("Should have a ValEntry, here ! " << valEntry->GetKey() 
                          << " lgt : " << valEntry->GetReadLength() 
                          << " at " << std::hex << valEntry->GetOffset());
   }
}

/**
 * \brief  Find the value Length of the passed Doc Entry
 * @param  entry Header Entry whose length of the value shall be loaded. 
 */
void Document::FindDocEntryLength( DocEntry *entry, std::string vr )
   throw ( FormatError )
{
   uint16_t length16;       
   
   if ( Filetype == ExplicitVR && !entry->IsImplicitVR() ) 
   {
      if ( vr == "OB" || vr == "OW" || vr == "SQ" || vr == "UT" 
                                                           || vr == "UN" )
      {
         // The following reserved two bytes (see PS 3.5-2003, section
         // "7.1.2 Data element structure with explicit vr", p 27) must be
         // skipped before proceeding on reading the length on 4 bytes.

         Fp->seekg( 2L, std::ios::cur); // Once per OW,OB,SQ DocEntry
         uint32_t length32 = ReadInt32();

         if ( (vr == "OB" || vr == "OW") && length32 == 0xffffffff ) 
         {
            uint32_t lengthOB;
            try 
            {
               lengthOB = FindDocEntryLengthOBOrOW();// for encapsulation of encoded pixel 
            }
            catch ( FormatUnexpected )
            {
               // Computing the length failed (this happens with broken
               // files like gdcm-JPEG-LossLess3a.dcm). We still have a
               // chance to get the pixels by deciding the element goes
               // until the end of the file. Hence we artificially fix the
               // the length and proceed.
               gdcmWarningMacro( " Computing the length failed for " << 
                                   entry->GetKey() <<" in " <<GetFileName());

               long currentPosition = Fp->tellg(); // Only for gdcm-JPEG-LossLess3a.dcm-like
               Fp->seekg(0L,std::ios::end);        // Only for gdcm-JPEG-LossLess3a.dcm-like

               long lengthUntilEOF = (long)(Fp->tellg())-currentPosition; // Only for gdcm-JPEG-LossLess3a.dcm-like
               Fp->seekg(currentPosition, std::ios::beg);                 // Only for gdcm-JPEG-LossLess3a.dcm-like

               entry->SetReadLength(lengthUntilEOF);
               entry->SetLength(lengthUntilEOF);
               return;
            }
            entry->SetReadLength(lengthOB);
            entry->SetLength(lengthOB);
            return;
         }
         FixDocEntryFoundLength(entry, length32); 
         return;
      }

      // Length is encoded on 2 bytes.
      length16 = ReadInt16();
  

⌨️ 快捷键说明

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