- // the length and proceed.
- long currentPosition = Fp->tellg();
- Fp->seekg(0L,std::ios_base::end);
- long lengthUntilEOF = Fp->tellg() - currentPosition;
- Fp->seekg(currentPosition, std::ios_base::beg);
- entry->SetLength(lengthUntilEOF);
- return;
- }
- entry->SetLength(lengthOB);
- return;
- }
- FixDocEntryFoundLength(entry, length32);
- return;
- }
-
- // Length is encoded on 2 bytes.
- length16 = ReadInt16();
-
- // We can tell the current file is encoded in big endian (like
- // Data/US-RGB-8-epicard) when we find the "Transfer Syntax" tag
- // and it's value is the one of the encoding of a big endian file.
- // In order to deal with such big endian encoded files, we have
- // (at least) two strategies:
- // * when we load the "Transfer Syntax" tag with value of big endian
- // encoding, we raise the proper flags. Then we wait for the end
- // of the META group (0x0002) among which is "Transfer Syntax",
- // before switching the swap code to big endian. We have to postpone
- // the switching of the swap code since the META group is fully encoded
- // in little endian, and big endian coding only starts at the next
- // group. The corresponding code can be hard to analyse and adds
- // many additional unnecessary tests for regular tags.
- // * the second strategy consists in waiting for trouble, that shall
- // 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
- // 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
- // length of a "Group Length" without committing a big mistake, we
- // add an additional check: we look in the already parsed elements
- // for the presence of a "Transfer Syntax" whose value has to be "big
- // endian encoding". When this is the case, chances are we have got our
- // hands on a big endian encoded file: we switch the swap code to
- // big endian and proceed...
- if ( element == 0x0000 && length16 == 0x0400 )
- {
- TransferSyntaxType ts = GetTransferSyntax();
- if ( ts != ExplicitVRBigEndian )
- {
- throw FormatError( "Document::FindDocEntryLength()",
- " not explicit VR." );
- return;
- }
- length16 = 4;
- SwitchSwapToBigEndian();
- // Restore the unproperly loaded values i.e. the group, the element
- // and the dictionary entry depending on them.
- uint16_t correctGroup = SwapShort( entry->GetGroup() );
- uint16_t correctElem = SwapShort( entry->GetElement() );
- DictEntry* newTag = GetDictEntryByNumber( correctGroup,
- correctElem );
- if ( !newTag )
- {
- // This correct tag is not in the dictionary. Create a new one.
- newTag = NewVirtualDictEntry(correctGroup, correctElem);
- }
- // FIXME this can create a memory leaks on the old entry that be
- // left unreferenced.
- entry->SetDictEntry( newTag );
- }
-
- // Heuristic: well, some files are really ill-formed.
- if ( length16 == 0xffff)
- {
- // 0xffff means that we deal with 'Unknown Length' Sequence
- length16 = 0;
- }
- FixDocEntryFoundLength( entry, (uint32_t)length16 );
- return;
- }
- else
- {
- // Either implicit VR or a non DICOM conformal (see note below) explicit
- // VR that ommited the VR of (at least) this element. Farts happen.
- // [Note: according to the part 5, PS 3.5-2001, section 7.1 p25
- // on Data elements "Implicit and Explicit VR Data Elements shall
- // not coexist in a Data Set and Data Sets nested within it".]
- // Length is on 4 bytes.
-
- FixDocEntryFoundLength( entry, ReadInt32() );
- return;
- }
-}
-
-/**
- * \brief Find the Value Representation of the current Dicom Element.
- * @param entry
- */
-void Document::FindDocEntryVR( DocEntry *entry )
-{
- if ( Filetype != ExplicitVR )
- {
- return;
- }
-
- char vr[3];
-
- long positionOnEntry = Fp->tellg();
- // Warning: we believe this is explicit VR (Value Representation) because
- // we used a heuristic that found "UL" in the first tag. Alas this
- // doesn't guarantee that all the tags will be in explicit VR. In some
- // cases (see e-film filtered files) one finds implicit VR tags mixed
- // within an explicit VR file. Hence we make sure the present tag
- // is in explicit VR and try to fix things if it happens not to be
- // the case.
-
- Fp->read (vr, (size_t)2);
- vr[2] = 0;
-
- if( !CheckDocEntryVR(entry, vr) )
- {
- Fp->seekg(positionOnEntry, std::ios_base::beg);
- // 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
- // dictionary entry. Still we have to flag the element as implicit since
- // we know now our assumption on expliciteness is not furfilled.
- // avoid .
- if ( entry->IsVRUnknown() )
- {
- entry->SetVR("Implicit");
- }
- entry->SetImplicitVR();
- }
-}
-
-/**
- * \brief Check the correspondance between the VR of the header entry
- * and the taken VR. If they are different, the header entry is
- * updated with the new VR.
- * @param entry Header Entry to check
- * @param vr Dicom Value Representation
- * @return false if the VR is incorrect of if the VR isn't referenced
- * otherwise, it returns true
-*/
-bool Document::CheckDocEntryVR(DocEntry *entry, VRKey vr)
-{
- std::string msg;
- bool realExplicit = true;
-
- // Assume we are reading a falsely explicit VR file i.e. we reached
- // a tag where we expect reading a VR but are in fact we read the
- // first to bytes of the length. Then we will interogate (through find)
- // the dicom_vr dictionary with oddities like "\004\0" which crashes
- // both GCC and VC++ implementations of the STL map. Hence when the
- // expected VR read happens to be non-ascii characters we consider
- // we hit falsely explicit VR tag.
-
- if ( !isalpha(vr[0]) && !isalpha(vr[1]) )
- {
- realExplicit = false;
- }
-
- // CLEANME searching the dicom_vr at each occurence is expensive.
- // PostPone this test in an optional integrity check at the end
- // of parsing or only in debug mode.
- if ( realExplicit && !Global::GetVR()->Count(vr) )
- {
- realExplicit = false;
- }