Program: gdcm
Module: $RCSfile: gdcmFile.cxx,v $
Language: C++
- Date: $Date: 2005/07/30 18:17:08 $
- Version: $Revision: 1.264 $
+ Date: $Date: 2005/10/06 19:26:00 $
+ Version: $Revision: 1.273 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
// in the images.
//
// Remember also :
-// Patient Position (0018,5100) values : HFP = Head First-Prone
-// HFS = Head First-Supine
-// HFDR = Head First-Decubitus Right
-// HFDL = Head First-Decubitus Left
-// FFDR = Feet First-Decubitus Right
-// FFDL = Feet First-Decubitus Left
-// FFP = Feet First-Prone
-// FFS = Feet First-Supine
-// can also find SEMIERECT
-// SUPINE
+// Patient Position (0018,5100) values :
+
+// HFS = Head First-Supine, where increasing (positive axis direction) :
+// X -> to the direction pointed to by the patient's oustretched left arm
+// Y -> to the anterior-to-posterior direction in the patient's body
+// Z -> to the feet-to-head direction in the patient's body
+
+// HFP = Head First-Prone, where increasing (positive axis direction) :
+// X -> to the direction pointed to by the patient's oustretched left arm
+// Y -> to the anterior-to-posterior direction in the patient's body
+// Z -> to the feet-to-head direction in the patient's body
+
+// FFS = Feet First-Supine, where increasing (positive axis direction) :
+// X -> to the direction pointed to by the patient's oustretched left arm
+// Y -> to the anterior-to-posterion direction in the patient's body
+// Z -> to the feet-to-head direction in the patient's body
+
+// FFP = Feet First-Prone, where increasing (positive axis direction) :
+// X -> to the direction pointed to by the patient's oustretched left arm
+// Y -> to the posterior-to-anterior direction in the patient's body
+// Z -> to the feet-to-head direction in the patient's body
+
+// HFDR = Head First-Decubitus Right
+// HFDL = Head First-Decubitus Left
+// FFDR = Feet First-Decubitus Right
+// FFDL = Feet First-Decubitus Left
+
+// we can also find
+
+// SEMIERECT
+// SUPINE
+
// CS 2 Patient Orientation (0020 0020)
-// When the coordinates of the image
-// are always present, this field is almost never used.
-// Better we don't tust it too much ...
-// Found Values are : L\P
-// L\FP
-// P\F
-// L\F
-// P\FR
-// R\F
+// When the coordinates of the image
+// are always present, this field is almost never used.
+// Better we don't trust it too much ...
+// Found Values are :
+// L\P
+// L\FP
+// P\F
+// L\F
+// P\FR
+// R\F
//
// (0020|0037) [Image Orientation (Patient)] [1\0\0\0\1\0 ]
-
+
// ---------------------------------------------------------------
//
#include "gdcmFile.h"
#include "gdcmJPEGFragmentsInfo.h"
#include <vector>
-#include <stdio.h> //sscanf
+#include <stdio.h> //sscanf
#include <stdlib.h> // for atoi
namespace gdcm
JPEGInfo = new JPEGFragmentsInfo;
GrPixel = 0x7fe0; // to avoid further troubles
NumPixel = 0x0010;
+ BasicOffsetTableItemValue = 0;
}
delete RLEInfo;
if ( JPEGInfo )
delete JPEGInfo;
+ delete[] BasicOffsetTableItemValue;
}
//-----------------------------------------------------------------------------
/**
* \brief gets the info from 0020,0037 : Image Orientation Patient
+ * or from 0020 0035 : Image Orientation (RET)
* (needed to organize DICOM files based on their x,y,z position)
* @param iop adress of the (6)float array to receive values
- * @return cosines of image orientation patient
+ * @return true when one of the tag is found
+ * false when nothing is found
*/
bool File::GetImageOrientationPatient( float iop[6] )
{
if ( sscanf( strImOriPat.c_str(), "%f \\ %f \\%f \\%f \\%f \\%f ",
&iop[0], &iop[1], &iop[2], &iop[3], &iop[4], &iop[5]) != 6 )
{
- gdcmWarningMacro( "Wrong Image Orientation Patient (0020,0037). Less than 6 values were found." );
+ gdcmWarningMacro( "Wrong Image Orientation Patient (0020,0037)."
+ << " Less than 6 values were found." );
return false;
}
}
if ( sscanf( strImOriPat.c_str(), "%f \\ %f \\%f \\%f \\%f \\%f ",
&iop[0], &iop[1], &iop[2], &iop[3], &iop[4], &iop[5]) != 6 )
{
- gdcmWarningMacro( "wrong Image Orientation Patient (0020,0035). Less than 6 values were found." );
+ gdcmWarningMacro( "wrong Image Orientation Patient (0020,0035). "
+ << "Less than 6 values were found." );
return false;
}
}
return true;
}
+
+
/**
* \brief Retrieve the number of Bits Stored (actually used)
* (as opposed to number of Bits Allocated)
// (in order no to be messed up by old ACR-NEMA RGB images)
// if (File::GetEntryValue(0x0028,0x0100) == "24")
// return 3;
+ assert( !(GetEntryValue(0x0028,0x0100) == "24") );
std::string pixelType = GetPixelType();
if ( pixelType == "8U" || pixelType == "8S" )
el.Group = group;
el.Elem = elem;
el.Value = value;
- AnonymizeList.push_back(el);
+ UserAnonymizeList.push_back(el);
}
/**
uint32_t lgth;
uint32_t valLgth = 0;
std::string *spaces;
- for (ListElements::iterator it = AnonymizeList.begin();
- it != AnonymizeList.end();
+ for (ListElements::iterator it = UserAnonymizeList.begin();
+ it != UserAnonymizeList.end();
++it)
{
d = GetDocEntry( (*it).Group, (*it).Elem);
if ( d == NULL)
continue;
- if ( dynamic_cast<SeqEntry *>(d) )
- {
- gdcmWarningMacro( "You cannot 'Anonymize a SeqEntry ");
- continue;
- }
+ if ( dynamic_cast<SeqEntry *>(d) )
+ {
+ gdcmWarningMacro( "You cannot 'Anonymize' a SeqEntry ");
+ continue;
+ }
offset = d->GetOffset();
lgth = d->GetLength();
bool File::AnonymizeFile()
{
// If Anonymisation list is empty, let's perform some basic anonymization
- if ( AnonymizeList.begin() == AnonymizeList.end() )
+ if ( UserAnonymizeList.begin() == UserAnonymizeList.end() )
{
// If exist, replace by spaces
SetValEntry (" ",0x0010, 0x2154); // Telephone
}
else
{
- SetValEntry("anonymised", 0x0010, 0x0010);
+ SetValEntry("anonymized", 0x0010, 0x0010);
}
}
}
else
{
gdcm::DocEntry *d;
- for (ListElements::iterator it = AnonymizeList.begin();
- it != AnonymizeList.end();
+ for (ListElements::iterator it = UserAnonymizeList.begin();
+ it != UserAnonymizeList.end();
++it)
{
d = GetDocEntry( (*it).Group, (*it).Elem);
if ( e0000 )
{
std::ostringstream sLen;
- sLen << ComputeGroup0002Length(writetype);
+ sLen << ComputeGroup0002Length( );
e0000->SetValue(sLen.str());
}
// - the first item in the sequence of items before the encoded pixel
// data stream shall be basic offset table item. The basic offset table
// item value, however, is not required to be present"
- ReadAndSkipEncapsulatedBasicOffsetTable();
+ ReadEncapsulatedBasicOffsetTable();
// Encapsulated RLE Compressed Images (see PS 3.5-2003, Annex G)
// Loop on the individual frame[s] and store the information
// - when more than one frame are present, then we are in
// the case of a multi-frame image.
long frameLength;
+ int i=0;
+ uint32_t sum = 0;
while ( (frameLength = ReadTagLength(0xfffe, 0xe000)) != 0 )
{
+ // Since we have read the basic offset table, let's check the value were correct
+ // or else produce a warning:
+ if ( BasicOffsetTableItemValue )
+ {
+ // If a BasicOffsetTableItemValue was read
+ uint32_t individualLength = BasicOffsetTableItemValue[i];
+ assert( individualLength == sum ); // REMOVE that if this is a problem
+ if( individualLength != sum )
+ {
+ gdcmWarningMacro( "BasicOffsetTableItemValue differs from the fragment lenght" );
+ }
+ sum += frameLength + 8;
+ i++;
+ }
// Parse the RLE Header and store the corresponding RLE Segment
// Offset Table information on fragments of this current Frame.
// Note that the fragment pixels themselves are not loaded
return;
}
- ReadAndSkipEncapsulatedBasicOffsetTable();
+ ReadEncapsulatedBasicOffsetTable();
// Loop on the fragments[s] and store the parsed information in a
// JPEGInfo.
long fragmentLength;
+ int i=0;
+ uint32_t sum = 0;
while ( (fragmentLength = ReadTagLength(0xfffe, 0xe000)) != 0 )
{
- long fragmentOffset = Fp->tellg();
+ // Since we have read the basic offset table, let's check the value were correct
+ // or else produce a warning:
+ // A.4 Transfer syntaxes for encapsulation of encoded pixel data:
+ // When the Item Value is present, the Basic Offset Table Item Value shall contain
+ // concatenated 32-bit unsigned integer values that are byte offsets to the first
+ // byte of the Item Tag of the first fragment for each frame in the Sequence of
+ // Items. These offsets are measured from the first byte of the first Item Tag
+ // following the Basic Offset Table item (See Table A.4-2).
+
+ if ( BasicOffsetTableItemValue )
+ {
+ // If a BasicOffsetTableItemValue was read
+ uint32_t individualLength = BasicOffsetTableItemValue[i];
+ //assert( individualLength == sum ); // Seems like 00191113.dcm is off by one ??
+ if( individualLength != sum )
+ {
+ gdcmWarningMacro( "BasicOffsetTableItemValue differs from the fragment lenght:" <<
+ individualLength << " != " << sum );
+ }
+ sum += fragmentLength + 8;
+ i++;
+ }
- // Store the collected info
- JPEGFragment *newFragment = new JPEGFragment;
- newFragment->SetOffset(fragmentOffset);
- newFragment->SetLength(fragmentLength);
- JPEGInfo->AddFragment(newFragment);
+ long fragmentOffset = Fp->tellg();
+ // Store the collected info
+ JPEGFragment *newFragment = new JPEGFragment;
+ newFragment->SetOffset(fragmentOffset);
+ newFragment->SetLength(fragmentLength);
+ JPEGInfo->AddFragment(newFragment);
- SkipBytes(fragmentLength);
+ SkipBytes(fragmentLength);
}
// Make sure that we encounter a 'Sequence Delimiter Item'
itemTagGroup = ReadInt16();
itemTagElem = ReadInt16();
}
- catch ( FormatError e )
+ catch ( FormatError /*e*/ )
{
//std::cerr << e << std::endl;
return false;
* \brief When parsing the Pixel Data of an encapsulated file, read
* the basic offset table (when present, and BTW dump it).
*/
-void File::ReadAndSkipEncapsulatedBasicOffsetTable()
+void File::ReadEncapsulatedBasicOffsetTable()
{
//// Read the Basic Offset Table Item Tag length...
uint32_t itemLength = ReadTagLength(0xfffe, 0xe000);
// lengths, but we won't bother with such fuses for the time being.
if ( itemLength != 0 )
{
- char *basicOffsetTableItemValue = new char[itemLength + 1];
- Fp->read(basicOffsetTableItemValue, itemLength);
+ char *charBasicOffsetTableItemValue = new char[itemLength];
+ Fp->read(charBasicOffsetTableItemValue, itemLength);
+ unsigned int nbEntries = itemLength/4;
+ assert( nbEntries*4 == itemLength); // Make sure this is a multiple
+ BasicOffsetTableItemValue = new uint32_t[nbEntries];
-#ifdef GDCM_DEBUG
- for (unsigned int i=0; i < itemLength; i += 4 )
+ for (unsigned int i=0; i < nbEntries; i++ )
{
- uint32_t individualLength = str2num( &basicOffsetTableItemValue[i],
- uint32_t);
- gdcmWarningMacro( "Read one length: " <<
- std::hex << individualLength );
+ BasicOffsetTableItemValue[i] = *((uint32_t*)(&charBasicOffsetTableItemValue[4*i]));
+ gdcmWarningMacro( "Read one length for: " <<
+ std::hex << BasicOffsetTableItemValue[i] );
}
-#endif //GDCM_DEBUG
- delete[] basicOffsetTableItemValue;
+ delete[] charBasicOffsetTableItemValue;
}
}