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

📄 gdcmfilehelper.cxx

📁 DTMK软件开发包,此为开源软件,是一款很好的医学图像开发资源.
💻 CXX
📖 第 1 页 / 共 5 页
字号:
   if ( nbBitsStored == 0 || nbBitsStored > nbBitsAllocated )
   {
      os.str("");
      os << nbBitsAllocated;
      CopyMandatoryEntry(0x0028,0x0101,os.str());
      gdcmWarningMacro("(0028,0101) changed from "
                       << nbBitsStored << " to " << nbBitsAllocated
                       << " for consistency purpose" );
      nbBitsStored = nbBitsAllocated; 
    }
   // check 'Hight Bit Position' vs 'Bits Allocated' and 'Bits Stored'
   int highBitPosition = FileInternal->GetHighBitPosition();
   if ( highBitPosition == 0 || 
        highBitPosition > nbBitsAllocated-1 ||
        highBitPosition < nbBitsStored-1  )
   {
      os.str("");
      os << nbBitsStored - 1; 
      CopyMandatoryEntry(0x0028,0x0102,os.str());
      gdcmWarningMacro("(0028,0102) changed from "
                       << highBitPosition << " to " << nbBitsAllocated-1
                       << " for consistency purpose");
   }

   std::string pixelSpacing = FileInternal->GetEntryValue(0x0028,0x0030);
   if ( pixelSpacing == GDCM_UNFOUND )
   {
      pixelSpacing = "1.0\\1.0";
       // if missing, Pixel Spacing forced to "1.0\1.0"
      CopyMandatoryEntry(0x0028,0x0030,pixelSpacing);
   }
   std::string imageOrientationPatient = FileInternal->GetEntryValue(0x0020,0x0037);
   if ( imageOrientationPatient == GDCM_UNFOUND )
   {
      imageOrientationPatient = "1\\0\\0\\0\\1\\0";
      CopyMandatoryEntry(0x0020,0x0037,imageOrientationPatient);
   }

   // 'Imager Pixel Spacing' : defaulted to 'Pixel Spacing'
   // --> This one is the *legal* one !
   // FIXME : we should write it only when we are *sure* the image comes from
   //         an imager (see also 0008,0x0064)
   CheckMandatoryEntry(0x0018,0x1164,pixelSpacing);

   // Samples Per Pixel (type 1) : default to grayscale
   CheckMandatoryEntry(0x0028,0x0002,"1");

   // --- Check UID-related Entries ---

   // If 'SOP Class UID' exists ('true DICOM' image)
   // we create the 'Source Image Sequence' SeqEntry
   // to hold informations about the Source Image

   ValEntry *e_0008_0016 = FileInternal->GetValEntry(0x0008, 0x0016);
   if ( e_0008_0016 )
   {
      // Make sure 0008,0016 & 0002,0002 are always consistant whatever user says...
      ValEntry *e_0002_0002 = FileInternal->GetValEntry(0x0002, 0x0002);
      e_0002_0002->SetValue( e_0008_0016->GetValue() );

      // Create 'Source Image Sequence' SeqEntry
      SeqEntry *sis = new SeqEntry (
            Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x2112) );
      SQItem *sqi = new SQItem(1);
      // (we assume 'SOP Instance UID' exists too)
      // create 'Referenced SOP Class UID'
      ValEntry *e_0008_1150 = new ValEntry(
            Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x1150) );
      e_0008_1150->SetValue( e_0008_0016->GetValue());
      sqi->AddEntry(e_0008_1150);

      // create 'Referenced SOP Instance UID'
      ValEntry *e_0008_0018 = FileInternal->GetValEntry(0x0008, 0x0018);

      // Make sure 0008,0018 & 0002,0003 are always consistant whatever user says...
      ValEntry *e_0002_0003 = FileInternal->GetValEntry(0x0002, 0x0003);
      e_0002_0003->SetValue( e_0008_0018->GetValue() );

      ValEntry *e_0008_1155 = new ValEntry(
            Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x1155) );
      e_0008_1155->SetValue( e_0008_0018->GetValue());
      sqi->AddEntry(e_0008_1155);

      sis->AddSQItem(sqi,1);
      // temporarily replaces any previous 'Source Image Sequence'
      Archive->Push(sis);

      // 'Image Type' (The written image is no longer an 'ORIGINAL' one)
      ValEntry *e_0008_0008 = FileInternal->GetValEntry(0x0008, 0x0008);
      std::string imagetype = "DERIVED\\PRIMARY";
      // Make sure to preserved information from element 0008,0008, simply replace
      // comp #1 of Image Type with 'DERIVED', as gdcm is always deriving image
      if( e_0008_0008 )
        {
        std::string s = e_0008_0008->GetValue();
        if( !s.empty() )
          {
          std::vector<std::string> tokens;
          gdcm::Util::Tokenize( s, tokens, "\\");
          // Make sure we can find at least 2 names...
          if( tokens.size() >= 2 )
            {
            itksys_ios::ostringstream os2;
            for( std::vector<std::string>::const_iterator it = tokens.begin();
              it != tokens.end(); ++it)
              {
              if( it == tokens.begin() )
                {
                // Mark it DERIVED
                os2 << "DERIVED";
                }
              else
                {
                os2 << "\\";
                os2 << *it;
                }
              }
            imagetype = os.str();
            }
          }
        }
      CopyMandatoryEntry(0x0008,0x0008,imagetype);
   }
   else
   {
     ValEntry *e_0002_0002 = FileInternal->GetValEntry(0x0002, 0x0002);
     if( e_0002_0002 )
       {
       e_0008_0016  =  new ValEntry(
         Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x0016) );
       e_0008_0016 ->SetValue( e_0002_0002->GetValue() );
       ValEntry *e_0008_0018 = FileInternal->GetValEntry(0x0008, 0x0018);
       if( e_0008_0018 )
         {
         e_0008_0018->SetValue(
           FileInternal->GetValEntry(0x0002,0x0003)->GetValue() );
         }
       Archive->Push(e_0008_0016);
       }
     else
       {
       // There was no 'SOP Class UID' nor 'Media Storage SOP UID'
       // the source image was NOT a true Dicom one.
       // We consider the image is a 'Secondary Capture' one
       // SOP Class UID
       e_0008_0016  =  new ValEntry(
         Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x0016) );
       // [Secondary Capture Image Storage]
       e_0008_0016 ->SetValue("1.2.840.10008.5.1.4.1.1.7");
       Archive->Push(e_0008_0016);
       }
   }

   // ---- The user will never have to take any action on the following ----

   // new value for 'SOP Instance UID'
   //ValEntry *e_0008_0018 = new ValEntry(
   //      Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x0018) );
   //e_0008_0018->SetValue( Util::CreateUniqueUID() );
   //Archive->Push(e_0008_0018);
   CheckMandatoryEntry(0x0008,0x0018,sop);

   // Instance Creation Date
   const std::string &date = Util::GetCurrentDate();
   CopyMandatoryEntry(0x0008,0x0012,date);

   // Instance Creation Time
   const std::string &time = Util::GetCurrentTime();
   CopyMandatoryEntry(0x0008,0x0013,time);

   // Study Date
   CheckMandatoryEntry(0x0008,0x0020,date);
   // Study Time
   CheckMandatoryEntry(0x0008,0x0030,time);

   // Accession Number
   //CopyMandatoryEntry(0x0008,0x0050,"");
   CheckMandatoryEntry(0x0008,0x0050,"");
   

   // ----- Add Mandatory Entries if missing ---
   // Entries whose type is 1 are mandatory, with a mandatory value
   // Entries whose type is 1c are mandatory-inside-a-Sequence,
   //                          with a mandatory value
   // Entries whose type is 2 are mandatory, with an optional value
   // Entries whose type is 2c are mandatory-inside-a-Sequence,
   //                          with an optional value
   // Entries whose type is 3 are optional

   // 'Study Instance UID'
   // Keep the value if exists
   // The user is allowed to create his own Study, 
   //          keeping the same 'Study Instance UID' for various images
   // The user may add images to a 'Manufacturer Study',
   //          adding new Series to an already existing Study 
   CheckMandatoryEntry(0x0020,0x000d,Util::CreateUniqueUID());

   // 'Serie Instance UID'
   // Keep the value if exists
   // The user is allowed to create his own Series, 
   // keeping the same 'Serie Instance UID' for various images
   // The user shouldn't add any image to a 'Manufacturer Serie'
   // but there is no way no to prevent him for doing that 
   CheckMandatoryEntry(0x0020,0x000e,Util::CreateUniqueUID());

   // Study ID
   CheckMandatoryEntry(0x0020,0x0010,"");

   // Series Number
   CheckMandatoryEntry(0x0020,0x0011,"");

   // Instance Number
   CheckMandatoryEntry(0x0020,0x0013,"");

   // Patient Orientation
   // Can be computed from (0020|0037) :  Image Orientation (Patient)
   gdcm::Orientation o;
   std::string ori = o.GetOrientation ( FileInternal );
   if (ori != "\\" && ori != GDCM_UNFOUND)
      CheckMandatoryEntry(0x0020,0x0020,ori);
   else
      CheckMandatoryEntry(0x0020,0x0020,"");

   // Modality : if missing we set it to 'OTher'
   CheckMandatoryEntry(0x0008,0x0060,"OT");

   // Conversion Type: if missing we set it to 'SYN'
   CheckMandatoryEntry(0x0008,0x0064,"SYN");

   // Manufacturer : if missing we set it to 'GDCM Factory'
   CheckMandatoryEntry(0x0008,0x0070,"GDCM Factory");

   // Institution Name : if missing we set it to 'GDCM Hospital'
   CheckMandatoryEntry(0x0008,0x0080,"GDCM Hospital");

   // Patient's Name : if missing, we set it to 'GDCM^Patient'
   CheckMandatoryEntry(0x0010,0x0010,"GDCM^Patient");

    // Patient ID : 'type 2' entry but some DICOM implementation really needs it.
   CheckMandatoryEntry(0x0010,0x0020,"GDCM ID");

   // Patient's Birth Date : 'type 2' entry -> must exist, value not mandatory
   CheckMandatoryEntry(0x0010,0x0030,"");

   // Patient's Sex :'type 2' entry -> must exist, value not mandatory
   CheckMandatoryEntry(0x0010,0x0040,"");

   // Referring Physician's Name :'type 2' entry -> must exist, value not mandatory
   CheckMandatoryEntry(0x0008,0x0090,"");

}

void FileHelper::CheckMandatoryEntry(uint16_t group,uint16_t elem,std::string value)
{
   ValEntry *ve = FileInternal->GetValEntry(group, elem);
   if ( !ve)
   {
      ve = new ValEntry(
            Global::GetDicts()->GetDefaultPubDict()->GetEntry(group, elem) );
      ve->SetValue( value );
      Archive->Push(ve);
   }
}

void FileHelper::CopyMandatoryEntry(uint16_t group,uint16_t elem,std::string value)
{
   ValEntry *entry = CopyValEntry(group,elem);
   entry->SetValue(value);
   Archive->Push(entry);
}

/**
 * \brief Restore in the File the initial group 0002
 */
void FileHelper::RestoreWriteMandatory()
{
   // group 0002 may be pushed out for ACR-NEMA writting purposes 
   Archive->Restore(0x0002,0x0000);
   Archive->Restore(0x0002,0x0001);
   Archive->Restore(0x0002,0x0002);
   Archive->Restore(0x0002,0x0003);
   Archive->Restore(0x0002,0x0010);
   Archive->Restore(0x0002,0x0012);
   Archive->Restore(0x0002,0x0013);
   Archive->Restore(0x0002,0x0016);
   Archive->Restore(0x0002,0x0100);
   Archive->Restore(0x0002,0x0102);

   Archive->Restore(0x0008,0x0012);
   Archive->Restore(0x0008,0x0013);
   Archive->Restore(0x0008,0x0016);
   Archive->Restore(0x0008,0x0018);
   Archive->Restore(0x0008,0x0060);
   Archive->Restore(0x0008,0x0070);
   Archive->Restore(0x0008,0x0080);
   Archive->Restore(0x0008,0x0090);
   Archive->Restore(0x0008,0x2112);

   Archive->Restore(0x0010,0x0010);
   Archive->Restore(0x0010,0x0030);
   Archive->Restore(0x0010,0x0040);

   Archive->Restore(0x0020,0x000d);
   Archive->Restore(0x0020,0x000e);

}

//-----------------------------------------------------------------------------
// Private
/**
 * \brief Factorization for various forms of constructors.
 */
void FileHelper::Initialize()
{
   UserFunction = 0;
   KeepMediaStorageSOPClassUID = false;

   WriteMode = WMODE_RAW;
   //WriteType = ExplicitVR;
   WriteType = Unknown;

   PixelReadConverter  = new PixelReadConvert;
   PixelWriteConverter = new PixelWriteConvert;
   Archive = new DocEntryArchive( FileInternal );
}

/**
 * \brief Reads/[decompresses] the pixels, 
 *        *without* making RGB from Palette Colors 
 * @return the pixels area, whatever its type 
 *         (uint8_t is just for prototyping : feel free to Cast it) 
 */ 
uint8_t *FileHelper::GetRaw()
{
   PixelReadConverter->SetUserFunction( UserFunction );

   uint8_t *raw = PixelReadConverter->GetRaw();
   if ( ! raw )
   {
      // The Raw image migth not be loaded yet:
      std::ifstream *fp = FileInternal->OpenFile();
      PixelReadConverter->ReadAndDecompressPixelData( fp );
      if ( fp ) 
         FileInternal->CloseFile();

      raw = PixelReadConverter->GetRaw();
      if ( ! raw )
      {
         gdcmWarningMacro( "Read/decompress of pixel data apparently went wrong.");
         return 0;
      }
   }
   return raw;
}

//-----------------------------------------------------------------------------
/**
 * \brief   Prints the common part of ValEntry, BinEntry, SeqEntry
 * @param   os ostream we want to print in
 * @param indent (unused)
 */
void FileHelper::Print(std::ostream &os, std::string const &)
{
   FileInternal->SetPrintLevel(PrintLevel);
   FileInternal->Print(os);

   if ( FileInternal->IsReadable() )
   {
      PixelReadConverter->SetPrintLevel(PrintLevel);
      PixelReadConverter->Print(os);
   }
}

//-----------------------------------------------------------------------------
} // end namespace gdcm

⌨️ 快捷键说明

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