From: frog Date: Tue, 30 Mar 2004 09:16:26 +0000 (+0000) Subject: * src/gdcmParser.[cxx|h] and gdcmHeader.[cxx.h]: gdcmHeader::Write split X-Git-Tag: Version0.5.bp~263 X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=commitdiff_plain;h=4f48626ba6d2dc26d40f07b780b0fdb5fcc04911;p=gdcm.git * src/gdcmParser.[cxx|h] and gdcmHeader.[cxx.h]: gdcmHeader::Write split in WriteEntryTagVRLength and WriteEntryValue. Those methods were moved to base class gdcmParser and only the specialisation is kept in gdcmHeader. * src/gdcmParser.[cxx|h]: ReplaceOrCreateByNumber(char*, guint16, guint16) trashed out (because ReplaceOrCreateByNumber(string, guint16, guint16) allready does the job. * src/gdcmDicomDir.[cxx|h]: WriteDicomDirEntries renamed to WriteEntries (to be consistent with gdcmParser::WriteEntries). --- diff --git a/ChangeLog b/ChangeLog index 61e8b554..facb56e7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2004-03-30 Eric Boix + * src/gdcmParser.[cxx|h] and gdcmHeader.[cxx.h]: gdcmHeader::Write split + in WriteEntryTagVRLength and WriteEntryValue. Those methods were + moved to base class gdcmParser and only the specialisation is kept + in gdcmHeader. + * src/gdcmParser.[cxx|h]: ReplaceOrCreateByNumber(char*, guint16, guint16) + trashed out (because ReplaceOrCreateByNumber(string, guint16, guint16) + allready does the job. + * src/gdcmDicomDir.[cxx|h]: WriteDicomDirEntries renamed to WriteEntries + (to be consistent with gdcmParser::WriteEntries). + 2004-03-30 Benoit Regrain * vtk/vtkGdcmReader.[h|cxx] : fix the read of 3 gdcmHeader when making an upate of the object's instance. It's passed to 2 in the unfavorable diff --git a/src/gdcmDicomDir.cxx b/src/gdcmDicomDir.cxx index 44214cbb..fb566c62 100644 --- a/src/gdcmDicomDir.cxx +++ b/src/gdcmDicomDir.cxx @@ -313,20 +313,18 @@ bool gdcmDicomDir::Write(std::string fileName) fwrite("DICM",4,1,fp1); free(filePreamble); UpdateDirectoryRecordSequenceLength(); - WriteDicomDirEntries(fp1); + WriteEntries(fp1); fclose(fp1); return true; } /** - * \ingroup gdcmParser - * \brief writes on disc according to the DICOMDIR format - * using the tree-like structure + * \brief Writes in a file using the tree-like structure. * @param _fp already open file pointer */ -void gdcmDicomDir::WriteDicomDirEntries(FILE *_fp) +void gdcmDicomDir::WriteEntries(FILE *_fp) { // TODO (?) tester les echecs en ecriture // (apres chaque fwrite, dans le WriteEntry) diff --git a/src/gdcmDicomDir.h b/src/gdcmDicomDir.h index d8621641..d2d02487 100644 --- a/src/gdcmDicomDir.h +++ b/src/gdcmDicomDir.h @@ -24,7 +24,6 @@ typedef GDCM_EXPORT void(gdcmMethod)(void * = NULL); * \brief gdcmDicomDir defines an object representing a DICOMDIR in memory. * */ - class GDCM_EXPORT gdcmDicomDir: public gdcmParser { public: @@ -97,6 +96,7 @@ public: gdcmDicomDirPatient * NewPatient(void); // Write + void WriteEntries(FILE *_fp); bool Write(std::string fileName); /// Types of the gdcmObject within the gdcmDicomDir @@ -133,7 +133,6 @@ private: void UpdateDirectoryRecordSequenceLength(void); static bool HeaderLessThan(gdcmHeader *header1,gdcmHeader *header2); - void WriteDicomDirEntries(FILE *_fp); // Variables /** diff --git a/src/gdcmHeader.cxx b/src/gdcmHeader.cxx index 1bbac5c4..9d7f6a11 100644 --- a/src/gdcmHeader.cxx +++ b/src/gdcmHeader.cxx @@ -574,7 +574,7 @@ unsigned char * gdcmHeader::GetLUTRGBA(void) { // if Photometric Interpretation # PALETTE COLOR, no LUT to be done if (GetEntryByNumber(0x0028,0x0004) != "PALETTE COLOR ") { - return NULL; + return NULL; } int lengthR, debR, nbitsR; int lengthG, debG, nbitsG; @@ -624,7 +624,7 @@ unsigned char * gdcmHeader::GetLUTRGBA(void) { GetEntryVoidAreaByNumber(0x0028,0x1203); if (!lutR || !lutG || !lutB ) { - return NULL; + return NULL; } // forge the 4 * 8 Bits Red/Green/Blue/Alpha LUT @@ -633,7 +633,7 @@ unsigned char * gdcmHeader::GetLUTRGBA(void) { return NULL; } memset(LUTRGBA, 0, 1024); - // Bits Allocated + // Bits Allocated int nb; std::string str_nb = GetEntryByNumber(0x0028,0x0100); if (str_nb == GDCM_UNFOUND ) { @@ -714,17 +714,17 @@ std::string gdcmHeader::GetTransfertSyntaxName(void) { void gdcmHeader::SetImageDataSize(size_t ImageDataSize) { std::string content1; char car[20]; - + // Assumes HeaderEntry (GrPixel, NumPixel) is unique ... - // TODO deal with multiplicity (see gdcmData/icone.dcm) + // TODO deal with multiplicity (see gdcmData/icone.dcm) sprintf(car,"%d",ImageDataSize); gdcmHeaderEntry *a = GetHeaderEntryByNumber(GrPixel, NumPixel); a->SetLength(ImageDataSize); - + ImageDataSize+=8; sprintf(car,"%d",ImageDataSize); - content1=car; + content1=car; SetEntryByNumber(content1, GrPixel, NumPixel); } @@ -745,30 +745,30 @@ void gdcmHeader::SetImageDataSize(size_t ImageDataSize) { s1=this->GetEntryByNumber(0x0010,0x0010); s2=header.GetEntryByNumber(0x0010,0x0010); if(s1 < s2) - return(true); + return(true); else if(s1 > s2) - return(false); + return(false); else { // Patient ID s1=this->GetEntryByNumber(0x0010,0x0020); s2=header.GetEntryByNumber(0x0010,0x0020); if (s1 < s2) - return(true); + return(true); else if (s1 > s2) return(1); else { - // Study Instance UID + // Study Instance UID s1=this->GetEntryByNumber(0x0020,0x000d); s2=header.GetEntryByNumber(0x0020,0x000d); if (s1 < s2) - return(true); + return(true); else if(s1 > s2) - return(false); + return(false); else { - // Serie Instance UID + // Serie Instance UID s1=this->GetEntryByNumber(0x0020,0x000e); s2=header.GetEntryByNumber(0x0020,0x000e); if (s1 < s2) @@ -781,6 +781,36 @@ void gdcmHeader::SetImageDataSize(size_t ImageDataSize) { return(false); } +bool gdcmHeader::WriteEntry(gdcmHeaderEntry *tag, FILE *_fp,FileType type) +{ + guint32 length = tag->GetLength(); + + // 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"); + tag->SetLength(tag->GetReadLength()+1); + } + + WriteEntryTagVRLength(tag, _fp, type); + + // Pixels are never loaded in the element ! + // we stop writting when Pixel are processed + // FIX : we loose trailing elements (RAB, right now) + guint16 el = tag->GetElement(); + guint16 group = tag->GetGroup(); + int compte =0; + if ((group == GrPixel) && (el == NumPixel) ) { + compte++; + if (compte == countGrPixel) {// we passed *all* the GrPixel,NumPixel + return false; + } + } + WriteEntryValue(tag, _fp, type); + return true; +} + //----------------------------------------------------------------------------- // Protected @@ -803,7 +833,7 @@ bool gdcmHeader::anonymizeHeader() { if (StudyInstanceUID !=GDCM_UNFOUND) ReplaceOrCreateByNumber(StudyInstanceUID, 0x0010, 0x0010); else - ReplaceOrCreateByNumber("anonymised", 0x0010, 0x0010); + ReplaceOrCreateByNumber(std::string("anonymised"), 0x0010, 0x0010); } // Just for fun :-( @@ -858,7 +888,7 @@ bool gdcmHeader::anonymizeHeader() { //300a 022c DA RT Air Kerma Rate Reference Date //300e 0004 DA RT Review Date return true; - } +} //----------------------------------------------------------------------------- // Private diff --git a/src/gdcmHeader.h b/src/gdcmHeader.h index e8f6146c..a2cece0a 100644 --- a/src/gdcmHeader.h +++ b/src/gdcmHeader.h @@ -28,6 +28,24 @@ */ class GDCM_EXPORT gdcmHeader : public gdcmParser { +protected: + /// In some cases (e.g. for some ACR-NEMA images) the Header Entry Element + /// Number of the 'Pixel Element' is *not* found at 0x0010. In order to + /// make things easier the parser shall store the proper value in + /// NumPixel to provide a unique access facility. See also the constructor + /// \ref gdcmHeader::gdcmHeader + guint16 NumPixel; + /// In some cases (e.g. for some ACR-NEMA images) the header entry for + /// the group of pixels is *not* found at 0x7fe0. In order to + /// make things easier the parser shall store the proper value in + /// GrPixel to provide a unique access facility. See also the constructor + /// \ref gdcmHeader::gdcmHeader + guint16 GrPixel; + /// Some DICOM files may contain several images (e.g. a icon, followd by + /// the image itself. Hence the tag (GrPixel,NumPixel) might appear + /// several times. countGrPixel is the number of occurences of the + /// tag of pixels (i.e. (GrPixel,NumPixel)) contained in the header. + int countGrPixel; public: gdcmHeader(bool exception_on_error = false); gdcmHeader(const char *filename, @@ -79,15 +97,10 @@ public: // TODO Swig int SetShaDict(std::string filename); // TODO Swig int SetPubDict(std::string filename); -// System access - /** - * \brief the Header Entry Group Number of the 'Pixel Group' - * is not allways 0x7fe0 - * @return GrPixel - */ + /// Accessor to \ref gdcmHeader::GrPixel guint16 GetGrPixel(void) {return GrPixel;} - /// Accessor to \ref gdcmParser::NumPixel + /// Accessor to \ref gdcmHeader::NumPixel guint16 GetNumPixel(void) {return NumPixel;} // Entry @@ -107,13 +120,15 @@ public: inline virtual std::string GetEntryVRByName (std::string tagName) { return(gdcmParser::GetEntryVRByName(tagName)); } - inline virtual bool SetEntryByNumber(std::string content,guint16 group, guint16 element) + inline virtual bool SetEntryByNumber(std::string content, + guint16 group, guint16 element) { return(gdcmParser::SetEntryByNumber(content,group,element)); } inline virtual bool SetEntryByName(std::string content,std::string tagName) { return(gdcmParser::SetEntryByName(content,tagName)); } - inline virtual bool SetEntryLengthByNumber(guint32 l,guint16 group, guint16 element) + inline virtual bool SetEntryLengthByNumber(guint32 l, + guint16 group, guint16 element) { return(gdcmParser::SetEntryLengthByNumber(l,group,element)); } inline virtual void UpdateShaEntries(void) @@ -124,6 +139,9 @@ public: bool operator<(gdcmHeader &header); + bool WriteEntry(gdcmHeaderEntry *tag,FILE *_fp,FileType type); + + protected: //CLEANME int write(std::ostream&); //CLEANME int anonymize(std::ostream&);//FIXME: anonymize should be a friend diff --git a/src/gdcmParser.cxx b/src/gdcmParser.cxx index 60d2277e..d75aae58 100644 --- a/src/gdcmParser.cxx +++ b/src/gdcmParser.cxx @@ -123,7 +123,6 @@ void gdcmParser::PrintEntry(std::ostream & os) { } /** - * \ingroup gdcmParser * \brief Prints The Dict Entries of THE public Dicom Dictionnry * @return */ @@ -132,7 +131,6 @@ void gdcmParser::PrintPubDict(std::ostream & os) { } /** - * \ingroup gdcmParser * \brief Prints The Dict Entries of THE shadow Dicom Dictionnary * @return */ @@ -143,7 +141,6 @@ void gdcmParser::PrintShaDict(std::ostream & os) { //----------------------------------------------------------------------------- // Public /** - * \ingroup gdcmParser * \brief Get the public dictionary used */ gdcmDict *gdcmParser::GetPubDict(void) { @@ -151,7 +148,6 @@ gdcmDict *gdcmParser::GetPubDict(void) { } /** - * \ingroup gdcmParser * \brief Get the shadow dictionary used */ gdcmDict *gdcmParser::GetShaDict(void) { @@ -159,7 +155,6 @@ gdcmDict *gdcmParser::GetShaDict(void) { } /** - * \ingroup gdcmParser * \brief Set the shadow dictionary used * \param dict dictionary to use in shadow */ @@ -169,7 +164,6 @@ bool gdcmParser::SetShaDict(gdcmDict *dict){ } /** - * \ingroup gdcmParser * \brief Set the shadow dictionary used * \param dictName name of the dictionary to use in shadow */ @@ -179,7 +173,6 @@ bool gdcmParser::SetShaDict(DictKey dictName){ } /** - * \ingroup gdcmParser * \brief 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 @@ -199,7 +192,6 @@ bool gdcmParser::IsReadable(void) { } /** - * \ingroup gdcmParser * \brief Determines if the Transfer Syntax was already encountered * and if it corresponds to a ImplicitVRLittleEndian one. * @return True when ImplicitVRLittleEndian found. False in all other cases. @@ -235,7 +227,6 @@ bool gdcmParser::IsExplicitVRLittleEndianTransferSyntax(void) { } /** - * \ingroup gdcmParser * \brief Determines if the Transfer Syntax was already encountered * and if it corresponds to a DeflatedExplicitVRLittleEndian one. * @return True when DeflatedExplicitVRLittleEndian found. False in all other cases. @@ -253,7 +244,6 @@ bool gdcmParser::IsDeflatedExplicitVRLittleEndianTransferSyntax(void) { } /** - * \ingroup gdcmParser * \brief Determines if the Transfer Syntax was already encountered * and if it corresponds to a Explicit VR Big Endian one. * @return True when big endian found. False in all other cases. @@ -271,7 +261,6 @@ bool gdcmParser::IsExplicitVRBigEndianTransferSyntax(void) { } /** - * \ingroup gdcmParser * \brief returns the File Type * (ACR, ACR_LIBIDO, ExplicitVR, ImplicitVR, Unknown) * @return the FileType code @@ -281,7 +270,6 @@ FileType gdcmParser::GetFileType(void) { } /** - * \ingroup gdcmParser * \brief opens the file * @param exception_on_error * @return @@ -322,7 +310,6 @@ FILE *gdcmParser::OpenFile(bool exception_on_error) } /** - * \ingroup gdcmParser * \brief closes the file * @return TRUE if the close was successfull */ @@ -335,13 +322,12 @@ bool gdcmParser::CloseFile(void) { } /** - * \ingroup gdcmParser - * \brief writes on disc all the Header Entries (Dicom Elements) + * \brief Writes in a file all the Header Entries (Dicom Elements) * of the Chained List * @param fp file pointer on an already open file - * @param type type of the File to be written + * @param type Type of the File to be written * (ACR-NEMA, ExplicitVR, ImplicitVR) - * @return always "True" ?! + * \return Always true. */ bool gdcmParser::Write(FILE *fp, FileType type) { // ============== @@ -396,18 +382,17 @@ bool gdcmParser::Write(FILE *fp, FileType type) { WriteEntries(fp,type); return(true); - } +} /** - * \ingroup gdcmParser * \brief Modifies the value of a given Header Entry (Dicom Element) - * if it exists; Creates it with the given value if it doesn't - * \warning : adds the Header Entry to the HTable, NOT to the chained List - * @param Value passed as a std::string - * @param Group group of the Entry - * @param Elem element of the Entry - * \return pointer to the created Header Entry - * NULL if creation failed + * 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 + * \return pointer to the modified/created Header Entry (NULL when creation + * failed). */ gdcmHeaderEntry * gdcmParser::ReplaceOrCreateByNumber( std::string Value, @@ -416,47 +401,19 @@ gdcmHeaderEntry * gdcmParser::ReplaceOrCreateByNumber( gdcmHeaderEntry* a; a = GetHeaderEntryByNumber( Group, Elem); if (a == NULL) { - gdcmHeaderEntry *a =NewHeaderEntryByNumber(Group, Elem); + gdcmHeaderEntry *a = NewHeaderEntryByNumber(Group, Elem); if (a == NULL) return NULL; AddHeaderEntry(a); } - //SetEntryByNumber(Value, Group, Elem); + //CLEANME SetEntryByNumber(Value, Group, Elem); a->SetValue(Value); return(a); } /** - * \ingroup gdcmParser - * \brief Modifies the value of a given Header Entry (Dicom Element) - * if it exists; Creates it with the given value if it doesn't - * @param Value passed as a char* - * @param Group group of the Entry - * @param Elem element of the Entry - * \return pointer to the created Header Entry - * NULL if creation failed - * - */ -gdcmHeaderEntry * gdcmParser::ReplaceOrCreateByNumber( - char* Value, - guint16 Group, - guint16 Elem ) { - gdcmHeaderEntry* nvHeaderEntry=NewHeaderEntryByNumber(Group, Elem); - - if(!nvHeaderEntry) - return(NULL); - - AddHeaderEntry(nvHeaderEntry); - - std::string v = Value; - SetEntryByNumber(v, Group, Elem); - return(nvHeaderEntry); -} - -/** - * \ingroup gdcmParser - * \brief Set a new value if the invoked element exists - * Seems to be useless !!! + * \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 @@ -473,7 +430,6 @@ bool gdcmParser::ReplaceIfExistByNumber(char* Value, guint16 Group, guint16 Elem // Protected /** - * \ingroup gdcmParser * \brief Checks if a given Dicom Element exists * within the H table * @param group Group number of the searched Dicom Element @@ -978,11 +934,10 @@ void gdcmParser::UpdateGroupLength(bool SkipSequence, FileType type) { /** * \brief Writes in a file (according to the requested format) * the group, the element, the value representation and the length - of a single gdcmHeaderEntry passed as argument. + * of a single gdcmHeaderEntry passed as argument. * @param tag pointer on the gdcmHeaderEntry to be written * @param _fp already open file pointer * @param type type of the File to be written - * (ACR-NEMA, ExplicitVR, ImplicitVR) */ void gdcmParser::WriteEntryTagVRLength(gdcmHeaderEntry *tag, FILE *_fp, @@ -1038,6 +993,13 @@ void gdcmParser::WriteEntryTagVRLength(gdcmHeaderEntry *tag, } } +/** + * \brief Writes in a file (according to the requested format) + * the value of a single gdcmHeaderEntry passed as argument. + * @param tag Pointer on the gdcmHeaderEntry to be written + * @param _fp Already open file pointer + * @param type type of the File to be written + */ void gdcmParser::WriteEntryValue(gdcmHeaderEntry *tag, FILE *_fp,FileType type) { guint16 group = tag->GetGroup(); @@ -1093,7 +1055,16 @@ void gdcmParser::WriteEntryValue(gdcmHeaderEntry *tag, FILE *_fp,FileType type) fwrite (tag->GetValue().c_str(), (size_t)lgr ,(size_t)1, _fp); // Elem value } -void gdcmParser::WriteEntry(gdcmHeaderEntry *tag, FILE *_fp,FileType type) +/** + * \brief Writes in a file (according to the requested format) + * a single gdcmHeaderEntry passed as argument. + * \sa WriteEntryValue, WriteEntryTagVRLength. + * @param tag Pointer on the gdcmHeaderEntry to be written + * @param _fp Already open file pointer + * @param type type of the File to be written + */ + +bool gdcmParser::WriteEntry(gdcmHeaderEntry *tag, FILE *_fp,FileType type) { guint32 length = tag->GetLength(); @@ -1106,22 +1077,8 @@ void gdcmParser::WriteEntry(gdcmHeaderEntry *tag, FILE *_fp,FileType type) } WriteEntryTagVRLength(tag, _fp, type); - - // Pixels are never loaded in the element ! - // we stop writting when Pixel are processed - // FIX : we loose trailing elements (RAB, right now) - guint16 el = tag->GetElement(); - guint16 group = tag->GetGroup(); - int compte =0; - itsTimeToWritePixels = false; - if ((group == GrPixel) && (el == NumPixel) ) { - compte++; - if (compte == countGrPixel) {// we passed *all* the GrPixel,NumPixel - itsTimeToWritePixels = true; - return; - } - } WriteEntryValue(tag, _fp, type); + return true; } /** @@ -1139,7 +1096,7 @@ void gdcmParser::WriteEntry(gdcmHeaderEntry *tag, FILE *_fp,FileType type) * @param _fp already open file pointer */ -void gdcmParser::WriteEntries(FILE *_fp,FileType type) +bool gdcmParser::WriteEntries(FILE *_fp,FileType type) { // TODO (?) tester les echecs en ecriture (apres chaque fwrite) @@ -1162,10 +1119,10 @@ void gdcmParser::WriteEntries(FILE *_fp,FileType type) // Ignore the documented delimiter continue; } - WriteEntry(*tag2,_fp,type); - if (itsTimeToWritePixels) - break; + if (! WriteEntry(*tag2,_fp,type) ) + return false; } + return true; } /** @@ -1201,8 +1158,7 @@ void gdcmParser::WriteEntriesDeprecated(FILE *_fp,FileType type) { // --> will be done with the next organization if ((*tag2->second).GetGroup() == 0xfffe ) continue; // ignore delimiters } - WriteEntry(tag2->second,_fp,type); - if (itsTimeToWritePixels) + if ( ! WriteEntry(tag2->second,_fp,type)) break; } } @@ -1478,13 +1434,6 @@ void gdcmParser::AddHeaderEntry(gdcmHeaderEntry *newHeaderEntry) { std::string vr = Entry->GetVR(); guint16 length16; - if( (element == NumPixel) && (group == GrPixel) ) - { - dbg.SetDebug(GDCM_DEBUG); - dbg.Verbose(2, "gdcmParser::FindLength: ", - "we reached (GrPixel,NumPixel)"); - } - if ( (filetype == ExplicitVR) && (! Entry->IsImplicitVR()) ) { if ( (vr=="OB") || (vr=="OW") || (vr=="SQ") || (vr=="UN") ) diff --git a/src/gdcmParser.h b/src/gdcmParser.h index bf844635..c9306c39 100644 --- a/src/gdcmParser.h +++ b/src/gdcmParser.h @@ -21,8 +21,8 @@ typedef std::map VRHT; // Value Representation Hash Table typedef std::multimap TagHeaderEntryHT; typedef std::pair PairHT; typedef std::pair IterHT; - -typedef std::list ListTag; // for linking together the Elements +/// for linking together the Elements +typedef std::list ListTag; typedef std::string GroupKey; typedef std::map GroupHT; @@ -33,35 +33,82 @@ typedef std::map GroupHT; */ class GDCM_EXPORT gdcmParser { +private: + /// Public dictionary used to parse this header + gdcmDict *RefPubDict; + + /// Optional "shadow dictionary" (private elements) used to parse + /// this header + gdcmDict *RefShaDict; + + /// Equals 1 if a gdcmHeaderEntry was added post parsing + int wasUpdated; + + /// Equals =1 if user wants to skip shadow groups while parsing + /// (to save space) + int ignoreShadow; + + /// Size threshold above which an element value will NOT be loaded in + /// memory (to avoid loading the image/volume itself). By default, + /// this upper bound is fixed to 1024 bytes (which might look reasonable + /// when one considers the definition of the various VR contents). + guint32 MaxSizeLoadEntry; + + /// Size threshold above which an element value will NOT be *printed* in + /// order no to polute the screen output. By default, this upper bound + /// is fixed to 64 bytes. + guint32 MaxSizePrintEntry; + +protected: + /// Refering underlying filename. + std::string filename; + + /// SWap code (e.g. Big Endian, Little Endian, Bad Big Endian, + /// Bad Little Endian) according to the processor Endianity and + /// what is written on disc. + int sw; + + /// File Pointer, opened during Header parsing. + FILE *fp; + + /// ACR, ACR_LIBIDO, ExplicitVR, ImplicitVR, Unknown + FileType filetype; + + /// After opening the file, we read HEADER_LENGTH_TO_READ bytes. + static const unsigned int HEADER_LENGTH_TO_READ; + + /// Elements whose value is longer than MAX_SIZE_LOAD_ELEMENT_VALUE + /// are NOT loaded. + static const unsigned int MAX_SIZE_LOAD_ELEMENT_VALUE; + + /// Elements whose value is longer than MAX_SIZE_PRINT_ELEMENT_VALUE + /// are NOT printed. + static const unsigned int MAX_SIZE_PRINT_ELEMENT_VALUE; + + /// Hash Table (multimap), to provide fast access + TagHeaderEntryHT tagHT; + + /// Chained list, to keep the 'spacial' ordering + ListTag listEntries; + + /// will be set 1 if user asks to 'go inside' the 'sequences' (VR = "SQ") + int enableSequences; + + /// Amount of printed details for each Header Entry (Dicom Element): + /// 0 : stands for the least detail level. + int printLevel; + public: + // Print - /** - * \ingroup gdcmParser - * \brief Sets the print level for the Dicom Header - * \note 0 for Light Print; 1 for 'medium' Print, 2 for Heavy - */ - void SetPrintLevel(int level) - { printLevel = level; }; - /** - * \ingroup gdcmParser - * \brief canonical Printer - * \sa SetPrintLevel - */ + /// Canonical Printing method (see also gdcmParser::SetPrintLevel) virtual void Print (std::ostream &os = std::cout) {PrintEntry(os);}; virtual void PrintEntry (std::ostream &os = std::cout); virtual void PrintPubDict (std::ostream &os = std::cout); virtual void PrintShaDict (std::ostream &os = std::cout); -// Standard values - /** - * \ingroup gdcmParser - * \brief Gets the external File Name - */ - inline std::string GetFileName(void) - {return filename;} - // Dictionnaries gdcmDict *GetPubDict(void); gdcmDict *GetShaDict(void); @@ -76,52 +123,33 @@ public: bool IsExplicitVRBigEndianTransferSyntax(void); FileType GetFileType(void); -// Entries - /** - * \ingroup gdcmHeader - * \brief returns a ref to the Dicom Header H table (multimap) - * return the Dicom Header H table - */ - inline TagHeaderEntryHT &GetEntry(void) { return tagHT; }; - - /** - * \ingroup gdcmHeader - * \brief returns a ref to the Dicom Header chained list - * return the Dicom Header chained list - */ - inline ListTag &GetListEntry(void) { return listEntries; }; - // Read (used in gdcmFile, gdcmDicomDir) FILE *OpenFile(bool exception_on_error = false) throw(gdcmFileError); bool CloseFile(void); // Write (used in gdcmFile, gdcmDicomDir) virtual bool Write(FILE *, FileType); + virtual void WriteEntryTagVRLength(gdcmHeaderEntry *tag, + FILE *_fp, FileType type); + virtual void WriteEntryValue(gdcmHeaderEntry *tag,FILE *_fp,FileType type); + virtual bool WriteEntry(gdcmHeaderEntry *tag,FILE *_fp,FileType type); + virtual bool WriteEntries(FILE *_fp,FileType type); + void WriteEntriesDeprecated(FILE *_fp,FileType type); // JPR - gdcmHeaderEntry * ReplaceOrCreateByNumber(std::string Value, guint16 Group, guint16 Elem); - gdcmHeaderEntry * ReplaceOrCreateByNumber( char *Value, guint16 Group, guint16 Elem); - bool ReplaceIfExistByNumber ( char *Value, guint16 Group, guint16 Elem); + gdcmHeaderEntry * ReplaceOrCreateByNumber(std::string Value, + guint16 Group, guint16 Elem); + bool ReplaceIfExistByNumber (char *Value, guint16 Group, guint16 Elem); // System access - /** - * \ingroup gdcmHeader - * \brief returns the 'swap code' - * (Big Endian, Little Endian, - * Bad Big Endian, Bad Little Endian) - * according to the processor Endianity and what's written on disc - * return - */ - inline int GetSwapCode(void) { return sw; } - guint16 SwapShort(guint16); // needed by gdcmFile guint32 SwapLong(guint32); // needed by gdcmFile guint16 UnswapShort(guint16); // needed by gdcmFile guint32 UnswapLong(guint32); // needed by gdcmFile protected: -// constructor and destructor are protected to forbid end user -// to instanciate class gdcmParser -// (only gdcmHeader and gdcmDicomDir are meaningfull) + // Constructor and destructor are protected to forbid end user + // to instanciate from this class gdcmParser (only gdcmHeader and + // gdcmDicomDir are meaningfull). gdcmParser(bool exception_on_error = false); gdcmParser(const char *inFilename, bool exception_on_error = false, @@ -137,8 +165,10 @@ protected: virtual int GetEntryLengthByNumber(guint16 group, guint16 element); virtual bool SetEntryByName (std::string content, std::string tagName); - virtual bool SetEntryByNumber(std::string content, guint16 group, guint16 element); - virtual bool SetEntryLengthByNumber(guint32 length, guint16 group, guint16 element); + virtual bool SetEntryByNumber(std::string content, + guint16 group, guint16 element); + virtual bool SetEntryLengthByNumber(guint32 length, + guint16 group, guint16 element); virtual size_t GetEntryOffsetByNumber (guint16 Group, guint16 Elem); virtual void *GetEntryVoidAreaByNumber(guint16 Group, guint16 Elem); @@ -155,78 +185,11 @@ protected: void LoadHeaderEntrySafe(gdcmHeaderEntry *); - void UpdateGroupLength(bool SkipSequence = false, FileType type = ImplicitVR); - void WriteEntryTagVRLength(gdcmHeaderEntry *tag, FILE *_fp, FileType type); - void WriteEntryValue(gdcmHeaderEntry *tag,FILE *_fp,FileType type); - void WriteEntry(gdcmHeaderEntry *tag,FILE *_fp,FileType type); - void WriteEntries(FILE *_fp,FileType type); - void WriteEntriesDeprecated(FILE *_fp,FileType type); // JPR + void UpdateGroupLength(bool SkipSequence = false, + FileType type = ImplicitVR); void AddHeaderEntry (gdcmHeaderEntry *); - /** - * \ingroup gdcmParser - * \brief Set the external File Name - */ - inline void SetFileName(char* fileName) - {filename = fileName;} - -// Variables - /** - * \brief File Pointer, open during Header parsing - */ - FILE *fp; - /** - * \brief ACR, ACR_LIBIDO, ExplicitVR, ImplicitVR, Unknown - */ - FileType filetype; - -/// after opening the file, we read HEADER_LENGTH_TO_READ bytes. - static const unsigned int HEADER_LENGTH_TO_READ; -/// Elements whose value is longer than MAX_SIZE_LOAD_ELEMENT_VALUE are NOT loaded - static const unsigned int MAX_SIZE_LOAD_ELEMENT_VALUE; -/// Elements whose value is longer than MAX_SIZE_PRINT_ELEMENT_VALUE are NOT printed - static const unsigned int MAX_SIZE_PRINT_ELEMENT_VALUE; - -protected: - /** - * \brief H Table (multimap), to provide fast access - */ - TagHeaderEntryHT tagHT; - /** - * \brief chained list, to keep the 'spacial' ordering - */ - ListTag listEntries; - /** - * \brief will be set 1 if user asks to 'go inside' the 'sequences' (VR = "SQ") - */ - int enableSequences; - /** - * \brief amount of printed details for each Header Entry (Dicom Element) - * 0 : the least - */ - int printLevel; - - /** - * \brief For some ACR-NEMA images, it's *not* 7fe0 ... - */ - guint16 GrPixel; - - /// In some cases (e.g. for some ACR-NEMA images) the Header Entry Element - /// Number of the 'Pixel Element' is *not* found at 0x0010. In order to - /// make things easier the parser shall store the proper value in - /// NumPixel to provide a unique access facility. See also - /// \ref gdcmHeader::gdcmHeader - guint16 NumPixel; - /** - * \brief some files may contain icons; GrPixel,NumPixel appears several times - * Let's remember how many times! - */ - int countGrPixel; - /** - * \brief = true when the 'pixel Element' is reached during writting process - */ - bool itsTimeToWritePixels; private: // Read @@ -280,51 +243,25 @@ private: guint32 GenerateFreeTagKeyInGroup(guint16 group); - /** - * \brief Refering underlying filename. - */ - std::string filename; +public: +// Accessors: + /// Accessor to \ref printLevel + void SetPrintLevel(int level) { printLevel = level; }; - /** - * \brief Public dictionary used to parse this header - */ - gdcmDict *RefPubDict; - - /** - * \brief Optional "shadow dictionary" (private elements) used to parse this header - */ - gdcmDict *RefShaDict; + /// Accessor to \ref filename + inline std::string GetFileName(void) {return filename;} - /** - * \brief = 1 if a gdcmHeaderEntry was added post parsing - */ - int wasUpdated; - - /** - * \brief =1 if user wants to skip shadow groups while parsing (to save space) - */ - int ignoreShadow; - - /** - * \brief Swap code e.g. little, big, bad-big, bad-little endian). - * \warning : this code is not fixed during header parsing. - */ - int sw; - /** - * \brief Size threshold above which an element value will NOT be loaded in - * memory (to avoid loading the image/volume itself). By default, - * this upper bound is fixed to 1024 bytes (which might look reasonable - * when one considers the definition of the various VR contents). - */ - guint32 MaxSizeLoadEntry; - - /** - * \brief Size threshold above which an element value will NOT be *printed* in - * order no to polute the screen output. - * By default, this upper bound is fixed to 64 bytes. - */ - guint32 MaxSizePrintEntry; - + /// Accessor to \ref filename + inline void SetFileName(char* fileName) {filename = fileName;} + + /// Accessor to \ref gdcmParser::tagHT + inline TagHeaderEntryHT &GetEntry(void) { return tagHT; }; + + /// Accessor to \ref gdcmParser::listEntries + inline ListTag &GetListEntry(void) { return listEntries; }; + + /// 'Swap code' accessor (see \ref sw ) + inline int GetSwapCode(void) { return sw; } }; //-----------------------------------------------------------------------------