Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

gdcmParser Class Reference

#include <gdcmParser.h>

Inheritance diagram for gdcmParser:

gdcmDicomDir gdcmHeader gdcmHeaderHelper List of all members.

Public Member Functions

 gdcmParser (bool exception_on_error=false)
 gdcmParser (const char *filename, bool exception_on_error=false, bool enable_sequences=false, bool ignore_shadow=false)
virtual ~gdcmParser (void)
 Canonical destructor.

void SetPrintLevel (int level)
 Sets the print level for the Dicom Header.

virtual void Print (std::ostream &os=std::cout)
virtual void PrintEntry (std::ostream &os=std::cout)
 Prints the Header Entries (Dicom Elements) both from the H Table and the chained list.

virtual void PrintPubDict (std::ostream &os=std::cout)
 Prints The Dict Entries of THE public Dicom Dictionnry.

virtual void PrintShaDict (std::ostream &os=std::cout)
 Prints The Dict Entries of THE shadow Dicom Dictionnry.

std::string GetFileName (void)
gdcmDictGetPubDict (void)
 Get the public dictionary used.

gdcmDictGetShaDict (void)
 Get the shadow dictionary used.

bool SetShaDict (gdcmDict *dict)
 Set the shadow dictionary used.

bool SetShaDict (DictKey dictName)
 Set the shadow dictionary used.

virtual bool IsReadable (void)
 This predicate, based on hopefully reasonable heuristics, decides whether or not the current gdcmParser was properly parsed and contains the mandatory information for being considered as a well formed and usable Dicom/Acr File.

bool IsImplicitVRLittleEndianTransferSyntax (void)
 Determines if the Transfer Syntax was already encountered and if it corresponds to a ImplicitVRLittleEndian one.

bool IsExplicitVRLittleEndianTransferSyntax (void)
 Determines if the Transfer Syntax was already encountered and if it corresponds to a ExplicitVRLittleEndian one.

bool IsDeflatedExplicitVRLittleEndianTransferSyntax (void)
 Determines if the Transfer Syntax was already encountered and if it corresponds to a DeflatedExplicitVRLittleEndian one.

bool IsExplicitVRBigEndianTransferSyntax (void)
 Determines if the Transfer Syntax was already encountered and if it corresponds to a Explicit VR Big Endian one.

FileType GetFileType (void)
 returns the File Type (ACR, ACR_LIBIDO, ExplicitVR, ImplicitVR, Unknown)

TagHeaderEntryHTGetEntry (void)
 returns a ref to the Dicom Header H table (multimap) return the Dicom Header H table

ListTagGetListEntry (void)
 returns a ref to the Dicom Header chained list return the Dicom Header chained list

FILE * OpenFile (bool exception_on_error=false) throw (gdcmFileError)
 opens the file

bool CloseFile (void)
 closes the file

virtual bool Write (FILE *, FileType)
bool ReplaceOrCreateByNumber (std::string Value, guint16 Group, guint16 Elem)
 Modifies the value of a given Header Entry (Dicom Element) if it exists; Creates it with the given value if it doesn't.

bool ReplaceOrCreateByNumber (char *Value, guint16 Group, guint16 Elem)
 Modifies the value of a given Header Entry (Dicom Element) if it exists; Creates it with the given value if it doesn't.

bool ReplaceIfExistByNumber (char *Value, guint16 Group, guint16 Elem)
 Set a new value if the invoked element exists Seems to be useless !!!

int GetSwapCode (void)
guint16 GetGrPixel (void)
guint16 GetNumPixel (void)
guint16 SwapShort (guint16)
 Swaps the bytes so they agree with the processor order.

guint32 SwapLong (guint32)
 Swaps back the bytes of 4-byte long integer accordingly to processor order.

guint16 UnswapShort (guint16)
 Unswaps the bytes so they agree with the processor order.

guint32 UnswapLong (guint32)
 Unswaps back the bytes of 4-byte long integer accordingly to processor order.


Protected Member Functions

int CheckIfEntryExistByNumber (guint16 Group, guint16 Elem)
 Checks if a given Dicom Element exists within the H table.

virtual std::string GetEntryByName (std::string tagName)
 Searches within Header Entries (Dicom Elements) parsed with the public and private dictionaries for the element value of a given tag.

virtual std::string GetEntryVRByName (std::string tagName)
 Searches within Header Entries (Dicom Elements) parsed with the public and private dictionaries for the element value representation of a given tag.

virtual std::string GetEntryByNumber (guint16 group, guint16 element)
 Searches within Header Entries (Dicom Elements) parsed with the public and private dictionaries for the element value representation of a given tag.

virtual std::string GetEntryVRByNumber (guint16 group, guint16 element)
 Searches within Header Entries (Dicom Elements) parsed with the public and private dictionaries for the element value representation of a given tag..

virtual bool SetEntryByName (std::string content, std::string tagName)
 Sets the value (string) of the Header Entry (Dicom Element).

virtual bool SetEntryByNumber (std::string content, guint16 group, guint16 element)
 Accesses an existing gdcmHeaderEntry (i.e. a Dicom Element) through it's (group, element) and modifies it's content with the given value.

virtual bool SetEntryLengthByNumber (guint32 length, guint16 group, guint16 element)
 Accesses an existing gdcmHeaderEntry (i.e. a Dicom Element) in the PubHeaderEntrySet of this instance through it's (group, element) and modifies it's length with the given value.

virtual size_t GetEntryOffsetByNumber (guint16 Group, guint16 Elem)
 Gets (from Header) the offset of a 'non string' element value (LoadElementValues has already be executed).

virtual void * GetEntryVoidAreaByNumber (guint16 Group, guint16 Elem)
 Gets (from Header) a 'non string' element value (LoadElementValues has already be executed).

virtual void * LoadEntryVoidArea (guint16 Group, guint16 Element)
 Loads (from disk) the element content when a string is not suitable.

virtual bool SetEntryVoidAreaByNumber (void *a, guint16 Group, guint16 Elem)
 Sets a 'non string' value to a given Dicom Element.

virtual void UpdateShaEntries (void)
 Update the entries with the shadow dictionary. Only non even entries are analyzed.

gdcmHeaderEntryGetHeaderEntryByNumber (guint16 group, guint16 element)
 retrieves a Dicom Element (the first one) using (group, element)

gdcmHeaderEntryGetHeaderEntryByName (std::string Name)
 Searches within the Header Entries for a Dicom Element of a given tag.

IterHT GetHeaderEntrySameNumber (guint16 group, guint16 element)
 retrieves the Dicom Elements (all of them) using (group, element)

void LoadHeaderEntrySafe (gdcmHeaderEntry *)
 Loads the element while preserving the current underlying file position indicator as opposed to to LoadHeaderEntry that modifies it.

void UpdateGroupLength (bool SkipSequence=false, FileType type=ImplicitVR)
 Re-computes the length of a ACR-NEMA/Dicom group from a DcmHeader.

void WriteEntries (FILE *_fp, FileType type)
 writes on disc according to the requested format (ACR-NEMA, ExplicitVR, ImplicitVR) the image


Protected Attributes

FILE * fp
FileType filetype
TagHeaderEntryHT tagHT
ListTag listEntries
int enableSequences
int printLevel
guint16 GrPixel
guint16 NumPixel
int countGrPixel

Static Protected Attributes

const unsigned int HEADER_LENGTH_TO_READ = 256
const unsigned int MAX_SIZE_LOAD_ELEMENT_VALUE = 4096
const unsigned int MAX_SIZE_PRINT_ELEMENT_VALUE = 64

Private Member Functions

bool ParseHeader (bool exception_on_error=false) throw (gdcmFormatError)
 Parses the header of the file but WITHOUT loading element values.

void LoadHeaderEntries (void)
 Loads the element values of all the Header Entries pointed in the public Chained List.

void LoadHeaderEntry (gdcmHeaderEntry *)
 Loads the element content if its length doesn't exceed the value specified with gdcmParser::SetMaxSizeLoadEntry().

void AddHeaderEntry (gdcmHeaderEntry *)
 add a new Dicom Element pointer to the H Table and to the chained List

void FindHeaderEntryLength (gdcmHeaderEntry *)
void FindHeaderEntryVR (gdcmHeaderEntry *)
 Find the Value Representation of the current Dicom Element.

bool CheckHeaderEntryVR (gdcmHeaderEntry *, VRKey)
 Check the correspondance between the VR of the header entry and the taken VR. If they are different, the header entry is updated with the new VR.

std::string GetHeaderEntryValue (gdcmHeaderEntry *)
 Get the transformed value of the header entry. The VR value is used to define the transformation to operate on the value.

std::string GetHeaderEntryUnvalue (gdcmHeaderEntry *)
 Get the reverse transformed value of the header entry. The VR value is used to define the reverse transformation to operate on the value.

void SkipHeaderEntry (gdcmHeaderEntry *)
 Skip a given Header Entry.

void FixHeaderEntryFoundLength (gdcmHeaderEntry *, guint32)
 When the length of an element value is obviously wrong (because the parser went Jabberwocky) one can hope improving things by applying this heuristic.

bool IsHeaderEntryAnInteger (gdcmHeaderEntry *)
 Apply some heuristics to predict wether the considered element value contains/represents an integer or not.

guint32 FindHeaderEntryLengthOB (void)
guint16 ReadInt16 (void)
 Reads a supposed to be 16 Bits integer (swaps it depending on processor endianity).

guint32 ReadInt32 (void)
 Reads a supposed to be 32 Bits integer (swaps it depending on processor endianity).

void SkipBytes (guint32)
void Initialise (void)
bool CheckSwap (void)
 Discover what the swap code is (among little endian, big endian, bad little endian, bad big endian). sw is set.

void SwitchSwapToBigEndian (void)
void SetMaxSizeLoadEntry (long)
 during parsing, Header Elements too long are not loaded in memory

void SetMaxSizePrintEntry (long)
 Header Elements too long will not be printed.

gdcmDictEntryGetDictEntryByName (std::string Name)
 Searches both the public and the shadow dictionary (when they exist) for the presence of the DictEntry with given name. The public dictionary has precedence on the shadow one.

gdcmDictEntryGetDictEntryByNumber (guint16, guint16)
 Searches both the public and the shadow dictionary (when they exist) for the presence of the DictEntry with given group and element. The public dictionary has precedence on the shadow one.

gdcmDictEntryNewVirtualDictEntry (guint16 group, guint16 element, std::string vr="unkn", std::string fourth="unkn", std::string name="unkn")
 Request a new virtual dict entry to the dict set.

gdcmDictEntryNewVirtualDictEntry (gdcmHeaderEntry *)
gdcmHeaderEntryReadNextHeaderEntry (void)
 Read the next tag but WITHOUT loading it's value.

gdcmHeaderEntryNewHeaderEntryByNumber (guint16 group, guint16 element)
 Build a new Element Value from all the low level arguments. Check for existence of dictionary entry, and build a default one when absent.

gdcmHeaderEntryNewHeaderEntryByName (std::string Name)
 Build a new Element Value from all the low level arguments. Check for existence of dictionary entry, and build a default one when absent.

guint32 GenerateFreeTagKeyInGroup (guint16 group)
 Small utility function that creates a new manually crafted (as opposed as read from the file) gdcmHeaderEntry with user specified name and adds it to the public tag hash table. Generate a free TagKey i.e. a TagKey that is not present in the TagHt dictionary.


Private Attributes

std::string filename
gdcmDictRefPubDict
gdcmDictRefShaDict
int wasUpdated
int ignoreShadow
int sw
guint32 MaxSizeLoadEntry
guint32 MaxSizePrintEntry

Constructor & Destructor Documentation

gdcmParser::gdcmParser bool  exception_on_error = false  ) 
 

Parameters:
exception_on_error 

Definition at line 121 of file gdcmParser.cxx.

References enableSequences, Initialise(), MAX_SIZE_LOAD_ELEMENT_VALUE, SetMaxSizeLoadEntry(), and wasUpdated.

00121                                               {
00122    enableSequences=0;
00123 
00124    SetMaxSizeLoadEntry(MAX_SIZE_LOAD_ELEMENT_VALUE);
00125    Initialise();
00126 
00127    wasUpdated = 0;  // will be set to 1 if user adds an entry
00128    printLevel = 1;  // 'Medium' print level by default
00129 }

gdcmParser::gdcmParser const char *  InFilename,
bool  exception_on_error = false,
bool  enable_sequences = false,
bool  ignore_shadow = false
 

Parameters:
InFilename 
exception_on_error 
enable_sequences = true to allow the header to be parsed *inside* the SeQuences, when they have an actual length
ignore_shadow to allow skipping the shadow elements, to save memory space.
Warning:
The TRUE value for this param has to be used with a FALSE value for the 'enable_sequence' param. ('public elements' may be embedded in 'shadow Sequences')

Definition at line 94 of file gdcmParser.cxx.

References CloseFile(), enableSequences, ignoreShadow, Initialise(), LoadHeaderEntries(), MAX_SIZE_LOAD_ELEMENT_VALUE, OpenFile(), ParseHeader(), SetMaxSizeLoadEntry(), and wasUpdated.

00097                                            {
00098    enableSequences=enable_sequences;
00099    ignoreShadow   =ignore_shadow;
00100    
00101    SetMaxSizeLoadEntry(MAX_SIZE_LOAD_ELEMENT_VALUE);
00102    filename = InFilename;
00103    Initialise();
00104 
00105    if ( !OpenFile(exception_on_error))
00106       return;
00107    if (ParseHeader()) {
00108      LoadHeaderEntries();
00109    }
00110    CloseFile();
00111 
00112    wasUpdated = 0;  // will be set to 1 if user adds an entry
00113    printLevel = 1;  // 'Medium' print level by default
00114 }

gdcmParser::~gdcmParser void   )  [virtual]
 

Canonical destructor.

Definition at line 135 of file gdcmParser.cxx.

References RefPubDict, and RefShaDict.

00135                              {
00136    RefPubDict = NULL;
00137    RefShaDict = NULL;
00138 }


Member Function Documentation

void gdcmParser::AddHeaderEntry gdcmHeaderEntry newHeaderEntry  )  [private]
 

add a new Dicom Element pointer to the H Table and to the chained List

Warning:
push_bash in listEntries ONLY during ParseHeader

Todo:
something to allow further Elements addition, (at their right place in the chained list) when position to be taken care of
Parameters:
newHeaderEntry 

Definition at line 1404 of file gdcmParser.cxx.

References gdcmHeaderEntry::GetKey(), listEntries, PairHT, tagHT, and wasUpdated.

Referenced by ReplaceOrCreateByNumber(), and UpdateGroupLength().

01404                                                                {
01405    tagHT.insert( PairHT( newHeaderEntry->GetKey(),newHeaderEntry) );
01406    listEntries.push_back(newHeaderEntry); 
01407    wasUpdated = 1;
01408 }

bool gdcmParser::CheckHeaderEntryVR gdcmHeaderEntry Entry,
VRKey  vr
[private]
 

Check the correspondance between the VR of the header entry and the taken VR. If they are different, the header entry is updated with the new VR.

Parameters:
Entry Header Entry to check
vr Dicom Value Representation
Returns:
false if the VR is incorrect of if the VR isn't referenced otherwise, it returns true

Definition at line 1576 of file gdcmParser.cxx.

References gdcmVR::Count(), dbg, gdcmHeaderEntry::GetElement(), gdcmHeaderEntry::GetGroup(), gdcmHeaderEntry::GetName(), gdcmHeaderEntry::GetVR(), gdcmGlobal::GetVR(), gdcmHeaderEntry::IsVRUnknown(), NewVirtualDictEntry(), gdcmHeaderEntry::SetDictEntry(), gdcmHeaderEntry::SetVR(), gdcmDebug::Verbose(), and VRKey.

Referenced by FindHeaderEntryVR(), and UpdateShaEntries().

01577 {
01578    char msg[100]; // for sprintf
01579    bool RealExplicit = true;
01580 
01581    // Assume we are reading a falsely explicit VR file i.e. we reached
01582    // a tag where we expect reading a VR but are in fact we read the
01583    // first to bytes of the length. Then we will interogate (through find)
01584    // the dicom_vr dictionary with oddities like "\004\0" which crashes
01585    // both GCC and VC++ implementations of the STL map. Hence when the
01586    // expected VR read happens to be non-ascii characters we consider
01587    // we hit falsely explicit VR tag.
01588 
01589    if ( (!isalpha(vr[0])) && (!isalpha(vr[1])) )
01590       RealExplicit = false;
01591 
01592    // CLEANME searching the dicom_vr at each occurence is expensive.
01593    // PostPone this test in an optional integrity check at the end
01594    // of parsing or only in debug mode.
01595    if ( RealExplicit && !gdcmGlobal::GetVR()->Count(vr) )
01596       RealExplicit= false;
01597 
01598    if ( !RealExplicit ) 
01599    {
01600       // We thought this was explicit VR, but we end up with an
01601       // implicit VR tag. Let's backtrack.   
01602       sprintf(msg,"Falsely explicit vr file (%04x,%04x)\n", 
01603                    Entry->GetGroup(),Entry->GetElement());
01604       dbg.Verbose(1, "gdcmParser::FindVR: ",msg);
01605       if (Entry->GetGroup()%2 && Entry->GetElement() == 0x0000) { // Group length is UL !
01606          gdcmDictEntry* NewEntry = NewVirtualDictEntry(
01607                                    Entry->GetGroup(),Entry->GetElement(),
01608                                    "UL","FIXME","Group Length");
01609          Entry->SetDictEntry(NewEntry);                                                                       
01610       }
01611       return(false);
01612    }
01613 
01614    if ( Entry->IsVRUnknown() ) 
01615    {
01616       // When not a dictionary entry, we can safely overwrite the VR.
01617       if (Entry->GetElement() == 0x0000) { // Group length is UL !
01618          Entry->SetVR("UL");
01619       } else {
01620          Entry->SetVR(vr);
01621       }
01622    }
01623    else if ( Entry->GetVR() != vr ) 
01624    {
01625       // The VR present in the file and the dictionary disagree. We assume
01626       // the file writer knew best and use the VR of the file. Since it would
01627       // be unwise to overwrite the VR of a dictionary (since it would
01628       // compromise it's next user), we need to clone the actual DictEntry
01629       // and change the VR for the read one.
01630       gdcmDictEntry* NewEntry = NewVirtualDictEntry(
01631                                  Entry->GetGroup(),Entry->GetElement(),
01632                                  vr,"FIXME",Entry->GetName());
01633       Entry->SetDictEntry(NewEntry);
01634    }
01635    return(true); 
01636 }

int gdcmParser::CheckIfEntryExistByNumber guint16  group,
guint16  element
[protected]
 

Checks if a given Dicom Element exists within the H table.

Parameters:
group Group number of the searched Dicom Element
element Element number of the searched Dicom Element
Returns:
number of occurences

Definition at line 509 of file gdcmParser.cxx.

References tagHT, and gdcmDictEntry::TranslateToKey().

Referenced by ReplaceOrCreateByNumber().

00509                                                                          {
00510         std::string key = gdcmDictEntry::TranslateToKey(group, element );
00511         return (tagHT.count(key));
00512 }

bool gdcmParser::CheckSwap void   )  [private]
 

Discover what the swap code is (among little endian, big endian, bad little endian, bad big endian). sw is set.

Returns:
false when we are absolutely sure it's neither ACR-NEMA nor DICOM true when we hope ours assuptions are OK

Definition at line 2003 of file gdcmParser.cxx.

References ACR, dbg, ExplicitVR, filetype, fp, HEADER_LENGTH_TO_READ, sw, Unknown, and gdcmDebug::Verbose().

02003                            {
02004 
02005    // The only guaranted way of finding the swap code is to find a
02006    // group tag since we know it's length has to be of four bytes i.e.
02007    // 0x00000004. Finding the swap code in then straigthforward. Trouble
02008    // occurs when we can't find such group...
02009    
02010    guint32  x=4;  // x : for ntohs
02011    bool net2host; // true when HostByteOrder is the same as NetworkByteOrder
02012    guint32  s32;
02013    guint16  s16;
02014        
02015    int lgrLue;
02016    char *entCur;
02017    char deb[HEADER_LENGTH_TO_READ];
02018     
02019    // First, compare HostByteOrder and NetworkByteOrder in order to
02020    // determine if we shall need to swap bytes (i.e. the Endian type).
02021    if (x==ntohs(x))
02022       net2host = true;
02023    else
02024       net2host = false; 
02025          
02026    // The easiest case is the one of a DICOM header, since it possesses a
02027    // file preamble where it suffice to look for the string "DICM".
02028    lgrLue = fread(deb, 1, HEADER_LENGTH_TO_READ, fp);
02029    
02030    entCur = deb + 128;
02031    if(memcmp(entCur, "DICM", (size_t)4) == 0) {
02032       dbg.Verbose(1, "gdcmParser::CheckSwap:", "looks like DICOM Version3");
02033       
02034       // Next, determine the value representation (VR). Let's skip to the
02035       // first element (0002, 0000) and check there if we find "UL" 
02036       // - or "OB" if the 1st one is (0002,0001) -,
02037       // in which case we (almost) know it is explicit VR.
02038       // WARNING: if it happens to be implicit VR then what we will read
02039       // is the length of the group. If this ascii representation of this
02040       // length happens to be "UL" then we shall believe it is explicit VR.
02041       // FIXME: in order to fix the above warning, we could read the next
02042       // element value (or a couple of elements values) in order to make
02043       // sure we are not commiting a big mistake.
02044       // We need to skip :
02045       // * the 128 bytes of File Preamble (often padded with zeroes),
02046       // * the 4 bytes of "DICM" string,
02047       // * the 4 bytes of the first tag (0002, 0000),or (0002, 0001)
02048       // i.e. a total of  136 bytes.
02049       entCur = deb + 136;
02050      
02051       // FIXME : FIXME:
02052       // Sometimes (see : gdcmData/icone.dcm) group 0x0002 *is* Explicit VR,
02053       // but elem 0002,0010 (Transfert Syntax) tells us the file is *Implicit* VR.
02054       // -and it is !- 
02055       
02056       if( (memcmp(entCur, "UL", (size_t)2) == 0) ||
02057           (memcmp(entCur, "OB", (size_t)2) == 0) ||
02058           (memcmp(entCur, "UI", (size_t)2) == 0) ||       
02059           (memcmp(entCur, "CS", (size_t)2) == 0) )  // CS, to remove later
02060                                                     // when Write DCM *adds*
02061       // FIXME
02062       // Use gdcmParser::dicom_vr to test all the possibilities
02063       // instead of just checking for UL, OB and UI !?                                              // group 0000 
02064                                                      
02065       {
02066          filetype = ExplicitVR;
02067          dbg.Verbose(1, "gdcmParser::CheckSwap:",
02068                      "explicit Value Representation");
02069       } 
02070       else 
02071       {
02072          filetype = ImplicitVR;
02073          dbg.Verbose(1, "gdcmParser::CheckSwap:",
02074                      "not an explicit Value Representation");
02075       }
02076       
02077       if (net2host) 
02078       {
02079          sw = 4321;
02080          dbg.Verbose(1, "gdcmParser::CheckSwap:",
02081                         "HostByteOrder != NetworkByteOrder");
02082       } 
02083       else 
02084       {
02085          sw = 0;
02086          dbg.Verbose(1, "gdcmParser::CheckSwap:",
02087                         "HostByteOrder = NetworkByteOrder");
02088       }
02089       
02090       // Position the file position indicator at first tag (i.e.
02091       // after the file preamble and the "DICM" string).
02092       rewind(fp);
02093       fseek (fp, 132L, SEEK_SET);
02094       return true;
02095    } // End of DicomV3
02096 
02097    // Alas, this is not a DicomV3 file and whatever happens there is no file
02098    // preamble. We can reset the file position indicator to where the data
02099    // is (i.e. the beginning of the file).
02100    dbg.Verbose(1, "gdcmParser::CheckSwap:", "not a DICOM Version3 file");
02101    rewind(fp);
02102 
02103    // Our next best chance would be to be considering a 'clean' ACR/NEMA file.
02104    // By clean we mean that the length of the first tag is written down.
02105    // If this is the case and since the length of the first group HAS to be
02106    // four (bytes), then determining the proper swap code is straightforward.
02107 
02108    entCur = deb + 4;
02109    // We assume the array of char we are considering contains the binary
02110    // representation of a 32 bits integer. Hence the following dirty
02111    // trick :
02112    s32 = *((guint32 *)(entCur));
02113       
02114    switch (s32) {
02115       case 0x00040000 :
02116          sw = 3412;
02117          filetype = ACR;
02118          return true;
02119       case 0x04000000 :
02120          sw = 4321;
02121          filetype = ACR;
02122          return true;
02123       case 0x00000400 :
02124          sw = 2143;
02125          filetype = ACR;
02126          return true;
02127       case 0x00000004 :
02128          sw = 0;
02129          filetype = ACR;
02130          return true;
02131       default :
02132          
02133       // We are out of luck. It is not a DicomV3 nor a 'clean' ACR/NEMA file.
02134       // It is time for despaired wild guesses. 
02135       // So, let's check if this file wouldn't happen to be 'dirty' ACR/NEMA,
02136       //  i.e. the 'group length' element is not present :     
02137       
02138       //  check the supposed to be 'group number'
02139       //  0x0002 or 0x0004 or 0x0008
02140       //  to determine ' sw' value .
02141       //  Only 0 or 4321 will be possible 
02142       //  (no oportunity to check for the formerly well known
02143       //  ACR-NEMA 'Bad Big Endian' or 'Bad Little Endian' 
02144       //  if unsuccessfull (i.e. neither 0x0002 nor 0x0200 etc -4, 8-) 
02145       //  the file IS NOT ACR-NEMA nor DICOM V3
02146       //  Find a trick to tell it the caller...
02147       
02148       s16 = *((guint16 *)(deb));
02149       
02150       switch (s16) {
02151       case 0x0002 :
02152       case 0x0004 :
02153       case 0x0008 :      
02154          sw = 0;
02155          filetype = ACR;
02156          return true;
02157       case 0x0200 :
02158       case 0x0400 :
02159       case 0x0800 : 
02160          sw = 4321;
02161          filetype = ACR;
02162          return true;
02163       default :
02164          dbg.Verbose(0, "gdcmParser::CheckSwap:",
02165                      "ACR/NEMA unfound swap info (Really hopeless !)"); 
02166          filetype = Unknown;     
02167          return false;
02168       }
02169          
02170       // Then the only info we have is the net2host one.         
02171          //if (! net2host )
02172          //   sw = 0;
02173          //else
02174          //  sw = 4321;
02175          //return;                      
02176    }
02177 }

bool gdcmParser::CloseFile void   ) 
 

closes the file

Returns:
TRUE if the close was successfull

Definition at line 365 of file gdcmParser.cxx.

References fp.

Referenced by gdcmParser(), gdcmFile::ParsePixelData(), and gdcmFile::ReadPixelData().

00365                                {
00366   int closed = fclose(fp);
00367   fp = (FILE *)0;
00368   if (! closed)
00369      return false;
00370   return true;
00371 }

void gdcmParser::FindHeaderEntryLength gdcmHeaderEntry Entry  )  [private]
 

Parameters:
Entry Header Entry whose length of the value shall be loaded.
Returns:

Definition at line 1416 of file gdcmParser.cxx.

References dbg, ExplicitVR, filetype, FindHeaderEntryLengthOB(), FixHeaderEntryFoundLength(), fp, GDCM_DEBUG, GetDictEntryByNumber(), gdcmHeaderEntry::GetElement(), gdcmHeaderEntry::GetGroup(), gdcmHeaderEntry::GetVR(), GrPixel, IsExplicitVRBigEndianTransferSyntax(), gdcmHeaderEntry::IsImplicitVR(), NewVirtualDictEntry(), NumPixel, ReadInt16(), ReadInt32(), gdcmDebug::SetDebug(), gdcmHeaderEntry::SetDictEntry(), gdcmHeaderEntry::SetLength(), SwapShort(), SwitchSwapToBigEndian(), and gdcmDebug::Verbose().

Referenced by ReadNextHeaderEntry().

01416                                                                {
01417    guint16 element = Entry->GetElement();
01418    guint16 group   = Entry->GetGroup();
01419    std::string  vr = Entry->GetVR();
01420    guint16 length16;
01421    if( (element == NumPixel) && (group == GrPixel) ) 
01422    {
01423       dbg.SetDebug(GDCM_DEBUG);
01424       dbg.Verbose(2, "gdcmParser::FindLength: ",
01425                      "we reached (GrPixel,NumPixel)");
01426    }   
01427    
01428    if ( (filetype == ExplicitVR) && (! Entry->IsImplicitVR()) ) 
01429    {
01430       if ( (vr=="OB") || (vr=="OW") || (vr=="SQ") || (vr=="UN") ) 
01431       {
01432          // The following reserved two bytes (see PS 3.5-2001, section
01433          // 7.1.2 Data element structure with explicit vr p27) must be
01434          // skipped before proceeding on reading the length on 4 bytes.
01435          fseek(fp, 2L, SEEK_CUR);
01436          guint32 length32 = ReadInt32();
01437 
01438          if ( (vr == "OB") && (length32 == 0xffffffff) ) 
01439          {
01440             Entry->SetLength(FindHeaderEntryLengthOB());
01441             return;
01442          }
01443          FixHeaderEntryFoundLength(Entry, length32); 
01444          return;
01445       }
01446 
01447       // Length is encoded on 2 bytes.
01448       length16 = ReadInt16();
01449       
01450       // We can tell the current file is encoded in big endian (like
01451       // Data/US-RGB-8-epicard) when we find the "Transfer Syntax" tag
01452       // and it's value is the one of the encoding of a big endian file.
01453       // In order to deal with such big endian encoded files, we have
01454       // (at least) two strategies:
01455       // * when we load the "Transfer Syntax" tag with value of big endian
01456       //   encoding, we raise the proper flags. Then we wait for the end
01457       //   of the META group (0x0002) among which is "Transfer Syntax",
01458       //   before switching the swap code to big endian. We have to postpone
01459       //   the switching of the swap code since the META group is fully encoded
01460       //   in little endian, and big endian coding only starts at the next
01461       //   group. The corresponding code can be hard to analyse and adds
01462       //   many additional unnecessary tests for regular tags.
01463       // * the second strategy consists in waiting for trouble, that shall
01464       //   appear when we find the first group with big endian encoding. This
01465       //   is easy to detect since the length of a "Group Length" tag (the
01466       //   ones with zero as element number) has to be of 4 (0x0004). When we
01467       //   encounter 1024 (0x0400) chances are the encoding changed and we
01468       //   found a group with big endian encoding.
01469       // We shall use this second strategy. In order to make sure that we
01470       // can interpret the presence of an apparently big endian encoded
01471       // length of a "Group Length" without committing a big mistake, we
01472       // add an additional check: we look in the already parsed elements
01473       // for the presence of a "Transfer Syntax" whose value has to be "big
01474       // endian encoding". When this is the case, chances are we have got our
01475       // hands on a big endian encoded file: we switch the swap code to
01476       // big endian and proceed...
01477       if ( (element  == 0x0000) && (length16 == 0x0400) ) 
01478       {
01479          if ( ! IsExplicitVRBigEndianTransferSyntax() ) 
01480          {
01481             dbg.Verbose(0, "gdcmParser::FindLength", "not explicit VR");
01482             errno = 1;
01483             return;
01484          }
01485          length16 = 4;
01486          SwitchSwapToBigEndian();
01487          // Restore the unproperly loaded values i.e. the group, the element
01488          // and the dictionary entry depending on them.
01489          guint16 CorrectGroup   = SwapShort(Entry->GetGroup());
01490          guint16 CorrectElem    = SwapShort(Entry->GetElement());
01491          gdcmDictEntry * NewTag = GetDictEntryByNumber(CorrectGroup,
01492                                                        CorrectElem);
01493          if (!NewTag) 
01494          {
01495             // This correct tag is not in the dictionary. Create a new one.
01496             NewTag = NewVirtualDictEntry(CorrectGroup, CorrectElem);
01497          }
01498          // FIXME this can create a memory leaks on the old entry that be
01499          // left unreferenced.
01500          Entry->SetDictEntry(NewTag);
01501       }
01502        
01503       // Heuristic: well some files are really ill-formed.
01504       if ( length16 == 0xffff) 
01505       {
01506          length16 = 0;
01507          //dbg.Verbose(0, "gdcmParser::FindLength",
01508          //            "Erroneous element length fixed.");
01509          // Actually, length= 0xffff means that we deal with
01510          // Unknown Sequence Length 
01511       }
01512 
01513       FixHeaderEntryFoundLength(Entry, (guint32)length16);
01514       return;
01515    }
01516    else
01517    {
01518       // Either implicit VR or a non DICOM conformal (see not below) explicit
01519       // VR that ommited the VR of (at least) this element. Farts happen.
01520       // [Note: according to the part 5, PS 3.5-2001, section 7.1 p25
01521       // on Data elements "Implicit and Explicit VR Data Elements shall
01522       // not coexist in a Data Set and Data Sets nested within it".]
01523       // Length is on 4 bytes.
01524       FixHeaderEntryFoundLength(Entry, ReadInt32());
01525       return;
01526    }
01527 }

guint32 gdcmParser::FindHeaderEntryLengthOB void   )  [private]
 

Warning:
NOT end user intended method !
Returns:

Definition at line 1886 of file gdcmParser.cxx.

References dbg, fp, ReadInt16(), ReadInt32(), SkipBytes(), and gdcmDebug::Verbose().

Referenced by FindHeaderEntryLength().

01886                                                   {
01887    // See PS 3.5-2001, section A.4 p. 49 on encapsulation of encoded pixel data.
01888    guint16 g;
01889    guint16 n; 
01890    long PositionOnEntry = ftell(fp);
01891    bool FoundSequenceDelimiter = false;
01892    guint32 TotalLength = 0;
01893    guint32 ItemLength;
01894 
01895    while ( ! FoundSequenceDelimiter) 
01896    {
01897       g = ReadInt16();
01898       n = ReadInt16();   
01899       if (errno == 1)
01900          return 0;
01901       TotalLength += 4;  // We even have to decount the group and element 
01902      
01903       if ( g != 0xfffe && g!=0xb00c ) /*for bogus header */ 
01904       {
01905          char msg[100]; // for sprintf. Sorry
01906          sprintf(msg,"wrong group (%04x) for an item sequence (%04x,%04x)\n",g, g,n);
01907          dbg.Verbose(1, "gdcmParser::FindLengthOB: ",msg); 
01908          errno = 1;
01909          return 0;
01910       }
01911       if ( n == 0xe0dd || ( g==0xb00c && n==0x0eb6 ) ) /* for bogus header  */ 
01912          FoundSequenceDelimiter = true;
01913       else if ( n != 0xe000 )
01914       {
01915          char msg[100];  // for sprintf. Sorry
01916          sprintf(msg,"wrong element (%04x) for an item sequence (%04x,%04x)\n",
01917                       n, g,n);
01918          dbg.Verbose(1, "gdcmParser::FindLengthOB: ",msg);
01919          errno = 1;
01920          return 0;
01921       }
01922       ItemLength = ReadInt32();
01923       TotalLength += ItemLength + 4;  // We add 4 bytes since we just read
01924                                       // the ItemLength with ReadInt32                                     
01925       SkipBytes(ItemLength);
01926    }
01927    fseek(fp, PositionOnEntry, SEEK_SET);
01928    return TotalLength;
01929 }

void gdcmParser::FindHeaderEntryVR gdcmHeaderEntry Entry  )  [private]
 

Find the Value Representation of the current Dicom Element.

Parameters:
Entry 

Definition at line 1534 of file gdcmParser.cxx.

References CheckHeaderEntryVR(), ExplicitVR, filetype, fp, gdcmHeaderEntry::IsVRUnknown(), gdcmHeaderEntry::SetImplicitVR(), and gdcmHeaderEntry::SetVR().

Referenced by ReadNextHeaderEntry().

01535 {
01536    if (filetype != ExplicitVR)
01537       return;
01538 
01539    char VR[3];
01540 
01541    long PositionOnEntry = ftell(fp);
01542    // Warning: we believe this is explicit VR (Value Representation) because
01543    // we used a heuristic that found "UL" in the first tag. Alas this
01544    // doesn't guarantee that all the tags will be in explicit VR. In some
01545    // cases (see e-film filtered files) one finds implicit VR tags mixed
01546    // within an explicit VR file. Hence we make sure the present tag
01547    // is in explicit VR and try to fix things if it happens not to be
01548    // the case.
01549    
01550    int lgrLue=fread (&VR, (size_t)2,(size_t)1, fp); // lgrLue not used
01551    VR[2]=0;
01552    if(!CheckHeaderEntryVR(Entry,VR))
01553    {
01554       fseek(fp, PositionOnEntry, SEEK_SET);
01555       // When this element is known in the dictionary we shall use, e.g. for
01556       // the semantics (see the usage of IsAnInteger), the VR proposed by the
01557       // dictionary entry. Still we have to flag the element as implicit since
01558       // we know now our assumption on expliciteness is not furfilled.
01559       // avoid  .
01560       if ( Entry->IsVRUnknown() )
01561          Entry->SetVR("Implicit");
01562       Entry->SetImplicitVR();
01563    }
01564 }

void gdcmParser::FixHeaderEntryFoundLength gdcmHeaderEntry Entry,
guint32  FoundLength
[private]
 

When the length of an element value is obviously wrong (because the parser went Jabberwocky) one can hope improving things by applying this heuristic.

Definition at line 1766 of file gdcmParser.cxx.

References dbg, enableSequences, gdcmHeaderEntry::GetElement(), gdcmHeaderEntry::GetGroup(), gdcmHeaderEntry::GetVR(), gdcmHeaderEntry::SetReadLength(), gdcmHeaderEntry::SetUsableLength(), and gdcmDebug::Verbose().

Referenced by FindHeaderEntryLength().

01767 {
01768    Entry->SetReadLength(FoundLength); // will be updated only if a bug is found
01769                      
01770    if ( FoundLength == 0xffffffff) {
01771       FoundLength = 0;
01772    }
01773    
01774    guint16 gr =Entry->GetGroup();
01775    guint16 el =Entry->GetElement(); 
01776      
01777    if (FoundLength%2) {
01778       std::ostringstream s;
01779       s << "Warning : Tag with uneven length " << FoundLength 
01780          <<  " in x(" << std::hex << gr << "," << el <<")" << std::dec;
01781       dbg.Verbose(0,s.str().c_str());
01782    }
01783       
01784    // Sorry for the patch!  
01785    // XMedCom did the trick to read some nasty GE images ...
01786    if (FoundLength == 13) {
01787       // The following 'if' will be removed when there is no more
01788       // images on Creatis HDs with a 13 length for Manufacturer...
01789       if ( (Entry->GetGroup() != 0x0008) ||  
01790            ( (Entry->GetElement() != 0x0070) && (Entry->GetElement() != 0x0080) ) ){
01791       // end of remove area
01792          FoundLength =10;
01793          Entry->SetReadLength(10); // a bug is to be fixed
01794       }
01795    }
01796 
01797    // to fix some garbage 'Leonardo' Siemens images
01798    // May be commented out to avoid overhead
01799    else if ( (Entry->GetGroup() == 0x0009) &&
01800        ( (Entry->GetElement() == 0x1113) || (Entry->GetElement() == 0x1114) ) ){
01801       FoundLength =4;
01802       Entry->SetReadLength(4); // a bug is to be fixed 
01803    } 
01804    // end of fix
01805          
01806    // to try to 'go inside' SeQuences (with length), and not to skip them        
01807    else if ( Entry->GetVR() == "SQ") 
01808    { 
01809       if (enableSequences)    // only if the user does want to !
01810          FoundLength =0;      // ReadLength is unchanged         
01811    } 
01812     
01813    // a SeQuence Element is beginning                                          
01814    // Let's forget it's length                                                 
01815    // (we want to 'go inside')  
01816 
01817    // Pb : *normaly*  fffe|e000 is just a marker, its length *should be* zero
01818    // in gdcm-MR-PHILIPS-16-Multi-Seq.dcm we find lengthes as big as 28800
01819    // if we set the length to zero IsHeaderEntryAnInteger() breaks...
01820    // if we don't, we lost 28800 characters from the Header :-(
01821                                                  
01822    else if(Entry->GetGroup() == 0xfffe)
01823    { 
01824                        // sometimes, length seems to be wrong                                      
01825       FoundLength =0;  // some more clever checking to be done !
01826                        // I give up!
01827                        // only  gdcm-MR-PHILIPS-16-Multi-Seq.dcm
01828                        // causes troubles :-(                                                     
01829    }     
01830     
01831    Entry->SetUsableLength(FoundLength);
01832 }

guint32 gdcmParser::GenerateFreeTagKeyInGroup guint16  group  )  [private]
 

Small utility function that creates a new manually crafted (as opposed as read from the file) gdcmHeaderEntry with user specified name and adds it to the public tag hash table. Generate a free TagKey i.e. a TagKey that is not present in the TagHt dictionary.

Parameters:
group The generated tag must belong to this group.
Returns:
The element of tag with given group which is fee.

Definition at line 2453 of file gdcmParser.cxx.

References tagHT, TagKey, and gdcmDictEntry::TranslateToKey().

02454 {
02455    for (guint32 elem = 0; elem < UINT32_MAX; elem++) 
02456    {
02457       TagKey key = gdcmDictEntry::TranslateToKey(group, elem);
02458       if (tagHT.count(key) == 0)
02459          return elem;
02460    }
02461    return UINT32_MAX;
02462 }

gdcmDictEntry * gdcmParser::GetDictEntryByName std::string  Name  )  [private]
 

Searches both the public and the shadow dictionary (when they exist) for the presence of the DictEntry with given name. The public dictionary has precedence on the shadow one.

Parameters:
Name name of the searched DictEntry
Returns:
Corresponding DictEntry when it exists, NULL otherwise.

Definition at line 2254 of file gdcmParser.cxx.

References dbg, gdcmDict::GetDictEntryByName(), RefPubDict, RefShaDict, and gdcmDebug::Verbose().

Referenced by NewHeaderEntryByName().

02255 {
02256    gdcmDictEntry *found = (gdcmDictEntry *)0;
02257    if (!RefPubDict && !RefShaDict) 
02258    {
02259       dbg.Verbose(0, "gdcmParser::GetDictEntry",
02260                      "we SHOULD have a default dictionary");
02261    }
02262    if (RefPubDict) 
02263    {
02264       found = RefPubDict->GetDictEntryByName(Name);
02265       if (found)
02266          return found;
02267    }
02268    if (RefShaDict) 
02269    {
02270       found = RefShaDict->GetDictEntryByName(Name);
02271       if (found)
02272          return found;
02273    }
02274    return found;
02275 }

gdcmDictEntry * gdcmParser::GetDictEntryByNumber guint16  group,
guint16  element
[private]
 

Searches both the public and the shadow dictionary (when they exist) for the presence of the DictEntry with given group and element. The public dictionary has precedence on the shadow one.

Parameters:
group group of the searched DictEntry
element element of the searched DictEntry
Returns:
Corresponding DictEntry when it exists, NULL otherwise.

Definition at line 2287 of file gdcmParser.cxx.

References dbg, gdcmDict::GetDictEntryByNumber(), RefPubDict, RefShaDict, and gdcmDebug::Verbose().

Referenced by FindHeaderEntryLength(), and NewHeaderEntryByNumber().

02288 {
02289    gdcmDictEntry *found = (gdcmDictEntry *)0;
02290    if (!RefPubDict && !RefShaDict) 
02291    {
02292       dbg.Verbose(0, "gdcmParser::GetDictEntry",
02293                      "we SHOULD have a default dictionary");
02294    }
02295    if (RefPubDict) 
02296    {
02297       found = RefPubDict->GetDictEntryByNumber(group, element);
02298       if (found)
02299          return found;
02300    }
02301    if (RefShaDict) 
02302    {
02303       found = RefShaDict->GetDictEntryByNumber(group, element);
02304       if (found)
02305          return found;
02306    }
02307    return found;
02308 }

TagHeaderEntryHT& gdcmParser::GetEntry void   )  [inline]
 

returns a ref to the Dicom Header H table (multimap) return the Dicom Header H table

Definition at line 80 of file gdcmParser.h.

References TagHeaderEntryHT.

Referenced by gdcmHeader::gdcmHeader(), and gdcmFile::WriteBase().

00080 { return tagHT; };

std::string gdcmParser::GetEntryByName std::string  tagName  )  [protected, virtual]
 

Searches within Header Entries (Dicom Elements) parsed with the public and private dictionaries for the element value of a given tag.

Warning:
Don't use any longer : use GetPubEntryByName
Parameters:
tagName name of the searched element.
Returns:
Corresponding element value when it exists, and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.

Reimplemented in gdcmHeader.

Definition at line 524 of file gdcmParser.cxx.

References GDCM_UNFOUND, gdcmDict::GetDictEntryByName(), gdcmDictEntry::GetElement(), GetEntryByNumber(), gdcmDictEntry::GetGroup(), and RefPubDict.

Referenced by gdcmHeader::GetEntryByName().

00524                                                       {
00525    gdcmDictEntry *dictEntry = RefPubDict->GetDictEntryByName(tagName); 
00526    if( dictEntry == NULL)
00527       return GDCM_UNFOUND;
00528 
00529    return(GetEntryByNumber(dictEntry->GetGroup(),dictEntry->GetElement()));  
00530 }

std::string gdcmParser::GetEntryByNumber guint16  group,
guint16  element
[protected, virtual]
 

Searches within Header Entries (Dicom Elements) parsed with the public and private dictionaries for the element value representation of a given tag.

Parameters:
group Group of the searched tag.
element Element of the searched tag.
Returns:
Corresponding element value representation when it exists, and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.

Reimplemented in gdcmHeader.

Definition at line 566 of file gdcmParser.cxx.

References GDCM_UNFOUND, tagHT, TagKey, and gdcmDictEntry::TranslateToKey().

Referenced by GetEntryByName(), gdcmHeader::GetEntryByNumber(), and LoadHeaderEntries().

00566                                                                     {
00567    TagKey key = gdcmDictEntry::TranslateToKey(group, element);
00568    if ( ! tagHT.count(key))
00569       return GDCM_UNFOUND;
00570    return tagHT.find(key)->second->GetValue();
00571 }

size_t gdcmParser::GetEntryOffsetByNumber guint16  Group,
guint16  Elem
[protected, virtual]
 

Gets (from Header) the offset of a 'non string' element value (LoadElementValues has already be executed).

Parameters:
Group group of the Entry
Elem element of the Entry
Returns:
File Offset of the Element Value

Definition at line 695 of file gdcmParser.cxx.

References dbg, GetHeaderEntryByNumber(), gdcmHeaderEntry::GetOffset(), and gdcmDebug::Verbose().

00696 {
00697    gdcmHeaderEntry* Entry = GetHeaderEntryByNumber(Group, Elem);         
00698    if (!Entry) 
00699    {
00700       dbg.Verbose(1, "gdcmParser::GetHeaderEntryByNumber",
00701                       "failed to Locate gdcmHeaderEntry");
00702       return (size_t)0;
00703    }
00704    return Entry->GetOffset();
00705 }

void * gdcmParser::GetEntryVoidAreaByNumber guint16  Group,
guint16  Elem
[protected, virtual]
 

Gets (from Header) a 'non string' element value (LoadElementValues has already be executed).

Parameters:
Group group of the Entry
Elem element of the Entry
Returns:
Pointer to the 'non string' area

Definition at line 715 of file gdcmParser.cxx.

References dbg, GetHeaderEntryByNumber(), gdcmHeaderEntry::GetVoidArea(), and gdcmDebug::Verbose().

Referenced by gdcmHeader::GetLUTRGBA().

00716 {
00717    gdcmHeaderEntry* Entry = GetHeaderEntryByNumber(Group, Elem);         
00718    if (!Entry) 
00719    {
00720       dbg.Verbose(1, "gdcmParser::GetHeaderEntryByNumber",
00721                   "failed to Locate gdcmHeaderEntry");
00722       return (NULL);
00723    }
00724    return Entry->GetVoidArea();
00725 }

std::string gdcmParser::GetEntryVRByName std::string  tagName  )  [protected, virtual]
 

Searches within Header Entries (Dicom Elements) parsed with the public and private dictionaries for the element value representation of a given tag.

Obtaining the VR (Value Representation) might be needed by caller to convert the string typed content to caller's native type (think of C++ vs Python). The VR is actually of a higher level of semantics than just the native C++ type.

Parameters:
tagName name of the searched element.
Returns:
Corresponding element value representation when it exists, and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.

Reimplemented in gdcmHeader.

Definition at line 546 of file gdcmParser.cxx.

References GDCM_UNFOUND, gdcmDict::GetDictEntryByName(), gdcmDictEntry::GetElement(), gdcmDictEntry::GetGroup(), GetHeaderEntryByNumber(), gdcmHeaderEntry::GetVR(), and RefPubDict.

Referenced by gdcmHeader::GetEntryVRByName().

00546                                                         {
00547    gdcmDictEntry *dictEntry = RefPubDict->GetDictEntryByName(tagName); 
00548    if( dictEntry == NULL)
00549       return GDCM_UNFOUND;
00550 
00551    gdcmHeaderEntry* elem =  GetHeaderEntryByNumber(dictEntry->GetGroup(),
00552                                                    dictEntry->GetElement());                                    
00553    return elem->GetVR();
00554 }

std::string gdcmParser::GetEntryVRByNumber guint16  group,
guint16  element
[protected, virtual]
 

Searches within Header Entries (Dicom Elements) parsed with the public and private dictionaries for the element value representation of a given tag..

Obtaining the VR (Value Representation) might be needed by caller to convert the string typed content to caller's native type (think of C++ vs Python). The VR is actually of a higher level of semantics than just the native C++ type.

Parameters:
group Group of the searched tag.
element Element of the searched tag.
Returns:
Corresponding element value representation when it exists, and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.

Reimplemented in gdcmHeader.

Definition at line 588 of file gdcmParser.cxx.

References GDCM_UNFOUND, GetHeaderEntryByNumber(), and gdcmHeaderEntry::GetVR().

Referenced by gdcmHeader::GetEntryVRByNumber().

00588                                                                        {
00589    gdcmHeaderEntry* elem =  GetHeaderEntryByNumber(group, element);
00590    if ( !elem )
00591       return GDCM_UNFOUND;
00592    return elem->GetVR();
00593 }

std::string gdcmParser::GetFileName void   )  [inline]
 

Definition at line 58 of file gdcmParser.h.

Referenced by gdcmDicomDir::GetPath(), and gdcmDicomDir::SetElement().

00058 {return filename;}

FileType gdcmParser::GetFileType void   ) 
 

returns the File Type (ACR, ACR_LIBIDO, ExplicitVR, ImplicitVR, Unknown)

Returns:
the FileType code

Definition at line 315 of file gdcmParser.cxx.

References filetype, and FileType.

Referenced by gdcmFile::WriteBase().

00315                                      {
00316    return(filetype);
00317 }

guint16 gdcmParser::GetGrPixel void   )  [inline]
 

Definition at line 102 of file gdcmParser.h.

Referenced by gdcmFile::WriteBase().

00102 {return GrPixel;}

gdcmHeaderEntry * gdcmParser::GetHeaderEntryByName std::string  tagName  )  [protected]
 

Searches within the Header Entries for a Dicom Element of a given tag.

Parameters:
tagName name of the searched Dicom Element.
Returns:
Corresponding Dicom Element when it exists, and NULL otherwise.

Definition at line 829 of file gdcmParser.cxx.

References gdcmDict::GetDictEntryByName(), gdcmDictEntry::GetElement(), gdcmDictEntry::GetGroup(), GetHeaderEntryByNumber(), and RefPubDict.

00829                                                                     {
00830    gdcmDictEntry *dictEntry = RefPubDict->GetDictEntryByName(tagName); 
00831    if( dictEntry == NULL)
00832       return NULL;
00833 
00834   return(GetHeaderEntryByNumber(dictEntry->GetGroup(),dictEntry->GetElement()));
00835 }

gdcmHeaderEntry * gdcmParser::GetHeaderEntryByNumber guint16  group,
guint16  element
[protected]
 

retrieves a Dicom Element (the first one) using (group, element)

Warning:
(group, element) IS NOT an identifier inside the Dicom Header if you think it's NOT UNIQUE, check the count number and use iterators to retrieve ALL the Dicoms Elements within a given couple (group, element)
Parameters:
group Group number of the searched Dicom Element
element Element number of the searched Dicom Element
Returns:

Definition at line 848 of file gdcmParser.cxx.

References tagHT, TagKey, and gdcmDictEntry::TranslateToKey().

Referenced by gdcmHeader::anonymizeHeader(), GetEntryOffsetByNumber(), GetEntryVoidAreaByNumber(), GetEntryVRByName(), GetEntryVRByNumber(), GetHeaderEntryByName(), gdcmHeader::HasLUT(), IsDeflatedExplicitVRLittleEndianTransferSyntax(), gdcmHeader::IsDicomV3(), IsExplicitVRBigEndianTransferSyntax(), IsExplicitVRLittleEndianTransferSyntax(), IsImplicitVRLittleEndianTransferSyntax(), gdcmHeader::IsJPEG2000(), gdcmHeader::IsJPEGBaseLineProcess1TransferSyntax(), gdcmHeader::IsJPEGExtendedProcess2_4TransferSyntax(), gdcmHeader::IsJPEGExtendedProcess3_5TransferSyntax(), gdcmHeader::IsJPEGLossless(), gdcmHeader::IsJPEGSpectralSelectionProcess6_8TransferSyntax(), gdcmHeader::IsReadable(), gdcmHeader::IsRLELossLessTransferSyntax(), LoadEntryVoidArea(), gdcmHeader::SetImageDataSize(), and UpdateGroupLength().

00849 {
00850    TagKey key = gdcmDictEntry::TranslateToKey(group, element);
00851    if ( ! tagHT.count(key))
00852       return NULL;
00853    return tagHT.find(key)->second;
00854 }

IterHT gdcmParser::GetHeaderEntrySameNumber guint16  group,
guint16  element
[protected]
 

retrieves the Dicom Elements (all of them) using (group, element)

Parameters:
group Group number of the searched Dicom Element.
element Element number of the searched Dicom Element.
Returns:
a range (i.e.pair<,>) containing all elements whose key is group|element)

Definition at line 864 of file gdcmParser.cxx.

References IterHT, tagHT, TagKey, and gdcmDictEntry::TranslateToKey().

Referenced by gdcmHeader::GetPixelAreaLength(), and gdcmHeader::GetPixelOffset().

00864                                                                          {
00865    TagKey key = gdcmDictEntry::TranslateToKey(group, element);
00866    return (tagHT.equal_range(key));
00867 }

std::string gdcmParser::GetHeaderEntryUnvalue gdcmHeaderEntry Entry  )  [private]
 

Get the reverse transformed value of the header entry. The VR value is used to define the reverse transformation to operate on the value.

Warning:
NOT end user intended method !
Parameters:
Entry 
Returns:
Reverse transformed entry value

Definition at line 1704 of file gdcmParser.cxx.

References gdcmHeaderEntry::GetValue(), gdcmHeaderEntry::GetVR(), IsHeaderEntryAnInteger(), gdcmHeaderEntry::IsImplicitVR(), and Tokenize().

Referenced by UpdateShaEntries().

01705 {
01706    if ( (IsHeaderEntryAnInteger(Entry)) && (Entry->IsImplicitVR()) )
01707    {
01708       std::string vr=Entry->GetVR();
01709       std::ostringstream s;
01710       std::vector<std::string> tokens;
01711 
01712       if (vr == "US" || vr == "SS") 
01713       {
01714          guint16 NewInt16;
01715 
01716          tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
01717          Tokenize (Entry->GetValue(), tokens, "\\");
01718          for (unsigned int i=0; i<tokens.size();i++) 
01719          {
01720             NewInt16 = atoi(tokens[i].c_str());
01721             s<<(NewInt16&0xFF)<<((NewInt16>>8)&0xFF);
01722          }
01723          tokens.clear();
01724       }
01725       if (vr == "UL" || vr == "SL") 
01726       {
01727          guint32 NewInt32;
01728 
01729          tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
01730          Tokenize (Entry->GetValue(), tokens, "\\");
01731          for (unsigned int i=0; i<tokens.size();i++) 
01732          {
01733             NewInt32 = atoi(tokens[i].c_str());
01734             s<<(char)(NewInt32&0xFF)<<(char)((NewInt32>>8)&0xFF)
01735                <<(char)((NewInt32>>16)&0xFF)<<(char)((NewInt32>>24)&0xFF);
01736          }
01737          tokens.clear();
01738       }
01739 
01740 #ifdef GDCM_NO_ANSI_STRING_STREAM
01741       s << std::ends; // to avoid oddities on Solaris
01742 #endif //GDCM_NO_ANSI_STRING_STREAM
01743       return(s.str());
01744    }
01745 
01746    return(Entry->GetValue());
01747 }

std::string gdcmParser::GetHeaderEntryValue gdcmHeaderEntry Entry  )  [private]
 

Get the transformed value of the header entry. The VR value is used to define the transformation to operate on the value.

Warning:
NOT end user intended method !
Parameters:
Entry 
Returns:
Transformed entry value

Definition at line 1646 of file gdcmParser.cxx.

References gdcmHeaderEntry::GetLength(), gdcmHeaderEntry::GetValue(), gdcmHeaderEntry::GetVR(), IsHeaderEntryAnInteger(), gdcmHeaderEntry::IsImplicitVR(), SwapLong(), and SwapShort().

Referenced by UpdateShaEntries().

01647 {
01648    if ( (IsHeaderEntryAnInteger(Entry)) && (Entry->IsImplicitVR()) )
01649    {
01650       std::string val=Entry->GetValue();
01651       std::string vr=Entry->GetVR();
01652       guint32 length = Entry->GetLength();
01653       std::ostringstream s;
01654       int nbInt;
01655 
01656       if (vr == "US" || vr == "SS")
01657       {
01658          guint16 NewInt16;
01659 
01660          nbInt = length / 2;
01661          for (int i=0; i < nbInt; i++) 
01662          {
01663             if(i!=0)
01664                s << '\\';
01665             NewInt16 = (val[2*i+0]&0xFF)+((val[2*i+1]&0xFF)<<8);
01666             NewInt16 = SwapShort(NewInt16);
01667             s << NewInt16;
01668          }
01669       }
01670 
01671       else if (vr == "UL" || vr == "SL")
01672       {
01673          guint32 NewInt32;
01674 
01675          nbInt = length / 4;
01676          for (int i=0; i < nbInt; i++) 
01677          {
01678             if(i!=0)
01679                s << '\\';
01680             NewInt32= (val[4*i+0]&0xFF)+((val[4*i+1]&0xFF)<<8)+
01681                      ((val[4*i+2]&0xFF)<<16)+((val[4*i+3]&0xFF)<<24);
01682             NewInt32=SwapLong(NewInt32);
01683             s << NewInt32;
01684          }
01685       }
01686 #ifdef GDCM_NO_ANSI_STRING_STREAM
01687       s << std::ends; // to avoid oddities on Solaris
01688 #endif //GDCM_NO_ANSI_STRING_STREAM
01689       return(s.str());
01690    }
01691 
01692    return(Entry->GetValue());
01693 }

ListTag& gdcmParser::GetListEntry void   )  [inline]
 

returns a ref to the Dicom Header chained list return the Dicom Header chained list

Definition at line 87 of file gdcmParser.h.

References ListTag.

Referenced by gdcmDicomDir::CreateDicomDir(), gdcmDicomDir::gdcmDicomDir(), and LoadHeaderEntries().

00087 { return listEntries; };

guint16 gdcmParser::GetNumPixel void   )  [inline]
 

Definition at line 103 of file gdcmParser.h.

Referenced by gdcmFile::WriteBase().

00103 {return NumPixel;}

gdcmDict * gdcmParser::GetPubDict void   ) 
 

Get the public dictionary used.

Definition at line 185 of file gdcmParser.cxx.

References RefPubDict.

Referenced by gdcmDicomDir::SetElement().

00185                                      {
00186    return(RefPubDict);
00187 }

gdcmDict * gdcmParser::GetShaDict void   ) 
 

Get the shadow dictionary used.

Definition at line 193 of file gdcmParser.cxx.

References RefShaDict.

00193                                      {
00194    return(RefShaDict);
00195 }

int gdcmParser::GetSwapCode void   )  [inline]
 

Definition at line 101 of file gdcmParser.h.

Referenced by gdcmFile::gdcm_read_RLE_file(), gdcmFile::GetImageDataIntoVectorRaw(), gdcmFile::ParsePixelData(), and gdcmFile::ReadPixelData().

00101 { return sw; }

void gdcmParser::Initialise void   )  [private]
 

Definition at line 1988 of file gdcmParser.cxx.

References gdcmDictSet::GetDefaultPubDict(), gdcmGlobal::GetDicts(), RefPubDict, and RefShaDict.

Referenced by gdcmParser().

01989 {
01990    RefPubDict = gdcmGlobal::GetDicts()->GetDefaultPubDict();
01991    RefShaDict = (gdcmDict*)0;
01992 }

bool gdcmParser::IsDeflatedExplicitVRLittleEndianTransferSyntax void   ) 
 

Determines if the Transfer Syntax was already encountered and if it corresponds to a DeflatedExplicitVRLittleEndian one.

Returns:
True when DeflatedExplicitVRLittleEndian found. False in all other cases.

Definition at line 279 of file gdcmParser.cxx.

References GetHeaderEntryByNumber(), gdcmHeaderEntry::GetValue(), LoadHeaderEntrySafe(), and UI1_2_840_10008_1_2_1_99.

Referenced by gdcmFile::ParsePixelData(), and gdcmFile::ReadPixelData().

00279                                                                     {
00280    gdcmHeaderEntry* Element = GetHeaderEntryByNumber(0x0002, 0x0010);
00281    if ( !Element )
00282       return false;
00283    LoadHeaderEntrySafe(Element);
00284 
00285    std::string Transfer = Element->GetValue();
00286    if ( Transfer == UI1_2_840_10008_1_2_1_99 )
00287       return true;
00288    return false;
00289 }

bool gdcmParser::IsExplicitVRBigEndianTransferSyntax void   ) 
 

Determines if the Transfer Syntax was already encountered and if it corresponds to a Explicit VR Big Endian one.

Returns:
True when big endian found. False in all other cases.

Definition at line 297 of file gdcmParser.cxx.

References GetHeaderEntryByNumber(), gdcmHeaderEntry::GetValue(), LoadHeaderEntrySafe(), and UI1_2_840_10008_1_2_2.

Referenced by FindHeaderEntryLength(), gdcmFile::ParsePixelData(), and gdcmFile::ReadPixelData().

00297                                                          {
00298    gdcmHeaderEntry* Element = GetHeaderEntryByNumber(0x0002, 0x0010);
00299    if ( !Element )
00300       return false;
00301    LoadHeaderEntrySafe(Element);
00302 
00303    std::string Transfer = Element->GetValue();
00304    if ( Transfer == UI1_2_840_10008_1_2_2 )  //1.2.2 ??? A verifier !
00305       return true;
00306    return false;
00307 }

bool gdcmParser::IsExplicitVRLittleEndianTransferSyntax void   ) 
 

Determines if the Transfer Syntax was already encountered and if it corresponds to a ExplicitVRLittleEndian one.

Returns:
True when ExplicitVRLittleEndian found. False in all other cases.

Definition at line 261 of file gdcmParser.cxx.

References GetHeaderEntryByNumber(), gdcmHeaderEntry::GetValue(), LoadHeaderEntrySafe(), and UI1_2_840_10008_1_2_1.

Referenced by gdcmFile::ParsePixelData(), and gdcmFile::ReadPixelData().

00261                                                             {
00262    gdcmHeaderEntry* Element = GetHeaderEntryByNumber(0x0002, 0x0010);
00263    if ( !Element )
00264       return false;
00265    LoadHeaderEntrySafe(Element);
00266 
00267    std::string Transfer = Element->GetValue();
00268    if ( Transfer == UI1_2_840_10008_1_2_1 )
00269       return true;
00270    return false;
00271 }

bool gdcmParser::IsHeaderEntryAnInteger gdcmHeaderEntry Entry  )  [private]
 

Apply some heuristics to predict wether the considered element value contains/represents an integer or not.

Parameters:
Entry The element value on which to apply the predicate.
Returns:
The result of the heuristical predicate.

Definition at line 1841 of file gdcmParser.cxx.

References fp, gdcmHeaderEntry::GetElement(), gdcmHeaderEntry::GetGroup(), gdcmHeaderEntry::GetLength(), and gdcmHeaderEntry::GetVR().

Referenced by GetHeaderEntryUnvalue(), GetHeaderEntryValue(), and LoadHeaderEntry().

01841                                                               {
01842    guint16 element = Entry->GetElement();
01843    guint16 group   = Entry->GetGroup();
01844    std::string  vr = Entry->GetVR();
01845    guint32 length  = Entry->GetLength();
01846    // When we have some semantics on the element we just read, and if we
01847    // a priori know we are dealing with an integer, then we shall be
01848    // able to swap it's element value properly.
01849    if ( element == 0 )  // This is the group length of the group
01850    {  
01851       if (length == 4)
01852          return true;
01853       else 
01854       {
01855          std::ostringstream s;
01856          int filePosition = ftell(fp);
01857          s << "Erroneous Group Length element length  on : (" \
01858            << std::hex << group << " , " << element 
01859            << ") -before- position x(" << filePosition << ")"
01860            << "lgt : " << length;
01861         // These 2 lines commented out : a *very dirty* patch
01862         // to go on PrintHeader'ing gdcm-MR-PHILIPS-16-Multi-Seq.dcm.
01863         // have a glance at offset  x(8336) ...
01864         // For *regular* headers, the test is useless..
01865         // lets's print a warning message and go on, 
01866         // instead of giving up with an error message
01867         
01868         //std::cout << s.str().c_str() << std::endl;
01869         
01870         // dbg.Error("gdcmParser::IsHeaderEntryAnInteger",
01871         //    s.str().c_str());     
01872       }
01873    }
01874    if ( (vr == "UL") || (vr == "US") || (vr == "SL") || (vr == "SS") )
01875       return true;
01876    
01877    return false;
01878 }

bool gdcmParser::IsImplicitVRLittleEndianTransferSyntax void   ) 
 

Determines if the Transfer Syntax was already encountered and if it corresponds to a ImplicitVRLittleEndian one.

Returns:
True when ImplicitVRLittleEndian found. False in all other cases.

Definition at line 243 of file gdcmParser.cxx.

References GetHeaderEntryByNumber(), gdcmHeaderEntry::GetValue(), LoadHeaderEntrySafe(), and UI1_2_840_10008_1_2.

Referenced by gdcmFile::ParsePixelData(), and gdcmFile::ReadPixelData().

00243                                                             {
00244    gdcmHeaderEntry *Element = GetHeaderEntryByNumber(0x0002, 0x0010);
00245    if ( !Element )
00246       return false;
00247    LoadHeaderEntrySafe(Element);
00248 
00249    std::string Transfer = Element->GetValue();
00250    if ( Transfer == UI1_2_840_10008_1_2 )
00251       return true;
00252    return false;
00253 }

bool gdcmParser::IsReadable void   )  [virtual]
 

This predicate, based on hopefully reasonable heuristics, decides whether or not the current gdcmParser was properly parsed and contains the mandatory information for being considered as a well formed and usable Dicom/Acr File.

Returns:
true when gdcmParser is the one of a reasonable Dicom/Acr file, false otherwise.

Reimplemented in gdcmHeader.

Definition at line 226 of file gdcmParser.cxx.

References filetype, listEntries, and Unknown.

Referenced by gdcmHeader::IsReadable().

00226                                 { 
00227    if(filetype==Unknown) {
00228       return(false);
00229    }
00230    if(listEntries.size()<=0) {    
00231       return(false);
00232    }
00233 
00234    return(true);
00235 }

void * gdcmParser::LoadEntryVoidArea guint16  Group,
guint16  Elem
[protected, virtual]
 

Loads (from disk) the element content when a string is not suitable.

Parameters:
Group group of the Entry
Elem element of the Entry

Definition at line 734 of file gdcmParser.cxx.

References fp, GetHeaderEntryByNumber(), gdcmHeaderEntry::GetLength(), gdcmHeaderEntry::GetOffset(), and SetEntryVoidAreaByNumber().

Referenced by LoadHeaderEntries().

00735 {
00736    gdcmHeaderEntry * Element= GetHeaderEntryByNumber(Group, Elem);
00737    if ( !Element )
00738       return NULL;
00739    size_t o =(size_t)Element->GetOffset();
00740    fseek(fp, o, SEEK_SET);
00741    int l=Element->GetLength();
00742    void * a = malloc(l);
00743    if(!a) 
00744         return NULL;
00745 
00746    SetEntryVoidAreaByNumber(a, Group, Elem);
00747    // TODO check the result 
00748    size_t l2 = fread(a, 1, l ,fp);
00749    if(l != l2) 
00750    {
00751         free(a);
00752         return NULL;
00753    }
00754 
00755    return a;  
00756 }

void gdcmParser::LoadHeaderEntries void   )  [private]
 

Loads the element values of all the Header Entries pointed in the public Chained List.

Definition at line 1237 of file gdcmParser.cxx.

References ACR_LIBIDO, filetype, fp, GetEntryByNumber(), GetListEntry(), LoadEntryVoidArea(), LoadHeaderEntry(), and SetEntryByNumber().

Referenced by gdcmParser().

01237                                        {
01238    rewind(fp);
01239    for (ListTag::iterator i = GetListEntry().begin();
01240       i != GetListEntry().end();
01241       ++i)
01242    {
01243       LoadHeaderEntry(*i);
01244    }
01245             
01246    rewind(fp);
01247 
01248    // Load 'non string' values   
01249    std::string PhotometricInterpretation = GetEntryByNumber(0x0028,0x0004);   
01250    if( PhotometricInterpretation == "PALETTE COLOR " ) {
01251       LoadEntryVoidArea(0x0028,0x1200);  // gray LUT   
01252       LoadEntryVoidArea(0x0028,0x1201);  // R    LUT
01253       LoadEntryVoidArea(0x0028,0x1202);  // G    LUT
01254       LoadEntryVoidArea(0x0028,0x1203);  // B    LUT
01255       
01256       LoadEntryVoidArea(0x0028,0x1221);  // Segmented Red   Palette Color LUT Data
01257       LoadEntryVoidArea(0x0028,0x1222);  // Segmented Green Palette Color LUT Data
01258       LoadEntryVoidArea(0x0028,0x1223);  // Segmented Blue  Palette Color LUT Data
01259    } 
01260    //FIXME : how to use it?
01261    LoadEntryVoidArea(0x0028,0x3006);  //LUT Data (CTX dependent)     
01262    
01263    // --------------------------------------------------------------
01264    // Special Patch to allow gdcm to read ACR-LibIDO formated images
01265    //
01266    // if recognition code tells us we deal with a LibIDO image
01267    // we switch lineNumber and columnNumber
01268    //
01269    std::string RecCode; 
01270    RecCode = GetEntryByNumber(0x0008, 0x0010); // recognition code
01271    if (RecCode == "ACRNEMA_LIBIDO_1.1" ||
01272        RecCode == "CANRME_AILIBOD1_1." ) 
01273    {
01274          filetype = ACR_LIBIDO; 
01275          std::string rows    = GetEntryByNumber(0x0028, 0x0010);
01276          std::string columns = GetEntryByNumber(0x0028, 0x0011);
01277          SetEntryByNumber(columns, 0x0028, 0x0010);
01278          SetEntryByNumber(rows   , 0x0028, 0x0011);
01279    }
01280    // ----------------- End of Special Patch ----------------
01281 }

void gdcmParser::LoadHeaderEntry gdcmHeaderEntry Entry  )  [private]
 

Loads the element content if its length doesn't exceed the value specified with gdcmParser::SetMaxSizeLoadEntry().

Parameters:
Entry Header Entry (Dicom Element) to be dealt with

Definition at line 1289 of file gdcmParser.cxx.

References dbg, fp, gdcmHeaderEntry::GetGroup(), gdcmHeaderEntry::GetLength(), gdcmHeaderEntry::GetOffset(), gdcmHeaderEntry::GetVR(), IsHeaderEntryAnInteger(), MaxSizeLoadEntry, ReadInt16(), ReadInt32(), gdcmHeaderEntry::SetLength(), gdcmHeaderEntry::SetValue(), and gdcmDebug::Verbose().

Referenced by LoadHeaderEntries(), and LoadHeaderEntrySafe().

01289                                                         {
01290    size_t item_read;
01291    guint16 group  = Entry->GetGroup();
01292    std::string  vr= Entry->GetVR();
01293    guint32 length = Entry->GetLength();
01294    bool SkipLoad  = false;
01295 
01296    fseek(fp, (long)Entry->GetOffset(), SEEK_SET);
01297    
01298    // the test was commented out to 'go inside' the SeQuences
01299    // we don't any longer skip them !
01300     
01301    // if( vr == "SQ" )  //  (DO NOT remove this comment)
01302    //    SkipLoad = true;
01303 
01304    // A SeQuence "contains" a set of Elements.  
01305    //          (fffe e000) tells us an Element is beginning
01306    //          (fffe e00d) tells us an Element just ended
01307    //          (fffe e0dd) tells us the current SeQuence just ended
01308    if( group == 0xfffe )
01309       SkipLoad = true;
01310 
01311    if ( SkipLoad ) {
01312       Entry->SetLength(0);
01313       Entry->SetValue("gdcm::Skipped");
01314       return;
01315    }
01316 
01317    // When the length is zero things are easy:
01318    if ( length == 0 ) {
01319       Entry->SetValue("");
01320       return;
01321    }
01322 
01323    // The elements whose length is bigger than the specified upper bound
01324    // are not loaded. Instead we leave a short notice of the offset of
01325    // the element content and it's length.
01326    if (length > MaxSizeLoadEntry) {
01327       std::ostringstream s;
01328       s << "gdcm::NotLoaded.";
01329       s << " Address:" << (long)Entry->GetOffset();
01330       s << " Length:"  << Entry->GetLength();
01331       s << " x(" << std::hex << Entry->GetLength() << ")";
01332       Entry->SetValue(s.str());
01333       return;
01334    }
01335    
01336    // When integer(s) are expected, read and convert the following 
01337    // n *(two or four bytes)
01338    // properly i.e. as integers as opposed to strings.  
01339    // Elements with Value Multiplicity > 1
01340    // contain a set of integers (not a single one) 
01341         
01342    // Any compacter code suggested (?)
01343    if ( IsHeaderEntryAnInteger(Entry) ) {   
01344       guint32 NewInt;
01345       std::ostringstream s;
01346       int nbInt;
01347       if (vr == "US" || vr == "SS") {
01348          nbInt = length / 2;
01349          NewInt = ReadInt16();
01350          s << NewInt;
01351          if (nbInt > 1){
01352             for (int i=1; i < nbInt; i++) {
01353                s << '\\';
01354                NewInt = ReadInt16();
01355                s << NewInt;
01356             }
01357          }                      
01358       }
01359       else if (vr == "UL" || vr == "SL") {
01360          nbInt = length / 4;
01361          NewInt = ReadInt32();
01362          s << NewInt;
01363          if (nbInt > 1) {
01364             for (int i=1; i < nbInt; i++) {
01365                s << '\\';
01366                NewInt = ReadInt32();
01367                s << NewInt;
01368             }
01369          }
01370       }
01371 #ifdef GDCM_NO_ANSI_STRING_STREAM
01372       s << std::ends; // to avoid oddities on Solaris
01373 #endif //GDCM_NO_ANSI_STRING_STREAM
01374 
01375       Entry->SetValue(s.str());
01376       return;   
01377    }
01378    
01379    // We need an additional byte for storing \0 that is not on disk
01380    std::string NewValue(length,0);
01381    item_read = fread(&(NewValue[0]), (size_t)length, (size_t)1, fp);
01382    if ( item_read != 1 ) {
01383       dbg.Verbose(1, "gdcmParser::LoadElementValue","unread element value");
01384       Entry->SetValue("gdcm::UnRead");
01385       return;
01386    }
01387 
01388    if( (vr == "UI") ) // Because of correspondance with the VR dic
01389       Entry->SetValue(NewValue.c_str()); // ??? JPR ???
01390    else
01391       Entry->SetValue(NewValue);
01392 }

void gdcmParser::LoadHeaderEntrySafe gdcmHeaderEntry entry  )  [protected]
 

Loads the element while preserving the current underlying file position indicator as opposed to to LoadHeaderEntry that modifies it.

Parameters:
entry Header Entry whose value shall be loaded.
Returns:

Definition at line 877 of file gdcmParser.cxx.

References fp, and LoadHeaderEntry().

Referenced by IsDeflatedExplicitVRLittleEndianTransferSyntax(), IsExplicitVRBigEndianTransferSyntax(), IsExplicitVRLittleEndianTransferSyntax(), IsImplicitVRLittleEndianTransferSyntax(), gdcmHeader::IsJPEG2000(), gdcmHeader::IsJPEGBaseLineProcess1TransferSyntax(), gdcmHeader::IsJPEGExtendedProcess2_4TransferSyntax(), gdcmHeader::IsJPEGExtendedProcess3_5TransferSyntax(), gdcmHeader::IsJPEGLossless(), gdcmHeader::IsJPEGSpectralSelectionProcess6_8TransferSyntax(), and gdcmHeader::IsRLELossLessTransferSyntax().

00877                                                             {
00878    long PositionOnEntry = ftell(fp);
00879    LoadHeaderEntry(entry);
00880    fseek(fp, PositionOnEntry, SEEK_SET);
00881 }

gdcmHeaderEntry * gdcmParser::NewHeaderEntryByName std::string  Name  )  [private]
 

Build a new Element Value from all the low level arguments. Check for existence of dictionary entry, and build a default one when absent.

Parameters:
Name Name of the underlying DictEntry

Definition at line 2354 of file gdcmParser.cxx.

References dbg, GetDictEntryByName(), NewVirtualDictEntry(), and gdcmDebug::Verbose().

02355 {
02356    gdcmDictEntry *NewTag = GetDictEntryByName(Name);
02357    if (!NewTag)
02358       NewTag = NewVirtualDictEntry(0xffff, 0xffff, "LO", "unkn", Name);
02359 
02360    gdcmHeaderEntry* NewEntry = new gdcmHeaderEntry(NewTag);
02361    if (!NewEntry) 
02362    {
02363       dbg.Verbose(1, "gdcmParser::ObtainHeaderEntryByName",
02364                   "failed to allocate gdcmHeaderEntry");
02365       return (gdcmHeaderEntry *)0;
02366    }
02367    return NewEntry;
02368 }  

gdcmHeaderEntry * gdcmParser::NewHeaderEntryByNumber guint16  Group,
guint16  Elem
[private]
 

Build a new Element Value from all the low level arguments. Check for existence of dictionary entry, and build a default one when absent.

Parameters:
Group group of the underlying DictEntry
Elem element of the underlying DictEntry

Definition at line 2395 of file gdcmParser.cxx.

References dbg, GetDictEntryByNumber(), NewVirtualDictEntry(), and gdcmDebug::Verbose().

Referenced by ReadNextHeaderEntry(), and ReplaceOrCreateByNumber().

02396 {
02397    // Find out if the tag we encountered is in the dictionaries:
02398    gdcmDictEntry *DictEntry = GetDictEntryByNumber(Group, Elem);
02399    if (!DictEntry)
02400       DictEntry = NewVirtualDictEntry(Group, Elem);
02401 
02402    gdcmHeaderEntry *NewEntry = new gdcmHeaderEntry(DictEntry);
02403    if (!NewEntry) 
02404    {
02405       dbg.Verbose(1, "gdcmParser::NewHeaderEntryByNumber",
02406                   "failed to allocate gdcmHeaderEntry");
02407       return NULL;
02408    }
02409    return NewEntry;
02410 }

gdcmDictEntry* gdcmParser::NewVirtualDictEntry gdcmHeaderEntry  )  [private]
 

gdcmDictEntry * gdcmParser::NewVirtualDictEntry guint16  group,
guint16  element,
std::string  vr = "unkn",
std::string  fourth = "unkn",
std::string  name = "unkn"
[private]
 

Request a new virtual dict entry to the dict set.

Parameters:
group group of the underlying DictEntry
element element of the underlying DictEntry
vr VR of the underlying DictEntry
fourth owner group
name english name

Definition at line 2379 of file gdcmParser.cxx.

References gdcmGlobal::GetDicts(), and gdcmDictSet::NewVirtualDictEntry().

Referenced by CheckHeaderEntryVR(), FindHeaderEntryLength(), NewHeaderEntryByName(), NewHeaderEntryByNumber(), and UpdateShaEntries().

02383 {
02384    return gdcmGlobal::GetDicts()->NewVirtualDictEntry(group,element,vr,fourth,name);
02385 }

FILE * gdcmParser::OpenFile bool  exception_on_error = false  )  throw (gdcmFileError)
 

opens the file

Parameters:
exception_on_error 
Returns:

Definition at line 325 of file gdcmParser.cxx.

References dbg, and gdcmDebug::Verbose().

Referenced by gdcmParser(), gdcmFile::ParsePixelData(), and gdcmFile::ReadPixelData().

00327 {
00328   fp=fopen(filename.c_str(),"rb");
00329   if(exception_on_error) 
00330   {
00331     if(!fp)
00332       throw gdcmFileError("gdcmParser::gdcmParser(const char *, bool)");
00333   }
00334 
00335   if ( fp ) 
00336   {
00337      guint16 zero;
00338      fread(&zero,  (size_t)2, (size_t)1, fp);
00339 
00340     //ACR -- or DICOM with no Preamble --
00341     if( zero == 0x0008 || zero == 0x0800 || zero == 0x0002 || zero == 0x0200)
00342        return(fp);
00343 
00344     //DICOM
00345     fseek(fp, 126L, SEEK_CUR);
00346     char dicm[4];
00347     fread(dicm,  (size_t)4, (size_t)1, fp);
00348     if( memcmp(dicm, "DICM", 4) == 0 )
00349        return(fp);
00350 
00351     fclose(fp);
00352     dbg.Verbose(0, "gdcmParser::OpenFile not DICOM/ACR", filename.c_str());
00353   }
00354   else {
00355     dbg.Verbose(0, "gdcmParser::OpenFile cannot open file", filename.c_str());
00356   }
00357   return(NULL);
00358 }

bool gdcmParser::ParseHeader bool  exception_on_error = false  )  throw (gdcmFormatError) [private]
 

Parses the header of the file but WITHOUT loading element values.

Returns:
false if file is not ACR-NEMA / DICOM

Definition at line 1216 of file gdcmParser.cxx.

References gdcmHeaderEntry::GetGroup().

Referenced by gdcmParser().

01216                                                                            {
01217    
01218    rewind(fp);
01219    if (!CheckSwap())
01220       return false;
01221       
01222    gdcmHeaderEntry *newHeaderEntry = (gdcmHeaderEntry *)0;   
01223    while ( (newHeaderEntry = ReadNextHeaderEntry()) ) {
01224      SkipHeaderEntry(newHeaderEntry);
01225      if ( (ignoreShadow==0) || (newHeaderEntry->GetGroup()%2) == 0) { 
01226         AddHeaderEntry(newHeaderEntry); 
01227      }       
01228    }
01229    return true;
01230 }

virtual void gdcmParser::Print std::ostream &  os = std::cout  )  [inline, virtual]
 

Reimplemented in gdcmDicomDir.

Definition at line 52 of file gdcmParser.h.

00052 {PrintEntry(os);};

void gdcmParser::PrintEntry std::ostream &  os = std::cout  )  [virtual]
 

Prints the Header Entries (Dicom Elements) both from the H Table and the chained list.

Returns:

Definition at line 148 of file gdcmParser.cxx.

References listEntries.

00148                                            {
00149    std::ostringstream s;   
00150            
00151    for (ListTag::iterator i = listEntries.begin();  
00152            i != listEntries.end();
00153            ++i)
00154    {
00155            (*i)->SetPrintLevel(printLevel);
00156            (*i)->Print(os);   
00157    } 
00158    os<<s.str();
00159 }

void gdcmParser::PrintPubDict std::ostream &  os = std::cout  )  [virtual]
 

Prints The Dict Entries of THE public Dicom Dictionnry.

Returns:

Definition at line 166 of file gdcmParser.cxx.

References gdcmDict::Print(), and RefPubDict.

00166                                              {
00167    RefPubDict->Print(os);
00168 }

void gdcmParser::PrintShaDict std::ostream &  os = std::cout  )  [virtual]
 

Prints The Dict Entries of THE shadow Dicom Dictionnry.

Returns:

Definition at line 175 of file gdcmParser.cxx.

References gdcmDict::Print(), and RefShaDict.

00175                                              {
00176    RefShaDict->Print(os);
00177 }

guint16 gdcmParser::ReadInt16 void   )  [private]
 

Reads a supposed to be 16 Bits integer (swaps it depending on processor endianity).

Returns:
read value

Definition at line 1937 of file gdcmParser.cxx.

References dbg, fp, SwapShort(), and gdcmDebug::Verbose().

Referenced by FindHeaderEntryLength(), FindHeaderEntryLengthOB(), LoadHeaderEntry(), and ReadNextHeaderEntry().

01937                                   {
01938    guint16 g;
01939    size_t item_read;
01940    item_read = fread (&g, (size_t)2,(size_t)1, fp);
01941    if ( item_read != 1 ) {
01942       if(ferror(fp)) 
01943          dbg.Verbose(0, "gdcmParser::ReadInt16", " File Error");
01944       errno = 1;
01945       return 0;
01946    }
01947    errno = 0;
01948    g = SwapShort(g);   
01949    return g;
01950 }

guint32 gdcmParser::ReadInt32 void   )  [private]
 

Reads a supposed to be 32 Bits integer (swaps it depending on processor endianity).

Returns:
read value

Definition at line 1958 of file gdcmParser.cxx.

References dbg, fp, SwapLong(), and gdcmDebug::Verbose().

Referenced by FindHeaderEntryLength(), FindHeaderEntryLengthOB(), and LoadHeaderEntry().

01958                                   {
01959    guint32 g;
01960    size_t item_read;
01961    item_read = fread (&g, (size_t)4,(size_t)1, fp);
01962    if ( item_read != 1 ) { 
01963      if(ferror(fp)) 
01964          dbg.Verbose(0, "gdcmParser::ReadInt32", " File Error");   
01965       errno = 1;
01966       return 0;
01967    }
01968    errno = 0;   
01969    g = SwapLong(g);
01970    return g;
01971 }

gdcmHeaderEntry * gdcmParser::ReadNextHeaderEntry void   )  [private]
 

Read the next tag but WITHOUT loading it's value.

Returns:
On succes the newly created HeaderEntry, NULL on failure.

Definition at line 2315 of file gdcmParser.cxx.

References FindHeaderEntryLength(), FindHeaderEntryVR(), fp, NewHeaderEntryByNumber(), ReadInt16(), and gdcmHeaderEntry::SetOffset().

02315                                                      {
02316    guint16 g,n;
02317    gdcmHeaderEntry *NewEntry;
02318    g = ReadInt16();
02319    n = ReadInt16();
02320       
02321    if (errno == 1)
02322       // We reached the EOF (or an error occured) therefore 
02323       // header parsing has to be considered as finished.
02324       return (gdcmHeaderEntry *)0;
02325 
02326 /*  Pb : how to propagate the element length (used in SkipHeaderEntry)
02327 //       direct call to SkipBytes ?
02328    
02329    if (ignoreShadow == 1 && g%2 ==1)  //JPR
02330       // if user wants to skip shadow groups
02331       // and current element *is* a shadow element
02332       // we don't create anything
02333       return (gdcmHeaderEntry *)1; // to tell caller it's NOT finished
02334 */   
02335    NewEntry = NewHeaderEntryByNumber(g, n);
02336    FindHeaderEntryVR(NewEntry);
02337    FindHeaderEntryLength(NewEntry);
02338         
02339    if (errno == 1) {
02340       // Call it quits
02341       return NULL;
02342    }
02343    NewEntry->SetOffset(ftell(fp));  
02344    return NewEntry;
02345 }

bool gdcmParser::ReplaceIfExistByNumber char *  Value,
guint16  Group,
guint16  Elem
 

Set a new value if the invoked element exists Seems to be useless !!!

Parameters:
Value new element value
Group group of the Entry
Elem element of the Entry
Returns:
boolean

Definition at line 491 of file gdcmParser.cxx.

References SetEntryByNumber().

Referenced by gdcmHeader::anonymizeHeader().

00492 {
00493    std::string v = Value;       
00494    SetEntryByNumber(v, Group, Elem);
00495    return true;
00496 } 

bool gdcmParser::ReplaceOrCreateByNumber char *  Value,
guint16  Group,
guint16  Elem
 

Modifies the value of a given Header Entry (Dicom Element) if it exists; Creates it with the given value if it doesn't.

Parameters:
Value passed as a char*
Group group of the Entry
Elem element of the Entry
Returns:
boolean

Definition at line 469 of file gdcmParser.cxx.

References AddHeaderEntry(), NewHeaderEntryByNumber(), and SetEntryByNumber().

00469                                                                                   {
00470    gdcmHeaderEntry* nvHeaderEntry=NewHeaderEntryByNumber(Group, Elem);
00471 
00472    if(!nvHeaderEntry)
00473       return(false);
00474 
00475    AddHeaderEntry(nvHeaderEntry);
00476 
00477    std::string v = Value;       
00478    SetEntryByNumber(v, Group, Elem);
00479    return(true);
00480 }  

bool gdcmParser::ReplaceOrCreateByNumber std::string  Value,
guint16  Group,
guint16  Elem
 

Modifies the value of a given Header Entry (Dicom Element) if it exists; Creates it with the given value if it doesn't.

Parameters:
Value passed as a std::string
Group 
Elem 
Returns:
false only if new element creation fails

Definition at line 446 of file gdcmParser.cxx.

References AddHeaderEntry(), CheckIfEntryExistByNumber(), NewHeaderEntryByNumber(), and SetEntryByNumber().

Referenced by gdcmHeader::anonymizeHeader(), and Write().

00448                                                        {
00449    if (CheckIfEntryExistByNumber(Group, Elem) == 0) {
00450       gdcmHeaderEntry *a =NewHeaderEntryByNumber(Group, Elem);
00451       if (a == NULL) 
00452          return false;
00453       AddHeaderEntry(a);
00454    }   
00455    SetEntryByNumber(Value, Group, Elem);
00456    return(true);
00457 }   

bool gdcmParser::SetEntryByName std::string  content,
std::string  tagName
[protected, virtual]
 

Sets the value (string) of the Header Entry (Dicom Element).

Parameters:
content string value of the Dicom Element
tagName name of the searched Dicom Element.
Returns:
true when found

Reimplemented in gdcmHeader.

Definition at line 602 of file gdcmParser.cxx.

References gdcmDict::GetDictEntryByName(), gdcmDictEntry::GetElement(), gdcmDictEntry::GetGroup(), RefPubDict, and SetEntryByNumber().

Referenced by gdcmHeader::SetEntryByName().

00602                                                                    {
00603    gdcmDictEntry *dictEntry = RefPubDict->GetDictEntryByName(tagName); 
00604    if( dictEntry == NULL)
00605       return false;                                 
00606 
00607    return(SetEntryByNumber(content,dictEntry->GetGroup(),
00608                                    dictEntry->GetElement()));
00609 }

bool gdcmParser::SetEntryByNumber std::string  content,
guint16  group,
guint16  element
[protected, virtual]
 

Accesses an existing gdcmHeaderEntry (i.e. a Dicom Element) through it's (group, element) and modifies it's content with the given value.

Warning:
Don't use any longer : use SetPubEntryByNumber
Parameters:
content new value to substitute with
group group of the Dicom Element to modify
element element of the Dicom Element to modify

Reimplemented in gdcmHeader.

Definition at line 621 of file gdcmParser.cxx.

References gdcmHeaderEntry::GetVR(), IterHT, gdcmHeaderEntry::SetLength(), tagHT, TagKey, and gdcmDictEntry::TranslateToKey().

Referenced by LoadHeaderEntries(), ReplaceIfExistByNumber(), ReplaceOrCreateByNumber(), SetEntryByName(), and gdcmHeader::SetEntryByNumber().

00624 {
00625    TagKey key = gdcmDictEntry::TranslateToKey(group, element);
00626    if ( ! tagHT.count(key))
00627       return false;
00628    int l = content.length();
00629    if(l%2) // Non even length are padded with a space (020H).
00630    {  
00631       l++;
00632       content = content + '\0';
00633    }
00634       
00635    gdcmHeaderEntry * a;
00636    IterHT p;
00637    TagHeaderEntryHT::iterator p2;
00638    // DO NOT remove the following lines : they explain the stuff   
00639    //p= tagHT.equal_range(key); // get a pair of iterators first-last synonym
00640    //p2=p.first;                // iterator on the first synonym 
00641    //a=p2->second;              // H Table target column (2-nd col)
00642     
00643    // or, easier :
00644    a = ((tagHT.equal_range(key)).first)->second; 
00645        
00646    a-> SetValue(content); 
00647    
00648    std::string vr = a->GetVR();
00649    
00650    guint32 lgr;
00651    if( (vr == "US") || (vr == "SS") ) 
00652       lgr = 2;
00653    else if( (vr == "UL") || (vr == "SL") )
00654       lgr = 4;
00655    else
00656       lgr = l;     
00657 
00658    a->SetLength(lgr);   
00659    return true;
00660 }                                         

bool gdcmParser::SetEntryLengthByNumber guint32  l,
guint16  group,
guint16  element
[protected, virtual]
 

Accesses an existing gdcmHeaderEntry (i.e. a Dicom Element) in the PubHeaderEntrySet of this instance through it's (group, element) and modifies it's length with the given value.

Warning:
Use with extreme caution.
Parameters:
l new length to substitute with
group group of the Entry to modify
element element of the Entry to modify
Returns:
1 on success, 0 otherwise.

Reimplemented in gdcmHeader.

Definition at line 674 of file gdcmParser.cxx.

References tagHT, TagKey, and gdcmDictEntry::TranslateToKey().

Referenced by gdcmHeader::SetEntryLengthByNumber(), and Write().

00677 {
00678    TagKey key = gdcmDictEntry::TranslateToKey(group, element);
00679    if ( ! tagHT.count(key))
00680       return false;
00681    if (l%2) l++; // length must be even
00682    ( ((tagHT.equal_range(key)).first)->second )->SetLength(l);   
00683          
00684    return true ;                
00685 }

bool gdcmParser::SetEntryVoidAreaByNumber void *  area,
guint16  group,
guint16  element
[protected, virtual]
 

Sets a 'non string' value to a given Dicom Element.

Parameters:
area 
group Group number of the searched Dicom Element
element Element number of the searched Dicom Element
Returns:

Definition at line 766 of file gdcmParser.cxx.

References tagHT, TagKey, and gdcmDictEntry::TranslateToKey().

Referenced by LoadEntryVoidArea().

00769 {
00770    TagKey key = gdcmDictEntry::TranslateToKey(group, element);
00771    if ( ! tagHT.count(key))
00772       return false;
00773    ( ((tagHT.equal_range(key)).first)->second )->SetVoidArea(area);      
00774    return true;
00775 }

void gdcmParser::SetMaxSizeLoadEntry long  NewSize  )  [private]
 

during parsing, Header Elements too long are not loaded in memory

Parameters:
NewSize 

Definition at line 2211 of file gdcmParser.cxx.

References MaxSizeLoadEntry.

Referenced by gdcmParser().

02212 {
02213    if (NewSize < 0)
02214       return;
02215    if ((guint32)NewSize >= (guint32)0xffffffff) 
02216    {
02217       MaxSizeLoadEntry = 0xffffffff;
02218       return;
02219    }
02220    MaxSizeLoadEntry = NewSize;
02221 }

void gdcmParser::SetMaxSizePrintEntry long  NewSize  )  [private]
 

Header Elements too long will not be printed.

Warning:

Todo:
: not yet usable (see MAX_SIZE_PRINT_ELEMENT_VALUE in gdcmHeaderEntry gdcmLoadEntry)
Parameters:
NewSize 

Definition at line 2234 of file gdcmParser.cxx.

References MaxSizePrintEntry.

02235 {
02236    if (NewSize < 0)
02237       return;
02238    if ((guint32)NewSize >= (guint32)0xffffffff) 
02239    {
02240       MaxSizePrintEntry = 0xffffffff;
02241       return;
02242    }
02243    MaxSizePrintEntry = NewSize;
02244 }

void gdcmParser::SetPrintLevel int  level  )  [inline]
 

Sets the print level for the Dicom Header.

Note:
0 for Light Print; 1 for 'medium' Print, 2 for Heavy

Reimplemented in gdcmDicomDir.

Definition at line 51 of file gdcmParser.h.

00051 { printLevel = level; };

bool gdcmParser::SetShaDict DictKey  dictName  ) 
 

Set the shadow dictionary used.

Parameters:
dictName name of the dictionary to use in shadow

Definition at line 212 of file gdcmParser.cxx.

References DictKey, gdcmDictSet::GetDict(), gdcmGlobal::GetDicts(), and RefShaDict.

00212                                            {
00213    RefShaDict=gdcmGlobal::GetDicts()->GetDict(dictName);
00214    return(!RefShaDict);
00215 }

bool gdcmParser::SetShaDict gdcmDict dict  ) 
 

Set the shadow dictionary used.

Parameters:
dict dictionary to use in shadow

Definition at line 202 of file gdcmParser.cxx.

References RefShaDict.

00202                                          {
00203    RefShaDict=dict;
00204    return(!RefShaDict);
00205 }

void gdcmParser::SkipBytes guint32  NBytes  )  [private]
 

Warning:
NOT end user intended method !
Returns:

Definition at line 1979 of file gdcmParser.cxx.

References fp.

Referenced by FindHeaderEntryLengthOB(), and SkipHeaderEntry().

01979                                          {
01980    //FIXME don't dump the returned value
01981    (void)fseek(fp, (long)NBytes, SEEK_CUR);
01982 }

void gdcmParser::SkipHeaderEntry gdcmHeaderEntry entry  )  [private]
 

Skip a given Header Entry.

Warning:
NOT end user intended method !
Parameters:
entry 

Definition at line 1755 of file gdcmParser.cxx.

References gdcmHeaderEntry::GetLength(), and SkipBytes().

01756 {
01757     SkipBytes(entry->GetLength());
01758 }

guint32 gdcmParser::SwapLong guint32  a  ) 
 

Swaps back the bytes of 4-byte long integer accordingly to processor order.

Returns:
The properly swaped 32 bits integer.

Definition at line 1156 of file gdcmParser.cxx.

References dbg, gdcmDebug::Error(), and sw.

Referenced by gdcmFile::gdcm_read_RLE_file(), GetHeaderEntryValue(), gdcmFile::ParsePixelData(), ReadInt32(), gdcmFile::ReadPixelData(), and UnswapLong().

01156                                       {
01157    switch (sw) {
01158       case    0 :
01159          break;
01160       case 4321 :
01161          a=( ((a<<24) & 0xff000000) | ((a<<8)  & 0x00ff0000) | 
01162              ((a>>8)  & 0x0000ff00) | ((a>>24) & 0x000000ff) );
01163          break;
01164    
01165       case 3412 :
01166          a=( ((a<<16) & 0xffff0000) | ((a>>16) & 0x0000ffff) );
01167          break;
01168    
01169       case 2143 :
01170          a=( ((a<<8) & 0xff00ff00) | ((a>>8) & 0x00ff00ff)  );
01171          break;
01172       default :
01173          dbg.Error(" gdcmParser::SwapLong : unset swap code");
01174          a=0;
01175    }
01176    return(a);
01177 }

guint16 gdcmParser::SwapShort guint16  a  ) 
 

Swaps the bytes so they agree with the processor order.

Returns:
The properly swaped 16 bits integer.

Definition at line 1194 of file gdcmParser.cxx.

References sw.

Referenced by FindHeaderEntryLength(), gdcmFile::gdcm_read_RLE_file(), GetHeaderEntryValue(), gdcmFile::ParsePixelData(), ReadInt16(), gdcmFile::ReadPixelData(), and UnswapShort().

01194                                        {
01195    if ( (sw==4321)  || (sw==2143) )
01196       a =(((a<<8) & 0x0ff00) | ((a>>8)&0x00ff));
01197    return (a);
01198 }

void gdcmParser::SwitchSwapToBigEndian void   )  [private]
 

Definition at line 2183 of file gdcmParser.cxx.

References dbg, sw, and gdcmDebug::Verbose().

Referenced by FindHeaderEntryLength().

02184 {
02185    dbg.Verbose(1, "gdcmParser::SwitchSwapToBigEndian",
02186                   "Switching to BigEndian mode.");
02187    if ( sw == 0    ) 
02188    {
02189       sw = 4321;
02190       return;
02191    }
02192    if ( sw == 4321 ) 
02193    {
02194       sw = 0;
02195       return;
02196    }
02197    if ( sw == 3412 ) 
02198    {
02199       sw = 2143;
02200       return;
02201    }
02202    if ( sw == 2143 )
02203       sw = 3412;
02204 }

guint32 gdcmParser::UnswapLong guint32  a  ) 
 

Unswaps back the bytes of 4-byte long integer accordingly to processor order.

Returns:
The properly unswaped 32 bits integer.

Definition at line 1185 of file gdcmParser.cxx.

References SwapLong().

01185                                         {
01186    return (SwapLong(a));
01187 }

guint16 gdcmParser::UnswapShort guint16  a  ) 
 

Unswaps the bytes so they agree with the processor order.

Returns:
The properly unswaped 16 bits integer.

Definition at line 1205 of file gdcmParser.cxx.

References SwapShort().

01205                                          {
01206    return (SwapShort(a));
01207 }

void gdcmParser::UpdateGroupLength bool  SkipSequence = false,
FileType  type = ImplicitVR
[protected]
 

Re-computes the length of a ACR-NEMA/Dicom group from a DcmHeader.

Warning:
: to be re-written using the chained list instead of the H table.

: DO NOT use (doesn't work any longer because of the multimap)

Todo:
: to be re-written using the chained list instead of the H table
Parameters:
SkipSequence TRUE if we don't want to write Sequences (ACR-NEMA Files)
type Type of the File (ExplicitVR,ImplicitVR, ACR, ...)

Definition at line 892 of file gdcmParser.cxx.

References AddHeaderEntry(), ExplicitVR, gdcmHeaderEntry::GetElement(), gdcmHeaderEntry::GetGroup(), GetHeaderEntryByNumber(), gdcmHeaderEntry::GetLength(), gdcmHeaderEntry::GetVR(), GroupHT, GroupKey, gdcmHeaderEntry::SetLength(), gdcmHeaderEntry::SetValue(), tagHT, and TagKey.

00892                                                                    {
00893    guint16 gr, el;
00894    std::string vr;
00895    
00896    gdcmHeaderEntry *elem;
00897    char trash[10];
00898    std::string str_trash;
00899    
00900    GroupKey key;
00901    GroupHT groupHt;  // to hold the length of each group
00902    TagKey tk;
00903    // remember :
00904    // typedef std::map<GroupKey, int> GroupHT;
00905    
00906    gdcmHeaderEntry *elemZ;
00907   
00908    // for each Tag in the DCM Header
00909    
00910    for (TagHeaderEntryHT::iterator tag2 = tagHT.begin(); 
00911         tag2 != tagHT.end();
00912         ++tag2)
00913    {
00914       elem  = tag2->second;
00915       gr = elem->GetGroup();
00916       el = elem->GetElement();
00917       vr = elem->GetVR(); 
00918                  
00919       sprintf(trash, "%04x", gr);
00920       key = trash;              // generate 'group tag'
00921       
00922       // if the caller decided not to take SEQUENCEs into account 
00923       // e.g : he wants to write an ACR-NEMA File 
00924                 
00925       if (SkipSequence && vr == "SQ") 
00926          continue;
00927       
00928       // Still unsolved problem :
00929       // we cannot find the 'Sequence Delimitation Item'
00930       // since it's at the end of the Hash Table
00931       // (fffe,e0dd) 
00932        
00933       // pas SEQUENCE en ACR-NEMA
00934       // WARNING : 
00935       // --> la descente a l'interieur' des SQ 
00936       // devrait etre faite avec une liste chainee, pas avec une HTable...
00937             
00938       if ( groupHt.count(key) == 0) // we just read the first elem of a given group
00939       { 
00940          if (el == 0x0000) // the first elem is 0x0000
00941          {            
00942             groupHt[key] = 0;         // initialize group length 
00943          } 
00944          else 
00945          {
00946             groupHt[key] = 2 + 2 + 4 + elem->GetLength(); // non 0x0000 first group elem
00947          } 
00948       } 
00949       else // any elem but the first
00950       {   
00951          if (type == ExplicitVR) 
00952          {
00953             if ( (vr == "OB") || (vr == "OW") || (vr == "SQ") ) 
00954             {
00955                groupHt[key] +=  4; // explicit VR AND OB, OW, SQ : 4 more bytes
00956             }
00957          }
00958          groupHt[key] += 2 + 2 + 4 + elem->GetLength(); 
00959       } 
00960    }
00961 
00962    unsigned short int gr_bid;
00963   
00964    for (GroupHT::iterator g = groupHt.begin(); // for each group we found
00965         g != groupHt.end();
00966         ++g)
00967    { 
00968       // FIXME: g++ -Wall -Wstrict-prototypes reports on following line:
00969       //        warning: unsigned int format, different type arg
00970       sscanf(g->first.c_str(),"%x",&gr_bid);
00971       tk = g->first + "|0000";                  // generate the element full tag
00972                      
00973       if ( tagHT.count(tk) == 0) // if element 0x0000 not found
00974       {                 
00975          gdcmDictEntry * tagZ = new gdcmDictEntry(gr_bid, 0x0000, "UL");       
00976          elemZ = new gdcmHeaderEntry(tagZ);
00977          elemZ->SetLength(4);
00978          AddHeaderEntry(elemZ);                         // create it
00979       } 
00980       else 
00981       {
00982          elemZ=GetHeaderEntryByNumber(gr_bid, 0x0000);
00983       }     
00984       sprintf(trash ,"%d",g->second);
00985       str_trash=trash;
00986       elemZ->SetValue(str_trash);
00987    }   
00988 }

void gdcmParser::UpdateShaEntries void   )  [protected, virtual]
 

Update the entries with the shadow dictionary. Only non even entries are analyzed.

Reimplemented in gdcmHeader.

Definition at line 782 of file gdcmParser.cxx.

References CheckHeaderEntryVR(), gdcmDict::GetDictEntryByNumber(), GetHeaderEntryUnvalue(), GetHeaderEntryValue(), gdcmDictEntry::GetVR(), listEntries, NewVirtualDictEntry(), and RefShaDict.

Referenced by gdcmHeader::UpdateShaEntries().

00782                                       {
00783    gdcmDictEntry *entry;
00784    std::string vr;
00785 
00786    for(ListTag::iterator it=listEntries.begin();
00787        it!=listEntries.end();
00788        ++it)
00789    {
00790       // Odd group => from public dictionary
00791       if((*it)->GetGroup()%2==0)
00792          continue;
00793 
00794       // Peer group => search the corresponding dict entry
00795       if(RefShaDict)
00796          entry=RefShaDict->GetDictEntryByNumber((*it)->GetGroup(),(*it)->GetElement());
00797       else
00798          entry=NULL;
00799 
00800       if((*it)->IsImplicitVR())
00801          vr="Implicit";
00802       else
00803          vr=(*it)->GetVR();
00804 
00805       (*it)->SetValue(GetHeaderEntryUnvalue(*it));
00806       if(entry){
00807          // Set the new entry and the new value
00808          (*it)->SetDictEntry(entry);
00809          CheckHeaderEntryVR(*it,vr);
00810 
00811          (*it)->SetValue(GetHeaderEntryValue(*it));
00812       }
00813       else
00814       {
00815          // Remove precedent value transformation
00816          (*it)->SetDictEntry(NewVirtualDictEntry((*it)->GetGroup(),(*it)->GetElement(),vr));
00817       }
00818    }
00819 }

bool gdcmParser::Write FILE *  fp,
FileType  type
[virtual]
 

Parameters:
fp file pointer on an already open file
type type of the File to be written (ACR-NEMA, ExplicitVR, ImplicitVR)
Returns:
always "True" ?!

Definition at line 381 of file gdcmParser.cxx.

References ExplicitVR, ReplaceOrCreateByNumber(), SetEntryLengthByNumber(), UI1_2_840_10008_1_2, UI1_2_840_10008_1_2_1, and WriteEntries().

Referenced by gdcmFile::WriteBase().

00381                                               {
00382 // ==============
00383 // TODO The stuff was rewritten using the chained list instead 
00384 //      of the H table
00385 //      so we could remove the GroupHT from the gdcmParser
00386 // To be checked
00387 // =============
00388 
00389    // TODO : move the following lines (and a lot of others, to be written)
00390    // to a future function CheckAndCorrectHeader
00391    
00392         // Question :
00393         // Comment pourrait-on savoir si le DcmHeader vient d'un fichier DicomV3 ou non
00394         // (FileType est un champ de gdcmParser ...)
00395         // WARNING : Si on veut ecrire du DICOM V3 a partir d'un DcmHeader ACR-NEMA
00396         // no way 
00397         // a moins de se livrer a un tres complique ajout des champs manquants.
00398         // faire un CheckAndCorrectHeader (?)  
00399          
00400 
00401    if (type == ImplicitVR) 
00402    {
00403       std::string implicitVRTransfertSyntax = UI1_2_840_10008_1_2;
00404       ReplaceOrCreateByNumber(implicitVRTransfertSyntax,0x0002, 0x0010);
00405       
00406       //FIXME Refer to standards on page 21, chapter 6.2 "Value representation":
00407       //      values with a VR of UI shall be padded with a single trailing null
00408       //      Dans le cas suivant on doit pader manuellement avec un 0
00409       
00410       SetEntryLengthByNumber(18, 0x0002, 0x0010);
00411    } 
00412 
00413    if (type == ExplicitVR) 
00414    {
00415       std::string explicitVRTransfertSyntax = UI1_2_840_10008_1_2_1;
00416       ReplaceOrCreateByNumber(explicitVRTransfertSyntax,0x0002, 0x0010);
00417       
00418       //FIXME Refer to standards on page 21, chapter 6.2 "Value representation":
00419       //      values with a VR of UI shall be padded with a single trailing null
00420       //      Dans le cas suivant on doit pader manuellement avec un 0
00421       
00422       SetEntryLengthByNumber(20, 0x0002, 0x0010);
00423    }
00424 
00425 /* TODO : rewrite later
00426 
00427    if ( (type == ImplicitVR) || (type == ExplicitVR) )
00428       UpdateGroupLength(false,type);
00429    if ( type == ACR)
00430       UpdateGroupLength(true,ACR);
00431 */
00432 
00433    WriteEntries(fp,type);
00434    return(true);
00435  }

void gdcmParser::WriteEntries FILE *  _fp,
FileType  type
[protected]
 

writes on disc according to the requested format (ACR-NEMA, ExplicitVR, ImplicitVR) the image

Warning:
does NOT add the missing elements in the header : it's up to the user doing it ! (function CheckHeaderCoherence to be written)

DON'T try, right now, to write a DICOM image from an ACR Header (meta elements will be missing!)

Parameters:
type type of the File to be written (ACR-NEMA, ExplicitVR, ImplicitVR)
_fp already open file pointer

Definition at line 1003 of file gdcmParser.cxx.

References ACR, countGrPixel, DICOMDIR, ExplicitVR, GrPixel, listEntries, NumPixel, and Tokenize().

Referenced by Write(), and gdcmDicomDir::Write().

01004 {
01005    guint16 gr, el;
01006    guint32 lgr;
01007    std::string value;
01008    const char * val;
01009    std::string vr;
01010    guint32 val_uint32;
01011    guint16 val_uint16;
01012    guint16 valZero =0;
01013    void *voidArea;
01014    std::vector<std::string> tokens;
01015    
01016    // TODO : function CheckHeaderCoherence to be written
01017    
01018    //  uses now listEntries to iterate, not TagHt!
01019    //
01020    //        pb : gdcmParser.Add does NOT update listEntries
01021    //       TODO : find a trick (in STL?) to do it, at low cost !
01022 
01023    void *ptr;
01024 
01025    // TODO (?) tester les echecs en ecriture (apres chaque fwrite)
01026    int compte =0;
01027    
01028    for (ListTag::iterator tag2=listEntries.begin();
01029         tag2 != listEntries.end();
01030         ++tag2)
01031    {
01032       // === Deal with the length
01033       //     --------------------
01034       if(((*tag2)->GetLength())%2==1)
01035       {
01036          (*tag2)->SetValue((*tag2)->GetValue()+"\0");
01037          (*tag2)->SetLength((*tag2)->GetLength()+1);
01038       }
01039 
01040       gr    = (*tag2)->GetGroup();
01041       el    = (*tag2)->GetElement();
01042       lgr   = (*tag2)->GetReadLength();
01043       val   = (*tag2)->GetValue().c_str();
01044       vr    = (*tag2)->GetVR();
01045       voidArea = (*tag2)->GetVoidArea();
01046       
01047       if ( type == ACR ) 
01048       { 
01049          if (gr < 0x0008)   continue; // ignore pure DICOM V3 groups
01050          if (gr %2)         continue; // ignore shadow groups
01051          if (vr == "SQ" )   continue; // ignore Sequences
01052                    // TODO : find a trick to *skip* the SeQuences !
01053                    // Not only ignore the SQ element
01054          if (gr == 0xfffe ) continue; // ignore delimiters
01055       } 
01056 
01057       fwrite ( &gr,(size_t)2 ,(size_t)1 ,_fp);  //group
01058       fwrite ( &el,(size_t)2 ,(size_t)1 ,_fp);  //element
01059       
01060       // if ( (type == ExplicitVR) && (gr <= 0x0002) ) // ?!?  < 2  
01061       if ( (type == ExplicitVR) || (type == DICOMDIR) )      
01062       {
01063          // EXPLICIT VR
01064          guint16 z=0, shortLgr;
01065          if (vr == "unkn") 
01066          { // Unknown was 'written'      
01067             shortLgr=lgr;
01068             fwrite ( &shortLgr,(size_t)2 ,(size_t)1 ,_fp);
01069             fwrite ( &z,  (size_t)2 ,(size_t)1 ,_fp);
01070          } 
01071          else 
01072          {
01073             if (gr != 0xfffe) 
01074             { // NO value for 'delimiters'
01075                if (vr == "unkn") // Unknown was 'written'
01076                   fwrite(&z,(size_t)2 ,(size_t)1 ,_fp);
01077                else      
01078                   fwrite (vr.c_str(),(size_t)2 ,(size_t)1 ,_fp);
01079             }
01080 
01081             if ( (vr == "OB") || (vr == "OW") || (vr == "SQ") || gr == 0xfffe)
01082             {
01083                if (gr != 0xfffe)
01084                   fwrite ( &z,  (size_t)2 ,(size_t)1 ,_fp);
01085                   fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp);
01086             } 
01087             else 
01088             {
01089                shortLgr=lgr;
01090                fwrite ( &shortLgr,(size_t)2 ,(size_t)1 ,_fp);
01091             }
01092          }
01093       } 
01094       else // IMPLICIT VR 
01095       { 
01096          fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp);
01097       }
01098       
01099       // === Deal with the value
01100       //     -------------------
01101       if (vr == "SQ")  continue; // no "value" to write for the SEQuences
01102       if (gr == 0xfffe)continue;
01103       
01104       if (voidArea != NULL) 
01105       { // there is a 'non string' LUT, overlay, etc
01106          fwrite ( voidArea,(size_t)lgr ,(size_t)1 ,_fp); // Elem value
01107          continue;            
01108       }
01109       
01110       if (vr == "US" || vr == "SS") 
01111       {
01112          tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
01113          Tokenize ((*tag2)->GetValue(), tokens, "\\");
01114          for (unsigned int i=0; i<tokens.size();i++) 
01115          {
01116             val_uint16 = atoi(tokens[i].c_str());
01117             ptr = &val_uint16;
01118             fwrite ( ptr,(size_t)2 ,(size_t)1 ,_fp);
01119          }
01120          tokens.clear();
01121          continue;
01122       }
01123       if (vr == "UL" || vr == "SL") 
01124       {
01125          tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
01126          Tokenize ((*tag2)->GetValue(), tokens, "\\");
01127          for (unsigned int i=0; i<tokens.size();i++) 
01128          {
01129             val_uint32 = atoi(tokens[i].c_str());
01130             ptr = &val_uint32;
01131             fwrite ( ptr,(size_t)4 ,(size_t)1 ,_fp);
01132          }
01133          tokens.clear();
01134          continue;
01135       } 
01136           
01137       // Pixels are never loaded in the element !
01138       // we stop writting when Pixel are processed
01139       // FIX : we loose trailing elements (RAB, right now)           
01140             
01141       if ((gr == GrPixel) && (el == NumPixel) ) {
01142          compte++;
01143          if (compte == countGrPixel) // we passed *all* the GrPixel,NumPixel   
01144             break;
01145       }       
01146       fwrite ( val,(size_t)lgr ,(size_t)1 ,_fp); // Elem value
01147    }
01148 }


Member Data Documentation

int gdcmParser::countGrPixel [protected]
 

Definition at line 160 of file gdcmParser.h.

Referenced by WriteEntries().

int gdcmParser::enableSequences [protected]
 

Definition at line 152 of file gdcmParser.h.

Referenced by FixHeaderEntryFoundLength(), and gdcmParser().

std::string gdcmParser::filename [private]
 

Definition at line 215 of file gdcmParser.h.

FileType gdcmParser::filetype [protected]
 

Definition at line 142 of file gdcmParser.h.

Referenced by CheckSwap(), FindHeaderEntryLength(), FindHeaderEntryVR(), GetFileType(), IsReadable(), and LoadHeaderEntries().

FILE* gdcmParser::fp [protected]
 

Definition at line 141 of file gdcmParser.h.

Referenced by CheckSwap(), CloseFile(), FindHeaderEntryLength(), FindHeaderEntryLengthOB(), FindHeaderEntryVR(), IsHeaderEntryAnInteger(), LoadEntryVoidArea(), LoadHeaderEntries(), LoadHeaderEntry(), LoadHeaderEntrySafe(), ReadInt16(), ReadInt32(), ReadNextHeaderEntry(), and SkipBytes().

guint16 gdcmParser::GrPixel [protected]
 

Definition at line 156 of file gdcmParser.h.

Referenced by FindHeaderEntryLength(), and WriteEntries().

const unsigned int gdcmParser::HEADER_LENGTH_TO_READ = 256 [static, protected]
 

Definition at line 69 of file gdcmParser.cxx.

Referenced by CheckSwap().

int gdcmParser::ignoreShadow [private]
 

Definition at line 226 of file gdcmParser.h.

Referenced by gdcmParser().

ListTag gdcmParser::listEntries [protected]
 

Definition at line 150 of file gdcmParser.h.

Referenced by AddHeaderEntry(), IsReadable(), PrintEntry(), UpdateShaEntries(), and WriteEntries().

const unsigned int gdcmParser::MAX_SIZE_LOAD_ELEMENT_VALUE = 4096 [static, protected]
 

Definition at line 72 of file gdcmParser.cxx.

Referenced by gdcmParser().

const unsigned int gdcmParser::MAX_SIZE_PRINT_ELEMENT_VALUE = 64 [static, protected]
 

Definition at line 76 of file gdcmParser.cxx.

guint32 gdcmParser::MaxSizeLoadEntry [private]
 

Definition at line 236 of file gdcmParser.h.

Referenced by LoadHeaderEntry(), and SetMaxSizeLoadEntry().

guint32 gdcmParser::MaxSizePrintEntry [private]
 

Definition at line 240 of file gdcmParser.h.

Referenced by SetMaxSizePrintEntry().

guint16 gdcmParser::NumPixel [protected]
 

Definition at line 157 of file gdcmParser.h.

Referenced by FindHeaderEntryLength(), and WriteEntries().

int gdcmParser::printLevel [protected]
 

Definition at line 153 of file gdcmParser.h.

gdcmDict* gdcmParser::RefPubDict [private]
 

Definition at line 218 of file gdcmParser.h.

Referenced by GetDictEntryByName(), GetDictEntryByNumber(), GetEntryByName(), GetEntryVRByName(), GetHeaderEntryByName(), GetPubDict(), Initialise(), PrintPubDict(), SetEntryByName(), and ~gdcmParser().

gdcmDict* gdcmParser::RefShaDict [private]
 

Definition at line 220 of file gdcmParser.h.

Referenced by GetDictEntryByName(), GetDictEntryByNumber(), GetShaDict(), Initialise(), PrintShaDict(), SetShaDict(), UpdateShaEntries(), and ~gdcmParser().

int gdcmParser::sw [private]
 

Definition at line 230 of file gdcmParser.h.

Referenced by CheckSwap(), SwapLong(), SwapShort(), and SwitchSwapToBigEndian().

TagHeaderEntryHT gdcmParser::tagHT [protected]
 

Definition at line 149 of file gdcmParser.h.

Referenced by AddHeaderEntry(), CheckIfEntryExistByNumber(), GenerateFreeTagKeyInGroup(), GetEntryByNumber(), GetHeaderEntryByNumber(), GetHeaderEntrySameNumber(), SetEntryByNumber(), SetEntryLengthByNumber(), SetEntryVoidAreaByNumber(), and UpdateGroupLength().

int gdcmParser::wasUpdated [private]
 

Definition at line 223 of file gdcmParser.h.

Referenced by AddHeaderEntry(), and gdcmParser().


The documentation for this class was generated from the following files:
Generated on Mon Feb 14 16:13:39 2005 for gdcm by doxygen 1.3.6