bool enable_sequences,
bool ignore_shadow):
gdcmParser(InFilename,exception_on_error,enable_sequences,ignore_shadow)
-{
+{
+
+ // for some ACR-NEMA images GrPixel, NumPixel is *not* 7fe0,0010
+ // We may encounter the 'RETired' (0x0028, 0x0200) tag
+ // (Image Location") . This Element contains the number of
+ // the group that contains the pixel data (hence the "Pixel Data"
+ // is found by indirection through the "Image Location").
+ // Inside the group pointed by "Image Location" the searched element
+ // is conventionally the element 0x0010 (when the norm is respected).
+ // When the "Image Location" is absent we default to group 0x7fe0.
+
+ // This IS the right place for the code
+
+ std::string ImageLocation = GetEntryByNumber(0x0028, 0x0200);
+ if ( ImageLocation == GDCM_UNFOUND ) { // Image Location
+ GrPixel = 0x7fe0; // default value
+ } else {
+ GrPixel = (guint16) atoi( ImageLocation.c_str() );
+ }
+ if (GrPixel == 0xe07f) // sometimes Image Location value doesn't follow
+ GrPixel = 0x7fe0; // the supposed processor endianity.
+ // see gdcmData/cr172241.dcm
+ if (GrPixel != 0x7fe0)
+ // This is a kludge for old dirty Philips imager.
+ NumPixel = 0x1010;
+ else
+ NumPixel = 0x0010;
+
+ TagKey key = gdcmDictEntry::TranslateToKey(GrPixel, NumPixel);
+ countGrPixel = GetEntry().count(key);
}
/**
* @return The encountered number of Bits Stored, 0 by default.
* 0 means the file is NOT USABLE. The caller has to check it !
*/
-int gdcmHeader::GetBitsStored(void) {
+int gdcmHeader::GetBitsStored(void) {
std::string StrSize = GetEntryByNumber(0x0028,0x0101);
if (StrSize == GDCM_UNFOUND)
return 0; // It's supposed to be mandatory
* @return The encountered number of Bits Allocated, 0 by default.
* 0 means the file is NOT USABLE. The caller has to check it !
*/
-int gdcmHeader::GetBitsAllocated(void) {
+int gdcmHeader::GetBitsAllocated(void) { // TODO : move to gdcmFile
std::string StrSize = GetEntryByNumber(0x0028,0x0100);
if (StrSize == GDCM_UNFOUND)
return 0; // It's supposed to be mandatory
* @return The encountered number of Samples Per Pixel, 1 by default.
* (Gray level Pixels)
*/
-int gdcmHeader::GetSamplesPerPixel(void) {
+int gdcmHeader::GetSamplesPerPixel(void) { // TODO : move to gdcmFile
std::string StrSize = GetEntryByNumber(0x0028,0x0002);
if (StrSize == GDCM_UNFOUND)
return 1; // Well, it's supposed to be mandatory ...
*
* @return The encountered Planar Configuration, 0 by default.
*/
-int gdcmHeader::GetPlanarConfiguration(void) {
+int gdcmHeader::GetPlanarConfiguration(void) {
std::string StrSize = GetEntryByNumber(0x0028,0x0006);
if (StrSize == GDCM_UNFOUND)
return 0;
* \ 24 bit images appear as 8 bit
* @return 0S if nothing found. NOT USABLE file. The caller has to check
*/
-std::string gdcmHeader::GetPixelType(void) {
+std::string gdcmHeader::GetPixelType(void) {
std::string BitsAlloc = GetEntryByNumber(0x0028, 0x0100); // Bits Allocated
if (BitsAlloc == GDCM_UNFOUND) {
dbg.Verbose(0, "gdcmHeader::GetPixelType: unfound Bits Allocated");
return( BitsAlloc + Signed);
}
+
/**
* \ingroup gdcmHeader
* \brief Recover the offset (from the beginning of the file)
* \ of *image* pixels (not *icone image* pixels, if any !)
*/
-size_t gdcmHeader::GetPixelOffset(void) {
- // We may encounter the 'RETired' (0x0028, 0x0200) tag
- // (Image Location") . This Element contains the number of
- // the group that contains the pixel data (hence the "Pixel Data"
- // is found by indirection through the "Image Location").
- // Inside the group pointed by "Image Location" the searched element
- // is conventionally the element 0x0010 (when the norm is respected).
- // When the "Image Location" is absent we default to group 0x7fe0.
+size_t gdcmHeader::GetPixelOffset(void) { // TODO : move to gdcmFile
+
//
// If the element (0x0088,0x0200) 'icone image sequence' is found
// (grPixel,numPixel) is stored twice : the first one for the icon
// the second one for the image ...
// pb : sometimes , (0x0088,0x0200) exists, but doesn't contain *anything*
// see gdcmData/MxTwinLossLess.dcm ...
- guint16 grPixel;
- guint16 numPixel;
+
+
+ /*
+ guint16 grPixel = GrPixel;
+ guint16 numPixel= NumPixel;
std::string ImageLocation = GetEntryByNumber(0x0028, 0x0200);
if ( ImageLocation == GDCM_UNFOUND ) { // Image Location
numPixel = 0x1010;
else
numPixel = 0x0010;
+ */
- IterHT it = GetHeaderEntrySameNumber(grPixel,numPixel);
+ IterHT it = GetHeaderEntrySameNumber(GrPixel,NumPixel);
//std::string icone = GetEntryByNumber(0x0088,0x0200); //icone image sequence
- TagKey key = gdcmDictEntry::TranslateToKey(grPixel,numPixel);
+ TagKey key = gdcmDictEntry::TranslateToKey(GrPixel,NumPixel);
gdcmHeaderEntry* PixelElement;
- if (tagHT.count(key) == 1)
+ //if (tagHT.count(key) == 1)
+ if (countGrPixel == 1)
PixelElement = (it.first)->second;
else
PixelElement = (++it.first)->second;
* @return 0 by default. NOT USABLE file. The caller has to check.
*/
size_t gdcmHeader::GetPixelAreaLength(void) {
+
+/*
// If this file complies with the norm we should encounter the
// "Image Location" tag (0x0028, 0x0200). This tag contains the
// the group that contains the pixel data (hence the "Pixel Data"
// Inside the group pointed by "Image Location" the searched element
// is conventionally the element 0x0010 (when the norm is respected).
// When the "Image Location" is absent we default to group 0x7fe0.
+
+
guint16 grPixel;
- guint16 numPixel;
+ guint16 numPixel;
std::string ImageLocation = GetEntryByNumber(0x0028, 0x0200);
if ( ImageLocation == GDCM_UNFOUND ) { // Image Location
grPixel = 0x7fe0; // default value
numPixel = 0x1010;
else
numPixel = 0x0010;
+ */
- IterHT it = GetHeaderEntrySameNumber(grPixel,numPixel);
+ IterHT it = GetHeaderEntrySameNumber(GrPixel,NumPixel);
//std::string icone = GetEntryByNumber(0x0088,0x0200); //icone image sequence
- TagKey key = gdcmDictEntry::TranslateToKey(grPixel,numPixel);
+ TagKey key = gdcmDictEntry::TranslateToKey(GrPixel,NumPixel);
gdcmHeaderEntry* PixelElement;
- if (tagHT.count(key) == 1)
+ // if (tagHT.count(key) == 1)
+ if (countGrPixel)
PixelElement = (it.first)->second;
else
PixelElement = (++it.first)->second;
return PixelElement->GetLength();
else {
std::cout << "Big trouble : Pixel Element ("
- << std::hex << grPixel<<","<< numPixel<< ") NOT found"
+ << std::hex << GrPixel<<","<< NumPixel<< ") NOT found"
<< std::endl;
return 0;
}
*/
void gdcmHeader::SetImageDataSize(size_t ImageDataSize) {
std::string content1;
- char car[20];
- // Assumes HeaderEntry (0x7fe0, 0x0010) exists ...
- // TODO define private members PixelGroupNumber, PicxelElementNumber
- // update them, use them (only necessary for ACR-NEMA, not DICOM)
+ char car[20];
+
+ // Assumes HeaderEntry (GrPixel, NumPixel) is unique ...
+ // TODO deal with multiplicity (see gdcmData/icone.dcm)
sprintf(car,"%d",ImageDataSize);
- gdcmHeaderEntry *a = GetHeaderEntryByNumber(0x7fe0, 0x0010);
+ gdcmHeaderEntry *a = GetHeaderEntryByNumber(GrPixel, NumPixel);
a->SetLength(ImageDataSize);
ImageDataSize+=8;
sprintf(car,"%d",ImageDataSize);
content1=car;
- SetEntryByNumber(content1, 0x7fe0, 0x0000);
+ SetEntryByNumber(content1, GrPixel, NumPixel);
}
//-----------------------------------------------------------------------------
if ( !OpenFile(exception_on_error))
return;
- if (ParseHeader())
+ if (ParseHeader()) {
LoadHeaderEntries();
+ }
CloseFile();
wasUpdated = 0; // will be set to 1 if user adds an entry
*/
bool gdcmParser::Write(FILE *fp, FileType type) {
// ==============
-// TODO The stuff has been rewritten using the chained list instead
+// TODO The stuff was rewritten using the chained list instead
// of the H table
// so we could remove the GroupHT from the gdcmParser
// To be checked
// TODO : find a trick (in STL?) to do it, at low cost !
void *ptr;
-
- // TODO : get grPixel and numPixel
- guint16 grPixel =0x7fe0;
- guint16 numPixel=0x0010;
- //IterHT it = GetHeaderEntrySameNumber(grPixel,numPixel);
-
-
+
// TODO (?) tester les echecs en ecriture (apres chaque fwrite)
-
+ int compte =0;
+
for (ListTag::iterator tag2=listEntries.begin();
tag2 != listEntries.end();
++tag2)
lgr = (*tag2)->GetReadLength();
val = (*tag2)->GetValue().c_str();
vr = (*tag2)->GetVR();
- cout << hex << gr << " " << el << " " << vr <<" lgr " << lgr << endl;
if ( type == ACR )
{
if (gr < 0x0008) continue; // ignore pure DICOM V3 groups
}
tokens.clear();
continue;
- }
+ }
+
// Pixels are never loaded in the element !
-
- // TODO : FIX --> doesn't work when ICONE is found !!!
-
- if ((gr == grPixel) && (el == numPixel) )
- break;
-
+ // we stop writting when Pixel are processed
+ // FIX : we loose trailing elements (RAB, right now)
+
+ if ((gr == GrPixel) && (el == NumPixel) ) {
+ compte++;
+ if (compte == countGrPixel) // we passed *all* the GrPixel,NumPixel
+ break;
+ }
fwrite ( val,(size_t)lgr ,(size_t)1 ,_fp); // Elem value
}
}
LoadEntryVoidArea(0x0028,0x1221); // Segmented Red Palette Color LUT Data
LoadEntryVoidArea(0x0028,0x1222); // Segmented Green Palette Color LUT Data
LoadEntryVoidArea(0x0028,0x1223); // Segmented Blue Palette Color LUT Data
- }
-
+ }
+
// --------------------------------------------------------------
// Special Patch to allow gdcm to read ACR-LibIDO formated images
//
guint16 group = Entry->GetGroup();
std::string vr = Entry->GetVR();
guint16 length16;
- if( (element == 0x0010) && (group == 0x7fe0) )
+ if( (element == NumPixel) && (group == GrPixel) )
{
dbg.SetDebug(-1);
dbg.Verbose(2, "gdcmParser::FindLength: ",
- "we reached 7fe0 0010");
+ "we reached (GrPixel,NumPixel)");
}
if ( (filetype == ExplicitVR) && (! Entry->IsImplicitVR()) )
{
Entry->SetReadLength(FoundLength); // will be updated only if a bug is found
- if ( FoundLength == 0xffffffff)
- {
+ if ( FoundLength == 0xffffffff) {
FoundLength = 0;
}
+
+ guint16 gr =Entry->GetGroup();
+ guint16 el =Entry->GetElement();
+
+ if (FoundLength%2) {
+ std::cout << "Warning : Tag with uneven length " << FoundLength
+ << "in x(" << hex << gr << "," << el <<")" << std::endl;
+ }
// Sorry for the patch!
// XMedCom did the trick to read some nasty GE images ...
- else if (FoundLength == 13)
- {
+ 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 ( (Entry->GetGroup() != 0x0008) ||
- ( (Entry->GetElement() != 0x0070) && (Entry->GetElement() != 0x0080) ) ) {
+ ( (Entry->GetElement() != 0x0070) && (Entry->GetElement() != 0x0080) ) ){
// end of remove area
FoundLength =10;
Entry->SetReadLength(10); // a bug is to be fixed
// to fix some garbage 'Leonardo' Siemens images
// May be commented out to avoid overhead
else if ( (Entry->GetGroup() == 0x0009) &&
- ( (Entry->GetElement() == 0x1113) || (Entry->GetElement() == 0x1114) ) )
- {
+ ( (Entry->GetElement() == 0x1113) || (Entry->GetElement() == 0x1114) ) ){
FoundLength =4;
Entry->SetReadLength(4); // a bug is to be fixed
}
// FIXME
// Use gdcmParser::dicom_vr to test all the possibilities
// instead of just checking for UL, OB and UI !?
+
+ // FIXME : FIXME:
+ // Sometimes (see : gdcmData/icone.dcm) group 0x0002 *is* Explicit VR,
+ // but elem 0002,0010 (Transfert Syntax) tells us the file is *Implicit* VR.
+ // -and it is !-
+
+ // The following test is *absolutely useless*, since everything *goes right*
+ // with a *100 % wrong* assumption !!!
+
if( (memcmp(entCur, "UL", (size_t)2) == 0) ||
(memcmp(entCur, "OB", (size_t)2) == 0) ||
(memcmp(entCur, "UI", (size_t)2) == 0) )
return NULL;
}
NewEntry->SetOffset(ftell(fp));
- //if ( (g==0x7fe0) && (n==0x0010) )
return NewEntry;
}