gdcmDataEntry.cxx

Go to the documentation of this file.
00001 /*=========================================================================
00002                                                                                 
00003   Program:   gdcm
00004   Module:    $RCSfile: gdcmDataEntry.cxx,v $
00005   Language:  C++
00006   Date:      $Date: 2007/08/22 16:14:03 $
00007   Version:   $Revision: 1.45 $
00008                                                                                 
00009   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
00010   l'Image). All rights reserved. See Doc/License.txt or
00011   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
00012                                                                                 
00013      This software is distributed WITHOUT ANY WARRANTY; without even
00014      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
00015      PURPOSE.  See the above copyright notices for more information.
00016                                                                                 
00017 =========================================================================*/
00018 
00019 #include "gdcmDataEntry.h"
00020 #include "gdcmVR.h"
00021 #include "gdcmTS.h"
00022 #include "gdcmGlobal.h"
00023 #include "gdcmUtil.h"
00024 #include "gdcmDebug.h"
00025 
00026 #include <fstream>
00027 
00028 #if defined(__BORLANDC__)
00029  #include <mem.h>    // for memcpy
00030  #include <stdlib.h> // for atof
00031  #include <ctype.h>  // for isdigit
00032 #endif
00033 
00034 namespace GDCM_NAME_SPACE 
00035 {
00036 //-----------------------------------------------------------------------------
00037 #define MAX_SIZE_PRINT_ELEMENT_VALUE 0x7fffffff
00038 uint32_t DataEntry::MaxSizePrintEntry = MAX_SIZE_PRINT_ELEMENT_VALUE;
00039 
00040 //-----------------------------------------------------------------------------
00041 // Constructor / Destructor
00048 DataEntry::DataEntry(uint16_t group,uint16_t elem,
00049                                      VRKey const &vr) 
00050             : DocEntry(group,elem,vr)
00051 {
00052    State = STATE_LOADED;
00053    Flag = FLAG_NONE;
00054 
00055    StrArea = 0;
00056    BinArea = 0;
00057    SelfArea = true;
00058 }
00059 
00064 DataEntry::DataEntry(DocEntry *e)
00065             //: DocEntry(e->GetDictEntry())
00066             : DocEntry(e->GetGroup(),e->GetElement(), e->GetVR()  )
00067 {
00068    Flag = FLAG_NONE;
00069    BinArea = 0;
00070    
00071    SelfArea = true;
00072 
00073    Copy(e);
00074 }
00075 
00079 DataEntry::~DataEntry ()
00080 {
00081    DeleteBinArea();
00082    
00083 }
00084 
00085 //-----------------------------------------------------------------------------
00086 // Print
00087 
00088 //-----------------------------------------------------------------------------
00089 // Public
00095 void DataEntry::SetBinArea( uint8_t *area, bool self )  
00096 { 
00097    DeleteBinArea();
00098 
00099    BinArea = area;
00100    SelfArea = self;
00101 
00102    State = STATE_LOADED;
00103 }
00109 void DataEntry::CopyBinArea( uint8_t *area, uint32_t length )
00110 {
00111    DeleteBinArea();
00112 
00113    uint32_t lgh = length + length%2;
00114    SetLength(lgh);
00115 
00116    if( area && length > 0 )
00117    {
00118       NewBinArea();
00119       memcpy(BinArea,area,length);
00120       if( length!=lgh )
00121          BinArea[length]=0;
00122 
00123       State = STATE_LOADED;
00124    }
00125 }
00126 
00132 void DataEntry::SetValue(const uint32_t &id, const double &val)
00133 {
00134    if( !BinArea )
00135       NewBinArea();
00136    State = STATE_LOADED;
00137 
00138    if( id > GetValueCount() )
00139    {
00140       gdcmErrorMacro("Index (" << id << ") is greater than the data size");
00141       return;
00142    }
00143 
00144    const VRKey &vr = GetVR();
00145    if( vr == "US" || vr == "SS" )
00146    {
00147       uint16_t *data = (uint16_t *)BinArea;
00148       data[id] = (uint16_t)val;
00149    }
00150    else if( vr == "UL" || vr == "SL" )
00151    {
00152       uint32_t *data = (uint32_t *)BinArea;
00153       data[id] = (uint32_t)val;
00154    }
00155    else if( vr == "FL" )
00156    {
00157       float *data = (float *)BinArea;
00158       data[id] = (float)val;
00159    }
00160    else if( vr == "FD" )
00161    {
00162       double *data = (double *)BinArea;
00163       data[id] = (double)val;
00164    }
00165    else if( Global::GetVR()->IsVROfStringRepresentable(vr) )
00166    {
00167       gdcmErrorMacro("SetValue on String representable not implemented yet");
00168    }
00169    else
00170    {
00171       BinArea[id] = (uint8_t)val;
00172    }
00173 }
00180 double DataEntry::GetValue(const uint32_t &id) const
00181 {
00182    if( !BinArea )
00183    {
00184       if (GetLength() != 0) // avoid stupid messages
00186          gdcmErrorMacro("BinArea not set " << std::hex 
00187                      << GetGroup() << " " << GetElement() 
00188                      << " Can't get the value");
00189       return 0.0;
00190    }
00191 
00192    uint32_t count = GetValueCount();
00193    if( id > count )
00194    {
00195       gdcmErrorMacro("Index (" << id << ") is greater than the data size");
00196       return 0.0;
00197    }
00198 
00199    // if user *knows* that entry contains a US, 
00200    // he just has to cast the double he receives
00201    
00202    const VRKey &vr = GetVR();
00203 
00204    if( vr == "US" || vr == "SS" )
00205       return ((uint16_t *)BinArea)[id];
00206    else if( vr == "UL" || vr == "SL" )
00207       return ((uint32_t *)BinArea)[id];
00208    else if( vr == "FL" )
00209       return ((float *)BinArea)[id];
00210    else if( vr == "FD" )
00211       return ((double *)BinArea)[id];
00212    else if( Global::GetVR()->IsVROfStringRepresentable(vr) )
00213    {
00214       // this is for VR = "DS", ...
00215       if( GetLength() )
00216       {
00217          // Don't use std::string to accelerate processing
00218          double val;
00219          char *tmp = new char[GetLength()+1];
00220          memcpy(tmp,BinArea,GetLength());
00221          tmp[GetLength()]=0;
00222 
00223          if( count == 0 )
00224          {
00225             val = atof(tmp);
00226          }
00227          else
00228          {
00229             count = id;
00230             char *beg = tmp;
00231             for(uint32_t i=0;i<GetLength();i++)
00232             {
00233                if( tmp[i] == '\\' )
00234                {
00235                   if( count == 0 )
00236                   {
00237                      tmp[i] = 0;
00238                      break;
00239                   }
00240                   else
00241                   {
00242                      count--;
00243                      beg = &(tmp[i+1]);
00244                   }
00245                }
00246             }
00247             val = atof(beg);
00248          }
00249 
00250          delete[] tmp;
00251          return val;
00252       }
00253       else 
00254          return 0.0;
00255    }
00256    else
00257       return BinArea[id];
00258 }
00259 
00263 bool DataEntry::IsValueCountValid() /*const*/
00264 {
00265   uint32_t vm;
00266   const std::string &strVM = GetVM();
00267   uint32_t vc = GetValueCount();
00268   bool valid = vc == 0;
00269   if( valid )
00270     return true;
00271   
00272   // FIXME : what shall we do with VM = "2-n", "3-n", etc
00273   
00274   if( strVM == "1-n" )
00275   {
00276     // make sure there is at least one ??? FIXME
00277     valid = vc >= 1;
00278   }
00279   else
00280   {
00281     std::istringstream os;
00282     os.str( strVM );
00283     os >> vm;
00284     // Two cases:
00285     // vm respects the one from the dict
00286     // vm is 0 (we need to check if this element is allowed to be empty) FIXME
00287 
00288     // note  (JPR)
00289     // ----    
00290     // Entries whose type is 1 are mandatory, with a mandatory value.
00291     // Entries whose type is 1c are mandatory-inside-a-Sequence,
00292     //                          with a mandatory value.
00293     // Entries whose type is 2 are mandatory, with an optional value.
00294     // Entries whose type is 2c are mandatory-inside-a-Sequence,
00295     //                          with an optional value.
00296     // Entries whose type is 3 are optional.
00297 
00298     // case vc == 0 is only applicable for 'type 2' entries.
00299     // Problem : entry type may depend on the modality and/or the Sequence
00300     //           it's embedded in !
00301     //          (Get the information in the 'Conformance Statements' ...)  
00302     valid = vc == vm;
00303   }
00304   return valid;
00305 }
00306 
00310 uint32_t DataEntry::GetValueCount( ) const
00311 {
00312    const VRKey &vr = GetVR();
00313    if( vr == "US" || vr == "SS" )
00314       return GetLength()/sizeof(uint16_t);
00315    else if( vr == "UL" || vr == "SL" )
00316       return GetLength()/sizeof(uint32_t);
00317    else if( vr == "FL" || vr == "OF" )
00318       return GetLength()/4 ; // FL has a *4* length! sizeof(float);
00319    else if( vr == "FD" )
00320       return GetLength()/8;  // FD has a *8* length! sizeof(double);
00321    else if( Global::GetVR()->IsVROfStringRepresentable(vr) )
00322    {
00323       // Some element in DICOM are allowed to be empty
00324       if( !GetLength() ) 
00325          return 0;
00326       // Don't use std::string to accelerate processing
00327       uint32_t count = 1;
00328       for(uint32_t i=0;i<GetLength();i++)
00329       {
00330          if( BinArea[i] == '\\')
00331             count++;
00332       }
00333       return count;
00334    }
00335    return GetLength();
00336 }
00337 
00343  bool DataEntry::GetDSValue(std::vector <double> &valueVector)
00344  {
00346     std::vector<std::string> tokens;
00347     
00348     if (GetVR() != "DS") // never trust a user !
00349        return false;    
00350        
00351     Util::Tokenize ( GetString().c_str(), tokens, "\\" );
00352         
00353     int nbValues= tokens.size();
00354     if (nbValues == 0)
00355        return false;
00356                
00357     for (int loop=0; loop<nbValues; loop++) 
00358        valueVector.push_back(atof(tokens[loop].c_str()));
00359     
00360     return true;  
00361  }
00362  
00367 void DataEntry::SetString(std::string const &value)
00368 {
00369    DeleteBinArea();
00370    const VRKey &vr = GetVR();
00371    if ( vr == "US" || vr == "SS" )
00372    {
00373       std::vector<std::string> tokens;
00374       Util::Tokenize (value, tokens, "\\");
00375       SetLength(tokens.size()*sizeof(uint16_t));
00376       NewBinArea();
00377 
00378       uint16_t *data = (uint16_t *)BinArea;
00379       for (unsigned int i=0; i<tokens.size();i++)
00380          data[i] = atoi(tokens[i].c_str());
00381       tokens.clear();
00382    }
00383    else if ( vr == "UL" || vr == "SL" )
00384    {
00385       std::vector<std::string> tokens;
00386       Util::Tokenize (value, tokens, "\\");
00387       SetLength(tokens.size()*sizeof(uint32_t));
00388       NewBinArea();
00389 
00390       uint32_t *data = (uint32_t *)BinArea;
00391       for (unsigned int i=0; i<tokens.size();i++)
00392          data[i] = atoi(tokens[i].c_str());
00393       tokens.clear();
00394    }
00395    else if ( vr == "FL" )
00396    {
00397       std::vector<std::string> tokens;
00398       Util::Tokenize (value, tokens, "\\");
00399       SetLength(tokens.size()*sizeof(float));
00400       NewBinArea();
00401 
00402       float *data = (float *)BinArea;
00403       for (unsigned int i=0; i<tokens.size();i++)
00404          data[i] = (float)atof(tokens[i].c_str());
00405       tokens.clear();
00406    }
00407    else if ( vr == "FD" )
00408    {
00409       std::vector<std::string> tokens;
00410       Util::Tokenize (value, tokens, "\\");
00411       SetLength(tokens.size()*sizeof(double));
00412       NewBinArea();
00413 
00414       double *data = (double *)BinArea;
00415       for (unsigned int i=0; i<tokens.size();i++)
00416          data[i] = atof(tokens[i].c_str());
00417       tokens.clear();
00418    }
00419    else
00420    {      
00421       size_t l =  value.size();    
00422       SetLength(l + l%2);
00423       NewBinArea();
00424       memcpy(BinArea, value.c_str(), l);
00425       if (l%2) // padded with blank except for UI
00426          if ( vr == "UI" ) 
00427             BinArea[l] = '\0';
00428          else
00429             BinArea[l] = ' ';                
00430    }
00431    State = STATE_LOADED;
00432 }
00436 std::string const &DataEntry::GetString() const
00437 {
00438   static std::ostringstream s;
00439   const VRKey &vr = GetVR();
00440   s.str("");
00441   
00442   if (!StrArea)
00443      StrArea = new std::string();
00444   else 
00445      *StrArea="";
00446 
00447   if( !BinArea )
00448      return *StrArea;
00449       // When short integer(s) are stored, convert the following (n * 2) characters
00450   // as a displayable string, the values being separated by a back-slash
00451   if( vr == "US" )
00452   {
00453      uint16_t *data=(uint16_t *)BinArea;
00454      for (unsigned int i=0; i < GetValueCount(); i++)
00455      {
00456         if( i!=0 )
00457            s << '\\';
00458         s << data[i];
00459      }
00460      *StrArea=s.str();
00461   }
00462   else if (vr == "SS" )
00463   {
00464      int16_t *data=(int16_t *)BinArea;
00465      for (unsigned int i=0; i < GetValueCount(); i++)
00466      {
00467         if( i!=0 )
00468            s << '\\';
00469         s << data[i];
00470      }
00471      *StrArea=s.str();
00472   }      // See above comment on multiple short integers (mutatis mutandis).
00473   else if( vr == "UL" )
00474   {
00475      uint32_t *data=(uint32_t *)BinArea;
00476      for (unsigned int i=0; i < GetValueCount(); i++)
00477      {
00478         if( i!=0 )
00479            s << '\\';
00480         s << data[i];
00481      }
00482      *StrArea=s.str();
00483   }
00484   else if( vr == "SL" )
00485   {
00486      int32_t *data=(int32_t *)BinArea;
00487      for (unsigned int i=0; i < GetValueCount(); i++)
00488      {
00489         if( i!=0 )
00490            s << '\\';
00491         s << data[i];
00492      }
00493      *StrArea=s.str();
00494   }    else if( vr == "FL" )
00495   {
00496      float *data=(float *)BinArea;
00497      for (unsigned int i=0; i < GetValueCount(); i++)
00498      {
00499         if( i!=0 )
00500            s << '\\';
00501         s << data[i];
00502      }
00503      *StrArea=s.str();
00504   }
00505   else if( vr == "FD" )
00506   {
00507      double *data=(double *)BinArea;
00508      for (unsigned int i=0; i < GetValueCount(); i++)
00509      {
00510         if( i!=0 )
00511            s << '\\';
00512         s << data[i];
00513      }
00514      *StrArea=s.str();
00515   }
00516   else
00517   {
00518      StrArea->append((const char *)BinArea,GetLength());
00519      // to avoid gdcm to propagate oddities in lengthes
00520      if ( GetLength()%2)
00521         StrArea->append(" ",1);   }
00522   return *StrArea;
00523 }
00524 
00525 
00531 void DataEntry::Copy(DocEntry *doc)
00532 {
00533    DocEntry::Copy(doc);
00534 
00535    DataEntry *entry = dynamic_cast<DataEntry *>(doc);
00536    if ( entry )
00537    {
00538       State = entry->State;
00539       Flag = entry->Flag;
00540       CopyBinArea(entry->BinArea,entry->GetLength());      
00541    }
00542 }
00543 
00549 void DataEntry::WriteContent(std::ofstream *fp, FileType filetype, 
00550                                                       bool insideMetaElements)
00551 { 
00552    // writes the 'common part'
00553    DocEntry::WriteContent(fp, filetype, insideMetaElements);
00554 
00555    if ( GetGroup() == 0xfffe )
00556    {
00557       return; //delimitors have NO value
00558    }
00559    
00560    // --> We only deal with Little Endian writting.
00561    // --> forget Big Endian Transfer Syntax writting!
00562    //     Next DICOM version will give it up ...
00563  
00564    // WARNING - For Implicit VR private element,
00565    //           we have *no choice* but considering them as
00566    //           something like 'OB' values.
00567    //           we rewrite them as we found them on disc.
00568    //           Some trouble will occur if element was 
00569    //           *actually* OW, if image was produced 
00570    //           on Big endian based processor, read and writen 
00571    //           on Little endian based processor
00572    //           and, later on, somebody needs
00573    //           this 'OW' Implicit VR private element (?!?)
00574    //           (Same stuff, mutatis mutandis, for Little/Big)
00575  
00576    // 8/16 bits Pixels problem should be solved automatiquely,
00577    // since we ensure the VR (OB vs OW) is conform to Pixel size.
00578         
00579    uint8_t *data = BinArea; //safe notation
00580    size_t l = GetLength(); 
00581 //   gdcmDebugMacro("in DataEntry::WriteContent " << GetKey() << " AtomicLength: "
00582 //              << Global::GetVR()->GetAtomicElementLength(this->GetVR() ) // << " BinArea in :" << &BinArea
00583 //             );
00584    if (BinArea) // the binArea was *actually* loaded
00585    {
00586 #if defined(GDCM_WORDS_BIGENDIAN) || defined(GDCM_FORCE_BIGENDIAN_EMULATION)
00587       unsigned short vrLgth = 
00588                         Global::GetVR()->GetAtomicElementLength(this->GetVR());
00589       unsigned int i;
00590       switch(vrLgth)
00591       {
00592          case 1:
00593          {
00594             binary_write (*fp, data, l );           
00595             break;
00596          }     
00597          case 2:
00598          {
00599             uint16_t *data16 = (uint16_t *)data;
00600             for(i=0;i<l/vrLgth;i++)
00601                binary_write( *fp, data16[i]);
00602             break;
00603          }
00604          case 4:
00605          {
00606             uint32_t *data32 = (uint32_t *)data;
00607             for(i=0;i<l/vrLgth;i++)
00608                binary_write( *fp, data32[i]);
00609             break;
00610          }
00611          case 8:
00612          {
00613             double *data64 = (double *)data;
00614             for(i=0;i<l/vrLgth;i++)
00615                binary_write( *fp, data64[i]);
00616             break;
00617          }
00618       }
00619 #else
00620    binary_write (*fp, data, l );
00621 #endif //GDCM_WORDS_BIGENDIAN
00622 
00623    }
00624    else
00625    {
00626       // nothing was loaded, but we need to skip space on disc     
00627       if (l != 0)
00628       {
00629       //  --> WARNING : nothing is written; 
00630       //  --> the initial data (on the the source image) is lost
00631       //  --> user is *not* informed !      
00632          gdcmDebugMacro ("Nothing was loaded, but we need to skip space on disc. "
00633                       << "Length =" << l << " for " << GetKey() );   
00634          fp->seekp(l, std::ios::cur); // At Write time, for unloaded elems
00635       }
00636    }
00637    // to avoid gdcm to propagate oddities
00638    // (length was already modified)  
00639    if (l%2)
00640       fp->seekp(1, std::ios::cur);  // At Write time, for non even length elems
00641 }
00642 
00647 uint32_t DataEntry::ComputeFullLength()
00648 {
00649    return GetFullLength();
00650 }
00651 
00652 //-----------------------------------------------------------------------------
00653 // Protected
00656 void DataEntry::NewBinArea( )
00657 {
00658    DeleteBinArea();
00659    if( GetLength() > 0 )
00660       BinArea = new uint8_t[GetLength()];
00661    SelfArea = true;
00662 }
00665 void DataEntry::DeleteBinArea(void)
00666 {
00667    if (BinArea && SelfArea)
00668    {
00669       delete[] BinArea;
00670       BinArea = NULL;
00671    }
00672    if (StrArea)
00673    {
00674       delete StrArea;
00675       StrArea = 0;
00676    }
00677 }
00678 
00679 //-----------------------------------------------------------------------------
00680 // Private
00681 
00682 //-----------------------------------------------------------------------------
00683 // Print
00689 void DataEntry::Print(std::ostream &os, std::string const & )
00690 {
00691    os << "D ";
00692    DocEntry::Print(os);
00693 
00694    uint16_t g = GetGroup();
00695    if (g == 0xfffe) // delimiters have NO value
00696    {          
00697       return; // just to avoid identing all the remaining code 
00698    }
00699 
00700    std::ostringstream s;
00701    TSAtr v;
00702 
00703    if( BinArea )
00704    {
00705       v = GetString();
00706       const VRKey &vr = GetVR();
00707 
00708       if( vr == "US" || vr == "SS" || vr == "UL" || vr == "SL" 
00709        || vr == "FL" || vr == "FD")
00710          s << " [" << GetString() << "]";
00711       else
00712       { 
00713          if(Global::GetVR()->IsVROfStringRepresentable(vr))
00714          {
00715             // replace non printable characters by '.'
00716             std::string cleanString = Util::CreateCleanString(v);
00717             if ( cleanString.length() <= GetMaxSizePrintEntry()
00718               || PrintLevel >= 3
00719               || IsNotLoaded() )
00720            // FIXME : when IsNotLoaded(), you create a Clean String ?!?
00721            // FIXME : PrintLevel<2 *does* print the values 
00722            //        (3 is only for extra offsets printing)
00723            // What do you wanted to do ? JPR
00724             {
00725                s << " [" << cleanString << "]";
00726             }
00727             else
00728             {
00729                s << " [GDCM_NAME_SPACE::too long for print (" << cleanString.length() << ") ]";
00730             }
00731          }
00732          else
00733          {
00734             // A lot of Private elements (with no VR) contain actually 
00735             // only printable characters;
00736             // Let's deal with them as is they were VR std::string representable
00737     
00738             if ( Util::IsCleanArea( GetBinArea(), GetLength()  ) )
00739             {
00740                // FIXME : since the 'Area' *is* clean, just use
00741                //         a 'CreateString' method, to save CPU time.
00742                std::string cleanString = 
00743                      Util::CreateCleanString( BinArea,GetLength()  );
00744                s << " [" << cleanString << "]";
00745             }
00746             else
00747             {
00748                s << " [" << GDCM_BINLOADED << ";"
00749                << "length = " << GetLength() << "]";
00750             }
00751          }
00752       }
00753    }
00754    else
00755    {
00756       if( IsNotLoaded() )
00757          s << " [" << GDCM_NOTLOADED << "]";
00758       else if( IsUnfound() )
00759          s << " [" << GDCM_UNFOUND << "]";
00760       else if( IsUnread() )
00761          s << " [" << GDCM_UNREAD << "]";
00762       else if ( GetLength() == 0 )
00763          s << " []";
00764    }
00765 
00766    if( IsPixelData() )
00767       s << " (" << GDCM_PIXELDATA << ")";
00768 
00769    // Display the UID value (instead of displaying only the rough code)
00770    // First 'clean' trailing character (space or zero) 
00771    if(BinArea)
00772    {
00773       const uint16_t &gr = GetGroup();
00774       const uint16_t &elt = GetElement();
00775       TS *ts = Global::GetTS();
00776 
00777       if (gr == 0x0002)
00778       {
00779          // Any more to be displayed ?
00780          if ( elt == 0x0010 || elt == 0x0002 )
00781          {
00782             if ( v.length() != 0 )  // for brain damaged headers
00783             {
00784                if ( ! isdigit((unsigned char)v[v.length()-1]) )
00785                {
00786                   v.erase(v.length()-1, 1);
00787                }
00788             }
00789             s << "  ==>\t[" << ts->GetValue(v) << "]";
00790          }
00791       }
00792       else if (gr == 0x0008)
00793       {
00794          if ( elt == 0x0016 || elt == 0x1150 )
00795          {
00796             if ( v.length() != 0 )  // for brain damaged headers
00797             {
00798                if ( ! isdigit((unsigned char)v[v.length()-1]) )
00799                {
00800                   v.erase(v.length()-1, 1);
00801                }
00802             }
00803             s << "  ==>\t[" << ts->GetValue(v) << "]";
00804          }
00805       }
00806       else if (gr == 0x0004)
00807       {
00808          if ( elt == 0x1510 || elt == 0x1512  )
00809          {
00810             if ( v.length() != 0 )  // for brain damaged headers  
00811             {
00812                if ( ! isdigit((unsigned char)v[v.length()-1]) )
00813                {
00814                   v.erase(v.length()-1, 1);  
00815                }
00816             }
00817             s << "  ==>\t[" << ts->GetValue(v) << "]";
00818          }
00819       }
00820    }
00821 
00822    os << s.str();
00823 }
00824 
00825 //-----------------------------------------------------------------------------
00826 } // end namespace gdcm
00827 

Generated on Fri Aug 24 12:59:29 2007 for gdcm by  doxygen 1.4.6