Program: gdcm
Module: $RCSfile: gdcmDocument.cxx,v $
Language: C++
- Date: $Date: 2004/09/24 11:39:21 $
- Version: $Revision: 1.91 $
+ Date: $Date: 2004/10/08 08:38:54 $
+ Version: $Revision: 1.98 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
- http://www.creatis.insa-lyon.fr/Public/Gdcm/License.htm for details.
+ http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
#include "gdcmValEntry.h"
#include "gdcmBinEntry.h"
#include "gdcmSeqEntry.h"
-
#include "gdcmGlobal.h"
#include "gdcmUtil.h"
#include "gdcmDebug.h"
long beg = ftell(Fp);
lgt -= beg;
- (void)ParseDES( this, beg, lgt, false); // le Load sera fait a la volee
+ ParseDES( this, beg, lgt, false); // le Load sera fait a la volee
rewind(Fp);
|| IsGivenTransferSyntax(UI1_2_840_10008_1_2_4_91) );
}
+/**
+ * \brief Determines if the Transfer Syntax corresponds to encapsulated
+ * of encoded Pixel Data (as opposed to native).
+ * @return True when encapsulated. False when native.
+ */
+bool gdcmDocument::IsEncapsulateTransferSyntax()
+{
+ return ( IsJPEGBaseLineProcess1TransferSyntax()
+ || IsJPEGExtendedProcess2_4TransferSyntax()
+ || IsJPEGExtendedProcess3_5TransferSyntax()
+ || IsJPEGSpectralSelectionProcess6_8TransferSyntax()
+ || IsRLELossLessTransferSyntax()
+ || IsJPEGLossless()
+ || IsJPEG2000() );
+}
+
/**
* \brief Predicate for dicom version 3 file.
* @return True when the file is a dicom version 3.
* \brief Parses a DocEntrySet (Zero-level DocEntries or SQ Item DocEntries)
* @return length of the parsed set.
*/
-
-long gdcmDocument::ParseDES(gdcmDocEntrySet *set,
+void gdcmDocument::ParseDES(gdcmDocEntrySet *set,
long offset,
long l_max,
bool delim_mode)
{
gdcmDocEntry *newDocEntry = 0;
- unsigned long l = 0;
while (true)
{
// form ( group, elem )...
if (gdcmDocument* dummy = dynamic_cast< gdcmDocument* > ( set ) )
{
- (void)dummy;
newBinEntry->SetKey( newBinEntry->GetKey() );
}
// but when "this" is a SQItem, we are inserting this new
if (newDocEntry->GetGroup() == 0x7fe0 &&
newDocEntry->GetElement() == 0x0010 )
{
- if (newDocEntry->GetReadLength()==0xffffffff)
+ if ( IsRLELossLessTransferSyntax() )
{
- // Broken US.3405.1.dcm
- Parse7FE0(); // to skip the pixels
- // (multipart JPEG/RLE are trouble makers)
+ long PositionOnEntry = ftell(Fp);
+ fseek(Fp, newDocEntry->GetOffset(), SEEK_SET);
+ ComputeRLEInfo();
+ fseek(Fp, PositionOnEntry, SEEK_SET);
}
else
{
SkipToNextDocEntry(newDocEntry);
- l = newDocEntry->GetFullLength();
}
}
else
{
// to be sure we are at the beginning
SkipToNextDocEntry(newDocEntry);
- l = newDocEntry->GetFullLength();
}
}
else
{
// VR = "SQ"
- l = newDocEntry->GetReadLength();
+ unsigned long l = newDocEntry->GetReadLength();
if ( l != 0 ) // don't mess the delim_mode for zero-length sequence
{
if ( l == 0xffffffff )
if ( l != 0 )
{ // Don't try to parse zero-length sequences
- (void)ParseSQ( newSeqEntry,
- newDocEntry->GetOffset(),
- l, delim_mode);
+ ParseSQ( newSeqEntry,
+ newDocEntry->GetOffset(),
+ l, delim_mode);
}
set->AddEntry( newSeqEntry );
if ( !delim_mode && (ftell(Fp)-offset) >= l_max)
}
delete newDocEntry;
}
- return l; // Probably useless
}
/**
* \brief Parses a Sequence ( SeqEntry after SeqEntry)
* @return parsed length for this level
*/
-long gdcmDocument::ParseSQ( gdcmSeqEntry* seqEntry,
+void gdcmDocument::ParseSQ( gdcmSeqEntry* seqEntry,
long offset, long l_max, bool delim_mode)
{
int SQItemNumber = 0;
dlm_mod = false;
}
- (void)ParseDES(itemSQ, newDocEntry->GetOffset(), l, dlm_mod);
+ ParseDES(itemSQ, newDocEntry->GetOffset(), l, dlm_mod);
seqEntry->AddEntry( itemSQ, SQItemNumber );
SQItemNumber++;
break;
}
}
-
- int lgth = ftell(Fp) - offset;
- return lgth;
}
/**
{
if ( vr == "OB" || vr == "OW" || vr == "SQ" || vr == "UN" )
{
- // The following reserved two bytes (see PS 3.5-2001, section
- // 7.1.2 Data element structure with explicit vr p27) must be
+ // The following reserved two bytes (see PS 3.5-2003, section
+ // "7.1.2 Data element structure with explicit vr", p 27) must be
// skipped before proceeding on reading the length on 4 bytes.
fseek(Fp, 2L, SEEK_CUR);
uint32_t length32 = ReadInt32();
- if ( vr == "OB" && length32 == 0xffffffff )
+ if ( (vr == "OB" || vr == "OW") && length32 == 0xffffffff )
{
uint32_t lengthOB;
try
{
+ /// \todo rename that to FindDocEntryLengthOBOrOW since
+ /// the above test is on both OB and OW...
lengthOB = FindDocEntryLengthOB();
}
catch ( gdcmFormatUnexpected )
}
/**
- * \brief Parse pixel data from disk for multi-fragment Jpeg/Rle files
- * No other way so 'skip' the Data
+ * \brief Parse pixel data from disk of [multi-]fragment RLE encoding.
+ * Compute the RLE extra information and store it in \ref RLEInfo
+ * for later pixel retrieval usage.
*/
-void gdcmDocument::Parse7FE0 ()
+void gdcmDocument::ComputeRLEInfo()
{
- gdcmDocEntry* element = GetDocEntryByNumber(0x0002, 0x0010);
- if ( !element )
- {
- // Should warn user FIXME
- return;
- }
-
- if ( IsImplicitVRLittleEndianTransferSyntax()
- || IsExplicitVRLittleEndianTransferSyntax()
- || IsExplicitVRBigEndianTransferSyntax() /// \todo 1.2.2 ??? A verifier !
- || IsDeflatedExplicitVRLittleEndianTransferSyntax() )
+ if ( ! IsRLELossLessTransferSyntax() )
{
return;
}
-
- // ---------------- for Parsing : Position on begining of Jpeg/RLE Pixels
+ // Encoded pixel data: for the time being we are only concerned with
+ // Jpeg or RLE Pixel data encodings.
+ // As stated in PS 3.5-2003, section 8.2 p44:
+ // "If sent in Encapsulated Format (i.e. other than the Native Format) the
+ // value representation OB is used".
+ // Hence we expect an OB value representation. Concerning OB VR,
+ // the section PS 3.5-2003, section A.4.c p 58-59, states:
+ // "For the Value Representations OB and OW, the encoding shall meet the
+ // following specifications depending on the Data element tag:"
+ // [...snip...]
+ // - 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"
//// Read the Basic Offset Table Item Tag length...
uint32_t itemLength = ReadTagLength(0xfffe, 0xe000);
- //// ... and then read length[s] itself[themselves]. We don't use
- // the values read (BTW what is the purpous of those lengths ?)
+ // When present, read the basic offset table itself.
+ // Notes: - since the presence of this basic offset table is optional
+ // we can't rely on it for the implementation, and we will simply
+ // trash it's content (when present).
+ // - still, when present, we could add some further checks on the
+ // lengths, but we won't bother with such fuses for the time being.
if ( itemLength != 0 )
{
- // BTW, what is the purpous of those length anyhow !?
char* basicOffsetTableItemValue = new char[itemLength + 1];
fread(basicOffsetTableItemValue, itemLength, 1, Fp);
for (unsigned int i=0; i < itemLength; i += 4 )
{
- uint32_t individualLength = str2num(&basicOffsetTableItemValue[i],uint32_t);
+ uint32_t individualLength = str2num( &basicOffsetTableItemValue[i],
+ uint32_t);
std::ostringstream s;
s << " Read one length: ";
s << std::hex << individualLength << std::endl;
- dbg.Verbose(0, "gdcmDocument::Parse7FE0: ", s.str().c_str());
+ dbg.Verbose(0, "gdcmDocument::ComputeRLEInfo: ", s.str().c_str());
}
delete[] basicOffsetTableItemValue;
}
- if ( ! IsRLELossLessTransferSyntax() )
- {
- // JPEG Image
-
- //// We then skip (not reading them) all the fragments of images:
- while ( (itemLength = ReadTagLength(0xfffe, 0xe000)) )
- {
- SkipBytes(itemLength);
- }
- }
- else
- {
- // RLE Image
- long ftellRes;
- long rleSegmentLength[15], fragmentLength;
+ // Encapsulated RLE Compressed Images (see PS 3.5-2003, Annex G)
+ // Loop on the frame[s] and store the parsed information in a
+ // gdcmRLEFramesInfo.
+ long frameLength;
+
+ // Loop on the individual frame[s] and store the information
+ // on the RLE fragments in a gdcmRLEFramesInfo.
+ // Note: - when only a single frame is present, this is a
+ // classical image.
+ // - when more than one frame are present, then we are in
+ // the case of a multi-frame image.
+ while ( (frameLength = ReadTagLength(0xfffe, 0xe000)) )
+ {
+ // 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
+ // (but just skipped).
+ long frameOffset = ftell(Fp);
- // While we find some items:
- while ( (fragmentLength = ReadTagLength(0xfffe, 0xe000)) )
- {
- // Parse fragments of the current Fragment (Frame)
- //------------------ scanning (not reading) fragment pixels
- uint32_t nbRleSegments = ReadInt32();
+ uint32_t nbRleSegments = ReadInt32();
- //// Reading RLE Segments Offset Table
- uint32_t rleSegmentOffsetTable[15];
- for(int k=1; k<=15; k++)
- {
- ftellRes = ftell(Fp);
- rleSegmentOffsetTable[k] = ReadInt32();
- }
+ uint32_t rleSegmentOffsetTable[15];
+ for( int k = 1; k <= 15; k++ )
+ {
+ rleSegmentOffsetTable[k] = ReadInt32();
+ }
- // skipping (not reading) RLE Segments
- if ( nbRleSegments > 1)
+ // Deduce from both the RLE Header and the frameLength the
+ // fragment length, and again store this info in a
+ // gdcmRLEFramesInfo.
+ long rleSegmentLength[15];
+ // skipping (not reading) RLE Segments
+ if ( nbRleSegments > 1)
+ {
+ for(unsigned int k = 1; k <= nbRleSegments-1; k++)
{
- for(unsigned int k = 1; k <= nbRleSegments-1; k++)
- {
- rleSegmentLength[k] = rleSegmentOffsetTable[k+1]
- - rleSegmentOffsetTable[k];
- ftellRes = ftell(Fp);
- SkipBytes(rleSegmentLength[k]);
- }
+ rleSegmentLength[k] = rleSegmentOffsetTable[k+1]
+ - rleSegmentOffsetTable[k];
+ SkipBytes(rleSegmentLength[k]);
}
+ }
- rleSegmentLength[nbRleSegments] = fragmentLength
- - rleSegmentOffsetTable[nbRleSegments];
- ftellRes = ftell(Fp);
- SkipBytes(rleSegmentLength[nbRleSegments]);
- }
+ rleSegmentLength[nbRleSegments] = frameLength
+ - rleSegmentOffsetTable[nbRleSegments];
+ SkipBytes(rleSegmentLength[nbRleSegments]);
- // Make sure that at the end of the item we encounter a 'Sequence
- // Delimiter Item':
- if ( !ReadTag(0xfffe, 0xe0dd) )
- {
- dbg.Verbose(0, "gdcmDocument::Parse7FE0: no sequence delimiter item");
- dbg.Verbose(0, " at end of RLE item sequence");
- }
+ // Store the collected info
+ gdcmRLEFrame* newFrameInfo = new gdcmRLEFrame;
+ newFrameInfo->NumberFragments = nbRleSegments;
+ for( unsigned int uk = 1; uk <= nbRleSegments; uk++ )
+ {
+ newFrameInfo->Offset[uk] = frameOffset + rleSegmentOffsetTable[uk];
+ newFrameInfo->Length[uk] = rleSegmentLength[uk];
+ }
+ RLEInfo.Frames.push_back( newFrameInfo );
+ }
+
+ // Make sure that at the end of the item we encounter a 'Sequence
+ // Delimiter Item':
+ if ( !ReadTag(0xfffe, 0xe0dd) )
+ {
+ dbg.Verbose(0, "gdcmDocument::ComputeRLEInfo: no sequence delimiter ");
+ dbg.Verbose(0, " item at end of RLE item sequence");
}
}