X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmDocument.cxx;h=3b4c2d4a7c9ccef460ac9a6274d43ec550fd797e;hb=9f596ccd6001b165eca959c6a7b104eb10ff9911;hp=7a987771e99c1aa8d9424f5c86e322bad6e752af;hpb=801fe2221ca70b34c5c644b6f522aa1b7233945b;p=gdcm.git diff --git a/src/gdcmDocument.cxx b/src/gdcmDocument.cxx index 7a987771..3b4c2d4a 100644 --- a/src/gdcmDocument.cxx +++ b/src/gdcmDocument.cxx @@ -414,10 +414,9 @@ bool gdcmDocument::Write(FILE *fp, FileType type) { /** * \brief Modifies the value of a given Header Entry (Dicom Element) * when it exists. Create it with the given value when unexistant. - * \warning Adds the Header Entry to the HTable, NOT to the chained List * @param Value Value to be set - * @param Group Group of the Entry - * @param Elem Element of the Entry + * @param Group Group number of the Entry + * @param Elem Element number of the Entry * \return pointer to the modified/created Header Entry (NULL when creation * failed). */ @@ -444,8 +443,8 @@ gdcmDocEntry * gdcmDocument::ReplaceOrCreateByNumber( * \brief Set a new value if the invoked element exists * Seems to be useless !!! * @param Value new element value - * @param Group group of the Entry - * @param Elem element of the Entry + * @param Group group number of the Entry + * @param Elem element number of the Entry * \return boolean */ bool gdcmDocument::ReplaceIfExistByNumber(char* Value, guint16 Group, guint16 Elem ) @@ -459,9 +458,8 @@ bool gdcmDocument::ReplaceIfExistByNumber(char* Value, guint16 Group, guint16 El // Protected /** - * \brief Checks if a given Dicom Element exists - * within the H table - * @param group Group number of the searched Dicom Element + * \brief Checks if a given Dicom Element exists within the H table + * @param group Group number of the searched Dicom Element * @param element Element number of the searched Dicom Element * @return number of occurences */ @@ -515,8 +513,8 @@ std::string gdcmDocument::GetEntryVRByName(std::string tagName) { * \brief Searches within Header Entries (Dicom Elements) parsed with * the public and private dictionaries * for the element value representation of a given tag. - * @param group Group of the searched tag. - * @param element Element of the searched tag. + * @param group Group number of the searched tag. + * @param element Element number of the searched tag. * @return Corresponding element value representation when it exists, * and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise. */ @@ -536,8 +534,8 @@ std::string gdcmDocument::GetEntryByNumber(guint16 group, guint16 element){ * 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. - * @param group Group of the searched tag. - * @param element Element of the searched tag. + * @param group Group number of the searched tag. + * @param element Element number of the searched tag. * @return Corresponding element value representation when it exists, * and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise. */ @@ -552,8 +550,8 @@ std::string gdcmDocument::GetEntryVRByNumber(guint16 group, guint16 element) { * \brief Searches within Header Entries (Dicom Elements) parsed with * the public and private dictionaries * for the value length of a given tag.. - * @param group Group of the searched tag. - * @param element Element of the searched tag. + * @param group Group number of the searched tag. + * @param element Element number of the searched tag. * @return Corresponding element length; -2 if not found */ int gdcmDocument::GetEntryLengthByNumber(guint16 group, guint16 element) { @@ -582,8 +580,8 @@ bool gdcmDocument::SetEntryByName(std::string content,std::string tagName) { * through it's (group, element) and modifies it's content with * the given value. * @param content new value to substitute with - * @param group group of the Dicom Element to modify - * @param element element of the Dicom Element to modify + * @param group group number of the Dicom Element to modify + * @param element element number of the Dicom Element to modify */ bool gdcmDocument::SetEntryByNumber(std::string content, guint16 group, @@ -625,8 +623,8 @@ bool gdcmDocument::SetEntryByNumber(std::string content, * the given value. * \warning Use with extreme caution. * @param l new length to substitute with - * @param group group of the Entry to modify - * @param element element of the Entry to modify + * @param group group number of the Entry to modify + * @param element element number of the Entry to modify * @return true on success, false otherwise. */ bool gdcmDocument::SetEntryLengthByNumber(guint32 l, @@ -645,8 +643,8 @@ bool gdcmDocument::SetEntryLengthByNumber(guint32 l, /** * \brief Gets (from Header) the offset of a 'non string' element value * (LoadElementValues has already be executed) - * @param Group group of the Entry - * @param Elem element of the Entry + * @param Group group number of the Entry + * @param Elem element number of the Entry * @return File Offset of the Element Value */ size_t gdcmDocument::GetEntryOffsetByNumber(guint16 Group, guint16 Elem) @@ -664,8 +662,8 @@ size_t gdcmDocument::GetEntryOffsetByNumber(guint16 Group, guint16 Elem) /** * \brief Gets (from Header) a 'non string' element value * (LoadElementValues has already be executed) - * @param Group group of the Entry - * @param Elem element of the Entry + * @param Group group number of the Entry + * @param Elem element number of the Entry * @return Pointer to the 'non string' area */ void * gdcmDocument::GetEntryVoidAreaByNumber(guint16 Group, guint16 Elem) @@ -683,8 +681,8 @@ void * gdcmDocument::GetEntryVoidAreaByNumber(guint16 Group, guint16 Elem) /** * \brief Loads (from disk) the element content * when a string is not suitable - * @param Group group of the Entry - * @param Elem element of the Entry + * @param Group group number of the Entry + * @param Elem element number of the Entry */ void *gdcmDocument::LoadEntryVoidArea(guint16 Group, guint16 Elem) { @@ -713,7 +711,7 @@ void *gdcmDocument::LoadEntryVoidArea(guint16 Group, guint16 Elem) /** * \brief Sets a 'non string' value to a given Dicom Element * @param area - * @param group Group number of the searched Dicom Element + * @param group Group number of the searched Dicom Element * @param element Element number of the searched Dicom Element * @return */ @@ -909,15 +907,23 @@ void gdcmDocument::WriteEntryValue(gdcmDocEntry *tag, FILE *_fp,FileType type) if (group == 0xfffe) // Delimiters have no associated value: return; - + + //-------------------------------- + // + // FIXME + // + // ------------------------------- + + +/* // to go on compiling void *voidArea; - // voidArea = tag->GetVoidArea(); // to go on compiling + voidArea = tag->GetVoidArea(); // to go on compiling if (voidArea != NULL) { // there is a 'non string' LUT, overlay, etc fwrite ( voidArea,(size_t)lgr ,(size_t)1 ,_fp); // Elem value return; } - +*/ if (vr == "US" || vr == "SS") { // some 'Short integer' fields may be mulivaluated @@ -967,17 +973,20 @@ void gdcmDocument::WriteEntryValue(gdcmDocEntry *tag, FILE *_fp,FileType type) bool gdcmDocument::WriteEntry(gdcmDocEntry *tag, FILE *_fp,FileType type) { guint32 length = tag->GetLength(); - + gdcmValEntry * Vtag = (gdcmValEntry *) tag; +std::cout << "gdcmDocument::WriteEntry Vtag->GetValue() " << Vtag->GetValue() << std::endl; // The value of a tag MUST (see the DICOM norm) be an odd number of // bytes. When this is not the case, pad with an additional byte: if(length%2==1) { -// tag->SetValue(tag->GetValue()+"\0"); // to go on compiling - tag->SetLength(tag->GetReadLength()+1); + Vtag->SetValue(Vtag->GetValue()+"\0"); + Vtag->SetLength(Vtag->GetReadLength()+1); } - WriteEntryTagVRLength(tag, _fp, type); - WriteEntryValue(tag, _fp, type); + WriteEntryTagVRLength(Vtag, _fp, type); + std::cout << "after WriteEntryTagVRLength " << std::endl; + WriteEntryValue(Vtag, _fp, type); + std::cout << "after WriteEntryValue " << std::endl; return true; } @@ -990,7 +999,6 @@ bool gdcmDocument::WriteEntry(gdcmDocEntry *tag, FILE *_fp,FileType type) * (function CheckHeaderCoherence to be written) * \warning DON'T try, right now, to write a DICOM image * from an ACR Header (meta elements will be missing!) - * \sa WriteEntriesDeprecated (Special temporary method for Theralys) * @param type type of the File to be written * (ACR-NEMA, ExplicitVR, ImplicitVR) * @param _fp already open file pointer @@ -1002,25 +1010,33 @@ bool gdcmDocument::WriteEntries(FILE *_fp,FileType type) // FIXME : explore recursively the whole structure... /// \todo (?) check write failures (after *each* fwrite) - + + std::cout << "--------------------- gdcmDocument::WriteEntries " << std::endl; for (TagDocEntryHT::iterator tag2=tagHT.begin(); tag2 != tagHT.end(); ++tag2) { + + (*tag2).second->Print(); + if ( type == gdcmACR ){ if ((*tag2).second->GetGroup() < 0x0008) // Ignore pure DICOM V3 groups continue; - if ((*tag2).second->GetElement() %2) + if ((*tag2).second->GetGroup() %2) // Ignore the "shadow" groups continue; if ((*tag2).second->GetVR() == "SQ" ) // ignore Sequences continue; - if ((*tag2).second->GetSQDepthLevel() != 0) // Not only ignore the SQ element - continue; + //if ((*tag2).second->GetDepthLevel() != 0) // Not only ignore the SQ element + // continue; } - if (! WriteEntry((*tag2).second,_fp,type) ) + if (! WriteEntry((*tag2).second,_fp,type) ) { + std::cout << "Write Failure " << std::endl; return false; + } else { + + } } return true; } @@ -1096,7 +1112,7 @@ long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool gdcmValEntry *vl; gdcmBinEntry *bn; gdcmSeqEntry *sq; - std::string vr; + VRKey vr; long l; int depth; @@ -1109,55 +1125,55 @@ long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool NewDocEntry = ReadNextDocEntry( ); if (!NewDocEntry) break; - - vr = NewDocEntry->GetVR(); + + vr = NewDocEntry->GetVR(); if (vr!="SQ") { - if (vr == "AE" || vr == "AS" || vr == "DA" || vr == "PN" || - vr == "UI" || vr == "TM" || vr == "SH" || vr == "LO" || - vr == "CS" || vr == "IS" || vr == "LO" || vr == "LT" || - vr == "SH" || vr == "ST" || vr == "DS" || - vr == "SL" || vr == "SS" || vr == "UL" || vr == "US" - ) { - // --- ValEntry + if ( gdcmGlobal::GetVR()->IsVROfGdcmStringRepresentable(vr) ) + { + /////// ValEntry vl= new gdcmValEntry(NewDocEntry->GetDictEntry()); - vl->Copy(NewDocEntry); - vl->SetDepthLevel(depth), - set->AddEntry(vl); - LoadDocEntry(vl); + vl->Copy(NewDocEntry); + vl->SetDepthLevel(depth); + set->AddEntry(vl); + LoadDocEntry(vl); if (/*!delim_mode && */vl->isItemDelimitor()) break; - if ( !delim_mode && ftell(fp)-offset >= l_max) { + if ( !delim_mode && ftell(fp)-offset >= l_max) + { break; - } - } else { // BinEntry - - // Hope the following VR *do* correspond to a BinEntry - - //AT Attribute Tag; // 2 16-bit unsigned short integers - //FL Floating Point Single; // 32-bit IEEE 754:1985 float - //FD Floating Point Double; // 64-bit IEEE 754:1985 double - //UN Unknown; // Any length of bytes - //UT Unlimited Text; // At most 2^32 -1 chars - //OB Other Byte String; // String of bytes (VR independant) - //OW Other Word String; // String of 16-bit words (VR dependant) - + } + } + else + { + if ( ! gdcmGlobal::GetVR()->IsVROfGdcmBinaryRepresentable(vr) ) + { + ////// Neither ValEntry NOR BinEntry: should mean UNKOWN VR + dbg.Verbose(0, "gdcmDocument::ParseDES: neither Valentry, " + "nor BinEntry. Probably unknown VR."); + } + + ////// BinEntry or UNKOWN VR: bn = new gdcmBinEntry(NewDocEntry->GetDictEntry()); - bn->Copy(NewDocEntry); - set->AddEntry(bn); - LoadDocEntry(bn); - } - if (NewDocEntry->GetGroup() == 0x7fe0 && - NewDocEntry->GetElement() == 0x0010 ) { - if (NewDocEntry->GetLength()==0xffffffff) - // Broke US.3405.1.dcm - + bn->Copy(NewDocEntry); + set->AddEntry(bn); + LoadDocEntry(bn); + } + + if (NewDocEntry->GetGroup() == 0x7fe0 && + NewDocEntry->GetElement() == 0x0010 ) + { + if (NewDocEntry->GetLength()==0xffffffff) + // Broken US.3405.1.dcm Parse7FE0(); // to skip the pixels - // (multipart JPEG/RLE are trouble makers) - } else { - SkipToNextDocEntry(NewDocEntry); // to be sure we are at the beginning - l = NewDocEntry->GetFullLength(); - } + // (multipart JPEG/RLE are trouble makers) + } + else + { + // to be sure we are at the beginning + SkipToNextDocEntry(NewDocEntry); + l = NewDocEntry->GetFullLength(); + } } else { // VR = "SQ" l=NewDocEntry->GetReadLength(); @@ -1166,24 +1182,26 @@ long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool delim_mode = true; else delim_mode = false; - // no other way to create it ... - sq = new gdcmSeqEntry(NewDocEntry->GetDictEntry(),set->GetDepthLevel()); + // no other way to create it ... + sq = new gdcmSeqEntry(NewDocEntry->GetDictEntry(), + set->GetDepthLevel()); sq->Copy(NewDocEntry); - sq->SetDelimitorMode(delim_mode); - sq->SetDepthLevel(depth); + sq->SetDelimitorMode(delim_mode); + sq->SetDepthLevel(depth); - if (l != 0) { // Don't try to parse zero-length sequences - + if (l != 0) + { // Don't try to parse zero-length sequences long lgt = ParseSQ( sq, NewDocEntry->GetOffset(), l, delim_mode); - } - // FIXME : on en fait quoi, de lgt ? + } + // FIXME : on en fait quoi, de lgt ? set->AddEntry(sq); - if ( !delim_mode && ftell(fp)-offset >= l_max) { + if ( !delim_mode && ftell(fp)-offset >= l_max) + { break; - } - } + } + } } delete NewDocEntry; return l; // ?? @@ -1269,8 +1287,15 @@ void gdcmDocument::LoadDocEntry(gdcmDocEntry *Entry) { // are not loaded. Instead we leave a short notice of the offset of // the element content and it's length. if (length > MaxSizeLoadEntry) { - std::ostringstream s; - ((gdcmValEntry *)Entry)->SetValue(s.str()); + if (gdcmValEntry* ValEntryPtr = dynamic_cast< gdcmValEntry* >(Entry) ) + { + std::ostringstream s; + s << "gdcm::NotLoaded."; + s << " Address:" << (long)Entry->GetOffset(); + s << " Length:" << Entry->GetLength(); + s << " x(" << std::hex << Entry->GetLength() << ")"; + ValEntryPtr->SetValue(s.str()); + } // to be sure we are at the end of the value ... fseek(fp,(long)Entry->GetOffset()+(long)Entry->GetLength(),SEEK_SET); @@ -2238,8 +2263,8 @@ gdcmDocEntry *gdcmDocument::NewDocEntryByName(std::string Name) /** * \brief Request a new virtual dict entry to the dict set - * @param group group of the underlying DictEntry - * @param element element of the underlying DictEntry + * @param group group number of the underlying DictEntry + * @param element element number of the underlying DictEntry * @param vr VR of the underlying DictEntry * @param fourth owner group * @param name english name @@ -2256,8 +2281,8 @@ gdcmDictEntry *gdcmDocument::NewVirtualDictEntry(guint16 group, guint16 element, * \brief Build a new Element Value from all the low level arguments. * Check for existence of dictionary entry, and build * a default one when absent. - * @param Group group of the underlying DictEntry - * @param Elem element of the underlying DictEntry + * @param Group group number of the underlying DictEntry + * @param Elem element number of the underlying DictEntry */ gdcmDocEntry *gdcmDocument::NewDocEntryByNumber(guint16 Group, guint16 Elem) {