]> Creatis software - gdcm.git/blobdiff - Example/DenseMultiFramesToDicom.cxx
Fix mistypings
[gdcm.git] / Example / DenseMultiFramesToDicom.cxx
index 3e43a357f0cf3615d51023c6e53802742a7c1314..18109cac808234b39b190eba5f272bdca531e48b 100755 (executable)
@@ -3,8 +3,8 @@
   Program:   gdcm
   Module:    $RCSfile: DenseMultiFramesToDicom.cxx,v $
   Language:  C++
-  Date:      $Date: 2006/07/20 17:15:28 $
-  Version:   $Revision: 1.1 $
+  Date:      $Date: 2007/10/29 17:13:59 $
+  Version:   $Revision: 1.10 $
                                                                                 
   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
   l'Image). All rights reserved. See Doc/License.txt or
 #include <iostream>
 //#include <values.h>
 
+#if defined(__BORLANDC__)
+#include <ctype.h>
+#endif
+
 #include "gdcmFile.h"
 #include "gdcmFileHelper.h"
 #include "gdcmDebug.h"
@@ -36,9 +40,8 @@
   *           WARNING : directory must contain ONLY .txt files 
   */  
 
-
 void Load(std::ifstream &from, std::string imageName, std::string patName, 
-          std::string strStudyUID, int serieNumber);
+          std::string strStudyUID, std::string strSerieUID, int serieNumber, int verbose);
 
 //std::ifstream& eatwhite(std::ifstream& is);
 
@@ -93,17 +96,17 @@ The terms brightness and contrast are not used in radiology imaging
 int main(int argc, char *argv[])
 {
    START_USAGE(usage)
-   " \n DenseMultiframeToDicom :\n                                            ",
+   " \n DenseMultiFramesToDicom :                                           \n",
    " - explores recursively the given (single Patient, single Study) directory",
    "         - examines the '.txt' files                                      ",
    "         - Converts the files into 16 bits Dicom files,                   ",
    " WARNING : directory must contain ONLY .txt files                         ",
    " usage:                                                                   ",
-   " DenseMultiframeToDicom dirin=rootDirectoryName                           ",
+   " DenseMultiFramesToDicom dirin=rootDirectoryName                          ",
    "              [studyUID = ] [patName = ]                                  ",
    "              [listonly] [verbose] [debug]                                ",
    "                                                                          ",
-   "studyUID   : *aware* user wants to add the serie                          ",
+   " studyUID   : *aware* user wants to add the serie                         ",
    "                                             to an already existing study ",
    " verbose  : user wants to run the program in 'verbose mode'               ",
    " debug    : *developer*  wants to run the program in 'debug mode'         ",
@@ -111,7 +114,7 @@ int main(int argc, char *argv[])
 
    // ----- Initialize Arguments Manager ------
       
-   gdcm::ArgMgr *am = new gdcm::ArgMgr(argc, argv);
+   GDCM_NAME_SPACE::ArgMgr *am = new GDCM_NAME_SPACE::ArgMgr(argc, argv);
   
    if (argc == 1 || am->ArgMgrDefined("usage")) 
    {
@@ -124,20 +127,25 @@ int main(int argc, char *argv[])
    dirNamein  = am->ArgMgrGetString("dirin","."); 
 
    if (am->ArgMgrDefined("debug"))
-      gdcm::Debug::DebugOn();
+      GDCM_NAME_SPACE::Debug::DebugOn();
       
    int verbose  = am->ArgMgrDefined("verbose");      
    int listonly = am->ArgMgrDefined("listonly");
-   std::string patName = am->ArgMgrGetString("patname", "g^PatientName");
+   std::string patName = am->ArgMgrGetString("patname", dirNamein);
+   
+   bool userDefinedStudy = ( 0 != am->ArgMgrDefined("studyUID") );
 
-   bool userDefinedStudy = am->ArgMgrDefined("studyUID");
-   const char *studyUID  = am->ArgMgrGetString("studyUID");
+   const char *studyUID;
+   if (userDefinedStudy)
+      studyUID  = am->ArgMgrGetString("studyUID");  
+
+   // not described *on purpose* in the Usage !
+   bool userDefinedSerie = ( 0 != am->ArgMgrDefined("serieUID") );    
+   const char *serieUID;
+   if(userDefinedSerie)
+      serieUID = am->ArgMgrGetString("serieUID");
 
-// not described *on purpose* in the Usage ! 
-   bool userDefinedSerie = am->ArgMgrDefined("serieUID");   
-   const char *serieUID  = am->ArgMgrGetString("serieUID");
-      
-      
    // if unused Param we give up
    if ( am->ArgMgrPrintUnusedLabels() )
    { 
@@ -149,7 +157,7 @@ int main(int argc, char *argv[])
 
    // ----- Begin Processing -----
    
-   if ( ! gdcm::DirList::IsDirectory(dirNamein) )
+   if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirNamein) )
    {
       std::cout << "KO : [" << dirNamein << "] is not a Directory." 
                 << std::endl;
@@ -157,11 +165,12 @@ int main(int argc, char *argv[])
    }
    else
    {
-      std::cout << "OK : [" << dirNamein << "] is a Directory." << std::endl;
+      if (verbose)
+         std::cout << "OK : [" << dirNamein << "] is a Directory." << std::endl;
    }
 
    std::string strDirNamein(dirNamein);
-   gdcm::DirList dirList(strDirNamein, true); // (recursively) the list of files
+   GDCM_NAME_SPACE::DirList dirList(strDirNamein, true); // (recursively) the list of files
 
    if (listonly)
    {
@@ -174,16 +183,37 @@ int main(int argc, char *argv[])
    std::string filenameout;
 
    std::string strStudyUID;
-   strStudyUID =  gdcm::Util::CreateUniqueUID();
+   std::string strSerieUID;
+
+   if (userDefinedStudy)
+      strSerieUID =  studyUID;
+   else
+      strStudyUID =  GDCM_NAME_SPACE::Util::CreateUniqueUID();
+   
+   if (userDefinedStudy)
+     strSerieUID =  serieUID;
+   else
+      strStudyUID =  GDCM_NAME_SPACE::Util::CreateUniqueUID();  
+
+   
    int serieNumber =0;     
-   gdcm::DirListType fileNames;
+   GDCM_NAME_SPACE::DirListType fileNames;
    fileNames = dirList.GetFilenames();
-   for (gdcm::DirListType::iterator it = fileNames.begin();  
+   for (GDCM_NAME_SPACE::DirListType::iterator it = fileNames.begin();  
                                     it != fileNames.end();
                                   ++it)
-   {
-   
-   
+   { 
+      if ( GDCM_NAME_SPACE::Util::GetName((*it)).c_str()[0] == '.' ) 
+      {
+      // skip hidden files
+         continue;
+      }
+      int sz = (*it).size();
+      if ( (*it).c_str()[sz-1] != 't')
+      {
+         // skip non .txt files
+         continue;
+      }
       std::ifstream from( (*it).c_str() );   
       if ( !from )
       {
@@ -192,21 +222,26 @@ int main(int argc, char *argv[])
       }
       else
       { 
-         std::cout << "Success in open file" << *it << std::endl;
-         Load(from, *it, patName, strStudyUID, serieNumber);
-         serieNumber++;
+         if (verbose)
+           std::cout << "Success in open file" << *it << std::endl;
+         Load(from, *it, patName, strStudyUID, strSerieUID, serieNumber, verbose);
+         serieNumber+=2;
          //return 0;
       }   
    }
+   return 1;
 }
 
 
 void Load(std::ifstream &from, std::string imageName, std::string patName, 
-          std::string strStudyUID, int serieNumber)
+          std::string strStudyUID, std::string strSerieUID, int serieNumber, int verbose)
 {
+   if (verbose)  
+      std::cout << " ========= Deal with file [" << imageName << "]" << std::endl;
    if (!from)
       return;
-
+   if (verbose)      
+     std::cout << " ========= Create Parametric images" << std::endl; 
 /* was OK for single frames
 eg :
 ---------------------------
@@ -259,66 +294,119 @@ All pixels with zero strain values are outside the masks.
     from >> str1;
     from >> str1; // 52x59x14
    
-    std::cout << "[" << str1 << "]" << std::endl;
+    if(verbose)
+       std::cout << "[" << str1 << "]" << std::endl;
     
     sscanf( str1.c_str(),"%dx%dx%d", &nx,&ny,&nf);
     std::cout << nx << " " << ny << " " << nf << std::endl;
     
-       // Skip 4 lines.
-    for (int k=0; k<4; k++)
-    {   
+    std::getline(from, str1);
+
+    from >> str1; // Temporal
+    from >> str1; // Resolution
+    from >> str1; // =
+    
+    from >> str1; 
+    
+    float temporalResolution;
+    sscanf( str1.c_str(),"%f",&temporalResolution);
+    if(verbose)
+      std::cout << "temporal Resolution = " << temporalResolution << std::endl;
+    std::getline(from, str1);
+    
+    from >> str1; // First
+    from >> str1; // frame
+    from >> str1; // starts
+    from >> str1; // at
+    
+    from >> str1; 
+    float timeStart;
+    sscanf( str1.c_str(),"%f",&timeStart);
+    std::cout << "time Start = " << timeStart << std::endl;
+    std::getline(from, str1);           
+    
+       // Skip 3 lines.
+    for (int k=0; k<2; k++) // 
+    {
        std::getline(from, str1);
        std::cout << str1 << std::endl;
     }        
              
-   //float *f = new float(nx*ny);
+  //float *f = new float(nx*ny);
+  // -->float *f = new float[nx*ny]; // Would be better !
    float *f = (float *) malloc(nx*ny*nf*sizeof(float));
   // float mini = FLT_MAX, maxi = FLT_MIN;
    float val;
-    
-   std::string strSerieUID;
-   strSerieUID =  gdcm::Util::CreateUniqueUID();     
-   
-  for (int l=0; l<nf; l++)  // Loop on the frames
-  { 
+
+   int imageNumber = 0;     
+   float currentTime;
+   currentTime = timeStart;
+   int l1;
+   for (l1=0; l1<nf; l1++)  // Loop on the frames
+   { 
+     //std::cout << "Frame nb " << l1 << std::endl;
      for( int j=0; j<ny; j++)
-     { 
-      int l =0;   
+     {   
       for (int i=0; i<nx; i++)
       {
+         str1="";
          //eatwhite(from);
          char c;
-         for (;;)
+         for (;;) //eatwhite(from);
          {
             if (!from.get(c))
+            {
+               std::cout << " !from.get(c) ";
                break;
-            if (!isspace(c)) 
+            }
+            if (!isspace(c) ) 
             {
+               //std::cout << " !isspace(c) ";
                from.putback(c);
                break;
             }
-         }  
-         from >> str1;
+         } //end eatwhite(from);
+
+        // trouble : when space is missing "-0.0990263-8.8778"
+        // is not interpreted as TWO values  :-(
+        // from >> str1;
+
+         int first = 1;
+         char previous = 'z'; 
+         for(;;)
+         {
+            from.get(c);
+            if ( c == ' ')
+               break; 
+            if ( first != 1 && c == '-' && previous != 'e')
+            {
+               from.putback(c);
+               //std::cout << " One more gauffre in frame:" << std::dec << l 
+               //         << ", line : " << j << " element " << i << std::endl;
+               break;
+             }
+   
+             first=0;
+             previous = c;
+             str1=str1+c;
+         }
          val = (float)atof(str1.c_str());
-        // std::cout << "  " << val;
+         //std::cout << "  " << val;
          *(f+ /*l*nx*ny + */j*nx+i) = val;
  
         if(from.eof()) 
         {
-            std::cout << "Missing values at [" << j <<"," << i << "]" 
+            std::cout << "Missing values at [" << std::dec << j <<"," << i << "]" 
                       << std::endl; 
            break;
          }
-         l++;           
       }
       
-       std::cout << std::endl;
+      //std::cout << std::endl;
       //std::cout << std::endl << " line nb : " << j 
       //          << " line length : " << l << std::endl;
-         
     }
-   
     
    // std::cout << "mini : "<< mini  << " maxi : " << maxi << std::endl;
 /*
@@ -336,26 +424,26 @@ All pixels with zero strain values are outside the masks.
        ptr++;
     }     
 */
-    uint16_t *img = new uint16_t[ny*nx];
-    uint16_t *ptr = img;
+    int16_t *img = new int16_t[ny*nx];
+    int16_t *ptr = img;
     float *tmp = f /* + l*ny*nx */ ; // start on image nb l.
     for( int k=0; k<ny*nx; k++)
     {
-       if(*tmp 0) // artefacted pixel
+       if(*tmp > 1.0) // artefacted pixel
           *ptr = 0;
        else        /// \todo FIXME : what about max threshold ?
         *ptr = (int16_t)(*tmp *100); 
 
-       //std::cout << std::dec << "[" << *tmp <<" : " << *ptr << "] ";
+      // std::cout << std::dec << "[" << *tmp <<" : " << *ptr << "] ";
        tmp ++;
        ptr++;
     }  
 
- // gdcm::Debug::DebugOn();
+ // GDCM_NAME_SPACE::Debug::DebugOn();
   
         std::ostringstream str; 
-        gdcm::File *file;
-        file = gdcm::File::New();       
+        GDCM_NAME_SPACE::File *file;
+        file = GDCM_NAME_SPACE::File::New();       
               
   // Set the image size
         str.str("");
@@ -375,7 +463,7 @@ All pixels with zero strain values are outside the masks.
         file->InsertEntryString("15",0x0028,0x0102,"US"); // High Bit
 
   // Set the pixel representation // 0/1 1 : signed
-        file->InsertEntryString("0",0x0028,0x0103, "US"); // Pixel Representation
+        file->InsertEntryString("1",0x0028,0x0103, "US"); // Pixel Representation
 
   // Set the samples per pixel // 1:Grey level, 3:RGB
         file->InsertEntryString("1",0x0028,0x0002, "US"); // Samples per Pixel
@@ -397,10 +485,10 @@ All pixels with zero strain values are outside the masks.
 
 // 0020 0032 DS 3 Image Position (Patient)
         char charImagePosition[256]; 
-        sprintf(charImagePosition,"0.0\\0.0\\%f",float(l%nf));
+        sprintf(charImagePosition,"0.0\\0.0\\%f",float(l1%nf));
  
 // 0020 0x1041 DS 1 Slice Location 
-        sprintf(charImagePosition,"%f",float(l%nf));
+        sprintf(charImagePosition,"%f",float(l1%nf));
         file->InsertEntryString(charImagePosition,0x0020,0x1041, "DS");
  
 //0008 103e LO 1 Series Description
@@ -413,11 +501,19 @@ All pixels with zero strain values are outside the masks.
 //0020 0011 "IS" Series Number 
          sprintf(charImagePosition,"%04d",serieNumber);
          file->InsertEntryString(charImagePosition,0x0020,0x0011, "IS");
-
+//0020 0011 "IS" Instance Number 
+         sprintf(charImagePosition,"%04d",imageNumber);
+         file->InsertEntryString(charImagePosition,0x0020,0x0013, "IS");
+//0018 1060 "DS" Time Trigger 
+         sprintf(charImagePosition,"%f",currentTime);
+         file->InsertEntryString(charImagePosition,0x0018,0x1060, "DS");
    // file->Print();
     
-    gdcm::FileHelper *fh;
-    fh = gdcm::FileHelper::New(file);
+    GDCM_NAME_SPACE::FileHelper *fh;
+    fh = GDCM_NAME_SPACE::FileHelper::New(file);
     // cast is just to avoid warnings (*no* conversion)
     fh->SetImageData((uint8_t *)img,nx*ny*sizeof(uint16_t));
     fh->SetWriteModeToRaw(); 
@@ -425,18 +521,167 @@ All pixels with zero strain values are outside the masks.
     
     fh->SetWriteTypeToDcmExplVR();
 
-
     char numero[10];
-    sprintf(numero, "%02d", l);   
+    sprintf(numero, "%02d", l1);   
     std::string fileName = imageName + "." + numero + ".dcm";
-    std::cout << "fileName " << fileName << std::endl;
+    if(verbose)
+      std::cout << "fileName " << fileName << std::endl;
       
     if( !fh->Write(fileName))
        std::cout << "Failed for [" << fileName << "]\n"
                  << "           File is unwrittable" << std::endl;
 
-    delete img; 
+    delete img;
+    currentTime += temporalResolution; 
+    imageNumber ++;     
+
   } // end loop on frames
+    
        
+   // Anatomical Images.
+  std::cout << " ========= Create Anatomical images" << std::endl;   
+
+  strSerieUID =  GDCM_NAME_SPACE::Util::CreateUniqueUID();     
+  imageNumber = 0;     
+  currentTime = timeStart;
+     
+  for (int fr=0; fr<nf; fr++)  // Loop on the frames
+  {
+   //std::cout << "Frame nb " << l << std::endl;  
+     for( int j=0; j<ny; j++)
+     { 
+      int l =0;   
+      for (int i=0; i<nx; i++)
+      {
+         //eatwhite(from);
+         char c;
+         for (;;)
+         {
+            if (!from.get(c))
+               break;
+            if (!isspace(c)) 
+            {
+               from.putback(c);
+               break;
+            }
+         }  
+         from >> str1;
+         val = (float)atof(str1.c_str());
+        // std::cout << "  " << val;
+         *(f+ /*l*nx*ny + */j*nx+i) = val;
+        if(from.eof()) 
+        {
+            std::cout << "Missing values at [" << std::dec << j <<"," << i << "]" 
+                      << std::endl; 
+           break;
+         }
+         l++;           
+      } 
+     } 
+     
+    uint16_t *img = new uint16_t[ny*nx];
+    uint16_t *ptr = img;
+    float *tmp = f /* + l*ny*nx */ ; // start on image nb l.
+    for( int k=0; k<ny*nx; k++)
+    {
+       *ptr = (int16_t)(*tmp); 
+       tmp ++;
+       ptr++;
+    }
+        std::ostringstream str; 
+        GDCM_NAME_SPACE::File *file;
+        file = GDCM_NAME_SPACE::File::New();       
+              
+  // Set the image size
+        str.str("");
+        str << nx;
+        file->InsertEntryString(str.str(),0x0028,0x0011,"US"); // Columns
+        str.str("");
+        str << ny;
+        file->InsertEntryString(str.str(),0x0028,0x0010,"US"); // Rows
+
+  // Set the pixel type
+  //      16; //8, 16, 32
+        file->InsertEntryString("16",0x0028,0x0100,"US"); // Bits Allocated
+        str.str("");
+        str << 16; // may be 12 or 16 if componentSize =16
+        file->InsertEntryString("16",0x0028,0x0101,"US"); // Bits Stored
+
+        file->InsertEntryString("15",0x0028,0x0102,"US"); // High Bit
+
+  // Set the pixel representation // 0/1 1 : signed
+        file->InsertEntryString("0",0x0028,0x0103, "US"); // Pixel Representation
+
+  // Set the samples per pixel // 1:Grey level, 3:RGB
+        file->InsertEntryString("1",0x0028,0x0002, "US"); // Samples per Pixel
+
+/*
+  // Set Rescale Intercept
+        str.str("");
+        str << div;  
+        file->InsertEntryString(str.str(),0x0028,0x1052,"DS");
+
+  // Set Rescale Slope
+        str.str("");
+        str << mini;  
+        file->InsertEntryString(str.str(),0x0028,0x1053,"DS");
+*/
+
+// 0020 0037 DS 6 Image Orientation (Patient)
+         file->InsertEntryString("1.0\\0.0\\0.0\\0.0\\1.0\\0.0",0x0020,0x0037, "DS"); //[1\0\0\0\1\0] : Axial
+
+// 0020 0032 DS 3 Image Position (Patient)
+        char charImagePosition[256]; 
+        sprintf(charImagePosition,"0.0\\0.0\\%f",float(l1%nf));
+// 0020 0x1041 DS 1 Slice Location 
+        sprintf(charImagePosition,"%f",float(l1%nf));
+        file->InsertEntryString(charImagePosition,0x0020,0x1041, "DS");
+//0008 103e LO 1 Series Description
+        file->InsertEntryString(imageName,0x0008,0x103e, "LO");
+
+        file->InsertEntryString(strStudyUID,0x0020,0x000d,"UI");      
+        file->InsertEntryString(strSerieUID,0x0020,0x000e,"UI");
+        file->InsertEntryString(patName,0x0010,0x0010, "PN");   // Patient's Name
+        
+//0020 0011 "IS" Series Number 
+         sprintf(charImagePosition,"%04d",serieNumber+1);
+         file->InsertEntryString(charImagePosition,0x0020,0x0011, "IS");
+
+//0020 0011 "IS" Instance Number 
+         sprintf(charImagePosition,"%04d",imageNumber);
+         file->InsertEntryString(charImagePosition,0x0020,0x0013, "IS"); 
+
+//0018 1060 "DS" Time Trigger 
+         sprintf(charImagePosition,"%f",currentTime);
+         file->InsertEntryString(charImagePosition,0x0018,0x1060, "DS");
+   // file->Print();
+    
+    GDCM_NAME_SPACE::FileHelper *fh;
+    fh = GDCM_NAME_SPACE::FileHelper::New(file);
+    // cast is just to avoid warnings (*no* conversion)
+    fh->SetImageData((uint8_t *)img,nx*ny*sizeof(uint16_t));
+    fh->SetWriteModeToRaw(); 
+    fh->SetWriteTypeToDcmExplVR();
+    
+    fh->SetWriteTypeToDcmExplVR();
+
+    char numero[10];
+    sprintf(numero, "%02d", l1);   
+    std::string fileName = imageName + ".Anatomical." + numero + ".dcm";
+    std::cout << "fileName " << fileName << std::endl;
+      
+    if( !fh->Write(fileName))
+       std::cout << "Failed for [" << fileName << "]\n"
+                 << "           File is unwrittable" << std::endl;
+
+    delete img; 
+    currentTime += temporalResolution; 
+    imageNumber ++;                    
+      
+  } // end loop on frames 
+   
    from.close();
-}
+} // end void Load(