-// $Header: /cvs/public/gdcm/src/Attic/gdcmHeader.cxx,v 1.104 2003/10/30 17:04:21 jpr Exp $
+// $Header: /cvs/public/gdcm/src/Attic/gdcmHeader.cxx,v 1.117 2003/11/13 18:08:34 jpr Exp $
#include "gdcmHeader.h"
* @param InFilename
* @param exception_on_error
*/
-gdcmHeader::gdcmHeader(const char *InFilename, bool exception_on_error) {
+gdcmHeader::gdcmHeader(const char *InFilename,
+ bool exception_on_error,
+ bool enable_sequences ) {
+ if (enable_sequences)
+ enableSequences = 1;
+ else
+ enableSequences = 0;
+
SetMaxSizeLoadElementValue(_MaxSizeLoadElementValue_);
filename = InFilename;
Initialise();
fseek(fp, PositionOnEntry, SEEK_SET);
// When this element is known in the dictionary we shall use, e.g. for
- // the semantics (see the usage of IsAnInteger), the vr proposed by the
+ // the semantics (see the usage of IsAnInteger), the vr proposed by the
// dictionary entry. Still we have to flag the element as implicit since
// we know now our assumption on expliciteness is not furfilled.
// avoid .
const char * Transfert = Element->GetValue().c_str();
if ( memcmp(Transfert+strlen(Transfert)-2 ,"70",2)==0) return true;
if ( memcmp(Transfert+strlen(Transfert)-2 ,"55",2)==0) return true;
- if (Element->GetValue() == "1.2.840.10008.1.2.4.57") return true;
+ if (Element->GetValue() == "1.2.840.10008.1.2.4.57") return true;
return false;
}
* applying this heuristic.
*/
void gdcmHeader::FixFoundLength(gdcmElValue * ElVal, guint32 FoundLength) {
- if ( FoundLength == 0xffffffff)
+
+ ElVal->SetReadLength(FoundLength); // will be updated only if a bug is found
+
+ if ( FoundLength == 0xffffffff) {
FoundLength = 0;
+ }
// Sorry for the patch!
// XMedCom did the trick to read some nasty GE images ...
else if (FoundLength == 13) {
// The following 'if' will be removed when there is no more
// images on Creatis HDs with a 13 length for Manufacturer...
- if ( (ElVal->GetGroup() != 0x0008) || (ElVal->GetElement() != 0x0070)) {
+ if ( (ElVal->GetGroup() != 0x0008) &&
+ ( (ElVal->GetElement() != 0x0070) || (ElVal->GetElement() != 0x0080) ) ) {
// end of remove area
FoundLength =10;
+ ElVal->SetReadLength(10); // a bug is to be fixed
}
}
// to fix some garbage 'Leonardo' Siemens images
// May be commented out to avoid overhead
else if ( (ElVal->GetGroup() == 0x0009)
&&
- ( (ElVal->GetElement() == 0x1113) || (ElVal->GetElement() == 0x1114) ) )
- FoundLength =4;
-
- ElVal->SetLength(FoundLength);
+ ( (ElVal->GetElement() == 0x1113) || (ElVal->GetElement() == 0x1114) ) ){
+ FoundLength =4;
+ ElVal->SetReadLength(4); // a bug is to be fixed
+ }
+ // end of fix
+
+ // to try to 'go inside' SeQuences (with length), and not to skip them
+ else if ( ElVal->GetVR() == "SQ") {
+ if (enableSequences) // only if the user does want to !
+ FoundLength =0;
+ }
+
+ // a SeQuence Element is beginning
+ // Let's forget it's length
+ // (we want to 'go inside')
+ else if(ElVal->GetGroup() == 0xfffe){
+ FoundLength =0;
+ }
+
+ ElVal->SetUsableLength(FoundLength);
}
/**
ElVal->SetLength(FindLengthOB());
return;
}
- FixFoundLength(ElVal, length32);
+ FixFoundLength(ElVal, length32);
return;
}
// appear when we find the first group with big endian encoding. This
// is easy to detect since the length of a "Group Length" tag (the
// ones with zero as element number) has to be of 4 (0x0004). When we
- // encouter 1024 (0x0400) chances are the encoding changed and we
+ // encounter 1024 (0x0400) chances are the encoding changed and we
// found a group with big endian encoding.
// We shall use this second strategy. In order to make sure that we
// can interpret the presence of an apparently big endian encoded
// not coexist in a Data Set and Data Sets nested within it".]
// Length is on 4 bytes.
FixFoundLength(ElVal, ReadInt32());
+ return;
}
/**
* @return
*/
void gdcmHeader::SkipElementValue(gdcmElValue * ElVal) {
- SkipBytes(ElVal->GetLength());
+ SkipBytes(ElVal->GetLength());
}
/**
// car commencer par les ignorer risque de conduire a qq chose
// qui pourrait ne pas etre generalisable
// Well, I'm expecting your code !!!
+
+ // the test was commented out to 'go inside' the SeQuences
+ // we don't any longer skip them !
- if( vr == "SQ" )
- SkipLoad = true;
+ // if( vr == "SQ" )
+ // SkipLoad = true;
- // A sequence "contains" a set of Elements.
+ // A SeQuence "contains" a set of Elements.
// (fffe e000) tells us an Element is beginning
// (fffe e00d) tells us an Element just ended
- // (fffe e0dd) tells us the current SQuence just ended
+ // (fffe e0dd) tells us the current SeQuence just ended
if( group == 0xfffe )
SkipLoad = true;
s << "gdcm::NotLoaded.";
s << " Address:" << (long)ElVal->GetOffset();
s << " Length:" << ElVal->GetLength();
+ s << " x(" << std::hex << ElVal->GetLength() << ")";
ElVal->SetValue(s.str());
return;
}
// When an integer is expected, read and convert the following two or
// four bytes properly i.e. as an integer as opposed to a string.
- // pour les elements de Value Multiplicity > 1
- // on aura en fait une serie d'entiers
- // on devrait pouvoir faire + compact (?)
+ // Actually, elements with Value Multiplicity > 1
+ // contain a set of integers (not a single one)
+ // Any compacter code suggested (?)
if ( IsAnInteger(ElVal) ) {
guint32 NewInt;
s << NewInt;
}
}
- }
+ }
+ s << '\0'; // to avoid oddities on Solaris
ElVal->SetValue(s.str());
return;
}
*/
int gdcmHeader::ReplaceOrCreateByNumber(std::string Value,
guint16 Group, guint16 Elem ) {
-
// TODO : FIXME JPRx
// curieux, non ?
// on (je) cree une Elvalue ne contenant pas de valeur
NewElVal = NewElValueByNumber(g, n);
FindVR(NewElVal);
FindLength(NewElVal);
+
if (errno == 1) {
// Call it quits
return (gdcmElValue *)0;
* \ingroup gdcmHeader
* \brief Searches within the public dictionary for element value of
* a given tag.
- * @param TagName name of the researched element.
+ * @param TagName name of the searched element.
* @return Corresponding element value when it exists, and the string
* GDCM_UNFOUND ("gdcm::Unfound") otherwise.
*/
* 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 TagName name of the researched element.
+ * @param TagName name of the searched element.
* @return Corresponding element value representation when it exists,
* and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
*/
* \ingroup gdcmHeader
* \brief Searches within elements parsed with the SHADOW dictionary
* for the element value of a given tag.
- * @param group Group of the researched tag.
- * @param element Element of the researched tag.
+ * @param group Group of the searched tag.
+ * @param element Element of the searched tag.
* @return Corresponding element value representation when it exists,
* and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
*/
* 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 researched tag.
- * @param element Element of the researched tag.
+ * @param group Group of the searched tag.
+ * @param element Element of the searched tag.
* @return Corresponding element value representation when it exists,
* and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
*/
* \ingroup gdcmHeader
* \brief Searches within the elements parsed with the shadow dictionary
* for an element value of given tag.
- * @param TagName name of the researched element.
+ * @param TagName name of the searched element.
* @return Corresponding element value when it exists, and the string
* GDCM_UNFOUND ("gdcm::Unfound") otherwise.
*/
* 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 TagName name of the researched element.
+ * @param TagName name of the searched element.
* @return Corresponding element value representation when it exists,
* and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
*/
* \brief Searches within elements parsed with the public dictionary
* and then within the elements parsed with the shadow dictionary
* for the element value of a given tag.
- * @param group Group of the researched tag.
- * @param element Element of the researched tag.
+ * @param group Group of the searched tag.
+ * @param element Element of the searched tag.
* @return Corresponding element value representation when it exists,
* and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
*/
* 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 researched tag.
- * @param element Element of the researched tag.
+ * @param group Group of the searched tag.
+ * @param element Element of the searched tag.
* @return Corresponding element value representation when it exists,
* and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
*/
* \brief Searches within elements parsed with the public dictionary
* and then within the elements parsed with the shadow dictionary
* for the element value of a given tag.
- * @param TagName name of the researched element.
+ * @param TagName name of the searched element.
* @return Corresponding element value when it exists,
* and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
*/
* 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 TagName name of the researched element.
+ * @param TagName name of the searched element.
* @return Corresponding element value representation when it exists,
* and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
*/
rewind(fp);
CheckSwap();
- while ( (newElValue = ReadNextElement()) ) {
+ while ( (newElValue = ReadNextElement()) ) {
SkipElementValue(newElValue);
PubElValSet.Add(newElValue);
}
/**
* \ingroup gdcmHeader
- * \brief This predicate, based on hopefully reasonnable heuristics,
+ * \brief This predicate, based on hopefully reasonable heuristics,
* decides whether or not the current gdcmHeader was properly parsed
* and contains the mandatory information for being considered as
* a well formed and usable image.
* public tag based hash table.
*/
void gdcmHeader::LoadElements(void) {
- rewind(fp);
- TagElValueHT ht = PubElValSet.GetTagHt();
- for (TagElValueHT::iterator tag = ht.begin(); tag != ht.end(); ++tag) {
- LoadElementValue(tag->second);
- }
+ rewind(fp);
+
+ // We don't use any longer the HashTable, since a lot a stuff is missing
+ // when SeQuences were encountered
+ //
+ //TagElValueHT ht = PubElValSet.GetTagHt();
+ //for (TagElValueHT::iterator tag = ht.begin(); tag != ht.end(); ++tag) {
+ // LoadElementValue(tag->second);
+ //}
+
+ for (ListTag::iterator i = GetListElem().begin();
+ i != GetListElem().end();
+ ++i){
+ LoadElementValue(*i);
+ }
+
rewind(fp);
// Load 'non string' values
*/
int gdcmHeader::Write(FILE * fp, FileType type) {
-
- // TODO : move the following lines (and a lot of others)
+ // TODO : move the following lines (and a lot of others, to be written)
// to a future function CheckAndCorrectHeader
if (type == ImplicitVR) {
/**
* \ingroup gdcmHeader
* \brief Retrieve the number of Samples Per Pixel
- * (1 : gray level, 3 : RGB)
+ * (1 : gray level, 3 : RGB -1 or 3 Planes-)
*
* @return The encountered number of Samples Per Pixel, 1 by default.
*/
* - 32U unsigned 32 bit,
* - 32S signed 32 bit,
* \warning 12 bit images appear as 16 bit.
+ * \ 24 bit images appear as 8 bit
* @return
*/
std::string gdcmHeader::GetPixelType(void) {
dbg.Verbose(0, "gdcmHeader::GetPixelType: unfound Bits Allocated");
BitsAlloc = std::string("16");
}
- if (BitsAlloc == "12")
+ if (BitsAlloc == "12") // It will be unpacked
BitsAlloc = std::string("16");
-
+ else if (BitsAlloc == "24") // (in order no to be messed up
+ BitsAlloc = std::string("8"); // by old RGB images)
+
std::string Signed;
Signed = GetElValByName("Pixel Representation");
if (Signed == GDCM_UNFOUND) {
if (Signed == "0")
Signed = std::string("U");
else
+
+std::cout << "GetPixelType : " << BitsAlloc + Signed << std::endl;
Signed = std::string("S");
return( BitsAlloc + Signed);
/**
* \ingroup gdcmHeader
* \brief tells us if LUT are used
+ * \warning Right now, Segmented xxx Palette Color Lookup Table Data
+ * \ are NOT considered as LUT, since nobody knows
+ *\ how to deal with them
* @return int acts as a Boolean
*/
int gdcmHeader::HasLUT(void) {
- // Just hope checking the presence of the LUT Descriptors is enough
+ // Check the presence of the LUT Descriptors
if (GetPubElValByNumber(0x0028,0x1101) == GDCM_UNFOUND)
return 0;
// LutDescriptorGreen
return 0;
// LutDescriptorBlue
if (GetPubElValByNumber(0x0028,0x1103) == GDCM_UNFOUND)
+ return 0;
+ // It is not enough
+ // we check also
+ if (GetPubElValByNumber(0x0028,0x1201) == GDCM_UNFOUND)
return 0;
+ if (GetPubElValByNumber(0x0028,0x1202) == GDCM_UNFOUND)
+ return 0;
+ if (GetPubElValByNumber(0x0028,0x1203) == GDCM_UNFOUND)
+ return 0;
return 1;
}
* @return Lookup Table RGBA
*/
-void * gdcmHeader::GetLUTRGBA(void) {
+unsigned char * gdcmHeader::GetLUTRGBA(void) {
// Not so easy : see
// http://www.barre.nom.fr/medical/dicom2/limitations.html#Color%20Lookup%20Tables
// and OT-PAL-8-face.dcm
if (gdcmHeader::GetPubElValByNumber(0x0028,0x0004) != "PALETTE COLOR ") {
return NULL;
}
-
- void * LutR,*LutG,*LutB;
- int l;
+
int lengthR, debR, nbitsR;
int lengthG, debG, nbitsG;
int lengthB, debB, nbitsB;
}
// forge the 4 * 8 Bits Red/Green/Blue/Alpha LUT
- char *LUTRGBA = (char *)calloc(1024,1); // 256 * 4 (R, G, B, Alpha)
+ unsigned char *LUTRGBA = (unsigned char *)calloc(1024,1); // 256 * 4 (R, G, B, Alpha)
if (!LUTRGBA) {
return NULL;
- }
+ }
+ memset(LUTRGBA, 0, 1024);
// Bits Allocated
int nb;
std::string str_nb = GetPubElValByNumber(0x0028,0x0100);
// if it works, we shall have to check the 3 Palettes
// to see which byte is ==0 (first one, or second one)
// and fix the code
- // We give up the checking to avoid some overhead
- char *a;
- a= LUTRGBA+debR;
- for(int i=0;i<lengthR;i++) {
+ // We give up the checking to avoid some overhead
+
+ unsigned char *a;
+ int i;
+ a= LUTRGBA+0;
+ for(i=0;i<lengthR;i++) {
*a = lutR[i*mult+1];
a+=4;
}
- a= LUTRGBA+debG;
- for(int i=0;i<lengthG;i++) {
- *(a+1) = lutG[i*mult+1];
+ a= LUTRGBA+1;
+ for(i=0;i<lengthG;i++) {
+ *a = lutG[i*mult+1];
a+=4;
}
- a= LUTRGBA+debB;
- for(int i=0;i<lengthB;i++) {
- *(a+2) = lutB[i*mult+1];
+ a= LUTRGBA+2;
+ for(i=0;i<lengthB;i++) {
+ *a = lutB[i*mult+1];
a+=4;
}
- for(int i=0;i<255;i++) {
- *(a+3) = 1; // Alpha component
+ a= LUTRGBA+3;
+ for(i=0;i<256;i++) {
+ *a = 1; // Alpha component
a+=4;
}
-
-for (int i=0;i<255;i++)
- printf ( "%d %02x %02x %02x %02x \n",
- i,(LUTRGBA+i*4)[0],(LUTRGBA+i*4)[1],(LUTRGBA+i*4)[2],(LUTRGBA+i*4)[3]);
-
-// WHY does it seg fault ?!?
-//free(LutR); free(LutB); free(LutG); printf ("libere\n");
+
+//How to free the now useless LUTs?
+//
+//free(LutR); free(LutB); free(LutG);
return(LUTRGBA);
}